aboutsummaryrefslogtreecommitdiff
path: root/sdk/extensions
diff options
context:
space:
mode:
Diffstat (limited to 'sdk/extensions')
-rw-r--r--sdk/extensions/authoring/include/NvBlastExtAuthoringFractureTool.h17
-rw-r--r--sdk/extensions/authoring/include/NvBlastExtAuthoringMesh.h9
-rw-r--r--sdk/extensions/authoring/include/NvBlastExtAuthoringTypes.h2
-rw-r--r--sdk/extensions/authoring/source/NvBlastExtAuthoringCollisionBuilderImpl.cpp25
-rw-r--r--sdk/extensions/authoring/source/NvBlastExtAuthoringFractureToolImpl.cpp43
-rw-r--r--sdk/extensions/authoring/source/NvBlastExtAuthoringFractureToolImpl.h16
-rw-r--r--sdk/extensions/authoring/source/NvBlastExtAuthoringMeshImpl.cpp66
-rw-r--r--sdk/extensions/authoring/source/NvBlastExtAuthoringMeshImpl.h15
-rw-r--r--sdk/extensions/exporter/include/NvBlastExtExporter.h8
-rw-r--r--sdk/extensions/exporter/source/NvBlastExtExporterFbxReader.cpp282
-rw-r--r--sdk/extensions/exporter/source/NvBlastExtExporterFbxReader.h94
-rw-r--r--sdk/extensions/exporter/source/NvBlastExtExporterFbxUtils.cpp34
-rw-r--r--sdk/extensions/exporter/source/NvBlastExtExporterFbxUtils.h4
-rw-r--r--sdk/extensions/exporter/source/NvBlastExtExporterFbxWriter.cpp10
-rw-r--r--sdk/extensions/exporter/source/NvBlastExtExporterObjReader.cpp7
-rw-r--r--sdk/extensions/exporter/source/NvBlastExtExporterObjReader.h6
-rw-r--r--sdk/extensions/physx/include/NvBlastExtImpactDamageManager.h20
-rw-r--r--sdk/extensions/physx/source/physics/NvBlastExtImpactDamageManager.cpp35
-rw-r--r--sdk/extensions/physx/source/physics/NvBlastExtPxActorImpl.cpp7
-rw-r--r--sdk/extensions/physx/source/physics/NvBlastExtPxActorImpl.h5
-rw-r--r--sdk/extensions/physx/source/physics/NvBlastExtPxFamilyImpl.cpp12
-rw-r--r--sdk/extensions/serialization/source/NvBlastExtPxSerializerRAW.cpp1
22 files changed, 500 insertions, 218 deletions
diff --git a/sdk/extensions/authoring/include/NvBlastExtAuthoringFractureTool.h b/sdk/extensions/authoring/include/NvBlastExtAuthoringFractureTool.h
index e6a6d41..9cdb6c2 100644
--- a/sdk/extensions/authoring/include/NvBlastExtAuthoringFractureTool.h
+++ b/sdk/extensions/authoring/include/NvBlastExtAuthoringFractureTool.h
@@ -199,11 +199,26 @@ public:
/**
- Set input mesh wich will be fractured, FractureTool will be reseted.
+ Set input mesh which will be fractured, FractureTool will be reseted.
*/
virtual void setSourceMesh(const Mesh* mesh) = 0;
/**
+ Set the material id to use for new interior faces. Defaults to MATERIAL_INTERIOR
+ */
+ virtual void setInteriorMaterialId(int32_t materialId) = 0;
+
+ /**
+ Gets the material id to use for new interior faces
+ */
+ virtual int32_t getInteriorMaterialId() const = 0;
+
+ /**
+ Replaces an material id on faces with a new one
+ */
+ virtual void replaceMaterialId(int32_t oldMaterialId, int32_t newMaterialId) = 0;
+
+ /**
Get chunk mesh in polygonal representation. User's code should release it after usage.
*/
virtual Mesh* createChunkMesh(int32_t chunkId) = 0;
diff --git a/sdk/extensions/authoring/include/NvBlastExtAuthoringMesh.h b/sdk/extensions/authoring/include/NvBlastExtAuthoringMesh.h
index 039da52..3e65a48 100644
--- a/sdk/extensions/authoring/include/NvBlastExtAuthoringMesh.h
+++ b/sdk/extensions/authoring/include/NvBlastExtAuthoringMesh.h
@@ -123,12 +123,17 @@ public:
/**
Set per-facet material id.
*/
- virtual void setMaterialId(int32_t* materialIds) = 0;
+ virtual void setMaterialId(const int32_t* materialIds) = 0;
+
+ /**
+ Replaces an material id on faces with a new one
+ */
+ virtual void replaceMaterialId(int32_t oldMaterialId, int32_t newMaterialId) = 0;
/**
Set per-facet smoothing group.
*/
- virtual void setSmoothingGroup(int32_t* smoothingGroup) = 0;
+ virtual void setSmoothingGroup(const int32_t* smoothingGroups) = 0;
/**
Recalculate bounding box
diff --git a/sdk/extensions/authoring/include/NvBlastExtAuthoringTypes.h b/sdk/extensions/authoring/include/NvBlastExtAuthoringTypes.h
index 3c0675c..833798a 100644
--- a/sdk/extensions/authoring/include/NvBlastExtAuthoringTypes.h
+++ b/sdk/extensions/authoring/include/NvBlastExtAuthoringTypes.h
@@ -250,7 +250,7 @@ struct AuthoringResult
/**
Array of material names.
*/
- char** materialNames;
+ const char** materialNames;
/**
Size of array of material names.
*/
diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringCollisionBuilderImpl.cpp b/sdk/extensions/authoring/source/NvBlastExtAuthoringCollisionBuilderImpl.cpp
index 39c7586..ddfa668 100644
--- a/sdk/extensions/authoring/source/NvBlastExtAuthoringCollisionBuilderImpl.cpp
+++ b/sdk/extensions/authoring/source/NvBlastExtAuthoringCollisionBuilderImpl.cpp
@@ -239,7 +239,8 @@ void ConvexMeshBuilderImpl::trimCollisionGeometry(uint32_t chunksCount, Collisio
}
Mesh* hullMesh = new MeshImpl(vertices.data(), edges.data(), facets.data(), vertices.size(), edges.size(), facets.size());
BooleanEvaluator evl;
- Mesh* cuttingMesh = getCuttingBox(PxVec3(0, 0, 0), PxVec3(0, 0, 1), 40, 0);
+ //I think the material ID is unused for collision meshes so harcoding MATERIAL_INTERIOR is ok
+ Mesh* cuttingMesh = getCuttingBox(PxVec3(0, 0, 0), PxVec3(0, 0, 1), 40, 0, MATERIAL_INTERIOR);
for (uint32_t p = 0; p < chunkMidplanes[i].size(); ++p)
{
PxPlane& pl = chunkMidplanes[i][p];
@@ -277,27 +278,19 @@ void ConvexMeshBuilderImpl::trimCollisionGeometry(uint32_t chunksCount, Collisio
PxConvexMesh* ConvexMeshBuilderImpl::buildConvexMesh(uint32_t verticesCount, const physx::PxVec3* vertexData)
{
CollisionHull* hull = buildCollisionGeometry(verticesCount, vertexData);
-
- PxConvexMeshDesc convexMeshDescr;
- convexMeshDescr.indices.data = hull->indices;
- convexMeshDescr.indices.count = (uint32_t)hull->indicesCount;
- convexMeshDescr.indices.stride = sizeof(uint32_t);
-
- convexMeshDescr.points.data = hull->points;
- convexMeshDescr.points.count = (uint32_t)hull->pointsCount;
- convexMeshDescr.points.stride = sizeof(PxVec3);
-
- convexMeshDescr.polygons.data = hull->polygonData;
- convexMeshDescr.polygons.count = (uint32_t)hull->polygonDataCount;
- convexMeshDescr.polygons.stride = sizeof(PxHullPolygon);
-
- PxConvexMesh* convexMesh = mCooking->createConvexMesh(convexMeshDescr, *mInsertionCallback);
+ PxConvexMesh* convexMesh = buildConvexMesh(*hull);
hull->release();
return convexMesh;
}
PxConvexMesh* ConvexMeshBuilderImpl::buildConvexMesh(const CollisionHull& hull)
{
+ /* PxCooking::createConvexMesh expects PxHullPolygon input, which matches CollisionHull::HullPolygon */
+ static_assert(sizeof(PxHullPolygon) == sizeof(CollisionHull::HullPolygon), "CollisionHull::HullPolygon size mismatch");
+ static_assert(offsetof(PxHullPolygon, mPlane) == offsetof(CollisionHull::HullPolygon, mPlane), "CollisionHull::HullPolygon layout mismatch");
+ static_assert(offsetof(PxHullPolygon, mNbVerts) == offsetof(CollisionHull::HullPolygon, mNbVerts), "CollisionHull::HullPolygon layout mismatch");
+ static_assert(offsetof(PxHullPolygon, mIndexBase) == offsetof(CollisionHull::HullPolygon, mIndexBase), "CollisionHull::HullPolygon layout mismatch");
+
PxConvexMeshDesc convexMeshDescr;
convexMeshDescr.indices.data = hull.indices;
convexMeshDescr.indices.count = (uint32_t)hull.indicesCount;
diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringFractureToolImpl.cpp b/sdk/extensions/authoring/source/NvBlastExtAuthoringFractureToolImpl.cpp
index 8378ef0..666361c 100644
--- a/sdk/extensions/authoring/source/NvBlastExtAuthoringFractureToolImpl.cpp
+++ b/sdk/extensions/authoring/source/NvBlastExtAuthoringFractureToolImpl.cpp
@@ -100,10 +100,10 @@ void findCellBasePlanes(const std::vector<PxVec3>& sites, std::vector<std::vecto
#define SITE_BOX_SIZE 4
#define CUTTING_BOX_SIZE 40
-Mesh* getCellMesh(BooleanEvaluator& eval, int32_t planeIndexerOffset, int32_t cellId, const std::vector<PxVec3>& sites, std::vector < std::vector<int32_t> >& neighboors)
+Mesh* getCellMesh(BooleanEvaluator& eval, int32_t planeIndexerOffset, int32_t cellId, const std::vector<PxVec3>& sites, std::vector < std::vector<int32_t> >& neighboors, int32_t interiorMaterialId)
{
- Mesh* cell = getBigBox(sites[cellId], SITE_BOX_SIZE);
- Mesh* cuttingMesh = getCuttingBox(PxVec3(0, 0, 0), PxVec3(1, 1, 1), CUTTING_BOX_SIZE, 0);
+ Mesh* cell = getBigBox(sites[cellId], 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)
{
@@ -406,7 +406,7 @@ int32_t FractureToolImpl::voronoiFracturing(uint32_t chunkId, uint32_t cellCount
std::vector<uint32_t> newlyCreatedChunksIds;
for (uint32_t i = 0; i < cellPoints.size(); ++i)
{
- Mesh* cell = getCellMesh(eval, mPlaneIndexerOffset, i, cellPoints, neighboors);
+ Mesh* cell = getCellMesh(eval, mPlaneIndexerOffset, i, cellPoints, neighboors, mInteriorMaterialId);
if (cell == nullptr)
{
@@ -576,7 +576,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);
+ Mesh* cell = getCellMesh(eval, mPlaneIndexerOffset, i, cellPoints, neighboors, mInteriorMaterialId);
if (cell == nullptr)
{
@@ -670,7 +670,7 @@ int32_t FractureToolImpl::slicing(uint32_t chunkId, SlicingConfiguration conf, b
PxVec3 dir(1, 0, 0);
- Mesh* slBox = getCuttingBox(center, dir, 20, 0);
+ Mesh* slBox = getCuttingBox(center, dir, 20, 0, mInteriorMaterialId);
ChunkInfo ch;
ch.isLeaf = true;
@@ -871,7 +871,7 @@ int32_t FractureToolImpl::slicingNoisy(uint32_t chunkId, SlicingConfiguration co
{
PxVec3 randVect = PxVec3(2 * rnd->getRandomValue() - 1, 2 * rnd->getRandomValue() - 1, 2 * rnd->getRandomValue() - 1);
PxVec3 lDir = dir + randVect * conf.angle_variations;
- slBox = getNoisyCuttingBoxPair(center, lDir, 40, noisyPartSize, conf.surfaceResolution, mPlaneIndexerOffset, conf.noiseAmplitude, conf.noiseFrequency, conf.noiseOctaveNumber, rnd->getRandomValue());
+ slBox = getNoisyCuttingBoxPair(center, lDir, 40, noisyPartSize, conf.surfaceResolution, mPlaneIndexerOffset, conf.noiseAmplitude, conf.noiseFrequency, conf.noiseOctaveNumber, rnd->getRandomValue(), mInteriorMaterialId);
// DummyAccelerator accel(mesh->getFacetCount());
IntersectionTestingAccelerator accel(mesh, acceleratorRes);
DummyAccelerator dummy(slBox->getFacetCount());
@@ -899,7 +899,7 @@ int32_t FractureToolImpl::slicingNoisy(uint32_t chunkId, SlicingConfiguration co
ch.meshData = mesh;
xSlicedChunks.push_back(ch);
}
- slBox = getCuttingBox(center, dir, 20, 0);
+ slBox = getCuttingBox(center, dir, 20, 0, mInteriorMaterialId);
uint32_t slicedChunkSize = xSlicedChunks.size();
for (uint32_t chunk = 0; chunk < slicedChunkSize; ++chunk)
{
@@ -913,7 +913,7 @@ int32_t FractureToolImpl::slicingNoisy(uint32_t chunkId, SlicingConfiguration co
PxVec3 randVect = PxVec3(2 * rnd->getRandomValue() - 1, 2 * rnd->getRandomValue() - 1, 2 * rnd->getRandomValue() - 1);
PxVec3 lDir = dir + randVect * conf.angle_variations;
- slBox = getNoisyCuttingBoxPair(center, lDir, 40, noisyPartSize, conf.surfaceResolution, mPlaneIndexerOffset, conf.noiseAmplitude, conf.noiseFrequency, conf.noiseOctaveNumber, rnd->getRandomValue());
+ slBox = getNoisyCuttingBoxPair(center, lDir, 40, noisyPartSize, conf.surfaceResolution, mPlaneIndexerOffset, conf.noiseAmplitude, conf.noiseFrequency, conf.noiseOctaveNumber, rnd->getRandomValue(), mInteriorMaterialId);
// DummyAccelerator accel(mesh->getFacetCount());
IntersectionTestingAccelerator accel(mesh, acceleratorRes);
DummyAccelerator dummy(slBox->getFacetCount());
@@ -954,7 +954,7 @@ int32_t FractureToolImpl::slicingNoisy(uint32_t chunkId, SlicingConfiguration co
{
PxVec3 randVect = PxVec3(2 * rnd->getRandomValue() - 1, 2 * rnd->getRandomValue() - 1, 2 * rnd->getRandomValue() - 1);
PxVec3 lDir = dir + randVect * conf.angle_variations;
- slBox = getNoisyCuttingBoxPair(center, lDir, 40, noisyPartSize, conf.surfaceResolution, mPlaneIndexerOffset, conf.noiseAmplitude, conf.noiseFrequency, conf.noiseOctaveNumber, rnd->getRandomValue());
+ slBox = getNoisyCuttingBoxPair(center, lDir, 40, noisyPartSize, conf.surfaceResolution, mPlaneIndexerOffset, conf.noiseAmplitude, conf.noiseFrequency, conf.noiseOctaveNumber, rnd->getRandomValue(), mInteriorMaterialId);
// DummyAccelerator accel(mesh->getFacetCount());
IntersectionTestingAccelerator accel(mesh, acceleratorRes);
DummyAccelerator dummy(slBox->getFacetCount());
@@ -1126,9 +1126,15 @@ void FractureToolImpl::reset()
mChunkData.clear();
mPlaneIndexerOffset = 1;
mChunkIdCounter = 0;
+ mInteriorMaterialId = MATERIAL_INTERIOR;
}
+void FractureToolImpl::setInteriorMaterialId(int32_t materialId)
+{
+ mInteriorMaterialId = materialId;
+}
+
bool FractureToolImpl::isAncestorForChunk(int32_t ancestorId, int32_t chunkId)
{
if (ancestorId == chunkId)
@@ -1539,5 +1545,22 @@ int32_t FractureToolImpl::getChunkId(int32_t chunkIndex)
return mChunkData[chunkIndex].chunkId;
}
+int32_t FractureToolImpl::getInteriorMaterialId() const
+{
+ return mInteriorMaterialId;
+}
+
+
+void FractureToolImpl::replaceMaterialId(int32_t oldMaterialId, int32_t newMaterialId)
+{
+ for (auto& chunkData : mChunkData)
+ {
+ if (chunkData.meshData)
+ {
+ chunkData.meshData->replaceMaterialId(oldMaterialId, newMaterialId);
+ }
+ }
+}
+
} // namespace Blast
} // namespace Nv
diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringFractureToolImpl.h b/sdk/extensions/authoring/source/NvBlastExtAuthoringFractureToolImpl.h
index 612c0e7..d3eed09 100644
--- a/sdk/extensions/authoring/source/NvBlastExtAuthoringFractureToolImpl.h
+++ b/sdk/extensions/authoring/source/NvBlastExtAuthoringFractureToolImpl.h
@@ -138,6 +138,7 @@ public:
mPlaneIndexerOffset = 1;
mChunkIdCounter = 0;
mRemoveIslands = false;
+ mInteriorMaterialId = MATERIAL_INTERIOR;
}
~FractureToolImpl()
@@ -152,8 +153,22 @@ public:
*/
void reset() override;
+ /**
+ Set the material id to use for new interior faces. Defaults to MATERIAL_INTERIOR
+ */
+ void setInteriorMaterialId(int32_t materialId) override;
+
+ /**
+ Gets the material id to use for new interior faces
+ */
+ int32_t getInteriorMaterialId() const override;
/**
+ Replaces an material id on faces with a new one
+ */
+ void replaceMaterialId(int32_t oldMaterialId, int32_t newMaterialId) override;
+
+ /**
Set input mesh wich will be fractured, FractureTool will be reseted.
*/
void setSourceMesh(const Mesh* mesh) override;
@@ -322,6 +337,7 @@ protected:
std::vector<ChunkInfo> mChunkData;
bool mRemoveIslands;
+ int32_t mInteriorMaterialId;
};
} // namespace Blast
diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringMeshImpl.cpp b/sdk/extensions/authoring/source/NvBlastExtAuthoringMeshImpl.cpp
index 4b0c3ba..7330598 100644
--- a/sdk/extensions/authoring/source/NvBlastExtAuthoringMeshImpl.cpp
+++ b/sdk/extensions/authoring/source/NvBlastExtAuthoringMeshImpl.cpp
@@ -226,7 +226,7 @@ void getTangents(PxVec3& normal, PxVec3& t1, PxVec3& t2)
t2 = t1.cross(normal);
}
-Mesh* getCuttingBox(const PxVec3& point, const PxVec3& normal, float size, int32_t id)
+Mesh* getCuttingBox(const PxVec3& point, const PxVec3& normal, float size, int32_t id, int32_t interiorMaterialId)
{
PxVec3 lNormal = normal.getNormalized();
PxVec3 t1, t2;
@@ -280,38 +280,38 @@ Mesh* getCuttingBox(const PxVec3& point, const PxVec3& normal, float size, int32
edges.push_back(Edge(1, 2));
edges.push_back(Edge(2, 3));
edges.push_back(Edge(3, 0));
- facets.push_back(Facet(0, 4, MATERIAL_INTERIOR, id, -1));
+ 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, MATERIAL_INTERIOR, id, -1));
+ 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, MATERIAL_INTERIOR, id, -1));
+ 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, MATERIAL_INTERIOR, id, -1));
+ 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, MATERIAL_INTERIOR, id, -1));
+ 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, MATERIAL_INTERIOR, id, -1));
+ facets.push_back(Facet(20, 4, interiorMaterialId, id, -1));
return new MeshImpl(positions.data(), edges.data(), facets.data(), static_cast<uint32_t>(positions.size()), static_cast<uint32_t>(edges.size()), static_cast<uint32_t>(facets.size()));
}
@@ -327,7 +327,7 @@ void inverseNormalAndSetIndices(Mesh* mesh, int32_t id)
}
}
-void MeshImpl::setMaterialId(int32_t* materialId)
+void MeshImpl::setMaterialId(const int32_t* materialId)
{
if (materialId != nullptr)
{
@@ -339,14 +339,26 @@ void MeshImpl::setMaterialId(int32_t* materialId)
}
}
-void MeshImpl::setSmoothingGroup(int32_t* smoothingGroup)
+
+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 (smoothingGroup != nullptr)
+ if (smoothingGroups != nullptr)
{
for (uint32_t i = 0; i < mFacets.size(); ++i)
{
- mFacets[i].smoothingGroup = *smoothingGroup;
- ++smoothingGroup;
+ mFacets[i].smoothingGroup = *smoothingGroups;
+ ++smoothingGroups;
}
}
}
@@ -397,7 +409,7 @@ bool MeshImpl::isValid() const
return mVertices.size() > 0 && mEdges.size() > 0 && mFacets.size() > 0;
}
-Mesh* getNoisyCuttingBoxPair(const physx::PxVec3& point, const physx::PxVec3& normal, float size, float jaggedPlaneSize, uint32_t resolution, int32_t id, float amplitude, float frequency, int32_t octaves, int32_t seed)
+Mesh* getNoisyCuttingBoxPair(const physx::PxVec3& point, const physx::PxVec3& normal, float size, float jaggedPlaneSize, uint32_t resolution, int32_t id, float amplitude, float frequency, int32_t octaves, int32_t seed, int32_t interiorMaterialId)
{
SimplexNoise nEval(amplitude, frequency, octaves, seed);
PxVec3 t1, t2;
@@ -443,7 +455,7 @@ Mesh* getNoisyCuttingBoxPair(const physx::PxVec3& point, const physx::PxVec3& no
edges.push_back(Edge(i * (resolution + 1) + j + 1, (i + 1) * (resolution + 1) + j + 1));
edges.push_back(Edge((i + 1) * (resolution + 1) + j + 1, (i + 1) * (resolution + 1) + j));
edges.push_back(Edge((i + 1) * (resolution + 1) + j, i * (resolution + 1) + j));
- facets.push_back(Facet(start, 4, MATERIAL_INTERIOR, id, -1));
+ facets.push_back(Facet(start, 4, interiorMaterialId, id, -1));
}
}
uint32_t offset = (resolution + 1) * (resolution + 1);
@@ -492,7 +504,7 @@ Mesh* getNoisyCuttingBoxPair(const physx::PxVec3& point, const physx::PxVec3& no
edges.push_back(Edge(9 + offset, 8 + offset));
edges.push_back(Edge(8 + offset, 11 + offset));
- facets.push_back(Facet(edgeOffset, 8, MATERIAL_INTERIOR, id, -1));
+ facets.push_back(Facet(edgeOffset, 8, interiorMaterialId, id, -1));
@@ -500,37 +512,37 @@ Mesh* getNoisyCuttingBoxPair(const physx::PxVec3& point, const physx::PxVec3& no
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, MATERIAL_INTERIOR, id, -1));
+ 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, MATERIAL_INTERIOR, id, -1));
+ 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, MATERIAL_INTERIOR, id, -1));
+ 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, MATERIAL_INTERIOR, id, -1));
+ 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, MATERIAL_INTERIOR, id, -1));
+ 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)
+Mesh* getBigBox(const PxVec3& point, float size, int32_t interiorMaterialId)
{
PxVec3 normal(0, 0, 1);
normal.normalize();
@@ -572,38 +584,38 @@ Mesh* getBigBox(const PxVec3& point, float size)
edges.push_back(Edge(1, 2));
edges.push_back(Edge(2, 3));
edges.push_back(Edge(3, 0));
- facets.push_back(Facet(0, 4, MATERIAL_INTERIOR, 0, -1));
+ 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, MATERIAL_INTERIOR, 0, -1));
+ 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, MATERIAL_INTERIOR, 0, -1));
+ 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, MATERIAL_INTERIOR, 0, -1));
+ 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, MATERIAL_INTERIOR, 0, -1));
+ 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, MATERIAL_INTERIOR, 0, -1));
+ 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<uint32_t>(positions.size()), static_cast<uint32_t>(edges.size()), static_cast<uint32_t>(facets.size()));
diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringMeshImpl.h b/sdk/extensions/authoring/source/NvBlastExtAuthoringMeshImpl.h
index ee36f9c..5b7b245 100644
--- a/sdk/extensions/authoring/source/NvBlastExtAuthoringMeshImpl.h
+++ b/sdk/extensions/authoring/source/NvBlastExtAuthoringMeshImpl.h
@@ -138,12 +138,17 @@ public:
/**
Set per-facet material id.
*/
- void setMaterialId(int32_t* materialIds) override;
+ 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(int32_t* smoothingGroup) override;
+ void setSmoothingGroup(const int32_t* smoothingGroups) override;
private:
std::vector<Vertex> mVertices;
@@ -173,14 +178,14 @@ void setCuttingBox(const physx::PxVec3& point, const physx::PxVec3& normal, Mesh
\param[in] size Cutting box size
\param[in] id Cutting box ID
*/
-Mesh* getCuttingBox(const physx::PxVec3& point, const physx::PxVec3& normal, float size, int32_t id);
+Mesh* getCuttingBox(const physx::PxVec3& point, const physx::PxVec3& normal, float size, int32_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);
+Mesh* getBigBox(const physx::PxVec3& point, float size, int32_t interiorMaterialId);
/**
Create slicing box with noisy cutting surface.
@@ -195,7 +200,7 @@ Mesh* getBigBox(const physx::PxVec3& point, float size);
\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, uint32_t resolution, int32_t id, float amplitude, float frequency, int32_t octaves, int32_t seed);
+Mesh* getNoisyCuttingBoxPair(const physx::PxVec3& point, const physx::PxVec3& normal, float size, float jaggedPlaneSize, uint32_t resolution, int32_t id, float amplitude, float frequency, int32_t octaves, int32_t seed, int32_t interiorMaterialId);
/**
diff --git a/sdk/extensions/exporter/include/NvBlastExtExporter.h b/sdk/extensions/exporter/include/NvBlastExtExporter.h
index 5432ec7..a8bbb50 100644
--- a/sdk/extensions/exporter/include/NvBlastExtExporter.h
+++ b/sdk/extensions/exporter/include/NvBlastExtExporter.h
@@ -118,7 +118,7 @@ public:
/**
Number of loaded indices
*/
- virtual uint32_t getIdicesCount() const = 0;
+ virtual uint32_t getIndicesCount() const = 0;
/**
Get loaded vertex positions
@@ -148,7 +148,7 @@ public:
/**
Get material name.
*/
- virtual char* getMaterialName(int32_t id) = 0;
+ virtual const char* getMaterialName(int32_t id) = 0;
/**
Get material count.
@@ -176,7 +176,7 @@ public:
\param[out] hulls Array of hull. The first i-th mesh hull: hulls[hullsOffset[i]]. The size is written to hullsOffset[meshCount]
\return Number of meshes (meshCount)
*/
- virtual uint32_t getCollision(uint32_t*& hullsOffset, CollisionHull** hulls) = 0;
+ virtual uint32_t getCollision(uint32_t*& hullsOffset, CollisionHull**& hulls) = 0;
};
@@ -187,7 +187,7 @@ class IFbxFileReader : public IMeshFileReader
{
public:
/**
- Retrieve bone influence if it exist
+ Retrieve bone influence if it exist, this is a bone index for each vertex in the mesh
\note User should call NVBLAST_FREE for out when it not needed anymore
\param[out] out Array of bone influences.
diff --git a/sdk/extensions/exporter/source/NvBlastExtExporterFbxReader.cpp b/sdk/extensions/exporter/source/NvBlastExtExporterFbxReader.cpp
index c376701..263a660 100644
--- a/sdk/extensions/exporter/source/NvBlastExtExporterFbxReader.cpp
+++ b/sdk/extensions/exporter/source/NvBlastExtExporterFbxReader.cpp
@@ -28,17 +28,16 @@
#include "NvBlastExtExporterFbxReader.h"
#include "NvBlastExtExporterFbxUtils.h"
#include "NvBlastGlobals.h"
-#include "fileio/fbxiosettings.h"
-#include "fileio/fbxiosettingspath.h"
-#include "core/base/fbxstringlist.h"
+#include <fbxsdk.h>
#include <iostream>
#include <algorithm>
#include <cctype>
#include <sstream>
-#include "scene/geometry/fbxmesh.h"
+#include <unordered_map>
#include "PxVec3.h"
#include "PxVec2.h"
+#include "PxPlane.h"
#include "NvBlastExtAuthoringMesh.h"
#include "NvBlastExtAuthoringBondGenerator.h"
#include "NvBlastExtAuthoringCollisionBuilder.h"
@@ -50,7 +49,8 @@ using namespace Nv::Blast;
FbxFileReader::FbxFileReader()
{
- mBoneCount = 0;
+ mMeshCount = 0;
+ mChunkCount = 0;
}
void FbxFileReader::release()
@@ -74,11 +74,10 @@ void FbxFileReader::loadFromFile(const char* filename)
// Wrap in a shared ptr so that when it deallocates we get an auto destroy and all of the other assets created don't leak.
std::shared_ptr<FbxManager> sdkManager = std::shared_ptr<FbxManager>(FbxManager::Create(), [=](FbxManager* manager)
{
- std::cout << "Deleting FbxManager" << std::endl;
manager->Destroy();
});
- mBoneCount = 0;
+ mChunkCount = 0;
mCollisionNodes.clear();
FbxIOSettings* ios = FbxIOSettings::Create(sdkManager.get(), IOSROOT);
// Set some properties on the io settings
@@ -141,6 +140,7 @@ void FbxFileReader::loadFromFile(const char* filename)
blastUnits.ConvertScene(scene);
}
+ FbxGeometryConverter geoConverter(sdkManager.get());
FbxDisplayLayer* collisionDisplayLayer = scene->FindMember<FbxDisplayLayer>(FbxUtils::getCollisionGeometryLayerName().c_str());
// Recurse the fbx tree and find all meshes
@@ -155,11 +155,38 @@ void FbxFileReader::loadFromFile(const char* filename)
std::cout << "Found " << meshNodes.size() << " meshes." << std::endl;
- // Process just 0, because dumb. Fail out if more than 1?
if (meshNodes.size() > 1)
{
- std::cerr << "Can't load more that one graphics mesh." << std::endl;
- return;
+ FbxArray<FbxNode*> tempMeshArray;
+ tempMeshArray.Resize((int)meshNodes.size());
+ for (size_t i = 0; i < meshNodes.size(); i++)
+ {
+ FbxMesh* mesh = meshNodes[i]->GetMesh();
+ if (mesh->GetDeformerCount(FbxDeformer::eSkin) != 0)
+ {
+ std::cerr << "Multi-part mesh " << meshNodes[i]->GetName() << " is already skinned, not sure what to do" << std::endl;
+ return;
+ }
+ //Add a one-bone skin so later when we merge meshes the connection to the chunk transform will stick, this handles the non-skinned layout of the FBX file
+ FbxSkin* skin = FbxSkin::Create(scene, (std::string(meshNodes[i]->GetName()) + "_skin").c_str());
+ mesh->AddDeformer(skin);
+ FbxCluster* cluster = FbxCluster::Create(skin, (std::string(meshNodes[i]->GetName()) + "_cluster").c_str());
+ skin->AddCluster(cluster);
+ cluster->SetLink(meshNodes[i]);
+ const int cpCount = mesh->GetControlPointsCount();
+ cluster->SetControlPointIWCount(cpCount);
+ //Fully weight to the one bone
+ int* cpIdx = cluster->GetControlPointIndices();
+ double* cpWeights = cluster->GetControlPointWeights();
+ for (int cp = 0; cp < cpCount; cp++)
+ {
+ cpIdx[cp] = cp;
+ cpWeights[cp] = 1.0;
+ }
+ tempMeshArray.SetAt(int(i), meshNodes[i]);
+ }
+ meshNodes.resize(1);
+ meshNodes[0] = geoConverter.MergeMeshes(tempMeshArray, "MergedMesh", scene);
}
if (meshNodes.empty())
@@ -170,19 +197,16 @@ void FbxFileReader::loadFromFile(const char* filename)
FbxNode* meshNode = meshNodes[0];
FbxMesh* mesh = meshNode->GetMesh();
- int polyCount = mesh->GetPolygonCount();
-
-
- bool bAllTriangles = true;
// Verify that the mesh is triangulated.
- for (int i = 0; i < polyCount; i++)
+ bool bAllTriangles = mesh->IsTriangleMesh();
+ if (!bAllTriangles)
{
- if (mesh->GetPolygonSize(i) != 3)
- {
- bAllTriangles = false;
- }
+ //try letting the FBX SDK triangulate it
+ geoConverter.Triangulate(mesh, true);
+ bAllTriangles = mesh->IsTriangleMesh();
}
+ int polyCount = mesh->GetPolygonCount();
if (!bAllTriangles)
{
std::cerr << "Mesh 0 has " << polyCount << " but not all polygons are triangles. Mesh must be triangulated." << std::endl;
@@ -205,12 +229,7 @@ void FbxFileReader::loadFromFile(const char* filename)
uint32_t vertIndex = 0;
FbxAMatrix trans = getTransformForNode(meshNode);
- FbxVector4 rotation = trans.GetR();
- FbxVector4 scale = trans.GetS();
- FbxAMatrix normalTransf;
- normalTransf.SetR(rotation);
- normalTransf.SetS(scale);
- normalTransf = normalTransf.Inverse().Transpose();
+ FbxAMatrix normalTransf = trans.Inverse().Transpose();
int32_t matElements = mesh->GetElementMaterialCount();
if (matElements > 1)
@@ -220,12 +239,15 @@ void FbxFileReader::loadFromFile(const char* filename)
auto matLayer = mesh->GetElementMaterial(0);
auto smLayer = mesh->GetElementSmoothing();
+ const int triangleIndexMappingUnflipped[3] = { 0, 1, 2 };
+ const int triangleIndexMappingFlipped[3] = { 2, 1, 0 };
+ const int* triangleIndexMapping = trans.Determinant() < 0 ? triangleIndexMappingFlipped : triangleIndexMappingUnflipped;
for (int i = 0; i < polyCount; i++)
{
for (int vi = 0; vi < 3; vi++)
{
- int polyCPIdx = polyVertices[i*3+vi];
+ int polyCPIdx = polyVertices[i*3+ triangleIndexMapping[vi]];
FbxVector4 vert = mesh->GetControlPointAt(polyCPIdx);
FbxVector4 normVec;
@@ -321,33 +343,30 @@ bool FbxFileReader::isCollisionLoaded()
return !mCollisionNodes.empty();
}
-uint32_t FbxFileReader::getCollision(uint32_t*& hullsOffset, Nv::Blast::CollisionHull** hulls)
+uint32_t FbxFileReader::getCollision(uint32_t*& hullsOffset, Nv::Blast::CollisionHull**& hulls)
{
if (!isCollisionLoaded())
{
+ hullsOffset = nullptr;
+ hulls = nullptr;
return 0;
}
- hullsOffset = new uint32_t[mMeshCount + 1];
- hulls = new Nv::Blast::CollisionHull*[mMeshCount];
- memcpy(hullsOffset, mHullsOffset.data(), sizeof(uint32_t) * (mMeshCount + 1));
- memcpy(hulls, mHulls.data(), sizeof(Nv::Blast::CollisionHull*) * mMeshCount);
- return mMeshCount;
-}
-
-struct CollisionHullImpl : public Nv::Blast::CollisionHull
-{
- void release() override
+ hullsOffset = (uint32_t*)NVBLAST_ALLOC(sizeof(uint32_t) * mHullsOffset.size());
+ memcpy(hullsOffset, mHullsOffset.data(), sizeof(uint32_t) * mHullsOffset.size());
+
+
+ hulls = (Nv::Blast::CollisionHull**)NVBLAST_ALLOC(sizeof(Nv::Blast::CollisionHull*) * mHulls.size());
+ for (size_t i = 0; i < mHulls.size(); i++)
{
-
+ //This deep-copies the data inside
+ hulls[i] = new CollisionHullImpl(mHulls[i]);
}
-};
+ return mMeshCount;
+}
bool FbxFileReader::getCollisionInternal()
{
- for (auto hull : mHulls)
- {
- hull->release();
- }
+ mHulls.clear();
int32_t maxParentIndex = 0;
for (auto p : mCollisionNodes)
@@ -358,62 +377,126 @@ bool FbxFileReader::getCollisionInternal()
mMeshCount = maxParentIndex + 1;
mHullsOffset.resize(mMeshCount + 1);
mHulls.resize(mCollisionNodes.size());
- mHullsOffset[0] = 0;
+
+ uint32_t currentHullCount = 0;
+ uint32_t prevParentIndex = 0;
+ mHullsOffset[0] = currentHullCount;
for (auto p : mCollisionNodes) // it should be sorted by chunk id
{
- int32_t parentIndex = p.first;
- //hulls[parentIndex].push_back(Nv::Blast::CollisionHull());
- mHulls[mHullsOffset[parentIndex]] = new CollisionHullImpl();
- Nv::Blast::CollisionHull& chull = *mHulls[mHullsOffset[parentIndex]];
+ uint32_t parentIndex = p.first;
+ if (prevParentIndex != parentIndex)
+ {
+ for (uint32_t m = prevParentIndex + 1; m < parentIndex; m++)
+ {
+ //copy these if there were no collision meshes
+ mHullsOffset[m] = mHullsOffset[prevParentIndex];
+ }
+ mHullsOffset[parentIndex] = currentHullCount;
+ prevParentIndex = parentIndex;
+ }
+ Nv::Blast::CollisionHull& chull = mHulls[currentHullCount];
+ currentHullCount++;
+
FbxMesh* meshNode = p.second->GetMesh();
FbxAMatrix nodeTransform = getTransformForNode(p.second);
FbxAMatrix nodeTransformNormal = nodeTransform.Inverse().Transpose();
- chull.points = new PxVec3[meshNode->GetControlPointsCount()];
+ //PhysX seems to care about having welding verticies.
+ //Probably doing a dumb search is fast enough since how big could the convex hulls possibly be?
+ std::vector<FbxVector4> uniqueCPValues;
+ uniqueCPValues.reserve(meshNode->GetControlPointsCount());
+ std::vector<uint32_t> originalToNewCPMapping(meshNode->GetControlPointsCount(), ~0U);
+
FbxVector4* vpos = meshNode->GetControlPoints();
- /**
- Copy control points from FBX.
- */
for (int32_t i = 0; i < meshNode->GetControlPointsCount(); ++i)
{
FbxVector4 worldVPos = nodeTransform.MultT(*vpos);
+ bool found = false;
+ for (size_t j = 0; j < uniqueCPValues.size(); j++)
+ {
+ if (uniqueCPValues[j] == worldVPos)
+ {
+ originalToNewCPMapping[i] = uint32_t(j);
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ {
+ originalToNewCPMapping[i] = uint32_t(uniqueCPValues.size());
+ uniqueCPValues.push_back(worldVPos);
+ }
+ vpos++;
+ }
+
+ chull.points = new PxVec3[uniqueCPValues.size()];
+ chull.pointsCount = uint32_t(uniqueCPValues.size());
+
+ physx::PxVec3 hullCentroid(0.0f);
+
+ for (uint32_t i = 0; i < chull.pointsCount; ++i)
+ {
+ const FbxVector4& worldVPos = uniqueCPValues[i];
chull.points[i].x = (float)worldVPos[0];
chull.points[i].y = (float)worldVPos[1];
chull.points[i].z = (float)worldVPos[2];
- vpos++;
+ hullCentroid += chull.points[i];
+ }
+
+ if (chull.pointsCount)
+ {
+ hullCentroid /= (float)chull.pointsCount;
}
uint32_t polyCount = meshNode->GetPolygonCount();
chull.polygonData = new Nv::Blast::CollisionHull::HullPolygon[polyCount];
- FbxGeometryElementNormal* nrm = meshNode->GetElementNormal();
- FbxLayerElementArray& narr = nrm->GetDirectArray();
+ chull.polygonDataCount = polyCount;
+
+ chull.indicesCount = meshNode->GetPolygonVertexCount();
+ chull.indices = new uint32_t[chull.indicesCount];
+ uint32_t curIndexCount = 0;
for (uint32_t poly = 0; poly < polyCount; ++poly)
{
int32_t vInPolyCount = meshNode->GetPolygonSize(poly);
auto& pd = chull.polygonData[poly];
- pd.mIndexBase = (uint16_t)chull.indicesCount;
+ pd.mIndexBase = (uint16_t)curIndexCount;
pd.mNbVerts = (uint16_t)vInPolyCount;
int32_t* ind = &meshNode->GetPolygonVertices()[meshNode->GetPolygonVertexIndex(poly)];
- chull.indices = new uint32_t[vInPolyCount];
- memcpy(chull.indices, ind, sizeof(uint32_t) * vInPolyCount);
+ uint32_t* destInd = chull.indices + curIndexCount;
+ for (int32_t v = 0; v < vInPolyCount; v++)
+ {
+ destInd[v] = originalToNewCPMapping[ind[v]];
+ }
+ curIndexCount += vInPolyCount;
+
+ //Don't depend on the normals to create the plane normal, they could be wrong
+ PxVec3 lastThreeVerts[3] = {
+ chull.points[chull.indices[curIndexCount - 1]],
+ chull.points[chull.indices[curIndexCount - 2]],
+ chull.points[chull.indices[curIndexCount - 3]]
+ };
- FbxVector4 normal;
- narr.GetAt(poly, &normal);
+ physx::PxPlane plane(lastThreeVerts[0], lastThreeVerts[1], lastThreeVerts[2]);
+ plane.normalize();
- normal = nodeTransformNormal.MultT(normal);
+ const float s = plane.n.dot(lastThreeVerts[0] - hullCentroid) >= 0.0f ? 1.0f : -1.0f;
- pd.mPlane[0] = (float)normal[0];
- pd.mPlane[1] = (float)normal[1];
- pd.mPlane[2] = (float)normal[2];
- PxVec3 polyLastVertex = chull.points[chull.indices[vInPolyCount - 1]];
- pd.mPlane[3] = -((float)(polyLastVertex.x * normal[0] + polyLastVertex.y * normal[1] + polyLastVertex.z * normal[2]));
+ pd.mPlane[0] = s*plane.n.x;
+ pd.mPlane[1] = s*plane.n.y;
+ pd.mPlane[2] = s*plane.n.z;
+ pd.mPlane[3] = s*plane.d;
}
- mHullsOffset[parentIndex + 1] = mHullsOffset[parentIndex] + 1;
}
-
+
+ //Set the end marker
+ for (uint32_t m = prevParentIndex + 1; m <= mMeshCount; m++)
+ {
+ //copy these if there were no collision meshes
+ mHullsOffset[m] = currentHullCount;
+ }
return false;
}
@@ -424,43 +507,74 @@ bool FbxFileReader::getCollisionInternal()
**/
bool FbxFileReader::getBoneInfluencesInternal(FbxMesh* meshNode)
{
+ std::unordered_map<FbxNode*, uint32_t> boneToChunkIndex;
if (meshNode->GetDeformerCount() != 1)
{
std::cout << "Can't create bone mapping: There is no mesh deformers...: " << std::endl;
return false;
}
- mVertexToParentBoneMap.clear();
- mVertexToParentBoneMap.resize(mVertexPositions.size());
- std::vector<uint32_t> controlToParentBoneMap;
- controlToParentBoneMap.resize(meshNode->GetControlPointsCount());
+ mVertexToContainingChunkMap.clear();
+ mVertexToContainingChunkMap.resize(mVertexPositions.size());
+ std::vector<uint32_t> controlToParentChunkMap;
+ controlToParentChunkMap.resize(meshNode->GetControlPointsCount());
FbxSkin* def = (FbxSkin *)meshNode->GetDeformer(0, FbxDeformer::EDeformerType::eSkin);
if (def->GetClusterCount() == 0)
{
std::cout << "Can't create bone mapping: There is no vertex clusters...: " << std::endl;
return false;
- }
- mBoneCount = def->GetClusterCount();
+ }
+ //We want the number of chunks not the bones in the FBX file
+ mChunkCount = 0;
+
for (int32_t i = 0; i < def->GetClusterCount(); ++i)
{
FbxCluster* cls = def->GetCluster(i);
FbxNode* bone = cls->GetLink();
- int32_t parentChunk = atoi(bone->GetName() + 5);
+
+ uint32_t myChunkIndex;
+ auto findIt = boneToChunkIndex.find(bone);
+ if (findIt != boneToChunkIndex.end())
+ {
+ myChunkIndex = findIt->second;
+ }
+ else
+ {
+ myChunkIndex = FbxUtils::getChunkIndexForNode(bone);
+ if (myChunkIndex == UINT32_MAX)
+ {
+ //maybe an old file?
+ myChunkIndex = FbxUtils::getChunkIndexForNodeBackwardsCompatible(bone);
+ }
+
+ if (myChunkIndex == UINT32_MAX)
+ {
+ std::cerr << "Not sure what to do with node " << bone->GetName() << ". is this a chunk?" << std::endl;
+ }
+
+ boneToChunkIndex.emplace(bone, myChunkIndex);
+ if (myChunkIndex >= mChunkCount)
+ {
+ mChunkCount = myChunkIndex + 1;
+ }
+ }
+
int32_t* cpIndx = cls->GetControlPointIndices();
for (int32_t j = 0; j < cls->GetControlPointIndicesCount(); ++j)
{
- controlToParentBoneMap[*cpIndx] = parentChunk;
+ controlToParentChunkMap[*cpIndx] = myChunkIndex;
++cpIndx;
}
}
+
int* polyVertices = meshNode->GetPolygonVertices();
uint32_t lv = 0;
for (int i = 0; i < meshNode->GetPolygonCount(); i++)
{
for (int vi = 0; vi < 3; vi++)
{
- mVertexToParentBoneMap[lv] = controlToParentBoneMap[*polyVertices];
+ mVertexToContainingChunkMap[lv] = controlToParentChunkMap[*polyVertices];
polyVertices++;
lv++;
}
@@ -490,21 +604,21 @@ uint32_t* FbxFileReader::getIndexArray()
uint32_t FbxFileReader::getBoneInfluences(uint32_t*& out)
{
- out = static_cast<uint32_t*>(NVBLAST_ALLOC(sizeof(uint32_t) * mVertexToParentBoneMap.size()));
- memcpy(out, mVertexToParentBoneMap.data(), sizeof(uint32_t) * mVertexToParentBoneMap.size());
- return mVertexToParentBoneMap.size();
+ out = static_cast<uint32_t*>(NVBLAST_ALLOC(sizeof(uint32_t) * mVertexToContainingChunkMap.size()));
+ memcpy(out, mVertexToContainingChunkMap.data(), sizeof(uint32_t) * mVertexToContainingChunkMap.size());
+ return mVertexToContainingChunkMap.size();
}
uint32_t FbxFileReader::getBoneCount()
{
- return mBoneCount;
+ return mChunkCount;
}
-char* FbxFileReader::getMaterialName(int32_t id)
+const char* FbxFileReader::getMaterialName(int32_t id)
{
if (id < int32_t(mMaterialNames.size()) && id >= 0)
{
- return &mMaterialNames[id][0];
+ return mMaterialNames[id].c_str();
}
else
{
@@ -519,4 +633,4 @@ int32_t* FbxFileReader::getMaterialIds()
return nullptr;
}
return mMaterialIds.data();
-} \ No newline at end of file
+}
diff --git a/sdk/extensions/exporter/source/NvBlastExtExporterFbxReader.h b/sdk/extensions/exporter/source/NvBlastExtExporterFbxReader.h
index b7c81aa..db928f4 100644
--- a/sdk/extensions/exporter/source/NvBlastExtExporterFbxReader.h
+++ b/sdk/extensions/exporter/source/NvBlastExtExporterFbxReader.h
@@ -44,6 +44,87 @@ class Mesh;
class FbxFileReader : public IFbxFileReader
{
+ struct CollisionHullImpl : public Nv::Blast::CollisionHull
+ {
+ void release() override
+ {
+ delete this;
+ }
+
+ //copy from existing
+ CollisionHullImpl(const CollisionHullImpl& other) : CollisionHullImpl()
+ {
+ copyFrom(other);
+ }
+
+ CollisionHullImpl()
+ {
+ pointsCount = 0;
+ indicesCount = 0;
+ polygonDataCount = 0;
+ points = nullptr;
+ indices = nullptr;
+ polygonData = nullptr;
+ }
+
+ CollisionHullImpl(CollisionHullImpl&& other)
+ {
+ operator=(std::move(other));
+ }
+
+ CollisionHullImpl& operator=(const CollisionHullImpl& other)
+ {
+ if (&other != this)
+ {
+ release();
+ copyFrom(other);
+ }
+ return *this;
+ }
+
+ CollisionHullImpl& operator=(CollisionHullImpl&& other)
+ {
+ if (&other != this)
+ {
+ pointsCount = other.pointsCount;
+ indicesCount = other.indicesCount;
+ polygonDataCount = other.polygonDataCount;
+ points = other.points;
+ indices = other.indices;
+ polygonData = other.polygonData;
+
+ other.pointsCount = 0;
+ other.indicesCount = 0;
+ other.polygonDataCount = 0;
+ other.points = nullptr;
+ other.indices = nullptr;
+ other.polygonData = nullptr;
+ }
+ return *this;
+ }
+
+ virtual ~CollisionHullImpl()
+ {
+ delete[] points;
+ delete[] indices;
+ delete[] polygonData;
+ }
+ private:
+
+ void copyFrom(const CollisionHullImpl& other)
+ {
+ pointsCount = other.pointsCount;
+ indicesCount = other.indicesCount;
+ polygonDataCount = other.polygonDataCount;
+ points = new physx::PxVec3[pointsCount];
+ indices = new uint32_t[indicesCount];
+ polygonData = new Nv::Blast::CollisionHull::HullPolygon[polygonDataCount];
+ memcpy(points, other.points, sizeof(points[0]) * pointsCount);
+ memcpy(indices, other.indices, sizeof(indices[0]) * indicesCount);
+ memcpy(polygonData, other.polygonData, sizeof(polygonData[0]) * polygonDataCount);
+ }
+ };
+
public:
FbxFileReader();
~FbxFileReader() = default;
@@ -60,7 +141,7 @@ public:
return mVertexPositions.size();
}
- virtual uint32_t getIdicesCount() const override
+ virtual uint32_t getIndicesCount() const override
{
return mIndices.size();
}
@@ -73,7 +154,7 @@ public:
/**
Retrieve collision geometry if it exist
*/
- virtual uint32_t getCollision(uint32_t*& hullsOffset, Nv::Blast::CollisionHull** hulls) override;
+ virtual uint32_t getCollision(uint32_t*& hullsOffset, Nv::Blast::CollisionHull**& hulls) override;
virtual uint32_t getBoneInfluences(uint32_t*& out) override;
@@ -109,7 +190,7 @@ public:
/**
Get material name.
*/
- char* getMaterialName(int32_t id) override;
+ const char* getMaterialName(int32_t id) override;
int32_t getMaterialCount() override;
@@ -117,9 +198,10 @@ public:
private:
uint32_t mMeshCount;
+ uint32_t mChunkCount;
std::vector<uint32_t> mHullsOffset;
- std::vector<Nv::Blast::CollisionHull*> mHulls;
- std::vector<uint32_t> mVertexToParentBoneMap;
+ std::vector<CollisionHullImpl> mHulls;
+ std::vector<uint32_t> mVertexToContainingChunkMap;
std::multimap<uint32_t, FbxNode*> mCollisionNodes;
std::vector<physx::PxVec3> mVertexPositions;
std::vector<physx::PxVec3> mVertexNormals;
@@ -128,8 +210,6 @@ private:
std::vector<int32_t> mSmoothingGroups;
std::vector<int32_t> mMaterialIds;
std::vector<std::string> mMaterialNames;
-
- uint32_t mBoneCount;
FbxAMatrix getTransformForNode(FbxNode* node);
void getFbxMeshes(FbxDisplayLayer* collisionDisplayLayer, FbxNode* node, std::vector<FbxNode*>& meshNodes);
diff --git a/sdk/extensions/exporter/source/NvBlastExtExporterFbxUtils.cpp b/sdk/extensions/exporter/source/NvBlastExtExporterFbxUtils.cpp
index 95a757f..a71af2b 100644
--- a/sdk/extensions/exporter/source/NvBlastExtExporterFbxUtils.cpp
+++ b/sdk/extensions/exporter/source/NvBlastExtExporterFbxUtils.cpp
@@ -146,10 +146,17 @@ std::string FbxUtils::FbxSystemUnitToString(const FbxSystemUnit& systemUnit)
return std::string(systemUnit.GetScaleFactorAsString());
}
-const static std::string chunkPrefix = "chunk_";
+const static std::string currentChunkPrefix = "chunk_";
+const static std::string oldChunkPrefix = "bone_";
-uint32_t FbxUtils::getChunkIndexForNode(FbxNode* node, bool includeParents /*= true*/)
+static uint32_t getChunkIndexForNodeInternal(const std::string& chunkPrefix, FbxNode* node, uint32_t* outParentChunkIndex /*=nullptr*/)
{
+ if (!node)
+ {
+ //Found nothing
+ return UINT32_MAX;
+ }
+
std::string nodeName(node->GetNameOnly());
for (char& c : nodeName)
c = (char)std::tolower(c);
@@ -161,23 +168,32 @@ uint32_t FbxUtils::getChunkIndexForNode(FbxNode* node, bool includeParents /*= t
iss >> ret;
if (!iss.fail())
{
+ if (outParentChunkIndex)
+ {
+ *outParentChunkIndex = getChunkIndexForNodeInternal(chunkPrefix, node->GetParent(), nullptr);
+ }
return ret;
}
}
- if (includeParents && node->GetParent())
- {
- return getChunkIndexForNode(node->GetParent(), true);
- }
- //Found nothing
- return UINT32_MAX;
+ return getChunkIndexForNodeInternal(chunkPrefix, node->GetParent(), outParentChunkIndex);
+}
+
+uint32_t FbxUtils::getChunkIndexForNode(FbxNode* node, uint32_t* outParentChunkIndex /*=nullptr*/)
+{
+ return getChunkIndexForNodeInternal(currentChunkPrefix, node, outParentChunkIndex);
+}
+
+uint32_t FbxUtils::getChunkIndexForNodeBackwardsCompatible(FbxNode* node, uint32_t* outParentChunkIndex /*= nullptr*/)
+{
+ return getChunkIndexForNodeInternal(oldChunkPrefix, node, outParentChunkIndex);
}
std::string FbxUtils::getChunkNodeName(uint32_t chunkIndex)
{
//This naming is required for the UE4 plugin to find them
std::ostringstream namestream;
- namestream << chunkPrefix << chunkIndex;
+ namestream << currentChunkPrefix << chunkIndex;
return namestream.str();
}
diff --git a/sdk/extensions/exporter/source/NvBlastExtExporterFbxUtils.h b/sdk/extensions/exporter/source/NvBlastExtExporterFbxUtils.h
index d26a9e9..d699a6c 100644
--- a/sdk/extensions/exporter/source/NvBlastExtExporterFbxUtils.h
+++ b/sdk/extensions/exporter/source/NvBlastExtExporterFbxUtils.h
@@ -57,7 +57,9 @@ public:
static std::string FbxSystemUnitToString(const FbxSystemUnit& systemUnit);
//returns UINT32_MAX if not a chunk
- static uint32_t getChunkIndexForNode(FbxNode* node, bool includeParents = true);
+ static uint32_t getChunkIndexForNode(FbxNode* node, uint32_t* outParentChunkIndex = nullptr);
+ //Search using the old naming
+ static uint32_t getChunkIndexForNodeBackwardsCompatible(FbxNode* node, uint32_t* outParentChunkIndex = nullptr);
static std::string getChunkNodeName(uint32_t chunkIndex);
static std::string getCollisionGeometryLayerName();
diff --git a/sdk/extensions/exporter/source/NvBlastExtExporterFbxWriter.cpp b/sdk/extensions/exporter/source/NvBlastExtExporterFbxWriter.cpp
index eda8f7c..497c846 100644
--- a/sdk/extensions/exporter/source/NvBlastExtExporterFbxWriter.cpp
+++ b/sdk/extensions/exporter/source/NvBlastExtExporterFbxWriter.cpp
@@ -55,7 +55,6 @@ FbxFileWriter::FbxFileWriter():
// Wrap in a shared ptr so that when it deallocates we get an auto destroy and all of the other assets created don't leak.
sdkManager = std::shared_ptr<FbxManager>(FbxManager::Create(), [=](FbxManager* manager)
{
- std::cout << "Deleting FbxManager" << std::endl;
manager->Destroy();
});
@@ -197,8 +196,8 @@ bool FbxFileWriter::appendMesh(const AuthoringResult& aResult, const char* asset
// Now walk the tree and create a skeleton with geometry at the same time
// Find a "root" chunk and walk the tree from there.
- uint32_t chunkCount = aResult.chunkCount;
- auto chunks = aResult.chunkDescs;
+ uint32_t chunkCount = NvBlastAssetGetChunkCount(aResult.asset, Nv::Blast::logLL);
+ auto chunks = NvBlastAssetGetChunks(aResult.asset, Nv::Blast::logLL);
uint32_t cpIdx = 0;
for (uint32_t i = 0; i < chunkCount; i++)
@@ -242,9 +241,8 @@ bool FbxFileWriter::appendNonSkinnedMesh(const AuthoringResult& aResult, const c
// Now walk the tree and create a skeleton with geometry at the same time
// Find a "root" chunk and walk the tree from there.
- uint32_t chunkCount = aResult.chunkCount;
-
- auto chunks = aResult.chunkDescs;
+ uint32_t chunkCount = NvBlastAssetGetChunkCount(aResult.asset, Nv::Blast::logLL);
+ auto chunks = NvBlastAssetGetChunks(aResult.asset, Nv::Blast::logLL);
for (uint32_t i = 0; i < chunkCount; i++)
{
diff --git a/sdk/extensions/exporter/source/NvBlastExtExporterObjReader.cpp b/sdk/extensions/exporter/source/NvBlastExtExporterObjReader.cpp
index 95efb3e..fb6e9b3 100644
--- a/sdk/extensions/exporter/source/NvBlastExtExporterObjReader.cpp
+++ b/sdk/extensions/exporter/source/NvBlastExtExporterObjReader.cpp
@@ -103,10 +103,11 @@ bool ObjFileReader::isCollisionLoaded()
};
-uint32_t ObjFileReader::getCollision(uint32_t*& hullsOffset, Nv::Blast::CollisionHull** hulls)
+uint32_t ObjFileReader::getCollision(uint32_t*& hullsOffset, Nv::Blast::CollisionHull**& hulls)
{
- NV_UNUSED(hulls);
- return false;
+ hullsOffset = nullptr;
+ hulls = nullptr;
+ return 0;
};
physx::PxVec3* ObjFileReader::getPositionArray()
diff --git a/sdk/extensions/exporter/source/NvBlastExtExporterObjReader.h b/sdk/extensions/exporter/source/NvBlastExtExporterObjReader.h
index f80f8f9..8990287 100644
--- a/sdk/extensions/exporter/source/NvBlastExtExporterObjReader.h
+++ b/sdk/extensions/exporter/source/NvBlastExtExporterObjReader.h
@@ -57,7 +57,7 @@ public:
return mVertexPositions.size();
}
- virtual uint32_t getIdicesCount() const override
+ virtual uint32_t getIndicesCount() const override
{
return mIndices.size();
}
@@ -70,7 +70,7 @@ public:
/**
Retrieve collision geometry if it exist
*/
- virtual uint32_t getCollision(uint32_t*& hullsOffset, Nv::Blast::CollisionHull** hulls) override;
+ virtual uint32_t getCollision(uint32_t*& hullsOffset, Nv::Blast::CollisionHull**& hulls) override;
/**
Get loaded vertex positions
@@ -102,7 +102,7 @@ public:
/**
Get material name. Currently not supported by OBJ.
*/
- char* getMaterialName(int32_t id) override { return nullptr; }
+ const char* getMaterialName(int32_t id) override { return nullptr; }
/**
Get material count.
diff --git a/sdk/extensions/physx/include/NvBlastExtImpactDamageManager.h b/sdk/extensions/physx/include/NvBlastExtImpactDamageManager.h
index 28d0947..292ba5c 100644
--- a/sdk/extensions/physx/include/NvBlastExtImpactDamageManager.h
+++ b/sdk/extensions/physx/include/NvBlastExtImpactDamageManager.h
@@ -63,11 +63,11 @@ struct ExtImpactSettings
{
bool isSelfCollissionEnabled; //!< family's self collision enabled.
bool shearDamage; //!< use shear damage program (otherwise simple radial damage is used)
- float impulseMinThreshold; //!< min impulse value to apply impact damage.
- float impulseMaxThreshold; //!< max impulse value, damage is interpolated value between min and max impulses.
- float damageMax; //!< max damage to be applied (if impulse is >= impulseMaxThreshold).
- float damageRadiusMax; //!< max penetration depth (if impulse is >= impulseMaxThreshold).
- float damageAttenuation; //!< penetration attenuation ([0..1], where 1 means damage attenuates linearly from 0 to max penetration depth).
+ float hardness; //!< hardness of material for impact damage. Damage = impulse / hardness . This damage is capped by the material's health.
+ float damageRadiusMax; //!< the maximum radius in which full damage is applied.
+ float damageThresholdMin; //!< minimum damage fraction threshold to be applied. Range [0, 1]. For example 0.1 filters all damage below 10% of health.
+ float damageThresholdMax; //!< maximum damage fraction threshold to be applied. Range [0, 1]. For example 0.8 won't allow more then 80% of health damage to be applied.
+ float damageFalloffRadiusFactor; //!< damage attenuation radius factor. Given a radius R for full damage, for [R, R * damageFalloffRadiusFactor] radius interval damage attenuates down to zero at the outer radius.
ExtImpactDamageFunction damageFunction; //!< custom damage function, can be nullptr, default internal one will be used in that case.
void* damageFunctionData; //!< data to be passed in custom damage function.
@@ -75,11 +75,11 @@ struct ExtImpactSettings
ExtImpactSettings() :
isSelfCollissionEnabled(false),
shearDamage(true),
- impulseMinThreshold(0.0f),
- impulseMaxThreshold(1000000.0f),
- damageMax(100.f),
- damageRadiusMax(5.0f),
- damageAttenuation(1.f),
+ hardness(10.0f),
+ damageRadiusMax(2.0f),
+ damageThresholdMin(0.1f), // to filter small damage events
+ damageThresholdMax(1.0f),
+ damageFalloffRadiusFactor(2.0f),
damageFunction(nullptr),
damageFunctionData(nullptr)
{}
diff --git a/sdk/extensions/physx/source/physics/NvBlastExtImpactDamageManager.cpp b/sdk/extensions/physx/source/physics/NvBlastExtImpactDamageManager.cpp
index fc1f514..b7831cb 100644
--- a/sdk/extensions/physx/source/physics/NvBlastExtImpactDamageManager.cpp
+++ b/sdk/extensions/physx/source/physics/NvBlastExtImpactDamageManager.cpp
@@ -334,16 +334,13 @@ void ExtImpactDamageManagerImpl::applyDamage()
for (const ImpactDamageData& data : m_impactDamageBuffer)
{
- if (data.force.magnitudeSquared() > m_settings.impulseMinThreshold * m_settings.impulseMinThreshold)
- {
- PxTransform t(data.actor->getPhysXActor().getGlobalPose().getInverse());
- PxVec3 force = t.rotate(data.force);
- PxVec3 position = t.transform(data.position);
+ PxTransform t(data.actor->getPhysXActor().getGlobalPose().getInverse());
+ PxVec3 force = t.rotate(data.force);
+ PxVec3 position = t.transform(data.position);
- if (!damageFn || !damageFn(damageFnData, data.actor, data.shape, position, force))
- {
- damageActor(data.actor, data.shape, position, force);
- }
+ if (!damageFn || !damageFn(damageFnData, data.actor, data.shape, position, force))
+ {
+ damageActor(data.actor, data.shape, position, force);
}
}
m_impactDamageBuffer.clear();
@@ -366,10 +363,7 @@ void ExtImpactDamageManagerImpl::damageActor(ExtPxActor* actor, PxShape* /*shape
{
ensureBuffersSize(actor);
- const float f0 = m_settings.impulseMinThreshold;
- const float f1 = m_settings.impulseMaxThreshold;
- const float impulse01 = PxClamp<float>((force.magnitude() - f0) / PxMax<float>(f1 - f0, 1.0f), 0, 1);
- const float damage = m_settings.damageMax * impulse01;
+ const float damage = m_settings.hardness > 0.f ? force.magnitude() / m_settings.hardness : 0.f;
const void* material = actor->getTkActor().getFamily().getMaterial();
if (!material)
@@ -377,15 +371,16 @@ void ExtImpactDamageManagerImpl::damageActor(ExtPxActor* actor, PxShape* /*shape
return;
}
- const float normalizedDamage = reinterpret_cast<const NvBlastExtMaterial*>(material)->getNormalizedDamage(damage);
- if (normalizedDamage == 0.f)
+ float normalizedDamage = reinterpret_cast<const NvBlastExtMaterial*>(material)->getNormalizedDamage(damage);
+ if (normalizedDamage == 0.f || normalizedDamage < m_settings.damageThresholdMin)
{
return;
}
+ normalizedDamage = PxClamp<float>(normalizedDamage, 0, m_settings.damageThresholdMax);
const PxVec3 normal = force.getNormalized();
- const float maxDistance = m_settings.damageRadiusMax * impulse01;
- const float minDistance = maxDistance * PxClamp<float>(1 - m_settings.damageAttenuation, 0, 1);
+ const float minDistance = m_settings.damageRadiusMax * normalizedDamage;
+ const float maxDistance = minDistance * PxClamp<float>(m_settings.damageFalloffRadiusFactor, 1, 32);
NvBlastProgramParams programParams;
programParams.damageDescCount = 1;
@@ -397,8 +392,8 @@ void ExtImpactDamageManagerImpl::damageActor(ExtPxActor* actor, PxShape* /*shape
NvBlastExtShearDamageDesc desc[] = {
{
normalizedDamage,
- { normal[0], normal[1], normal[2] }, // shear
- { position[0], position[1], position[2] }, // position
+ { normal[0], normal[1], normal[2] },
+ { position[0], position[1], position[2] },
minDistance,
maxDistance
}
@@ -418,7 +413,7 @@ void ExtImpactDamageManagerImpl::damageActor(ExtPxActor* actor, PxShape* /*shape
NvBlastExtRadialDamageDesc desc[] = {
{
normalizedDamage,
- { position[0], position[1], position[2] }, // position
+ { position[0], position[1], position[2] },
minDistance,
maxDistance
}
diff --git a/sdk/extensions/physx/source/physics/NvBlastExtPxActorImpl.cpp b/sdk/extensions/physx/source/physics/NvBlastExtPxActorImpl.cpp
index c298e07..47463a4 100644
--- a/sdk/extensions/physx/source/physics/NvBlastExtPxActorImpl.cpp
+++ b/sdk/extensions/physx/source/physics/NvBlastExtPxActorImpl.cpp
@@ -161,8 +161,11 @@ ExtPxActorImpl::ExtPxActorImpl(ExtPxFamilyImpl* family, TkActor* tkActor, const
// set initial velocities
if (!(m_rigidDynamic->getRigidBodyFlags() & PxRigidBodyFlag::eKINEMATIC))
{
- m_rigidDynamic->setLinearVelocity(pxActorInfo.m_linearVelocity);
- m_rigidDynamic->setAngularVelocity(pxActorInfo.m_angularVelocity);
+ const PxVec3 COM = m_rigidDynamic->getGlobalPose().transform(m_rigidDynamic->getCMassLocalPose().p);
+ const PxVec3 linearVelocity = pxActorInfo.m_parentLinearVelocity + pxActorInfo.m_parentAngularVelocity.cross(COM - pxActorInfo.m_parentCOM);
+ const PxVec3 angularVelocity = pxActorInfo.m_parentAngularVelocity;
+ m_rigidDynamic->setLinearVelocity(linearVelocity);
+ m_rigidDynamic->setAngularVelocity(angularVelocity);
}
}
diff --git a/sdk/extensions/physx/source/physics/NvBlastExtPxActorImpl.h b/sdk/extensions/physx/source/physics/NvBlastExtPxActorImpl.h
index 5635591..db460e8 100644
--- a/sdk/extensions/physx/source/physics/NvBlastExtPxActorImpl.h
+++ b/sdk/extensions/physx/source/physics/NvBlastExtPxActorImpl.h
@@ -49,8 +49,9 @@ struct PxActorCreateInfo
{
PxTransform m_transform;
PxVec3 m_scale;
- PxVec3 m_linearVelocity;
- PxVec3 m_angularVelocity;
+ PxVec3 m_parentLinearVelocity;
+ PxVec3 m_parentAngularVelocity;
+ PxVec3 m_parentCOM;
};
diff --git a/sdk/extensions/physx/source/physics/NvBlastExtPxFamilyImpl.cpp b/sdk/extensions/physx/source/physics/NvBlastExtPxFamilyImpl.cpp
index 530bbe3..09e26d4 100644
--- a/sdk/extensions/physx/source/physics/NvBlastExtPxFamilyImpl.cpp
+++ b/sdk/extensions/physx/source/physics/NvBlastExtPxFamilyImpl.cpp
@@ -118,8 +118,8 @@ bool ExtPxFamilyImpl::spawn(const physx::PxTransform& pose, const physx::PxVec3&
for (uint32_t i = 0; i < actorCount; ++i)
{
PxActorCreateInfo& pxActorInfo = m_newActorCreateInfo[i];
- pxActorInfo.m_angularVelocity = PxVec3(PxZero);
- pxActorInfo.m_linearVelocity = PxVec3(PxZero);
+ pxActorInfo.m_parentAngularVelocity = PxVec3(PxZero);
+ pxActorInfo.m_parentLinearVelocity = PxVec3(PxZero);
pxActorInfo.m_transform = pose;
pxActorInfo.m_scale = scale;
}
@@ -176,13 +176,15 @@ void ExtPxFamilyImpl::receive(const TkEvent* events, uint32_t eventCount)
for (uint32_t j = totalNewActorsCount; j < totalNewActorsCount + newActorsCount; ++j)
{
- m_newActorCreateInfo[j].m_transform = parentPxActor ? parentPxActor->getGlobalPose() : m_initialTransform;
+ const PxTransform parentTransform = parentPxActor ? parentPxActor->getGlobalPose() : m_initialTransform;
+ m_newActorCreateInfo[j].m_transform = parentTransform;
+ m_newActorCreateInfo[j].m_parentCOM = parentTransform.transform(parentPxActor ? parentPxActor->getCMassLocalPose().p : PxVec3(PxZero));
//TODO: Get the current scale of the actor!
m_newActorCreateInfo[j].m_scale = m_initialScale;
- m_newActorCreateInfo[j].m_linearVelocity = parentPxActor ? parentPxActor->getLinearVelocity() : PxVec3(PxZero);
- m_newActorCreateInfo[j].m_angularVelocity = parentPxActor ? parentPxActor->getAngularVelocity() : PxVec3(PxZero);
+ m_newActorCreateInfo[j].m_parentLinearVelocity = parentPxActor ? parentPxActor->getLinearVelocity() : PxVec3(PxZero);
+ m_newActorCreateInfo[j].m_parentAngularVelocity = parentPxActor ? parentPxActor->getAngularVelocity() : PxVec3(PxZero);
m_newActorsBuffer[j] = splitEvent->children[j - totalNewActorsCount];
}
diff --git a/sdk/extensions/serialization/source/NvBlastExtPxSerializerRAW.cpp b/sdk/extensions/serialization/source/NvBlastExtPxSerializerRAW.cpp
index 526b148..ea9a57e 100644
--- a/sdk/extensions/serialization/source/NvBlastExtPxSerializerRAW.cpp
+++ b/sdk/extensions/serialization/source/NvBlastExtPxSerializerRAW.cpp
@@ -117,6 +117,7 @@ ExtPxAsset* deserializeExtPxAsset(ExtIStream& stream, TkFramework& framework, ph
// Read header
struct LegacyAssetDataHeader
{
+ LegacyAssetDataHeader() : dataType(0), version(0) {}
uint32_t dataType;
uint32_t version;
};