aboutsummaryrefslogtreecommitdiff
path: root/sdk/extensions/authoring/source/NvBlastExtAuthoringBondGeneratorImpl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'sdk/extensions/authoring/source/NvBlastExtAuthoringBondGeneratorImpl.cpp')
-rwxr-xr-xsdk/extensions/authoring/source/NvBlastExtAuthoringBondGeneratorImpl.cpp2279
1 files changed, 1169 insertions, 1110 deletions
diff --git a/sdk/extensions/authoring/source/NvBlastExtAuthoringBondGeneratorImpl.cpp b/sdk/extensions/authoring/source/NvBlastExtAuthoringBondGeneratorImpl.cpp
index 1952e0f..318479f 100755
--- a/sdk/extensions/authoring/source/NvBlastExtAuthoringBondGeneratorImpl.cpp
+++ b/sdk/extensions/authoring/source/NvBlastExtAuthoringBondGeneratorImpl.cpp
@@ -36,9 +36,9 @@
#include <NvBlastExtAuthoringBondGeneratorImpl.h>
#include <NvBlast.h>
#include <NvBlastGlobals.h>
+#include <NvBlastPxSharedHelpers.h>
#include "NvBlastExtTriangleProcessor.h"
#include "NvBlastExtApexSharedParts.h"
-#include "NvBlastExtAuthoringCollisionBuilderImpl.h"
#include "NvBlastExtAuthoringInternalCommon.h"
#include "NvBlastExtAuthoringTypes.h"
#include <vector>
@@ -49,9 +49,6 @@
#include <memory>
#include <set>
-using physx::PxVec3;
-using physx::PxBounds3;
-
#define SAFE_ARRAY_NEW(T, x) ((x) > 0) ? reinterpret_cast<T*>(NVBLAST_ALLOC(sizeof(T) * (x))) : nullptr;
//#define DEBUG_OUTPUT
@@ -59,7 +56,7 @@ using physx::PxBounds3;
void saveGeometryToObj(std::vector<PxVec3>& triangles, const char* filepath)
{
-
+
FILE* outStream = fopen(filepath, "w");
for (uint32_t i = 0; i < triangles.size(); ++i)
@@ -72,7 +69,8 @@ void saveGeometryToObj(std::vector<PxVec3>& triangles, const char* filepath)
}
for (uint32_t i = 0; i < triangles.size() / 3; ++i)
{
- PxVec3 normal = (triangles[3 * i + 2] - triangles[3 * i]).cross((triangles[3 * i + 1] - triangles[3 * i])).getNormalized();
+ PxVec3 normal =
+ (triangles[3 * i + 2] - triangles[3 * i]).cross((triangles[3 * i + 1] - triangles[3 * i])).getNormalized();
fprintf(outStream, "vn %lf %lf %lf\n", normal.x, normal.y, normal.z);
fprintf(outStream, "vn %lf %lf %lf\n", normal.x, normal.y, normal.z);
fprintf(outStream, "vn %lf %lf %lf\n", normal.x, normal.y, normal.z);
@@ -89,1322 +87,1383 @@ void saveGeometryToObj(std::vector<PxVec3>& triangles, const char* filepath)
}
fclose(outStream);
-
}
std::vector<PxVec3> intersectionBuffer;
std::vector<PxVec3> meshBuffer;
-#endif
+#endif
namespace Nv
{
- namespace Blast
- {
+namespace Blast
+{
- #define EPS_PLANE 0.0001f
-
- bool planeComparer(const PlaneChunkIndexer& as, const PlaneChunkIndexer& bs)
- {
- const PxPlane& a = as.plane;
- const PxPlane& b = bs.plane;
-
- if (a.d + EPS_PLANE < b.d) return true;
- if (a.d - EPS_PLANE > b.d) return false;
- if (a.n.x + EPS_PLANE < b.n.x) return true;
- if (a.n.x - EPS_PLANE > b.n.x) return false;
- if (a.n.y + EPS_PLANE < b.n.y) return true;
- if (a.n.y - EPS_PLANE > b.n.y) return false;
- return a.n.z + EPS_PLANE < b.n.z;
- }
+#define EPS_PLANE 0.0001f
+physx::PxVec3 getNormal(const Triangle& t)
+{
+ return toPxShared(t.b.p - t.a.p).cross(toPxShared(t.c.p - t.a.p));
+}
- struct Bond
- {
- int32_t m_chunkId;
- int32_t m_planeIndex;
- int32_t triangleIndex;
+bool planeComparer(const PlaneChunkIndexer& as, const PlaneChunkIndexer& bs)
+{
+ const NvcPlane& a = as.plane;
+ const NvcPlane& b = bs.plane;
+
+ if (a.d + EPS_PLANE < b.d)
+ return true;
+ if (a.d - EPS_PLANE > b.d)
+ return false;
+ if (a.n.x + EPS_PLANE < b.n.x)
+ return true;
+ if (a.n.x - EPS_PLANE > b.n.x)
+ return false;
+ if (a.n.y + EPS_PLANE < b.n.y)
+ return true;
+ if (a.n.y - EPS_PLANE > b.n.y)
+ return false;
+ return a.n.z + EPS_PLANE < b.n.z;
+}
- bool operator<(const Bond& inp) const
- {
- if (abs(m_planeIndex) == abs(inp.m_planeIndex))
- {
- return m_chunkId < inp.m_chunkId;
- }
- else
- {
- return abs(m_planeIndex) < abs(inp.m_planeIndex);
- }
- }
- };
+struct Bond
+{
+ int32_t m_chunkId;
+ int32_t m_planeIndex;
+ int32_t triangleIndex;
- struct BondInfo
+ bool operator<(const Bond& inp) const
+ {
+ if (abs(m_planeIndex) == abs(inp.m_planeIndex))
{
- float area;
- physx::PxBounds3 m_bb;
- physx::PxVec3 centroid;
- physx::PxVec3 normal;
- int32_t m_chunkId;
- };
-
- void AddTtAnchorPoints(const Triangle* a, const Triangle* b, std::vector<PxVec3>& points)
+ return m_chunkId < inp.m_chunkId;
+ }
+ else
{
- 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))
- {
+ return abs(m_planeIndex) < abs(inp.m_planeIndex);
+ }
+ }
+};
- 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);
- }
- }
- }
- }
+struct BondInfo
+{
+ float area;
+ physx::PxBounds3 m_bb;
+ physx::PxVec3 centroid;
+ physx::PxVec3 normal;
+ int32_t m_chunkId;
+};
+
+inline physx::PxVec3 getVertex(const Triangle& t, uint32_t i)
+{
+ return toPxShared((&t.a)[i].p);
+}
+void AddTtAnchorPoints(const Triangle* a, const Triangle* b, std::vector<PxVec3>& points)
+{
+ physx::PxVec3 na = getNormal(*a).getNormalized();
+ physx::PxVec3 nb = getNormal(*b).getNormalized();
- inline bool pointInsidePoly(const PxVec3& pt, const uint8_t *indices, uint16_t indexCount, const PxVec3 *verts, const PxVec3& n)
- {
- int s = 0;
- for (uint16_t i = 0; i < indexCount; ++i)
- {
- const PxVec3 r0 = verts[indices[i]] - pt;
- const PxVec3 r1 = verts[indices[(i + 1) % indexCount]] - pt;
- const float cn = r0.cross(r1).dot(n);
- const int cns = cn >= 0 ? 1 : -1;
- if (!s)
- {
- s = cns;
- }
- if (cns*s < 0)
- {
- return false;
- }
- }
- return true;
- }
+ physx::PxPlane pla(toPxShared(a->a.p), na);
+ physx::PxPlane plb(toPxShared(b->a.p), nb);
- void AddPpAnchorPoints(
- const uint8_t* indicesA, uint16_t indexCountA, const PxVec3* vertsA, const float planeA[4],
- const uint8_t* indicesB, uint16_t indexCountB, const PxVec3* vertsB, const float planeB[4],
- std::vector<PxVec3>& points)
- {
- PxPlane pla(planeA[0], planeA[1], planeA[2], planeA[3]);
- PxPlane plb(planeB[0], planeB[1], planeB[2], planeB[3]);
-
- for (uint16_t iA = 0; iA < indexCountA; ++iA)
- {
- PxVec3 pt;
- if (getPlaneSegmentIntersection(plb, vertsA[indicesA[iA]], vertsA[indicesA[(iA + 1) % indexCountA]], pt))
- {
- if (pointInsidePoly(pt, indicesB, indexCountB, vertsB, plb.n))
- {
- points.push_back(pt);
- }
- }
- }
-
- for (uint16_t iB = 0; iB < indexCountA; ++iB)
- {
- PxVec3 pt;
- if (getPlaneSegmentIntersection(pla, vertsB[indicesB[iB]], vertsB[indicesA[(iB + 1) % indexCountB]], pt))
- {
- if (pointInsidePoly(pt, indicesA, indexCountA, vertsA, pla.n))
- {
- points.push_back(pt);
- }
- }
- }
- }
-
-
- float BlastBondGeneratorImpl::processWithMidplanes(TriangleProcessor* trProcessor, const Triangle* mA, uint32_t mavc, const Triangle* mB, uint32_t mbvc,
- const CollisionHull* hull1, const CollisionHull* hull2, const std::vector<PxVec3>& hull1p, const std::vector<PxVec3>& hull2p, PxVec3& normal, PxVec3& centroid, float maxSeparation)
+
+ ProjectionDirections da = getProjectionDirection(na);
+ ProjectionDirections db = getProjectionDirection(nb);
+
+ TriangleProcessor prc;
+
+ TrPrcTriangle2d ta(getProjectedPoint(toPxShared(a->a.p), da), getProjectedPoint(toPxShared(a->b.p), da),
+ getProjectedPoint(toPxShared(a->c.p), da));
+ TrPrcTriangle2d tb(getProjectedPoint(toPxShared(b->a.p), db), getProjectedPoint(toPxShared(b->b.p), db),
+ getProjectedPoint(toPxShared(b->c.p), db));
+
+ /**
+ Compute
+ */
+ for (uint32_t i = 0; i < 3; ++i)
+ {
+ physx::PxVec3 pt;
+ if (getPlaneSegmentIntersection(pla, getVertex(*b, i), getVertex(*b, (i + 1) % 3), pt))
{
- PxBounds3 bounds;
- PxBounds3 aBounds;
- PxBounds3 bBounds;
- bounds.setEmpty();
- aBounds.setEmpty();
- bBounds.setEmpty();
-
- PxVec3 chunk1Centroid(0, 0, 0);
- PxVec3 chunk2Centroid(0, 0, 0);
-
- ///////////////////////////////////////////////////////////////////////////////////
- if (hull1p.size() < 4 || hull2p.size() < 4)
- {
- return 0.0;
- }
- for (uint32_t i = 0; i < hull1p.size(); ++i)
+ physx::PxVec2 pt2 = getProjectedPoint(pt, da);
+ if (prc.isPointInside(pt2, ta))
{
- chunk1Centroid += hull1p[i];
- bounds.include(hull1p[i]);
- aBounds.include(hull1p[i]);
+ points.push_back(pt);
}
- for (uint32_t i = 0; i < hull2p.size(); ++i)
+ }
+ if (getPlaneSegmentIntersection(plb, getVertex(*a, i), getVertex(*a, (i + 1) % 3), pt))
+ {
+ PxVec2 pt2 = getProjectedPoint(pt, db);
+ if (prc.isPointInside(pt2, tb))
{
- chunk2Centroid += hull2p[i];
- bounds.include(hull2p[i]);
- bBounds.include(hull2p[i]);
+ points.push_back(pt);
}
+ }
+ }
+}
- chunk1Centroid *= (1.0f / hull1p.size());
- chunk2Centroid *= (1.0f / hull2p.size());
+inline bool
+pointInsidePoly(const PxVec3& pt, const uint8_t* indices, uint16_t indexCount, const PxVec3* verts, const PxVec3& n)
+{
+ int s = 0;
+ for (uint16_t i = 0; i < indexCount; ++i)
+ {
+ const PxVec3 r0 = verts[indices[i]] - pt;
+ const PxVec3 r1 = verts[indices[(i + 1) % indexCount]] - pt;
+ const float cn = r0.cross(r1).dot(n);
+ const int cns = cn >= 0 ? 1 : -1;
+ if (!s)
+ {
+ s = cns;
+ }
+ if (cns * s < 0)
+ {
+ return false;
+ }
+ }
+ return true;
+}
-
+void AddPpAnchorPoints(const uint8_t* indicesA, uint16_t indexCountA, const PxVec3* vertsA, const float planeA[4],
+ const uint8_t* indicesB, uint16_t indexCountB, const PxVec3* vertsB, const float planeB[4],
+ std::vector<PxVec3>& points)
+{
+ PxPlane pla(planeA[0], planeA[1], planeA[2], planeA[3]);
+ PxPlane plb(planeB[0], planeB[1], planeB[2], planeB[3]);
- 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))
+ for (uint16_t iA = 0; iA < indexCountA; ++iA)
+ {
+ PxVec3 pt;
+ if (getPlaneSegmentIntersection(plb, vertsA[indicesA[iA]], vertsA[indicesA[(iA + 1) % indexCountA]], pt))
+ {
+ if (pointInsidePoly(pt, indicesB, indexCountB, vertsB, plb.n))
{
- return 0.0;
+ points.push_back(pt);
}
-
- const bool have_geometry = (mA != nullptr && mB != nullptr) || (hull1 != nullptr && hull2 != nullptr);
+ }
+ }
- if (separation.getDistance() > 0 || !have_geometry) // If chunks don't intersect then use midplane to produce bond, otherwise midplane can be wrong (only if we have geometry)
+ for (uint16_t iB = 0; iB < indexCountA; ++iB)
+ {
+ PxVec3 pt;
+ if (getPlaneSegmentIntersection(pla, vertsB[indicesB[iB]], vertsB[indicesA[(iB + 1) % indexCountB]], pt))
+ {
+ if (pointInsidePoly(pt, indicesA, indexCountA, vertsA, pla.n))
{
- // Build first plane interface
- PxPlane midplane = separation.plane;
- if (!midplane.n.isFinite())
- {
- return 0.0;
- }
+ points.push_back(pt);
+ }
+ }
+ }
+}
- std::vector<PxVec3> interfacePoints;
- float firstCentroidSide = (midplane.distance(chunk1Centroid) > 0) ? 1 : -1;
- float secondCentroidSide = (midplane.distance(chunk2Centroid) > 0) ? 1 : -1;
+float BlastBondGeneratorImpl::processWithMidplanes(TriangleProcessor* trProcessor, const Triangle* mA, uint32_t mavc,
+ const Triangle* mB, uint32_t mbvc, const CollisionHull* hull1,
+ const CollisionHull* hull2, const std::vector<PxVec3>& hull1p,
+ const std::vector<PxVec3>& hull2p, PxVec3& normal, PxVec3& centroid,
+ float maxSeparation)
+{
+ PxBounds3 bounds;
+ PxBounds3 aBounds;
+ PxBounds3 bBounds;
+ bounds.setEmpty();
+ aBounds.setEmpty();
+ bBounds.setEmpty();
+
+ PxVec3 chunk1Centroid(0, 0, 0);
+ PxVec3 chunk2Centroid(0, 0, 0);
+
+ ///////////////////////////////////////////////////////////////////////////////////
+ if (hull1p.size() < 4 || hull2p.size() < 4)
+ {
+ return 0.0;
+ }
- for (uint32_t i = 0; i < hull1p.size(); ++i)
- {
- float dst = midplane.distance(hull1p[i]);
- if (dst * firstCentroidSide < maxSeparation)
- {
- interfacePoints.push_back(hull1p[i]);
- }
- }
+ for (uint32_t i = 0; i < hull1p.size(); ++i)
+ {
+ chunk1Centroid += hull1p[i];
+ bounds.include(hull1p[i]);
+ aBounds.include(hull1p[i]);
+ }
+ for (uint32_t i = 0; i < hull2p.size(); ++i)
+ {
+ chunk2Centroid += hull2p[i];
+ bounds.include(hull2p[i]);
+ bBounds.include(hull2p[i]);
+ }
- for (uint32_t i = 0; i < hull2p.size(); ++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;
- }
- else
- {
- float area = 0.0f;
- std::vector<PxVec3> intersectionAnchors;
+ chunk1Centroid *= (1.0f / hull1p.size());
+ chunk2Centroid *= (1.0f / hull2p.size());
- if (mA != nullptr && mB != nullptr) // Use triangles
- {
- for (uint32_t i = 0; i < mavc; ++i)
- {
- for (uint32_t j = 0; j < mbvc; ++j)
- {
- AddTtAnchorPoints(mA + i, mB + j, intersectionAnchors);
- }
- }
- }
- else // Use hulls
- {
- for (uint32_t i1 = 0; i1 < hull1->polygonDataCount; ++i1)
- {
- CollisionHull::HullPolygon& poly1 = hull1->polygonData[i1];
- for (uint32_t i2 = 0; i2 < hull2->polygonDataCount; ++i2)
- {
- CollisionHull::HullPolygon& poly2 = hull2->polygonData[i2];
- AddPpAnchorPoints(
- reinterpret_cast<uint8_t*>(hull1->indices) + poly1.mIndexBase, poly1.mNbVerts, hull1->points, poly1.mPlane,
- reinterpret_cast<uint8_t*>(hull2->indices) + poly2.mIndexBase, poly2.mNbVerts, hull2->points, poly2.mPlane,
- 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;
- }
+ 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;
+ }
- PxVec3 dir1 = intersectionAnchors[0] - lcoid;
- PxVec3 dir2(0, 0, 0);
- float maxMagn = 0.0f;
- float maxDist = 0.0f;
+ const bool have_geometry = (mA != nullptr && mB != nullptr) || (hull1 != nullptr && hull2 != nullptr);
+ if (separation.getDistance() > 0 || !have_geometry) // If chunks don't intersect then use midplane to produce bond,
+ // otherwise midplane can be wrong (only if we have geometry)
+ {
+ // Build first plane interface
+ PxPlane midplane = separation.plane;
+ if (!midplane.n.isFinite())
+ {
+ return 0.0;
+ }
- for (uint32_t j = 0; j < intersectionAnchors.size(); ++j)
- {
- float d = (intersectionAnchors[j] - lcoid).magnitude();
+ std::vector<PxVec3> interfacePoints;
- PxVec3 tempNormal = (intersectionAnchors[j] - lcoid).cross(dir1);
- maxDist = std::max(d, maxDist);
-
- if (tempNormal.magnitude() > maxMagn)
- {
- dir2 = tempNormal;
- }
-
- }
+ float firstCentroidSide = (midplane.distance(chunk1Centroid) > 0) ? 1 : -1;
+ float secondCentroidSide = (midplane.distance(chunk2Centroid) > 0) ? 1 : -1;
- normal = dir2.getNormalized();
-
- area = (maxDist * maxDist) * 3.14f; // Compute area like circle area;
-
- return area;
+ for (uint32_t i = 0; i < hull1p.size(); ++i)
+ {
+ float dst = midplane.distance(hull1p[i]);
+ if (dst * firstCentroidSide < maxSeparation)
+ {
+ interfacePoints.push_back(hull1p[i]);
}
}
-
- struct BondGenerationCandidate
+ for (uint32_t i = 0; i < hull2p.size(); ++i)
{
- PxVec3 point;
- bool end;
- uint32_t parentChunk;
- uint32_t parentComponent;
- BondGenerationCandidate();
- BondGenerationCandidate(const PxVec3& p, bool isEnd, uint32_t pr, uint32_t c) :point(p), end(isEnd), parentChunk(pr), parentComponent(c)
- { };
-
- bool operator<(const BondGenerationCandidate& in) const
+ float dst = midplane.distance(hull2p[i]);
+ if (dst * secondCentroidSide < maxSeparation)
{
- if (point.x < in.point.x) return true;
- if (point.x > in.point.x) return false;
-
- if (point.y < in.point.y) return true;
- if (point.y > in.point.y) return false;
-
- if (point.z < in.point.z) return true;
- if (point.z > in.point.z) return false;
-
- return end < in.end;
- };
- };
-
+ 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;
+ }
+ else
+ {
+ float area = 0.0f;
- 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, std::set<std::pair<uint32_t, uint32_t> >* pairNotToTest)
- {
+ std::vector<PxVec3> intersectionAnchors;
- std::vector<std::vector<PxVec3> > chunksPoints(meshCount);
- std::vector<PxBounds3> bounds(meshCount);
- if (!chunkHulls)
+ if (mA != nullptr && mB != nullptr) // Use triangles
+ {
+ for (uint32_t i = 0; i < mavc; ++i)
{
- for (uint32_t i = 0; i < meshCount; ++i)
+ for (uint32_t j = 0; j < mbvc; ++j)
{
- bounds[i].setEmpty();
- if (!supportFlags[i])
- {
- continue;
- }
- uint32_t count = geometryOffset[i + 1] - geometryOffset[i];
- for (uint32_t j = 0; j < count; ++j)
- {
- 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);
- }
+ AddTtAnchorPoints(mA + i, mB + j, intersectionAnchors);
}
}
-
- std::unique_ptr<Nv::Blast::ConvexMeshBuilderImpl> builder;
- std::vector<std::vector<std::vector<PxVec3>>> hullPoints(meshCount);
- std::vector<BondGenerationCandidate> candidates;
-
-
- for (uint32_t chunk = 0; chunk < meshCount; ++chunk)
+ }
+ else // Use hulls
+ {
+ for (uint32_t i1 = 0; i1 < hull1->polygonDataCount; ++i1)
{
- if (!supportFlags[chunk])
+ HullPolygon& poly1 = hull1->polygonData[i1];
+ for (uint32_t i2 = 0; i2 < hull2->polygonDataCount; ++i2)
{
- continue;
+ HullPolygon& poly2 = hull2->polygonData[i2];
+ AddPpAnchorPoints(reinterpret_cast<uint8_t*>(hull1->indices) + poly1.indexBase, poly1.vertexCount,
+ toPxShared(hull1->points), poly1.plane,
+ reinterpret_cast<uint8_t*>(hull2->indices) + poly2.indexBase, poly2.vertexCount,
+ toPxShared(hull2->points), poly2.plane, intersectionAnchors);
}
- PxBounds3 bnd(PxBounds3::empty());
- CollisionHull* tempHullPtr = nullptr;
- uint32_t hullCountForMesh = 0;
- const CollisionHull** beginChunkHulls = nullptr;
- if (chunkHulls)
- {
- hullCountForMesh = geometryOffset[chunk + 1] - geometryOffset[chunk];
- beginChunkHulls = chunkHulls + geometryOffset[chunk];
- }
- else
- {
- //build a convex hull and store it in the temp slot
- if (!builder)
- {
- builder = std::unique_ptr<Nv::Blast::ConvexMeshBuilderImpl>(new Nv::Blast::ConvexMeshBuilderImpl(mPxCooking, mPxInsertionCallback));
- }
-
- tempHullPtr = builder->buildCollisionGeometry(chunksPoints[chunk].size(), chunksPoints[chunk].data());
- hullCountForMesh = 1;
- beginChunkHulls = const_cast<const CollisionHull**>(&tempHullPtr);
- }
-
- hullPoints[chunk].resize(hullCountForMesh);
- for (uint32_t hull = 0; hull < hullCountForMesh; ++hull)
- {
- auto& curHull = hullPoints[chunk][hull];
- const uint32_t pointCount = beginChunkHulls[hull]->pointsCount;
- curHull.resize(pointCount);
- for (uint32_t i = 0; i < pointCount; ++i)
- {
- curHull[i] = beginChunkHulls[hull]->points[i];
- bnd.include(curHull[i]);
- }
- }
-
- if (tempHullPtr)
- {
- tempHullPtr->release();
- }
- float minSide = bnd.getDimensions().abs().minElement();
- if (minSide > 0.f)
- {
- float scaling = std::max(1.1f, conf.maxSeparation / (minSide));
- bnd.scaleFast(scaling);
- }
- candidates.push_back(BondGenerationCandidate(bnd.minimum, false, chunk, meshGroups != nullptr ? meshGroups[chunk] : 0));
- candidates.push_back(BondGenerationCandidate(bnd.maximum, true, chunk, meshGroups != nullptr ? meshGroups[chunk] : 0));
}
+ }
- std::sort(candidates.begin(), candidates.end());
+ PxVec3 lcoid(0, 0, 0);
+ for (uint32_t i = 0; i < intersectionAnchors.size(); ++i)
+ {
+ lcoid += intersectionAnchors[i];
+ }
+ lcoid *= (1.0f / intersectionAnchors.size());
+ centroid = lcoid;
- std::set<uint32_t> listOfActiveChunks;
- std::vector<std::vector<uint32_t> > possibleBondGraph(meshCount);
+ if (intersectionAnchors.size() < 2)
+ {
+ return 0;
+ }
- for (uint32_t idx = 0; idx < candidates.size(); ++idx)
- {
- if (!candidates[idx].end) // If new candidate
- {
- for (uint32_t activeChunk : listOfActiveChunks)
- {
- if (meshGroups != nullptr && (meshGroups[activeChunk] == candidates[idx].parentComponent)) continue; // Don't connect components with itself.
- possibleBondGraph[activeChunk].push_back(candidates[idx].parentChunk);
- }
- listOfActiveChunks.insert(candidates[idx].parentChunk);
- }
- else
- {
- listOfActiveChunks.erase(candidates[idx].parentChunk);
- }
- }
- TriangleProcessor trProcessor;
- std::vector<NvBlastBondDesc> mResultBondDescs;
- for (uint32_t i = 0; i < meshCount; ++i)
- {
- const uint32_t ihullCount = hullPoints[i].size();
- 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
- }
+ PxVec3 dir1 = intersectionAnchors[0] - lcoid;
+ PxVec3 dir2(0, 0, 0);
+ float maxMagn = 0.0f;
+ float maxDist = 0.0f;
-
- const uint32_t jhullCount = hullPoints[j].size();
- for (uint32_t ihull = 0; ihull < ihullCount; ++ihull)
- {
- for (uint32_t jhull = 0; jhull < jhullCount; ++jhull)
- {
- PxVec3 normal;
- PxVec3 centroid;
-
- float area = processWithMidplanes(&trProcessor,
- geometry ? geometry + geometryOffset[i] : nullptr, geometryOffset[i + 1] - geometryOffset[i],
- geometry ? geometry + geometryOffset[j] : nullptr, geometryOffset[j + 1] - geometryOffset[j],
- geometry ? nullptr : chunkHulls[geometryOffset[i] + ihull],
- geometry ? nullptr : chunkHulls[geometryOffset[j] + jhull],
- hullPoints[i][ihull], hullPoints[j][jhull], normal, centroid, conf.maxSeparation);
-
- if (area > 0)
- {
- NvBlastBondDesc bDesc;
- bDesc.chunkIndices[0] = i;
- bDesc.chunkIndices[1] = j;
- bDesc.bond.area = area;
- bDesc.bond.centroid[0] = centroid.x;
- 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;
-
- mResultBondDescs.push_back(bDesc);
- }
- }
- }
+ 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;
}
- resultBondDescs = SAFE_ARRAY_NEW(NvBlastBondDesc, mResultBondDescs.size());
- memcpy(resultBondDescs, mResultBondDescs.data(), sizeof(NvBlastBondDesc)*mResultBondDescs.size());
- return mResultBondDescs.size();
}
- uint32_t isSamePlane(PxPlane& a, PxPlane& b)
- {
- if (PxAbs(a.d - b.d) > EPS_PLANE) return 0;
- if (PxAbs(a.n.x - b.n.x) > EPS_PLANE) return 0;
- if (PxAbs(a.n.y - b.n.y) > EPS_PLANE) return 0;
- if (PxAbs(a.n.z - b.n.z) > EPS_PLANE) return 0;
- return 1;
- }
+ normal = dir2.getNormalized();
- int32_t BlastBondGeneratorImpl::createFullBondListExact(uint32_t meshCount, const uint32_t* geometryOffset, const Triangle* geometry,
- const bool* supportFlags, NvBlastBondDesc*& resultBondDescs, BondGenerationConfig conf)
- {
- std::vector < PlaneChunkIndexer > planeTriangleMapping;
- NV_UNUSED(conf);
- for (uint32_t i = 0; i < meshCount; ++i)
- {
- if (!supportFlags[i])
- {
- continue;
- }
- uint32_t count = geometryOffset[i + 1] - geometryOffset[i];
- for (uint32_t j = 0; j < count; ++j)
- {
-#ifdef DEBUG_OUTPUT
- meshBuffer.push_back(geometry[geometryOffset[i] + j].a.p );
- meshBuffer.push_back(geometry[geometryOffset[i] + j].b.p);
- meshBuffer.push_back(geometry[geometryOffset[i] + j].c.p );
-#endif
+ area = (maxDist * maxDist) * 3.14f; // Compute area like circle area;
- PxPlane nPlane = PxPlane(geometry[geometryOffset[i] + j].a.p, geometry[geometryOffset[i] + j].b.p, geometry[geometryOffset[i] + j].c.p);
- planeTriangleMapping.push_back(PlaneChunkIndexer(i, j, nPlane));
- }
- }
+ return area;
+ }
+}
- std::sort(planeTriangleMapping.begin(), planeTriangleMapping.end(), planeComparer);
- return createFullBondListExactInternal(meshCount, geometryOffset, geometry, planeTriangleMapping, resultBondDescs);
- }
- void BlastBondGeneratorImpl::buildGeometryCache(uint32_t meshCount, const uint32_t* geometryOffset, const Triangle* geometry)
+struct BondGenerationCandidate
+{
+ PxVec3 point;
+ bool end;
+ uint32_t parentChunk;
+ uint32_t parentComponent;
+ BondGenerationCandidate();
+ BondGenerationCandidate(const PxVec3& p, bool isEnd, uint32_t pr, uint32_t c)
+ : point(p), end(isEnd), parentChunk(pr), parentComponent(c){};
+
+ bool operator<(const BondGenerationCandidate& in) const
+ {
+ if (point.x < in.point.x)
+ return true;
+ if (point.x > in.point.x)
+ return false;
+
+ if (point.y < in.point.y)
+ return true;
+ if (point.y > in.point.y)
+ return false;
+
+ if (point.z < in.point.z)
+ return true;
+ if (point.z > in.point.z)
+ return false;
+
+ return end < in.end;
+ };
+};
+
+
+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,
+ std::set<std::pair<uint32_t, uint32_t> >* pairNotToTest)
+{
+
+ std::vector<std::vector<NvcVec3> > chunksPoints(meshCount);
+ std::vector<PxBounds3> bounds(meshCount);
+ if (!chunkHulls)
+ {
+ for (uint32_t i = 0; i < meshCount; ++i)
{
- uint32_t geometryCount = geometryOffset[meshCount];
- for (uint32_t i = 0; i < meshCount; i++)
+ bounds[i].setEmpty();
+ if (!supportFlags[i])
{
- mGeometryCache.push_back(std::vector<Triangle>());
- uint32_t count = geometryOffset[i + 1] - geometryOffset[i];
- mGeometryCache.back().resize(count);
- memcpy(mGeometryCache.back().data(), geometry + geometryOffset[i], sizeof(Triangle) * count);
+ continue;
}
- mHullsPointsCache.resize(geometryCount);
- mBoundsCache.resize(geometryCount);
- mCHullCache.resize(geometryCount);
- for (uint32_t i = 0; i < mGeometryCache.size(); ++i)
+ uint32_t count = geometryOffset[i + 1] - geometryOffset[i];
+ for (uint32_t j = 0; j < count; ++j)
{
- for (uint32_t j = 0; j < mGeometryCache[i].size(); ++j)
- {
-
- PxPlane nPlane = PxPlane(mGeometryCache[i][j].a.p, mGeometryCache[i][j].b.p, mGeometryCache[i][j].c.p);
- mPlaneCache.push_back(PlaneChunkIndexer(i, j, nPlane));
- }
+ 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(toPxShared(geometry[geometryOffset[i] + j].a.p));
+ bounds[i].include(toPxShared(geometry[geometryOffset[i] + j].b.p));
+ bounds[i].include(toPxShared(geometry[geometryOffset[i] + j].c.p));
}
+ }
+ }
- for (uint32_t ch = 0; ch < mGeometryCache.size(); ++ch)
- {
- std::vector<PxVec3> chunksPoints(mGeometryCache[ch].size() * 3);
-
- int32_t sp = 0;
- for (uint32_t i = 0; i < mGeometryCache[ch].size(); ++i)
- {
- chunksPoints[sp++] = mGeometryCache[ch][i].a.p;
- chunksPoints[sp++] = mGeometryCache[ch][i].b.p;
- chunksPoints[sp++] = mGeometryCache[ch][i].c.p;
- }
-
- Nv::Blast::ConvexMeshBuilderImpl builder(mPxCooking, mPxInsertionCallback);
-
- mCHullCache[ch] = builder.buildCollisionGeometry(chunksPoints.size(), chunksPoints.data());
+ std::vector<std::vector<std::vector<PxVec3> > > hullPoints(meshCount);
+ std::vector<BondGenerationCandidate> candidates;
- mHullsPointsCache[ch].resize(mCHullCache[ch]->pointsCount);
- mBoundsCache[ch].setEmpty();
- for (uint32_t i = 0; i < mCHullCache[ch]->pointsCount; ++i)
- {
- mHullsPointsCache[ch][i] = mCHullCache[ch]->points[i];
- mBoundsCache[ch].include(mHullsPointsCache[ch][i]);
- }
- }
+ for (uint32_t chunk = 0; chunk < meshCount; ++chunk)
+ {
+ if (!supportFlags[chunk])
+ {
+ continue;
+ }
+ PxBounds3 bnd(PxBounds3::empty());
+ CollisionHull* tempHullPtr = nullptr;
+ uint32_t hullCountForMesh = 0;
+ const CollisionHull** beginChunkHulls = nullptr;
+ if (chunkHulls)
+ {
+ hullCountForMesh = geometryOffset[chunk + 1] - geometryOffset[chunk];
+ beginChunkHulls = chunkHulls + geometryOffset[chunk];
+ }
+ else
+ {
+ // build a convex hull and store it in the temp slot
+ tempHullPtr =
+ mConvexMeshBuilder->buildCollisionGeometry(chunksPoints[chunk].size(), chunksPoints[chunk].data());
+ hullCountForMesh = 1;
+ beginChunkHulls = const_cast<const CollisionHull**>(&tempHullPtr);
}
- void BlastBondGeneratorImpl::resetGeometryCache()
- {
- mGeometryCache.clear();
- mPlaneCache.clear();
- mHullsPointsCache.clear();
- for (auto h : mCHullCache)
+ hullPoints[chunk].resize(hullCountForMesh);
+ for (uint32_t hull = 0; hull < hullCountForMesh; ++hull)
+ {
+ auto& curHull = hullPoints[chunk][hull];
+ const uint32_t pointCount = beginChunkHulls[hull]->pointsCount;
+ curHull.resize(pointCount);
+ for (uint32_t i = 0; i < pointCount; ++i)
{
- h->release();
+ curHull[i] = toPxShared(beginChunkHulls[hull]->points[i]);
+ bnd.include(curHull[i]);
}
- mCHullCache.clear();
- mBoundsCache.clear();
}
- int32_t BlastBondGeneratorImpl::createFullBondListExactInternal(uint32_t meshCount, const uint32_t* geometryOffset, const Triangle* geometry,
- std::vector<PlaneChunkIndexer>& planeTriangleMapping, NvBlastBondDesc*& resultBondDescs)
+ if (tempHullPtr)
+ {
+ mConvexMeshBuilder->releaseCollisionHull(tempHullPtr);
+ }
+ float minSide = bnd.getDimensions().abs().minElement();
+ if (minSide > 0.f)
{
- NV_UNUSED(meshCount);
+ float scaling = std::max(1.1f, conf.maxSeparation / (minSide));
+ bnd.scaleFast(scaling);
+ }
+ candidates.push_back(
+ BondGenerationCandidate(bnd.minimum, false, chunk, meshGroups != nullptr ? meshGroups[chunk] : 0));
+ candidates.push_back(
+ BondGenerationCandidate(bnd.maximum, true, chunk, meshGroups != nullptr ? meshGroups[chunk] : 0));
+ }
- std::map<std::pair<int32_t, int32_t>, std::pair<NvBlastBondDesc, int32_t> > bonds;
+ std::sort(candidates.begin(), candidates.end());
- TriangleProcessor trPrc;
- std::vector<PxVec3> intersectionBufferLocal;
+ std::set<uint32_t> listOfActiveChunks;
+ std::vector<std::vector<uint32_t> > possibleBondGraph(meshCount);
- NvBlastBondDesc cleanBond;
- memset(&cleanBond, 0, sizeof(NvBlastBondDesc));
- for (uint32_t tIndex = 0; tIndex < planeTriangleMapping.size(); ++tIndex)
+ for (uint32_t idx = 0; idx < candidates.size(); ++idx)
+ {
+ if (!candidates[idx].end) // If new candidate
+ {
+ for (uint32_t activeChunk : listOfActiveChunks)
{
-
- PlaneChunkIndexer opp = planeTriangleMapping[tIndex];
-
- opp.plane.d *= -1;
- opp.plane.n *= -1;
-
- uint32_t startIndex = (uint32_t)(std::lower_bound(planeTriangleMapping.begin(), planeTriangleMapping.end(), opp, planeComparer) - planeTriangleMapping.begin());
- uint32_t endIndex = (uint32_t)(std::upper_bound(planeTriangleMapping.begin(), planeTriangleMapping.end(), opp, planeComparer) - planeTriangleMapping.begin());
- // uint32_t startIndex = 0;
- // uint32_t endIndex = (uint32_t)planeTriangleMapping.size();
-
- PlaneChunkIndexer& mappedTr = planeTriangleMapping[tIndex];
- const Triangle& trl = geometry[geometryOffset[mappedTr.chunkId] + mappedTr.trId];
- PxPlane pln = mappedTr.plane;
- TrPrcTriangle trp(trl.a.p, trl.b.p, trl.c.p);
- PxVec3 trCentroid = (trl.a.p + trl.b.p + trl.c.p) * (1.0f / 3.0f);
- trp.points[0] -= trCentroid;
- trp.points[1] -= trCentroid;
- trp.points[2] -= trCentroid;
- ProjectionDirections pDir = getProjectionDirection(pln.n);
- TrPrcTriangle2d trp2d;
- trp2d.points[0] = getProjectedPointWithWinding(trp.points[0], pDir);
- trp2d.points[1] = getProjectedPointWithWinding(trp.points[1], pDir);
- trp2d.points[2] = getProjectedPointWithWinding(trp.points[2], pDir);
-
- for (uint32_t i = startIndex; i <= endIndex && i < planeTriangleMapping.size(); ++i)
- {
- PlaneChunkIndexer& mappedTr2 = planeTriangleMapping[i];
- if (mappedTr2.trId == opp.chunkId)
- {
- continue;
- }
+ if (meshGroups != nullptr && (meshGroups[activeChunk] == candidates[idx].parentComponent))
+ continue; // Don't connect components with itself.
+ possibleBondGraph[activeChunk].push_back(candidates[idx].parentChunk);
+ }
+ listOfActiveChunks.insert(candidates[idx].parentChunk);
+ }
+ else
+ {
+ listOfActiveChunks.erase(candidates[idx].parentChunk);
+ }
+ }
- if (!isSamePlane(opp.plane, mappedTr2.plane))
- {
- continue;
- }
-
- if (mappedTr.chunkId == mappedTr2.chunkId)
- {
- continue;
- }
- std::pair<int32_t, int32_t> bondEndPoints = std::make_pair(mappedTr.chunkId, mappedTr2.chunkId);
- if (bondEndPoints.second < bondEndPoints.first) continue;
- std::pair<int32_t, int32_t> bondEndPointsSwapped = std::make_pair(mappedTr2.chunkId, mappedTr.chunkId);
- if (bonds.find(bondEndPoints) == bonds.end() && bonds.find(bondEndPointsSwapped) != bonds.end())
- {
- continue; // We do not need account interface surface twice
- }
- if (bonds.find(bondEndPoints) == bonds.end())
- {
- bonds[bondEndPoints].second = 0;
- bonds[bondEndPoints].first = cleanBond;
- bonds[bondEndPoints].first.chunkIndices[0] = bondEndPoints.first;
- bonds[bondEndPoints].first.chunkIndices[1] = bondEndPoints.second;
- bonds[bondEndPoints].first.bond.normal[0] = pln.n[0];
- bonds[bondEndPoints].first.bond.normal[1] = pln.n[1];
- bonds[bondEndPoints].first.bond.normal[2] = pln.n[2];
- }
- const Triangle& trl2 = geometry[geometryOffset[mappedTr2.chunkId] + mappedTr2.trId];
+ TriangleProcessor trProcessor;
+ std::vector<NvBlastBondDesc> mResultBondDescs;
+ for (uint32_t i = 0; i < meshCount; ++i)
+ {
+ const uint32_t ihullCount = hullPoints[i].size();
+ 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
+ }
- TrPrcTriangle trp2(trl2.a.p, trl2.b.p, trl2.c.p);
- intersectionBufferLocal.clear();
- intersectionBufferLocal.reserve(32);
- trPrc.getTriangleIntersection(trp, trp2d, trp2, trCentroid, intersectionBufferLocal, pln.n);
- PxVec3 centroidPoint(0, 0, 0);
- int32_t collectedVerticesCount = 0;
- float area = 0;
- if (intersectionBufferLocal.size() >= 3)
+ const uint32_t jhullCount = hullPoints[j].size();
+ for (uint32_t ihull = 0; ihull < ihullCount; ++ihull)
+ {
+ for (uint32_t jhull = 0; jhull < jhullCount; ++jhull)
+ {
+ PxVec3 normal;
+ PxVec3 centroid;
+
+ float area = processWithMidplanes(
+ &trProcessor, geometry ? geometry + geometryOffset[i] : nullptr,
+ geometryOffset[i + 1] - geometryOffset[i], geometry ? geometry + geometryOffset[j] : nullptr,
+ geometryOffset[j + 1] - geometryOffset[j],
+ geometry ? nullptr : chunkHulls[geometryOffset[i] + ihull],
+ geometry ? nullptr : chunkHulls[geometryOffset[j] + jhull], hullPoints[i][ihull],
+ hullPoints[j][jhull], normal, centroid, conf.maxSeparation);
+
+ if (area > 0)
{
-#ifdef DEBUG_OUTPUT
- for (uint32_t p = 1; p < intersectionBufferLocal.size() - 1; ++p)
+ NvBlastBondDesc bDesc;
+ bDesc.chunkIndices[0] = i;
+ bDesc.chunkIndices[1] = j;
+ bDesc.bond.area = area;
+ bDesc.bond.centroid[0] = centroid.x;
+ 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)
{
- intersectionBuffer.push_back(intersectionBufferLocal[0]);
- intersectionBuffer.push_back(intersectionBufferLocal[p]);
- intersectionBuffer.push_back(intersectionBufferLocal[p + 1]);
+ normal = -normal;
}
-#endif
- centroidPoint = intersectionBufferLocal[0] + intersectionBufferLocal.back();
- collectedVerticesCount = 2;
- for (uint32_t j = 1; j < intersectionBufferLocal.size() - 1; ++j)
- {
- ++collectedVerticesCount;
- centroidPoint += intersectionBufferLocal[j];
- area += (intersectionBufferLocal[j + 1] - intersectionBufferLocal[0]).cross(intersectionBufferLocal[j] - intersectionBufferLocal[0]).magnitude();
- }
- }
- if (area > 0.00001f)
- {
- bonds[bondEndPoints].second += collectedVerticesCount;
+ bDesc.bond.normal[0] = normal.x;
+ bDesc.bond.normal[1] = normal.y;
+ bDesc.bond.normal[2] = normal.z;
- bonds[bondEndPoints].first.bond.area += area * 0.5f;
- bonds[bondEndPoints].first.bond.centroid[0] += (centroidPoint.x);
- bonds[bondEndPoints].first.bond.centroid[1] += (centroidPoint.y);
- bonds[bondEndPoints].first.bond.centroid[2] += (centroidPoint.z);
+ mResultBondDescs.push_back(bDesc);
}
}
}
+ }
+ }
+ resultBondDescs = SAFE_ARRAY_NEW(NvBlastBondDesc, mResultBondDescs.size());
+ memcpy(resultBondDescs, mResultBondDescs.data(), sizeof(NvBlastBondDesc) * mResultBondDescs.size());
+ return mResultBondDescs.size();
+}
- std::vector<NvBlastBondDesc> mResultBondDescs;
- for (auto it : bonds)
- {
- if (it.second.first.bond.area > 0)
- {
- float mlt = 1.0f / (it.second.second);
- it.second.first.bond.centroid[0] *= mlt;
- it.second.first.bond.centroid[1] *= mlt;
- it.second.first.bond.centroid[2] *= mlt;
-
- mResultBondDescs.push_back(it.second.first);
- }
+uint32_t isSamePlane(NvcPlane& a, NvcPlane& b)
+{
+ if (PxAbs(a.d - b.d) > EPS_PLANE)
+ return 0;
+ if (PxAbs(a.n.x - b.n.x) > EPS_PLANE)
+ return 0;
+ if (PxAbs(a.n.y - b.n.y) > EPS_PLANE)
+ return 0;
+ if (PxAbs(a.n.z - b.n.z) > EPS_PLANE)
+ return 0;
+ return 1;
+}
- }
+int32_t BlastBondGeneratorImpl::createFullBondListExact(uint32_t meshCount, const uint32_t* geometryOffset,
+ const Triangle* geometry, const bool* supportFlags,
+ NvBlastBondDesc*& resultBondDescs, BondGenerationConfig conf)
+{
+ std::vector<PlaneChunkIndexer> planeTriangleMapping;
+ NV_UNUSED(conf);
+ for (uint32_t i = 0; i < meshCount; ++i)
+ {
+ if (!supportFlags[i])
+ {
+ continue;
+ }
+ uint32_t count = geometryOffset[i + 1] - geometryOffset[i];
+ for (uint32_t j = 0; j < count; ++j)
+ {
#ifdef DEBUG_OUTPUT
- saveGeometryToObj(meshBuffer, "Mesh.obj");
- saveGeometryToObj(intersectionBuffer, "inter.obj");
+ meshBuffer.push_back(geometry[geometryOffset[i] + j].a.p);
+ meshBuffer.push_back(geometry[geometryOffset[i] + j].b.p);
+ meshBuffer.push_back(geometry[geometryOffset[i] + j].c.p);
#endif
- resultBondDescs = SAFE_ARRAY_NEW(NvBlastBondDesc, mResultBondDescs.size());
- memcpy(resultBondDescs, mResultBondDescs.data(), sizeof(NvBlastBondDesc)*mResultBondDescs.size());
- return mResultBondDescs.size();
+
+ NvcPlane nPlane = fromPxShared(physx::PxPlane(toPxShared(geometry[geometryOffset[i] + j].a.p),
+ toPxShared(geometry[geometryOffset[i] + j].b.p),
+ toPxShared(geometry[geometryOffset[i] + j].c.p)));
+ planeTriangleMapping.push_back({ (int32_t)i, (int32_t)j, nPlane });
}
+ }
- int32_t BlastBondGeneratorImpl::createBondForcedInternal(const std::vector<PxVec3>& hull0, const std::vector<PxVec3>& hull1,
- const CollisionHull& cHull0,const CollisionHull& cHull1,
- PxBounds3 bound0, PxBounds3 bound1, NvBlastBond& resultBond, float overlapping)
+ std::sort(planeTriangleMapping.begin(), planeTriangleMapping.end(), planeComparer);
+ return createFullBondListExactInternal(meshCount, geometryOffset, geometry, planeTriangleMapping, resultBondDescs);
+}
+
+void BlastBondGeneratorImpl::buildGeometryCache(uint32_t meshCount, const uint32_t* geometryOffset,
+ const Triangle* geometry)
+{
+ uint32_t geometryCount = geometryOffset[meshCount];
+ for (uint32_t i = 0; i < meshCount; i++)
+ {
+ mGeometryCache.push_back(std::vector<Triangle>());
+ uint32_t count = geometryOffset[i + 1] - geometryOffset[i];
+ mGeometryCache.back().resize(count);
+ memcpy(mGeometryCache.back().data(), geometry + geometryOffset[i], sizeof(Triangle) * count);
+ }
+ mHullsPointsCache.resize(geometryCount);
+ mBoundsCache.resize(geometryCount);
+ mCHullCache.resize(geometryCount);
+ for (uint32_t i = 0; i < mGeometryCache.size(); ++i)
+ {
+ for (uint32_t j = 0; j < mGeometryCache[i].size(); ++j)
{
- TriangleProcessor trProcessor;
- Separation separation;
- importerHullsInProximityApexFree(hull0.size(), hull0.data(), bound0, PxTransform(PxIdentity), PxVec3(1, 1, 1), hull1.size(), hull1.data(), bound1, PxTransform(PxIdentity), PxVec3(1, 1, 1), 0.000, &separation);
+ NvcPlane nPlane =
+ fromPxShared(physx::PxPlane(toPxShared(mGeometryCache[i][j].a.p), toPxShared(mGeometryCache[i][j].b.p),
+ toPxShared(mGeometryCache[i][j].c.p)));
+ mPlaneCache.push_back({ (int32_t)i, (int32_t)j, nPlane });
+ }
+ }
- if (std::isnan(separation.plane.d))
- {
- importerHullsInProximityApexFree(hull0.size(), hull0.data(), bound0, PxTransform(PxVec3(0.000001f, 0.000001f, 0.000001f)), PxVec3(1, 1, 1), hull1.size(), hull1.data(), bound1, PxTransform(PxIdentity), PxVec3(1, 1, 1), 0.000, &separation);
- if (std::isnan(separation.plane.d))
- {
- return 1;
- }
- }
+ for (uint32_t ch = 0; ch < mGeometryCache.size(); ++ch)
+ {
+ std::vector<NvcVec3> chunksPoints(mGeometryCache[ch].size() * 3);
- PxPlane pl = separation.plane;
- std::vector<PxVec3> ifsPoints[2];
+ int32_t sp = 0;
+ for (uint32_t i = 0; i < mGeometryCache[ch].size(); ++i)
+ {
+ chunksPoints[sp++] = mGeometryCache[ch][i].a.p;
+ chunksPoints[sp++] = mGeometryCache[ch][i].b.p;
+ chunksPoints[sp++] = mGeometryCache[ch][i].c.p;
+ }
- float dst[2][2];
+ mCHullCache[ch] = mConvexMeshBuilder->buildCollisionGeometry(chunksPoints.size(), chunksPoints.data());
- dst[0][0] = 0;
- dst[0][1] = MAXIMUM_EXTENT;
- for (uint32_t p = 0; p < cHull0.pointsCount; ++p)
+ mHullsPointsCache[ch].resize(mCHullCache[ch]->pointsCount);
+
+ mBoundsCache[ch].setEmpty();
+ for (uint32_t i = 0; i < mCHullCache[ch]->pointsCount; ++i)
+ {
+ mHullsPointsCache[ch][i] = toPxShared(mCHullCache[ch]->points[i]);
+ mBoundsCache[ch].include(mHullsPointsCache[ch][i]);
+ }
+ }
+}
+
+void BlastBondGeneratorImpl::resetGeometryCache()
+{
+ mGeometryCache.clear();
+ mPlaneCache.clear();
+ mHullsPointsCache.clear();
+ for (auto h : mCHullCache)
+ {
+ mConvexMeshBuilder->releaseCollisionHull(h);
+ }
+ mCHullCache.clear();
+ mBoundsCache.clear();
+}
+
+int32_t BlastBondGeneratorImpl::createFullBondListExactInternal(uint32_t meshCount, const uint32_t* geometryOffset,
+ const Triangle* geometry,
+ std::vector<PlaneChunkIndexer>& planeTriangleMapping,
+ NvBlastBondDesc*& resultBondDescs)
+{
+ NV_UNUSED(meshCount);
+
+ std::map<std::pair<int32_t, int32_t>, std::pair<NvBlastBondDesc, int32_t> > bonds;
+
+ TriangleProcessor trPrc;
+ std::vector<PxVec3> intersectionBufferLocal;
+
+ NvBlastBondDesc cleanBond;
+ memset(&cleanBond, 0, sizeof(NvBlastBondDesc));
+ for (uint32_t tIndex = 0; tIndex < planeTriangleMapping.size(); ++tIndex)
+ {
+
+ PlaneChunkIndexer opp = planeTriangleMapping[tIndex];
+
+ opp.plane.d *= -1;
+ opp.plane.n = opp.plane.n * - 1;
+
+ uint32_t startIndex =
+ (uint32_t)(std::lower_bound(planeTriangleMapping.begin(), planeTriangleMapping.end(), opp, planeComparer) -
+ planeTriangleMapping.begin());
+ uint32_t endIndex =
+ (uint32_t)(std::upper_bound(planeTriangleMapping.begin(), planeTriangleMapping.end(), opp, planeComparer) -
+ planeTriangleMapping.begin());
+ // uint32_t startIndex = 0;
+ // uint32_t endIndex = (uint32_t)planeTriangleMapping.size();
+
+ PlaneChunkIndexer& mappedTr = planeTriangleMapping[tIndex];
+ const Triangle& trl = geometry[geometryOffset[mappedTr.chunkId] + mappedTr.trId];
+ PxPlane pln = toPxShared(mappedTr.plane);
+ TrPrcTriangle trp(toPxShared(trl.a.p), toPxShared(trl.b.p), toPxShared(trl.c.p));
+ PxVec3 trCentroid = toPxShared(trl.a.p + trl.b.p + trl.c.p) * (1.0f / 3.0f);
+ trp.points[0] -= trCentroid;
+ trp.points[1] -= trCentroid;
+ trp.points[2] -= trCentroid;
+ ProjectionDirections pDir = getProjectionDirection(pln.n);
+ TrPrcTriangle2d trp2d;
+ trp2d.points[0] = getProjectedPointWithWinding(trp.points[0], pDir);
+ trp2d.points[1] = getProjectedPointWithWinding(trp.points[1], pDir);
+ trp2d.points[2] = getProjectedPointWithWinding(trp.points[2], pDir);
+
+ for (uint32_t i = startIndex; i <= endIndex && i < planeTriangleMapping.size(); ++i)
+ {
+ PlaneChunkIndexer& mappedTr2 = planeTriangleMapping[i];
+ if (mappedTr2.trId == opp.chunkId)
{
- float d = pl.distance(cHull0.points[p]);
- if (PxAbs(d) > PxAbs(dst[0][0]))
- {
- dst[0][0] = d;
- }
- if (PxAbs(d) < PxAbs(dst[0][1]))
- {
- dst[0][1] = d;
- }
+ continue;
}
- dst[1][0] = 0;
- dst[1][1] = MAXIMUM_EXTENT;
- for (uint32_t p = 0; p < cHull1.pointsCount; ++p)
+ if (!isSamePlane(opp.plane, mappedTr2.plane))
{
- float d = pl.distance(cHull0.points[p]);
- if (PxAbs(d) > PxAbs(dst[1][0]))
- {
- dst[1][0] = d;
- }
- if (PxAbs(d) < PxAbs(dst[1][1]))
- {
- dst[1][1] = d;
- }
+ continue;
}
-
- float cvOffset[2] = { dst[0][1] + (dst[0][0] - dst[0][1]) * overlapping, dst[1][1] + (dst[1][0] - dst[1][1]) * overlapping };
-
- for (uint32_t i = 0; i < cHull0.polygonDataCount; ++i)
+ if (mappedTr.chunkId == mappedTr2.chunkId)
{
- auto& pd = cHull0.polygonData[i];
- PxVec3 result;
- for (uint32_t j = 0; j < pd.mNbVerts; ++j)
- {
- uint32_t nxj = (j + 1) % pd.mNbVerts;
- const uint32_t* ind = cHull0.indices;
- PxVec3 a = hull0[ind[j + pd.mIndexBase]] - pl.n * cvOffset[0];
- PxVec3 b = hull0[ind[nxj + pd.mIndexBase]] - pl.n * cvOffset[0];
-
- if (getPlaneSegmentIntersection(pl, a, b, result))
- {
- ifsPoints[0].push_back(result);
- }
- }
+ continue;
}
-
- for (uint32_t i = 0; i < cHull1.polygonDataCount; ++i)
+ std::pair<int32_t, int32_t> bondEndPoints = std::make_pair(mappedTr.chunkId, mappedTr2.chunkId);
+ if (bondEndPoints.second < bondEndPoints.first)
+ continue;
+ std::pair<int32_t, int32_t> bondEndPointsSwapped = std::make_pair(mappedTr2.chunkId, mappedTr.chunkId);
+ if (bonds.find(bondEndPoints) == bonds.end() && bonds.find(bondEndPointsSwapped) != bonds.end())
{
- auto& pd = cHull1.polygonData[i];
- PxVec3 result;
- for (uint32_t j = 0; j < pd.mNbVerts; ++j)
- {
- uint32_t nxj = (j + 1) % pd.mNbVerts;
- const uint32_t* ind = cHull1.indices;
- PxVec3 a = hull1[ind[j + pd.mIndexBase]] - pl.n * cvOffset[1];
- PxVec3 b = hull1[ind[nxj + pd.mIndexBase]] - pl.n * cvOffset[1];
-
- if (getPlaneSegmentIntersection(pl, a, b, result))
- {
- ifsPoints[1].push_back(result);
- }
- }
+ continue; // We do not need account interface surface twice
}
+ if (bonds.find(bondEndPoints) == bonds.end())
+ {
+ bonds[bondEndPoints].second = 0;
+ bonds[bondEndPoints].first = cleanBond;
+ bonds[bondEndPoints].first.chunkIndices[0] = bondEndPoints.first;
+ bonds[bondEndPoints].first.chunkIndices[1] = bondEndPoints.second;
+ bonds[bondEndPoints].first.bond.normal[0] = pln.n[0];
+ bonds[bondEndPoints].first.bond.normal[1] = pln.n[1];
+ bonds[bondEndPoints].first.bond.normal[2] = pln.n[2];
+ }
+ const Triangle& trl2 = geometry[geometryOffset[mappedTr2.chunkId] + mappedTr2.trId];
+ TrPrcTriangle trp2(toPxShared(trl2.a.p), toPxShared(trl2.b.p), toPxShared(trl2.c.p));
- std::vector<PxVec3> convexes[2];
-
- trProcessor.buildConvexHull(ifsPoints[0], convexes[0], pl.n);
- trProcessor.buildConvexHull(ifsPoints[1], convexes[1], pl.n);
-
- float areas[2] = { 0, 0 };
- PxVec3 centroids[2] = { PxVec3(0, 0, 0), PxVec3(0, 0, 0) };
-
- for (uint32_t cv = 0; cv < 2; ++cv)
+ intersectionBufferLocal.clear();
+ intersectionBufferLocal.reserve(32);
+ trPrc.getTriangleIntersection(trp, trp2d, trp2, trCentroid, intersectionBufferLocal, pln.n);
+ PxVec3 centroidPoint(0, 0, 0);
+ int32_t collectedVerticesCount = 0;
+ float area = 0;
+ if (intersectionBufferLocal.size() >= 3)
{
- if (convexes[cv].size() == 0)
+#ifdef DEBUG_OUTPUT
+ for (uint32_t p = 1; p < intersectionBufferLocal.size() - 1; ++p)
{
- continue;
+ intersectionBuffer.push_back(intersectionBufferLocal[0]);
+ intersectionBuffer.push_back(intersectionBufferLocal[p]);
+ intersectionBuffer.push_back(intersectionBufferLocal[p + 1]);
}
- centroids[cv] = convexes[cv][0] + convexes[cv].back();
- for (uint32_t i = 1; i < convexes[cv].size() - 1; ++i)
- {
- centroids[cv] += convexes[cv][i];
- areas[cv] += (convexes[cv][i + 1] - convexes[cv][0]).cross(convexes[cv][i] - convexes[cv][0]).magnitude();
-#ifdef DEBUG_OUTPUT
- intersectionBuffer.push_back(convexes[cv][0]);
- intersectionBuffer.push_back(convexes[cv][i]);
- intersectionBuffer.push_back(convexes[cv][i + 1]);
#endif
+ centroidPoint = intersectionBufferLocal[0] + intersectionBufferLocal.back();
+ collectedVerticesCount = 2;
+ for (uint32_t j = 1; j < intersectionBufferLocal.size() - 1; ++j)
+ {
+ ++collectedVerticesCount;
+ centroidPoint += intersectionBufferLocal[j];
+ area += (intersectionBufferLocal[j + 1] - intersectionBufferLocal[0])
+ .cross(intersectionBufferLocal[j] - intersectionBufferLocal[0])
+ .magnitude();
}
- centroids[cv] *= (1.0f / convexes[cv].size());
- areas[cv] = PxAbs(areas[cv]);
}
+ if (area > 0.00001f)
+ {
+ bonds[bondEndPoints].second += collectedVerticesCount;
- resultBond.area = (areas[0] + areas[1]) * 0.5f;
- resultBond.centroid[0] = (centroids[0][0] + centroids[1][0]) * 0.5f;
- resultBond.centroid[1] = (centroids[0][1] + centroids[1][1]) * 0.5f;
- resultBond.centroid[2] = (centroids[0][2] + centroids[1][2]) * 0.5f;
- resultBond.normal[0] = pl.n[0];
- resultBond.normal[1] = pl.n[1];
- resultBond.normal[2] = pl.n[2];
+ bonds[bondEndPoints].first.bond.area += area * 0.5f;
+ bonds[bondEndPoints].first.bond.centroid[0] += (centroidPoint.x);
+ bonds[bondEndPoints].first.bond.centroid[1] += (centroidPoint.y);
+ bonds[bondEndPoints].first.bond.centroid[2] += (centroidPoint.z);
+ }
+ }
+ }
+ std::vector<NvBlastBondDesc> mResultBondDescs;
+ for (auto it : bonds)
+ {
+ if (it.second.first.bond.area > 0)
+ {
+ float mlt = 1.0f / (it.second.second);
+ it.second.first.bond.centroid[0] *= mlt;
+ it.second.first.bond.centroid[1] *= mlt;
+ it.second.first.bond.centroid[2] *= mlt;
+
+ mResultBondDescs.push_back(it.second.first);
+ }
+ }
#ifdef DEBUG_OUTPUT
- saveGeometryToObj(meshBuffer, "ArbitMeshes.obj");
- saveGeometryToObj(intersectionBuffer, "inter.obj");
+ saveGeometryToObj(meshBuffer, "Mesh.obj");
+ saveGeometryToObj(intersectionBuffer, "inter.obj");
#endif
+ resultBondDescs = SAFE_ARRAY_NEW(NvBlastBondDesc, mResultBondDescs.size());
+ memcpy(resultBondDescs, mResultBondDescs.data(), sizeof(NvBlastBondDesc) * mResultBondDescs.size());
+ return mResultBondDescs.size();
+}
+
+int32_t BlastBondGeneratorImpl::createBondForcedInternal(const std::vector<PxVec3>& hull0,
+ const std::vector<PxVec3>& hull1, const CollisionHull& cHull0,
+ const CollisionHull& cHull1, PxBounds3 bound0,
+ PxBounds3 bound1, NvBlastBond& resultBond, float overlapping)
+{
+
+ TriangleProcessor trProcessor;
+ Separation separation;
+ importerHullsInProximityApexFree(hull0.size(), hull0.data(), bound0, PxTransform(PxIdentity), PxVec3(1, 1, 1),
+ hull1.size(), hull1.data(), bound1, PxTransform(PxIdentity), PxVec3(1, 1, 1),
+ 0.000, &separation);
+
+ if (std::isnan(separation.plane.d))
+ {
+ importerHullsInProximityApexFree(
+ hull0.size(), hull0.data(), bound0, PxTransform(PxVec3(0.000001f, 0.000001f, 0.000001f)), PxVec3(1, 1, 1),
+ hull1.size(), hull1.data(), bound1, PxTransform(PxIdentity), PxVec3(1, 1, 1), 0.000, &separation);
+ if (std::isnan(separation.plane.d))
+ {
+ return 1;
+ }
+ }
+ PxPlane pl = separation.plane;
+ std::vector<PxVec3> ifsPoints[2];
- return 0;
+ float dst[2][2];
+
+ dst[0][0] = 0;
+ dst[0][1] = MAXIMUM_EXTENT;
+ for (uint32_t p = 0; p < cHull0.pointsCount; ++p)
+ {
+ float d = pl.distance(toPxShared(cHull0.points[p]));
+ if (PxAbs(d) > PxAbs(dst[0][0]))
+ {
+ dst[0][0] = d;
}
-
- int32_t BlastBondGeneratorImpl::buildDescFromInternalFracture(FractureTool* tool, const bool* chunkIsSupport,
- NvBlastBondDesc*& resultBondDescs, NvBlastChunkDesc*& resultChunkDescriptors)
+ if (PxAbs(d) < PxAbs(dst[0][1]))
{
- uint32_t chunkCount = tool->getChunkCount();
- std::vector<uint32_t> trianglesCount(chunkCount);
- std::vector<std::shared_ptr<Triangle>> trianglesBuffer;
+ dst[0][1] = d;
+ }
+ }
- for (uint32_t i = 0; i < chunkCount; ++i)
- {
- Triangle* t;
- trianglesCount[i] = tool->getBaseMesh(i, t);
- trianglesBuffer.push_back(std::shared_ptr<Triangle>(t, [](Triangle* t) {
- delete[] t;
- }));
- }
+ dst[1][0] = 0;
+ dst[1][1] = MAXIMUM_EXTENT;
+ for (uint32_t p = 0; p < cHull1.pointsCount; ++p)
+ {
+ float d = pl.distance(toPxShared(cHull0.points[p]));
+ if (PxAbs(d) > PxAbs(dst[1][0]))
+ {
+ dst[1][0] = d;
+ }
+ if (PxAbs(d) < PxAbs(dst[1][1]))
+ {
+ dst[1][1] = d;
+ }
+ }
- if (chunkCount == 0)
- {
- return 0;
- }
- resultChunkDescriptors = SAFE_ARRAY_NEW(NvBlastChunkDesc, trianglesBuffer.size());
- std::vector<Bond> bondDescriptors;
- resultChunkDescriptors[0].parentChunkIndex = UINT32_MAX;
- resultChunkDescriptors[0].userData = 0;
- resultChunkDescriptors[0].flags = NvBlastChunkDesc::NoFlags;
+ float cvOffset[2] = { dst[0][1] + (dst[0][0] - dst[0][1]) * overlapping,
+ dst[1][1] + (dst[1][0] - dst[1][1]) * overlapping };
+
+ for (uint32_t i = 0; i < cHull0.polygonDataCount; ++i)
+ {
+ auto& pd = cHull0.polygonData[i];
+ PxVec3 result;
+ for (uint32_t j = 0; j < pd.vertexCount; ++j)
+ {
+ uint32_t nxj = (j + 1) % pd.vertexCount;
+ const uint32_t* ind = cHull0.indices;
+ PxVec3 a = hull0[ind[j + pd.indexBase]] - pl.n * cvOffset[0];
+ PxVec3 b = hull0[ind[nxj + pd.indexBase]] - pl.n * cvOffset[0];
+
+ if (getPlaneSegmentIntersection(pl, a, b, result))
{
- PxVec3 chunkCentroid(0, 0, 0);
- for (uint32_t tr = 0; tr < trianglesCount[0]; ++tr)
- {
- 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];
- resultChunkDescriptors[0].centroid[1] = chunkCentroid[1];
- resultChunkDescriptors[0].centroid[2] = chunkCentroid[2];
+ ifsPoints[0].push_back(result);
}
+ }
+ }
-
- bool hasCreatedByIslands = false;
+ for (uint32_t i = 0; i < cHull1.polygonDataCount; ++i)
+ {
+ auto& pd = cHull1.polygonData[i];
+ PxVec3 result;
+ for (uint32_t j = 0; j < pd.vertexCount; ++j)
+ {
+ uint32_t nxj = (j + 1) % pd.vertexCount;
+ const uint32_t* ind = cHull1.indices;
+ PxVec3 a = hull1[ind[j + pd.indexBase]] - pl.n * cvOffset[1];
+ PxVec3 b = hull1[ind[nxj + pd.indexBase]] - pl.n * cvOffset[1];
- for (uint32_t i = 1; i < chunkCount; ++i)
+ if (getPlaneSegmentIntersection(pl, a, b, result))
{
- 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)
- {
- auto& trRef = trianglesBuffer[i].get()[tr];
- chunkCentroid += trRef.a.p;
- chunkCentroid += trRef.b.p;
- chunkCentroid += trRef.c.p;
-
- int32_t id = trRef.userData;
- if (id == 0)
- continue;
- bondDescriptors.push_back(Bond());
- Bond& bond = bondDescriptors.back();
- bond.m_chunkId = i;
- bond.m_planeIndex = id;
- bond.triangleIndex = tr;
- }
- chunkCentroid *= (1.0f / (3 * trianglesCount[i]));
- desc.centroid[0] = chunkCentroid[0];
- desc.centroid[1] = chunkCentroid[1];
- desc.centroid[2] = chunkCentroid[2];
+ ifsPoints[1].push_back(result);
}
- std::sort(bondDescriptors.begin(), bondDescriptors.end());
+ }
+ }
- std::vector<NvBlastBondDesc> mResultBondDescs;
+ std::vector<PxVec3> convexes[2];
- if (!bondDescriptors.empty())
- {
+ trProcessor.buildConvexHull(ifsPoints[0], convexes[0], pl.n);
+ trProcessor.buildConvexHull(ifsPoints[1], convexes[1], pl.n);
- 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 (i == bondDescriptors.size() || (chunkId != bondDescriptors[i].m_chunkId || abs(planeId) != abs(bondDescriptors[i].m_planeIndex)))
- {
- if (chunkId != -1)
- {
- 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;
- }
- if (i == bondDescriptors.size() || abs(planeId) != abs(bondDescriptors[i].m_planeIndex))
- {
- for (uint32_t fchunk = 0; fchunk < forwardChunks.size(); ++fchunk)
- {
- if (chunkIsSupport[forwardChunks[fchunk].m_chunkId] == false)
- {
- continue;
- }
- for (uint32_t bchunk = 0; bchunk < backwardChunks.size(); ++bchunk)
- {
- 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;
- }
- }
- forwardChunks.clear();
- backwardChunks.clear();
- if (i != bondDescriptors.size())
- {
- planeId = bondDescriptors[i].m_planeIndex;
- }
- else
- {
- break;
- }
- }
+ float areas[2] = { 0, 0 };
+ PxVec3 centroids[2] = { PxVec3(0, 0, 0), PxVec3(0, 0, 0) };
- 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);
- }
- }
+ for (uint32_t cv = 0; cv < 2; ++cv)
+ {
+ if (convexes[cv].size() == 0)
+ {
+ continue;
+ }
+ centroids[cv] = convexes[cv][0] + convexes[cv].back();
+ for (uint32_t i = 1; i < convexes[cv].size() - 1; ++i)
+ {
+ centroids[cv] += convexes[cv][i];
+ areas[cv] += (convexes[cv][i + 1] - convexes[cv][0]).cross(convexes[cv][i] - convexes[cv][0]).magnitude();
+#ifdef DEBUG_OUTPUT
+ intersectionBuffer.push_back(convexes[cv][0]);
+ intersectionBuffer.push_back(convexes[cv][i]);
+ intersectionBuffer.push_back(convexes[cv][i + 1]);
+#endif
+ }
+ centroids[cv] *= (1.0f / convexes[cv].size());
+ areas[cv] = PxAbs(areas[cv]);
+ }
- if (hasCreatedByIslands)
- {
- std::vector<Triangle> chunkTriangles;
- std::vector<uint32_t> chunkTrianglesOffsets;
-
- std::set<std::pair<uint32_t, uint32_t> > pairsAlreadyCreated;
+ resultBond.area = (areas[0] + areas[1]) * 0.5f;
+ resultBond.centroid[0] = (centroids[0][0] + centroids[1][0]) * 0.5f;
+ resultBond.centroid[1] = (centroids[0][1] + centroids[1][1]) * 0.5f;
+ resultBond.centroid[2] = (centroids[0][2] + centroids[1][2]) * 0.5f;
+ resultBond.normal[0] = pl.n[0];
+ resultBond.normal[1] = pl.n[1];
+ resultBond.normal[2] = pl.n[2];
- 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]);
+#ifdef DEBUG_OUTPUT
+ saveGeometryToObj(meshBuffer, "ArbitMeshes.obj");
+ saveGeometryToObj(intersectionBuffer, "inter.obj");
+#endif
- pairsAlreadyCreated.insert(pr);
- }
+ return 0;
+}
- 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)
- {
- chunkTriangles.push_back(trianglesBuffer[i].get()[k]);
+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<std::shared_ptr<Triangle> > trianglesBuffer;
- chunkTriangles.back().a.p = (chunkTriangles.back().a.p - centroid) * SCALE_FACTOR + centroid; // inflate mesh a bit to find
- }
- chunkTrianglesOffsets.push_back(chunkTriangles.size());
- }
+ for (uint32_t i = 0; i < chunkCount; ++i)
+ {
+ Triangle* t;
+ trianglesCount[i] = tool->getBaseMesh(i, t);
+ trianglesBuffer.push_back(std::shared_ptr<Triangle>(t, [](Triangle* t) { delete[] t; }));
+ }
- NvBlastBondDesc* adsc;
+ if (chunkCount == 0)
+ {
+ return 0;
+ }
+ resultChunkDescriptors = SAFE_ARRAY_NEW(NvBlastChunkDesc, trianglesBuffer.size());
+ std::vector<Bond> bondDescriptors;
+ resultChunkDescriptors[0].parentChunkIndex = UINT32_MAX;
+ resultChunkDescriptors[0].userData = 0;
+ resultChunkDescriptors[0].flags = NvBlastChunkDesc::NoFlags;
+ {
+ PxVec3 chunkCentroid(0, 0, 0);
+ for (uint32_t tr = 0; tr < trianglesCount[0]; ++tr)
+ {
+ chunkCentroid += toPxShared(trianglesBuffer[0].get()[tr].a.p);
+ chunkCentroid += toPxShared(trianglesBuffer[0].get()[tr].b.p);
+ chunkCentroid += toPxShared(trianglesBuffer[0].get()[tr].c.p);
+ }
+ chunkCentroid *= (1.0f / (3 * trianglesCount[0]));
+ resultChunkDescriptors[0].centroid[0] = chunkCentroid[0];
+ resultChunkDescriptors[0].centroid[1] = chunkCentroid[1];
+ resultChunkDescriptors[0].centroid[2] = chunkCentroid[2];
+ }
- 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);
+ bool hasCreatedByIslands = false;
- for (uint32_t i = 0; i < nbListSize; ++i)
- {
- mResultBondDescs.push_back(adsc[i]);
- }
- NVBLAST_FREE(adsc);
- }
+ 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)
+ {
+ auto& trRef = trianglesBuffer[i].get()[tr];
+ chunkCentroid += toPxShared(trRef.a.p);
+ chunkCentroid += toPxShared(trRef.b.p);
+ chunkCentroid += toPxShared(trRef.c.p);
+
+ int32_t id = trRef.userData;
+ if (id == 0)
+ continue;
+ bondDescriptors.push_back(Bond());
+ Bond& bond = bondDescriptors.back();
+ bond.m_chunkId = i;
+ bond.m_planeIndex = id;
+ bond.triangleIndex = tr;
+ }
+ chunkCentroid *= (1.0f / (3 * trianglesCount[i]));
+ desc.centroid[0] = chunkCentroid[0];
+ desc.centroid[1] = chunkCentroid[1];
+ desc.centroid[2] = chunkCentroid[2];
+ }
+ std::sort(bondDescriptors.begin(), bondDescriptors.end());
- resultBondDescs = SAFE_ARRAY_NEW(NvBlastBondDesc, mResultBondDescs.size());
- memcpy(resultBondDescs, mResultBondDescs.data(), sizeof(NvBlastBondDesc) * mResultBondDescs.size());
- return mResultBondDescs.size();
- }
+ std::vector<NvBlastBondDesc> mResultBondDescs;
+
+ if (!bondDescriptors.empty())
+ {
- int32_t BlastBondGeneratorImpl::createBondBetweenMeshes(uint32_t meshCount, const uint32_t* geometryOffset, const Triangle* geometry,
- uint32_t overlapsCount, const uint32_t* overlapsA, const uint32_t* overlapsB, NvBlastBondDesc*& resultBond, BondGenerationConfig cfg)
+ 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 (cfg.bondMode == BondGenerationConfig::AVERAGE)
+ if (i == bondDescriptors.size() ||
+ (chunkId != bondDescriptors[i].m_chunkId || abs(planeId) != abs(bondDescriptors[i].m_planeIndex)))
{
- resetGeometryCache();
- buildGeometryCache(meshCount, geometryOffset, geometry);
- }
- resultBond = SAFE_ARRAY_NEW(NvBlastBondDesc, overlapsCount);
-
- if (cfg.bondMode == BondGenerationConfig::EXACT)
- {
- for (uint32_t i = 0; i < overlapsCount; ++i)
+ if (chunkId != -1)
{
- NvBlastBondDesc& desc = resultBond[i];
- desc.chunkIndices[0] = overlapsA[i];
- desc.chunkIndices[1] = overlapsB[i];
- uint32_t meshACount = geometryOffset[overlapsA[i] + 1] - geometryOffset[overlapsA[i]];
- uint32_t meshBCount = geometryOffset[overlapsB[i] + 1] - geometryOffset[overlapsB[i]];
- createBondBetweenMeshes(meshACount, geometry + geometryOffset[overlapsA[i]],
- meshBCount, geometry + geometryOffset[overlapsB[i]], desc.bond, cfg);
+ 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;
}
- else
+ if (i == bondDescriptors.size() || abs(planeId) != abs(bondDescriptors[i].m_planeIndex))
{
- for (uint32_t i = 0; i < overlapsCount; ++i)
+ for (uint32_t fchunk = 0; fchunk < forwardChunks.size(); ++fchunk)
{
- NvBlastBondDesc& desc = resultBond[i];
- desc.chunkIndices[0] = overlapsA[i];
- desc.chunkIndices[1] = overlapsB[i];
- createBondForcedInternal(mHullsPointsCache[overlapsA[i]], mHullsPointsCache[overlapsB[i]], *mCHullCache[overlapsA[i]], *mCHullCache[overlapsB[i]],
- mBoundsCache[overlapsA[i]], mBoundsCache[overlapsB[i]], desc.bond, 0.3f);
+ if (chunkIsSupport[forwardChunks[fchunk].m_chunkId] == false)
+ {
+ continue;
+ }
+ for (uint32_t bchunk = 0; bchunk < backwardChunks.size(); ++bchunk)
+ {
+ 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;
+ }
}
- }
-
- return overlapsCount;
- }
-
- int32_t BlastBondGeneratorImpl::createBondBetweenMeshes(uint32_t meshACount, const Triangle* meshA, uint32_t meshBCount, const Triangle* meshB,
- NvBlastBond& resultBond, BondGenerationConfig conf)
- {
- float overlapping = 0.3;
- if (conf.bondMode == BondGenerationConfig::EXACT)
- {
- std::vector<uint32_t> chunksOffsets = { 0, meshACount, meshACount + meshBCount };
- std::vector<Triangle> chunks;
- chunks.resize(meshACount + meshBCount);
- memcpy(chunks.data(), meshA, sizeof(Triangle) * meshACount);
- memcpy(chunks.data() + meshACount, meshB, sizeof(Triangle) * meshBCount);
- std::shared_ptr<bool> isSupport(new bool[2] {true, true}, [](bool* b) { delete[] b; });
- NvBlastBondDesc* desc;
- uint32_t descSize = createFullBondListExact(2, chunksOffsets.data(), chunks.data(), isSupport.get(), desc, conf);
- if (descSize > 0)
+ forwardChunks.clear();
+ backwardChunks.clear();
+ if (i != bondDescriptors.size())
{
- resultBond = desc->bond;
+ planeId = bondDescriptors[i].m_planeIndex;
}
else
{
- memset(&resultBond, 0, sizeof(NvBlastBond));
- return 1;
+ break;
}
- return 0;
}
-
- std::vector<PxVec3> chunksPoints1(meshACount * 3);
- std::vector<PxVec3> chunksPoints2(meshBCount * 3);
- int32_t sp = 0;
- for (uint32_t i = 0; i < meshACount; ++i)
- {
- chunksPoints1[sp++] = meshA[i].a.p;
- chunksPoints1[sp++] = meshA[i].b.p;
- chunksPoints1[sp++] = meshA[i].c.p;
-#ifdef DEBUG_OUTPUT
- meshBuffer.push_back(meshA[i].a.p);
- meshBuffer.push_back(meshA[i].b.p);
- meshBuffer.push_back(meshA[i].c.p);
-#endif
+ collected++;
+ auto& trRef = trianglesBuffer[chunkId].get()[bondDescriptors[i].triangleIndex];
+ PxVec3 n = getNormal(trRef);
+ area += n.magnitude();
+ normal = n.getNormalized();
+ centroid += toPxShared(trRef.a.p);
+ centroid += toPxShared(trRef.b.p);
+ centroid += toPxShared(trRef.c.p);
+
+ bb.include(toPxShared(trRef.a.p));
+ bb.include(toPxShared(trRef.b.p));
+ bb.include(toPxShared(trRef.c.p));
+ }
+ }
+
+ if (hasCreatedByIslands)
+ {
+ std::vector<Triangle> chunkTriangles;
+ std::vector<uint32_t> chunkTrianglesOffsets;
+ std::set<std::pair<uint32_t, uint32_t> > pairsAlreadyCreated;
- }
- sp = 0;
- for (uint32_t i = 0; i < meshBCount; ++i)
+ 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;
+ NvcVec3 centroid = {resultChunkDescriptors[i].centroid[0], resultChunkDescriptors[i].centroid[1],
+ resultChunkDescriptors[i].centroid[2]};
+ for (uint32_t k = 0; k < trianglesCount[i]; ++k)
{
- chunksPoints2[sp++] = meshB[i].a.p;
- chunksPoints2[sp++] = meshB[i].b.p;
- chunksPoints2[sp++] = meshB[i].c.p;
-#ifdef DEBUG_OUTPUT
- meshBuffer.push_back(meshB[i].a.p);
- meshBuffer.push_back(meshB[i].b.p);
- meshBuffer.push_back(meshB[i].c.p);
-#endif
- }
+ 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());
+ }
- Nv::Blast::ConvexMeshBuilderImpl builder(mPxCooking, mPxInsertionCallback);
+ NvBlastBondDesc* adsc;
- CollisionHull* cHull[2];
- cHull[0] = builder.buildCollisionGeometry(chunksPoints1.size(), chunksPoints1.data());
- cHull[1] = builder.buildCollisionGeometry(chunksPoints2.size(), chunksPoints2.data());
+ BondGenerationConfig cfg;
+ cfg.bondMode = BondGenerationConfig::AVERAGE;
+ cfg.maxSeparation = 0.0f;
- std::vector<PxVec3> hullPoints[2];
- hullPoints[0].resize(cHull[0]->pointsCount);
- hullPoints[1].resize(cHull[1]->pointsCount);
+ 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);
+ }
- PxBounds3 bb[2];
- bb[0].setEmpty();
- bb[1].setEmpty();
+ resultBondDescs = SAFE_ARRAY_NEW(NvBlastBondDesc, mResultBondDescs.size());
+ memcpy(resultBondDescs, mResultBondDescs.data(), sizeof(NvBlastBondDesc) * mResultBondDescs.size());
- for (uint32_t cv = 0; cv < 2; ++cv)
- {
- for (uint32_t i = 0; i < cHull[cv]->pointsCount; ++i)
- {
- hullPoints[cv][i] = cHull[cv]->points[i];
- bb[cv].include(hullPoints[cv][i]);
- }
- }
- auto ret = createBondForcedInternal(hullPoints[0], hullPoints[1], *cHull[0], *cHull[1], bb[0], bb[1], resultBond, overlapping);
+ return mResultBondDescs.size();
+}
- cHull[0]->release();
- cHull[1]->release();
+int32_t BlastBondGeneratorImpl::createBondBetweenMeshes(uint32_t meshCount, const uint32_t* geometryOffset,
+ const Triangle* geometry, uint32_t overlapsCount,
+ const uint32_t* overlapsA, const uint32_t* overlapsB,
+ NvBlastBondDesc*& resultBond, BondGenerationConfig cfg)
+{
+ if (cfg.bondMode == BondGenerationConfig::AVERAGE)
+ {
+ resetGeometryCache();
+ buildGeometryCache(meshCount, geometryOffset, geometry);
+ }
+ resultBond = SAFE_ARRAY_NEW(NvBlastBondDesc, overlapsCount);
- return ret;
+ if (cfg.bondMode == BondGenerationConfig::EXACT)
+ {
+ for (uint32_t i = 0; i < overlapsCount; ++i)
+ {
+ NvBlastBondDesc& desc = resultBond[i];
+ desc.chunkIndices[0] = overlapsA[i];
+ desc.chunkIndices[1] = overlapsB[i];
+ uint32_t meshACount = geometryOffset[overlapsA[i] + 1] - geometryOffset[overlapsA[i]];
+ uint32_t meshBCount = geometryOffset[overlapsB[i] + 1] - geometryOffset[overlapsB[i]];
+ createBondBetweenMeshes(meshACount, geometry + geometryOffset[overlapsA[i]], meshBCount,
+ geometry + geometryOffset[overlapsB[i]], desc.bond, cfg);
}
-
- int32_t BlastBondGeneratorImpl::bondsFromPrefractured(uint32_t meshCount, const uint32_t* geometryCount, const Triangle* geometry,
- const bool* chunkIsSupport, NvBlastBondDesc*& resultBondDescs, BondGenerationConfig conf)
+ }
+ else
+ {
+ for (uint32_t i = 0; i < overlapsCount; ++i)
{
- int32_t ret_val = 0;
- switch (conf.bondMode)
- {
- case BondGenerationConfig::AVERAGE:
- ret_val = createFullBondListAveraged(meshCount, geometryCount, geometry, nullptr, chunkIsSupport, nullptr, resultBondDescs, conf);
- break;
- case BondGenerationConfig::EXACT:
- ret_val = createFullBondListExact(meshCount, geometryCount, geometry, chunkIsSupport, resultBondDescs, conf);
- break;
- }
- return ret_val;
+ NvBlastBondDesc& desc = resultBond[i];
+ desc.chunkIndices[0] = overlapsA[i];
+ desc.chunkIndices[1] = overlapsB[i];
+ createBondForcedInternal(mHullsPointsCache[overlapsA[i]], mHullsPointsCache[overlapsB[i]],
+ *mCHullCache[overlapsA[i]], *mCHullCache[overlapsB[i]], mBoundsCache[overlapsA[i]],
+ mBoundsCache[overlapsB[i]], desc.bond, 0.3f);
}
+ }
+ return overlapsCount;
+}
- int32_t BlastBondGeneratorImpl::bondsFromPrefractured(uint32_t meshCount, const uint32_t* convexHullOffset, const CollisionHull** chunkHulls, const bool* chunkIsSupport, const uint32_t* meshGroups, NvBlastBondDesc*& resultBondDescs, float maxSeparation)
+int32_t BlastBondGeneratorImpl::createBondBetweenMeshes(uint32_t meshACount, const Triangle* meshA, uint32_t meshBCount,
+ const Triangle* meshB, NvBlastBond& resultBond,
+ BondGenerationConfig conf)
+{
+ float overlapping = 0.3;
+ if (conf.bondMode == BondGenerationConfig::EXACT)
+ {
+ std::vector<uint32_t> chunksOffsets = { 0, meshACount, meshACount + meshBCount };
+ std::vector<Triangle> chunks;
+ chunks.resize(meshACount + meshBCount);
+ memcpy(chunks.data(), meshA, sizeof(Triangle) * meshACount);
+ memcpy(chunks.data() + meshACount, meshB, sizeof(Triangle) * meshBCount);
+ std::shared_ptr<bool> isSupport(new bool[2]{ true, true }, [](bool* b) { delete[] b; });
+ NvBlastBondDesc* desc;
+ uint32_t descSize = createFullBondListExact(2, chunksOffsets.data(), chunks.data(), isSupport.get(), desc, conf);
+ if (descSize > 0)
{
- BondGenerationConfig conf;
- conf.maxSeparation = maxSeparation;
- conf.bondMode = BondGenerationConfig::AVERAGE;
- return createFullBondListAveraged(meshCount, convexHullOffset, nullptr, chunkHulls, chunkIsSupport, meshGroups, resultBondDescs, conf);
+ resultBond = desc->bond;
}
+ else
+ {
+ memset(&resultBond, 0, sizeof(NvBlastBond));
+ return 1;
+ }
+ return 0;
+ }
+
+ std::vector<NvcVec3> chunksPoints1(meshACount * 3);
+ std::vector<NvcVec3> chunksPoints2(meshBCount * 3);
+
+ int32_t sp = 0;
+ for (uint32_t i = 0; i < meshACount; ++i)
+ {
+ chunksPoints1[sp++] = meshA[i].a.p;
+ chunksPoints1[sp++] = meshA[i].b.p;
+ chunksPoints1[sp++] = meshA[i].c.p;
+#ifdef DEBUG_OUTPUT
+ meshBuffer.push_back(meshA[i].a.p);
+ meshBuffer.push_back(meshA[i].b.p);
+ meshBuffer.push_back(meshA[i].c.p);
+#endif
+ }
+ sp = 0;
+ for (uint32_t i = 0; i < meshBCount; ++i)
+ {
+ chunksPoints2[sp++] = meshB[i].a.p;
+ chunksPoints2[sp++] = meshB[i].b.p;
+ chunksPoints2[sp++] = meshB[i].c.p;
+#ifdef DEBUG_OUTPUT
+ meshBuffer.push_back(meshB[i].a.p);
+ meshBuffer.push_back(meshB[i].b.p);
+ meshBuffer.push_back(meshB[i].c.p);
+#endif
+ }
+
+ CollisionHull* cHull[2];
+
+ cHull[0] = mConvexMeshBuilder->buildCollisionGeometry(chunksPoints1.size(), chunksPoints1.data());
+ cHull[1] = mConvexMeshBuilder->buildCollisionGeometry(chunksPoints2.size(), chunksPoints2.data());
+
+ std::vector<PxVec3> hullPoints[2];
+ hullPoints[0].resize(cHull[0]->pointsCount);
+ hullPoints[1].resize(cHull[1]->pointsCount);
- void BlastBondGeneratorImpl::release()
+
+ PxBounds3 bb[2];
+ bb[0].setEmpty();
+ bb[1].setEmpty();
+
+ for (uint32_t cv = 0; cv < 2; ++cv)
+ {
+ for (uint32_t i = 0; i < cHull[cv]->pointsCount; ++i)
{
- delete this;
+ hullPoints[cv][i] = toPxShared(cHull[cv]->points[i]);
+ bb[cv].include(hullPoints[cv][i]);
}
+ }
+ auto ret = createBondForcedInternal(hullPoints[0], hullPoints[1], *cHull[0], *cHull[1], bb[0], bb[1], resultBond,
+ overlapping);
+
+ mConvexMeshBuilder->releaseCollisionHull(cHull[0]);
+ mConvexMeshBuilder->releaseCollisionHull(cHull[1]);
+ return ret;
+}
+
+int32_t BlastBondGeneratorImpl::bondsFromPrefractured(uint32_t meshCount, const uint32_t* geometryCount,
+ const Triangle* geometry, const bool* chunkIsSupport,
+ NvBlastBondDesc*& resultBondDescs, BondGenerationConfig conf)
+{
+ int32_t ret_val = 0;
+ switch (conf.bondMode)
+ {
+ case BondGenerationConfig::AVERAGE:
+ ret_val = createFullBondListAveraged(meshCount, geometryCount, geometry, nullptr, chunkIsSupport, nullptr,
+ resultBondDescs, conf);
+ break;
+ case BondGenerationConfig::EXACT:
+ ret_val = createFullBondListExact(meshCount, geometryCount, geometry, chunkIsSupport, resultBondDescs, conf);
+ break;
}
+ return ret_val;
}
+
+
+int32_t BlastBondGeneratorImpl::bondsFromPrefractured(uint32_t meshCount, const uint32_t* convexHullOffset,
+ const CollisionHull** chunkHulls, const bool* chunkIsSupport,
+ const uint32_t* meshGroups, NvBlastBondDesc*& resultBondDescs,
+ float maxSeparation)
+{
+ BondGenerationConfig conf;
+ conf.maxSeparation = maxSeparation;
+ conf.bondMode = BondGenerationConfig::AVERAGE;
+ return createFullBondListAveraged(meshCount, convexHullOffset, nullptr, chunkHulls, chunkIsSupport, meshGroups,
+ resultBondDescs, conf);
+}
+
+void BlastBondGeneratorImpl::release()
+{
+ delete this;
+}
+
+} // namespace Blast
+} // namespace Nv