From 6f51c0ad55f3ed33597b8b12391d426fe28a0923 Mon Sep 17 00:00:00 2001 From: bgaldrikian Date: Wed, 3 Oct 2018 17:51:20 -0700 Subject: Blast 1.1.4. See docs/release_notes.txt. --- .../authoring/source/NvBlastExtAuthoring.cpp | 41 +- .../source/NvBlastExtAuthoringAccelerator.cpp | 845 --------------- .../source/NvBlastExtAuthoringAccelerator.h | 220 ---- .../NvBlastExtAuthoringBondGeneratorImpl.cpp | 495 ++++++--- .../source/NvBlastExtAuthoringBondGeneratorImpl.h | 21 +- .../source/NvBlastExtAuthoringBooleanTool.cpp | 28 +- .../source/NvBlastExtAuthoringBooleanTool.h | 1 - .../NvBlastExtAuthoringCollisionBuilderImpl.cpp | 17 +- .../NvBlastExtAuthoringCollisionBuilderImpl.h | 2 + .../source/NvBlastExtAuthoringFractureToolImpl.cpp | 76 +- .../source/NvBlastExtAuthoringFractureToolImpl.h | 5 +- .../source/NvBlastExtAuthoringInternalCommon.h | 260 ----- .../source/NvBlastExtAuthoringMeshCleanerImpl.cpp | 26 + .../source/NvBlastExtAuthoringMeshCleanerImpl.h | 34 +- .../source/NvBlastExtAuthoringMeshImpl.cpp | 1139 -------------------- .../authoring/source/NvBlastExtAuthoringMeshImpl.h | 289 ----- .../source/NvBlastExtAuthoringMeshUtils.cpp | 941 ++++++++++++++++ .../source/NvBlastExtAuthoringMeshUtils.h | 126 +++ .../NvBlastExtAuthoringPatternGeneratorImpl.cpp | 311 ++++++ .../NvBlastExtAuthoringPatternGeneratorImpl.h | 58 + .../source/NvBlastExtAuthoringTriangulator.cpp | 2 +- 21 files changed, 1968 insertions(+), 2969 deletions(-) delete mode 100755 sdk/extensions/authoring/source/NvBlastExtAuthoringAccelerator.cpp delete mode 100755 sdk/extensions/authoring/source/NvBlastExtAuthoringAccelerator.h delete mode 100755 sdk/extensions/authoring/source/NvBlastExtAuthoringInternalCommon.h delete mode 100755 sdk/extensions/authoring/source/NvBlastExtAuthoringMeshImpl.cpp delete mode 100755 sdk/extensions/authoring/source/NvBlastExtAuthoringMeshImpl.h create mode 100644 sdk/extensions/authoring/source/NvBlastExtAuthoringMeshUtils.cpp create mode 100644 sdk/extensions/authoring/source/NvBlastExtAuthoringMeshUtils.h create mode 100644 sdk/extensions/authoring/source/NvBlastExtAuthoringPatternGeneratorImpl.cpp create mode 100644 sdk/extensions/authoring/source/NvBlastExtAuthoringPatternGeneratorImpl.h (limited to 'sdk/extensions/authoring/source') diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoring.cpp b/sdk/extensions/authoring/source/NvBlastExtAuthoring.cpp index 6bc12bd..ef012d6 100755 --- a/sdk/extensions/authoring/source/NvBlastExtAuthoring.cpp +++ b/sdk/extensions/authoring/source/NvBlastExtAuthoring.cpp @@ -38,6 +38,8 @@ #include "NvBlastGlobals.h" #include "NvBlastExtPxAsset.h" #include "NvBlastExtAssetUtils.h" +#include "NvBlastExtAuthoringPatternGeneratorImpl.h" +#include "NvBlastExtAuthoringAccelerator.h" #include #include @@ -53,6 +55,11 @@ Mesh* NvBlastExtAuthoringCreateMesh(const PxVec3* position, const PxVec3* normal return new MeshImpl(position, normals, uv, verticesCount, indices, indicesCount); } +Mesh* NvBlastExtAuthoringCreateMeshOnlyTriangles(const void* Vertices, uint32_t vcount, uint32_t* indices, uint32_t indexCount, void* materials, uint32_t materialStride) +{ + return new MeshImpl((Vertex*)Vertices, vcount, indices, indexCount, materials, materialStride); +} + Mesh* NvBlastExtAuthoringCreateMeshFromFacets(const void* vertices, const void* edges, const void* facets, uint32_t verticesCount, uint32_t edgesCount, uint32_t facetsCount) { return new MeshImpl((Vertex*)vertices, (Edge*)edges, (Facet*)facets, verticesCount, edgesCount, facetsCount); @@ -222,11 +229,6 @@ void buildPhysicsChunks(ConvexMeshBuilder& collisionBuilder, AuthoringResult& re SAFE_ARRAY_DELETE(tempHull); } - SAFE_ARRAY_DELETE(result.collisionHullOffset); - SAFE_ARRAY_DELETE(result.collisionHull); - SAFE_ARRAY_DELETE(result.physicsSubchunks); - SAFE_ARRAY_DELETE(result.physicsChunks); - result.collisionHullOffset = SAFE_ARRAY_NEW(uint32_t, chunkCount + 1); result.collisionHullOffset[0] = 0; result.collisionHull = SAFE_ARRAY_NEW(CollisionHull*, totalHulls); @@ -255,6 +257,14 @@ void buildPhysicsChunks(ConvexMeshBuilder& collisionBuilder, AuthoringResult& re struct AuthoringResultImpl : public AuthoringResult { + AuthoringResultImpl() + { + collisionHullOffset = nullptr; + collisionHull = nullptr; + physicsChunks = nullptr; + physicsSubchunks = nullptr; + } + void releaseCollisionHulls() override { if (collisionHull != nullptr) @@ -313,8 +323,7 @@ AuthoringResult* NvBlastExtAuthoringProcessFracture(FractureTool& fTool, BlastBo } } - BondGenerationConfig cnf; - cnf.bondMode = BondGenerationConfig::EXACT; + const uint32_t bondCount = bondGenerator.buildDescFromInternalFracture(&fTool, isSupport.get(), aResult.bondDescs, aResult.chunkDescs); aResult.bondCount = bondCount; @@ -535,3 +544,21 @@ void NvBlastExtAuthoringBuildCollisionMeshes(Nv::Blast::AuthoringResult& ares, N { buildPhysicsChunks(collisionBuilder, ares, collisionParam, chunksToProcessCount, chunksToProcess); } + +PatternGenerator* NvBlastExtAuthoringCreatePatternGenerator() +{ + return NVBLAST_NEW(PatternGeneratorImpl); +} + +Grid* NvBlastExtAuthoringCreateGridAccelerator(uint32_t resolution, const Mesh* m) +{ + Grid* g = NVBLAST_NEW(Grid)(resolution); + g->setMesh(m); + return g; +} + +GridWalker* NvBlastExtAuthoringCreateGridWalker(Grid* parentGrid) +{ + return NVBLAST_NEW(GridWalker)(parentGrid); +} + diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringAccelerator.cpp b/sdk/extensions/authoring/source/NvBlastExtAuthoringAccelerator.cpp deleted file mode 100755 index 69c7d65..0000000 --- a/sdk/extensions/authoring/source/NvBlastExtAuthoringAccelerator.cpp +++ /dev/null @@ -1,845 +0,0 @@ -// 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" - - -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::PxVec3& point) { - current = 0; - NV_UNUSED(point); -} -int32_t DummyAccelerator::getNextFacet() -{ - if (current < count) - { - ++current; - return current - 1; - } - else - return -1; -} - - - -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; - } - } - } - - buildAccelStructure(mesh->getVertices(), mesh->getEdges(), mesh->getFacetsBuffer(), mesh->getFacetCount()); -} - - -BBoxBasedAccelerator::~BBoxBasedAccelerator() -{ - mResolution = 0; - mBounds.setEmpty(); - mSpatialMap.clear(); - mCells.clear(); -} - -int32_t BBoxBasedAccelerator::getNextFacet() -{ - int32_t facetId = -1; - - while (mIteratorCell != -1) - { - if (mIteratorFacet >= (int32_t)mSpatialMap[mIteratorCell].size()) - { - if (!cellList.empty()) - { - mIteratorCell = cellList.back(); - cellList.pop_back(); - 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) -{ - alreadyGotValue++; - mIteratorCell = -1; - mIteratorFacet = -1; - cellList.clear(); - facetBox.setEmpty(); - const Edge* edge = ed + fc.firstEdgeNumber; - uint32_t count = fc.edgesCount; - for (uint32_t ec = 0; ec < count; ++ec) - { - facetBox.include(pos[edge->s].p); - facetBox.include(pos[edge->e].p); - edge++; - } - for (uint32_t i = 0; i < mCells.size(); ++i) - { - if (testCellPolygonIntersection(i, facetBox)) - { - if (!mSpatialMap[i].empty()) - cellList.push_back(i); - } - } - if (!cellList.empty()) - { - mIteratorFacet = 0; - mIteratorCell = cellList.back(); - cellList.pop_back(); - } -} - - -void BBoxBasedAccelerator::setState(const PxVec3& p) -{ - alreadyGotValue++; - mIteratorCell = -1; - mIteratorFacet = -1; - cellList.clear(); - 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.push_back(cell); - } - } - } - if (!cellList.empty()) - { - mIteratorFacet = 0; - mIteratorCell = cellList.back(); - cellList.pop_back(); - } -} - - -bool BBoxBasedAccelerator::testCellPolygonIntersection(int32_t cellId, PxBounds3& facetBB) -{ - if (weakBoundingBoxIntersection(mCells[cellId], facetBB)) - { - return true; - } - else - return false; -} - -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 (testCellPolygonIntersection(i, bBox)) - { - mSpatialMap[i].push_back(facet); - } - } - fc++; - } - alreadyGotFlag.resize(facetCount, 0); - cellList.resize(mCells.size()); -} - -int32_t testEdgeAgainstCube(PxVec3& p1, PxVec3& p2) -{ - PxVec3 vec = p2 - p1; - PxVec3 vecSigns; - for (int32_t i = 0; i < 3; ++i) - { - vecSigns[i] = (vec[i] < 0) ? -1 : 1; - } - for (int32_t i = 0; i < 3; ++i) - { - if (p1[i] * vecSigns[i] > 0.5f) return 0; - if (p2[i] * vecSigns[i] < -0.5f) return 0; - } - - for (int32_t i = 0; i < 3; ++i) - { - int32_t ip1 = (i + 1) % 3; - int32_t ip2 = (i + 2) % 3; - - float vl1 = vec[ip2] * p1[ip1] - vec[ip1] * p1[ip2]; - float vl2 = 0.5f * (vec[ip2] * vecSigns[ip1] + vec[ip1] * vecSigns[ip2]); - if (vl1 * vl1 > vl2 * vl2) - { - return 0; - } - } - return 1; -} - -NV_INLINE int32_t isInSegm(float a, float b, float c) -{ - return (b >= c) - (a >= c); -} - -NV_INLINE int32_t edgeIsAbovePoint(PxVec2& p1, PxVec2& p2, PxVec2& p) -{ - int32_t direction = isInSegm(p1.x, p2.x, p.x); - if (direction != 0) - { - if (isInSegm(p1.y, p2.y, p.y)) - { - if (direction * (p.x - p1.x) * (p2.y - p1.y) >= direction * (p.y - p1.y) * (p2.x - p1.x)) - { - return direction; - } - } - else - { - if (p1.y > p.y) - return direction; - } - } - return 0; -} - -int32_t pointInPolygon(PxVec3* vertices, PxVec3& diagPoint, int32_t edgeCount, PxVec3& normal) -{ - std::vector projectedVertices(edgeCount * 2); - ProjectionDirections pDir = getProjectionDirection(normal); - PxVec2 projectedDiagPoint = getProjectedPoint(diagPoint, pDir); - PxVec2* saveVert = projectedVertices.data(); - PxVec3* p = vertices; - for (int32_t i = 0; i < edgeCount * 2; ++i) - { - *saveVert = getProjectedPoint(*p, pDir); - ++saveVert; - ++p; - } - int32_t counter = 0; - PxVec2* v = projectedVertices.data(); - for (int32_t i = 0; i < edgeCount; ++i) - { - PxVec2& p1 = *v; - PxVec2& p2 = *(v + 1); - counter += edgeIsAbovePoint(p1, p2, projectedDiagPoint); - v += 2; - } - return counter != 0; -} - - - -int32_t testFacetUnitCubeIntersectionInternal(PxVec3* vertices,PxVec3& facetNormal, int32_t edgeCount) -{ - PxVec3* pnt_p = vertices; - for (int32_t i = 0; i < edgeCount; ++i) - { - if (testEdgeAgainstCube(*pnt_p, *(pnt_p + 1)) == 1) - { - return 1; - } - pnt_p += 2; - } - - PxVec3 cubeDiag(0, 0, 0); - for (int32_t i = 0; i < 3; ++i) - cubeDiag[i] = (facetNormal[i] < 0) ? -1 : 1; - float t = vertices->dot(facetNormal) / (cubeDiag.dot(facetNormal)); - if (t > 0.5 || t < -0.5) - return 0; - - PxVec3 intersPoint = cubeDiag * t; - int trs = pointInPolygon(vertices, intersPoint, edgeCount, facetNormal); - return trs; -} - -enum TrivialFlags -{ - HAS_POINT_BELOW_HIGH_X = ~(1 << 0), - HAS_POINT_ABOVE_LOW_X = ~(1 << 1), - - HAS_POINT_BELOW_HIGH_Y = ~(1 << 2), - HAS_POINT_ABOVE_LOW_Y = ~(1 << 3), - - HAS_POINT_BELOW_HIGH_Z = ~(1 << 4), - HAS_POINT_ABOVE_LOW_Z = ~(1 << 5), - - - - ALL_ONE = (1 << 6) - 1 -}; - - - - - -int32_t testFacetUnitCubeIntersection(const Vertex* vertices, const Edge* edges, const Facet& fc, PxBounds3 cube, float fattening) -{ - const Edge* ed = edges + fc.firstEdgeNumber; - int32_t trivialFlags = ALL_ONE; - cube.fattenFast(fattening); - for (uint32_t i = 0; i < fc.edgesCount; ++i) - { - { - const PxVec3& p = vertices[ed->s].p; - if (cube.contains(p)) - return 1; - if (p.x < cube.getCenter().x + 0.5) - trivialFlags &= HAS_POINT_BELOW_HIGH_X; - if (p.x > cube.getCenter().x - 0.5) - trivialFlags &= HAS_POINT_ABOVE_LOW_X; - - if (p.y < cube.getCenter().y + 0.5) - trivialFlags &= HAS_POINT_BELOW_HIGH_Y; - if (p.y > cube.getCenter().y - 0.5) - trivialFlags &= HAS_POINT_ABOVE_LOW_Y; - - if (p.z < cube.getCenter().z + 0.5) - trivialFlags &= HAS_POINT_BELOW_HIGH_Z; - if (p.z > cube.getCenter().z - 0.5) - trivialFlags &= HAS_POINT_ABOVE_LOW_Z; - } - { - const PxVec3& p = vertices[ed->e].p; - if (cube.contains(p)) - return 1; - if (p.x < cube.getCenter().x + 0.5) - trivialFlags &= HAS_POINT_BELOW_HIGH_X; - if (p.x > cube.getCenter().x - 0.5) - trivialFlags &= HAS_POINT_ABOVE_LOW_X; - - if (p.y < cube.getCenter().y + 0.5) - trivialFlags &= HAS_POINT_BELOW_HIGH_Y; - if (p.y > cube.getCenter().y - 0.5) - trivialFlags &= HAS_POINT_ABOVE_LOW_Y; - - if (p.z < cube.getCenter().z + 0.5) - trivialFlags &= HAS_POINT_BELOW_HIGH_Z; - if (p.z > cube.getCenter().z - 0.5) - trivialFlags &= HAS_POINT_ABOVE_LOW_Z; - } - - ++ed; - } - if (trivialFlags != 0) - { - return 0; - } - std::vector verticesRescaled(fc.edgesCount * 2); - - int32_t vrt = 0; - ed = edges + fc.firstEdgeNumber; - PxVec3 offset = cube.getCenter(); - PxVec3 normal(1, 1, 1); - - /** - Compute normal - */ - const PxVec3& v1 = vertices[ed->s].p; - const PxVec3* v2 = nullptr; - const PxVec3* v3 = nullptr; - - for (uint32_t i = 0; i < fc.edgesCount; ++i) - { - if (v1 != vertices[ed->s].p) - { - v2 = &vertices[ed->s].p; - break; - } - if (v1 != vertices[ed->e].p) - { - v2 = &vertices[ed->e].p; - break; - } - ed++; - } - ed = edges + fc.firstEdgeNumber; - for (uint32_t i = 0; i < fc.edgesCount; ++i) - { - if (v1 != vertices[ed->s].p && *v2 != vertices[ed->s].p) - { - v3 = &vertices[ed->s].p; - break; - } - if (v1 != vertices[ed->e].p && *v2 != vertices[ed->e].p) - { - v3 = &vertices[ed->e].p; - break; - } - ed++; - } - ed = edges + fc.firstEdgeNumber; - if (v2 != nullptr && v3 != nullptr) - { - normal = (*v2 - v1).cross(*v3 - v1); - } - else - { - return true; // If cant find normal, assume it intersects box. - } - - - normal.normalize(); - - PxVec3 rescale(.5f / (cube.getExtents().x), .5f / (cube.getExtents().y), 0.5f / (cube.getExtents().z)); - for (uint32_t i = 0; i < fc.edgesCount; ++i) - { - verticesRescaled[vrt] = vertices[ed->s].p - offset; - verticesRescaled[vrt].x *= rescale.x; - verticesRescaled[vrt].y *= rescale.y; - verticesRescaled[vrt].z *= rescale.z; - ++vrt; - verticesRescaled[vrt] = vertices[ed->e].p - offset; - verticesRescaled[vrt].x *= rescale.x; - verticesRescaled[vrt].y *= rescale.y; - verticesRescaled[vrt].z *= rescale.z; - ++ed; - ++vrt; - } - return testFacetUnitCubeIntersectionInternal(verticesRescaled.data(), normal, fc.edgesCount); -} - - -IntersectionTestingAccelerator::IntersectionTestingAccelerator(const Mesh* in, int32_t resolution) -{ - - - alreadyGotFlag.resize(in->getFacetCount(), 0); - alreadyGotValue = 0; - mResolution = resolution; - - float cubeSize = 1.0f / resolution; - PxVec3 cubeMinimal(-0.5, -0.5, -0.5); - PxVec3 extents(cubeSize, cubeSize, cubeSize); - mCubes.resize(mResolution * mResolution * mResolution); - mSpatialMap.resize(mCubes.size()); - int32_t cubeId = 0; - - // Build unit cube partition - for (int32_t i = 0; i < mResolution; ++i) - { - cubeMinimal.y = -0.5; - cubeMinimal.z = -0.5; - for (int32_t j = 0; j < mResolution; ++j) - { - cubeMinimal.z = -0.5; - for (int32_t k = 0; k < mResolution; ++k) - { - mCubes[cubeId].minimum = cubeMinimal; - mCubes[cubeId].maximum = cubeMinimal + extents; - cubeMinimal.z += cubeSize; - ++cubeId; - } - cubeMinimal.y += cubeSize; - } - cubeMinimal.x += cubeSize; - } - - - for (uint32_t i = 0; i < in->getFacetCount(); ++i) - { - for (uint32_t c = 0; c < mCubes.size(); ++c) - { - if (testFacetUnitCubeIntersection(in->getVertices(), in->getEdges(), *in->getFacet(i), mCubes[c], 0.001)) - { - mSpatialMap[c].push_back(i); - } - } - } -} - - -int32_t IntersectionTestingAccelerator::getNextFacet() -{ - int32_t facetId = -1; - - while (mIteratorCell != -1) - { - if (mIteratorFacet >= (int32_t)mSpatialMap[mIteratorCell].size()) - { - if (!cellList.empty()) - { - mIteratorCell = cellList.back(); - cellList.pop_back(); - 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 IntersectionTestingAccelerator::setState(const Vertex* pos, const Edge* ed, const Facet& fc) -{ - alreadyGotValue++; - mIteratorCell = -1; - mIteratorFacet = -1; - cellList.clear(); - PxBounds3 bigBox(PxVec3(-0.5, -0.5, -0.5), PxVec3(0.5, 0.5, 0.5)); - if (!testFacetUnitCubeIntersection(pos, ed, fc, bigBox, 0.001f)) - { - return; - } - for (uint32_t i = 0; i < mCubes.size(); ++i) - { - if (!mSpatialMap[i].empty()) - if (testFacetUnitCubeIntersection(pos, ed, fc, mCubes[i], 0.001f)) - { - cellList.push_back(i); - } - } - if (!cellList.empty()) - { - mIteratorFacet = 0; - mIteratorCell = cellList.back(); - cellList.pop_back(); - } -} - -void IntersectionTestingAccelerator::setState(const PxVec3& p) -{ - alreadyGotValue++; - mIteratorCell = -1; - mIteratorFacet = -1; - cellList.clear(); - - - for (uint32_t i = 0; i < mCubes.size(); ++i) - { - PxBounds3 tmp = mCubes[i]; - tmp.fattenFast(0.001); - if (tmp.contains(p)) - { - int32_t xyCellId = (((int)((float)i / mResolution)) * mResolution); - for (int32_t zCell = 0; zCell < mResolution; ++zCell) - { - int32_t cell = zCell + xyCellId; - if (!mSpatialMap[cell].empty()) - { - cellList.push_back(cell); - } - - } - } - } - if (!cellList.empty()) - { - mIteratorFacet = 0; - mIteratorCell = cellList.back(); - cellList.pop_back(); - } -} - - -#define SWEEP_RESOLUTION 2048 - - -void buildIndex(std::vector& segm, float offset, float mlt, std::vector>& blocks) -{ - std::set 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 xevs; - std::vector yevs; - std::vector 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 Vertex* pos, const Edge* ed, const Facet& fc) -{ - current = 0; - indices.clear(); - - PxBounds3 bnd; - bnd.setEmpty(); - for (uint32_t i = 0; i < fc.edgesCount; ++i) - { - bnd.include(pos[ed[fc.firstEdgeNumber + i].s].p); - } - 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 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(current) < indices.size()) - { - ++current; - return indices[current - 1]; - } - else - return -1; -} - - - - - - -} // namespace Blast -} // namespace Nv diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringAccelerator.h b/sdk/extensions/authoring/source/NvBlastExtAuthoringAccelerator.h deleted file mode 100755 index e206e58..0000000 --- a/sdk/extensions/authoring/source/NvBlastExtAuthoringAccelerator.h +++ /dev/null @@ -1,220 +0,0 @@ -// 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 NVBLASTEXTAUTHORINGACCELERATOR_H -#define NVBLASTEXTAUTHORINGACCELERATOR_H - -#include -#include -#include "NvBlastExtAuthoringTypes.h" - - -namespace Nv -{ - namespace Blast - { - - class Mesh; - - - /** - Acceleration structure interface. - */ - class SpatialAccelerator - { - public: - /** - Set state of accelerator to return all facets which possibly can intersect given facet. - \param[in] pos Vertex buffer - \param[in] ed Edge buffer - \param[in] fc Facet which should be tested. - */ - virtual void setState(const Vertex* pos, const Edge* ed, const Facet& fc) = 0; - /** - Set state of accelerator to return all facets which possibly can cover given point. Needed for testing whether point is inside mesh. - \param[in] point Point which should be tested. - */ - virtual void setState(const physx::PxVec3& point) = 0; - /** - Recieve next facet for setted state. - \return Next facet index, or -1 if no facets left. - */ - virtual int32_t getNextFacet() = 0; - - - virtual ~SpatialAccelerator() {}; - }; - - - /** - Dummy accelerator iterates through all facets of mesh. - */ - class DummyAccelerator : public SpatialAccelerator - { - public: - /** - \param[in] count Mesh facets count for which accelerator should be built. - */ - DummyAccelerator(int32_t count); - virtual void setState(const Vertex* pos, const Edge* ed, const Facet& fc); - virtual void setState(const physx::PxVec3& point); - virtual int32_t getNextFacet(); - - private: - int32_t count; - int32_t current; - }; - - struct SegmentToIndex - { - float coord; - uint32_t index; - bool end; - - SegmentToIndex(float c, uint32_t i, bool end) : coord(c), index(i), end(end) {}; - - bool operator<(const SegmentToIndex& in) const - { - if (coord < in.coord) return true; - if (coord > in.coord) return false; - return end < in.end; - } - }; - - -class SweepingAccelerator : public SpatialAccelerator -{ -public: - /** - \param[in] count Mesh facets count for which accelerator should be built. - */ - SweepingAccelerator(Nv::Blast::Mesh* in); - virtual void setState(const Vertex* pos, const Edge* ed, const Facet& fc); - virtual void setState(const physx::PxVec3& point); - virtual int32_t getNextFacet(); - -private: - - - /* - For fast point test. - */ - std::vector > xSegm; - std::vector > ySegm; - std::vector > zSegm; - std::vector indices; - std::vector foundx; - std::vector foundy; - - uint32_t iterId; - int32_t current; - uint32_t facetCount; - - physx::PxVec3 minimal; - physx::PxVec3 maximal; - - physx::PxVec3 rescale; - - -}; - - -/** - Accelerator which builds map from 3d grid to initial mesh facets. - To find all facets which possibly intersect given one, it return all facets which are pointed by grid cells, which intersects with bounding box of given facet. - To find all facets which possibly cover given point, all facets which are pointed by cells in column which contains given point are returned. -*/ -class BBoxBasedAccelerator : public SpatialAccelerator -{ -public: - /** - \param[in] mesh Mesh for which acceleration structure should be built. - \param[in] resolution Resolution on 3d grid. - */ - BBoxBasedAccelerator(const Mesh* mesh, int32_t resolution); - virtual ~BBoxBasedAccelerator(); - int32_t getNextFacet(); - void setState(const Vertex* pos, const Edge* ed, const Facet& fc); - void setState(const physx::PxVec3& p); -private: - - bool testCellPolygonIntersection(int32_t cellId, physx::PxBounds3& facetBB); - void buildAccelStructure(const Vertex* pos, const Edge* edges, const Facet* fc, int32_t facetCount); - - int32_t mResolution; - physx::PxBounds3 mBounds; - physx::PxBounds3 facetBox; - std::vector< std::vector > mSpatialMap; - std::vector mCells; - - - // Iterator data - std::vector alreadyGotFlag; - uint32_t alreadyGotValue; - std::vector cellList; - int32_t mIteratorCell; - int32_t mIteratorFacet; -}; - - - -/** - Accelerator which builds map from 3d grid to initial mesh facets. - To find all facets which possibly intersect given one, it return all facets which are pointed by grid cells, which are intersected by given facet. - To find all facets which possibly cover given point, all facets which are pointed by cells in column which contains given point are returned. - - In difference with BBoxBasedAccelerator this accelerator computes actual intersection of cube with polygon. It is more precise and omits much more intersections but slower. -*/ - -class IntersectionTestingAccelerator : public SpatialAccelerator -{ -public: - IntersectionTestingAccelerator(const Mesh* mesh, int32_t resolution); - int32_t getNextFacet(); - void setState(const Vertex* pos, const Edge* ed, const Facet& fc); - void setState(const physx::PxVec3& p); - - -private: - std::vector< std::vector > mSpatialMap; - std::vector mCubes; - int32_t mResolution; - - // Iterator data - std::vector alreadyGotFlag; - uint32_t alreadyGotValue; - std::vector cellList; - int32_t mIteratorCell; - int32_t mIteratorFacet; -}; - -} // namespace Blast -} // namsepace Nv - - -#endif // ifndef NVBLASTEXTAUTHORINGACCELERATOR_H diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringBondGeneratorImpl.cpp b/sdk/extensions/authoring/source/NvBlastExtAuthoringBondGeneratorImpl.cpp index b73bdd2..2f87c67 100755 --- a/sdk/extensions/authoring/source/NvBlastExtAuthoringBondGeneratorImpl.cpp +++ b/sdk/extensions/authoring/source/NvBlastExtAuthoringBondGeneratorImpl.cpp @@ -97,6 +97,7 @@ std::vector intersectionBuffer; std::vector meshBuffer; #endif + namespace Nv { namespace Blast @@ -148,7 +149,52 @@ namespace Nv int32_t m_chunkId; }; - float BlastBondGeneratorImpl::processWithMidplanes(TriangleProcessor* trProcessor, const std::vector& chunk1Points, const std::vector& chunk2Points, + void AddTtAnchorPoints(const Triangle* a, const Triangle* b, std::vector& points) + { + PxVec3 na = a->getNormal().getNormalized(); + PxVec3 nb = b->getNormal().getNormalized(); + + PxPlane pla(a->a.p, na); + PxPlane plb(b->a.p, nb); + + + ProjectionDirections da = getProjectionDirection(na); + ProjectionDirections db = getProjectionDirection(nb); + + TriangleProcessor prc; + + TrPrcTriangle2d ta(getProjectedPoint(a->a.p, da), getProjectedPoint(a->b.p, da), getProjectedPoint(a->c.p, da)); + TrPrcTriangle2d tb(getProjectedPoint(b->a.p, db), getProjectedPoint(b->b.p, db), getProjectedPoint(b->c.p, db)); + + /** + Compute + */ + for (uint32_t i = 0; i < 3; ++i) + { + PxVec3 pt; + if (getPlaneSegmentIntersection(pla, b->getVertex(i).p, b->getVertex((i + 1) % 3).p, pt)) + { + + PxVec2 pt2 = getProjectedPoint(pt, da); + if (prc.isPointInside(pt2, ta)) + { + points.push_back(pt); + } + } + if (getPlaneSegmentIntersection(plb, a->getVertex(i).p, a->getVertex((i + 1) % 3).p, pt)) + { + PxVec2 pt2 = getProjectedPoint(pt, db); + if (prc.isPointInside(pt2, tb)) + { + points.push_back(pt); + } + } + } + + } + + + float BlastBondGeneratorImpl::processWithMidplanes(TriangleProcessor* trProcessor, const Triangle* mA, uint32_t mavc, const Triangle* mB, uint32_t mbvc, const std::vector& hull1p, const std::vector& hull2p, PxVec3& normal, PxVec3& centroid, float maxSeparation) { PxBounds3 bounds; @@ -162,85 +208,146 @@ namespace Nv PxVec3 chunk2Centroid(0, 0, 0); /////////////////////////////////////////////////////////////////////////////////// - if (chunk1Points.size() < 4 || chunk2Points.size() < 4) + if (hull1p.size() < 4 || hull2p.size() < 4) { return 0.0; } - for (uint32_t i = 0; i < chunk1Points.size(); ++i) + for (uint32_t i = 0; i < hull1p.size(); ++i) { - chunk1Centroid += chunk1Points[i]; - bounds.include(chunk1Points[i]); - aBounds.include(chunk1Points[i]); + chunk1Centroid += hull1p[i]; + bounds.include(hull1p[i]); + aBounds.include(hull1p[i]); } - for (uint32_t i = 0; i < chunk2Points.size(); ++i) + for (uint32_t i = 0; i < hull2p.size(); ++i) { - chunk2Centroid += chunk2Points[i]; - bounds.include(chunk2Points[i]); - bBounds.include(chunk2Points[i]); + chunk2Centroid += hull2p[i]; + bounds.include(hull2p[i]); + bBounds.include(hull2p[i]); } - chunk1Centroid *= (1.0f / chunk1Points.size()); - chunk2Centroid *= (1.0f / chunk2Points.size()); + chunk1Centroid *= (1.0f / hull1p.size()); + chunk2Centroid *= (1.0f / hull2p.size()); + + Separation separation; if (!importerHullsInProximityApexFree(hull1p.size(), hull1p.data(), aBounds, PxTransform(PxIdentity), PxVec3(1, 1, 1), hull2p.size(), hull2p.data(), bBounds, PxTransform(PxIdentity), PxVec3(1, 1, 1), 2.0f * maxSeparation, &separation)) { return 0.0; } - - // Build first plane interface - PxPlane midplane = separation.plane; - if (!midplane.n.isFinite()) + + if (separation.getDistance() > 0) // If chunks don't intersect then use midplane to produce bond, otherwise midplane can be wrong { - return 0.0; - } - std::vector interfacePoints; + // Build first plane interface + PxPlane midplane = separation.plane; + if (!midplane.n.isFinite()) + { + return 0.0; + } - float firstCentroidSide = (midplane.distance(chunk1Centroid) > 0) ? 1 : -1; - float secondCentroidSide = (midplane.distance(chunk2Centroid) > 0) ? 1 : -1; + std::vector interfacePoints; - for (uint32_t i = 0; i < chunk1Points.size(); ++i) - { - float dst = midplane.distance(chunk1Points[i]); - if (dst * firstCentroidSide < maxSeparation) + float firstCentroidSide = (midplane.distance(chunk1Centroid) > 0) ? 1 : -1; + float secondCentroidSide = (midplane.distance(chunk2Centroid) > 0) ? 1 : -1; + + for (uint32_t i = 0; i < hull1p.size(); ++i) { - interfacePoints.push_back(chunk1Points[i]); + float dst = midplane.distance(hull1p[i]); + if (dst * firstCentroidSide < maxSeparation) + { + interfacePoints.push_back(hull1p[i]); + } } - } - for (uint32_t i = 0; i < chunk2Points.size(); ++i) - { - float dst = midplane.distance(chunk2Points[i]); - if (dst * secondCentroidSide < maxSeparation) + for (uint32_t i = 0; i < hull2p.size(); ++i) { - interfacePoints.push_back(chunk2Points[i]); + float dst = midplane.distance(hull2p[i]); + if (dst * secondCentroidSide < maxSeparation) + { + interfacePoints.push_back(hull2p[i]); + } } + std::vector convexHull; + trProcessor->buildConvexHull(interfacePoints, convexHull, midplane.n); + float area = 0; + PxVec3 centroidLocal(0, 0, 0); + if (convexHull.size() < 3) + { + return 0.0; + } + for (uint32_t i = 0; i < convexHull.size() - 1; ++i) + { + centroidLocal += convexHull[i]; + area += (convexHull[i] - convexHull[0]).cross((convexHull[i + 1] - convexHull[0])).magnitude(); + } + centroidLocal += convexHull.back(); + centroidLocal *= (1.0f / convexHull.size()); + float direction = midplane.n.dot(chunk2Centroid - chunk1Centroid); + if (direction < 0) + { + normal = -1.0f * normal; + } + normal = midplane.n; + centroid = centroidLocal; + return area * 0.5f; } - std::vector convexHull; - trProcessor->buildConvexHull(interfacePoints, convexHull, midplane.n); - float area = 0; - PxVec3 centroidLocal(0, 0, 0); - if (convexHull.size() < 3) - { - return 0.0; - } - for (uint32_t i = 0; i < convexHull.size() - 1; ++i) - { - centroidLocal += convexHull[i]; - area += (convexHull[i] - convexHull[0]).cross((convexHull[i + 1] - convexHull[0])).magnitude(); - } - centroidLocal += convexHull.back(); - centroidLocal *= (1.0f / convexHull.size()); - float direction = midplane.n.dot(chunk2Centroid - chunk1Centroid); - if (direction < 0) + else { - normal = -1.0f * normal; + float area = 0.0f; + + std::vector intersectionAnchors; + + + for (uint32_t i = 0; i < mavc; ++i) + { + for (uint32_t j = 0; j < mbvc; ++j) + { + AddTtAnchorPoints(mA + i, mB + j, intersectionAnchors); + } + } + + PxVec3 lcoid(0, 0, 0); + for (uint32_t i = 0; i < intersectionAnchors.size(); ++i) + { + lcoid += intersectionAnchors[i]; + } + lcoid *= (1.0f / intersectionAnchors.size()); + centroid = lcoid; + + if (intersectionAnchors.size() < 2) + { + return 0; + } + + + PxVec3 dir1 = intersectionAnchors[0] - lcoid; + PxVec3 dir2(0, 0, 0); + float maxMagn = 0.0f; + float maxDist = 0.0f; + + + for (uint32_t j = 0; j < intersectionAnchors.size(); ++j) + { + float d = (intersectionAnchors[j] - lcoid).magnitude(); + + PxVec3 tempNormal = (intersectionAnchors[j] - lcoid).cross(dir1); + maxDist = std::max(d, maxDist); + + if (tempNormal.magnitude() > maxMagn) + { + dir2 = tempNormal; + } + + } + + normal = dir2.getNormalized(); + + area = (maxDist * maxDist) * 3.14f; // Compute area like circle area; + + return area; } - normal = midplane.n; - centroid = centroidLocal; - return area * 0.5f; } @@ -271,14 +378,16 @@ namespace Nv int32_t BlastBondGeneratorImpl::createFullBondListAveraged(uint32_t meshCount, const uint32_t* geometryOffset, const Triangle* geometry, const CollisionHull** chunkHulls, - const bool* supportFlags, const uint32_t* meshGroups, NvBlastBondDesc*& resultBondDescs, BondGenerationConfig conf) + const bool* supportFlags, const uint32_t* meshGroups, NvBlastBondDesc*& resultBondDescs, BondGenerationConfig conf, std::set >* pairNotToTest) { std::vector > chunksPoints(meshCount); + std::vector bounds(meshCount); if (!chunkHulls) { for (uint32_t i = 0; i < meshCount; ++i) { + bounds[i].setEmpty(); if (!supportFlags[i]) { continue; @@ -289,6 +398,9 @@ namespace Nv chunksPoints[i].push_back(geometry[geometryOffset[i] + j].a.p); chunksPoints[i].push_back(geometry[geometryOffset[i] + j].b.p); chunksPoints[i].push_back(geometry[geometryOffset[i] + j].c.p); + bounds[i].include(geometry[geometryOffset[i] + j].a.p); + bounds[i].include(geometry[geometryOffset[i] + j].b.p); + bounds[i].include(geometry[geometryOffset[i] + j].c.p); } } } @@ -383,6 +495,15 @@ namespace Nv for (uint32_t tj = 0; tj < possibleBondGraph[i].size(); ++tj) { uint32_t j = possibleBondGraph[i][tj]; + + auto pr = (i < j) ? std::make_pair(i, j) : std::make_pair(j, i); + + if (pairNotToTest != nullptr && pairNotToTest->find(pr) != pairNotToTest->end()) + { + continue; // This chunks should not generate bonds. This is used for mixed generation with bondFrom + } + + const uint32_t jhullCount = hullPoints[j].size(); for (uint32_t ihull = 0; ihull < ihullCount; ++ihull) @@ -392,7 +513,9 @@ namespace Nv PxVec3 normal; PxVec3 centroid; - float area = processWithMidplanes(&trProcessor, chunksPoints[i].empty() ? hullPoints[i][ihull] : chunksPoints[i], chunksPoints[j].empty() ? hullPoints[j][jhull] : chunksPoints[j], hullPoints[i][ihull], hullPoints[j][jhull], normal, centroid, conf.maxSeparation); + float area = processWithMidplanes(&trProcessor, geometry + geometryOffset[i], geometryOffset[i + 1] - geometryOffset[i], + geometry + geometryOffset[j], geometryOffset[j + 1] - geometryOffset[j], hullPoints[i][ihull], hullPoints[j][jhull], normal, centroid, conf.maxSeparation); + if (area > 0) { NvBlastBondDesc bDesc; @@ -403,6 +526,12 @@ namespace Nv bDesc.bond.centroid[1] = centroid.y; bDesc.bond.centroid[2] = centroid.z; + uint32_t maxIndex = std::max(i, j); + if ((bounds[maxIndex].getCenter() - centroid).dot(normal) < 0) + { + normal = -normal; + } + bDesc.bond.normal[0] = normal.x; bDesc.bond.normal[1] = normal.y; bDesc.bond.normal[2] = normal.z; @@ -797,22 +926,26 @@ namespace Nv return 0; } - + int32_t BlastBondGeneratorImpl::buildDescFromInternalFracture(FractureTool* tool, const bool* chunkIsSupport, NvBlastBondDesc*& resultBondDescs, NvBlastChunkDesc*& resultChunkDescriptors) { uint32_t chunkCount = tool->getChunkCount(); std::vector trianglesCount(chunkCount); - std::vector trianglesBuffer(chunkCount); + std::vector> trianglesBuffer; - for (uint32_t i = 0; i < trianglesBuffer.size(); ++i) + for (uint32_t i = 0; i < chunkCount; ++i) { - trianglesCount[i] = tool->getBaseMesh(i, trianglesBuffer[i]); + Triangle* t; + trianglesCount[i] = tool->getBaseMesh(i, t); + trianglesBuffer.push_back(std::shared_ptr(t, [](Triangle* t) { + delete[] t; + })); } if (chunkCount == 0) { - return 0; + return 0; } resultChunkDescriptors = SAFE_ARRAY_NEW(NvBlastChunkDesc, trianglesBuffer.size()); std::vector bondDescriptors; @@ -824,9 +957,9 @@ namespace Nv PxVec3 chunkCentroid(0, 0, 0); for (uint32_t tr = 0; tr < trianglesCount[0]; ++tr) { - chunkCentroid += trianglesBuffer[0][tr].a.p; - chunkCentroid += trianglesBuffer[0][tr].b.p; - chunkCentroid += trianglesBuffer[0][tr].c.p; + chunkCentroid += trianglesBuffer[0].get()[tr].a.p; + chunkCentroid += trianglesBuffer[0].get()[tr].b.p; + chunkCentroid += trianglesBuffer[0].get()[tr].c.p; } chunkCentroid *= (1.0f / (3 * trianglesCount[0])); resultChunkDescriptors[0].centroid[0] = chunkCentroid[0]; @@ -834,22 +967,28 @@ namespace Nv resultChunkDescriptors[0].centroid[2] = chunkCentroid[2]; } + + bool hasCreatedByIslands = false; + for (uint32_t i = 1; i < chunkCount; ++i) { NvBlastChunkDesc& desc = resultChunkDescriptors[i]; desc.userData = i; desc.parentChunkIndex = tool->getChunkIndex(tool->getChunkInfo(i).parent); desc.flags = NvBlastChunkDesc::NoFlags; + hasCreatedByIslands |= (tool->getChunkInfo(i).flags & ChunkInfo::CREATED_BY_ISLAND_DETECTOR); if (chunkIsSupport[i]) + { desc.flags = NvBlastChunkDesc::SupportFlag; + } PxVec3 chunkCentroid(0, 0, 0); for (uint32_t tr = 0; tr < trianglesCount[i]; ++tr) { - chunkCentroid += trianglesBuffer[i][tr].a.p; - chunkCentroid += trianglesBuffer[i][tr].b.p; - chunkCentroid += trianglesBuffer[i][tr].c.p; + auto& trRef = trianglesBuffer[i].get()[tr]; + chunkCentroid += trRef.a.p; + chunkCentroid += trRef.b.p; + chunkCentroid += trRef.c.p; - Triangle& trRef = trianglesBuffer[i][tr]; int32_t id = trRef.userData; if (id == 0) continue; @@ -865,111 +1004,165 @@ namespace Nv desc.centroid[2] = chunkCentroid[2]; } std::sort(bondDescriptors.begin(), bondDescriptors.end()); - if (bondDescriptors.empty()) - { - return 0; - } - int32_t chunkId, planeId; - chunkId = bondDescriptors[0].m_chunkId; - planeId = bondDescriptors[0].m_planeIndex; - std::vector forwardChunks; - std::vector backwardChunks; - - float area = 0; - PxVec3 normal(0, 0, 0); - PxVec3 centroid(0, 0, 0); - int32_t collected = 0; - PxBounds3 bb = PxBounds3::empty(); - - chunkId = -1; - planeId = bondDescriptors[0].m_planeIndex; + + std::vector mResultBondDescs; - for (uint32_t i = 0; i <= bondDescriptors.size(); ++i) + + if (!bondDescriptors.empty()) { - if (i == bondDescriptors.size() || (chunkId != bondDescriptors[i].m_chunkId || abs(planeId) != abs(bondDescriptors[i].m_planeIndex))) + + int32_t chunkId, planeId; + chunkId = bondDescriptors[0].m_chunkId; + planeId = bondDescriptors[0].m_planeIndex; + std::vector forwardChunks; + std::vector backwardChunks; + + float area = 0; + PxVec3 normal(0, 0, 0); + PxVec3 centroid(0, 0, 0); + int32_t collected = 0; + PxBounds3 bb = PxBounds3::empty(); + + chunkId = -1; + planeId = bondDescriptors[0].m_planeIndex; + for (uint32_t i = 0; i <= bondDescriptors.size(); ++i) { - if (chunkId != -1) + if (i == bondDescriptors.size() || (chunkId != bondDescriptors[i].m_chunkId || abs(planeId) != abs(bondDescriptors[i].m_planeIndex))) { - if (bondDescriptors[i - 1].m_planeIndex > 0) { - forwardChunks.push_back(BondInfo()); - forwardChunks.back().area = area; - forwardChunks.back().normal = normal; - forwardChunks.back().centroid = centroid * (1.0f / 3.0f / collected); - forwardChunks.back().m_chunkId = chunkId; - forwardChunks.back().m_bb = bb; - - } - else + if (chunkId != -1) { - backwardChunks.push_back(BondInfo()); - backwardChunks.back().area = area; - backwardChunks.back().normal = normal; - backwardChunks.back().centroid = centroid * (1.0f / 3.0f / collected); - backwardChunks.back().m_chunkId = chunkId; - backwardChunks.back().m_bb = bb; + if (bondDescriptors[i - 1].m_planeIndex > 0) { + forwardChunks.push_back(BondInfo()); + forwardChunks.back().area = area; + forwardChunks.back().normal = normal; + forwardChunks.back().centroid = centroid * (1.0f / 3.0f / collected); + forwardChunks.back().m_chunkId = chunkId; + forwardChunks.back().m_bb = bb; + + } + else + { + backwardChunks.push_back(BondInfo()); + backwardChunks.back().area = area; + backwardChunks.back().normal = normal; + backwardChunks.back().centroid = centroid * (1.0f / 3.0f / collected); + backwardChunks.back().m_chunkId = chunkId; + backwardChunks.back().m_bb = bb; + } } + bb.setEmpty(); + collected = 0; + area = 0; + normal = PxVec3(0, 0, 0); + centroid = PxVec3(0, 0, 0); + if (i != bondDescriptors.size()) + chunkId = bondDescriptors[i].m_chunkId; } - bb.setEmpty(); - collected = 0; - area = 0; - normal = PxVec3(0, 0, 0); - centroid = PxVec3(0, 0, 0); - if (i != bondDescriptors.size()) - chunkId = bondDescriptors[i].m_chunkId; - } - if (i == bondDescriptors.size() || abs(planeId) != abs(bondDescriptors[i].m_planeIndex)) - { - for (uint32_t fchunk = 0; fchunk < forwardChunks.size(); ++fchunk) + if (i == bondDescriptors.size() || abs(planeId) != abs(bondDescriptors[i].m_planeIndex)) { - for (uint32_t bchunk = 0; bchunk < backwardChunks.size(); ++bchunk) + for (uint32_t fchunk = 0; fchunk < forwardChunks.size(); ++fchunk) { - if (weakBoundingBoxIntersection(forwardChunks[fchunk].m_bb, backwardChunks[bchunk].m_bb) == 0) + if (chunkIsSupport[forwardChunks[fchunk].m_chunkId] == false) { continue; } - if (chunkIsSupport[forwardChunks[fchunk].m_chunkId] == false || chunkIsSupport[backwardChunks[bchunk].m_chunkId] == false) + for (uint32_t bchunk = 0; bchunk < backwardChunks.size(); ++bchunk) { - continue; + if (weakBoundingBoxIntersection(forwardChunks[fchunk].m_bb, backwardChunks[bchunk].m_bb) == 0) + { + continue; + } + if (chunkIsSupport[backwardChunks[bchunk].m_chunkId] == false) + { + continue; + } + mResultBondDescs.push_back(NvBlastBondDesc()); + mResultBondDescs.back().bond.area = std::min(forwardChunks[fchunk].area, backwardChunks[bchunk].area); + mResultBondDescs.back().bond.normal[0] = forwardChunks[fchunk].normal.x; + mResultBondDescs.back().bond.normal[1] = forwardChunks[fchunk].normal.y; + mResultBondDescs.back().bond.normal[2] = forwardChunks[fchunk].normal.z; + + mResultBondDescs.back().bond.centroid[0] = (forwardChunks[fchunk].centroid.x + backwardChunks[bchunk].centroid.x) * 0.5; + mResultBondDescs.back().bond.centroid[1] = (forwardChunks[fchunk].centroid.y + backwardChunks[bchunk].centroid.y) * 0.5; + mResultBondDescs.back().bond.centroid[2] = (forwardChunks[fchunk].centroid.z + backwardChunks[bchunk].centroid.z) * 0.5; + + + mResultBondDescs.back().chunkIndices[0] = forwardChunks[fchunk].m_chunkId; + mResultBondDescs.back().chunkIndices[1] = backwardChunks[bchunk].m_chunkId; } - mResultBondDescs.push_back(NvBlastBondDesc()); - mResultBondDescs.back().bond.area = std::min(forwardChunks[fchunk].area, backwardChunks[bchunk].area); - mResultBondDescs.back().bond.normal[0] = forwardChunks[fchunk].normal.x; - mResultBondDescs.back().bond.normal[1] = forwardChunks[fchunk].normal.y; - mResultBondDescs.back().bond.normal[2] = forwardChunks[fchunk].normal.z; + } + forwardChunks.clear(); + backwardChunks.clear(); + if (i != bondDescriptors.size()) + { + planeId = bondDescriptors[i].m_planeIndex; + } + else + { + break; + } + } - mResultBondDescs.back().bond.centroid[0] = (forwardChunks[fchunk].centroid.x + backwardChunks[bchunk].centroid.x ) * 0.5; - mResultBondDescs.back().bond.centroid[1] = (forwardChunks[fchunk].centroid.y + backwardChunks[bchunk].centroid.y) * 0.5; - mResultBondDescs.back().bond.centroid[2] = (forwardChunks[fchunk].centroid.z + backwardChunks[bchunk].centroid.z) * 0.5; + collected++; + auto& trRef = trianglesBuffer[chunkId].get()[bondDescriptors[i].triangleIndex]; + PxVec3 n = trRef.getNormal(); + area += n.magnitude(); + normal = n.getNormalized(); + centroid += trRef.a.p; + centroid += trRef.b.p; + centroid += trRef.c.p; + + bb.include(trRef.a.p); + bb.include(trRef.b.p); + bb.include(trRef.c.p); + } + } + if (hasCreatedByIslands) + { + std::vector chunkTriangles; + std::vector chunkTrianglesOffsets; + + std::set > pairsAlreadyCreated; - mResultBondDescs.back().chunkIndices[0] = forwardChunks[fchunk].m_chunkId; - mResultBondDescs.back().chunkIndices[1] = backwardChunks[bchunk].m_chunkId; - } - } - forwardChunks.clear(); - backwardChunks.clear(); - if (i != bondDescriptors.size()) - { - planeId = bondDescriptors[i].m_planeIndex; - } - else + for (uint32_t i = 0; i < mResultBondDescs.size(); ++i) + { + auto pr = (mResultBondDescs[i].chunkIndices[0] < mResultBondDescs[i].chunkIndices[1]) ? + std::make_pair(mResultBondDescs[i].chunkIndices[0], mResultBondDescs[i].chunkIndices[1]) : + std::make_pair(mResultBondDescs[i].chunkIndices[1], mResultBondDescs[i].chunkIndices[0]); + + pairsAlreadyCreated.insert(pr); + } + + + chunkTrianglesOffsets.push_back(0); + for (uint32_t i = 0; i < chunkCount; ++i) + { + const float SCALE_FACTOR = 1.001f; + PxVec3 centroid(resultChunkDescriptors[i].centroid[0], resultChunkDescriptors[i].centroid[1], resultChunkDescriptors[i].centroid[2]); + for (uint32_t k = 0; k < trianglesCount[i]; ++k) { - break; + chunkTriangles.push_back(trianglesBuffer[i].get()[k]); + + chunkTriangles.back().a.p = (chunkTriangles.back().a.p - centroid) * SCALE_FACTOR + centroid; // inflate mesh a bit to find } + chunkTrianglesOffsets.push_back(chunkTriangles.size()); } - collected++; - int32_t tr = bondDescriptors[i].triangleIndex; - PxVec3 n = trianglesBuffer[chunkId][tr].getNormal(); - area += n.magnitude(); - normal = n.getNormalized(); - centroid += trianglesBuffer[chunkId][tr].a.p; - centroid += trianglesBuffer[chunkId][tr].b.p; - centroid += trianglesBuffer[chunkId][tr].c.p; - - bb.include(trianglesBuffer[chunkId][tr].a.p); - bb.include(trianglesBuffer[chunkId][tr].b.p); - bb.include(trianglesBuffer[chunkId][tr].c.p); + NvBlastBondDesc* adsc; + + + BondGenerationConfig cfg; + cfg.bondMode = BondGenerationConfig::AVERAGE; + cfg.maxSeparation = 0.0f; + + uint32_t nbListSize = createFullBondListAveraged(chunkCount, chunkTrianglesOffsets.data(), chunkTriangles.data(), nullptr, chunkIsSupport, nullptr, adsc, cfg, &pairsAlreadyCreated); + + for (uint32_t i = 0; i < nbListSize; ++i) + { + mResultBondDescs.push_back(adsc[i]); + } + NVBLAST_FREE(adsc); } resultBondDescs = SAFE_ARRAY_NEW(NvBlastBondDesc, mResultBondDescs.size()); diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringBondGeneratorImpl.h b/sdk/extensions/authoring/source/NvBlastExtAuthoringBondGeneratorImpl.h index 17222ee..bef3668 100755 --- a/sdk/extensions/authoring/source/NvBlastExtAuthoringBondGeneratorImpl.h +++ b/sdk/extensions/authoring/source/NvBlastExtAuthoringBondGeneratorImpl.h @@ -35,6 +35,7 @@ #include #include #include +#include namespace Nv { @@ -47,10 +48,10 @@ namespace Blast class BlastBondGeneratorImpl : public BlastBondGenerator { -public: +public: BlastBondGeneratorImpl(physx::PxCooking* cooking, physx::PxPhysicsInsertionCallback* insertionCallback) - : mPxCooking(cooking), mPxInsertionCallback(insertionCallback){}; + : mPxCooking(cooking), mPxInsertionCallback(insertionCallback) {}; virtual void release() override; @@ -58,7 +59,7 @@ public: NvBlastBondDesc*& resultBondDescs, NvBlastChunkDesc*& resultChunkDescriptors) override; virtual int32_t createBondBetweenMeshes(uint32_t meshACount, const Triangle* meshA, uint32_t meshBCount, const Triangle* meshB, - NvBlastBond& resultBond, BondGenerationConfig conf = BondGenerationConfig()) override; + NvBlastBond& resultBond, BondGenerationConfig conf) override; virtual int32_t createBondBetweenMeshes(uint32_t meshCount, const uint32_t* geometryOffset, const Triangle* geometry, uint32_t overlapsCount, const uint32_t* overlapsA, const uint32_t* overlapsB, @@ -66,19 +67,19 @@ public: virtual int32_t bondsFromPrefractured(uint32_t meshCount, const uint32_t* geometryOffset, const Triangle* geometry, const bool* chunkIsSupport, NvBlastBondDesc*& resultBondDescs, - BondGenerationConfig conf = BondGenerationConfig()) override; + BondGenerationConfig conf) override; virtual int32_t bondsFromPrefractured(uint32_t meshCount, const uint32_t* convexHullOffset, const CollisionHull** chunkHulls, const bool* chunkIsSupport, const uint32_t* meshGroups, NvBlastBondDesc*& resultBondDescs, float maxSeparation) override; + + private: - float processWithMidplanes( TriangleProcessor* trProcessor, - const std::vector& chunk1Points, const std::vector& chunk2Points, - const std::vector& hull1p, const std::vector& hull2p, - physx::PxVec3& normal, physx::PxVec3& centroid, float maxSeparation); + float processWithMidplanes(TriangleProcessor* trProcessor, const Triangle* mA, uint32_t mavc, const Triangle* mB, uint32_t mbvc, + const std::vector& hull1p, const std::vector& hull2p, physx::PxVec3& normal, physx::PxVec3& centroid, float maxSeparation); int32_t createFullBondListAveraged( uint32_t meshCount, const uint32_t* geometryOffset, const Triangle* geometry, const CollisionHull** chunkHulls, - const bool* supportFlags, const uint32_t* meshGroups, NvBlastBondDesc*& resultBondDescs, BondGenerationConfig conf); + const bool* supportFlags, const uint32_t* meshGroups, NvBlastBondDesc*& resultBondDescs, BondGenerationConfig conf, std::set >* pairNotToTest = nullptr); int32_t createFullBondListExact( uint32_t meshCount, const uint32_t* geometryOffset, const Triangle* geometry, const bool* supportFlags, NvBlastBondDesc*& resultBondDescs, BondGenerationConfig conf); int32_t createFullBondListExactInternal(uint32_t meshCount, const uint32_t* geometryOffset, const Triangle* geometry, @@ -99,6 +100,8 @@ private: std::vector mCHullCache; std::vector > mHullsPointsCache; std::vector mBoundsCache; + + }; } // namespace Blast diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringBooleanTool.cpp b/sdk/extensions/authoring/source/NvBlastExtAuthoringBooleanTool.cpp index 681e0b6..5d85c36 100755 --- a/sdk/extensions/authoring/source/NvBlastExtAuthoringBooleanTool.cpp +++ b/sdk/extensions/authoring/source/NvBlastExtAuthoringBooleanTool.cpp @@ -40,6 +40,7 @@ using physx::PxVec2; using physx::PxBounds3; + namespace Nv { namespace Blast @@ -383,7 +384,7 @@ int32_t edgesIntersection(const Vertex& eAs, const Vertex& eAe, const Vertex& eB bool bShadowing = false; /** - Search for two pairs where parts of A shadows B, and where B shadows are. + Search for two pairs where parts of A shadows B, and where B shadows A. Needed for search intersection point. */ @@ -785,7 +786,6 @@ void BooleanEvaluator::buildFaceFaceIntersections(BooleanConf mode) { statusValue = edgeFacetIntersection12(meshAPoints[fae->s], meshAPoints[fae->e], mMeshB->getVertices(), facetBEdges, facetBEdgeCount, newPointA, newPointB); } - inclusionValue = -inclusionValueEdgeFace(mode, statusValue); if (inclusionValue > 0) { @@ -817,6 +817,8 @@ void BooleanEvaluator::buildFaceFaceIntersections(BooleanConf mode) { statusValue = edgeFacetIntersection21(meshBPoints[(fbe)->s], meshBPoints[(fbe)->e], mMeshA->getVertices(), facetAEdges, facetAEdgeCount, newPointA, newPointB); } + + inclusionValue = inclusionValueEdgeFace(mode, statusValue); if (inclusionValue > 0) { @@ -843,14 +845,8 @@ void BooleanEvaluator::buildFaceFaceIntersections(BooleanConf mode) NVBLAST_LOG_ERROR("Not equal number of starting and ending vertices! Probably input mesh has open edges."); return; } - if (retainedStarts.size() > 1) - { - comp.basePoint = compositeEndPoint - compositeStartPoint; - std::sort(retainedStarts.begin(), retainedStarts.end(), comp); - std::sort(retainedEnds.begin(), retainedEnds.end(), comp); - } for (uint32_t rv = 0; rv < retainedStarts.size(); ++rv) - { + { newEdge.s = addIfNotExist(retainedStarts[rv].first); newEdge.e = addIfNotExist(retainedEnds[rv].first); newEdge.parent = facetA; @@ -997,6 +993,7 @@ void BooleanEvaluator::collectRetainedPartsFromA(BooleanConf mode) { statusValue = 0; } + inclusionValue = -inclusionValue03(mode, statusValue); if (inclusionValue > 0) @@ -1135,6 +1132,7 @@ void BooleanEvaluator::collectRetainedPartsFromB(BooleanConf mode) { statusValue = 0; } + inclusionValue = -inclusionValue30(mode, statusValue); if (inclusionValue > 0) @@ -1232,7 +1230,7 @@ void BooleanEvaluator::collectRetainedPartsFromB(BooleanConf mode) } EdgeWithParent newEdge; for (uint32_t rv = 0; rv < retainedStartVertices.size(); ++rv) - { + { newEdge.s = addIfNotExist(retainedStartVertices[rv]); newEdge.e = addIfNotExist(retainedEndVertices[rv]); newEdge.parent = facetId + mMeshA->getFacetCount(); @@ -1322,8 +1320,8 @@ Mesh* BooleanEvaluator::createNewMesh() std::sort(mEdgeAggregate.begin(), mEdgeAggregate.end(), EdgeWithParentSortComp); std::vector newFacets; std::vector newEdges(mEdgeAggregate.size()); - int32_t lastPos = 0; - int32_t lastParent = mEdgeAggregate[0].parent; + uint32_t lastPos = 0; + uint32_t lastParent = mEdgeAggregate[0].parent; uint32_t collected = 0; int64_t userData = 0; int32_t materialId = 0; @@ -1333,7 +1331,7 @@ Mesh* BooleanEvaluator::createNewMesh() { if (mEdgeAggregate[i].parent != lastParent) { - if (lastParent < (int32_t)mMeshA->getFacetCount()) + if (lastParent < mMeshA->getFacetCount()) { userData = mMeshA->getFacet(lastParent)->userData; materialId = mMeshA->getFacet(lastParent)->materialId; @@ -1355,8 +1353,7 @@ Mesh* BooleanEvaluator::createNewMesh() newEdges[i].s = mEdgeAggregate[i].s; newEdges[i].e = mEdgeAggregate[i].e; } - int32_t pr = lastParent - mMeshA->getFacetCount(); - if (lastParent < (int32_t)mMeshA->getFacetCount()) + if (lastParent < mMeshA->getFacetCount()) { userData = mMeshA->getFacet(lastParent)->userData; materialId = mMeshA->getFacet(lastParent)->materialId; @@ -1364,6 +1361,7 @@ Mesh* BooleanEvaluator::createNewMesh() } else { + uint32_t pr = lastParent - mMeshA->getFacetCount(); userData = mMeshB->getFacet(pr)->userData; materialId = mMeshB->getFacet(pr)->materialId; smoothingGroup = mMeshB->getFacet(pr)->smoothingGroup; diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringBooleanTool.h b/sdk/extensions/authoring/source/NvBlastExtAuthoringBooleanTool.h index 820bec6..48875fa 100755 --- a/sdk/extensions/authoring/source/NvBlastExtAuthoringBooleanTool.h +++ b/sdk/extensions/authoring/source/NvBlastExtAuthoringBooleanTool.h @@ -32,7 +32,6 @@ #include "NvBlastExtAuthoringTypes.h" #include "NvBlastExtAuthoringInternalCommon.h" #include -#include #include "NvBlastTypes.h" diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringCollisionBuilderImpl.cpp b/sdk/extensions/authoring/source/NvBlastExtAuthoringCollisionBuilderImpl.cpp index 7735fbc..60435d0 100755 --- a/sdk/extensions/authoring/source/NvBlastExtAuthoringCollisionBuilderImpl.cpp +++ b/sdk/extensions/authoring/source/NvBlastExtAuthoringCollisionBuilderImpl.cpp @@ -37,7 +37,7 @@ #include #include - +#include #include using namespace physx; @@ -328,6 +328,21 @@ PxConvexMesh* ConvexMeshBuilderImpl::buildConvexMesh(const CollisionHull& hull) return convexMesh; } + +PxConvexMesh* ConvexMeshBuilderImpl::buildConvexMeshRT(const Nv::Blast::Vertex* vrs, uint32_t count) +{ + PxConvexMeshDesc convexMeshDescr; + + convexMeshDescr.points.data = vrs; + convexMeshDescr.points.count = (uint32_t)count; + convexMeshDescr.points.stride = sizeof(Nv::Blast::Vertex); + + convexMeshDescr.flags = PxConvexFlag::eCOMPUTE_CONVEX | PxConvexFlag::eGPU_COMPATIBLE; + + PxConvexMesh* convexMesh = mCooking->createConvexMesh(convexMeshDescr, *mInsertionCallback); + return convexMesh; +} + void ConvexMeshBuilderImpl::release() { delete this; diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringCollisionBuilderImpl.h b/sdk/extensions/authoring/source/NvBlastExtAuthoringCollisionBuilderImpl.h index d012e7e..afdbcde 100755 --- a/sdk/extensions/authoring/source/NvBlastExtAuthoringCollisionBuilderImpl.h +++ b/sdk/extensions/authoring/source/NvBlastExtAuthoringCollisionBuilderImpl.h @@ -71,6 +71,8 @@ public: virtual physx::PxConvexMesh* buildConvexMesh(uint32_t verticesCount, const physx::PxVec3* vertexData) override; virtual physx::PxConvexMesh* buildConvexMesh(const CollisionHull& hull) override; + + virtual physx::PxConvexMesh* buildConvexMeshRT(const Vertex* vrs, uint32_t count) override; virtual void trimCollisionGeometry(uint32_t chunksCount, CollisionHull** in, const uint32_t* chunkDepth) override; diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringFractureToolImpl.cpp b/sdk/extensions/authoring/source/NvBlastExtAuthoringFractureToolImpl.cpp index 18ebd34..d5575cb 100755 --- a/sdk/extensions/authoring/source/NvBlastExtAuthoringFractureToolImpl.cpp +++ b/sdk/extensions/authoring/source/NvBlastExtAuthoringFractureToolImpl.cpp @@ -27,6 +27,7 @@ #include "NvBlastExtAuthoringFractureToolImpl.h" #include "NvBlastExtAuthoringMeshImpl.h" +#include "NvBlastExtAuthoringMeshUtils.h" // This warning arises when using some stl containers with older versions of VC // c:\program files (x86)\microsoft visual studio 12.0\vc\include\xtree(1826): warning C4702: unreachable code @@ -133,9 +134,9 @@ void findCellBasePlanes(const std::vector& sites, std::vector& sites, std::vector < std::vector >& neighboors, int32_t interiorMaterialId) +Mesh* getCellMesh(BooleanEvaluator& eval, int32_t planeIndexerOffset, int32_t cellId, const std::vector& sites, std::vector < std::vector >& neighboors, int32_t interiorMaterialId, physx::PxVec3 origin) { - Mesh* cell = getBigBox(sites[cellId], SITE_BOX_SIZE, interiorMaterialId); + Mesh* cell = getBigBox(origin, SITE_BOX_SIZE, interiorMaterialId); Mesh* cuttingMesh = getCuttingBox(PxVec3(0, 0, 0), PxVec3(1, 1, 1), CUTTING_BOX_SIZE, 0, interiorMaterialId); for (uint32_t i = 0; i < neighboors[cellId].size(); ++i) @@ -154,6 +155,7 @@ Mesh* getCellMesh(BooleanEvaluator& eval, int32_t planeIndexerOffset, int32_t ce if (cell == nullptr) break; } + delete cuttingMesh; return cell; } @@ -441,7 +443,7 @@ int32_t FractureToolImpl::voronoiFracturing(uint32_t chunkId, uint32_t cellCount std::vector newlyCreatedChunksIds; for (uint32_t i = 0; i < cellPoints.size(); ++i) { - Mesh* cell = getCellMesh(eval, mPlaneIndexerOffset, i, cellPoints, neighboors, mInteriorMaterialId); + Mesh* cell = getCellMesh(eval, mPlaneIndexerOffset, i, cellPoints, neighboors, mInteriorMaterialId, cellPoints[i]); if (cell == nullptr) { @@ -452,13 +454,10 @@ int32_t FractureToolImpl::voronoiFracturing(uint32_t chunkId, uint32_t cellCount Mesh* resultMesh = voronoiMeshEval.createNewMesh(); if (resultMesh) { - mChunkData.push_back(ChunkInfo()); - mChunkData.back().isChanged = true; - mChunkData.back().isLeaf = true; - mChunkData.back().meshData = resultMesh; - mChunkData.back().parent = parentChunk; - mChunkData.back().chunkId = mChunkIdCounter++; - newlyCreatedChunksIds.push_back(mChunkData.back().chunkId); + uint32_t ncidx = createNewChunk(parentChunk); + mChunkData[ncidx].isLeaf = true; + mChunkData[ncidx].meshData = resultMesh; + newlyCreatedChunksIds.push_back(mChunkData[ncidx].chunkId); } eval.reset(); delete cell; @@ -612,7 +611,7 @@ int32_t FractureToolImpl::voronoiFracturing(uint32_t chunkId, uint32_t cellCount for (uint32_t i = 0; i < cellPoints.size(); ++i) { - Mesh* cell = getCellMesh(eval, mPlaneIndexerOffset, i, cellPoints, neighboors, mInteriorMaterialId); + Mesh* cell = getCellMesh(eval, mPlaneIndexerOffset, i, cellPoints, neighboors, mInteriorMaterialId, cellPoints[i]); if (cell == nullptr) { @@ -632,13 +631,10 @@ int32_t FractureToolImpl::voronoiFracturing(uint32_t chunkId, uint32_t cellCount Mesh* resultMesh = voronoiMeshEval.createNewMesh(); if (resultMesh) { - mChunkData.push_back(ChunkInfo()); - mChunkData.back().isLeaf = true; - mChunkData.back().isChanged = true; - mChunkData.back().meshData = resultMesh; - mChunkData.back().parent = parentChunk; - mChunkData.back().chunkId = mChunkIdCounter++; - newlyCreatedChunksIds.push_back(mChunkData.back().chunkId); + uint32_t ncidx = createNewChunk(parentChunk); + mChunkData[ncidx].isLeaf = true; + mChunkData[ncidx].meshData = resultMesh; + newlyCreatedChunksIds.push_back(mChunkData[ncidx].chunkId); } eval.reset(); delete cell; @@ -711,6 +707,7 @@ int32_t FractureToolImpl::slicing(uint32_t chunkId, const SlicingConfiguration& ChunkInfo ch; ch.isLeaf = true; ch.isChanged = true; + ch.flags = ChunkInfo::NO_FLAGS; ch.parent = replaceChunk ? mChunkData[chunkIndex].parent : chunkId; std::vector xSlicedChunks; std::vector ySlicedChunks; @@ -898,6 +895,7 @@ int32_t FractureToolImpl::slicingNoisy(uint32_t chunkId, const SlicingConfigurat ChunkInfo ch; ch.isLeaf = true; ch.isChanged = true; + ch.flags = ChunkInfo::NO_FLAGS; ch.parent = replaceChunk ? mChunkData[chunkIndex].parent : chunkId; std::vector xSlicedChunks; std::vector ySlicedChunks; @@ -1071,6 +1069,7 @@ int32_t FractureToolImpl::cut(uint32_t chunkId, const physx::PxVec3& normal, con ch.chunkId = -1; ch.isLeaf = true; ch.isChanged = true; + ch.flags = ChunkInfo::NO_FLAGS; ch.parent = replaceChunk ? mChunkData[chunkIndex].parent : chunkId; float noisyPartSize = 1.2f; @@ -1194,6 +1193,7 @@ int32_t FractureToolImpl::cutout(uint32_t chunkId, CutoutConfiguration conf, boo ChunkInfo ch; ch.isLeaf = true; ch.isChanged = true; + ch.flags = ChunkInfo::NO_FLAGS; ch.parent = replaceChunk ? mChunkData[chunkIndex].parent : chunkId; std::vector newlyCreatedChunksIds; @@ -1489,6 +1489,7 @@ int32_t FractureToolImpl::setChunkMesh(const Mesh* meshInput, int32_t parentId) chunk.parent = parentId; chunk.isLeaf = true; chunk.isChanged = true; + chunk.flags = ChunkInfo::NO_FLAGS; if ((size_t)parentId < mChunkData.size()) { mChunkData[parentId].isLeaf = false; @@ -1802,9 +1803,9 @@ void FractureToolImpl::setRemoveIslands(bool isRemoveIslands) mRemoveIslands = isRemoveIslands; } -int32_t FractureToolImpl::islandDetectionAndRemoving(int32_t chunkId) +int32_t FractureToolImpl::islandDetectionAndRemoving(int32_t chunkId, bool createAtNewDepth) { - if (chunkId == 0) + if (chunkId == 0 && createAtNewDepth == false) { return 0; } @@ -1935,17 +1936,32 @@ int32_t FractureToolImpl::islandDetectionAndRemoving(int32_t chunkId) } } - delete mChunkData[chunkIndex].meshData; - mChunkData[chunkIndex].meshData = new MeshImpl(compVertices[0].data(), compEdges[0].data(), compFacets[0].data(), static_cast(compVertices[0].size()), - static_cast(compEdges[0].size()), static_cast(compFacets[0].size()));; - for (int32_t i = 1; i < cComp; ++i) + if (createAtNewDepth == false || chunkId != 0) { - mChunkData.push_back(ChunkInfo(mChunkData[chunkIndex])); - mChunkData.back().chunkId = mChunkIdCounter++; - mChunkData.back().meshData = new MeshImpl(compVertices[i].data(), compEdges[i].data(), compFacets[i].data(), static_cast(compVertices[i].size()), - static_cast(compEdges[i].size()), static_cast(compFacets[i].size())); + delete mChunkData[chunkIndex].meshData; + mChunkData[chunkIndex].meshData = new MeshImpl(compVertices[0].data(), compEdges[0].data(), compFacets[0].data(), static_cast(compVertices[0].size()), + static_cast(compEdges[0].size()), static_cast(compFacets[0].size()));; + for (int32_t i = 1; i < cComp; ++i) + { + mChunkData.push_back(ChunkInfo(mChunkData[chunkIndex])); + mChunkData.back().chunkId = mChunkIdCounter++; + mChunkData.back().meshData = new MeshImpl(compVertices[i].data(), compEdges[i].data(), compFacets[i].data(), static_cast(compVertices[i].size()), + static_cast(compEdges[i].size()), static_cast(compFacets[i].size())); + } } - + else + { + mChunkData[chunkIndex].isLeaf = false; + deleteAllChildrenOfChunk(chunkId); + for (int32_t i = 0; i < cComp; ++i) + { + uint32_t nc = createNewChunk(chunkId); + mChunkData[nc].isLeaf = true; + mChunkData[nc].flags = ChunkInfo::CREATED_BY_ISLAND_DETECTOR; + mChunkData[nc].meshData = new MeshImpl(compVertices[i].data(), compEdges[i].data(), compFacets[i].data(), static_cast(compVertices[i].size()), + static_cast(compEdges[i].size()), static_cast(compFacets[i].size())); + } + } return cComp; } return 0; @@ -2083,6 +2099,8 @@ uint32_t FractureToolImpl::createNewChunk(uint32_t parent) mChunkData.back().meshData = nullptr; mChunkData.back().isLeaf = false; mChunkData.back().isChanged = true; + mChunkData.back().flags = ChunkInfo::NO_FLAGS; + return mChunkData.size() - 1; } diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringFractureToolImpl.h b/sdk/extensions/authoring/source/NvBlastExtAuthoringFractureToolImpl.h index 6f7504d..fa6aed3 100755 --- a/sdk/extensions/authoring/source/NvBlastExtAuthoringFractureToolImpl.h +++ b/sdk/extensions/authoring/source/NvBlastExtAuthoringFractureToolImpl.h @@ -365,7 +365,7 @@ public: \param[in] chunkId Chunk ID which should be checked for islands \return Number of found islands is returned */ - int32_t islandDetectionAndRemoving(int32_t chunkId) override; + int32_t islandDetectionAndRemoving(int32_t chunkId, bool createAtNewDepth = false) override; /** Check if input mesh contains open edges. Open edges can lead to wrong fracturing results. @@ -427,6 +427,9 @@ protected: int32_t mInteriorMaterialId; }; +void findCellBasePlanes(const std::vector& sites, std::vector >& neighboors); +Mesh* getCellMesh(class BooleanEvaluator& eval, int32_t planeIndexerOffset, int32_t cellId, const std::vector& sites, std::vector < std::vector >& neighboors, int32_t interiorMaterialId, physx::PxVec3 origin); + } // namespace Blast } // namespace Nv diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringInternalCommon.h b/sdk/extensions/authoring/source/NvBlastExtAuthoringInternalCommon.h deleted file mode 100755 index d337d43..0000000 --- a/sdk/extensions/authoring/source/NvBlastExtAuthoringInternalCommon.h +++ /dev/null @@ -1,260 +0,0 @@ -// 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 - -using namespace physx; - -namespace Nv -{ -namespace Blast -{ - -/** -Edge representation with index of parent facet -*/ -struct EdgeWithParent -{ - int32_t s, e; // Starting and ending vertices - int32_t parent; // Parent facet index - EdgeWithParent() : s(0), e(0), parent(0) {} - EdgeWithParent(int32_t s, int32_t e, int32_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 VEC_COMPARISON_OFFSET 1e-5f -/** -Vertex comparator for vertex welding. -*/ -struct VrtComp -{ - bool operator()(const Vertex& a, const Vertex& b) const - { - if (a.p.x + VEC_COMPARISON_OFFSET < b.p.x) return true; - if (a.p.x - VEC_COMPARISON_OFFSET > b.p.x) return false; - if (a.p.y + VEC_COMPARISON_OFFSET < b.p.y) return true; - if (a.p.y - VEC_COMPARISON_OFFSET > b.p.y) return false; - if (a.p.z + VEC_COMPARISON_OFFSET < b.p.z) return true; - if (a.p.z - VEC_COMPARISON_OFFSET > b.p.z) return false; - - if (a.n.x + 1e-3 < b.n.x) return true; - if (a.n.x - 1e-3 > b.n.x) return false; - if (a.n.y + 1e-3 < b.n.y) return true; - if (a.n.y - 1e-3 > b.n.y) return false; - if (a.n.z + 1e-3 < b.n.z) return true; - if (a.n.z - 1e-3 > b.n.z) return false; - - - if (a.uv[0].x + 1e-3 < b.uv[0].x) return true; - if (a.uv[0].x - 1e-3 > b.uv[0].x) return false; - if (a.uv[0].y + 1e-3 < 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 + VEC_COMPARISON_OFFSET < b.x) return true; - if (a.x - VEC_COMPARISON_OFFSET > b.x) return false; - if (a.y + VEC_COMPARISON_OFFSET < b.y) return true; - if (a.y - VEC_COMPARISON_OFFSET > b.y) return false; - if (a.z + VEC_COMPARISON_OFFSET < b.z) return true; - if (a.z - VEC_COMPARISON_OFFSET > b.z) return false; - return false; - }; -}; - -} // namespace Blast -} // namespace Nv - -#endif \ No newline at end of file diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringMeshCleanerImpl.cpp b/sdk/extensions/authoring/source/NvBlastExtAuthoringMeshCleanerImpl.cpp index 167ffd4..ba2bd89 100755 --- a/sdk/extensions/authoring/source/NvBlastExtAuthoringMeshCleanerImpl.cpp +++ b/sdk/extensions/authoring/source/NvBlastExtAuthoringMeshCleanerImpl.cpp @@ -1,3 +1,29 @@ +// 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 #include diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringMeshCleanerImpl.h b/sdk/extensions/authoring/source/NvBlastExtAuthoringMeshCleanerImpl.h index dbf37cf..aec863e 100755 --- a/sdk/extensions/authoring/source/NvBlastExtAuthoringMeshCleanerImpl.h +++ b/sdk/extensions/authoring/source/NvBlastExtAuthoringMeshCleanerImpl.h @@ -1,3 +1,33 @@ +// 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 NVBLASTEXTAUTHORINGMESHCLEANERIMPL_H +#define NVBLASTEXTAUTHORINGMESHCLEANERIMPL_H + #include "NvBlastExtAuthoringMeshCleaner.h" namespace Nv @@ -22,4 +52,6 @@ public: }; } -} \ No newline at end of file +} + +#endif //NVBLASTEXTAUTHORINGMESHCLEANERIMPL_H \ No newline at end of file diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringMeshImpl.cpp b/sdk/extensions/authoring/source/NvBlastExtAuthoringMeshImpl.cpp deleted file mode 100755 index 5f5c57c..0000000 --- a/sdk/extensions/authoring/source/NvBlastExtAuthoringMeshImpl.cpp +++ /dev/null @@ -1,1139 +0,0 @@ -// 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 "NvBlastExtAuthoringPerlinNoise.h" -#include -#include "PxMath.h" -#include -#include -#include -#include - -using physx::PxVec2; -using physx::PxVec3; -using physx::PxBounds3; - -#define UV_SCALE 1.f - -#define CYLINDER_UV_SCALE (UV_SCALE * 1.732) - -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); - mBounds.setEmpty(); - for (uint32_t i = 0; i < verticesCount; ++i) - { - mBounds.include(mVertices[i].p); - } - 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++; - } -} - -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); - mBounds.setEmpty(); - for (uint32_t i = 0; i < posCount; ++i) - { - mBounds.include(mVertices[i].p); - } -} - -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(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(mEdges.size()); -} -uint32_t MeshImpl::getVerticesCount() const -{ - return static_cast(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); - } -} - - - -void getTangents(const PxVec3& normal, PxVec3& t1, PxVec3& t2) -{ - - if (std::abs(normal.z) < 0.9) - { - t1 = normal.cross(PxVec3(0, 0, 1)); - } - else - { - t1 = normal.cross(PxVec3(1, 0, 0)); - } - t2 = t1.cross(normal); -} - -Mesh* getCuttingBox(const PxVec3& point, const PxVec3& normal, float size, int64_t id, int32_t interiorMaterialId) -{ - PxVec3 lNormal = normal.getNormalized(); - PxVec3 t1, t2; - getTangents(lNormal, t1, t2); - - std::vector positions(8); - positions[0].p = point + (t1 + t2) * size; - positions[1].p = point + (t2 - t1) * size; - - positions[2].p = point + (-t1 - t2) * size; - positions[3].p = point + (t1 - t2) * size; - - - positions[4].p = point + (t1 + t2 + lNormal) * size; - positions[5].p = point + (t2 - t1 + lNormal) * size; - - positions[6].p = point + (-t1 - t2 + lNormal) * size; - positions[7].p = point + (t1 - t2 + lNormal) * size; - - positions[0].n = -lNormal; - positions[1].n = -lNormal; - - positions[2].n = -lNormal; - positions[3].n = -lNormal; - - - positions[4].n = -lNormal; - positions[5].n = -lNormal; - - positions[6].n = -lNormal; - positions[7].n = -lNormal; - - positions[0].uv[0] = PxVec2(0, 0); - positions[1].uv[0] = PxVec2(UV_SCALE, 0); - - positions[2].uv[0] = PxVec2(UV_SCALE, UV_SCALE); - positions[3].uv[0] = PxVec2(0, UV_SCALE); - - - positions[4].uv[0] = PxVec2(0, 0); - positions[5].uv[0] = PxVec2(UV_SCALE, 0); - - positions[6].uv[0] = PxVec2(UV_SCALE, UV_SCALE); - positions[7].uv[0] = PxVec2(0, UV_SCALE); - - - std::vector edges; - std::vector facets; - - edges.push_back(Edge(0, 1)); - edges.push_back(Edge(1, 2)); - edges.push_back(Edge(2, 3)); - edges.push_back(Edge(3, 0)); - facets.push_back(Facet(0, 4, interiorMaterialId, id, -1)); - - - edges.push_back(Edge(0, 3)); - edges.push_back(Edge(3, 7)); - edges.push_back(Edge(7, 4)); - edges.push_back(Edge(4, 0)); - facets.push_back(Facet(4, 4, interiorMaterialId, id, -1)); - - edges.push_back(Edge(3, 2)); - edges.push_back(Edge(2, 6)); - edges.push_back(Edge(6, 7)); - edges.push_back(Edge(7, 3)); - facets.push_back(Facet(8, 4, interiorMaterialId, id, -1)); - - edges.push_back(Edge(5, 6)); - edges.push_back(Edge(6, 2)); - edges.push_back(Edge(2, 1)); - edges.push_back(Edge(1, 5)); - facets.push_back(Facet(12, 4, interiorMaterialId, id, -1)); - - edges.push_back(Edge(4, 5)); - edges.push_back(Edge(5, 1)); - edges.push_back(Edge(1, 0)); - edges.push_back(Edge(0, 4)); - facets.push_back(Facet(16, 4, interiorMaterialId, id, -1)); - - edges.push_back(Edge(4, 7)); - edges.push_back(Edge(7, 6)); - edges.push_back(Edge(6, 5)); - edges.push_back(Edge(5, 4)); - facets.push_back(Facet(20, 4, interiorMaterialId, id, -1)); - return new MeshImpl(positions.data(), edges.data(), facets.data(), static_cast(positions.size()), static_cast(edges.size()), static_cast(facets.size())); -} - -void inverseNormalAndIndices(Mesh* mesh) -{ - for (uint32_t i = 0; i < mesh->getVerticesCount(); ++i) - { - mesh->getVerticesWritable()[i].n *= -1.0f; - } - for (uint32_t i = 0; i < mesh->getFacetCount(); ++i) - { - mesh->getFacetWritable(i)->userData = -mesh->getFacet(i)->userData; - } -} - -void MeshImpl::setMaterialId(const int32_t* materialId) -{ - if (materialId != nullptr) - { - for (uint32_t i = 0; i < mFacets.size(); ++i) - { - mFacets[i].materialId = *materialId; - ++materialId; - } - } -} - - -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; - } - } -} - - -void setCuttingBox(const PxVec3& point, const PxVec3& normal, Mesh* mesh, float size, int64_t id) -{ - PxVec3 t1, t2; - PxVec3 lNormal = normal.getNormalized(); - getTangents(lNormal, t1, t2); - - Vertex* positions = mesh->getVerticesWritable(); - positions[0].p = point + (t1 + t2) * size; - positions[1].p = point + (t2 - t1) * size; - - positions[2].p = point + (-t1 - t2) * size; - positions[3].p = point + (t1 - t2) * size; - - - positions[4].p = point + (t1 + t2 + lNormal) * size; - positions[5].p = point + (t2 - t1 + lNormal) * size; - - positions[6].p = point + (-t1 - t2 + lNormal) * size; - positions[7].p = point + (t1 - t2 + lNormal) * size; - - positions[0].n = -lNormal; - positions[1].n = -lNormal; - - positions[2].n = -lNormal; - positions[3].n = -lNormal; - - - positions[4].n = -lNormal; - positions[5].n = -lNormal; - - positions[6].n = -lNormal; - positions[7].n = -lNormal; - - for (uint32_t i = 0; i < mesh->getFacetCount(); ++i) - { - mesh->getFacetWritable(i)->userData = id; - } - mesh->recalculateBoundingBox(); -} - -bool MeshImpl::isValid() const -{ - return mVertices.size() > 0 && mEdges.size() > 0 && mFacets.size() > 0; -} - -struct Stepper -{ - virtual physx::PxVec3 getStep1(uint32_t w, uint32_t h) const = 0; - virtual physx::PxVec3 getStep2(uint32_t w) const = 0; - virtual physx::PxVec3 getStart() const = 0; - virtual physx::PxVec3 getNormal(uint32_t w, uint32_t h) const = 0; - virtual bool isStep2ClosedLoop() const - { - return false; - } - virtual bool isStep2FreeBoundary() const - { - return false; - } -}; - -struct PlaneStepper : public Stepper -{ - PlaneStepper(const physx::PxVec3& normal, const physx::PxVec3& point, float sizeX, float sizeY, uint32_t resolutionX, uint32_t resolutionY, bool swapTangents = false) - { - PxVec3 t1, t2; - lNormal = normal.getNormalized(); - getTangents(lNormal, t1, t2); - if (swapTangents) - { - std::swap(t1, t2); - } - t11d = -t1 * 2.0f * sizeX / resolutionX; - t12d = -t2 * 2.0f * sizeY / resolutionY; - t21d = t11d; - t22d = t12d; - cPos = point + (t1 * sizeX + t2 * sizeY); - resY = resolutionY; - } - //Define face by 4 corner points, points should lay in plane - PlaneStepper(const physx::PxVec3& p11, const physx::PxVec3& p12, const physx::PxVec3& p21, const physx::PxVec3& p22, - uint32_t resolutionX, uint32_t resolutionY) - { - lNormal = -(p21 - p11).cross(p12 - p11).getNormalized(); - if (lNormal.magnitude() < 1e-5) - { - lNormal = (p21 - p22).cross(p12 - p22).getNormalized(); - } - t11d = (p11 - p21) / resolutionX; - t12d = (p12 - p11) / resolutionY; - t21d = (p12 - p22) / resolutionX; - t22d = (p22 - p21) / resolutionY; - cPos = p21; - resY = resolutionY; - } - physx::PxVec3 getStep1(uint32_t y, uint32_t) const - { - return (t11d * (resY - y) + t21d * y) / resY; - } - physx::PxVec3 getStep2(uint32_t) const - { - return t22d; - } - physx::PxVec3 getStart() const - { - return cPos; - } - physx::PxVec3 getNormal(uint32_t, uint32_t) const - { - return lNormal; - } - - PxVec3 t11d, t12d, t21d, t22d, cPos, lNormal; - uint32_t resY; -}; - -void fillEdgesAndFaces(std::vector& edges, std::vector& facets, - uint32_t h, uint32_t w, uint32_t firstVertex, uint32_t verticesCount, int64_t id, int32_t interiorMaterialId, int32_t smoothingGroup = -1, bool reflected = false) -{ - for (uint32_t i = 0; i < w; ++i) - { - for (uint32_t j = 0; j < h; ++j) - { - uint32_t start = edges.size(); - uint32_t idx00 = i * (h + 1) + j + firstVertex; - uint32_t idx01 = idx00 + 1; - uint32_t idx10 = (idx00 + h + 1) % verticesCount; - uint32_t idx11 = (idx01 + h + 1) % verticesCount; - if (reflected) - { - edges.push_back(Edge(idx01, idx11)); - edges.push_back(Edge(idx11, idx10)); - edges.push_back(Edge(idx10, idx01)); - facets.push_back(Facet(start, 3, interiorMaterialId, id, smoothingGroup)); - - start = edges.size(); - edges.push_back(Edge(idx01, idx10)); - edges.push_back(Edge(idx10, idx00)); - edges.push_back(Edge(idx00, idx01)); - facets.push_back(Facet(start, 3, interiorMaterialId, id, smoothingGroup)); - } - else - { - edges.push_back(Edge(idx00, idx01)); - edges.push_back(Edge(idx01, idx11)); - edges.push_back(Edge(idx11, idx00)); - facets.push_back(Facet(start, 3, interiorMaterialId, id, smoothingGroup)); - - start = edges.size(); - edges.push_back(Edge(idx00, idx11)); - edges.push_back(Edge(idx11, idx10)); - edges.push_back(Edge(idx10, idx00)); - facets.push_back(Facet(start, 3, interiorMaterialId, id, smoothingGroup)); - } - } - } -} - -void getNoisyFace(std::vector& vertices, std::vector& edges, std::vector& facets, - uint32_t h, uint32_t w, const physx::PxVec2& uvOffset, const physx::PxVec2& uvScale, - const Stepper& stepper, SimplexNoise& nEval, int64_t id, int32_t interiorMaterialId, bool randomizeLast = false) -{ - uint32_t randIdx = randomizeLast ? 1 : 0; - PxVec3 cPosit = stepper.getStart(); - uint32_t firstVertex = vertices.size(); - for (uint32_t i = 0; i < w + 1; ++i) - { - PxVec3 lcPosit = cPosit; - for (uint32_t j = 0; j < h + 1; ++j) - { - vertices.push_back(Vertex()); - vertices.back().p = lcPosit; - vertices.back().uv[0] = uvOffset + uvScale.multiply(physx::PxVec2(j, i)); - lcPosit += stepper.getStep1(i, j); - } - cPosit += stepper.getStep2(i); - } - - for (uint32_t i = 1 - randIdx; i < w + randIdx; ++i) - { - for (uint32_t j = 1; j < h; ++j) - { - //TODO limit max displacement for cylinder - PxVec3& pnt = vertices[i * (h + 1) + j + firstVertex].p; - pnt += stepper.getNormal(i, j) * nEval.sample(pnt); - } - } - - fillEdgesAndFaces(edges, facets, h, w, firstVertex, vertices.size(), id, interiorMaterialId); -} - -PX_INLINE uint32_t unsignedMod(int32_t n, uint32_t modulus) -{ - const int32_t d = n / (int32_t)modulus; - const int32_t m = n - d*(int32_t)modulus; - return m >= 0 ? (uint32_t)m : (uint32_t)m + modulus; -} - -void calculateNormals(std::vector& vertices, uint32_t h, uint32_t w, bool inverseNormals = false) -{ - for (uint32_t i = 1; i < w; ++i) - { - for (uint32_t j = 1; j < h; ++j) - { - int32_t idx = i * (h + 1) + j; - PxVec3 v1 = vertices[idx + h + 1].p - vertices[idx].p; - PxVec3 v2 = vertices[idx + 1].p - vertices[idx].p; - PxVec3 v3 = vertices[idx - (h + 1)].p - vertices[idx].p; - PxVec3 v4 = vertices[idx - 1].p - vertices[idx].p; - - vertices[idx].n = v1.cross(v2) + v2.cross(v3) + v3.cross(v4) + v4.cross(v1); - if (inverseNormals) - { - vertices[idx].n = -vertices[idx].n; - } - vertices[idx].n.normalize(); - } - } -} - -Mesh* getNoisyCuttingBoxPair(const physx::PxVec3& point, const physx::PxVec3& normal, float size, float jaggedPlaneSize, physx::PxVec3 resolution, int64_t id, float amplitude, float frequency, int32_t octaves, int32_t seed, int32_t interiorMaterialId) -{ - PxVec3 t1, t2; - PxVec3 lNormal = normal.getNormalized(); - getTangents(lNormal, t1, t2); - float sz = 2.f * jaggedPlaneSize; - uint32_t resolutionX = std::max(1u, (uint32_t)std::roundf(sz * std::abs(t1.x) * resolution.x + sz * std::abs(t1.y) * resolution.y + sz * std::abs(t1.z) * resolution.z)); - uint32_t resolutionY = std::max(1u, (uint32_t)std::roundf(sz * std::abs(t2.x) * resolution.x + sz * std::abs(t2.y) * resolution.y + sz * std::abs(t2.z) * resolution.z)); - - PlaneStepper stepper(normal, point, jaggedPlaneSize, jaggedPlaneSize, resolutionX, resolutionY); - SimplexNoise nEval(amplitude, frequency, octaves, seed); - - std::vector vertices; vertices.reserve((resolutionX + 1) * (resolutionY + 1) + 12); - std::vector edges; - std::vector facets; - getNoisyFace(vertices, edges, facets, resolutionX, resolutionY, physx::PxVec2(0.f), physx::PxVec2(UV_SCALE / resolutionX, UV_SCALE / resolutionY), - stepper, nEval, id, interiorMaterialId); - calculateNormals(vertices, resolutionX, resolutionY); - - uint32_t offset = (resolutionX + 1) * (resolutionY + 1); - vertices.resize(offset + 12); - - vertices[0 + offset].p = point + (t1 + t2) * size; - vertices[1 + offset].p = point + (t2 - t1) * size; - - vertices[2 + offset].p = point + (-t1 - t2) * size; - vertices[3 + offset].p = point + (t1 - t2) * size; - - vertices[8 + offset].p = point + (t1 + t2) * jaggedPlaneSize; - vertices[9 + offset].p = point + (t2 - t1) * jaggedPlaneSize; - - vertices[10 + offset].p = point + (-t1 - t2) * jaggedPlaneSize; - vertices[11 + offset].p = point + (t1 - t2) * jaggedPlaneSize; - - vertices[4 + offset].p = point + (t1 + t2 + lNormal) * size; - vertices[5 + offset].p = point + (t2 - t1 + lNormal) * size; - - vertices[6 + offset].p = point + (-t1 - t2 + lNormal) * size; - vertices[7 + offset].p = point + (t1 - t2 + lNormal) * size; - - int32_t edgeOffset = edges.size(); - edges.push_back(Edge(0 + offset, 1 + offset)); - edges.push_back(Edge(1 + offset, 2 + offset)); - edges.push_back(Edge(2 + offset, 3 + offset)); - edges.push_back(Edge(3 + offset, 0 + offset)); - - edges.push_back(Edge(11 + offset, 10 + offset)); - edges.push_back(Edge(10 + offset, 9 + offset)); - edges.push_back(Edge(9 + offset, 8 + offset)); - edges.push_back(Edge(8 + offset, 11 + offset)); - - facets.push_back(Facet(edgeOffset, 8, interiorMaterialId, id, -1)); - - edges.push_back(Edge(0 + offset, 3 + offset)); - edges.push_back(Edge(3 + offset, 7 + offset)); - edges.push_back(Edge(7 + offset, 4 + offset)); - edges.push_back(Edge(4 + offset, 0 + offset)); - facets.push_back(Facet(8 + edgeOffset, 4, interiorMaterialId, id, -1)); - - edges.push_back(Edge(3 + offset, 2 + offset)); - edges.push_back(Edge(2 + offset, 6 + offset)); - edges.push_back(Edge(6 + offset, 7 + offset)); - edges.push_back(Edge(7 + offset, 3 + offset)); - facets.push_back(Facet(12 + edgeOffset, 4, interiorMaterialId, id, -1)); - - edges.push_back(Edge(5 + offset, 6 + offset)); - edges.push_back(Edge(6 + offset, 2 + offset)); - edges.push_back(Edge(2 + offset, 1 + offset)); - edges.push_back(Edge(1 + offset, 5 + offset)); - facets.push_back(Facet(16 + edgeOffset, 4, interiorMaterialId, id, -1)); - - edges.push_back(Edge(4 + offset, 5 + offset)); - edges.push_back(Edge(5 + offset, 1 + offset)); - edges.push_back(Edge(1 + offset, 0 + offset)); - edges.push_back(Edge(0 + offset, 4 + offset)); - facets.push_back(Facet(20 + edgeOffset, 4, interiorMaterialId, id, -1)); - - edges.push_back(Edge(4 + offset, 7 + offset)); - edges.push_back(Edge(7 + offset, 6 + offset)); - edges.push_back(Edge(6 + offset, 5 + offset)); - edges.push_back(Edge(5 + offset, 4 + offset)); - facets.push_back(Facet(24 + edgeOffset, 4, interiorMaterialId, id, -1)); - - // - return new MeshImpl(vertices.data(), edges.data(), facets.data(), vertices.size(), edges.size(), facets.size()); -} - -Mesh* getBigBox(const PxVec3& point, float size, int32_t interiorMaterialId) -{ - PxVec3 normal(0, 0, 1); - normal.normalize(); - PxVec3 t1, t2; - getTangents(normal, t1, t2); - - std::vector positions(8); - positions[0].p = point + (t1 + t2 - normal) * size; - positions[1].p = point + (t2 - t1 - normal) * size; - - positions[2].p = point + (-t1 - t2 - normal) * size; - positions[3].p = point + (t1 - t2 - normal) * size; - - - positions[4].p = point + (t1 + t2 + normal) * size; - positions[5].p = point + (t2 - t1 + normal) * size; - - positions[6].p = point + (-t1 - t2 + normal) * size; - positions[7].p = point + (t1 - t2 + normal) * size; - - positions[0].uv[0] = PxVec2(0, 0); - positions[1].uv[0] = PxVec2(UV_SCALE, 0); - - positions[2].uv[0] = PxVec2(UV_SCALE, UV_SCALE); - positions[3].uv[0] = PxVec2(0, UV_SCALE); - - - positions[4].uv[0] = PxVec2(0, 0); - positions[5].uv[0] = PxVec2(UV_SCALE, 0); - - positions[6].uv[0] = PxVec2(UV_SCALE, UV_SCALE); - positions[7].uv[0] = PxVec2(0, UV_SCALE); - - - std::vector edges; - std::vector facets; - - edges.push_back(Edge(0, 1)); - edges.push_back(Edge(1, 2)); - edges.push_back(Edge(2, 3)); - edges.push_back(Edge(3, 0)); - facets.push_back(Facet(0, 4, interiorMaterialId, 0, -1)); - - - edges.push_back(Edge(0, 3)); - edges.push_back(Edge(3, 7)); - edges.push_back(Edge(7, 4)); - edges.push_back(Edge(4, 0)); - facets.push_back(Facet(4, 4, interiorMaterialId, 0, -1)); - - edges.push_back(Edge(3, 2)); - edges.push_back(Edge(2, 6)); - edges.push_back(Edge(6, 7)); - edges.push_back(Edge(7, 3)); - facets.push_back(Facet(8, 4, interiorMaterialId, 0, -1)); - - edges.push_back(Edge(5, 6)); - edges.push_back(Edge(6, 2)); - edges.push_back(Edge(2, 1)); - edges.push_back(Edge(1, 5)); - facets.push_back(Facet(12, 4, interiorMaterialId, 0, -1)); - - edges.push_back(Edge(4, 5)); - edges.push_back(Edge(5, 1)); - edges.push_back(Edge(1, 0)); - edges.push_back(Edge(0, 4)); - facets.push_back(Facet(16, 4, interiorMaterialId, 0, -1)); - - edges.push_back(Edge(4, 7)); - edges.push_back(Edge(7, 6)); - edges.push_back(Edge(6, 5)); - edges.push_back(Edge(5, 4)); - facets.push_back(Facet(20, 4, interiorMaterialId, 0, -1)); - for (int i = 0; i < 8; ++i) - positions[i].n = PxVec3(0, 0, 0); - return new MeshImpl(positions.data(), edges.data(), facets.data(), static_cast(positions.size()), static_cast(edges.size()), static_cast(facets.size())); -} - -bool CmpSharedFace::operator()(const std::pair& pv1, const std::pair& pv2) const -{ - CmpVec vc; - if ((pv1.first -pv2.first).magnitude() < 1e-5) - { - return vc(pv1.second, pv2.second); - } - return vc(pv1.first, pv2.first); -} - -#define INDEXER_OFFSET (1ll << 32) - -void buildCuttingConeFaces(const CutoutConfiguration& conf, const std::vector>& cutoutPoints, - float heightBot, float heightTop, float conicityBot, float conicityTop, - int64_t& id, int32_t seed, int32_t interiorMaterialId, SharedFacesMap& sharedFacesMap) -{ - std::map>, CmpVec> newCutoutPoints; - uint32_t resH = (conf.noise.amplitude <= FLT_EPSILON) ? 1 : std::max((uint32_t)std::roundf((heightBot + heightTop) / conf.noise.samplingInterval.z) , 1u); - - //generate noisy faces - SimplexNoise nEval(conf.noise.amplitude, conf.noise.frequency, conf.noise.octaveNumber, seed); - - for (uint32_t i = 0; i < cutoutPoints.size(); i++) - { - auto& points = cutoutPoints[i]; - uint32_t pointCount = points.size(); - float finalP = 0, currentP = 0; - for (uint32_t j = 0; j < pointCount; j++) - { - finalP += (points[(j + 1) % pointCount] - points[j]).magnitude(); - } - - for (uint32_t p = 0; p < pointCount; p++) - { - auto p0 = points[p]; - auto p1 = points[(p + 1) % pointCount]; - - auto cp0 = newCutoutPoints.find(p0); - if (cp0 == newCutoutPoints.end()) - { - newCutoutPoints[p0] = std::make_pair(0u, std::vector(resH + 1, physx::PxVec3(0.f))); - cp0 = newCutoutPoints.find(p0); - } - auto cp1 = newCutoutPoints.find(p1); - if (cp1 == newCutoutPoints.end()) - { - newCutoutPoints[p1] = std::make_pair(0u, std::vector(resH + 1, physx::PxVec3(0.f))); - cp1 = newCutoutPoints.find(p1); - } - - - auto vec = p1 - p0; - auto cPos = (p0 + p1) * 0.5f; - uint32_t numPts = (conf.noise.amplitude <= FLT_EPSILON) ? 1 : (uint32_t)(std::abs(vec.x) / conf.noise.samplingInterval.x + std::abs(vec.y) / conf.noise.samplingInterval.y) + 1; - - auto normal = vec.cross(physx::PxVec3(0, 0, 1)); - normal = normal; - - auto p00 = p0 * conicityBot; p00.z = -heightBot; - auto p01 = p1 * conicityBot; p01.z = -heightBot; - auto p10 = p0 * conicityTop; p10.z = heightTop; - auto p11 = p1 * conicityTop; p11.z = heightTop; - PlaneStepper stepper(p00, p01, p10, p11, resH, numPts); - - PlaneStepper stepper1(normal, cPos, heightTop, vec.magnitude() * 0.5f, resH, numPts, true); - stepper1.getNormal(0, 0); - - auto t = std::make_pair(p0, p1); - auto sfIt = sharedFacesMap.find(t); - if (sfIt == sharedFacesMap.end() && sharedFacesMap.find(std::make_pair(p1, p0)) == sharedFacesMap.end()) - { - sharedFacesMap[t] = SharedFace(numPts, resH, -(id + INDEXER_OFFSET), interiorMaterialId); - sfIt = sharedFacesMap.find(t); - auto& SF = sfIt->second; - getNoisyFace(SF.vertices, SF.edges, SF.facets, resH, numPts, - physx::PxVec2(0, CYLINDER_UV_SCALE * currentP / (heightBot + heightTop)), - physx::PxVec2(CYLINDER_UV_SCALE / resH, CYLINDER_UV_SCALE * vec.magnitude() / (heightBot + heightTop) / numPts), - stepper, nEval, id++ + INDEXER_OFFSET, interiorMaterialId, true); - - currentP += vec.magnitude(); - cp0->second.first++; - cp1->second.first++; - for (uint32_t k = 0; k <= resH; k++) - { - cp0->second.second[k] += SF.vertices[k].p; - cp1->second.second[k] += SF.vertices[SF.vertices.size() - resH - 1 + k].p; - } - } - } - } - - //limit faces displacement iteratively - for (uint32_t i = 0; i < cutoutPoints.size(); i++) - { - auto& points = cutoutPoints[i]; - uint32_t pointCount = points.size(); - for (uint32_t p = 0; p < pointCount; p++) - { - auto p0 = points[p]; - auto p1 = points[(p + 1) % pointCount]; - auto p2 = points[(p + 2) % pointCount]; - auto& cp1 = newCutoutPoints.find(p1)->second; - float d = physx::PxClamp((p1 - p0).getNormalized().dot((p2 - p1).getNormalized()), 0.f, 1.f); - - for (uint32_t h = 0; h <= resH; h++) - { - float z = cp1.second[h].z; - float conicity = (conicityBot * h + conicityTop * (resH - h)) / resH; - cp1.second[h] = cp1.second[h] * d + p1 * cp1.first * conicity * (1.f - d); - cp1.second[h].z = z; - } - } - } - - //relax nearby points for too big faces displacement limitations - for (uint32_t i = 0; i < cutoutPoints.size(); i++) - { - auto& points = cutoutPoints[i]; - uint32_t pointCount = points.size(); - for (uint32_t p = 0; p < pointCount; p++) - { - auto p0 = points[p]; - auto p1 = points[(p + 1) % pointCount]; - auto& cp0 = newCutoutPoints.find(p0)->second; - auto& cp1 = newCutoutPoints.find(p1)->second; - - auto SFIt = sharedFacesMap.find(std::make_pair(p0, p1)); - - uint32_t idx0 = 0, idx1; - if (SFIt == sharedFacesMap.end()) - { - SFIt = sharedFacesMap.find(std::make_pair(p1, p0)); - idx1 = 0; - idx0 = SFIt->second.w * (SFIt->second.h + 1); - } - else - { - idx1 = SFIt->second.w * (SFIt->second.h + 1); - } - - for (uint32_t h = 0; h <= resH; h++) - { - float z = cp1.second[h].z; - float R0 = (cp0.second[h] / cp0.first - SFIt->second.vertices[idx0 + h].p).magnitude(); - float R1 = (cp1.second[h] / cp1.first - SFIt->second.vertices[idx1 + h].p).magnitude(); - float R = R0 - R1; - float r = 0.25f * (cp1.second[h] / cp1.first - cp0.second[h] / cp0.first).magnitude(); - float conicity = (conicityBot * h + conicityTop * (resH - h)) / resH; - if (R > r) - { - float w = std::min(1.f, r / R); - cp1.second[h] = cp1.second[h] * w + p1 * cp1.first * conicity * (1.f - w); - cp1.second[h].z = z; - } - } - } - - for (int32_t p = pointCount - 1; p >= 0; p--) - { - auto p0 = points[p]; - auto p1 = points[unsignedMod(p - 1, pointCount)]; - auto& cp0 = newCutoutPoints.find(p0)->second; - auto& cp1 = newCutoutPoints.find(p1)->second; - - auto SFIt = sharedFacesMap.find(std::make_pair(p0, p1)); - uint32_t idx0 = 0, idx1; - if (SFIt == sharedFacesMap.end()) - { - SFIt = sharedFacesMap.find(std::make_pair(p1, p0)); - idx1 = 0; - idx0 = SFIt->second.w * (SFIt->second.h + 1); - } - else - { - idx1 = SFIt->second.w * (SFIt->second.h + 1); - } - - for (uint32_t h = 0; h <= resH; h++) - { - float z = cp1.second[h].z; - float R0 = (cp0.second[h] / cp0.first - SFIt->second.vertices[idx0 + h].p).magnitude(); - float R1 = (cp1.second[h] / cp1.first - SFIt->second.vertices[idx1 + h].p).magnitude(); - float R = R0 - R1; - float r = 0.25f * (cp1.second[h] / cp1.first - cp0.second[h] / cp0.first).magnitude(); - float conicity = (conicityBot * h + conicityTop * (resH - h)) / resH; - if (R > r) - { - float w = std::min(1.f, r / R); - cp1.second[h] = cp1.second[h] * w + p1 * cp1.first * conicity * (1.f - w); - cp1.second[h].z = z; - } - } - } - } - - //glue faces - for (auto& SF : sharedFacesMap) - { - auto& cp0 = newCutoutPoints.find(SF.first.first)->second; - auto& cp1 = newCutoutPoints.find(SF.first.second)->second; - auto& v = SF.second.vertices; - float invW = 1.f / SF.second.w; - - for (uint32_t w = 0; w <= SF.second.w; w++) - { - for (uint32_t h = 0; h <= SF.second.h; h++) - { - v[w * (SF.second.h + 1) + h].p += ((cp0.second[h] / cp0.first - v[h].p) * (SF.second.w - w) - + (cp1.second[h] / cp1.first - v[SF.second.w * (SF.second.h + 1) + h].p) * w) * invW; - } - } - } -} - -Mesh* getNoisyCuttingCone(const std::vector& points, const std::set& smoothingGroups, - const physx::PxTransform& transform, bool useSmoothing, float heightBot, float heightTop, float conicityMultiplierBot, float conicityMultiplierTop, - const physx::PxVec3* samplingInterval, uint32_t interiorMaterialId, const SharedFacesMap& sharedFacesMap, bool inverseNormals) -{ - uint32_t pointCount = points.size(); - uint32_t resP = pointCount; - uint32_t resH = 1; - if (samplingInterval != nullptr) - { - for (uint32_t i = 0; i < pointCount; i++) - { - auto vec = (points[(i + 1) % pointCount] - points[i]); - resP += (uint32_t)(std::abs(vec.x) / samplingInterval->x + std::abs(vec.y) / samplingInterval->y); - } - resH = std::max((uint32_t)std::roundf((heightBot + heightTop) / samplingInterval->z), 1u); - } - - std::vector positions; positions.reserve((resH + 1) * (resP + 1)); - std::vector edges; edges.reserve(resH * resP * 6 + (resP + 1) * 2); - std::vector facets; facets.reserve(resH * resP * 2 + 2); - - uint32_t pCount = 0; - int sg = useSmoothing ? 1 : -1; - for (uint32_t p = 0; p < pointCount; p++) - { - if (useSmoothing && smoothingGroups.find(p) != smoothingGroups.end()) - { - sg = sg ^ 3; - } - auto p0 = points[p]; - auto p1 = points[(p + 1) % pointCount]; - - uint32_t firstVertexIndex = positions.size(); - uint32_t firstEdgeIndex = edges.size(); - - auto sfIt = sharedFacesMap.find(std::make_pair(p0, p1)); - int32_t vBegin = 0, vEnd = -1, vIncr = 1; - if (sfIt == sharedFacesMap.end()) - { - sfIt = sharedFacesMap.find(std::make_pair(p1, p0));; - vBegin = sfIt->second.w; - vIncr = -1; - } - else - { - vEnd = sfIt->second.w + 1; - } - - auto& SF = sfIt->second; - positions.resize(firstVertexIndex + (SF.w + 1) * (SF.h + 1)); - if (vBegin < vEnd) - { - for (auto& e : SF.edges) - { - edges.push_back(Edge(e.s + firstVertexIndex, e.e + firstVertexIndex)); - } - for (auto& f : SF.facets) - { - facets.push_back(f); - facets.back().firstEdgeNumber += firstEdgeIndex; - facets.back().smoothingGroup = sg; - } - } - else - { - fillEdgesAndFaces(edges, facets, SF.h, SF.w, firstVertexIndex, positions.size(), SF.f.userData, SF.f.materialId, sg, true); - } - for (int32_t v = vBegin; v != vEnd; v += vIncr) - { - std::copy(SF.vertices.begin() + v * (resH + 1), SF.vertices.begin() + (v + 1) * (SF.h + 1), positions.begin() + firstVertexIndex); - firstVertexIndex += SF.h + 1; - } - pCount += SF.vertices.size() / (resH + 1) - 1; - } - - if (inverseNormals) - { - for (uint32_t e = 0; e < edges.size(); e += 3) - { - std::swap(edges[e + 0].s, edges[e + 0].e); - std::swap(edges[e + 1].s, edges[e + 1].e); - std::swap(edges[e + 2].s, edges[e + 2].e); - std::swap(edges[e + 0], edges[e + 2]); - } - } - - uint32_t totalCount = pCount + pointCount; - calculateNormals(positions, resH, totalCount - 1, inverseNormals); - - std::vector xPos, yPos; - int32_t ii = 0; - for (auto& p : positions) - { - if ((ii++) % (resH + 1) == 1) - { - xPos.push_back(p.p.x); - yPos.push_back(p.p.y); - } - p.p = transform.transform(p.p); - p.n = transform.rotate(p.n); - } - totalCount /= 2; - - for (uint32_t i = 0; i < totalCount; i++) - { - uint32_t idx = 2 * i * (resH + 1); - edges.push_back(Edge(idx, (idx + 2 * (resH + 1)) % positions.size())); - } - for (int32_t i = totalCount; i > 0; i--) - { - uint32_t idx = (2 * i + 1) * (resH + 1) - 1; - edges.push_back(Edge(idx % positions.size(), idx - 2 * (resH + 1))); - } - - if (smoothingGroups.find(0) != smoothingGroups.end() || smoothingGroups.find(pointCount - 1) != smoothingGroups.end()) - { - if (facets[0].smoothingGroup == facets[facets.size() - 1].smoothingGroup) - { - for (uint32_t i = 0; i < resH; i++) - { - facets[i].smoothingGroup = 4; - } - } - } - - facets.push_back(Facet(resH * pCount * 6, totalCount, interiorMaterialId, 0, -1)); - facets.push_back(Facet(resH * pCount * 6 + totalCount, totalCount, interiorMaterialId, 0, -1)); - return new MeshImpl(positions.data(), edges.data(), facets.data(), static_cast(positions.size()), static_cast(edges.size()), static_cast(facets.size())); -} - -Mesh* getCuttingCone(const CutoutConfiguration& conf, const std::vector& points, const std::set& smoothingGroups, - float heightBot, float heightTop, float conicityBot, float conicityTop, - int64_t& id, int32_t seed, int32_t interiorMaterialId, const SharedFacesMap& sharedFacesMap, bool inverseNormals) -{ - if (conf.noise.amplitude > FLT_EPSILON) - { - return getNoisyCuttingCone(points, smoothingGroups, conf.transform, conf.useSmoothing, heightBot, heightTop, conicityBot, conicityTop, - &conf.noise.samplingInterval, interiorMaterialId, sharedFacesMap, inverseNormals); - } - else - { - return getNoisyCuttingCone(points, smoothingGroups, conf.transform, conf.useSmoothing, heightBot, heightTop, conicityBot, conicityTop, - nullptr, interiorMaterialId, sharedFacesMap, inverseNormals); - } -} - -} // namespace Blast -} // namespace Nv diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringMeshImpl.h b/sdk/extensions/authoring/source/NvBlastExtAuthoringMeshImpl.h deleted file mode 100755 index c0c80a8..0000000 --- a/sdk/extensions/authoring/source/NvBlastExtAuthoringMeshImpl.h +++ /dev/null @@ -1,289 +0,0 @@ -// 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 "NvBlastExtAuthoringFractureTool.h" -#include -#include -#include - -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(); - - 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; - -private: - std::vector mVertices; - std::vector mEdges; - std::vector mFacets; - physx::PxBounds3 mBounds; -}; - - -/** - Helper functions -*/ - -/** - Set cutting box at some particular position. - \param[in] point Cutting face center - \param[in] normal Cutting face normal - \param[in] mesh Cutting box mesh - \param[in] size Cutting box size - \param[in] id Cutting box ID -*/ -void setCuttingBox(const physx::PxVec3& point, const physx::PxVec3& normal, Mesh* mesh, float size, int64_t id); -/** - Create cutting box at some particular position. - \param[in] point Cutting face center - \param[in] normal Cutting face normal - \param[in] size Cutting box size - \param[in] id Cutting box ID -*/ -Mesh* getCuttingBox(const physx::PxVec3& point, const physx::PxVec3& normal, float size, int64_t id, int32_t interiorMaterialId); - -/** - Create box at some particular position. - \param[in] point Cutting face center - \param[in] size Cutting box size -*/ -Mesh* getBigBox(const physx::PxVec3& point, float size, int32_t interiorMaterialId); - -/** - Create slicing box with noisy cutting surface. - \param[in] point Cutting face center - \param[in] normal Cutting face normal - \param[in] size Cutting box size - \param[in] jaggedPlaneSize Noisy surface size - \param[in] resolution Noisy surface resolution - \param[in] id Cutting box ID - \param[in] amplitude Noise amplitude - \param[in] frequency Noise frequency - \param[in] octaves Noise octaves - \param[in] seed Random generator seed, used for noise generation. -*/ -Mesh* getNoisyCuttingBoxPair(const physx::PxVec3& point, const physx::PxVec3& normal, float size, float jaggedPlaneSize, physx::PxVec3 resolution, int64_t id, float amplitude, float frequency, int32_t octaves, int32_t seed, int32_t interiorMaterialId); - - -/** - Inverses normals of cutting box and sets indices. - \param[in] mesh Cutting box mesh -*/ -void inverseNormalAndIndices(Mesh* mesh); - -struct CmpVec -{ - bool operator()(const physx::PxVec3& v1, const physx::PxVec3& v2) const; -}; - -typedef std::map, CmpVec> PointMap; - -struct SharedFace -{ - SharedFace() {} - SharedFace(uint32_t inW, uint32_t inH, int64_t inUD, int32_t inMatId) - : w(inW), h(inH), f(0, 3, inMatId, inUD) - { - vertices.reserve((w + 1) * (h + 1)); - } - uint32_t w, h; - Facet f; - std::vector vertices; - std::vector edges; - std::vector facets; -}; - -struct CmpSharedFace -{ - bool operator()(const std::pair& pv1, const std::pair& pv2) const; -}; - -typedef std::map, SharedFace, CmpSharedFace> SharedFacesMap; - -void buildCuttingConeFaces(const CutoutConfiguration& conf, const std::vector>& points, - float heightBot, float heightTop, float conicityBot, float conicityTop, - int64_t& id, int32_t seed, int32_t interiorMaterialId, SharedFacesMap& sharedFacesMap); - -/** - Create cutting cone at some particular position. - \param[in] conf Cutout configuration parameters and data - \param[in] meshId Cutout index - \param[in] points Array of points for loop - \param[in] smoothingGroups Array of point indices at which smoothing group should be toggled - \param[in] heightBot Cutting cone bottom height (below z = 0) - \param[in] heightTop Cutting cone top height (below z = 0) - \param[in] conicityBot Cutting cone bottom points multiplier - \param[in] conicityTop Cutting cone top points multiplier - \param[in] id Cutting cylinder ID - \param[in] seed Seed for RNG - \param[in] interiorMaterialId Interior material index - \param[in] sharedFacesMap Shared faces for noisy fracture -*/ -Mesh* getCuttingCone(const CutoutConfiguration& conf, - const std::vector& points, const std::set& smoothingGroups, - float heightBot, float heightTop, float conicityBot, float conicityTop, - int64_t& id, int32_t seed, int32_t interiorMaterialId, const SharedFacesMap& sharedFacesMap, bool inverseNormals = false); - -} // namespace Blast -} // namespace Nv - - -#endif // ifndef NVBLASTAUTHORINGMESHIMPL_H diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringMeshUtils.cpp b/sdk/extensions/authoring/source/NvBlastExtAuthoringMeshUtils.cpp new file mode 100644 index 0000000..e8a9a24 --- /dev/null +++ b/sdk/extensions/authoring/source/NvBlastExtAuthoringMeshUtils.cpp @@ -0,0 +1,941 @@ +#include "NvBlastExtAuthoringMeshUtils.h" +#include "PxVec3.h" +#include "NvBlastExtAuthoringMeshImpl.h" +#include "NvBlastExtAuthoringPerlinNoise.h" +#include "NvBlastExtAuthoringFractureTool.h" +#include + + +using namespace physx; + +#define UV_SCALE 1.f + +#define CYLINDER_UV_SCALE (UV_SCALE * 1.732) + + +namespace Nv +{ + namespace Blast + { + + void getTangents(const PxVec3& normal, PxVec3& t1, PxVec3& t2) + { + + if (std::abs(normal.z) < 0.9) + { + t1 = normal.cross(PxVec3(0, 0, 1)); + } + else + { + t1 = normal.cross(PxVec3(1, 0, 0)); + } + t2 = t1.cross(normal); + } + + Mesh* getCuttingBox(const PxVec3& point, const PxVec3& normal, float size, int64_t id, int32_t interiorMaterialId) + { + PxVec3 lNormal = normal.getNormalized(); + PxVec3 t1, t2; + getTangents(lNormal, t1, t2); + + std::vector positions(8); + positions[0].p = point + (t1 + t2) * size; + positions[1].p = point + (t2 - t1) * size; + + positions[2].p = point + (-t1 - t2) * size; + positions[3].p = point + (t1 - t2) * size; + + + positions[4].p = point + (t1 + t2 + lNormal) * size; + positions[5].p = point + (t2 - t1 + lNormal) * size; + + positions[6].p = point + (-t1 - t2 + lNormal) * size; + positions[7].p = point + (t1 - t2 + lNormal) * size; + + positions[0].n = -lNormal; + positions[1].n = -lNormal; + + positions[2].n = -lNormal; + positions[3].n = -lNormal; + + + positions[4].n = -lNormal; + positions[5].n = -lNormal; + + positions[6].n = -lNormal; + positions[7].n = -lNormal; + + positions[0].uv[0] = PxVec2(0, 0); + positions[1].uv[0] = PxVec2(UV_SCALE, 0); + + positions[2].uv[0] = PxVec2(UV_SCALE, UV_SCALE); + positions[3].uv[0] = PxVec2(0, UV_SCALE); + + + positions[4].uv[0] = PxVec2(0, 0); + positions[5].uv[0] = PxVec2(UV_SCALE, 0); + + positions[6].uv[0] = PxVec2(UV_SCALE, UV_SCALE); + positions[7].uv[0] = PxVec2(0, UV_SCALE); + + + std::vector edges; + std::vector facets; + + edges.push_back(Edge(0, 1)); + edges.push_back(Edge(1, 2)); + edges.push_back(Edge(2, 3)); + edges.push_back(Edge(3, 0)); + facets.push_back(Facet(0, 4, interiorMaterialId, id, -1)); + + + edges.push_back(Edge(0, 3)); + edges.push_back(Edge(3, 7)); + edges.push_back(Edge(7, 4)); + edges.push_back(Edge(4, 0)); + facets.push_back(Facet(4, 4, interiorMaterialId, id, -1)); + + edges.push_back(Edge(3, 2)); + edges.push_back(Edge(2, 6)); + edges.push_back(Edge(6, 7)); + edges.push_back(Edge(7, 3)); + facets.push_back(Facet(8, 4, interiorMaterialId, id, -1)); + + edges.push_back(Edge(5, 6)); + edges.push_back(Edge(6, 2)); + edges.push_back(Edge(2, 1)); + edges.push_back(Edge(1, 5)); + facets.push_back(Facet(12, 4, interiorMaterialId, id, -1)); + + edges.push_back(Edge(4, 5)); + edges.push_back(Edge(5, 1)); + edges.push_back(Edge(1, 0)); + edges.push_back(Edge(0, 4)); + facets.push_back(Facet(16, 4, interiorMaterialId, id, -1)); + + edges.push_back(Edge(4, 7)); + edges.push_back(Edge(7, 6)); + edges.push_back(Edge(6, 5)); + edges.push_back(Edge(5, 4)); + facets.push_back(Facet(20, 4, interiorMaterialId, id, -1)); + return new MeshImpl(positions.data(), edges.data(), facets.data(), static_cast(positions.size()), static_cast(edges.size()), static_cast(facets.size())); + } + + void inverseNormalAndIndices(Mesh* mesh) + { + for (uint32_t i = 0; i < mesh->getVerticesCount(); ++i) + { + mesh->getVerticesWritable()[i].n *= -1.0f; + } + for (uint32_t i = 0; i < mesh->getFacetCount(); ++i) + { + mesh->getFacetWritable(i)->userData = -mesh->getFacet(i)->userData; + } + } + + void setCuttingBox(const PxVec3& point, const PxVec3& normal, Mesh* mesh, float size, int64_t id) + { + PxVec3 t1, t2; + PxVec3 lNormal = normal.getNormalized(); + getTangents(lNormal, t1, t2); + + Vertex* positions = mesh->getVerticesWritable(); + positions[0].p = point + (t1 + t2) * size; + positions[1].p = point + (t2 - t1) * size; + + positions[2].p = point + (-t1 - t2) * size; + positions[3].p = point + (t1 - t2) * size; + + + positions[4].p = point + (t1 + t2 + lNormal) * size; + positions[5].p = point + (t2 - t1 + lNormal) * size; + + positions[6].p = point + (-t1 - t2 + lNormal) * size; + positions[7].p = point + (t1 - t2 + lNormal) * size; + + positions[0].n = -lNormal; + positions[1].n = -lNormal; + + positions[2].n = -lNormal; + positions[3].n = -lNormal; + + + positions[4].n = -lNormal; + positions[5].n = -lNormal; + + positions[6].n = -lNormal; + positions[7].n = -lNormal; + + for (uint32_t i = 0; i < mesh->getFacetCount(); ++i) + { + mesh->getFacetWritable(i)->userData = id; + } + mesh->recalculateBoundingBox(); + } + + struct Stepper + { + virtual physx::PxVec3 getStep1(uint32_t w, uint32_t h) const = 0; + virtual physx::PxVec3 getStep2(uint32_t w) const = 0; + virtual physx::PxVec3 getStart() const = 0; + virtual physx::PxVec3 getNormal(uint32_t w, uint32_t h) const = 0; + virtual bool isStep2ClosedLoop() const + { + return false; + } + virtual bool isStep2FreeBoundary() const + { + return false; + } + }; + + struct PlaneStepper : public Stepper + { + PlaneStepper(const physx::PxVec3& normal, const physx::PxVec3& point, float sizeX, float sizeY, uint32_t resolutionX, uint32_t resolutionY, bool swapTangents = false) + { + PxVec3 t1, t2; + lNormal = normal.getNormalized(); + getTangents(lNormal, t1, t2); + if (swapTangents) + { + std::swap(t1, t2); + } + t11d = -t1 * 2.0f * sizeX / resolutionX; + t12d = -t2 * 2.0f * sizeY / resolutionY; + t21d = t11d; + t22d = t12d; + cPos = point + (t1 * sizeX + t2 * sizeY); + resY = resolutionY; + } + //Define face by 4 corner points, points should lay in plane + PlaneStepper(const physx::PxVec3& p11, const physx::PxVec3& p12, const physx::PxVec3& p21, const physx::PxVec3& p22, + uint32_t resolutionX, uint32_t resolutionY) + { + lNormal = -(p21 - p11).cross(p12 - p11).getNormalized(); + if (lNormal.magnitude() < 1e-5) + { + lNormal = (p21 - p22).cross(p12 - p22).getNormalized(); + } + t11d = (p11 - p21) / resolutionX; + t12d = (p12 - p11) / resolutionY; + t21d = (p12 - p22) / resolutionX; + t22d = (p22 - p21) / resolutionY; + cPos = p21; + resY = resolutionY; + } + physx::PxVec3 getStep1(uint32_t y, uint32_t) const + { + return (t11d * (resY - y) + t21d * y) / resY; + } + physx::PxVec3 getStep2(uint32_t) const + { + return t22d; + } + physx::PxVec3 getStart() const + { + return cPos; + } + physx::PxVec3 getNormal(uint32_t, uint32_t) const + { + return lNormal; + } + + PxVec3 t11d, t12d, t21d, t22d, cPos, lNormal; + uint32_t resY; + }; + + void fillEdgesAndFaces(std::vector& edges, std::vector& facets, + uint32_t h, uint32_t w, uint32_t firstVertex, uint32_t verticesCount, int64_t id, int32_t interiorMaterialId, int32_t smoothingGroup = -1, bool reflected = false) + { + for (uint32_t i = 0; i < w; ++i) + { + for (uint32_t j = 0; j < h; ++j) + { + uint32_t start = edges.size(); + uint32_t idx00 = i * (h + 1) + j + firstVertex; + uint32_t idx01 = idx00 + 1; + uint32_t idx10 = (idx00 + h + 1) % verticesCount; + uint32_t idx11 = (idx01 + h + 1) % verticesCount; + if (reflected) + { + edges.push_back(Edge(idx01, idx11)); + edges.push_back(Edge(idx11, idx10)); + edges.push_back(Edge(idx10, idx01)); + facets.push_back(Facet(start, 3, interiorMaterialId, id, smoothingGroup)); + + start = edges.size(); + edges.push_back(Edge(idx01, idx10)); + edges.push_back(Edge(idx10, idx00)); + edges.push_back(Edge(idx00, idx01)); + facets.push_back(Facet(start, 3, interiorMaterialId, id, smoothingGroup)); + } + else + { + edges.push_back(Edge(idx00, idx01)); + edges.push_back(Edge(idx01, idx11)); + edges.push_back(Edge(idx11, idx00)); + facets.push_back(Facet(start, 3, interiorMaterialId, id, smoothingGroup)); + + start = edges.size(); + edges.push_back(Edge(idx00, idx11)); + edges.push_back(Edge(idx11, idx10)); + edges.push_back(Edge(idx10, idx00)); + facets.push_back(Facet(start, 3, interiorMaterialId, id, smoothingGroup)); + } + } + } + } + + void getNoisyFace(std::vector& vertices, std::vector& edges, std::vector& facets, + uint32_t h, uint32_t w, const physx::PxVec2& uvOffset, const physx::PxVec2& uvScale, + const Stepper& stepper, SimplexNoise& nEval, int64_t id, int32_t interiorMaterialId, bool randomizeLast = false) + { + uint32_t randIdx = randomizeLast ? 1 : 0; + PxVec3 cPosit = stepper.getStart(); + uint32_t firstVertex = vertices.size(); + for (uint32_t i = 0; i < w + 1; ++i) + { + PxVec3 lcPosit = cPosit; + for (uint32_t j = 0; j < h + 1; ++j) + { + vertices.push_back(Vertex()); + vertices.back().p = lcPosit; + vertices.back().uv[0] = uvOffset + uvScale.multiply(physx::PxVec2(j, i)); + lcPosit += stepper.getStep1(i, j); + } + cPosit += stepper.getStep2(i); + } + + for (uint32_t i = 1 - randIdx; i < w + randIdx; ++i) + { + for (uint32_t j = 1; j < h; ++j) + { + //TODO limit max displacement for cylinder + PxVec3& pnt = vertices[i * (h + 1) + j + firstVertex].p; + pnt += stepper.getNormal(i, j) * nEval.sample(pnt); + } + } + + fillEdgesAndFaces(edges, facets, h, w, firstVertex, vertices.size(), id, interiorMaterialId); + } + + PX_INLINE uint32_t unsignedMod(int32_t n, uint32_t modulus) + { + const int32_t d = n / (int32_t)modulus; + const int32_t m = n - d*(int32_t)modulus; + return m >= 0 ? (uint32_t)m : (uint32_t)m + modulus; + } + + void calculateNormals(std::vector& vertices, uint32_t h, uint32_t w, bool inverseNormals = false) + { + for (uint32_t i = 1; i < w; ++i) + { + for (uint32_t j = 1; j < h; ++j) + { + int32_t idx = i * (h + 1) + j; + PxVec3 v1 = vertices[idx + h + 1].p - vertices[idx].p; + PxVec3 v2 = vertices[idx + 1].p - vertices[idx].p; + PxVec3 v3 = vertices[idx - (h + 1)].p - vertices[idx].p; + PxVec3 v4 = vertices[idx - 1].p - vertices[idx].p; + + vertices[idx].n = v1.cross(v2) + v2.cross(v3) + v3.cross(v4) + v4.cross(v1); + if (inverseNormals) + { + vertices[idx].n = -vertices[idx].n; + } + vertices[idx].n.normalize(); + } + } + } + + Mesh* getNoisyCuttingBoxPair(const physx::PxVec3& point, const physx::PxVec3& normal, float size, float jaggedPlaneSize, physx::PxVec3 resolution, int64_t id, float amplitude, float frequency, int32_t octaves, int32_t seed, int32_t interiorMaterialId) + { + PxVec3 t1, t2; + PxVec3 lNormal = normal.getNormalized(); + getTangents(lNormal, t1, t2); + float sz = 2.f * jaggedPlaneSize; + uint32_t resolutionX = std::max(1u, (uint32_t)std::roundf(sz * std::abs(t1.x) * resolution.x + sz * std::abs(t1.y) * resolution.y + sz * std::abs(t1.z) * resolution.z)); + uint32_t resolutionY = std::max(1u, (uint32_t)std::roundf(sz * std::abs(t2.x) * resolution.x + sz * std::abs(t2.y) * resolution.y + sz * std::abs(t2.z) * resolution.z)); + + PlaneStepper stepper(normal, point, jaggedPlaneSize, jaggedPlaneSize, resolutionX, resolutionY); + SimplexNoise nEval(amplitude, frequency, octaves, seed); + + std::vector vertices; vertices.reserve((resolutionX + 1) * (resolutionY + 1) + 12); + std::vector edges; + std::vector facets; + getNoisyFace(vertices, edges, facets, resolutionX, resolutionY, physx::PxVec2(0.f), physx::PxVec2(UV_SCALE / resolutionX, UV_SCALE / resolutionY), + stepper, nEval, id, interiorMaterialId); + calculateNormals(vertices, resolutionX, resolutionY); + + uint32_t offset = (resolutionX + 1) * (resolutionY + 1); + vertices.resize(offset + 12); + + vertices[0 + offset].p = point + (t1 + t2) * size; + vertices[1 + offset].p = point + (t2 - t1) * size; + + vertices[2 + offset].p = point + (-t1 - t2) * size; + vertices[3 + offset].p = point + (t1 - t2) * size; + + vertices[8 + offset].p = point + (t1 + t2) * jaggedPlaneSize; + vertices[9 + offset].p = point + (t2 - t1) * jaggedPlaneSize; + + vertices[10 + offset].p = point + (-t1 - t2) * jaggedPlaneSize; + vertices[11 + offset].p = point + (t1 - t2) * jaggedPlaneSize; + + vertices[4 + offset].p = point + (t1 + t2 + lNormal) * size; + vertices[5 + offset].p = point + (t2 - t1 + lNormal) * size; + + vertices[6 + offset].p = point + (-t1 - t2 + lNormal) * size; + vertices[7 + offset].p = point + (t1 - t2 + lNormal) * size; + + int32_t edgeOffset = edges.size(); + edges.push_back(Edge(0 + offset, 1 + offset)); + edges.push_back(Edge(1 + offset, 2 + offset)); + edges.push_back(Edge(2 + offset, 3 + offset)); + edges.push_back(Edge(3 + offset, 0 + offset)); + + edges.push_back(Edge(11 + offset, 10 + offset)); + edges.push_back(Edge(10 + offset, 9 + offset)); + edges.push_back(Edge(9 + offset, 8 + offset)); + edges.push_back(Edge(8 + offset, 11 + offset)); + + facets.push_back(Facet(edgeOffset, 8, interiorMaterialId, id, -1)); + + edges.push_back(Edge(0 + offset, 3 + offset)); + edges.push_back(Edge(3 + offset, 7 + offset)); + edges.push_back(Edge(7 + offset, 4 + offset)); + edges.push_back(Edge(4 + offset, 0 + offset)); + facets.push_back(Facet(8 + edgeOffset, 4, interiorMaterialId, id, -1)); + + edges.push_back(Edge(3 + offset, 2 + offset)); + edges.push_back(Edge(2 + offset, 6 + offset)); + edges.push_back(Edge(6 + offset, 7 + offset)); + edges.push_back(Edge(7 + offset, 3 + offset)); + facets.push_back(Facet(12 + edgeOffset, 4, interiorMaterialId, id, -1)); + + edges.push_back(Edge(5 + offset, 6 + offset)); + edges.push_back(Edge(6 + offset, 2 + offset)); + edges.push_back(Edge(2 + offset, 1 + offset)); + edges.push_back(Edge(1 + offset, 5 + offset)); + facets.push_back(Facet(16 + edgeOffset, 4, interiorMaterialId, id, -1)); + + edges.push_back(Edge(4 + offset, 5 + offset)); + edges.push_back(Edge(5 + offset, 1 + offset)); + edges.push_back(Edge(1 + offset, 0 + offset)); + edges.push_back(Edge(0 + offset, 4 + offset)); + facets.push_back(Facet(20 + edgeOffset, 4, interiorMaterialId, id, -1)); + + edges.push_back(Edge(4 + offset, 7 + offset)); + edges.push_back(Edge(7 + offset, 6 + offset)); + edges.push_back(Edge(6 + offset, 5 + offset)); + edges.push_back(Edge(5 + offset, 4 + offset)); + facets.push_back(Facet(24 + edgeOffset, 4, interiorMaterialId, id, -1)); + + // + return new MeshImpl(vertices.data(), edges.data(), facets.data(), vertices.size(), edges.size(), facets.size()); + } + + Mesh* getBigBox(const PxVec3& point, float size, int32_t interiorMaterialId) + { + PxVec3 normal(0, 0, 1); + normal.normalize(); + PxVec3 t1, t2; + getTangents(normal, t1, t2); + + std::vector positions(8); + positions[0].p = point + (t1 + t2 - normal) * size; + positions[1].p = point + (t2 - t1 - normal) * size; + + positions[2].p = point + (-t1 - t2 - normal) * size; + positions[3].p = point + (t1 - t2 - normal) * size; + + + positions[4].p = point + (t1 + t2 + normal) * size; + positions[5].p = point + (t2 - t1 + normal) * size; + + positions[6].p = point + (-t1 - t2 + normal) * size; + positions[7].p = point + (t1 - t2 + normal) * size; + + positions[0].uv[0] = PxVec2(0, 0); + positions[1].uv[0] = PxVec2(UV_SCALE, 0); + + positions[2].uv[0] = PxVec2(UV_SCALE, UV_SCALE); + positions[3].uv[0] = PxVec2(0, UV_SCALE); + + + positions[4].uv[0] = PxVec2(0, 0); + positions[5].uv[0] = PxVec2(UV_SCALE, 0); + + positions[6].uv[0] = PxVec2(UV_SCALE, UV_SCALE); + positions[7].uv[0] = PxVec2(0, UV_SCALE); + + + std::vector edges; + std::vector facets; + + edges.push_back(Edge(0, 1)); + edges.push_back(Edge(1, 2)); + edges.push_back(Edge(2, 3)); + edges.push_back(Edge(3, 0)); + facets.push_back(Facet(0, 4, interiorMaterialId, 0, -1)); + + + edges.push_back(Edge(0, 3)); + edges.push_back(Edge(3, 7)); + edges.push_back(Edge(7, 4)); + edges.push_back(Edge(4, 0)); + facets.push_back(Facet(4, 4, interiorMaterialId, 0, -1)); + + edges.push_back(Edge(3, 2)); + edges.push_back(Edge(2, 6)); + edges.push_back(Edge(6, 7)); + edges.push_back(Edge(7, 3)); + facets.push_back(Facet(8, 4, interiorMaterialId, 0, -1)); + + edges.push_back(Edge(5, 6)); + edges.push_back(Edge(6, 2)); + edges.push_back(Edge(2, 1)); + edges.push_back(Edge(1, 5)); + facets.push_back(Facet(12, 4, interiorMaterialId, 0, -1)); + + edges.push_back(Edge(4, 5)); + edges.push_back(Edge(5, 1)); + edges.push_back(Edge(1, 0)); + edges.push_back(Edge(0, 4)); + facets.push_back(Facet(16, 4, interiorMaterialId, 0, -1)); + + edges.push_back(Edge(4, 7)); + edges.push_back(Edge(7, 6)); + edges.push_back(Edge(6, 5)); + edges.push_back(Edge(5, 4)); + facets.push_back(Facet(20, 4, interiorMaterialId, 0, -1)); + for (int i = 0; i < 8; ++i) + positions[i].n = PxVec3(0, 0, 0); + return new MeshImpl(positions.data(), edges.data(), facets.data(), static_cast(positions.size()), static_cast(edges.size()), static_cast(facets.size())); + } + + bool CmpSharedFace::operator()(const std::pair& pv1, const std::pair& pv2) const + { + CmpVec vc; + if ((pv1.first - pv2.first).magnitude() < 1e-5) + { + return vc(pv1.second, pv2.second); + } + return vc(pv1.first, pv2.first); + } + +#define INDEXER_OFFSET (1ll << 32) + + void buildCuttingConeFaces(const CutoutConfiguration& conf, const std::vector>& cutoutPoints, + float heightBot, float heightTop, float conicityBot, float conicityTop, + int64_t& id, int32_t seed, int32_t interiorMaterialId, SharedFacesMap& sharedFacesMap) + { + if (conf.noise.amplitude <= FLT_EPSILON) + { + return; + } + std::map>, CmpVec> newCutoutPoints; + uint32_t resH = std::max((uint32_t)std::roundf((heightBot + heightTop) / conf.noise.samplingInterval.z), 1u); + + //generate noisy faces + SimplexNoise nEval(conf.noise.amplitude, conf.noise.frequency, conf.noise.octaveNumber, seed); + + for (uint32_t i = 0; i < cutoutPoints.size(); i++) + { + auto& points = cutoutPoints[i]; + uint32_t pointCount = points.size(); + float finalP = 0, currentP = 0; + for (uint32_t j = 0; j < pointCount; j++) + { + finalP += (points[(j + 1) % pointCount] - points[j]).magnitude(); + } + + for (uint32_t p = 0; p < pointCount; p++) + { + auto p0 = points[p]; + auto p1 = points[(p + 1) % pointCount]; + + auto cp0 = newCutoutPoints.find(p0); + if (cp0 == newCutoutPoints.end()) + { + newCutoutPoints[p0] = std::make_pair(0u, std::vector(resH + 1, physx::PxVec3(0.f))); + cp0 = newCutoutPoints.find(p0); + } + auto cp1 = newCutoutPoints.find(p1); + if (cp1 == newCutoutPoints.end()) + { + newCutoutPoints[p1] = std::make_pair(0u, std::vector(resH + 1, physx::PxVec3(0.f))); + cp1 = newCutoutPoints.find(p1); + } + + + auto vec = p1 - p0; + auto cPos = (p0 + p1) * 0.5f; + uint32_t numPts = (uint32_t)(std::abs(vec.x) / conf.noise.samplingInterval.x + std::abs(vec.y) / conf.noise.samplingInterval.y) + 1; + auto normal = vec.cross(physx::PxVec3(0, 0, 1)); + normal = normal; + + auto p00 = p0 * conicityBot; p00.z = -heightBot; + auto p01 = p1 * conicityBot; p01.z = -heightBot; + auto p10 = p0 * conicityTop; p10.z = heightTop; + auto p11 = p1 * conicityTop; p11.z = heightTop; + PlaneStepper stepper(p00, p01, p10, p11, resH, numPts); + + PlaneStepper stepper1(normal, cPos, heightTop, vec.magnitude() * 0.5f, resH, numPts, true); + stepper1.getNormal(0, 0); + + auto t = std::make_pair(p0, p1); + auto sfIt = sharedFacesMap.find(t); + if (sfIt == sharedFacesMap.end() && sharedFacesMap.find(std::make_pair(p1, p0)) == sharedFacesMap.end()) + { + sharedFacesMap[t] = SharedFace(numPts, resH, -(id + INDEXER_OFFSET), interiorMaterialId); + sfIt = sharedFacesMap.find(t); + auto& SF = sfIt->second; + getNoisyFace(SF.vertices, SF.edges, SF.facets, resH, numPts, + physx::PxVec2(0, CYLINDER_UV_SCALE * currentP / (heightBot + heightTop)), + physx::PxVec2(CYLINDER_UV_SCALE / resH, CYLINDER_UV_SCALE * vec.magnitude() / (heightBot + heightTop) / numPts), + stepper, nEval, id++ + INDEXER_OFFSET, interiorMaterialId, true); + + currentP += vec.magnitude(); + cp0->second.first++; + cp1->second.first++; + for (uint32_t k = 0; k <= resH; k++) + { + cp0->second.second[k] += SF.vertices[k].p; + cp1->second.second[k] += SF.vertices[SF.vertices.size() - resH - 1 + k].p; + } + } + } + } + + //limit faces displacement iteratively + for (uint32_t i = 0; i < cutoutPoints.size(); i++) + { + auto& points = cutoutPoints[i]; + uint32_t pointCount = points.size(); + for (uint32_t p = 0; p < pointCount; p++) + { + auto p0 = points[p]; + auto p1 = points[(p + 1) % pointCount]; + auto p2 = points[(p + 2) % pointCount]; + auto& cp1 = newCutoutPoints.find(p1)->second; + float d = physx::PxClamp((p1 - p0).getNormalized().dot((p2 - p1).getNormalized()), 0.f, 1.f); + + for (uint32_t h = 0; h <= resH; h++) + { + float z = cp1.second[h].z; + float conicity = (conicityBot * h + conicityTop * (resH - h)) / resH; + cp1.second[h] = cp1.second[h] * d + p1 * cp1.first * conicity * (1.f - d); + cp1.second[h].z = z; + } + } + } + + //relax nearby points for too big faces displacement limitations + for (uint32_t i = 0; i < cutoutPoints.size(); i++) + { + auto& points = cutoutPoints[i]; + uint32_t pointCount = points.size(); + for (uint32_t p = 0; p < pointCount; p++) + { + auto p0 = points[p]; + auto p1 = points[(p + 1) % pointCount]; + auto& cp0 = newCutoutPoints.find(p0)->second; + auto& cp1 = newCutoutPoints.find(p1)->second; + + auto SFIt = sharedFacesMap.find(std::make_pair(p0, p1)); + + uint32_t idx0 = 0, idx1; + if (SFIt == sharedFacesMap.end()) + { + SFIt = sharedFacesMap.find(std::make_pair(p1, p0)); + idx1 = 0; + idx0 = SFIt->second.w * (SFIt->second.h + 1); + } + else + { + idx1 = SFIt->second.w * (SFIt->second.h + 1); + } + + for (uint32_t h = 0; h <= resH; h++) + { + float z = cp1.second[h].z; + float R0 = (cp0.second[h] / cp0.first - SFIt->second.vertices[idx0 + h].p).magnitude(); + float R1 = (cp1.second[h] / cp1.first - SFIt->second.vertices[idx1 + h].p).magnitude(); + float R = R0 - R1; + float r = 0.25f * (cp1.second[h] / cp1.first - cp0.second[h] / cp0.first).magnitude(); + float conicity = (conicityBot * h + conicityTop * (resH - h)) / resH; + if (R > r) + { + float w = std::min(1.f, r / R); + cp1.second[h] = cp1.second[h] * w + p1 * cp1.first * conicity * (1.f - w); + cp1.second[h].z = z; + } + } + } + + for (int32_t p = pointCount - 1; p >= 0; p--) + { + auto p0 = points[p]; + auto p1 = points[unsignedMod(p - 1, pointCount)]; + auto& cp0 = newCutoutPoints.find(p0)->second; + auto& cp1 = newCutoutPoints.find(p1)->second; + + auto SFIt = sharedFacesMap.find(std::make_pair(p0, p1)); + uint32_t idx0 = 0, idx1; + if (SFIt == sharedFacesMap.end()) + { + SFIt = sharedFacesMap.find(std::make_pair(p1, p0)); + idx1 = 0; + idx0 = SFIt->second.w * (SFIt->second.h + 1); + } + else + { + idx1 = SFIt->second.w * (SFIt->second.h + 1); + } + + for (uint32_t h = 0; h <= resH; h++) + { + float z = cp1.second[h].z; + float R0 = (cp0.second[h] / cp0.first - SFIt->second.vertices[idx0 + h].p).magnitude(); + float R1 = (cp1.second[h] / cp1.first - SFIt->second.vertices[idx1 + h].p).magnitude(); + float R = R0 - R1; + float r = 0.25f * (cp1.second[h] / cp1.first - cp0.second[h] / cp0.first).magnitude(); + float conicity = (conicityBot * h + conicityTop * (resH - h)) / resH; + if (R > r) + { + float w = std::min(1.f, r / R); + cp1.second[h] = cp1.second[h] * w + p1 * cp1.first * conicity * (1.f - w); + cp1.second[h].z = z; + } + } + } + } + + //glue faces + for (auto& SF : sharedFacesMap) + { + auto& cp0 = newCutoutPoints.find(SF.first.first)->second; + auto& cp1 = newCutoutPoints.find(SF.first.second)->second; + auto& v = SF.second.vertices; + float invW = 1.f / SF.second.w; + + for (uint32_t w = 0; w <= SF.second.w; w++) + { + for (uint32_t h = 0; h <= SF.second.h; h++) + { + v[w * (SF.second.h + 1) + h].p += ((cp0.second[h] / cp0.first - v[h].p) * (SF.second.w - w) + + (cp1.second[h] / cp1.first - v[SF.second.w * (SF.second.h + 1) + h].p) * w) * invW; + } + } + } + } + + Mesh* getNoisyCuttingCone(const std::vector& points, const std::set& smoothingGroups, + const physx::PxTransform& transform, bool useSmoothing, float heightBot, float heightTop, float conicityMultiplierBot, float conicityMultiplierTop, + physx::PxVec3 samplingInterval, uint32_t interiorMaterialId, const SharedFacesMap& sharedFacesMap, bool inverseNormals) + { + uint32_t pointCount = points.size(); + uint32_t resP = pointCount; + for (uint32_t i = 0; i < pointCount; i++) + { + auto vec = (points[(i + 1) % pointCount] - points[i]); + resP += (uint32_t)(std::abs(vec.x) / samplingInterval.x + std::abs(vec.y) / samplingInterval.y); + } + uint32_t resH = std::max((uint32_t)std::roundf((heightBot + heightTop) / samplingInterval.z), 1u); + + std::vector positions; positions.reserve((resH + 1) * (resP + 1)); + std::vector edges; edges.reserve(resH * resP * 6 + (resP + 1) * 2); + std::vector facets; facets.reserve(resH * resP * 2 + 2); + + uint32_t pCount = 0; + int sg = useSmoothing ? 1 : -1; + for (uint32_t p = 0; p < pointCount; p++) + { + if (useSmoothing && smoothingGroups.find(p) != smoothingGroups.end()) + { + sg = sg ^ 3; + } + auto p0 = points[p]; + auto p1 = points[(p + 1) % pointCount]; + + uint32_t firstVertexIndex = positions.size(); + uint32_t firstEdgeIndex = edges.size(); + + auto sfIt = sharedFacesMap.find(std::make_pair(p0, p1)); + int32_t vBegin = 0, vEnd = -1, vIncr = 1; + if (sfIt == sharedFacesMap.end()) + { + sfIt = sharedFacesMap.find(std::make_pair(p1, p0));; + vBegin = sfIt->second.w; + vIncr = -1; + } + else + { + vEnd = sfIt->second.w + 1; + } + + auto& SF = sfIt->second; + positions.resize(firstVertexIndex + (SF.w + 1) * (SF.h + 1)); + if (vBegin < vEnd) + { + for (auto& e : SF.edges) + { + edges.push_back(Edge(e.s + firstVertexIndex, e.e + firstVertexIndex)); + } + for (auto& f : SF.facets) + { + facets.push_back(f); + facets.back().firstEdgeNumber += firstEdgeIndex; + facets.back().smoothingGroup = sg; + } + } + else + { + fillEdgesAndFaces(edges, facets, SF.h, SF.w, firstVertexIndex, positions.size(), SF.f.userData, SF.f.materialId, sg, true); + } + for (int32_t v = vBegin; v != vEnd; v += vIncr) + { + std::copy(SF.vertices.begin() + v * (resH + 1), SF.vertices.begin() + (v + 1) * (SF.h + 1), positions.begin() + firstVertexIndex); + firstVertexIndex += SF.h + 1; + } + pCount += SF.vertices.size() / (resH + 1) - 1; + } + + if (inverseNormals) + { + for (uint32_t e = 0; e < edges.size(); e += 3) + { + std::swap(edges[e + 0].s, edges[e + 0].e); + std::swap(edges[e + 1].s, edges[e + 1].e); + std::swap(edges[e + 2].s, edges[e + 2].e); + std::swap(edges[e + 0], edges[e + 2]); + } + } + + uint32_t totalCount = pCount + pointCount; + calculateNormals(positions, resH, totalCount - 1, inverseNormals); + + std::vector xPos, yPos; + int32_t ii = 0; + for (auto& p : positions) + { + if ((ii++) % (resH + 1) == 1) + { + xPos.push_back(p.p.x); + yPos.push_back(p.p.y); + } + p.p = transform.transform(p.p); + p.n = transform.rotate(p.n); + } + totalCount /= 2; + + for (uint32_t i = 0; i < totalCount; i++) + { + uint32_t idx = 2 * i * (resH + 1); + edges.push_back(Edge(idx, (idx + 2 * (resH + 1)) % positions.size())); + } + for (int32_t i = totalCount; i > 0; i--) + { + uint32_t idx = (2 * i + 1) * (resH + 1) - 1; + edges.push_back(Edge(idx % positions.size(), idx - 2 * (resH + 1))); + } + + if (smoothingGroups.find(0) != smoothingGroups.end() || smoothingGroups.find(pointCount - 1) != smoothingGroups.end()) + { + if (facets[0].smoothingGroup == facets[facets.size() - 1].smoothingGroup) + { + for (uint32_t i = 0; i < resH; i++) + { + facets[i].smoothingGroup = 4; + } + } + } + + facets.push_back(Facet(resH * pCount * 6, totalCount, interiorMaterialId, 0, -1)); + facets.push_back(Facet(resH * pCount * 6 + totalCount, totalCount, interiorMaterialId, 0, -1)); + return new MeshImpl(positions.data(), edges.data(), facets.data(), static_cast(positions.size()), static_cast(edges.size()), static_cast(facets.size())); + } + + Mesh* getCuttingCone(const CutoutConfiguration& conf, const std::vector& points, const std::set& smoothingGroups, + float heightBot, float heightTop, float conicityBot, float conicityTop, + int64_t& id, int32_t seed, int32_t interiorMaterialId, const SharedFacesMap& sharedFacesMap, bool inverseNormals) + { + uint32_t pointCount = points.size(); + if (conf.noise.amplitude > FLT_EPSILON) + { + return getNoisyCuttingCone(points, smoothingGroups, conf.transform, conf.useSmoothing, heightBot, heightTop, conicityBot, conicityTop, + conf.noise.samplingInterval, interiorMaterialId, sharedFacesMap, inverseNormals); + } + + float currentP = 0; + std::vector positions((pointCount + 1) * 2); + std::vector edges(pointCount * 6 + 2); + std::vector facets(pointCount + 2); + + int sg = conf.useSmoothing ? 1 : -1; + for (uint32_t i = 0; i < pointCount + 1; i++) + { + if (conf.useSmoothing && smoothingGroups.find(i) != smoothingGroups.end()) + { + sg = sg ^ 3; + } + uint32_t i1 = i + pointCount + 1; + uint32_t i3 = i + 1; + uint32_t i2 = i3 + pointCount + 1; + + auto& p0 = positions[i]; + auto& p1 = positions[i1]; + p0.n = p1.n = physx::PxVec3(0.f, 0.f, 0.f); + p0.p = points[i % pointCount] * conicityBot; + p0.p.z = -heightBot; + p1.p = points[i % pointCount] * conicityTop; + p1.p.z = heightTop; + p0.p = conf.transform.transform(p0.p); + p1.p = conf.transform.transform(p1.p); + p0.uv[0] = PxVec2(0.f, CYLINDER_UV_SCALE * currentP / (heightBot + heightTop)); + p1.uv[0] = PxVec2(CYLINDER_UV_SCALE, CYLINDER_UV_SCALE * currentP / (heightBot + heightTop)); + if (i == pointCount) + { + break; + } + currentP += (points[(i + 1) % pointCount] - points[i]).magnitude(); + + int32_t edgeIdx = 4 * i; + if (inverseNormals) + { + edges[edgeIdx + 1] = Edge(i1, i2); + edges[edgeIdx + 2] = Edge(i2, i3); + edges[edgeIdx + 3] = Edge(i3, i); + edges[edgeIdx + 0] = Edge(i, i1); + } + else + { + edges[edgeIdx + 0] = Edge(i, i3); + edges[edgeIdx + 1] = Edge(i3, i2); + edges[edgeIdx + 2] = Edge(i2, i1); + edges[edgeIdx + 3] = Edge(i1, i); + } + facets[i] = Facet(edgeIdx, 4, interiorMaterialId, id, sg); + + edges[5 * pointCount + i + 1] = Edge(i1, i2); + edges[5 * pointCount - i - 1] = Edge(i3, i); + } + edges[5 * pointCount] = Edge(0, pointCount); + edges[6 * pointCount + 1] = Edge(2 * pointCount + 1, pointCount + 1); + + if (smoothingGroups.find(0) != smoothingGroups.end() || smoothingGroups.find(pointCount - 1) != smoothingGroups.end()) + { + if (facets[0].smoothingGroup == facets[pointCount - 1].smoothingGroup) + { + facets[0].smoothingGroup = 4; + } + } + + facets[pointCount + 0] = Facet(4 * pointCount, pointCount + 1, interiorMaterialId, 0, -1); + facets[pointCount + 1] = Facet(5 * pointCount + 1, pointCount + 1, interiorMaterialId, 0, -1); + return new MeshImpl(positions.data(), edges.data(), facets.data(), static_cast(positions.size()), static_cast(edges.size()), static_cast(facets.size())); + } + + } +} \ No newline at end of file diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringMeshUtils.h b/sdk/extensions/authoring/source/NvBlastExtAuthoringMeshUtils.h new file mode 100644 index 0000000..b4841ef --- /dev/null +++ b/sdk/extensions/authoring/source/NvBlastExtAuthoringMeshUtils.h @@ -0,0 +1,126 @@ +#include +#include +#include +#include +#include "NvBlastExtAuthoringTypes.h" + +namespace physx +{ + class PxVec3; +}; + +namespace Nv +{ +namespace Blast +{ + + class Mesh; + +/** + Helper functions +*/ + +/** +Set cutting box at some particular position. +\param[in] point Cutting face center +\param[in] normal Cutting face normal +\param[in] mesh Cutting box mesh +\param[in] size Cutting box size +\param[in] id Cutting box ID +*/ +void setCuttingBox(const physx::PxVec3& point, const physx::PxVec3& normal, Mesh* mesh, float size, int64_t id); +/** +Create cutting box at some particular position. +\param[in] point Cutting face center +\param[in] normal Cutting face normal +\param[in] size Cutting box size +\param[in] id Cutting box ID +*/ +Mesh* getCuttingBox(const physx::PxVec3& point, const physx::PxVec3& normal, float size, int64_t id, int32_t interiorMaterialId); + +/** +Create box at some particular position. +\param[in] point Cutting face center +\param[in] size Cutting box size +*/ +Mesh* getBigBox(const physx::PxVec3& point, float size, int32_t interiorMaterialId); + +/** +Create slicing box with noisy cutting surface. +\param[in] point Cutting face center +\param[in] normal Cutting face normal +\param[in] size Cutting box size +\param[in] jaggedPlaneSize Noisy surface size +\param[in] resolution Noisy surface resolution +\param[in] id Cutting box ID +\param[in] amplitude Noise amplitude +\param[in] frequency Noise frequency +\param[in] octaves Noise octaves +\param[in] seed Random generator seed, used for noise generation. +*/ +Mesh* getNoisyCuttingBoxPair(const physx::PxVec3& point, const physx::PxVec3& normal, float size, float jaggedPlaneSize, physx::PxVec3 resolution, int64_t id, float amplitude, float frequency, int32_t octaves, int32_t seed, int32_t interiorMaterialId); + + +/** +Inverses normals of cutting box and sets indices. +\param[in] mesh Cutting box mesh +*/ +void inverseNormalAndIndices(Mesh* mesh); + +struct CmpVec +{ + bool operator()(const physx::PxVec3& v1, const physx::PxVec3& v2) const; +}; + +typedef std::map, CmpVec> PointMap; + +struct SharedFace +{ + SharedFace() {} + SharedFace(uint32_t inW, uint32_t inH, int64_t inUD, int32_t inMatId) + : w(inW), h(inH), f(0, 3, inMatId, inUD) + { + vertices.reserve((w + 1) * (h + 1)); + } + uint32_t w, h; + Facet f; + std::vector vertices; + std::vector edges; + std::vector facets; +}; + +struct CmpSharedFace +{ + bool operator()(const std::pair& pv1, const std::pair& pv2) const; +}; + +typedef std::map, SharedFace, CmpSharedFace> SharedFacesMap; + +struct CutoutConfiguration; + +void buildCuttingConeFaces(const CutoutConfiguration& conf, const std::vector>& points, + float heightBot, float heightTop, float conicityBot, float conicityTop, + int64_t& id, int32_t seed, int32_t interiorMaterialId, SharedFacesMap& sharedFacesMap); + +/** +Create cutting cone at some particular position. +\param[in] conf Cutout configuration parameters and data +\param[in] meshId Cutout index +\param[in] points Array of points for loop +\param[in] smoothingGroups Array of point indices at which smoothing group should be toggled +\param[in] heightBot Cutting cone bottom height (below z = 0) +\param[in] heightTop Cutting cone top height (below z = 0) +\param[in] conicityBot Cutting cone bottom points multiplier +\param[in] conicityTop Cutting cone top points multiplier +\param[in] id Cutting cylinder ID +\param[in] seed Seed for RNG +\param[in] interiorMaterialId Interior material index +\param[in] sharedFacesMap Shared faces for noisy fracture +*/ +Mesh* getCuttingCone(const CutoutConfiguration& conf, + const std::vector& points, const std::set& smoothingGroups, + float heightBot, float heightTop, float conicityBot, float conicityTop, + int64_t& id, int32_t seed, int32_t interiorMaterialId, const SharedFacesMap& sharedFacesMap, bool inverseNormals = false); + +}; +}; \ No newline at end of file diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringPatternGeneratorImpl.cpp b/sdk/extensions/authoring/source/NvBlastExtAuthoringPatternGeneratorImpl.cpp new file mode 100644 index 0000000..f12c931 --- /dev/null +++ b/sdk/extensions/authoring/source/NvBlastExtAuthoringPatternGeneratorImpl.cpp @@ -0,0 +1,311 @@ +// 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 "NvBlastGlobals.h" +#include "NvBlastAssert.h" +#include "NvBlastExtAuthoringTypes.h" +#include "NvBlastExtAuthoringPatternGeneratorImpl.h" +#include "NvBlastExtAuthoringMeshUtils.h" +#include "NvBlastExtAuthoringMeshImpl.h" +#include "NvBlastExtAuthoringFractureToolImpl.h" +#include "NvBlastExtAuthoringBooleanTool.h" +#include "NvBlastExtAuthoringTriangulator.h" +#include "NvBlastExtAuthoringPerlinNoise.h" + +#include +#include "PxVec3.h" + +using namespace Nv::Blast; +using namespace physx; + +struct DamagePatternImpl : public DamagePattern +{ + virtual void release() override; +}; + +DamagePattern* PatternGeneratorImpl::generateUniformPattern(const UniformPatternDesc* desc) +{ + std::vector points; + float radiusDelta = desc->radiusMax - desc->radiusMin; + for (uint32_t i = 0; i < desc->cellsCount; ++i) + { + float rd = desc->RNG() * radiusDelta + desc->radiusMin; + + if (desc->radiusDistr != 1.0f) + { + rd = std::pow(rd / desc->radiusMax, desc->radiusDistr) * desc->radiusMax; + } + + float phi = desc->RNG() * 6.28f; + float theta = (desc->RNG()) * 6.28f; + + float x = rd * cos(phi) * sin(theta); + float y = rd * sin(phi) * sin(theta); + float z = rd * cos(theta); + + points.push_back(PxVec3(x, y, z)); + } + + + auto pattern = generateVoronoiPattern((uint32_t)points.size(), points.data(), desc->interiorMaterialId); + pattern->activationRadius = desc->radiusMax * desc->debrisRadiusMult; + return pattern; +} + +DamagePattern* PatternGeneratorImpl::generateVoronoiPattern(uint32_t cellCount, const physx::PxVec3* inPoints, int32_t interiorMaterialId) +{ + return generateVoronoiPatternInternal(cellCount, inPoints, interiorMaterialId); +} + +DamagePattern* PatternGeneratorImpl::generateVoronoiPatternInternal(uint32_t cellCount, const physx::PxVec3* inPoints, int32_t interiorMaterialId, float angle) +{ + DamagePatternImpl* pattern = NVBLAST_NEW(DamagePatternImpl); + + std::vector points(cellCount); + physx::PxVec3 orig(0.f); + for (uint32_t i = 0; i < cellCount; ++i) + { + points[i] = inPoints[i]; + orig += points[i]; + } + orig /= cellCount; + + std::vector > neighboors; + findCellBasePlanes(points, neighboors); + + Mesh** patterns = (Mesh**)NVBLAST_ALLOC(sizeof(Mesh*) * cellCount); + + //PreparedMesh** prepMeshes = (PreparedMesh**)NVBLAST_ALLOC(sizeof(PreparedMesh*) * cellCount); + + BooleanEvaluator evl; + for (uint32_t i = 0; i < cellCount; ++i) + { + patterns[i] = getCellMesh(evl, 0, i, points, neighboors, interiorMaterialId, orig); + if (patterns[i] == nullptr) + { + continue; + } + if (angle != 0) + { + auto* vr = patterns[i]->getVerticesWritable(); + for (uint32_t j = 0; j < patterns[i]->getVerticesCount(); ++j) + { + float& z = vr[j].p.z; + z -= 3.8f; + if (z < -2) // we presume that this vertex has infinite -z position (everything scaled to unit cube). + { + if (angle > 0) + { + float d = sqrt(vr[j].p.x * vr[j].p.x + vr[j].p.y * vr[j].p.y); + + vr[j].p.x *= (d + 4 * tan(angle * physx::PxPi / 180.f)) / d; + vr[j].p.y *= (d + 4 * tan(angle * physx::PxPi / 180.f)) / d; + } + } + } + patterns[i]->recalculateBoundingBox(); + } + } + for (int32_t i = cellCount - 1; i >= 0; i--) + { + if (patterns[i] == nullptr) + { + cellCount--; + std::swap(patterns[i], patterns[cellCount]); + //std::swap(prepMeshes[i], prepMeshes[cellCount]); + } + } + pattern->cellsCount = cellCount; + pattern->cellsMeshes = patterns; + //pattern->preparedMeshes = prepMeshes; + +#ifdef USE_MERGED_MESH + pattern->outputEdges = NVBLAST_ALLOC(sizeof(BooleanResultEdge) * (cellCount * BLASTRT_MAX_EDGES_PER_CHUNK)); + pattern->outputEdgesCount = (uint32_t*)NVBLAST_ALLOC(sizeof(uint32_t) * cellCount); +#endif + + return pattern; +} + +DamagePattern* PatternGeneratorImpl::generateBeamPattern(const BeamPatternDesc* desc) +{ + std::vector points; + + float radiusDelta = desc->radiusMax - desc->radiusMin; + + for (uint32_t i = 0; i < desc->cellsCount; ++i) + { + float rd = desc->RNG() * radiusDelta + desc->radiusMin; + float phi = desc->RNG() * 6.28f; + + float x = rd * cos(phi); + float y = rd * sin(phi); + float z = desc->RNG() - 1; + points.push_back(PxVec3(x, y, z)); + } + auto pattern = generateVoronoiPattern((uint32_t)points.size(), points.data(), desc->interiorMaterialId); + pattern->activationType = DamagePattern::Line; + return pattern; +} + +DamagePattern* PatternGeneratorImpl::generateRegularRadialPattern(const RegularRadialPatternDesc* desc) +{ + SimplexNoise noise(desc->radialNoiseAmplitude, desc->radialNoiseFrequency, 3, desc->RNG() * 999999); + std::vector points; + + float radialDelta = (desc->radiusMax - desc->radiusMin) / desc->radialSteps; + float angularDelta = 2 * acos(-1.0f) / desc->angularSteps; + + + for (uint32_t i = 0; i < desc->radialSteps; ++i) + { + for (uint32_t j = 0; j < desc->angularSteps; ++j) + { + float angle = j * angularDelta + desc->RNG() * desc->angularNoiseAmplitude; + float rd = ((i + noise.sample(PxVec3(angle, 0, 0))) * radialDelta + desc->radiusMin); + float x = rd * cos(angle); + float y = rd * sin(angle); + float z = 0; + points.push_back(PxVec3(x, y, z)); + } + } + float mrd = 0.0; + for (uint32_t i = 0; i < points.size(); ++i) + { + mrd = std::max(mrd, points[i].magnitude()); + } + for (uint32_t i = 0; i < points.size(); ++i) + { + points[i] *= desc->radiusMax / mrd; + } + + float ap = std::max(0.0f, desc->aperture); + + auto pattern = generateVoronoiPatternInternal((uint32_t)points.size(), points.data(), desc->interiorMaterialId, ap); + + pattern->activationRadius = desc->radiusMax * desc->debrisRadiusMult; + pattern->activationType = (ap == 0) ? DamagePattern::Line : DamagePattern::Cone; + pattern->angle = ap; + return pattern; +} + + + +void PatternGeneratorImpl::release() +{ + NVBLAST_DELETE(this, PatternGeneratorImpl); +} + +void DamagePatternImpl::release() +{ + if (cellsMeshes) + { + for (uint32_t i = 0; i < cellsCount; i++) + { + cellsMeshes[i]->release(); + } + NVBLAST_FREE(cellsMeshes); + } +#ifdef USE_MERGED_MESH + if (outputEdges) + { + NVBLAST_FREE(outputEdges); + } + if (outputEdgesCount) + { + NVBLAST_FREE(outputEdgesCount); + } + if (mergedMesh) + { + mergedMesh->release(); + } + if (preparedMergedMesh) + { + preparedMergedMesh->release(); + } + if (validFacetsForChunk) + { + for (uint32_t i = 0; i < cellsCount; i++) + { + if (validFacetsForChunk[i]) + { + NVBLAST_FREE(validFacetsForChunk[i]); + } + } + NVBLAST_FREE(validFacetsForChunk); + } +#endif + NVBLAST_DELETE(this, DamagePatternImpl); +} + + +namespace Nv +{ + namespace Blast + { + void savePatternToObj(DamagePattern* pattern) + { + FILE* fl = fopen("Pattern.obj", "w"); + + std::vector trc; + + for (uint32_t mesh = 0; mesh < pattern->cellsCount; ++mesh) + { + Mesh* m = pattern->cellsMeshes[mesh]; + + Triangulator trgl; + trgl.triangulate(m); + + auto& t = trgl.getBaseMesh(); + + for (uint32_t v = 0; v < t.size(); ++v) + { + fprintf(fl, "v %f %f %f\n", t[v].a.p.x, t[v].a.p.y, t[v].a.p.z); + fprintf(fl, "v %f %f %f\n", t[v].b.p.x, t[v].b.p.y, t[v].b.p.z); + fprintf(fl, "v %f %f %f\n", t[v].c.p.x, t[v].c.p.y, t[v].c.p.z); + } + trc.push_back(t.size()); + } + + uint32_t cv = 1; + for (uint32_t m = 0; m < trc.size(); ++m) + { + fprintf(fl, "g %d\n", m); + for (uint32_t k = 0; k < trc[m]; ++k) + { + + fprintf(fl, "f %d %d %d \n", cv, cv + 1, cv + 2); + cv += 3; + } + } + + + fclose(fl); + } + + } +} \ No newline at end of file diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringPatternGeneratorImpl.h b/sdk/extensions/authoring/source/NvBlastExtAuthoringPatternGeneratorImpl.h new file mode 100644 index 0000000..566cf71 --- /dev/null +++ b/sdk/extensions/authoring/source/NvBlastExtAuthoringPatternGeneratorImpl.h @@ -0,0 +1,58 @@ +// 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 NVBLASTEXTAUTHORINGPATTERNGENERATORIMPL_H +#define NVBLASTEXTAUTHORINGPATTERNGENERATORIMPL_H + +#include "NvBlastExtAuthoringTypes.h" +#include "NvBlastExtAuthoringPatternGenerator.h" + + +namespace Nv +{ +namespace Blast +{ + + class PatternGeneratorImpl : public PatternGenerator + { + public: + virtual DamagePattern* generateUniformPattern(const UniformPatternDesc* desc) override; + virtual DamagePattern* generateBeamPattern(const BeamPatternDesc* desc) override; + virtual DamagePattern* generateRegularRadialPattern(const RegularRadialPatternDesc* desc) override; + virtual void release() override; + + virtual DamagePattern* generateVoronoiPattern(uint32_t pointCount, const physx::PxVec3* points, int32_t interiorMaterialId) override; + private: + DamagePattern* generateVoronoiPatternInternal(uint32_t pointCount, const physx::PxVec3* points, int32_t interiorMaterialId, float angle = 0.0f); + }; + + +} // namespace Blast +} // namespace Nv + +#endif // ifndef NVBLASTEXTAUTHORINGMESHCLEANER_H \ No newline at end of file diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringTriangulator.cpp b/sdk/extensions/authoring/source/NvBlastExtAuthoringTriangulator.cpp index 89045eb..79965a1 100755 --- a/sdk/extensions/authoring/source/NvBlastExtAuthoringTriangulator.cpp +++ b/sdk/extensions/authoring/source/NvBlastExtAuthoringTriangulator.cpp @@ -534,7 +534,7 @@ void Triangulator::triangulate(const Mesh* mesh) return; } std::vector temp; - int32_t fP = mBaseMeshEdges[0].parent; + uint32_t fP = mBaseMeshEdges[0].parent; for (uint32_t i = 0; i < mBaseMeshEdges.size(); ++i) { if (fP != mBaseMeshEdges[i].parent) -- cgit v1.2.3