diff options
Diffstat (limited to 'sdk/extensions')
31 files changed, 4330 insertions, 3412 deletions
diff --git a/sdk/extensions/authoring/include/NvBlastExtAuthoring.h b/sdk/extensions/authoring/include/NvBlastExtAuthoring.h index d25ded3..5b6c5d6 100755 --- a/sdk/extensions/authoring/include/NvBlastExtAuthoring.h +++ b/sdk/extensions/authoring/include/NvBlastExtAuthoring.h @@ -48,6 +48,9 @@ namespace Nv class ConvexMeshBuilder;
class BlastBondGenerator;
class MeshCleaner;
+ class PatternGenerator;
+ class Grid;
+ class GridWalker;
struct CollisionParams;
struct CollisionHull;
}
@@ -72,6 +75,22 @@ NVBLAST_API Nv::Blast::Mesh* NvBlastExtAuthoringCreateMesh(const physx::PxVec3* const physx::PxVec2* uv, uint32_t verticesCount, const uint32_t* indices, uint32_t indicesCount);
/**
+Constructs mesh object from triangles represented as arrays of vertices, indices and per facet material.
+User should call Mesh::release() after usage.
+
+\param[in] vertices Array for vertex positions, 3 * verticesCount floats will be read
+\param[in] verticesCount Number of vertices in mesh
+\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)
+\param[in] materials Array of material indices per triangle. If not set default material (0) will be assigned.
+\param[in] materialStride Stride for material indices
+
+\return pointer to Nv::Blast::Mesh if it was created succefully otherwise return nullptr
+*/
+NVBLAST_API Nv::Blast::Mesh* NvBlastExtAuthoringCreateMeshOnlyTriangles(const void* vertices, uint32_t verticesCount,
+ uint32_t* indices, uint32_t indexCount, void* materials = nullptr, uint32_t materialStride = 4);
+
+/**
Constructs mesh object from array of vertices, edges and facets.
User should call release() after usage.
@@ -250,4 +269,19 @@ NVBLAST_API uint32_t NvBlastExtAuthoringFindAssetConnectingBonds float maxSeparation = 0.0f
);
+/**
+Returns pattern generator used for generating fracture patterns for Real Time (RT) fracture
+*/
+NVBLAST_API Nv::Blast::PatternGenerator* NvBlastExtAuthoringCreatePatternGenerator();
+
+/**
+TODO
+*/
+NVBLAST_API Nv::Blast::Grid* NvBlastExtAuthoringCreateGridAccelerator(uint32_t resolution, const Nv::Blast::Mesh* m);
+
+/**
+TODO
+*/
+NVBLAST_API Nv::Blast::GridWalker* NvBlastExtAuthoringCreateGridWalker(Nv::Blast::Grid* parent);
+
#endif // ifndef NVBLASTAUTHORING_H
diff --git a/sdk/extensions/authoring/include/NvBlastExtAuthoringBondGenerator.h b/sdk/extensions/authoring/include/NvBlastExtAuthoringBondGenerator.h index f4bd754..55e252e 100755 --- a/sdk/extensions/authoring/include/NvBlastExtAuthoringBondGenerator.h +++ b/sdk/extensions/authoring/include/NvBlastExtAuthoringBondGenerator.h @@ -113,7 +113,7 @@ public: \return 0 if success
*/
virtual int32_t createBondBetweenMeshes(uint32_t meshACount, const Triangle* meshA, uint32_t meshBCount, const Triangle* meshB,
- NvBlastBond& resultBond, BondGenerationConfig conf = BondGenerationConfig()) = 0;
+ NvBlastBond& resultBond, BondGenerationConfig conf) = 0;
/**
Creates bond description between number of meshes
@@ -149,7 +149,7 @@ public: */
virtual int32_t bondsFromPrefractured(uint32_t meshCount, const uint32_t* geometryOffset, const Triangle* geometry,
const bool* chunkIsSupport, NvBlastBondDesc*& resultBondDescs,
- BondGenerationConfig conf = BondGenerationConfig()) = 0;
+ BondGenerationConfig conf) = 0;
/**
Creates bond description for prefractured meshes, when there is no info about which chunks should be connected with bond.
@@ -167,6 +167,9 @@ public: */
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) = 0;
+
+
+
};
} // namespace Blast
diff --git a/sdk/extensions/authoring/include/NvBlastExtAuthoringCollisionBuilder.h b/sdk/extensions/authoring/include/NvBlastExtAuthoringCollisionBuilder.h index cde115a..d174850 100755 --- a/sdk/extensions/authoring/include/NvBlastExtAuthoringCollisionBuilder.h +++ b/sdk/extensions/authoring/include/NvBlastExtAuthoringCollisionBuilder.h @@ -47,6 +47,7 @@ namespace Blast struct CollisionHull;
struct Triangle;
+struct Vertex;
struct CollisionParams
{
@@ -108,6 +109,8 @@ public: */
virtual physx::PxConvexMesh* buildConvexMesh(const CollisionHull& hull) = 0;
+ virtual physx::PxConvexMesh* buildConvexMeshRT(const Nv::Blast::Vertex* vrs, uint32_t count) = 0;
+
/**
Convex geometry trimming.
diff --git a/sdk/extensions/authoring/include/NvBlastExtAuthoringFractureTool.h b/sdk/extensions/authoring/include/NvBlastExtAuthoringFractureTool.h index b75073a..fd3d985 100755 --- a/sdk/extensions/authoring/include/NvBlastExtAuthoringFractureTool.h +++ b/sdk/extensions/authoring/include/NvBlastExtAuthoringFractureTool.h @@ -46,9 +46,16 @@ class CutoutSet; */
struct ChunkInfo
{
+ enum ChunkFlags
+ {
+ NO_FLAGS = 0,
+ CREATED_BY_ISLAND_DETECTOR = 1
+ };
+
Mesh* meshData;
int32_t parent;
int32_t chunkId;
+ uint32_t flags;
bool isLeaf;
bool isChanged;
};
@@ -447,7 +454,7 @@ public: \param[in] chunkId Chunk ID which should be checked for islands
\return Number of found islands is returned
*/
- virtual int32_t islandDetectionAndRemoving(int32_t chunkId) = 0;
+ virtual int32_t islandDetectionAndRemoving(int32_t chunkId, bool createAtNewDepth = false) = 0;
/**
Check if input mesh contains open edges. Open edges can lead to wrong fracturing results.
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 <algorithm>
#include <memory>
@@ -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.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 <set>
-#include <vector>
-#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<std::vector<uint32_t> > xSegm;
- std::vector<std::vector<uint32_t> > ySegm;
- std::vector<std::vector<uint32_t> > zSegm;
- std::vector<uint32_t> indices;
- std::vector<uint32_t> foundx;
- std::vector<uint32_t> 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<int32_t> > mSpatialMap;
- std::vector<physx::PxBounds3> mCells;
-
-
- // Iterator data
- std::vector<uint32_t> alreadyGotFlag;
- uint32_t alreadyGotValue;
- std::vector<int32_t> 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<int32_t> > mSpatialMap;
- std::vector<physx::PxBounds3> mCubes;
- int32_t mResolution;
-
- // Iterator data
- std::vector<uint32_t> alreadyGotFlag;
- uint32_t alreadyGotValue;
- std::vector<int32_t> 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<PxVec3> intersectionBuffer; std::vector<PxVec3> meshBuffer;
#endif
+
namespace Nv
{
namespace Blast
@@ -148,7 +149,52 @@ namespace Nv int32_t m_chunkId;
};
- float BlastBondGeneratorImpl::processWithMidplanes(TriangleProcessor* trProcessor, const std::vector<PxVec3>& chunk1Points, const std::vector<PxVec3>& chunk2Points,
+ void AddTtAnchorPoints(const Triangle* a, const Triangle* b, std::vector<PxVec3>& 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<PxVec3>& hull1p, const std::vector<PxVec3>& 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<PxVec3> 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<PxVec3> 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<PxVec3> 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<PxVec3> 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<PxVec3> 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<std::pair<uint32_t, uint32_t> >* pairNotToTest)
{
std::vector<std::vector<PxVec3> > chunksPoints(meshCount);
+ std::vector<PxBounds3> 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<uint32_t> trianglesCount(chunkCount);
- std::vector<Triangle*> trianglesBuffer(chunkCount);
+ std::vector<std::shared_ptr<Triangle>> 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<Triangle>(t, [](Triangle* t) {
+ delete[] t;
+ }));
}
if (chunkCount == 0)
{
- return 0;
+ return 0;
}
resultChunkDescriptors = SAFE_ARRAY_NEW(NvBlastChunkDesc, trianglesBuffer.size());
std::vector<Bond> 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<BondInfo> forwardChunks;
- std::vector<BondInfo> 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<NvBlastBondDesc> 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<BondInfo> forwardChunks;
+ std::vector<BondInfo> 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<Triangle> chunkTriangles;
+ std::vector<uint32_t> chunkTrianglesOffsets;
+
+ std::set<std::pair<uint32_t, uint32_t> > 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 <PxPlane.h>
#include <NvBlastExtAuthoringCollisionBuilder.h>
#include <vector>
+#include <set>
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<physx::PxVec3>& chunk1Points, const std::vector<physx::PxVec3>& chunk2Points,
- const std::vector<physx::PxVec3>& hull1p, const std::vector<physx::PxVec3>& 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<physx::PxVec3>& hull1p, const std::vector<physx::PxVec3>& 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<std::pair<uint32_t, uint32_t> >* 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<CollisionHull*> mCHullCache;
std::vector<std::vector<physx::PxVec3> > mHullsPointsCache;
std::vector<physx::PxBounds3 > 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<Facet> newFacets;
std::vector<Edge> 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 <vector>
-#include <map>
#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 <NvBlastExtAuthoringBooleanTool.h>
#include <NvBlastExtAuthoringMeshImpl.h>
-
+#include <NvBlastExtAuthoringMeshUtils.h>
#include <VHACD.h>
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<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, int32_t interiorMaterialId)
+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, 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<uint32_t> 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<ChunkInfo> xSlicedChunks;
std::vector<ChunkInfo> 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<ChunkInfo> xSlicedChunks;
std::vector<ChunkInfo> 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<uint32_t> 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<uint32_t>(compVertices[0].size()),
- static_cast<uint32_t>(compEdges[0].size()), static_cast<uint32_t>(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<uint32_t>(compVertices[i].size()),
- static_cast<uint32_t>(compEdges[i].size()), static_cast<uint32_t>(compFacets[i].size()));
+ delete mChunkData[chunkIndex].meshData;
+ mChunkData[chunkIndex].meshData = new MeshImpl(compVertices[0].data(), compEdges[0].data(), compFacets[0].data(), static_cast<uint32_t>(compVertices[0].size()),
+ static_cast<uint32_t>(compEdges[0].size()), static_cast<uint32_t>(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<uint32_t>(compVertices[i].size()),
+ static_cast<uint32_t>(compEdges[i].size()), static_cast<uint32_t>(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<uint32_t>(compVertices[i].size()),
+ static_cast<uint32_t>(compEdges[i].size()), static_cast<uint32_t>(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<physx::PxVec3>& sites, std::vector<std::vector<int32_t> >& neighboors);
+Mesh* getCellMesh(class BooleanEvaluator& eval, int32_t planeIndexerOffset, int32_t cellId, const std::vector<physx::PxVec3>& sites, std::vector < std::vector<int32_t> >& neighboors, int32_t interiorMaterialId, physx::PxVec3 origin);
+
} // namespace Blast
} // namespace Nv
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 <PxVec3.h>
#include <PxVec2.h>
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 <NvBlastAssert.h>
-#include "PxMath.h"
-#include <cmath>
-#include <string.h>
-#include <vector>
-#include <algorithm>
-
-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<uint32_t>(mFacets.size());
-}
-
-Vertex* MeshImpl::getVerticesWritable()
-{
- return mVertices.data();
-}
-
-Edge* MeshImpl::getEdgesWritable()
-{
- return mEdges.data();
-}
-
-const Vertex* MeshImpl::getVertices() const
-{
- return mVertices.data();
-}
-
-const Edge* MeshImpl::getEdges() const
-{
- return mEdges.data();
-}
-
-uint32_t MeshImpl::getEdgesCount() const
-{
- return static_cast<uint32_t>(mEdges.size());
-}
-uint32_t MeshImpl::getVerticesCount() const
-{
- return static_cast<uint32_t>(mVertices.size());
-}
-Facet* MeshImpl::getFacetsBufferWritable()
-{
- return mFacets.data();
-}
-const Facet* MeshImpl::getFacetsBuffer() const
-{
- return mFacets.data();
-}
-Facet* MeshImpl::getFacetWritable(int32_t facet)
-{
- return &mFacets[facet];
-}
-const Facet* MeshImpl::getFacet(int32_t facet) const
-{
- return &mFacets[facet];
-}
-
-MeshImpl::~MeshImpl()
-{
-}
-
-void MeshImpl::release()
-{
- delete this;
-}
-
-const PxBounds3& MeshImpl::getBoundingBox() const
-{
- return mBounds;
-}
-
-PxBounds3& MeshImpl::getBoundingBoxWritable()
-{
- return mBounds;
-}
-
-void MeshImpl::recalculateBoundingBox()
-{
- mBounds.setEmpty();
- for (uint32_t i = 0; i < mVertices.size(); ++i)
- {
- mBounds.include(mVertices[i].p);
- }
-}
-
-
-
-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<Vertex> 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<Edge> edges;
- std::vector<Facet> 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<uint32_t>(positions.size()), static_cast<uint32_t>(edges.size()), static_cast<uint32_t>(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<Edge>& edges, std::vector<Facet>& 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<Vertex>& vertices, std::vector<Edge>& edges, std::vector<Facet>& 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<Vertex>& 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<Vertex> vertices; vertices.reserve((resolutionX + 1) * (resolutionY + 1) + 12);
- std::vector<Edge> edges;
- std::vector<Facet> 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<Vertex> 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<Edge> edges;
- std::vector<Facet> 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<uint32_t>(positions.size()), static_cast<uint32_t>(edges.size()), static_cast<uint32_t>(facets.size()));
-}
-
-bool CmpSharedFace::operator()(const std::pair<physx::PxVec3, physx::PxVec3>& pv1, const std::pair<physx::PxVec3, physx::PxVec3>& 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<std::vector<physx::PxVec3>>& cutoutPoints,
- float heightBot, float heightTop, float conicityBot, float conicityTop,
- int64_t& id, int32_t seed, int32_t interiorMaterialId, SharedFacesMap& sharedFacesMap)
-{
- std::map<physx::PxVec3, std::pair<uint32_t, std::vector<physx::PxVec3>>, 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<physx::PxVec3>(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<physx::PxVec3>(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<physx::PxVec3>& points, const std::set<int32_t>& 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<Vertex> positions; positions.reserve((resH + 1) * (resP + 1));
- std::vector<Edge> edges; edges.reserve(resH * resP * 6 + (resP + 1) * 2);
- std::vector<Facet> 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<float> 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<uint32_t>(positions.size()), static_cast<uint32_t>(edges.size()), static_cast<uint32_t>(facets.size()));
-}
-
-Mesh* getCuttingCone(const CutoutConfiguration& conf, const std::vector<physx::PxVec3>& points, const std::set<int32_t>& 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/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 <algorithm> + + +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<Vertex> 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<Edge> edges; + std::vector<Facet> 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<uint32_t>(positions.size()), static_cast<uint32_t>(edges.size()), static_cast<uint32_t>(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<Edge>& edges, std::vector<Facet>& 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<Vertex>& vertices, std::vector<Edge>& edges, std::vector<Facet>& 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<Vertex>& 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<Vertex> vertices; vertices.reserve((resolutionX + 1) * (resolutionY + 1) + 12); + std::vector<Edge> edges; + std::vector<Facet> 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<Vertex> 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<Edge> edges; + std::vector<Facet> 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<uint32_t>(positions.size()), static_cast<uint32_t>(edges.size()), static_cast<uint32_t>(facets.size())); + } + + bool CmpSharedFace::operator()(const std::pair<physx::PxVec3, physx::PxVec3>& pv1, const std::pair<physx::PxVec3, physx::PxVec3>& 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<std::vector<physx::PxVec3>>& 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<physx::PxVec3, std::pair<uint32_t, std::vector<physx::PxVec3>>, 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<physx::PxVec3>(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<physx::PxVec3>(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<physx::PxVec3>& points, const std::set<int32_t>& 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<Vertex> positions; positions.reserve((resH + 1) * (resP + 1)); + std::vector<Edge> edges; edges.reserve(resH * resP * 6 + (resP + 1) * 2); + std::vector<Facet> 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<float> 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<uint32_t>(positions.size()), static_cast<uint32_t>(edges.size()), static_cast<uint32_t>(facets.size())); + } + + Mesh* getCuttingCone(const CutoutConfiguration& conf, const std::vector<physx::PxVec3>& points, const std::set<int32_t>& 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<Vertex> positions((pointCount + 1) * 2); + std::vector<Edge> edges(pointCount * 6 + 2); + std::vector<Facet> 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<uint32_t>(positions.size()), static_cast<uint32_t>(edges.size()), static_cast<uint32_t>(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 <cinttypes> +#include <map> +#include <set> +#include <vector> +#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<physx::PxVec3, std::map<uint32_t, uint32_t>, 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<Nv::Blast::Vertex> vertices; + std::vector<Nv::Blast::Edge> edges; + std::vector<Nv::Blast::Facet> facets; +}; + +struct CmpSharedFace +{ + bool operator()(const std::pair<physx::PxVec3, physx::PxVec3>& pv1, const std::pair<physx::PxVec3, physx::PxVec3>& pv2) const; +}; + +typedef std::map<std::pair<physx::PxVec3, physx::PxVec3>, SharedFace, CmpSharedFace> SharedFacesMap; + +struct CutoutConfiguration; + +void buildCuttingConeFaces(const CutoutConfiguration& conf, const std::vector<std::vector<physx::PxVec3>>& 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<physx::PxVec3>& points, const std::set<int32_t>& 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 <vector> +#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<PxVec3> 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<PxVec3> 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<std::vector<int32_t> > 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<PxVec3> 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<PxVec3> 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<uint32_t> 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<Edge> 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)
diff --git a/sdk/extensions/authoringCommon/include/NvBlastExtAuthoringAccelerator.h b/sdk/extensions/authoringCommon/include/NvBlastExtAuthoringAccelerator.h new file mode 100644 index 0000000..fdbc524 --- /dev/null +++ b/sdk/extensions/authoringCommon/include/NvBlastExtAuthoringAccelerator.h @@ -0,0 +1,248 @@ +// 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 <set> +#include <vector> +#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 bound. + \param[in] pos Vertex buffer + \param[in] ed Edge buffer + \param[in] fc Facet which should be tested. + */ + virtual void setState(const physx::PxBounds3* bounds) = 0; + + /** + 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 void setPointCmpDirection(int32_t dir) = 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 physx::PxBounds3* bounds) override; + virtual void setState(const Vertex* pos, const Edge* ed, const Facet& fc) override; + virtual void setState(const physx::PxVec3& point) override; + virtual int32_t getNextFacet() override; + + virtual void setPointCmpDirection(int32_t dir) override {}; + 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 Grid + { + + public: + + friend class GridWalker; + + Grid(int32_t resolution); + void setMesh(const Nv::Blast::Mesh* m); + + private: + int32_t mResolution; + int32_t r3; + int32_t mappedFacetCount; + physx::PxVec3 spos; + physx::PxVec3 deltas; + std::vector< std::vector<int32_t> > mSpatialMap; + }; + + class GridWalker : public SpatialAccelerator // Iterator to traverse the grid + { + public: + GridWalker(Grid* grd); + + virtual void setState(const physx::PxBounds3* bounds) override; + virtual void setState(const Vertex* pos, const Edge* ed, const Facet& fc) override; + virtual void setState(const physx::PxVec3& point) override; + virtual int32_t getNextFacet() override; + virtual void setPointCmpDirection(int32_t dir) override; + private: + Grid* mGrid; + + // Iterator data + std::vector<uint32_t> alreadyGotFlag; + uint32_t alreadyGotValue; + std::vector<int32_t> cellList; + int32_t gotCells; + int32_t mIteratorCell; + int32_t mIteratorFacet; + int32_t pointCmdDir; + }; + + + 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) override; + virtual void setState(const physx::PxBounds3* bounds) override; + virtual void setState(const physx::PxVec3& point) override; + virtual int32_t getNextFacet() override; + virtual void setPointCmpDirection(int32_t dir) override {}; + private: + + + /* + For fast point test. + */ + std::vector<std::vector<uint32_t> > xSegm; + std::vector<std::vector<uint32_t> > ySegm; + std::vector<std::vector<uint32_t> > zSegm; + std::vector<uint32_t> indices; + std::vector<uint32_t> foundx; + std::vector<uint32_t> 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() override; + void setState(const Vertex* pos, const Edge* ed, const Facet& fc) override; + void setState(const physx::PxBounds3* bounds) override; + void setState(const physx::PxVec3& p) override; + void setPointCmpDirection(int32_t dir) override {}; + private: + + void buildAccelStructure(const Vertex* pos, const Edge* edges, const Facet* fc, int32_t facetCount); + + int32_t mResolution; + physx::PxBounds3 mBounds; + std::vector< std::vector<int32_t> > mSpatialMap; + std::vector<physx::PxBounds3> mCells; + + + // Iterator data + std::vector<uint32_t> alreadyGotFlag; + uint32_t alreadyGotValue; + std::vector<int32_t> cellList; + int32_t gotCells; + //std::vector<int32_t> cellList; + int32_t mIteratorCell; + int32_t mIteratorFacet; + }; + + } // namespace Blast +} // namsepace Nv + + +#endif // ifndef NVBLASTEXTAUTHORINGACCELERATOR_H diff --git a/sdk/extensions/authoring/include/NvBlastExtAuthoringMesh.h b/sdk/extensions/authoringCommon/include/NvBlastExtAuthoringMesh.h index b523dcd..b8a8b72 100755..100644 --- a/sdk/extensions/authoring/include/NvBlastExtAuthoringMesh.h +++ b/sdk/extensions/authoringCommon/include/NvBlastExtAuthoringMesh.h @@ -1,154 +1,167 @@ -// 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 NVBLASTAUTHORINGMESH_H
-#define NVBLASTAUTHORINGMESH_H
-
-#include "NvBlastExtAuthoringTypes.h"
-
-namespace Nv
-{
-namespace Blast
-{
-
-/**
- Class for internal mesh representation
-*/
-class Mesh
-{
-public:
- virtual ~Mesh() {}
-
- /**
- Release Mesh memory
- */
- virtual void release() = 0;
-
- /**
- Return true if mesh is valid
- */
- virtual bool isValid() const = 0;
-
- /**
- Return writable pointer on vertices array
- */
- virtual Vertex* getVerticesWritable() = 0;
-
- /**
- Return pointer on vertices array
- */
- virtual const Vertex* getVertices() const = 0;
-
-
- /**
- Return writable pointer on edges array
- */
- virtual Edge* getEdgesWritable() = 0;
-
- /**
- Return pointer on edges array
- */
- virtual const Edge* getEdges() const = 0;
-
- /**
- Return writable pointer on facets array
- */
- virtual Facet* getFacetsBufferWritable() = 0;
-
- /**
- Return pointer on facets array
- */
- virtual const Facet* getFacetsBuffer() const = 0;
-
- /**
- Return writable pointer on specified facet
- */
- virtual Facet* getFacetWritable(int32_t facet) = 0;
- /**
- Return pointer on specified facet
- */
- virtual const Facet* getFacet(int32_t facet) const = 0;
-
- /**
- Return edges count
- */
- virtual uint32_t getEdgesCount() const = 0;
-
- /**
- Return vertices count
- */
- virtual uint32_t getVerticesCount() const = 0;
-
- /**
- Return facet count
- */
- virtual uint32_t getFacetCount() const = 0;
-
- /**
- Return reference on mesh bounding box.
- */
- virtual const physx::PxBounds3& getBoundingBox() const = 0;
-
- /**
- Return writable reference on mesh bounding box.
- */
- virtual physx::PxBounds3& getBoundingBoxWritable() = 0;
-
-
- /**
- Set per-facet material id.
- */
- 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(const int32_t* smoothingGroups) = 0;
-
- /**
- Recalculate bounding box
- */
- virtual void recalculateBoundingBox() = 0;
-
- /**
- Compute mesh volume. Can be used only for triangulated meshes.
- Return mesh volume. If mesh is not triangulated return 0.
- */
- virtual float getMeshVolume() = 0;
-};
-
-} // namespace Blast
-} // namespace Nv
-
-
-#endif // ifndef NVBLASTAUTHORINGMESH_H
+// 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 NVBLASTAUTHORINGMESH_H +#define NVBLASTAUTHORINGMESH_H + +#include "NvBlastExtAuthoringTypes.h" + +namespace Nv +{ +namespace Blast +{ + +/** + Class for internal mesh representation +*/ +class Mesh +{ +public: + + virtual ~Mesh() {} + + /** + Release Mesh memory + */ + virtual void release() = 0; + + /** + Return true if mesh is valid + */ + virtual bool isValid() const = 0; + + /** + Return writable pointer on vertices array + */ + virtual Vertex* getVerticesWritable() = 0; + + /** + Return pointer on vertices array + */ + virtual const Vertex* getVertices() const = 0; + + + /** + Return writable pointer on edges array + */ + virtual Edge* getEdgesWritable() = 0; + + /** + Return pointer on edges array + */ + virtual const Edge* getEdges() const = 0; + + /** + Return writable pointer on facets array + */ + virtual Facet* getFacetsBufferWritable() = 0; + + /** + Return pointer on facets array + */ + virtual const Facet* getFacetsBuffer() const = 0; + + /** + Return writable pointer on specified facet + */ + virtual Facet* getFacetWritable(int32_t facet) = 0; + /** + Return pointer on specified facet + */ + virtual const Facet* getFacet(int32_t facet) const = 0; + + /** + Return edges count + */ + virtual uint32_t getEdgesCount() const = 0; + + /** + Return vertices count + */ + virtual uint32_t getVerticesCount() const = 0; + + /** + Return facet count + */ + virtual uint32_t getFacetCount() const = 0; + + /** + Return reference on mesh bounding box. + */ + virtual const physx::PxBounds3& getBoundingBox() const = 0; + + /** + Return writable reference on mesh bounding box. + */ + virtual physx::PxBounds3& getBoundingBoxWritable() = 0; + + + /** + Set per-facet material id. + */ + 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(const int32_t* smoothingGroups) = 0; + + /** + Recalculate bounding box + */ + virtual void recalculateBoundingBox() = 0; + + /** + Compute mesh volume. Can be used only for triangulated meshes. + Return mesh volume. If mesh is not triangulated return 0. + */ + virtual float getMeshVolume() = 0; + + + /** + Calculate per-facet bounding boxes. + */ + virtual void calcPerFacetBounds() = 0; + + /** + Get pointer on facet bounding box, if not calculated return nullptr. + */ + virtual const physx::PxBounds3* getFacetBound(uint32_t index) const = 0; + +}; + +} // namespace Blast +} // namespace Nv + + +#endif // ifndef NVBLASTAUTHORINGMESH_H diff --git a/sdk/extensions/authoringCommon/include/NvBlastExtAuthoringPatternGenerator.h b/sdk/extensions/authoringCommon/include/NvBlastExtAuthoringPatternGenerator.h new file mode 100644 index 0000000..e446109 --- /dev/null +++ b/sdk/extensions/authoringCommon/include/NvBlastExtAuthoringPatternGenerator.h @@ -0,0 +1,126 @@ +// 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 NVBLASTEXTAUTHORINGPATTERNGENERATOR_H +#define NVBLASTEXTAUTHORINGPATTERNGENERATOR_H + +#include "NvBlastGlobals.h" + +namespace Nv +{ + namespace Blast + { + typedef float (*RNG_CALLBACK)(void); + + struct PatternDescriptor + { + RNG_CALLBACK RNG = nullptr; + + uint32_t interiorMaterialId = 1000; + }; + + struct UniformPatternDesc : public PatternDescriptor + { + uint32_t cellsCount = 2; + + float radiusMin = 0.0f; + float radiusMax = 1.0f; + float radiusDistr = 1.0f; + + float debrisRadiusMult = 1.0f; + }; + + struct BeamPatternDesc : public PatternDescriptor + { + uint32_t cellsCount; + + float radiusMin; + float radiusMax; + }; + + struct RegularRadialPatternDesc : public PatternDescriptor + { + float radiusMin = 0.0f; + float radiusMax = 1.0f; + + uint32_t radialSteps = 3; + uint32_t angularSteps = 8; + + float aperture = .0f; + + float angularNoiseAmplitude = 0.0f; + + float radialNoiseAmplitude = 0.0f; + float radialNoiseFrequency = 0.0f; + + float debrisRadiusMult = 1.0f; + }; + + + struct DamagePattern + { + /** + Used to compute activated chunks. + */ + float activationRadius; + float angle; // For cone shape activation + enum ActivationDistanceType + { + Point = 0, + Line, + Cone + }; + ActivationDistanceType activationType = Point; + // ---------------------------------------------- + + + uint32_t cellsCount; + class Mesh** cellsMeshes = nullptr; + + virtual void release() = 0; + }; + + class PatternGenerator + { + public: + virtual DamagePattern* generateUniformPattern(const UniformPatternDesc* desc) = 0; + virtual DamagePattern* generateBeamPattern(const BeamPatternDesc* desc) = 0; + virtual DamagePattern* generateRegularRadialPattern(const RegularRadialPatternDesc* desc) = 0; + + + virtual DamagePattern* generateVoronoiPattern(uint32_t pointCount, const physx::PxVec3* points, int32_t interiorMaterialId) = 0; + virtual void release() = 0; + }; + + NVBLAST_API void savePatternToObj(DamagePattern* pattern); + + } // namespace Blast +} // namespace Nv + + +#endif // ifndef NVBLASTEXTAUTHORINGMESHCLEANER_H
\ No newline at end of file diff --git a/sdk/extensions/authoring/include/NvBlastExtAuthoringTypes.h b/sdk/extensions/authoringCommon/include/NvBlastExtAuthoringTypes.h index fe5cef2..729453b 100755..100644 --- a/sdk/extensions/authoring/include/NvBlastExtAuthoringTypes.h +++ b/sdk/extensions/authoringCommon/include/NvBlastExtAuthoringTypes.h @@ -1,287 +1,291 @@ -// 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 NVBLASTAUTHORINGTYPES_H
-#define NVBLASTAUTHORINGTYPES_H
-
-#include <PxVec3.h>
-#include <PxVec2.h>
-#include <PxBounds3.h>
-#include "NvBlastTypes.h"
-
-#define NOT_VALID_VERTEX INT32_MAX
-
-namespace Nv
-{
-namespace Blast
-{
-
-/**
- Edge representation
-*/
-struct Edge
-{
- uint32_t s, e;
- Edge() : s(NOT_VALID_VERTEX), e(NOT_VALID_VERTEX){}
- Edge(int s, int e) : s(s), e(e) {}
- bool operator<(const Edge& b) const
- {
- if (s == b.s)
- return e < b.e;
- else
- return s < b.s;
- }
-};
-
-/**
- Mesh vertex representation
-*/
-struct Vertex
-{
- physx::PxVec3 p; // Position
- physx::PxVec3 n; // Normal
- physx::PxVec2 uv[1]; // UV-coordinates array, currently supported only one UV coordinate.
-};
-
-
-// Interior material ID
-#define MATERIAL_INTERIOR 1000
-#define SMOOTHING_GROUP_INTERIOR 1000
-
-
-
-/**
- Mesh triangle representation
-*/
-struct Triangle
-{
- Triangle() {};
- Triangle(Vertex a, Vertex b, Vertex c) : a(a), b(b), c(c) {};
- Vertex a, b, c;
- int32_t userData;
- int32_t materialId;
- int32_t smoothingGroup;
- physx::PxVec3 getNormal() const
- {
- return ((b.p - a.p).cross(c.p - a.p));
- }
- inline Vertex& getVertex(uint32_t index)
- {
- return (&a)[index];
- }
- inline const Vertex& getVertex(uint32_t index) const
- {
- return (&a)[index];
- }
-};
-
-
-/**
- Index based triangle
-*/
-struct TriangleIndexed
-{
- TriangleIndexed() {};
- TriangleIndexed(uint32_t a, uint32_t b, uint32_t c) : ea(a), eb(b), ec(c) {};
-
- uint32_t getOpposite(uint32_t a, uint32_t b)
- {
- if (ea != a && ea != b)
- return ea;
- if (eb != a && eb != b)
- return eb;
- if (ec != a && ec != b)
- return ec;
- return NOT_VALID_VERTEX;
- }
-
- bool isContainEdge(uint32_t a, uint32_t b)
- {
- return (a == ea || a == eb || a == ec) && (b == ea || b == eb || b == ec);
- }
-
- Triangle convertToTriangle(Vertex* vertices)
- {
- Triangle tr;
- tr.a = vertices[ea];
- tr.b = vertices[eb];
- tr.c = vertices[ec];
-
- tr.userData = userData;
- tr.materialId = materialId;
- tr.smoothingGroup = smoothingGroup;
- return tr;
- }
-
- uint32_t ea, eb, ec;
- int32_t materialId;
- int32_t smoothingGroup;
- int32_t userData;
-};
-
-
-
-
-/**
- Mesh facet representation
-*/
-struct Facet
-{
- int32_t firstEdgeNumber;
- uint32_t edgesCount;
- int64_t userData;
- int32_t materialId;
- int32_t smoothingGroup;
-
- Facet(int32_t fEdge = 0, uint32_t eCount = 0, int32_t materialId = 0, int64_t userData = 0, int32_t smoothingGroup = 0) : firstEdgeNumber(fEdge), edgesCount(eCount), userData(userData), materialId(materialId), smoothingGroup(smoothingGroup) {}
-};
-
-/**
- Abstract base class for user-defined random value generator.
-*/
-class RandomGeneratorBase
-{
-public:
- // Generates uniformly distributed value in [0, 1] range.
- virtual float getRandomValue() = 0;
- // Seeds random value generator
- virtual void seed(int32_t seed) = 0;
- virtual ~RandomGeneratorBase() {};
-};
-
-/**
- Collision hull geometry format.
-*/
-struct CollisionHull
-{
- /**
- Collision hull polygon format.
- */
- struct HullPolygon
- {
- // Polygon base plane
- float mPlane[4];
- // Number vertices in polygon
- uint16_t mNbVerts;
- // First index in CollisionHull.indices array for this polygon
- uint16_t mIndexBase;
- };
- ///**
-
- uint32_t pointsCount;
- uint32_t indicesCount;
- uint32_t polygonDataCount;
- physx::PxVec3* points;
- uint32_t* indices;
- HullPolygon* polygonData;
-
- virtual ~CollisionHull() {}
-
- virtual void release() = 0;
-};
-
-/**
- Authoring results. Which contains NvBlastAsset, render and collision meshes
-*/
-struct AuthoringResult
-{
- uint32_t chunkCount; //Number of chunks in Blast asset
-
- uint32_t bondCount; //Number of bonds in Blast asset
-
- NvBlastAsset* asset; //Blast asset
-
- /**
- assetToFractureChunkIdMap used for getting internal FractureChunkId with FractureTool::getChunkId.
- FractureChunkId = FractureTool.getChunkId(aResult.assetToFractureChunkIdMap(AssetChunkId);
- */
- uint32_t* assetToFractureChunkIdMap;
-
- /**
- Offsets for render mesh geometry. Contains chunkCount + 1 element.
- First triangle for i-th chunk: aResult.geometry[aResult.geometryOffset[i]]
- aResult.geometryOffset[chunkCount+1] is total number of triangles in geometry
- */
- uint32_t* geometryOffset;
-
- Triangle* geometry; //Raw array of Triangle for all chunks
-
- NvBlastChunkDesc* chunkDescs; //Array of chunk descriptors. Contains chunkCount elements
-
- NvBlastBondDesc* bondDescs; //Array of bond descriptors. Contains bondCount elements
-
- /**
- Collision hull offsets. Contains chunkCount + 1 element.
- First collision hull for i-th chunk: aResult.collisionHull[aResult.collisionHullOffset[i]]
- aResult.collisionHullOffset[chunkCount+1] is total number of collision hulls in collisionHull
- */
- uint32_t* collisionHullOffset;
-
- CollisionHull** collisionHull; //Raw array of pointers to collision hull for all chunks.
-
- /**
- Array of chunk physics parameters. Contains chunkCount elements
- */
- struct ExtPxChunk* physicsChunks;
-
- /**
- Array of phisics subchunks (convex mesh) descriptors.
- Use collisionHullOffset for accessing elements.
- */
- struct ExtPxSubchunk* physicsSubchunks;
-
- /**
- Array of material names.
- */
- const char** materialNames;
- /**
- Size of array of material names.
- */
-
- uint32_t materialCount;
-
- //// Member functions ////
- virtual ~AuthoringResult() {}
-
- /**
- Free collision hulls data
- */
- virtual void releaseCollisionHulls() = 0;
-
- /**
- Free all data and AuthoringResult
- */
- virtual void release() = 0;
-};
-
-
-} // namespace Blast
-} // namespace Nv
-
-
-#endif // ifndef NVBLASTAUTHORINGTYPES_H
+// 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 NVBLASTAUTHORINGTYPES_H +#define NVBLASTAUTHORINGTYPES_H + +#include <PxVec3.h> +#include <PxVec2.h> +#include <PxBounds3.h> +#include "NvBlastTypes.h" + +#define NOT_VALID_VERTEX UINT32_MAX + +namespace Nv +{ +namespace Blast +{ + +/** + Edge representation +*/ +struct Edge +{ + uint32_t s, e; + Edge() : s(NOT_VALID_VERTEX), e(NOT_VALID_VERTEX){} + Edge(uint32_t s, uint32_t e) : s(s), e(e) {} + bool operator<(const Edge& b) const + { + if (s == b.s) + return e < b.e; + else + return s < b.s; + } + uint32_t operator[](uint32_t i) const + { + return *(reinterpret_cast<const uint32_t*>(this) + i); + } + +}; + +/** + Mesh vertex representation +*/ +struct Vertex +{ + physx::PxVec3 p; // Position + physx::PxVec3 n; // Normal + physx::PxVec2 uv[1]; // UV-coordinates array, currently supported only one UV coordinate. +}; + + +// Interior material ID +#define MATERIAL_INTERIOR 1000 +#define SMOOTHING_GROUP_INTERIOR 1000 + + + +/** + Mesh triangle representation +*/ +struct Triangle +{ + Triangle() {}; + Triangle(Vertex a, Vertex b, Vertex c) : a(a), b(b), c(c) {}; + Vertex a, b, c; + int32_t userData; + int32_t materialId; + int32_t smoothingGroup; + physx::PxVec3 getNormal() const + { + return ((b.p - a.p).cross(c.p - a.p)); + } + inline Vertex& getVertex(uint32_t index) + { + return (&a)[index]; + } + inline const Vertex& getVertex(uint32_t index) const + { + return (&a)[index]; + } +}; + + +/** + Index based triangle +*/ +struct TriangleIndexed +{ + TriangleIndexed() {}; + TriangleIndexed(uint32_t a, uint32_t b, uint32_t c) : ea(a), eb(b), ec(c) {}; + + uint32_t getOpposite(uint32_t a, uint32_t b) + { + if (ea != a && ea != b) + return ea; + if (eb != a && eb != b) + return eb; + if (ec != a && ec != b) + return ec; + return NOT_VALID_VERTEX; + } + + bool isContainEdge(uint32_t a, uint32_t b) + { + return (a == ea || a == eb || a == ec) && (b == ea || b == eb || b == ec); + } + + Triangle convertToTriangle(Vertex* vertices) + { + Triangle tr; + tr.a = vertices[ea]; + tr.b = vertices[eb]; + tr.c = vertices[ec]; + + tr.userData = userData; + tr.materialId = materialId; + tr.smoothingGroup = smoothingGroup; + return tr; + } + + uint32_t ea, eb, ec; + int32_t materialId; + int32_t smoothingGroup; + int32_t userData; +}; + + + + +/** + Mesh facet representation +*/ +struct Facet +{ + int32_t firstEdgeNumber; + uint32_t edgesCount; + int64_t userData; + int32_t materialId; + int32_t smoothingGroup; + Facet(int32_t fEdge = 0, uint32_t eCount = 0, int32_t materialId = 0, int64_t userData = 0, int32_t smoothingGroup = 0) : firstEdgeNumber(fEdge), edgesCount(eCount), userData(userData), materialId(materialId), smoothingGroup(smoothingGroup) {} +}; + +/** + Abstract base class for user-defined random value generator. +*/ +class RandomGeneratorBase +{ +public: + // Generates uniformly distributed value in [0, 1] range. + virtual float getRandomValue() = 0; + // Seeds random value generator + virtual void seed(int32_t seed) = 0; + virtual ~RandomGeneratorBase() {}; +}; + +/** + Collision hull geometry format. +*/ +struct CollisionHull +{ + /** + Collision hull polygon format. + */ + struct HullPolygon + { + // Polygon base plane + float mPlane[4]; + // Number vertices in polygon + uint16_t mNbVerts; + // First index in CollisionHull.indices array for this polygon + uint16_t mIndexBase; + }; + ///** + + uint32_t pointsCount; + uint32_t indicesCount; + uint32_t polygonDataCount; + physx::PxVec3* points; + uint32_t* indices; + HullPolygon* polygonData; + + virtual ~CollisionHull() {} + + virtual void release() = 0; +}; + +/** + Authoring results. Which contains NvBlastAsset, render and collision meshes +*/ +struct AuthoringResult +{ + uint32_t chunkCount; //Number of chunks in Blast asset + + uint32_t bondCount; //Number of bonds in Blast asset + + NvBlastAsset* asset; //Blast asset + + /** + assetToFractureChunkIdMap used for getting internal FractureChunkId with FractureTool::getChunkId. + FractureChunkId = FractureTool.getChunkId(aResult.assetToFractureChunkIdMap(AssetChunkId); + */ + uint32_t* assetToFractureChunkIdMap; + + /** + Offsets for render mesh geometry. Contains chunkCount + 1 element. + First triangle for i-th chunk: aResult.geometry[aResult.geometryOffset[i]] + aResult.geometryOffset[chunkCount+1] is total number of triangles in geometry + */ + uint32_t* geometryOffset; + + Triangle* geometry; //Raw array of Triangle for all chunks + + NvBlastChunkDesc* chunkDescs; //Array of chunk descriptors. Contains chunkCount elements + + NvBlastBondDesc* bondDescs; //Array of bond descriptors. Contains bondCount elements + + /** + Collision hull offsets. Contains chunkCount + 1 element. + First collision hull for i-th chunk: aResult.collisionHull[aResult.collisionHullOffset[i]] + aResult.collisionHullOffset[chunkCount+1] is total number of collision hulls in collisionHull + */ + uint32_t* collisionHullOffset; + + CollisionHull** collisionHull; //Raw array of pointers to collision hull for all chunks. + + /** + Array of chunk physics parameters. Contains chunkCount elements + */ + struct ExtPxChunk* physicsChunks; + + /** + Array of phisics subchunks (convex mesh) descriptors. + Use collisionHullOffset for accessing elements. + */ + struct ExtPxSubchunk* physicsSubchunks; + + /** + Array of material names. + */ + const char** materialNames; + /** + Size of array of material names. + */ + + uint32_t materialCount; + + //// Member functions //// + virtual ~AuthoringResult() {} + + /** + Free collision hulls data + */ + virtual void releaseCollisionHulls() = 0; + + /** + Free all data and AuthoringResult + */ + virtual void release() = 0; +}; + + +} // namespace Blast +} // namespace Nv + + +#endif // ifndef NVBLASTAUTHORINGTYPES_H diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringAccelerator.cpp b/sdk/extensions/authoringCommon/source/NvBlastExtAuthoringAccelerator.cpp index 69c7d65..20ff78b 100755..100644 --- a/sdk/extensions/authoring/source/NvBlastExtAuthoringAccelerator.cpp +++ b/sdk/extensions/authoringCommon/source/NvBlastExtAuthoringAccelerator.cpp @@ -1,845 +1,654 @@ -// This code contains NVIDIA Confidential Information and is disclosed to you
-// under a form of NVIDIA software license agreement provided separately to you.
-//
-// Notice
-// NVIDIA Corporation and its licensors retain all intellectual property and
-// proprietary rights in and to this software and related documentation and
-// any modifications thereto. Any use, reproduction, disclosure, or
-// distribution of this software and related documentation without an express
-// license agreement from NVIDIA Corporation is strictly prohibited.
-//
-// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
-// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
-// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
-// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
-//
-// Information and code furnished is believed to be accurate and reliable.
-// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
-// information or for any infringement of patents or other rights of third parties that may
-// result from its use. No license is granted by implication or otherwise under any patent
-// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
-// This code supersedes and replaces all information previously supplied.
-// NVIDIA Corporation products are not authorized for use as critical
-// components in life support devices or systems without express written approval of
-// NVIDIA Corporation.
-//
-// Copyright (c) 2016-2018 NVIDIA Corporation. All rights reserved.
-
-
-#include "NvBlastExtAuthoringAccelerator.h"
-#include "NvBlastExtAuthoringMesh.h"
-#include "NvBlastExtAuthoringInternalCommon.h"
-
-
-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<PxVec2> 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<PxVec3> 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<SegmentToIndex>& segm, float offset, float mlt, std::vector<std::vector<uint32_t>>& blocks)
-{
- std::set<uint32_t> currentEnabled;
- uint32_t lastBlock = 0;
- for (uint32_t i = 0; i < segm.size(); ++i)
- {
- uint32_t currentBlock = (segm[i].coord - offset) * mlt;
- if (currentBlock >= SWEEP_RESOLUTION) break;
- if (currentBlock != lastBlock)
- {
- for (uint32_t j = lastBlock + 1; j <= currentBlock; ++j)
- {
- for (auto id : currentEnabled)
- blocks[j].push_back(id);
- }
- lastBlock = currentBlock;
- }
- if (segm[i].end == false)
- {
- blocks[lastBlock].push_back(segm[i].index);
- currentEnabled.insert(segm[i].index);
- }
- else
- {
- currentEnabled.erase(segm[i].index);
- }
- }
-
-}
-
-
-SweepingAccelerator::SweepingAccelerator(Nv::Blast::Mesh* in)
-{
- PxBounds3 bnd;
-
- const Vertex* verts = in->getVertices();
- const Edge* edges = in->getEdges();
-
- facetCount = in->getFacetCount();
-
- foundx.resize(facetCount, 0);
- foundy.resize(facetCount, 0);
-
-
- std::vector<SegmentToIndex> xevs;
- std::vector<SegmentToIndex> yevs;
- std::vector<SegmentToIndex> zevs;
-
-
- for (uint32_t i = 0; i < in->getFacetCount(); ++i)
- {
- const Facet* fc = in->getFacet(i);
- bnd.setEmpty();
- for (uint32_t v = 0; v < fc->edgesCount; ++v)
- {
- bnd.include(verts[edges[v + fc->firstEdgeNumber].s].p);
- }
- bnd.scaleFast(1.1f);
- xevs.push_back(SegmentToIndex(bnd.minimum.x, i, false));
- xevs.push_back(SegmentToIndex(bnd.maximum.x, i, true));
-
- yevs.push_back(SegmentToIndex(bnd.minimum.y, i, false));
- yevs.push_back(SegmentToIndex(bnd.maximum.y, i, true));
-
- zevs.push_back(SegmentToIndex(bnd.minimum.z, i, false));
- zevs.push_back(SegmentToIndex(bnd.maximum.z, i, true));
-
- }
-
- std::sort(xevs.begin(), xevs.end());
- std::sort(yevs.begin(), yevs.end());
- std::sort(zevs.begin(), zevs.end());
-
-
- minimal.x = xevs[0].coord;
- minimal.y = yevs[0].coord;
- minimal.z = zevs[0].coord;
-
-
- maximal.x = xevs.back().coord;
- maximal.y = yevs.back().coord;
- maximal.z = zevs.back().coord;
-
-
- rescale = (maximal - minimal) * 1.01f;
- rescale.x = 1.0f / rescale.x * SWEEP_RESOLUTION;
- rescale.y = 1.0f / rescale.y * SWEEP_RESOLUTION;
- rescale.z = 1.0f / rescale.z * SWEEP_RESOLUTION;
-
- xSegm.resize(SWEEP_RESOLUTION);
- ySegm.resize(SWEEP_RESOLUTION);
- zSegm.resize(SWEEP_RESOLUTION);
-
-
- buildIndex(xevs, minimal.x, rescale.x, xSegm);
- buildIndex(yevs, minimal.y, rescale.y, ySegm);
- buildIndex(zevs, minimal.z, rescale.z, zSegm);
-
-
- iterId = 1;
- current = 0;
-}
-
-void SweepingAccelerator::setState(const 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<uint32_t>(current) < indices.size())
- {
- ++current;
- return indices[current - 1];
- }
- else
- return -1;
-}
-
-
-
-
-
-
-} // namespace Blast
-} // namespace Nv
+// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2016-2018 NVIDIA Corporation. All rights reserved. + + +#include "NvBlastExtAuthoringAccelerator.h" +#include "NvBlastExtAuthoringMesh.h" +#include "NvBlastExtAuthoringInternalCommon.h" +#include "NvBlastGlobals.h" + +using namespace physx; + + +namespace Nv +{ +namespace Blast +{ + +DummyAccelerator::DummyAccelerator(int32_t count) :count(count) +{ + current = 0; +} +void DummyAccelerator::setState(const Vertex* pos, const Edge* ed, const Facet& fc) +{ + current = 0; + NV_UNUSED(pos); + NV_UNUSED(ed); + NV_UNUSED(fc); +} +void DummyAccelerator::setState(const physx::PxBounds3* bound) { + current = 0; + NV_UNUSED(bound); +} + +void DummyAccelerator::setState(const physx::PxVec3& point) { + current = 0; + NV_UNUSED(point); +} +int32_t DummyAccelerator::getNextFacet() +{ + if (current < count) + { + ++current; + return current - 1; + } + else + return -1; +} + +Grid::Grid(int32_t resolution) : mResolution(resolution) +{ + /** + Set up 3d grid + */ + r3 = resolution * resolution * resolution; + mSpatialMap.resize(resolution * resolution * resolution); +} + +void Grid::setMesh(const Mesh* m) +{ + physx::PxBounds3 bd = m->getBoundingBox(); + mappedFacetCount = m->getFacetCount(); + bd.fattenFast(0.001f); + spos = bd.minimum; + deltas = PxVec3(mResolution / bd.getDimensions().x, mResolution / bd.getDimensions().y, mResolution / bd.getDimensions().z); + + for (int32_t i = 0; i < r3; ++i) + mSpatialMap[i].clear(); + + const float ofs = 0.001f; + + for (uint32_t fc = 0; fc < m->getFacetCount(); ++fc) + { + physx::PxBounds3 cfc = *m->getFacetBound(fc); + + int32_t is = std::max(0.f, (cfc.minimum.x - spos.x - ofs) * deltas.x); + int32_t ie = std::max(0.f, (cfc.maximum.x - spos.x + ofs) * deltas.x); + + int32_t js = std::max(0.f, (cfc.minimum.y - spos.y - ofs) * deltas.y); + int32_t je = std::max(0.f, (cfc.maximum.y - spos.y + ofs) * deltas.y); + + int32_t ks = std::max(0.f, (cfc.minimum.z - spos.z - ofs) * deltas.z); + int32_t ke = std::max(0.f, (cfc.maximum.z - spos.z + ofs) * deltas.z); + + for (int32_t i = is; i < mResolution && i <= ie; ++i) + { + for (int32_t j = js; j < mResolution && j <= je; ++j) + { + for (int32_t k = ks; k < mResolution && k <= ke; ++k) + { + mSpatialMap[(i * mResolution + j) * mResolution + k].push_back(fc); + } + } + } + } +} + + +GridWalker::GridWalker(Grid* grd) +{ + mGrid = grd; + alreadyGotValue = 0; + alreadyGotFlag.resize(1 << 12); + cellList.resize(1 << 12); + pointCmdDir = 0; +} + +void GridWalker::setState(const Vertex* pos, const Edge* ed, const Facet& fc) +{ + + physx::PxBounds3 cfc(PxBounds3::empty()); + + for (uint32_t v = 0; v < fc.edgesCount; ++v) + { + cfc.include(pos[ed[fc.firstEdgeNumber + v].s].p); + cfc.include(pos[ed[fc.firstEdgeNumber + v].e].p); + } + setState(&cfc); +} + +void GridWalker::setState(const PxBounds3* facetBounding) +{ + alreadyGotValue++; + mIteratorCell = -1; + mIteratorFacet = -1; + gotCells = 0; + + physx::PxBounds3 cfc = *facetBounding; + + + + int32_t is = std::max(0.f, (cfc.minimum.x - mGrid->spos.x - 0.001f) * mGrid->deltas.x); + int32_t ie = std::max(0.f, (cfc.maximum.x - mGrid->spos.x + 0.001f) * mGrid->deltas.x); + + int32_t js = std::max(0.f, (cfc.minimum.y - mGrid->spos.y - 0.001f) * mGrid->deltas.y); + int32_t je = std::max(0.f, (cfc.maximum.y - mGrid->spos.y + 0.001f) * mGrid->deltas.y); + + int32_t ks = std::max(0.f, (cfc.minimum.z - mGrid->spos.z - 0.001f) * mGrid->deltas.z); + int32_t ke = std::max(0.f, (cfc.maximum.z - mGrid->spos.z + 0.001f) * mGrid->deltas.z); + + for (int32_t i = is; i < mGrid->mResolution && i <= ie; ++i) + { + for (int32_t j = js; j < mGrid->mResolution && j <= je; ++j) + { + for (int32_t k = ks; k < mGrid->mResolution && k <= ke; ++k) + { + int32_t id = (i * mGrid->mResolution + j) * mGrid->mResolution + k; + if (!mGrid->mSpatialMap[id].empty()) + { + cellList[gotCells++] = id; + } + + } + } + } + if (gotCells != 0) + { + mIteratorFacet = 0; + mIteratorCell = cellList[gotCells - 1]; + gotCells--; + } +} + + +void GridWalker::setPointCmpDirection(int32_t d) +{ + pointCmdDir = d; +} + + +void GridWalker::setState(const physx::PxVec3& point) +{ + alreadyGotValue++; + mIteratorCell = -1; + mIteratorFacet = -1; + gotCells = 0; + + int32_t is = std::max(0.f, (point.x - mGrid->spos.x - 0.001f) * mGrid->deltas.x); + int32_t ie = std::max(0.f, (point.x - mGrid->spos.x + 0.001f) * mGrid->deltas.x); + + int32_t js = std::max(0.f, (point.y - mGrid->spos.y - 0.001f) * mGrid->deltas.y); + int32_t je = std::max(0.f, (point.y - mGrid->spos.y + 0.001f) * mGrid->deltas.y); + + int32_t ks = 0; + int32_t ke = mGrid->mResolution; + switch (pointCmdDir) + { + case 1: + ks = std::max(0.f, (point.z - mGrid->spos.z - 0.001f) * mGrid->deltas.z); + break; + case -1: + ke = std::max(0.f, (point.z - mGrid->spos.z + 0.001f) * mGrid->deltas.z); + } + + for (int32_t i = is; i < mGrid->mResolution && i <= ie; ++i) + { + for (int32_t j = js; j < mGrid->mResolution && j <= je; ++j) + { + for (int32_t k = ks; k <= ke && k < mGrid->mResolution; ++k) + { + int32_t id = (i * mGrid->mResolution + j) * mGrid->mResolution + k; + if (!mGrid->mSpatialMap[id].empty()) + { + cellList[gotCells++] = id; + } + } + } + } + + if (gotCells != 0) + { + mIteratorFacet = 0; + mIteratorCell = cellList[gotCells - 1]; + gotCells--; + } +} +int32_t GridWalker::getNextFacet() +{ + int32_t facetId = -1; + + while (mIteratorCell != -1) + { + if (mIteratorFacet >= (int32_t)mGrid->mSpatialMap[mIteratorCell].size()) + { + if (gotCells != 0) + { + mIteratorCell = cellList[gotCells - 1]; + gotCells--; + mIteratorFacet = 0; + } + else + { + mIteratorCell = -1; + break; + } + } + if (alreadyGotFlag[mGrid->mSpatialMap[mIteratorCell][mIteratorFacet]] != alreadyGotValue) + { + facetId = mGrid->mSpatialMap[mIteratorCell][mIteratorFacet]; + mIteratorFacet++; + break; + } + else + { + mIteratorFacet++; + } + } + if (facetId != -1) + { + alreadyGotFlag[facetId] = alreadyGotValue; + } + return facetId; +} + + + +BBoxBasedAccelerator::BBoxBasedAccelerator(const Mesh* mesh, int32_t resolution) : mResolution(resolution), alreadyGotValue(1) +{ + mBounds = mesh->getBoundingBox(); + mSpatialMap.resize(resolution * resolution * resolution); + mCells.resize(resolution * resolution * resolution); + int32_t currentCell = 0; + PxVec3 incr = (mBounds.maximum - mBounds.minimum) * (1.0f / mResolution); + for (int32_t z = 0; z < resolution; ++z) + { + for (int32_t y = 0; y < resolution; ++y) + { + for (int32_t x = 0; x < resolution; ++x) + { + mCells[currentCell].minimum.x = mBounds.minimum.x + x * incr.x; + mCells[currentCell].minimum.y = mBounds.minimum.y + y * incr.y; + mCells[currentCell].minimum.z = mBounds.minimum.z + z * incr.z; + + mCells[currentCell].maximum.x = mBounds.minimum.x + (x + 1) * incr.x; + mCells[currentCell].maximum.y = mBounds.minimum.y + (y + 1) * incr.y; + mCells[currentCell].maximum.z = mBounds.minimum.z + (z + 1) * incr.z; + + ++currentCell; + } + } + } + cellList.resize(1 << 16); + gotCells = 0; + buildAccelStructure(mesh->getVertices(), mesh->getEdges(), mesh->getFacetsBuffer(), mesh->getFacetCount()); +} + + +BBoxBasedAccelerator::~BBoxBasedAccelerator() +{ + mResolution = 0; + mBounds.setEmpty(); + mSpatialMap.clear(); + mCells.clear(); + cellList.clear(); +} + +int32_t BBoxBasedAccelerator::getNextFacet() +{ + int32_t facetId = -1; + + while (mIteratorCell != -1) + { + if (mIteratorFacet >= (int32_t)mSpatialMap[mIteratorCell].size()) + { + if (gotCells != 0) + { + mIteratorCell = cellList[gotCells - 1]; + gotCells--; + mIteratorFacet = 0; + } + else + { + mIteratorCell = -1; + break; + } + } + if (alreadyGotFlag[mSpatialMap[mIteratorCell][mIteratorFacet]] != alreadyGotValue) + { + facetId = mSpatialMap[mIteratorCell][mIteratorFacet]; + mIteratorFacet++; + break; + } + else + { + mIteratorFacet++; + } + } + if (facetId != -1) + { + alreadyGotFlag[facetId] = alreadyGotValue; + } + return facetId; +} + + +void BBoxBasedAccelerator::setState(const Vertex* pos, const Edge* ed, const Facet& fc) +{ + + physx::PxBounds3 cfc(PxBounds3::empty()); + + for (uint32_t v = 0; v < fc.edgesCount; ++v) + { + cfc.include(pos[ed[fc.firstEdgeNumber + v].s].p); + cfc.include(pos[ed[fc.firstEdgeNumber + v].e].p); + } + setState(&cfc); +} + +void BBoxBasedAccelerator::setState(const PxBounds3* facetBox) +{ + alreadyGotValue++; + mIteratorCell = -1; + mIteratorFacet = -1; + gotCells = 0; + + for (uint32_t i = 0; i < mCells.size(); ++i) + { + if (weakBoundingBoxIntersection(mCells[i], *facetBox)) + { + if (!mSpatialMap[i].empty()) + cellList[gotCells++] = i; + } + } + if (gotCells != 0) + { + mIteratorFacet = 0; + mIteratorCell = cellList[gotCells - 1]; + gotCells--; + } +} + + +void BBoxBasedAccelerator::setState(const PxVec3& p) +{ + alreadyGotValue++; + mIteratorCell = -1; + mIteratorFacet = -1; + gotCells = 0; + int32_t perSlice = mResolution * mResolution; + for (uint32_t i = 0; i < mCells.size(); ++i) + { + if (mCells[i].contains(p)) + { + int32_t xyCellId = i % perSlice; + for (int32_t zCell = 0; zCell < mResolution; ++zCell) + { + int32_t cell = zCell * perSlice + xyCellId; + if (!mSpatialMap[cell].empty()) + cellList[gotCells++] = cell; + } + } + } + if (gotCells != 0) + { + mIteratorFacet = 0; + mIteratorCell = cellList[gotCells - 1]; + gotCells--; + } +} + + +void BBoxBasedAccelerator::buildAccelStructure(const Vertex* pos, const Edge* edges, const Facet* fc, int32_t facetCount) +{ + for (int32_t facet = 0; facet < facetCount; ++facet) + { + PxBounds3 bBox; + bBox.setEmpty(); + const Edge* edge = &edges[0] + fc->firstEdgeNumber; + int32_t count = fc->edgesCount; + for (int32_t ec = 0; ec < count; ++ec) + { + bBox.include(pos[edge->s].p); + bBox.include(pos[edge->e].p); + edge++; + } + + for (uint32_t i = 0; i < mCells.size(); ++i) + { + if (weakBoundingBoxIntersection(mCells[i], bBox)) + { + mSpatialMap[i].push_back(facet); + } + } + fc++; + } + alreadyGotFlag.resize(facetCount, 0); +} + +#define SWEEP_RESOLUTION 2048 + +void buildIndex(std::vector<SegmentToIndex>& segm, float offset, float mlt, std::vector<std::vector<uint32_t>>& blocks) +{ + std::set<uint32_t> currentEnabled; + uint32_t lastBlock = 0; + for (uint32_t i = 0; i < segm.size(); ++i) + { + uint32_t currentBlock = (segm[i].coord - offset) * mlt; + if (currentBlock >= SWEEP_RESOLUTION) break; + if (currentBlock != lastBlock) + { + for (uint32_t j = lastBlock + 1; j <= currentBlock; ++j) + { + for (auto id : currentEnabled) + blocks[j].push_back(id); + } + lastBlock = currentBlock; + } + if (segm[i].end == false) + { + blocks[lastBlock].push_back(segm[i].index); + currentEnabled.insert(segm[i].index); + } + else + { + currentEnabled.erase(segm[i].index); + } + } + +} + + +SweepingAccelerator::SweepingAccelerator(Nv::Blast::Mesh* in) +{ + PxBounds3 bnd; + + const Vertex* verts = in->getVertices(); + const Edge* edges = in->getEdges(); + + facetCount = in->getFacetCount(); + + foundx.resize(facetCount, 0); + foundy.resize(facetCount, 0); + + + std::vector<SegmentToIndex> xevs; + std::vector<SegmentToIndex> yevs; + std::vector<SegmentToIndex> zevs; + + + for (uint32_t i = 0; i < in->getFacetCount(); ++i) + { + const Facet* fc = in->getFacet(i); + bnd.setEmpty(); + for (uint32_t v = 0; v < fc->edgesCount; ++v) + { + bnd.include(verts[edges[v + fc->firstEdgeNumber].s].p); + } + bnd.scaleFast(1.1f); + xevs.push_back(SegmentToIndex(bnd.minimum.x, i, false)); + xevs.push_back(SegmentToIndex(bnd.maximum.x, i, true)); + + yevs.push_back(SegmentToIndex(bnd.minimum.y, i, false)); + yevs.push_back(SegmentToIndex(bnd.maximum.y, i, true)); + + zevs.push_back(SegmentToIndex(bnd.minimum.z, i, false)); + zevs.push_back(SegmentToIndex(bnd.maximum.z, i, true)); + + } + + std::sort(xevs.begin(), xevs.end()); + std::sort(yevs.begin(), yevs.end()); + std::sort(zevs.begin(), zevs.end()); + + + minimal.x = xevs[0].coord; + minimal.y = yevs[0].coord; + minimal.z = zevs[0].coord; + + + maximal.x = xevs.back().coord; + maximal.y = yevs.back().coord; + maximal.z = zevs.back().coord; + + + rescale = (maximal - minimal) * 1.01f; + rescale.x = 1.0f / rescale.x * SWEEP_RESOLUTION; + rescale.y = 1.0f / rescale.y * SWEEP_RESOLUTION; + rescale.z = 1.0f / rescale.z * SWEEP_RESOLUTION; + + xSegm.resize(SWEEP_RESOLUTION); + ySegm.resize(SWEEP_RESOLUTION); + zSegm.resize(SWEEP_RESOLUTION); + + + buildIndex(xevs, minimal.x, rescale.x, xSegm); + buildIndex(yevs, minimal.y, rescale.y, ySegm); + buildIndex(zevs, minimal.z, rescale.z, zSegm); + + + iterId = 1; + current = 0; +} + +void SweepingAccelerator::setState(const PxBounds3* facetBounds) +{ + current = 0; + indices.clear(); + + PxBounds3 bnd = *facetBounds; + + bnd.scaleFast(1.1); + uint32_t start = (std::max(0.0f, bnd.minimum.x - minimal.x)) * rescale.x; + uint32_t end = (std::max(0.0f, bnd.maximum.x - minimal.x)) * rescale.x; + for (uint32_t i = start; i <= end && i < SWEEP_RESOLUTION; ++i) + { + for (auto id : xSegm[i]) + { + foundx[id] = iterId; + } + } + start = (std::max(0.0f, bnd.minimum.y - minimal.y)) * rescale.y; + end = (std::max(0.0f, bnd.maximum.y - minimal.y)) * rescale.y; + for (uint32_t i = start; i <= end && i < SWEEP_RESOLUTION; ++i) + { + for (auto id : ySegm[i]) + { + foundy[id] = iterId; + } + } + start = (std::max(0.0f, bnd.minimum.z - minimal.z)) * rescale.z; + end = (std::max(0.0f, bnd.maximum.z - minimal.z)) * rescale.z; + for (uint32_t i = start; i <= end && i < SWEEP_RESOLUTION; ++i) + { + for (auto id : zSegm[i]) + { + if (foundy[id] == iterId && foundx[id] == iterId) + { + foundx[id] = iterId + 1; + foundy[id] = iterId + 1; + indices.push_back(id); + } + } + } + + iterId += 2; +} + +void SweepingAccelerator::setState(const Vertex* pos, const Edge* ed, const Facet& fc) +{ + + physx::PxBounds3 cfc(PxBounds3::empty()); + + for (uint32_t v = 0; v < fc.edgesCount; ++v) + { + cfc.include(pos[ed[fc.firstEdgeNumber + v].s].p); + cfc.include(pos[ed[fc.firstEdgeNumber + v].e].p); + } + setState(&cfc); +} + + +void SweepingAccelerator::setState(const physx::PxVec3& point) { + + indices.clear(); + + /*for (uint32_t i = 0; i < facetCount; ++i) + { + indices.push_back(i); + }*/ + + uint32_t xIndex = (point.x - minimal.x) * rescale.x; + uint32_t yIndex = (point.y- minimal.y) * rescale.y; + + for (uint32_t i = 0; i < xSegm[xIndex].size(); ++i) + { + foundx[xSegm[xIndex][i]] = iterId; + } + for (uint32_t i = 0; i < ySegm[yIndex].size(); ++i) + { + if (foundx[ySegm[yIndex][i]] == iterId) + { + indices.push_back(ySegm[yIndex][i]); + } + } + iterId++; + current = 0; + NV_UNUSED(point); +} +int32_t SweepingAccelerator::getNextFacet() +{ + if (static_cast<uint32_t>(current) < indices.size()) + { + ++current; + return indices[current - 1]; + } + else + return -1; +} + +} // namespace Blast +} // namespace Nv diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringInternalCommon.h b/sdk/extensions/authoringCommon/source/NvBlastExtAuthoringInternalCommon.h index d337d43..28d3349 100755..100644 --- a/sdk/extensions/authoring/source/NvBlastExtAuthoringInternalCommon.h +++ b/sdk/extensions/authoringCommon/source/NvBlastExtAuthoringInternalCommon.h @@ -1,260 +1,265 @@ -// This code contains NVIDIA Confidential Information and is disclosed to you
-// under a form of NVIDIA software license agreement provided separately to you.
-//
-// Notice
-// NVIDIA Corporation and its licensors retain all intellectual property and
-// proprietary rights in and to this software and related documentation and
-// any modifications thereto. Any use, reproduction, disclosure, or
-// distribution of this software and related documentation without an express
-// license agreement from NVIDIA Corporation is strictly prohibited.
-//
-// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
-// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
-// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
-// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
-//
-// Information and code furnished is believed to be accurate and reliable.
-// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
-// information or for any infringement of patents or other rights of third parties that may
-// result from its use. No license is granted by implication or otherwise under any patent
-// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
-// This code supersedes and replaces all information previously supplied.
-// NVIDIA Corporation products are not authorized for use as critical
-// components in life support devices or systems without express written approval of
-// NVIDIA Corporation.
-//
-// Copyright (c) 2018 NVIDIA Corporation. All rights reserved.
-
-
-#ifndef NVBLASTINTERNALCOMMON_H
-#define NVBLASTINTERNALCOMMON_H
-#include "NvBlastExtAuthoringTypes.h"
-#include <algorithm>
-
-using namespace physx;
-
-namespace Nv
-{
-namespace Blast
-{
-
-/**
-Edge representation with index of parent facet
-*/
-struct EdgeWithParent
-{
- 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
-
+// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2018 NVIDIA Corporation. All rights reserved. + + +#ifndef NVBLASTINTERNALCOMMON_H +#define NVBLASTINTERNALCOMMON_H +#include "NvBlastExtAuthoringTypes.h" +#include <algorithm> + +using namespace physx; + +namespace Nv +{ +namespace Blast +{ + +/** +Edge representation with index of parent facet +*/ +struct EdgeWithParent +{ + uint32_t s, e; // Starting and ending vertices + uint32_t parent; // Parent facet index + EdgeWithParent() : s(0), e(0), parent(0) {} + EdgeWithParent(uint32_t s, uint32_t e, uint32_t p) : s(s), e(e), parent(p) {} +}; + + +/** +Comparator for sorting edges according to parent facet number. +*/ +struct EdgeComparator +{ + bool operator()(const EdgeWithParent& a, const EdgeWithParent& b) const + { + if (a.parent == b.parent) + { + if (a.s == b.s) + { + return a.e < b.e; + } + else + { + return a.s < b.s; + } + } + else + { + return a.parent < b.parent; + } + } +}; + + +/** +Vertex projection direction flag. +*/ +enum ProjectionDirections +{ + YZ_PLANE = 1 << 1, + XY_PLANE = 1 << 2, + ZX_PLANE = 1 << 3, + + OPPOSITE_WINDING = 1 << 4 +}; + +/** +Computes best direction to project points. +*/ +NV_FORCE_INLINE ProjectionDirections getProjectionDirection(const physx::PxVec3& normal) +{ + float maxv = std::max(std::abs(normal.x), std::max(std::abs(normal.y), std::abs(normal.z))); + ProjectionDirections retVal; + if (maxv == std::abs(normal.x)) + { + retVal = YZ_PLANE; + if (normal.x < 0) retVal = (ProjectionDirections)((int)retVal | (int)OPPOSITE_WINDING); + return retVal; + } + if (maxv == std::abs(normal.y)) + { + retVal = ZX_PLANE; + if (normal.y > 0) retVal = (ProjectionDirections)((int)retVal | (int)OPPOSITE_WINDING); + return retVal; + } + retVal = XY_PLANE; + if (normal.z < 0) retVal = (ProjectionDirections)((int)retVal | (int)OPPOSITE_WINDING); + return retVal; +} + + +/** +Computes point projected on given axis aligned plane. +*/ +NV_FORCE_INLINE physx::PxVec2 getProjectedPoint(const physx::PxVec3& point, ProjectionDirections dir) +{ + if (dir & YZ_PLANE) + { + return physx::PxVec2(point.y, point.z); + } + if (dir & ZX_PLANE) + { + return physx::PxVec2(point.x, point.z); + } + return physx::PxVec2(point.x, point.y); +} + +/** +Computes point projected on given axis aligned plane, this method is polygon-winding aware. +*/ +NV_FORCE_INLINE physx::PxVec2 getProjectedPointWithWinding(const physx::PxVec3& point, ProjectionDirections dir) +{ + if (dir & YZ_PLANE) + { + if (dir & OPPOSITE_WINDING) + { + return physx::PxVec2(point.z, point.y); + } + else + return physx::PxVec2(point.y, point.z); + } + if (dir & ZX_PLANE) + { + if (dir & OPPOSITE_WINDING) + { + return physx::PxVec2(point.z, point.x); + } + return physx::PxVec2(point.x, point.z); + } + if (dir & OPPOSITE_WINDING) + { + return physx::PxVec2(point.y, point.x); + } + return physx::PxVec2(point.x, point.y); +} + + + +#define MAXIMUM_EXTENT 1000 * 1000 * 1000 +#define BBOX_TEST_EPS 1e-5f + +/** +Test fattened bounding box intersetion. +*/ +NV_INLINE bool weakBoundingBoxIntersection(const physx::PxBounds3& aBox, const physx::PxBounds3& bBox) +{ + if (std::max(aBox.minimum.x, bBox.minimum.x) > std::min(aBox.maximum.x, bBox.maximum.x) + BBOX_TEST_EPS) + return false; + if (std::max(aBox.minimum.y, bBox.minimum.y) > std::min(aBox.maximum.y, bBox.maximum.y) + BBOX_TEST_EPS) + return false; + if (std::max(aBox.minimum.z, bBox.minimum.z) > std::min(aBox.maximum.z, bBox.maximum.z) + BBOX_TEST_EPS) + return false; + return true; +} + + + +/** +Test segment vs plane intersection. If segment intersects the plane true is returned. Point of intersection is written into 'result'. +*/ +NV_INLINE bool getPlaneSegmentIntersection(const PxPlane& pl, const PxVec3& a, const PxVec3& b, PxVec3& result) +{ + float div = (b - a).dot(pl.n); + if (PxAbs(div) < 0.0001f) + { + if (pl.contains(a)) + { + result = a; + return true; + } + else + { + return false; + } + } + float t = (-a.dot(pl.n) - pl.d) / div; + if (t < 0.0f || t > 1.0f) + { + return false; + } + result = (b - a) * t + a; + return true; +} + + +#define POS_COMPARISON_OFFSET 1e-5f +#define NORM_COMPARISON_OFFSET 1e-3f +/** +Vertex comparator for vertex welding. +*/ +struct VrtComp +{ + bool operator()(const Vertex& a, const Vertex& b) const + { + if (a.p.x + POS_COMPARISON_OFFSET < b.p.x) return true; + if (a.p.x - POS_COMPARISON_OFFSET > b.p.x) return false; + if (a.p.y + POS_COMPARISON_OFFSET < b.p.y) return true; + if (a.p.y - POS_COMPARISON_OFFSET > b.p.y) return false; + if (a.p.z + POS_COMPARISON_OFFSET < b.p.z) return true; + if (a.p.z - POS_COMPARISON_OFFSET > b.p.z) return false; + + if (a.n.x + NORM_COMPARISON_OFFSET < b.n.x) return true; + if (a.n.x - NORM_COMPARISON_OFFSET > b.n.x) return false; + if (a.n.y + NORM_COMPARISON_OFFSET < b.n.y) return true; + if (a.n.y - NORM_COMPARISON_OFFSET > b.n.y) return false; + if (a.n.z + NORM_COMPARISON_OFFSET < b.n.z) return true; + if (a.n.z - NORM_COMPARISON_OFFSET > b.n.z) return false; + + + if (a.uv[0].x + NORM_COMPARISON_OFFSET < b.uv[0].x) return true; + if (a.uv[0].x - NORM_COMPARISON_OFFSET > b.uv[0].x) return false; + if (a.uv[0].y + NORM_COMPARISON_OFFSET < b.uv[0].y) return true; + return false; + }; +}; + +/** +Vertex comparator for vertex welding (not accounts normal and uv parameters of vertice). +*/ +struct VrtPositionComparator +{ + bool operator()(const physx::PxVec3& a, const physx::PxVec3& b) const + { + if (a.x + POS_COMPARISON_OFFSET < b.x) return true; + if (a.x - POS_COMPARISON_OFFSET > b.x) return false; + if (a.y + POS_COMPARISON_OFFSET < b.y) return true; + if (a.y - POS_COMPARISON_OFFSET > b.y) return false; + if (a.z + POS_COMPARISON_OFFSET < b.z) return true; + if (a.z - POS_COMPARISON_OFFSET > b.z) return false; + return false; + }; + bool operator()(const Vertex& a, const Vertex& b) const + { + return operator()(a.p, b.p); + }; +}; + +} // namespace Blast +} // namespace Nv + #endif
\ No newline at end of file diff --git a/sdk/extensions/authoringCommon/source/NvBlastExtAuthoringMeshImpl.cpp b/sdk/extensions/authoringCommon/source/NvBlastExtAuthoringMeshImpl.cpp new file mode 100644 index 0000000..f0c9a84 --- /dev/null +++ b/sdk/extensions/authoringCommon/source/NvBlastExtAuthoringMeshImpl.cpp @@ -0,0 +1,358 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2016-2018 NVIDIA Corporation. All rights reserved. + +#define _CRT_SECURE_NO_WARNINGS + +#include "NvBlastExtAuthoringMeshImpl.h" +#include "NvBlastExtAuthoringTypes.h" +#include <NvBlastAssert.h> +#include "PxMath.h" +#include <cmath> +#include <string.h> +#include <vector> +#include <algorithm> + +using physx::PxVec2; +using physx::PxVec3; +using physx::PxBounds3; + + +namespace Nv +{ +namespace Blast +{ + +MeshImpl::MeshImpl(const PxVec3* position, const PxVec3* normals, const PxVec2* uv, uint32_t verticesCount, const uint32_t* indices, uint32_t indicesCount) +{ + + mVertices.resize(verticesCount); + for (uint32_t i = 0; i < mVertices.size(); ++i) + { + mVertices[i].p = position[i]; + } + if (normals != 0) + { + for (uint32_t i = 0; i < mVertices.size(); ++i) + { + mVertices[i].n = normals[i]; + } + + } + else + { + for (uint32_t i = 0; i < mVertices.size(); ++i) + { + mVertices[i].n = PxVec3(0, 0, 0); + } + } + if (uv != 0) + { + for (uint32_t i = 0; i < mVertices.size(); ++i) + { + mVertices[i].uv[0] = uv[i]; + } + } + else + { + for (uint32_t i = 0; i < mVertices.size(); ++i) + { + mVertices[i].uv[0] = PxVec2(0, 0); + } + } + mEdges.resize(indicesCount); + mFacets.resize(indicesCount / 3); + + + int32_t facetId = 0; + for (uint32_t i = 0; i < indicesCount; i += 3) + { + mEdges[i].s = indices[i]; + mEdges[i].e = indices[i + 1]; + + mEdges[i + 1].s = indices[i + 1]; + mEdges[i + 1].e = indices[i + 2]; + + mEdges[i + 2].s = indices[i + 2]; + mEdges[i + 2].e = indices[i]; + mFacets[facetId].firstEdgeNumber = i; + mFacets[facetId].edgesCount = 3; + mFacets[facetId].materialId = 0; + //Unassigned for now + mFacets[facetId].smoothingGroup = -1; + facetId++; + } + recalculateBoundingBox(); +} + +MeshImpl::MeshImpl(const Vertex* vertices, const Edge* edges, const Facet* facets, uint32_t posCount, uint32_t edgesCount, uint32_t facetsCount) +{ + mVertices.resize(posCount); + mEdges.resize(edgesCount); + mFacets.resize(facetsCount); + + memcpy(mVertices.data(), vertices, sizeof(Vertex) * posCount); + memcpy(mEdges.data(), edges, sizeof(Edge) * edgesCount); + memcpy(mFacets.data(), facets, sizeof(Facet) * facetsCount); + recalculateBoundingBox(); +} + +MeshImpl::MeshImpl(const Vertex* vertices, uint32_t count) +{ + mVertices = std::vector<Vertex>(vertices, vertices + count); + mEdges.resize(count); + mFacets.resize(count / 3); + uint32_t vp = 0; + for (uint32_t i = 0; i < count; i += 3) + { + mEdges[i].s = vp; + mEdges[i].e = vp + 1; + + mEdges[i + 1].s = vp + 1; + mEdges[i + 1].e = vp + 2; + + mEdges[i + 2].s = vp + 2; + mEdges[i + 2].e = vp; + vp += 3; + } + for (uint32_t i = 0; i < count / 3; ++i) + { + mFacets[i].edgesCount = 3; + mFacets[i].firstEdgeNumber = i * 3; + } + recalculateBoundingBox(); +} + +MeshImpl::MeshImpl(const Vertex* vertices, uint32_t count, uint32_t* indices, uint32_t indexCount, void* materials, uint32_t materialStride) +{ + mVertices = std::vector<Vertex>(vertices, vertices + count); + mEdges.resize(indexCount); + mFacets.resize(indexCount / 3); + + for (uint32_t i = 0; i < indexCount; i += 3) + { + mEdges[i].s = indices[i]; + mEdges[i].e = indices[i + 1]; + + mEdges[i + 1].s = indices[i + 1]; + mEdges[i + 1].e = indices[i + 2]; + + mEdges[i + 2].s = indices[i + 2]; + mEdges[i + 2].e = indices[i]; + } + for (uint32_t i = 0; i < indexCount / 3; ++i) + { + mFacets[i].edgesCount = 3; + mFacets[i].firstEdgeNumber = i * 3; + mFacets[i].userData = 0; + if (materials != nullptr) + { + mFacets[i].materialId = *(uint32_t*)((uint8_t*)materials + i * materialStride); + } + } + recalculateBoundingBox(); +} + + + +float MeshImpl::getMeshVolume() +{ + /** + Check if mesh boundary consist only of triangles + */ + for (uint32_t i = 0; i < mFacets.size(); ++i) + { + if (mFacets[i].edgesCount != 3) + { + return 0.0f; + } + } + + float volume = 0; + for (uint32_t i = 0; i < mFacets.size(); ++i) + { + int32_t offset = mFacets[i].firstEdgeNumber; + PxVec3& a = mVertices[mEdges[offset].s].p; + PxVec3& b = mVertices[mEdges[offset + 1].s].p; + PxVec3& c = mVertices[mEdges[offset + 2].s].p; + + volume += (a.x * b.y * c.z - a.x * b.z * c.y - a.y * b.x * c.z + a.y * b.z * c.x + a.z * b.x * c.y - a.z * b.y * c.x); + } + return (1.0f / 6.0f) * std::abs(volume); +} + + +uint32_t MeshImpl::getFacetCount() const +{ + return static_cast<uint32_t>(mFacets.size()); +} + +Vertex* MeshImpl::getVerticesWritable() +{ + return mVertices.data(); +} + +Edge* MeshImpl::getEdgesWritable() +{ + return mEdges.data(); +} + +const Vertex* MeshImpl::getVertices() const +{ + return mVertices.data(); +} + +const Edge* MeshImpl::getEdges() const +{ + return mEdges.data(); +} + +uint32_t MeshImpl::getEdgesCount() const +{ + return static_cast<uint32_t>(mEdges.size()); +} +uint32_t MeshImpl::getVerticesCount() const +{ + return static_cast<uint32_t>(mVertices.size()); +} +Facet* MeshImpl::getFacetsBufferWritable() +{ + return mFacets.data(); +} +const Facet* MeshImpl::getFacetsBuffer() const +{ + return mFacets.data(); +} +Facet* MeshImpl::getFacetWritable(int32_t facet) +{ + return &mFacets[facet]; +} +const Facet* MeshImpl::getFacet(int32_t facet) const +{ + return &mFacets[facet]; +} + +MeshImpl::~MeshImpl() +{ +} + +void MeshImpl::release() +{ + delete this; +} + +const PxBounds3& MeshImpl::getBoundingBox() const +{ + return mBounds; +} + +PxBounds3& MeshImpl::getBoundingBoxWritable() +{ + return mBounds; +} + + +void MeshImpl::recalculateBoundingBox() +{ + mBounds.setEmpty(); + for (uint32_t i = 0; i < mVertices.size(); ++i) + { + mBounds.include(mVertices[i].p); + } + calcPerFacetBounds(); +} + +const physx::PxBounds3* MeshImpl::getFacetBound(uint32_t index) const +{ + if (mPerFacetBounds.empty()) + { + return nullptr; + } + return &mPerFacetBounds[index]; +} + +void MeshImpl::calcPerFacetBounds() +{ + mPerFacetBounds.resize(mFacets.size()); + + for (uint32_t i = 0; i < mFacets.size(); ++i) + { + auto& fb = mPerFacetBounds[i]; + fb.setEmpty(); + + for (uint32_t v = 0; v < mFacets[i].edgesCount; ++v) + { + fb.include(mVertices[mEdges[mFacets[i].firstEdgeNumber + v].s].p); + fb.include(mVertices[mEdges[mFacets[i].firstEdgeNumber + v].e].p); + } + } +} + +void MeshImpl::setMaterialId(const int32_t* materialId) +{ + if (materialId != nullptr) + { + for (uint32_t i = 0; i < mFacets.size(); ++i) + { + mFacets[i].materialId = *materialId; + ++materialId; + } + } +} + +bool MeshImpl::isValid() const +{ + return mVertices.size() > 0 && mEdges.size() > 0 && mFacets.size() > 0; +} + + +void MeshImpl::replaceMaterialId(int32_t oldMaterialId, int32_t newMaterialId) +{ + for (uint32_t i = 0; i < mFacets.size(); ++i) + { + if (mFacets[i].materialId == oldMaterialId) + { + mFacets[i].materialId = newMaterialId; + } + } +} + +void MeshImpl::setSmoothingGroup(const int32_t* smoothingGroups) +{ + if (smoothingGroups != nullptr) + { + for (uint32_t i = 0; i < mFacets.size(); ++i) + { + mFacets[i].smoothingGroup = *smoothingGroups; + ++smoothingGroups; + } + } +} + + + +} // namespace Blast +} // namespace Nv diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringMeshImpl.h b/sdk/extensions/authoringCommon/source/NvBlastExtAuthoringMeshImpl.h index c0c80a8..0f4c339 100755..100644 --- a/sdk/extensions/authoring/source/NvBlastExtAuthoringMeshImpl.h +++ b/sdk/extensions/authoringCommon/source/NvBlastExtAuthoringMeshImpl.h @@ -1,289 +1,200 @@ -// This code contains NVIDIA Confidential Information and is disclosed to you
-// under a form of NVIDIA software license agreement provided separately to you.
-//
-// Notice
-// NVIDIA Corporation and its licensors retain all intellectual property and
-// proprietary rights in and to this software and related documentation and
-// any modifications thereto. Any use, reproduction, disclosure, or
-// distribution of this software and related documentation without an express
-// license agreement from NVIDIA Corporation is strictly prohibited.
-//
-// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
-// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
-// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
-// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
-//
-// Information and code furnished is believed to be accurate and reliable.
-// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
-// information or for any infringement of patents or other rights of third parties that may
-// result from its use. No license is granted by implication or otherwise under any patent
-// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
-// This code supersedes and replaces all information previously supplied.
-// NVIDIA Corporation products are not authorized for use as critical
-// components in life support devices or systems without express written approval of
-// NVIDIA Corporation.
-//
-// Copyright (c) 2016-2018 NVIDIA Corporation. All rights reserved.
-
-#ifndef NVBLASTAUTHORINGMESHIMPL_H
-#define NVBLASTAUTHORINGMESHIMPL_H
-
-#include "NvBlastExtAuthoringMesh.h"
-#include "NvBlastExtAuthoringFractureTool.h"
-#include <vector>
-#include <map>
-#include <set>
-
-namespace Nv
-{
-namespace Blast
-{
-
-/**
- Class for internal mesh representation
-*/
-class MeshImpl : public Mesh
-{
-public:
-
- /**
- Constructs mesh object from array of triangles.
- \param[in] position Array of vertex positions
- \param[in] normals Array of vertex normals
- \param[in] uv Array of vertex uv coordinates
- \param[in] verticesCount Vertices count
- \param[in] indices Array of vertex indices. Indices contain vertex index triplets which form a mesh triangle.
- \param[in] indicesCount Indices count (should be equal to numberOfTriangles * 3)
- */
- MeshImpl(const physx::PxVec3* position, const physx::PxVec3* normals, const physx::PxVec2* uv, uint32_t verticesCount, const uint32_t* indices, uint32_t indicesCount);
-
- /**
- Constructs mesh object from array of facets.
- \param[in] vertices Array of vertices
- \param[in] edges Array of edges
- \param[in] facets Array of facets
- \param[in] posCount Vertices count
- \param[in] edgesCount Edges count
- \param[in] facetsCount Facets count
- */
- MeshImpl(const Vertex* vertices, const Edge* edges, const Facet* facets, uint32_t posCount, uint32_t edgesCount, uint32_t facetsCount);
-
- ~MeshImpl();
-
- 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<Vertex> mVertices;
- std::vector<Edge> mEdges;
- std::vector<Facet> 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<physx::PxVec3, std::map<uint32_t, uint32_t>, 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<Nv::Blast::Vertex> vertices;
- std::vector<Nv::Blast::Edge> edges;
- std::vector<Nv::Blast::Facet> facets;
-};
-
-struct CmpSharedFace
-{
- bool operator()(const std::pair<physx::PxVec3, physx::PxVec3>& pv1, const std::pair<physx::PxVec3, physx::PxVec3>& pv2) const;
-};
-
-typedef std::map<std::pair<physx::PxVec3, physx::PxVec3>, SharedFace, CmpSharedFace> SharedFacesMap;
-
-void buildCuttingConeFaces(const CutoutConfiguration& conf, const std::vector<std::vector<physx::PxVec3>>& 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<physx::PxVec3>& points, const std::set<int32_t>& 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
+// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2016-2018 NVIDIA Corporation. All rights reserved. + +#ifndef NVBLASTAUTHORINGMESHIMPL_H +#define NVBLASTAUTHORINGMESHIMPL_H + +#include "NvBlastExtAuthoringMesh.h" +#include <vector> +#include <map> +#include <set> + +namespace Nv +{ +namespace Blast +{ + +/** + Class for internal mesh representation +*/ +class MeshImpl : public Mesh +{ +public: + + /** + Constructs mesh object from array of triangles. + \param[in] position Array of vertex positions + \param[in] normals Array of vertex normals + \param[in] uv Array of vertex uv coordinates + \param[in] verticesCount Vertices count + \param[in] indices Array of vertex indices. Indices contain vertex index triplets which form a mesh triangle. + \param[in] indicesCount Indices count (should be equal to numberOfTriangles * 3) + */ + MeshImpl(const physx::PxVec3* position, const physx::PxVec3* normals, const physx::PxVec2* uv, uint32_t verticesCount, const uint32_t* indices, uint32_t indicesCount); + + /** + Constructs mesh object from array of facets. + \param[in] vertices Array of vertices + \param[in] edges Array of edges + \param[in] facets Array of facets + \param[in] posCount Vertices count + \param[in] edgesCount Edges count + \param[in] facetsCount Facets count + */ + MeshImpl(const Vertex* vertices, const Edge* edges, const Facet* facets, uint32_t posCount, uint32_t edgesCount, uint32_t facetsCount); + + MeshImpl(const Vertex* vertices, uint32_t count); + + MeshImpl(const Vertex* vertices, uint32_t count, uint32_t* indices, uint32_t indexCount, void* materials, uint32_t materialStride); + + ~MeshImpl(); + + virtual void release() override; + + /** + Return true if mesh is valid + */ + bool isValid() const override; + + /** + Return pointer on vertices array + */ + Vertex* getVerticesWritable() override; + + /** + Return pointer on edges array + */ + Edge* getEdgesWritable() override; + + /** + Return pointer on facets array + */ + Facet* getFacetsBufferWritable() override; + + /** + Return pointer on vertices array + */ + const Vertex* getVertices() const override; + + /** + Return pointer on edges array + */ + const Edge* getEdges() const override; + + /** + Return pointer on facets array + */ + const Facet* getFacetsBuffer() const override; + + /** + Return writable pointer on specified facet + */ + Facet* getFacetWritable(int32_t facet) override; + + /** + Return writable pointer on specified facet + */ + const Facet* getFacet(int32_t facet) const override; + + /** + Return edges count + */ + uint32_t getEdgesCount() const override; + + /** + Return vertices count + */ + uint32_t getVerticesCount() const override; + + /** + Return facet count + */ + uint32_t getFacetCount() const override; + + + /** + Return reference on mesh bounding box. + */ + const physx::PxBounds3& getBoundingBox() const override; + + /** + Return writable reference on mesh bounding box. + */ + physx::PxBounds3& getBoundingBoxWritable() override; + + /** + Recalculate bounding box + */ + void recalculateBoundingBox() override; + + /** + Compute mesh volume. Can be used only for triangulated meshes. + Return mesh volume. If mesh is not triangulated return 0. + */ + float getMeshVolume() override; + + + /** + Set per-facet material id. + */ + void setMaterialId(const int32_t* materialIds) override; + + /** + Replaces an material id on faces with a new one + */ + void replaceMaterialId(int32_t oldMaterialId, int32_t newMaterialId) override; + + /** + Set per-facet smoothing group. + */ + void setSmoothingGroup(const int32_t* smoothingGroups) override; + + /** + Calculate per-facet bounding boxes. + */ + virtual void calcPerFacetBounds() override; + + /** + Get pointer on facet bounding box, if not calculated return nullptr. + */ + virtual const physx::PxBounds3* getFacetBound(uint32_t index) const override; + +private: + std::vector<Vertex> mVertices; + std::vector<Edge> mEdges; + std::vector<Facet> mFacets; + physx::PxBounds3 mBounds; + std::vector<physx::PxBounds3> mPerFacetBounds; +}; + + + +} // namespace Blast +} // namespace Nv + + +#endif // ifndef NVBLASTAUTHORINGMESHIMPL_H diff --git a/sdk/extensions/exporter/source/NvBlastExtExporterObjReader.cpp b/sdk/extensions/exporter/source/NvBlastExtExporterObjReader.cpp index f188912..d43c1ae 100755 --- a/sdk/extensions/exporter/source/NvBlastExtExporterObjReader.cpp +++ b/sdk/extensions/exporter/source/NvBlastExtExporterObjReader.cpp @@ -68,6 +68,10 @@ void ObjFileReader::loadFromFile(const char* filename) lastDelimeter--;
}
mtlPath = std::string(filename, filename + lastDelimeter);
+ if (mtlPath == "")
+ {
+ mtlPath = '.';
+ }
mtlPath += '/';
bool ret = tinyobj::LoadObj(shapes, mats, err, filename, mtlPath.c_str());
|