diff options
| author | bgaldrikian <[email protected]> | 2018-10-03 17:51:20 -0700 |
|---|---|---|
| committer | bgaldrikian <[email protected]> | 2018-10-03 17:51:20 -0700 |
| commit | 6f51c0ad55f3ed33597b8b12391d426fe28a0923 (patch) | |
| tree | b132a8cb2485820ff9556dafc8e874bc9d41f255 /sdk/extensions/authoringCommon/source | |
| parent | Fixes to UnitySample to make it build & run. ( In Unity 2018.2 ) (diff) | |
| download | blast-1.1.4_rc1.tar.xz blast-1.1.4_rc1.zip | |
Blast 1.1.4. See docs/release_notes.txt.v1.1.4_rc1
Diffstat (limited to 'sdk/extensions/authoringCommon/source')
4 files changed, 1477 insertions, 0 deletions
diff --git a/sdk/extensions/authoringCommon/source/NvBlastExtAuthoringAccelerator.cpp b/sdk/extensions/authoringCommon/source/NvBlastExtAuthoringAccelerator.cpp new file mode 100644 index 0000000..20ff78b --- /dev/null +++ b/sdk/extensions/authoringCommon/source/NvBlastExtAuthoringAccelerator.cpp @@ -0,0 +1,654 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2016-2018 NVIDIA Corporation. All rights reserved. + + +#include "NvBlastExtAuthoringAccelerator.h" +#include "NvBlastExtAuthoringMesh.h" +#include "NvBlastExtAuthoringInternalCommon.h" +#include "NvBlastGlobals.h" + +using namespace physx; + + +namespace Nv +{ +namespace Blast +{ + +DummyAccelerator::DummyAccelerator(int32_t count) :count(count) +{ + current = 0; +} +void DummyAccelerator::setState(const Vertex* pos, const Edge* ed, const Facet& fc) +{ + current = 0; + NV_UNUSED(pos); + NV_UNUSED(ed); + NV_UNUSED(fc); +} +void DummyAccelerator::setState(const physx::PxBounds3* bound) { + current = 0; + NV_UNUSED(bound); +} + +void DummyAccelerator::setState(const physx::PxVec3& point) { + current = 0; + NV_UNUSED(point); +} +int32_t DummyAccelerator::getNextFacet() +{ + if (current < count) + { + ++current; + return current - 1; + } + else + return -1; +} + +Grid::Grid(int32_t resolution) : mResolution(resolution) +{ + /** + Set up 3d grid + */ + r3 = resolution * resolution * resolution; + mSpatialMap.resize(resolution * resolution * resolution); +} + +void Grid::setMesh(const Mesh* m) +{ + physx::PxBounds3 bd = m->getBoundingBox(); + mappedFacetCount = m->getFacetCount(); + bd.fattenFast(0.001f); + spos = bd.minimum; + deltas = PxVec3(mResolution / bd.getDimensions().x, mResolution / bd.getDimensions().y, mResolution / bd.getDimensions().z); + + for (int32_t i = 0; i < r3; ++i) + mSpatialMap[i].clear(); + + const float ofs = 0.001f; + + for (uint32_t fc = 0; fc < m->getFacetCount(); ++fc) + { + physx::PxBounds3 cfc = *m->getFacetBound(fc); + + int32_t is = std::max(0.f, (cfc.minimum.x - spos.x - ofs) * deltas.x); + int32_t ie = std::max(0.f, (cfc.maximum.x - spos.x + ofs) * deltas.x); + + int32_t js = std::max(0.f, (cfc.minimum.y - spos.y - ofs) * deltas.y); + int32_t je = std::max(0.f, (cfc.maximum.y - spos.y + ofs) * deltas.y); + + int32_t ks = std::max(0.f, (cfc.minimum.z - spos.z - ofs) * deltas.z); + int32_t ke = std::max(0.f, (cfc.maximum.z - spos.z + ofs) * deltas.z); + + for (int32_t i = is; i < mResolution && i <= ie; ++i) + { + for (int32_t j = js; j < mResolution && j <= je; ++j) + { + for (int32_t k = ks; k < mResolution && k <= ke; ++k) + { + mSpatialMap[(i * mResolution + j) * mResolution + k].push_back(fc); + } + } + } + } +} + + +GridWalker::GridWalker(Grid* grd) +{ + mGrid = grd; + alreadyGotValue = 0; + alreadyGotFlag.resize(1 << 12); + cellList.resize(1 << 12); + pointCmdDir = 0; +} + +void GridWalker::setState(const Vertex* pos, const Edge* ed, const Facet& fc) +{ + + physx::PxBounds3 cfc(PxBounds3::empty()); + + for (uint32_t v = 0; v < fc.edgesCount; ++v) + { + cfc.include(pos[ed[fc.firstEdgeNumber + v].s].p); + cfc.include(pos[ed[fc.firstEdgeNumber + v].e].p); + } + setState(&cfc); +} + +void GridWalker::setState(const PxBounds3* facetBounding) +{ + alreadyGotValue++; + mIteratorCell = -1; + mIteratorFacet = -1; + gotCells = 0; + + physx::PxBounds3 cfc = *facetBounding; + + + + int32_t is = std::max(0.f, (cfc.minimum.x - mGrid->spos.x - 0.001f) * mGrid->deltas.x); + int32_t ie = std::max(0.f, (cfc.maximum.x - mGrid->spos.x + 0.001f) * mGrid->deltas.x); + + int32_t js = std::max(0.f, (cfc.minimum.y - mGrid->spos.y - 0.001f) * mGrid->deltas.y); + int32_t je = std::max(0.f, (cfc.maximum.y - mGrid->spos.y + 0.001f) * mGrid->deltas.y); + + int32_t ks = std::max(0.f, (cfc.minimum.z - mGrid->spos.z - 0.001f) * mGrid->deltas.z); + int32_t ke = std::max(0.f, (cfc.maximum.z - mGrid->spos.z + 0.001f) * mGrid->deltas.z); + + for (int32_t i = is; i < mGrid->mResolution && i <= ie; ++i) + { + for (int32_t j = js; j < mGrid->mResolution && j <= je; ++j) + { + for (int32_t k = ks; k < mGrid->mResolution && k <= ke; ++k) + { + int32_t id = (i * mGrid->mResolution + j) * mGrid->mResolution + k; + if (!mGrid->mSpatialMap[id].empty()) + { + cellList[gotCells++] = id; + } + + } + } + } + if (gotCells != 0) + { + mIteratorFacet = 0; + mIteratorCell = cellList[gotCells - 1]; + gotCells--; + } +} + + +void GridWalker::setPointCmpDirection(int32_t d) +{ + pointCmdDir = d; +} + + +void GridWalker::setState(const physx::PxVec3& point) +{ + alreadyGotValue++; + mIteratorCell = -1; + mIteratorFacet = -1; + gotCells = 0; + + int32_t is = std::max(0.f, (point.x - mGrid->spos.x - 0.001f) * mGrid->deltas.x); + int32_t ie = std::max(0.f, (point.x - mGrid->spos.x + 0.001f) * mGrid->deltas.x); + + int32_t js = std::max(0.f, (point.y - mGrid->spos.y - 0.001f) * mGrid->deltas.y); + int32_t je = std::max(0.f, (point.y - mGrid->spos.y + 0.001f) * mGrid->deltas.y); + + int32_t ks = 0; + int32_t ke = mGrid->mResolution; + switch (pointCmdDir) + { + case 1: + ks = std::max(0.f, (point.z - mGrid->spos.z - 0.001f) * mGrid->deltas.z); + break; + case -1: + ke = std::max(0.f, (point.z - mGrid->spos.z + 0.001f) * mGrid->deltas.z); + } + + for (int32_t i = is; i < mGrid->mResolution && i <= ie; ++i) + { + for (int32_t j = js; j < mGrid->mResolution && j <= je; ++j) + { + for (int32_t k = ks; k <= ke && k < mGrid->mResolution; ++k) + { + int32_t id = (i * mGrid->mResolution + j) * mGrid->mResolution + k; + if (!mGrid->mSpatialMap[id].empty()) + { + cellList[gotCells++] = id; + } + } + } + } + + if (gotCells != 0) + { + mIteratorFacet = 0; + mIteratorCell = cellList[gotCells - 1]; + gotCells--; + } +} +int32_t GridWalker::getNextFacet() +{ + int32_t facetId = -1; + + while (mIteratorCell != -1) + { + if (mIteratorFacet >= (int32_t)mGrid->mSpatialMap[mIteratorCell].size()) + { + if (gotCells != 0) + { + mIteratorCell = cellList[gotCells - 1]; + gotCells--; + mIteratorFacet = 0; + } + else + { + mIteratorCell = -1; + break; + } + } + if (alreadyGotFlag[mGrid->mSpatialMap[mIteratorCell][mIteratorFacet]] != alreadyGotValue) + { + facetId = mGrid->mSpatialMap[mIteratorCell][mIteratorFacet]; + mIteratorFacet++; + break; + } + else + { + mIteratorFacet++; + } + } + if (facetId != -1) + { + alreadyGotFlag[facetId] = alreadyGotValue; + } + return facetId; +} + + + +BBoxBasedAccelerator::BBoxBasedAccelerator(const Mesh* mesh, int32_t resolution) : mResolution(resolution), alreadyGotValue(1) +{ + mBounds = mesh->getBoundingBox(); + mSpatialMap.resize(resolution * resolution * resolution); + mCells.resize(resolution * resolution * resolution); + int32_t currentCell = 0; + PxVec3 incr = (mBounds.maximum - mBounds.minimum) * (1.0f / mResolution); + for (int32_t z = 0; z < resolution; ++z) + { + for (int32_t y = 0; y < resolution; ++y) + { + for (int32_t x = 0; x < resolution; ++x) + { + mCells[currentCell].minimum.x = mBounds.minimum.x + x * incr.x; + mCells[currentCell].minimum.y = mBounds.minimum.y + y * incr.y; + mCells[currentCell].minimum.z = mBounds.minimum.z + z * incr.z; + + mCells[currentCell].maximum.x = mBounds.minimum.x + (x + 1) * incr.x; + mCells[currentCell].maximum.y = mBounds.minimum.y + (y + 1) * incr.y; + mCells[currentCell].maximum.z = mBounds.minimum.z + (z + 1) * incr.z; + + ++currentCell; + } + } + } + cellList.resize(1 << 16); + gotCells = 0; + buildAccelStructure(mesh->getVertices(), mesh->getEdges(), mesh->getFacetsBuffer(), mesh->getFacetCount()); +} + + +BBoxBasedAccelerator::~BBoxBasedAccelerator() +{ + mResolution = 0; + mBounds.setEmpty(); + mSpatialMap.clear(); + mCells.clear(); + cellList.clear(); +} + +int32_t BBoxBasedAccelerator::getNextFacet() +{ + int32_t facetId = -1; + + while (mIteratorCell != -1) + { + if (mIteratorFacet >= (int32_t)mSpatialMap[mIteratorCell].size()) + { + if (gotCells != 0) + { + mIteratorCell = cellList[gotCells - 1]; + gotCells--; + mIteratorFacet = 0; + } + else + { + mIteratorCell = -1; + break; + } + } + if (alreadyGotFlag[mSpatialMap[mIteratorCell][mIteratorFacet]] != alreadyGotValue) + { + facetId = mSpatialMap[mIteratorCell][mIteratorFacet]; + mIteratorFacet++; + break; + } + else + { + mIteratorFacet++; + } + } + if (facetId != -1) + { + alreadyGotFlag[facetId] = alreadyGotValue; + } + return facetId; +} + + +void BBoxBasedAccelerator::setState(const Vertex* pos, const Edge* ed, const Facet& fc) +{ + + physx::PxBounds3 cfc(PxBounds3::empty()); + + for (uint32_t v = 0; v < fc.edgesCount; ++v) + { + cfc.include(pos[ed[fc.firstEdgeNumber + v].s].p); + cfc.include(pos[ed[fc.firstEdgeNumber + v].e].p); + } + setState(&cfc); +} + +void BBoxBasedAccelerator::setState(const PxBounds3* facetBox) +{ + alreadyGotValue++; + mIteratorCell = -1; + mIteratorFacet = -1; + gotCells = 0; + + for (uint32_t i = 0; i < mCells.size(); ++i) + { + if (weakBoundingBoxIntersection(mCells[i], *facetBox)) + { + if (!mSpatialMap[i].empty()) + cellList[gotCells++] = i; + } + } + if (gotCells != 0) + { + mIteratorFacet = 0; + mIteratorCell = cellList[gotCells - 1]; + gotCells--; + } +} + + +void BBoxBasedAccelerator::setState(const PxVec3& p) +{ + alreadyGotValue++; + mIteratorCell = -1; + mIteratorFacet = -1; + gotCells = 0; + int32_t perSlice = mResolution * mResolution; + for (uint32_t i = 0; i < mCells.size(); ++i) + { + if (mCells[i].contains(p)) + { + int32_t xyCellId = i % perSlice; + for (int32_t zCell = 0; zCell < mResolution; ++zCell) + { + int32_t cell = zCell * perSlice + xyCellId; + if (!mSpatialMap[cell].empty()) + cellList[gotCells++] = cell; + } + } + } + if (gotCells != 0) + { + mIteratorFacet = 0; + mIteratorCell = cellList[gotCells - 1]; + gotCells--; + } +} + + +void BBoxBasedAccelerator::buildAccelStructure(const Vertex* pos, const Edge* edges, const Facet* fc, int32_t facetCount) +{ + for (int32_t facet = 0; facet < facetCount; ++facet) + { + PxBounds3 bBox; + bBox.setEmpty(); + const Edge* edge = &edges[0] + fc->firstEdgeNumber; + int32_t count = fc->edgesCount; + for (int32_t ec = 0; ec < count; ++ec) + { + bBox.include(pos[edge->s].p); + bBox.include(pos[edge->e].p); + edge++; + } + + for (uint32_t i = 0; i < mCells.size(); ++i) + { + if (weakBoundingBoxIntersection(mCells[i], bBox)) + { + mSpatialMap[i].push_back(facet); + } + } + fc++; + } + alreadyGotFlag.resize(facetCount, 0); +} + +#define SWEEP_RESOLUTION 2048 + +void buildIndex(std::vector<SegmentToIndex>& segm, float offset, float mlt, std::vector<std::vector<uint32_t>>& blocks) +{ + std::set<uint32_t> currentEnabled; + uint32_t lastBlock = 0; + for (uint32_t i = 0; i < segm.size(); ++i) + { + uint32_t currentBlock = (segm[i].coord - offset) * mlt; + if (currentBlock >= SWEEP_RESOLUTION) break; + if (currentBlock != lastBlock) + { + for (uint32_t j = lastBlock + 1; j <= currentBlock; ++j) + { + for (auto id : currentEnabled) + blocks[j].push_back(id); + } + lastBlock = currentBlock; + } + if (segm[i].end == false) + { + blocks[lastBlock].push_back(segm[i].index); + currentEnabled.insert(segm[i].index); + } + else + { + currentEnabled.erase(segm[i].index); + } + } + +} + + +SweepingAccelerator::SweepingAccelerator(Nv::Blast::Mesh* in) +{ + PxBounds3 bnd; + + const Vertex* verts = in->getVertices(); + const Edge* edges = in->getEdges(); + + facetCount = in->getFacetCount(); + + foundx.resize(facetCount, 0); + foundy.resize(facetCount, 0); + + + std::vector<SegmentToIndex> xevs; + std::vector<SegmentToIndex> yevs; + std::vector<SegmentToIndex> zevs; + + + for (uint32_t i = 0; i < in->getFacetCount(); ++i) + { + const Facet* fc = in->getFacet(i); + bnd.setEmpty(); + for (uint32_t v = 0; v < fc->edgesCount; ++v) + { + bnd.include(verts[edges[v + fc->firstEdgeNumber].s].p); + } + bnd.scaleFast(1.1f); + xevs.push_back(SegmentToIndex(bnd.minimum.x, i, false)); + xevs.push_back(SegmentToIndex(bnd.maximum.x, i, true)); + + yevs.push_back(SegmentToIndex(bnd.minimum.y, i, false)); + yevs.push_back(SegmentToIndex(bnd.maximum.y, i, true)); + + zevs.push_back(SegmentToIndex(bnd.minimum.z, i, false)); + zevs.push_back(SegmentToIndex(bnd.maximum.z, i, true)); + + } + + std::sort(xevs.begin(), xevs.end()); + std::sort(yevs.begin(), yevs.end()); + std::sort(zevs.begin(), zevs.end()); + + + minimal.x = xevs[0].coord; + minimal.y = yevs[0].coord; + minimal.z = zevs[0].coord; + + + maximal.x = xevs.back().coord; + maximal.y = yevs.back().coord; + maximal.z = zevs.back().coord; + + + rescale = (maximal - minimal) * 1.01f; + rescale.x = 1.0f / rescale.x * SWEEP_RESOLUTION; + rescale.y = 1.0f / rescale.y * SWEEP_RESOLUTION; + rescale.z = 1.0f / rescale.z * SWEEP_RESOLUTION; + + xSegm.resize(SWEEP_RESOLUTION); + ySegm.resize(SWEEP_RESOLUTION); + zSegm.resize(SWEEP_RESOLUTION); + + + buildIndex(xevs, minimal.x, rescale.x, xSegm); + buildIndex(yevs, minimal.y, rescale.y, ySegm); + buildIndex(zevs, minimal.z, rescale.z, zSegm); + + + iterId = 1; + current = 0; +} + +void SweepingAccelerator::setState(const PxBounds3* facetBounds) +{ + current = 0; + indices.clear(); + + PxBounds3 bnd = *facetBounds; + + bnd.scaleFast(1.1); + uint32_t start = (std::max(0.0f, bnd.minimum.x - minimal.x)) * rescale.x; + uint32_t end = (std::max(0.0f, bnd.maximum.x - minimal.x)) * rescale.x; + for (uint32_t i = start; i <= end && i < SWEEP_RESOLUTION; ++i) + { + for (auto id : xSegm[i]) + { + foundx[id] = iterId; + } + } + start = (std::max(0.0f, bnd.minimum.y - minimal.y)) * rescale.y; + end = (std::max(0.0f, bnd.maximum.y - minimal.y)) * rescale.y; + for (uint32_t i = start; i <= end && i < SWEEP_RESOLUTION; ++i) + { + for (auto id : ySegm[i]) + { + foundy[id] = iterId; + } + } + start = (std::max(0.0f, bnd.minimum.z - minimal.z)) * rescale.z; + end = (std::max(0.0f, bnd.maximum.z - minimal.z)) * rescale.z; + for (uint32_t i = start; i <= end && i < SWEEP_RESOLUTION; ++i) + { + for (auto id : zSegm[i]) + { + if (foundy[id] == iterId && foundx[id] == iterId) + { + foundx[id] = iterId + 1; + foundy[id] = iterId + 1; + indices.push_back(id); + } + } + } + + iterId += 2; +} + +void SweepingAccelerator::setState(const Vertex* pos, const Edge* ed, const Facet& fc) +{ + + physx::PxBounds3 cfc(PxBounds3::empty()); + + for (uint32_t v = 0; v < fc.edgesCount; ++v) + { + cfc.include(pos[ed[fc.firstEdgeNumber + v].s].p); + cfc.include(pos[ed[fc.firstEdgeNumber + v].e].p); + } + setState(&cfc); +} + + +void SweepingAccelerator::setState(const physx::PxVec3& point) { + + indices.clear(); + + /*for (uint32_t i = 0; i < facetCount; ++i) + { + indices.push_back(i); + }*/ + + uint32_t xIndex = (point.x - minimal.x) * rescale.x; + uint32_t yIndex = (point.y- minimal.y) * rescale.y; + + for (uint32_t i = 0; i < xSegm[xIndex].size(); ++i) + { + foundx[xSegm[xIndex][i]] = iterId; + } + for (uint32_t i = 0; i < ySegm[yIndex].size(); ++i) + { + if (foundx[ySegm[yIndex][i]] == iterId) + { + indices.push_back(ySegm[yIndex][i]); + } + } + iterId++; + current = 0; + NV_UNUSED(point); +} +int32_t SweepingAccelerator::getNextFacet() +{ + if (static_cast<uint32_t>(current) < indices.size()) + { + ++current; + return indices[current - 1]; + } + else + return -1; +} + +} // namespace Blast +} // namespace Nv diff --git a/sdk/extensions/authoringCommon/source/NvBlastExtAuthoringInternalCommon.h b/sdk/extensions/authoringCommon/source/NvBlastExtAuthoringInternalCommon.h new file mode 100644 index 0000000..28d3349 --- /dev/null +++ b/sdk/extensions/authoringCommon/source/NvBlastExtAuthoringInternalCommon.h @@ -0,0 +1,265 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2018 NVIDIA Corporation. All rights reserved. + + +#ifndef NVBLASTINTERNALCOMMON_H +#define NVBLASTINTERNALCOMMON_H +#include "NvBlastExtAuthoringTypes.h" +#include <algorithm> + +using namespace physx; + +namespace Nv +{ +namespace Blast +{ + +/** +Edge representation with index of parent facet +*/ +struct EdgeWithParent +{ + uint32_t s, e; // Starting and ending vertices + uint32_t parent; // Parent facet index + EdgeWithParent() : s(0), e(0), parent(0) {} + EdgeWithParent(uint32_t s, uint32_t e, uint32_t p) : s(s), e(e), parent(p) {} +}; + + +/** +Comparator for sorting edges according to parent facet number. +*/ +struct EdgeComparator +{ + bool operator()(const EdgeWithParent& a, const EdgeWithParent& b) const + { + if (a.parent == b.parent) + { + if (a.s == b.s) + { + return a.e < b.e; + } + else + { + return a.s < b.s; + } + } + else + { + return a.parent < b.parent; + } + } +}; + + +/** +Vertex projection direction flag. +*/ +enum ProjectionDirections +{ + YZ_PLANE = 1 << 1, + XY_PLANE = 1 << 2, + ZX_PLANE = 1 << 3, + + OPPOSITE_WINDING = 1 << 4 +}; + +/** +Computes best direction to project points. +*/ +NV_FORCE_INLINE ProjectionDirections getProjectionDirection(const physx::PxVec3& normal) +{ + float maxv = std::max(std::abs(normal.x), std::max(std::abs(normal.y), std::abs(normal.z))); + ProjectionDirections retVal; + if (maxv == std::abs(normal.x)) + { + retVal = YZ_PLANE; + if (normal.x < 0) retVal = (ProjectionDirections)((int)retVal | (int)OPPOSITE_WINDING); + return retVal; + } + if (maxv == std::abs(normal.y)) + { + retVal = ZX_PLANE; + if (normal.y > 0) retVal = (ProjectionDirections)((int)retVal | (int)OPPOSITE_WINDING); + return retVal; + } + retVal = XY_PLANE; + if (normal.z < 0) retVal = (ProjectionDirections)((int)retVal | (int)OPPOSITE_WINDING); + return retVal; +} + + +/** +Computes point projected on given axis aligned plane. +*/ +NV_FORCE_INLINE physx::PxVec2 getProjectedPoint(const physx::PxVec3& point, ProjectionDirections dir) +{ + if (dir & YZ_PLANE) + { + return physx::PxVec2(point.y, point.z); + } + if (dir & ZX_PLANE) + { + return physx::PxVec2(point.x, point.z); + } + return physx::PxVec2(point.x, point.y); +} + +/** +Computes point projected on given axis aligned plane, this method is polygon-winding aware. +*/ +NV_FORCE_INLINE physx::PxVec2 getProjectedPointWithWinding(const physx::PxVec3& point, ProjectionDirections dir) +{ + if (dir & YZ_PLANE) + { + if (dir & OPPOSITE_WINDING) + { + return physx::PxVec2(point.z, point.y); + } + else + return physx::PxVec2(point.y, point.z); + } + if (dir & ZX_PLANE) + { + if (dir & OPPOSITE_WINDING) + { + return physx::PxVec2(point.z, point.x); + } + return physx::PxVec2(point.x, point.z); + } + if (dir & OPPOSITE_WINDING) + { + return physx::PxVec2(point.y, point.x); + } + return physx::PxVec2(point.x, point.y); +} + + + +#define MAXIMUM_EXTENT 1000 * 1000 * 1000 +#define BBOX_TEST_EPS 1e-5f + +/** +Test fattened bounding box intersetion. +*/ +NV_INLINE bool weakBoundingBoxIntersection(const physx::PxBounds3& aBox, const physx::PxBounds3& bBox) +{ + if (std::max(aBox.minimum.x, bBox.minimum.x) > std::min(aBox.maximum.x, bBox.maximum.x) + BBOX_TEST_EPS) + return false; + if (std::max(aBox.minimum.y, bBox.minimum.y) > std::min(aBox.maximum.y, bBox.maximum.y) + BBOX_TEST_EPS) + return false; + if (std::max(aBox.minimum.z, bBox.minimum.z) > std::min(aBox.maximum.z, bBox.maximum.z) + BBOX_TEST_EPS) + return false; + return true; +} + + + +/** +Test segment vs plane intersection. If segment intersects the plane true is returned. Point of intersection is written into 'result'. +*/ +NV_INLINE bool getPlaneSegmentIntersection(const PxPlane& pl, const PxVec3& a, const PxVec3& b, PxVec3& result) +{ + float div = (b - a).dot(pl.n); + if (PxAbs(div) < 0.0001f) + { + if (pl.contains(a)) + { + result = a; + return true; + } + else + { + return false; + } + } + float t = (-a.dot(pl.n) - pl.d) / div; + if (t < 0.0f || t > 1.0f) + { + return false; + } + result = (b - a) * t + a; + return true; +} + + +#define POS_COMPARISON_OFFSET 1e-5f +#define NORM_COMPARISON_OFFSET 1e-3f +/** +Vertex comparator for vertex welding. +*/ +struct VrtComp +{ + bool operator()(const Vertex& a, const Vertex& b) const + { + if (a.p.x + POS_COMPARISON_OFFSET < b.p.x) return true; + if (a.p.x - POS_COMPARISON_OFFSET > b.p.x) return false; + if (a.p.y + POS_COMPARISON_OFFSET < b.p.y) return true; + if (a.p.y - POS_COMPARISON_OFFSET > b.p.y) return false; + if (a.p.z + POS_COMPARISON_OFFSET < b.p.z) return true; + if (a.p.z - POS_COMPARISON_OFFSET > b.p.z) return false; + + if (a.n.x + NORM_COMPARISON_OFFSET < b.n.x) return true; + if (a.n.x - NORM_COMPARISON_OFFSET > b.n.x) return false; + if (a.n.y + NORM_COMPARISON_OFFSET < b.n.y) return true; + if (a.n.y - NORM_COMPARISON_OFFSET > b.n.y) return false; + if (a.n.z + NORM_COMPARISON_OFFSET < b.n.z) return true; + if (a.n.z - NORM_COMPARISON_OFFSET > b.n.z) return false; + + + if (a.uv[0].x + NORM_COMPARISON_OFFSET < b.uv[0].x) return true; + if (a.uv[0].x - NORM_COMPARISON_OFFSET > b.uv[0].x) return false; + if (a.uv[0].y + NORM_COMPARISON_OFFSET < b.uv[0].y) return true; + return false; + }; +}; + +/** +Vertex comparator for vertex welding (not accounts normal and uv parameters of vertice). +*/ +struct VrtPositionComparator +{ + bool operator()(const physx::PxVec3& a, const physx::PxVec3& b) const + { + if (a.x + POS_COMPARISON_OFFSET < b.x) return true; + if (a.x - POS_COMPARISON_OFFSET > b.x) return false; + if (a.y + POS_COMPARISON_OFFSET < b.y) return true; + if (a.y - POS_COMPARISON_OFFSET > b.y) return false; + if (a.z + POS_COMPARISON_OFFSET < b.z) return true; + if (a.z - POS_COMPARISON_OFFSET > b.z) return false; + return false; + }; + bool operator()(const Vertex& a, const Vertex& b) const + { + return operator()(a.p, b.p); + }; +}; + +} // namespace Blast +} // namespace Nv + +#endif
\ No newline at end of file diff --git a/sdk/extensions/authoringCommon/source/NvBlastExtAuthoringMeshImpl.cpp b/sdk/extensions/authoringCommon/source/NvBlastExtAuthoringMeshImpl.cpp new file mode 100644 index 0000000..f0c9a84 --- /dev/null +++ b/sdk/extensions/authoringCommon/source/NvBlastExtAuthoringMeshImpl.cpp @@ -0,0 +1,358 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2016-2018 NVIDIA Corporation. All rights reserved. + +#define _CRT_SECURE_NO_WARNINGS + +#include "NvBlastExtAuthoringMeshImpl.h" +#include "NvBlastExtAuthoringTypes.h" +#include <NvBlastAssert.h> +#include "PxMath.h" +#include <cmath> +#include <string.h> +#include <vector> +#include <algorithm> + +using physx::PxVec2; +using physx::PxVec3; +using physx::PxBounds3; + + +namespace Nv +{ +namespace Blast +{ + +MeshImpl::MeshImpl(const PxVec3* position, const PxVec3* normals, const PxVec2* uv, uint32_t verticesCount, const uint32_t* indices, uint32_t indicesCount) +{ + + mVertices.resize(verticesCount); + for (uint32_t i = 0; i < mVertices.size(); ++i) + { + mVertices[i].p = position[i]; + } + if (normals != 0) + { + for (uint32_t i = 0; i < mVertices.size(); ++i) + { + mVertices[i].n = normals[i]; + } + + } + else + { + for (uint32_t i = 0; i < mVertices.size(); ++i) + { + mVertices[i].n = PxVec3(0, 0, 0); + } + } + if (uv != 0) + { + for (uint32_t i = 0; i < mVertices.size(); ++i) + { + mVertices[i].uv[0] = uv[i]; + } + } + else + { + for (uint32_t i = 0; i < mVertices.size(); ++i) + { + mVertices[i].uv[0] = PxVec2(0, 0); + } + } + mEdges.resize(indicesCount); + mFacets.resize(indicesCount / 3); + + + int32_t facetId = 0; + for (uint32_t i = 0; i < indicesCount; i += 3) + { + mEdges[i].s = indices[i]; + mEdges[i].e = indices[i + 1]; + + mEdges[i + 1].s = indices[i + 1]; + mEdges[i + 1].e = indices[i + 2]; + + mEdges[i + 2].s = indices[i + 2]; + mEdges[i + 2].e = indices[i]; + mFacets[facetId].firstEdgeNumber = i; + mFacets[facetId].edgesCount = 3; + mFacets[facetId].materialId = 0; + //Unassigned for now + mFacets[facetId].smoothingGroup = -1; + facetId++; + } + recalculateBoundingBox(); +} + +MeshImpl::MeshImpl(const Vertex* vertices, const Edge* edges, const Facet* facets, uint32_t posCount, uint32_t edgesCount, uint32_t facetsCount) +{ + mVertices.resize(posCount); + mEdges.resize(edgesCount); + mFacets.resize(facetsCount); + + memcpy(mVertices.data(), vertices, sizeof(Vertex) * posCount); + memcpy(mEdges.data(), edges, sizeof(Edge) * edgesCount); + memcpy(mFacets.data(), facets, sizeof(Facet) * facetsCount); + recalculateBoundingBox(); +} + +MeshImpl::MeshImpl(const Vertex* vertices, uint32_t count) +{ + mVertices = std::vector<Vertex>(vertices, vertices + count); + mEdges.resize(count); + mFacets.resize(count / 3); + uint32_t vp = 0; + for (uint32_t i = 0; i < count; i += 3) + { + mEdges[i].s = vp; + mEdges[i].e = vp + 1; + + mEdges[i + 1].s = vp + 1; + mEdges[i + 1].e = vp + 2; + + mEdges[i + 2].s = vp + 2; + mEdges[i + 2].e = vp; + vp += 3; + } + for (uint32_t i = 0; i < count / 3; ++i) + { + mFacets[i].edgesCount = 3; + mFacets[i].firstEdgeNumber = i * 3; + } + recalculateBoundingBox(); +} + +MeshImpl::MeshImpl(const Vertex* vertices, uint32_t count, uint32_t* indices, uint32_t indexCount, void* materials, uint32_t materialStride) +{ + mVertices = std::vector<Vertex>(vertices, vertices + count); + mEdges.resize(indexCount); + mFacets.resize(indexCount / 3); + + for (uint32_t i = 0; i < indexCount; i += 3) + { + mEdges[i].s = indices[i]; + mEdges[i].e = indices[i + 1]; + + mEdges[i + 1].s = indices[i + 1]; + mEdges[i + 1].e = indices[i + 2]; + + mEdges[i + 2].s = indices[i + 2]; + mEdges[i + 2].e = indices[i]; + } + for (uint32_t i = 0; i < indexCount / 3; ++i) + { + mFacets[i].edgesCount = 3; + mFacets[i].firstEdgeNumber = i * 3; + mFacets[i].userData = 0; + if (materials != nullptr) + { + mFacets[i].materialId = *(uint32_t*)((uint8_t*)materials + i * materialStride); + } + } + recalculateBoundingBox(); +} + + + +float MeshImpl::getMeshVolume() +{ + /** + Check if mesh boundary consist only of triangles + */ + for (uint32_t i = 0; i < mFacets.size(); ++i) + { + if (mFacets[i].edgesCount != 3) + { + return 0.0f; + } + } + + float volume = 0; + for (uint32_t i = 0; i < mFacets.size(); ++i) + { + int32_t offset = mFacets[i].firstEdgeNumber; + PxVec3& a = mVertices[mEdges[offset].s].p; + PxVec3& b = mVertices[mEdges[offset + 1].s].p; + PxVec3& c = mVertices[mEdges[offset + 2].s].p; + + volume += (a.x * b.y * c.z - a.x * b.z * c.y - a.y * b.x * c.z + a.y * b.z * c.x + a.z * b.x * c.y - a.z * b.y * c.x); + } + return (1.0f / 6.0f) * std::abs(volume); +} + + +uint32_t MeshImpl::getFacetCount() const +{ + return static_cast<uint32_t>(mFacets.size()); +} + +Vertex* MeshImpl::getVerticesWritable() +{ + return mVertices.data(); +} + +Edge* MeshImpl::getEdgesWritable() +{ + return mEdges.data(); +} + +const Vertex* MeshImpl::getVertices() const +{ + return mVertices.data(); +} + +const Edge* MeshImpl::getEdges() const +{ + return mEdges.data(); +} + +uint32_t MeshImpl::getEdgesCount() const +{ + return static_cast<uint32_t>(mEdges.size()); +} +uint32_t MeshImpl::getVerticesCount() const +{ + return static_cast<uint32_t>(mVertices.size()); +} +Facet* MeshImpl::getFacetsBufferWritable() +{ + return mFacets.data(); +} +const Facet* MeshImpl::getFacetsBuffer() const +{ + return mFacets.data(); +} +Facet* MeshImpl::getFacetWritable(int32_t facet) +{ + return &mFacets[facet]; +} +const Facet* MeshImpl::getFacet(int32_t facet) const +{ + return &mFacets[facet]; +} + +MeshImpl::~MeshImpl() +{ +} + +void MeshImpl::release() +{ + delete this; +} + +const PxBounds3& MeshImpl::getBoundingBox() const +{ + return mBounds; +} + +PxBounds3& MeshImpl::getBoundingBoxWritable() +{ + return mBounds; +} + + +void MeshImpl::recalculateBoundingBox() +{ + mBounds.setEmpty(); + for (uint32_t i = 0; i < mVertices.size(); ++i) + { + mBounds.include(mVertices[i].p); + } + calcPerFacetBounds(); +} + +const physx::PxBounds3* MeshImpl::getFacetBound(uint32_t index) const +{ + if (mPerFacetBounds.empty()) + { + return nullptr; + } + return &mPerFacetBounds[index]; +} + +void MeshImpl::calcPerFacetBounds() +{ + mPerFacetBounds.resize(mFacets.size()); + + for (uint32_t i = 0; i < mFacets.size(); ++i) + { + auto& fb = mPerFacetBounds[i]; + fb.setEmpty(); + + for (uint32_t v = 0; v < mFacets[i].edgesCount; ++v) + { + fb.include(mVertices[mEdges[mFacets[i].firstEdgeNumber + v].s].p); + fb.include(mVertices[mEdges[mFacets[i].firstEdgeNumber + v].e].p); + } + } +} + +void MeshImpl::setMaterialId(const int32_t* materialId) +{ + if (materialId != nullptr) + { + for (uint32_t i = 0; i < mFacets.size(); ++i) + { + mFacets[i].materialId = *materialId; + ++materialId; + } + } +} + +bool MeshImpl::isValid() const +{ + return mVertices.size() > 0 && mEdges.size() > 0 && mFacets.size() > 0; +} + + +void MeshImpl::replaceMaterialId(int32_t oldMaterialId, int32_t newMaterialId) +{ + for (uint32_t i = 0; i < mFacets.size(); ++i) + { + if (mFacets[i].materialId == oldMaterialId) + { + mFacets[i].materialId = newMaterialId; + } + } +} + +void MeshImpl::setSmoothingGroup(const int32_t* smoothingGroups) +{ + if (smoothingGroups != nullptr) + { + for (uint32_t i = 0; i < mFacets.size(); ++i) + { + mFacets[i].smoothingGroup = *smoothingGroups; + ++smoothingGroups; + } + } +} + + + +} // namespace Blast +} // namespace Nv diff --git a/sdk/extensions/authoringCommon/source/NvBlastExtAuthoringMeshImpl.h b/sdk/extensions/authoringCommon/source/NvBlastExtAuthoringMeshImpl.h new file mode 100644 index 0000000..0f4c339 --- /dev/null +++ b/sdk/extensions/authoringCommon/source/NvBlastExtAuthoringMeshImpl.h @@ -0,0 +1,200 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2016-2018 NVIDIA Corporation. All rights reserved. + +#ifndef NVBLASTAUTHORINGMESHIMPL_H +#define NVBLASTAUTHORINGMESHIMPL_H + +#include "NvBlastExtAuthoringMesh.h" +#include <vector> +#include <map> +#include <set> + +namespace Nv +{ +namespace Blast +{ + +/** + Class for internal mesh representation +*/ +class MeshImpl : public Mesh +{ +public: + + /** + Constructs mesh object from array of triangles. + \param[in] position Array of vertex positions + \param[in] normals Array of vertex normals + \param[in] uv Array of vertex uv coordinates + \param[in] verticesCount Vertices count + \param[in] indices Array of vertex indices. Indices contain vertex index triplets which form a mesh triangle. + \param[in] indicesCount Indices count (should be equal to numberOfTriangles * 3) + */ + MeshImpl(const physx::PxVec3* position, const physx::PxVec3* normals, const physx::PxVec2* uv, uint32_t verticesCount, const uint32_t* indices, uint32_t indicesCount); + + /** + Constructs mesh object from array of facets. + \param[in] vertices Array of vertices + \param[in] edges Array of edges + \param[in] facets Array of facets + \param[in] posCount Vertices count + \param[in] edgesCount Edges count + \param[in] facetsCount Facets count + */ + MeshImpl(const Vertex* vertices, const Edge* edges, const Facet* facets, uint32_t posCount, uint32_t edgesCount, uint32_t facetsCount); + + MeshImpl(const Vertex* vertices, uint32_t count); + + MeshImpl(const Vertex* vertices, uint32_t count, uint32_t* indices, uint32_t indexCount, void* materials, uint32_t materialStride); + + ~MeshImpl(); + + virtual void release() override; + + /** + Return true if mesh is valid + */ + bool isValid() const override; + + /** + Return pointer on vertices array + */ + Vertex* getVerticesWritable() override; + + /** + Return pointer on edges array + */ + Edge* getEdgesWritable() override; + + /** + Return pointer on facets array + */ + Facet* getFacetsBufferWritable() override; + + /** + Return pointer on vertices array + */ + const Vertex* getVertices() const override; + + /** + Return pointer on edges array + */ + const Edge* getEdges() const override; + + /** + Return pointer on facets array + */ + const Facet* getFacetsBuffer() const override; + + /** + Return writable pointer on specified facet + */ + Facet* getFacetWritable(int32_t facet) override; + + /** + Return writable pointer on specified facet + */ + const Facet* getFacet(int32_t facet) const override; + + /** + Return edges count + */ + uint32_t getEdgesCount() const override; + + /** + Return vertices count + */ + uint32_t getVerticesCount() const override; + + /** + Return facet count + */ + uint32_t getFacetCount() const override; + + + /** + Return reference on mesh bounding box. + */ + const physx::PxBounds3& getBoundingBox() const override; + + /** + Return writable reference on mesh bounding box. + */ + physx::PxBounds3& getBoundingBoxWritable() override; + + /** + Recalculate bounding box + */ + void recalculateBoundingBox() override; + + /** + Compute mesh volume. Can be used only for triangulated meshes. + Return mesh volume. If mesh is not triangulated return 0. + */ + float getMeshVolume() override; + + + /** + Set per-facet material id. + */ + void setMaterialId(const int32_t* materialIds) override; + + /** + Replaces an material id on faces with a new one + */ + void replaceMaterialId(int32_t oldMaterialId, int32_t newMaterialId) override; + + /** + Set per-facet smoothing group. + */ + void setSmoothingGroup(const int32_t* smoothingGroups) override; + + /** + Calculate per-facet bounding boxes. + */ + virtual void calcPerFacetBounds() override; + + /** + Get pointer on facet bounding box, if not calculated return nullptr. + */ + virtual const physx::PxBounds3* getFacetBound(uint32_t index) const override; + +private: + std::vector<Vertex> mVertices; + std::vector<Edge> mEdges; + std::vector<Facet> mFacets; + physx::PxBounds3 mBounds; + std::vector<physx::PxBounds3> mPerFacetBounds; +}; + + + +} // namespace Blast +} // namespace Nv + + +#endif // ifndef NVBLASTAUTHORINGMESHIMPL_H |