From 9f4fc41dc5d857e3c7c3500fc71953e54d780a39 Mon Sep 17 00:00:00 2001 From: Bryan Galdrikian Date: Tue, 17 Sep 2019 09:16:55 -0700 Subject: * NvBlastAsset::testForValidChunkOrder (used when creating an NvBlastAsset) is now more strict, requiring parent chunk descriptors to come before their children. It is still less strict than the order created by NvBlastBuildAssetDescChunkReorderMap. * Added FractureTool::setApproximateBonding function. Signals the tool to create bonds by proximity instead of just using cut plane data. * Chunks which have been merged using the uniteChunks function may be merged again * Restored chunk volume calculation * NvBlastBuildAssetDescChunkReorderMap failure cases fixed. --- .../include/NvBlastExtAuthoringFractureTool.h | 14 +++- .../authoring/source/NvBlastExtAuthoring.cpp | 29 ++++----- .../NvBlastExtAuthoringBondGeneratorImpl.cpp | 20 +++--- .../source/NvBlastExtAuthoringFractureToolImpl.cpp | 76 +++++++++++++++++++--- .../source/NvBlastExtAuthoringFractureToolImpl.h | 2 + .../source/NvBlastExtAuthoringInternalCommon.h | 42 ++++++++++++ 6 files changed, 147 insertions(+), 36 deletions(-) (limited to 'sdk/extensions') diff --git a/sdk/extensions/authoring/include/NvBlastExtAuthoringFractureTool.h b/sdk/extensions/authoring/include/NvBlastExtAuthoringFractureTool.h index 55b15f5..0798f95 100755 --- a/sdk/extensions/authoring/include/NvBlastExtAuthoringFractureTool.h +++ b/sdk/extensions/authoring/include/NvBlastExtAuthoringFractureTool.h @@ -48,8 +48,8 @@ struct ChunkInfo { enum ChunkFlags { - NO_FLAGS = 0, - CREATED_BY_ISLAND_DETECTOR = 1 + NO_FLAGS = 0, + APPROXIMATE_BONDING = 1 // Created by island splitting or chunk merge, etc. and should check for inexact bonds }; Mesh* meshData; @@ -512,7 +512,15 @@ class FractureTool const NvcVec2i* adjChunks, uint32_t adjChunksSize, bool removeOriginalChunks = false) = 0; - /** + /** + Set the APPROXIMATE_BONDING flag in the chunk's ChunkInfo + \param[in] chunkIndex chunk index - use getChunkIndex(ID) + \param[in] useApproximateBonding value of flag to set + \return true if the chunk ID is found, false otherwise + */ + virtual bool setApproximateBonding(uint32_t chunkIndex, bool useApproximateBonding) = 0; + + /** Rescale interior uv coordinates of given chunk to fit square of given size. \param[in] side Size of square side \param[in] chunkId Chunk ID for which UVs should be scaled. diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoring.cpp b/sdk/extensions/authoring/source/NvBlastExtAuthoring.cpp index a0e6fc2..b26eee3 100755 --- a/sdk/extensions/authoring/source/NvBlastExtAuthoring.cpp +++ b/sdk/extensions/authoring/source/NvBlastExtAuthoring.cpp @@ -40,6 +40,7 @@ #include "NvBlastExtAuthoringBondGeneratorImpl.h" #include "NvBlastExtAuthoringCollisionBuilderImpl.h" #include "NvBlastExtAuthoringCutoutImpl.h" +#include "NvBlastExtAuthoringInternalCommon.h" #include "NvBlastPxSharedHelpers.h" #include @@ -381,21 +382,19 @@ AuthoringResult* NvBlastExtAuthoringProcessFracture(FractureTool& fTool, BlastBo buildPhysicsChunks(collisionBuilder, aResult, collisionParam); // set NvBlastChunk volume from Px geometry - //for (uint32_t i = 0; i < chunkCount; i++) - //{ - // float totalVolume = 0.f; - // for (uint32_t k = 0; k < aResult.physicsChunks[i].subchunkCount; k++) - // { - // const auto& subChunk = aResult.physicsSubchunks[aResult.physicsChunks[i].firstSubchunkIndex + k]; - // physx::PxVec3 localCenterOfMass; physx::PxMat33 intertia; float mass; - // subChunk.geometry.convexMesh->getMassInformation(mass, intertia, localCenterOfMass); - // const physx::PxVec3 scale = subChunk.geometry.scale.scale; - // mass *= scale.x * scale.y * scale.z; - // totalVolume += mass / 1.0f; // unit density - // } - - // aResult.chunkDescs[i].volume = totalVolume; - //} + for (uint32_t i = 0; i < chunkCount; i++) + { + float totalVolume = 0.f; + for (uint32_t k = aResult.collisionHullOffset[i]; k < aResult.collisionHullOffset[i+1]; k++) + { + const CollisionHull* hull = aResult.collisionHull[k]; + if (hull) + { + totalVolume += calculateCollisionHullVolume(*hull); + } + } + aResult.chunkDescs[i].volume = totalVolume; + } // build and serialize ExtPhysicsAsset NvBlastAssetDesc descriptor; diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringBondGeneratorImpl.cpp b/sdk/extensions/authoring/source/NvBlastExtAuthoringBondGeneratorImpl.cpp index bda11e9..1fc61c2 100755 --- a/sdk/extensions/authoring/source/NvBlastExtAuthoringBondGeneratorImpl.cpp +++ b/sdk/extensions/authoring/source/NvBlastExtAuthoringBondGeneratorImpl.cpp @@ -1091,15 +1091,15 @@ int32_t BlastBondGeneratorImpl::buildDescFromInternalFracture(FractureTool* tool } - bool hasCreatedByIslands = false; + bool hasApproximateBonding = false; for (uint32_t i = 1; i < chunkCount; ++i) { NvBlastChunkDesc& desc = resultChunkDescriptors[i]; - desc.userData = i; + desc.userData = tool->getChunkId(i); desc.parentChunkIndex = tool->getChunkIndex(tool->getChunkInfo(i).parent); desc.flags = NvBlastChunkDesc::NoFlags; - hasCreatedByIslands |= (tool->getChunkInfo(i).flags & ChunkInfo::CREATED_BY_ISLAND_DETECTOR); + hasApproximateBonding |= !!(tool->getChunkInfo(i).flags & ChunkInfo::APPROXIMATE_BONDING); if (chunkIsSupport[i]) { desc.flags = NvBlastChunkDesc::SupportFlag; @@ -1246,7 +1246,7 @@ int32_t BlastBondGeneratorImpl::buildDescFromInternalFracture(FractureTool* tool } } - if (hasCreatedByIslands) + if (hasApproximateBonding) { std::vector chunkTriangles; std::vector chunkTrianglesOffsets; @@ -1262,6 +1262,7 @@ int32_t BlastBondGeneratorImpl::buildDescFromInternalFracture(FractureTool* tool pairsAlreadyCreated.insert(pr); } + const float EXPANSION = 0.01f; chunkTrianglesOffsets.push_back(0); for (uint32_t i = 0; i < chunkCount; ++i) @@ -1273,18 +1274,19 @@ int32_t BlastBondGeneratorImpl::buildDescFromInternalFracture(FractureTool* tool { 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 - } + // inflate mesh a bit + chunkTriangles.back().a.p = chunkTriangles.back().a.p + (chunkTriangles.back().a.p - centroid) * EXPANSION; + chunkTriangles.back().b.p = chunkTriangles.back().b.p + (chunkTriangles.back().b.p - centroid) * EXPANSION; + chunkTriangles.back().c.p = chunkTriangles.back().c.p + (chunkTriangles.back().c.p - centroid) * EXPANSION; + } chunkTrianglesOffsets.push_back(chunkTriangles.size()); } NvBlastBondDesc* adsc; - BondGenerationConfig cfg; cfg.bondMode = BondGenerationConfig::AVERAGE; - cfg.maxSeparation = 0.01f; + cfg.maxSeparation = EXPANSION; uint32_t nbListSize = createFullBondListAveraged(chunkCount, chunkTrianglesOffsets.data(), chunkTriangles.data(), nullptr, diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringFractureToolImpl.cpp b/sdk/extensions/authoring/source/NvBlastExtAuthoringFractureToolImpl.cpp index e4cc86f..a5cd4c1 100755 --- a/sdk/extensions/authoring/source/NvBlastExtAuthoringFractureToolImpl.cpp +++ b/sdk/extensions/authoring/source/NvBlastExtAuthoringFractureToolImpl.cpp @@ -1628,6 +1628,7 @@ bool FractureToolImpl::deleteChunkSubhierarchy(int32_t chunkId, bool deleteRoot std::swap(mChunkData.back(), mChunkData[m]); mChunkData.pop_back(); } + markLeaves(); return chunkToDelete.size() > 0; } @@ -1688,7 +1689,10 @@ void FractureToolImpl::finalizeFracturing() std::swap(mChunkData[badOnes[i]], mChunkData.back()); mChunkData.pop_back(); } - fitAllUvToRect(1.0f, newChunkMask); + if (!mChunkPostprocessors.empty()) // Failsafe to prevent infinite loop (leading to stack overflow) + { + fitAllUvToRect(1.0f, newChunkMask); + } } uint32_t FractureToolImpl::getChunkCount() const @@ -1750,13 +1754,26 @@ uint32_t FractureToolImpl::updateBaseMesh(int32_t chunkIndex, Triangle* output) float getVolume(std::vector& triangles) { + if (triangles.size() == 0) + { + return 0.0f; + } + + // Find an approximate centroid for a more accurate calculation + NvcVec3 centroid = { 0.0f, 0.0f, 0.0f }; + for (size_t i = 0; i < triangles.size(); ++i) + { + centroid = centroid + triangles[i].a.p + triangles[i].b.p + triangles[i].c.p; + } + centroid = centroid / (3 * triangles.size()); + float volume = 0.0f; - for (uint32_t i = 0; i < triangles.size(); ++i) + for (size_t i = 0; i < triangles.size(); ++i) { - NvcVec3& a = triangles[i].a.p; - NvcVec3& b = triangles[i].b.p; - NvcVec3& c = triangles[i].c.p; + const NvcVec3 a = triangles[i].a.p - centroid; + const NvcVec3 b = triangles[i].b.p - centroid; + const NvcVec3 c = triangles[i].c.p - centroid; 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); } @@ -1988,19 +2005,19 @@ int32_t FractureToolImpl::islandDetectionAndRemoving(int32_t chunkId, bool creat } else { - mChunkData[chunkIndex].isLeaf = false; deleteChunkSubhierarchy(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].flags = ChunkInfo::APPROXIMATE_BONDING; 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())); } - } + mChunkData[chunkIndex].isLeaf = false; + } return cComp; } return 0; @@ -2110,7 +2127,12 @@ uint32_t FractureToolImpl::stretchGroup(const std::vector& grp, std::v } offsetEdges = nEdges.size(); offsetVertices = nVertices.size(); - } + + if (mChunkData[grp[i]].flags & ChunkInfo::APPROXIMATE_BONDING) + { + mChunkData[newChunkIndex].flags |= ChunkInfo::APPROXIMATE_BONDING; + } + } std::vector finalFacets; std::set hasCutting; for (uint32_t i = 0; i < nFacets.size(); ++i) @@ -2129,6 +2151,7 @@ uint32_t FractureToolImpl::stretchGroup(const std::vector& grp, std::v mChunkData[newChunkIndex].meshData = new MeshImpl(nVertices.data(), nEdges.data(), finalFacets.data(), static_cast(nVertices.size()), static_cast(nEdges.size()), static_cast(finalFacets.size())); + return newChunkIndex; } @@ -2254,6 +2277,22 @@ void FractureToolImpl::fitAllUvToRect(float side, std::set& mask) } } +void FractureToolImpl::markLeaves() +{ + for (ChunkInfo& info : mChunkData) + { + info.isLeaf = true; + } + + for (ChunkInfo& info : mChunkData) + { + const int32_t index = getChunkIndex(info.parent); + if (index >= 0) + { + mChunkData[index].isLeaf = false; + } + } +} void FractureToolImpl::rebuildAdjGraph(const std::vector& chunks, const NvcVec2i* adjChunks, uint32_t adjChunksSize, std::vector >& chunkGraph) @@ -2570,5 +2609,24 @@ void FractureToolImpl::uniteChunks(uint32_t threshold, uint32_t targetClusterSiz } } +bool FractureToolImpl::setApproximateBonding(uint32_t chunkIndex, bool useApproximateBonding) +{ + if ((size_t)chunkIndex >= mChunkData.size()) + { + return false; + } + + if (useApproximateBonding) + { + mChunkData[chunkIndex].flags |= (uint32_t)ChunkInfo::APPROXIMATE_BONDING; + } + else + { + mChunkData[chunkIndex].flags &= ~(uint32_t)ChunkInfo::APPROXIMATE_BONDING; + } + + return true; +} + } // namespace Blast } // namespace Nv diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringFractureToolImpl.h b/sdk/extensions/authoring/source/NvBlastExtAuthoringFractureToolImpl.h index 9e4d41e..153e43c 100755 --- a/sdk/extensions/authoring/source/NvBlastExtAuthoringFractureToolImpl.h +++ b/sdk/extensions/authoring/source/NvBlastExtAuthoringFractureToolImpl.h @@ -380,6 +380,7 @@ public: const NvcVec2i* adjChunks, uint32_t adjChunksSize, bool removeOriginalChunks = false) override; + bool setApproximateBonding(uint32_t chunkId, bool useApproximateBonding) override; /** Rescale interior uv coordinates of given chunk to fit square of given size. @@ -403,6 +404,7 @@ private: void rebuildAdjGraph(const std::vector& chunksToRebuild, const NvcVec2i* adjChunks, uint32_t adjChunksSize, std::vector >& chunkGraph); void fitAllUvToRect(float side, std::set& mask); + void markLeaves(); /** Returns newly created chunk index in mChunkData. diff --git a/sdk/extensions/authoringCommon/source/NvBlastExtAuthoringInternalCommon.h b/sdk/extensions/authoringCommon/source/NvBlastExtAuthoringInternalCommon.h index 4a0fbd0..79bbe3a 100644 --- a/sdk/extensions/authoringCommon/source/NvBlastExtAuthoringInternalCommon.h +++ b/sdk/extensions/authoringCommon/source/NvBlastExtAuthoringInternalCommon.h @@ -29,6 +29,7 @@ #ifndef NVBLASTINTERNALCOMMON_H #define NVBLASTINTERNALCOMMON_H #include "NvBlastExtAuthoringTypes.h" +#include "NvBlastPxSharedHelpers.h" #include #include #include @@ -275,6 +276,47 @@ struct VrtPositionComparator }; }; + +NV_INLINE float calculateCollisionHullVolume(const CollisionHull& hull) +{ + if (hull.pointsCount == 0) + { + return 0.0f; + } + + // Find an approximate centroid for a more accurate calculation + NvcVec3 centroid = { 0.0f, 0.0f, 0.0f }; + for (uint32_t i = 0; i < hull.pointsCount; ++i) + { + centroid = centroid + hull.points[i]; + } + centroid = centroid / hull.pointsCount; + + float volume = 0.0f; + + for (uint32_t i = 0; i < hull.polygonDataCount; ++i) + { + const HullPolygon& poly = hull.polygonData[i]; + if (poly.vertexCount < 3) + { + continue; + } + const uint32_t i0 = hull.indices[poly.indexBase]; + uint32_t i1 = hull.indices[poly.indexBase + 1]; + for (uint32_t j = 2; j < poly.vertexCount; ++j) + { + const uint32_t i2 = hull.indices[poly.indexBase + j]; + const NvcVec3 a = hull.points[i0] - centroid; + const NvcVec3 b = hull.points[i1] - centroid; + const NvcVec3 c = hull.points[i2] - centroid; + 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); + i1 = i2; + } + } + return (1.0f / 6.0f) * std::abs(volume); +} + } // namespace Blast } // namespace Nv -- cgit v1.2.3