aboutsummaryrefslogtreecommitdiff
path: root/sdk/extensions/authoring/source/NvBlastExtAuthoring.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'sdk/extensions/authoring/source/NvBlastExtAuthoring.cpp')
-rw-r--r--sdk/extensions/authoring/source/NvBlastExtAuthoring.cpp258
1 files changed, 232 insertions, 26 deletions
diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoring.cpp b/sdk/extensions/authoring/source/NvBlastExtAuthoring.cpp
index 787cb6b..b024bb7 100644
--- a/sdk/extensions/authoring/source/NvBlastExtAuthoring.cpp
+++ b/sdk/extensions/authoring/source/NvBlastExtAuthoring.cpp
@@ -19,6 +19,7 @@
#include "NvBlast.h"
#include "NvBlastGlobals.h"
#include "NvBlastExtPxAsset.h"
+#include "NvBlastExtAssetUtils.h"
#include <algorithm>
#include <memory>
@@ -26,8 +27,8 @@
using namespace Nv::Blast;
using namespace physx;
-#define SAFE_ARRAY_NEW(T, x) ((x) > 0) ? new T[x] : nullptr;
-#define SAFE_ARRAY_DELETE(x) if (x != nullptr) {delete[] x; x = nullptr;}
+#define SAFE_ARRAY_NEW(T, x) ((x) > 0) ? reinterpret_cast<T*>(NVBLAST_ALLOC(sizeof(T) * (x))) : nullptr;
+#define SAFE_ARRAY_DELETE(x) if (x != nullptr) {NVBLAST_FREE(x); x = nullptr;}
Mesh* NvBlastExtAuthoringCreateMesh(const PxVec3* position, const PxVec3* normals, const PxVec2* uv, uint32_t verticesCount, const uint32_t* indices, uint32_t indicesCount)
{
@@ -59,34 +60,139 @@ ConvexMeshBuilder* NvBlastExtAuthoringCreateConvexMeshBuilder(PxCooking* cooking
return new ConvexMeshBuilderImpl(cooking, insertionCallback);
}
-void buildPhysicsChunks(ConvexMeshBuilder& collisionBuilder, AuthoringResult& result)
+
+void NvBlastExtAuthoringTransformCollisionHullInPlace(CollisionHull* hull, const physx::PxVec3* scaling, const physx::PxQuat* rotation, const physx::PxVec3* translation)
+{
+ // Local copies of scaling (S), rotation (R), and translation (T)
+ physx::PxVec3 S = { 1, 1, 1 };
+ physx::PxQuat R = { 0, 0, 0, 1 };
+ physx::PxVec3 T = { 0, 0, 0 };
+ physx::PxVec3 cofS = { 1, 1, 1 };
+ float sgnDetS = 1;
+
+ {
+ if (rotation)
+ {
+ R = *rotation;
+ }
+
+ if (scaling)
+ {
+ S = *scaling;
+ cofS.x = S.y * S.z;
+ cofS.y = S.z * S.x;
+ cofS.z = S.x * S.y;
+ sgnDetS = (S.x * S.y * S.z < 0) ? -1 : 1;
+ }
+
+ if (translation)
+ {
+ T = *translation;
+ }
+ }
+
+ const uint32_t pointCount = hull->pointsCount;
+ for (uint32_t pi = 0; pi < pointCount; pi++)
+ {
+ physx::PxVec3& p = hull->points[pi];
+ p = (R.rotate(p.multiply(S)) + T);
+ }
+
+ const uint32_t planeCount = hull->polygonDataCount;
+ for (uint32_t pi = 0; pi < planeCount; pi++)
+ {
+ float* plane = hull->polygonData[pi].mPlane;
+ physx::PxPlane pxPlane(plane[0], plane[1], plane[2], plane[3]);
+ PxVec3 transformedNormal = sgnDetS*R.rotate(pxPlane.n.multiply(cofS)).getNormalized();
+ PxVec3 transformedPt = R.rotate(pxPlane.pointInPlane().multiply(S)) + T;
+
+ physx::PxPlane transformedPlane(transformedPt, transformedNormal);
+ plane[0] = transformedPlane.n[0];
+ plane[1] = transformedPlane.n[1];
+ plane[2] = transformedPlane.n[2];
+ plane[3] = transformedPlane.d;
+ }
+}
+
+
+CollisionHull* NvBlastExtAuthoringTransformCollisionHull(const CollisionHull* hull, const physx::PxVec3* scaling, const physx::PxQuat* rotation, const physx::PxVec3* translation)
+{
+ CollisionHullImpl* ret = new CollisionHullImpl(*hull);
+ NvBlastExtAuthoringTransformCollisionHullInPlace(ret, scaling, rotation, translation);
+ return ret;
+}
+
+void buildPhysicsChunks(ConvexMeshBuilder& collisionBuilder, AuthoringResult& result, const CollisionParams& params)
{
uint32_t chunkCount = (uint32_t)result.chunkCount;
- result.collisionHullOffset = SAFE_ARRAY_NEW(uint32_t, chunkCount + 1);
- result.collisionHullOffset[0] = 0;
- result.collisionHull = SAFE_ARRAY_NEW(CollisionHull*, chunkCount);
- result.physicsSubchunks = SAFE_ARRAY_NEW(ExtPxSubchunk, chunkCount);
- result.physicsChunks = SAFE_ARRAY_NEW(ExtPxChunk, chunkCount);
- for (uint32_t i = 0; i < chunkCount; ++i)
+ if (params.maximumNumberOfHulls == 1)
{
- std::vector<physx::PxVec3> vertices;
- for (uint32_t p = result.geometryOffset[i]; p < result.geometryOffset[i+1]; ++p)
+ result.collisionHullOffset = SAFE_ARRAY_NEW(uint32_t, chunkCount + 1);
+ result.collisionHullOffset[0] = 0;
+ result.collisionHull = SAFE_ARRAY_NEW(CollisionHull*, chunkCount);
+ result.physicsSubchunks = SAFE_ARRAY_NEW(ExtPxSubchunk, chunkCount);
+ result.physicsChunks = SAFE_ARRAY_NEW(ExtPxChunk, chunkCount);
+ for (uint32_t i = 0; i < chunkCount; ++i)
{
- Nv::Blast::Triangle& tri = result.geometry[p];
- vertices.push_back(tri.a.p);
- vertices.push_back(tri.b.p);
- vertices.push_back(tri.c.p);
+ std::vector<physx::PxVec3> vertices;
+ for (uint32_t p = result.geometryOffset[i]; p < result.geometryOffset[i + 1]; ++p)
+ {
+ Nv::Blast::Triangle& tri = result.geometry[p];
+ vertices.push_back(tri.a.p);
+ vertices.push_back(tri.b.p);
+ vertices.push_back(tri.c.p);
+ }
+ result.collisionHullOffset[i + 1] = result.collisionHullOffset[i] + 1;
+ result.collisionHull[i] = collisionBuilder.buildCollisionGeometry((uint32_t)vertices.size(), vertices.data());
+ result.physicsSubchunks[i].transform = physx::PxTransform(physx::PxIdentity);
+ result.physicsSubchunks[i].geometry = physx::PxConvexMeshGeometry(collisionBuilder.buildConvexMesh(*result.collisionHull[i]));
+
+ result.physicsChunks[i].isStatic = false;
+ result.physicsChunks[i].subchunkCount = 1;
+ result.physicsChunks[i].firstSubchunkIndex = i;
+ //outPhysicsChunks.get()[i].subchunks = &outPhysicsSubchunks[i];
}
+ }
+ else
+ {
+ std::vector<std::vector<CollisionHull*> > hulls(chunkCount);
+ int32_t totalHulls = 0;
+ for (uint32_t i = 0; i < chunkCount; ++i)
+ {
+ CollisionHull** tempHull;
- result.collisionHullOffset[i + 1] = result.collisionHullOffset[i] + 1;
- result.collisionHull[i] = collisionBuilder.buildCollisionGeometry((uint32_t)vertices.size(), vertices.data());
- result.physicsSubchunks[i].transform = physx::PxTransform(physx::PxIdentity);
- result.physicsSubchunks[i].geometry = physx::PxConvexMeshGeometry(collisionBuilder.buildConvexMesh(*result.collisionHull[i]));
+ int32_t newHulls = collisionBuilder.buildMeshConvexDecomposition(result.geometry + result.geometryOffset[i],
+ result.geometryOffset[i + 1] - result.geometryOffset[i], params, tempHull);
+ totalHulls += newHulls;
+ for (int32_t h = 0; h < newHulls; ++h)
+ {
+ hulls[i].push_back(tempHull[h]);
+ }
+ SAFE_ARRAY_DELETE(tempHull);
+ }
- result.physicsChunks[i].isStatic = false;
- result.physicsChunks[i].subchunkCount = 1;
- result.physicsChunks[i].firstSubchunkIndex = i;
- //outPhysicsChunks.get()[i].subchunks = &outPhysicsSubchunks[i];
+ result.collisionHullOffset = SAFE_ARRAY_NEW(uint32_t, chunkCount + 1);
+ result.collisionHullOffset[0] = 0;
+ result.collisionHull = SAFE_ARRAY_NEW(CollisionHull*, totalHulls);
+ result.physicsSubchunks = SAFE_ARRAY_NEW(ExtPxSubchunk, totalHulls);
+ result.physicsChunks = SAFE_ARRAY_NEW(ExtPxChunk, chunkCount);
+
+ int32_t firstSubchunk = 0;
+ for (uint32_t i = 0; i < chunkCount; ++i)
+ {
+ result.collisionHullOffset[i + 1] = result.collisionHullOffset[i] + hulls[i].size();
+ int32_t off = result.collisionHullOffset[i];
+ for (uint32_t subhull = 0; subhull < hulls[i].size(); ++subhull)
+ {
+ result.collisionHull[off + subhull] = hulls[i][subhull];
+ result.physicsSubchunks[firstSubchunk + subhull].transform = physx::PxTransform(physx::PxIdentity);
+ result.physicsSubchunks[firstSubchunk + subhull].geometry = physx::PxConvexMeshGeometry(collisionBuilder.buildConvexMesh(*hulls[i][subhull]));
+ }
+ result.physicsChunks[i].isStatic = false;
+ result.physicsChunks[i].subchunkCount = static_cast<uint32_t>(hulls[i].size());
+ result.physicsChunks[i].firstSubchunkIndex = firstSubchunk;
+ firstSubchunk += result.physicsChunks[i].subchunkCount;
+ }
}
}
@@ -121,7 +227,7 @@ struct AuthoringResultImpl : public AuthoringResult
}
};
-AuthoringResult* NvBlastExtAuthoringProcessFracture(FractureTool& fTool, BlastBondGenerator& bondGenerator, ConvexMeshBuilder& collisionBuilder, int32_t defaultSupportDepth)
+AuthoringResult* NvBlastExtAuthoringProcessFracture(FractureTool& fTool, BlastBondGenerator& bondGenerator, ConvexMeshBuilder& collisionBuilder, const CollisionParams& collisionParam, int32_t defaultSupportDepth)
{
fTool.finalizeFracturing();
const uint32_t chunkCount = fTool.getChunkCount();
@@ -220,7 +326,7 @@ AuthoringResult* NvBlastExtAuthoringProcessFracture(FractureTool& fTool, BlastBo
//std::cout << "MAX: " << maxX << ", " << maxY << ", " << maxZ << std::endl;
// prepare physics data (convexes)
- buildPhysicsChunks(collisionBuilder, aResult);
+ buildPhysicsChunks(collisionBuilder, aResult, collisionParam);
// set NvBlastChunk volume from Px geometry
for (uint32_t i = 0; i < chunkCount; i++)
@@ -259,4 +365,104 @@ AuthoringResult* NvBlastExtAuthoringProcessFracture(FractureTool& fTool, BlastBo
ret->materialCount = 0;
ret->materialNames = nullptr;
return ret;
-} \ No newline at end of file
+}
+
+uint32_t NvBlastExtAuthoringFindAssetConnectingBonds
+(
+ const NvBlastAsset** components,
+ const physx::PxVec3* scales,
+ const physx::PxQuat* rotations,
+ const physx::PxVec3* translations,
+ const uint32_t** convexHullOffsets,
+ const CollisionHull*** chunkHulls,
+ uint32_t componentCount,
+ NvBlastExtAssetUtilsBondDesc*& newBondDescs
+)
+{
+ //We don't need to use any of the cooking related parts of this
+ BlastBondGeneratorImpl bondGenerator(nullptr, nullptr);
+
+ std::vector<uint32_t> componentChunkOffsets;
+ componentChunkOffsets.reserve(componentCount + 1);
+ componentChunkOffsets.push_back(0);
+
+ std::vector<uint32_t> combinedConvexHullOffsets;
+ std::vector<const CollisionHull*> combinedConvexHulls;
+ std::vector<CollisionHull*> hullsToRelease;
+ combinedConvexHullOffsets.push_back(0);
+
+ std::vector<uint32_t> originalComponentIndex;
+
+ const physx::PxVec3 identityScale(1);
+
+ //Combine our hull lists into a single combined list for bondsFromPrefractured
+ for (uint32_t c = 0; c < componentCount; c++)
+ {
+ const uint32_t chunkCount = NvBlastAssetGetChunkCount(components[c], &logLL);
+ const physx::PxVec3* scale = scales ? scales + c : nullptr;
+ const physx::PxQuat* rotation = rotations ? rotations + c : nullptr;
+ const physx::PxVec3* translation = translations ? translations + c : nullptr;
+
+ componentChunkOffsets.push_back(chunkCount + componentChunkOffsets.back());
+ for (uint32_t chunk = 0; chunk < chunkCount; chunk++)
+ {
+ const uint32_t hullsStart = convexHullOffsets[c][chunk];
+ const uint32_t hullsEnd = convexHullOffsets[c][chunk + 1];
+ for (uint32_t hull = hullsStart; hull < hullsEnd; hull++)
+ {
+ if ((scale != nullptr && *scale != identityScale) || (rotation != nullptr && !rotation->isIdentity()) || (translation != nullptr && !translation->isZero()))
+ {
+ hullsToRelease.emplace_back(NvBlastExtAuthoringTransformCollisionHull(chunkHulls[c][hull], scale, rotation, translation));
+ combinedConvexHulls.emplace_back(hullsToRelease.back());
+ }
+ else
+ {
+ //No need to transform
+ combinedConvexHulls.emplace_back(chunkHulls[c][hull]);
+ }
+ }
+ combinedConvexHullOffsets.push_back((hullsEnd - hullsStart) + combinedConvexHullOffsets.back());
+ originalComponentIndex.push_back(c);
+ }
+ }
+ const uint32_t totalChunkCount = componentChunkOffsets.back();
+ //Can't use std::vector<bool> since we need a bool* later
+ std::unique_ptr<bool[]> isSupportChunk(new bool[totalChunkCount]);
+ for (uint32_t c = 0; c < componentCount; c++)
+ {
+ const uint32_t chunkCount = componentChunkOffsets[c + 1] - componentChunkOffsets[c];
+ NvBlastSupportGraph supportGraph = NvBlastAssetGetSupportGraph(components[c], &logLL);
+ for (uint32_t chunk = 0; chunk < chunkCount; chunk++)
+ {
+ auto chunkIndiciesEnd = supportGraph.chunkIndices + supportGraph.nodeCount;
+ isSupportChunk[chunk + componentChunkOffsets[c]] = (std::find(supportGraph.chunkIndices, chunkIndiciesEnd, chunk) != chunkIndiciesEnd);
+ }
+ }
+
+ //Find the bonds
+ NvBlastBondDesc* newBonds = nullptr;
+ const int32_t newBoundCount = bondGenerator.bondsFromPrefractured(totalChunkCount, combinedConvexHullOffsets.data(), combinedConvexHulls.data(), isSupportChunk.get(), originalComponentIndex.data(), newBonds);
+
+ //Convert the bonds back to per-component chunks
+ newBondDescs = SAFE_ARRAY_NEW(NvBlastExtAssetUtilsBondDesc, newBoundCount);
+ for (int32_t nb = 0; nb < newBoundCount; ++nb)
+ {
+ newBondDescs[nb].bond = newBonds[nb].bond;
+ for (uint32_t ci = 0; ci < 2; ++ci)
+ {
+ uint32_t absChunkIdx = newBonds[nb].chunkIndices[ci];
+ uint32_t componentIdx = originalComponentIndex[absChunkIdx];
+ newBondDescs[nb].componentIndices[ci] = componentIdx;
+ newBondDescs[nb].chunkIndices[ci] = absChunkIdx - componentChunkOffsets[componentIdx];
+ }
+ }
+ //Don't need this anymore
+ NVBLAST_FREE(newBonds);
+
+ for (CollisionHull* hull : hullsToRelease)
+ {
+ hull->release();
+ }
+
+ return newBoundCount;
+}