From 3dfe2108cfab31ba3ee5527e217d0d8e99a51162 Mon Sep 17 00:00:00 2001 From: git perforce import user Date: Tue, 25 Oct 2016 12:29:14 -0600 Subject: Initial commit: PhysX 3.4.0 Update @ 21294896 APEX 1.4.0 Update @ 21275617 [CL 21300167] --- .../general/RenderDebug/src/Hull2MeshEdges.cpp | 459 +++++++++++++++++++++ 1 file changed, 459 insertions(+) create mode 100644 APEX_1.4/shared/general/RenderDebug/src/Hull2MeshEdges.cpp (limited to 'APEX_1.4/shared/general/RenderDebug/src/Hull2MeshEdges.cpp') diff --git a/APEX_1.4/shared/general/RenderDebug/src/Hull2MeshEdges.cpp b/APEX_1.4/shared/general/RenderDebug/src/Hull2MeshEdges.cpp new file mode 100644 index 00000000..94f60f4e --- /dev/null +++ b/APEX_1.4/shared/general/RenderDebug/src/Hull2MeshEdges.cpp @@ -0,0 +1,459 @@ +#include "Hull2MeshEdges.h" +#include "PsUserAllocated.h" +#include "PxVec4.h" +#include "PxVec3.h" +#include "PxPlane.h" +#include "PxMath.h" +#include "PxTransform.h" +#include "PsArray.h" + + +#define FLT_EPS 0.000000001f + +PX_INLINE bool intersectPlanes(physx::PxVec3& pos, physx::PxVec3& dir, const physx::PxPlane& plane0, const physx::PxPlane& plane1) +{ + const physx::PxVec3 n0 = plane0.n; + const physx::PxVec3 n1 = plane1.n; + + dir = n0.cross(n1); + + if(dir.normalize() < FLT_EPS) + { + return false; + } + + pos = physx::PxVec3(0.0f); + + for (int iter = 3; iter--;) + { + // Project onto plane0: + pos = plane0.project(pos); + + // Raycast to plane1: + const physx::PxVec3 b = dir.cross(n0); + //pos = pos - (pos.dot(plane1.n)/b.dot(plane1.n))*b; + + pos = pos - (plane1.distance(pos) / b.dot(plane1.n))*b; + + } + + return true; +} + +void calculatePolygonEdges(physx::shdfnd::Array& edges,uint32_t planeCount,const physx::PxPlane *planes) +{ + for (uint32_t i = 0; i FLT_EPS) + { + const float s = num/den; + if (den > 0.0f) + { + maxS = physx::PxMin(maxS, s); + } + else + { + minS = physx::PxMax(minS, s); + } + if (maxS <= minS) + { + intersectionFound = false; + break; + } + } + else + if (num < -10*FLT_EPS) + { + intersectionFound = false; + break; + } + } + if (intersectionFound && minS != -FLT_MAX && maxS != FLT_MIN) + { + HullEdge& s = edges.insert(); + s.e0 = orig + minS * edgeDir; + s.e1 = orig + maxS * edgeDir; + } + } + } + } +} + +struct ConvexMeshBuilder +{ + ConvexMeshBuilder(void) : mVertices("ConvexMeshBuilder::mVertice"), mIndices("ConvexMeshBuilder::mIndices") {} + void buildMesh(uint16_t numPlanes,const physx::PxVec4 *planes); + physx::shdfnd::Array mVertices; + physx::shdfnd::Array mIndices; +}; + +static float det(physx::PxVec4 v0, physx::PxVec4 v1, physx::PxVec4 v2, physx::PxVec4 v3) +{ + const physx::PxVec3& d0 = reinterpret_cast(v0); + const physx::PxVec3& d1 = reinterpret_cast(v1); + const physx::PxVec3& d2 = reinterpret_cast(v2); + const physx::PxVec3& d3 = reinterpret_cast(v3); + + return v0.w * d1.cross(d2).dot(d3) + - v1.w * d0.cross(d2).dot(d3) + + v2.w * d0.cross(d1).dot(d3) + - v3.w * d0.cross(d1).dot(d2); +} + +static physx::PxVec3 intersect(physx::PxVec4 p0, physx::PxVec4 p1, physx::PxVec4 p2) +{ + const physx::PxVec3& d0 = reinterpret_cast(p0); + const physx::PxVec3& d1 = reinterpret_cast(p1); + const physx::PxVec3& d2 = reinterpret_cast(p2); + + return (p0.w * d1.cross(d2) + + p1.w * d2.cross(d0) + + p2.w * d0.cross(d1)) + / d0.dot(d2.cross(d1)); +} + +static const uint16_t sInvalid = uint16_t(-1); + +// restriction: only supports a single patch per vertex. +struct HalfedgeMesh +{ + struct Halfedge + { + Halfedge(uint16_t vertex = sInvalid, uint16_t face = sInvalid, + uint16_t next = sInvalid, uint16_t prev = sInvalid) + : mVertex(vertex), mFace(face), mNext(next), mPrev(prev) + {} + + uint16_t mVertex; // to + uint16_t mFace; // left + uint16_t mNext; // ccw + uint16_t mPrev; // cw + }; + + HalfedgeMesh() : mNumTriangles(0), mHalfedges("mHalfedges"),mVertices("mVertices"),mFaces("mFaces"),mPoints("mPoints") {} + + uint16_t findHalfedge(uint16_t v0, uint16_t v1) + { + uint16_t h = mVertices[v0], start = h; + while(h != sInvalid && mHalfedges[h].mVertex != v1) + { + h = mHalfedges[h ^ 1u].mNext; + if(h == start) + return sInvalid; + } + return h; + } + + void connect(uint16_t h0, uint16_t h1) + { + mHalfedges[h0].mNext = h1; + mHalfedges[h1].mPrev = h0; + } + + void addTriangle(uint16_t v0, uint16_t v1, uint16_t v2) + { + // add new vertices + uint16_t n = physx::PxMax(v0, physx::PxMax(v1, v2))+1u; + if(mVertices.size() < n) + mVertices.resize(n, sInvalid); + + // collect halfedges, prev and next of triangle + uint16_t verts[] = { v0, v1, v2 }; + uint16_t handles[3], prev[3], next[3]; + for(uint16_t i=0; i<3; ++i) + { + uint16_t j = (i+1u)%3; + uint16_t h = findHalfedge(verts[i], verts[j]); + if(h == sInvalid) + { + // add new edge + h = uint16_t(mHalfedges.size()); + mHalfedges.pushBack(Halfedge(verts[j])); + mHalfedges.pushBack(Halfedge(verts[i])); + } + handles[i] = h; + prev[i] = mHalfedges[h].mPrev; + next[i] = mHalfedges[h].mNext; + } + + // patch connectivity + for(uint16_t i=0; i<3; ++i) + { + uint16_t j = (i+1u)%3; + + mHalfedges[handles[i]].mFace = uint16_t(mFaces.size()); + + // connect prev and next + connect(handles[i], handles[j]); + + if(next[j] == sInvalid) // new next edge, connect opposite + connect(handles[j]^1u, next[i]!=sInvalid ? next[i] : handles[i]^1u); + + if(prev[i] == sInvalid) // new prev edge, connect opposite + connect(prev[j]!=sInvalid ? prev[j] : handles[j]^1u, handles[i]^1u); + + // prev is boundary, update middle vertex + if(mHalfedges[handles[i]^1u].mFace == sInvalid) + mVertices[verts[j]] = handles[i]^1u; + } + + PX_ASSERT(mNumTriangles < 0xffff); + mFaces.pushBack(handles[2]); + ++mNumTriangles; + } + + uint16_t removeTriangle(uint16_t f) + { + uint16_t result = sInvalid; + + for(uint16_t i=0, h = mFaces[f]; i<3; ++i) + { + uint16_t v0 = mHalfedges[h^1u].mVertex; + uint16_t v1 = mHalfedges[h].mVertex; + + mHalfedges[h].mFace = sInvalid; + + if(mHalfedges[h^1u].mFace == sInvalid) // was boundary edge, remove + { + uint16_t v0Prev = mHalfedges[h ].mPrev; + uint16_t v0Next = mHalfedges[h^1u].mNext; + uint16_t v1Prev = mHalfedges[h^1u].mPrev; + uint16_t v1Next = mHalfedges[h ].mNext; + + // update halfedge connectivity + connect(v0Prev, v0Next); + connect(v1Prev, v1Next); + + // update vertex boundary or delete + mVertices[v0] = (v0Prev^1) == v0Next ? sInvalid : v0Next; + mVertices[v1] = (v1Prev^1) == v1Next ? sInvalid : v1Next; + } + else + { + mVertices[v0] = h; // update vertex boundary + result = v1; + } + + h = mHalfedges[h].mNext; + } + + mFaces[f] = sInvalid; + --mNumTriangles; + + return result; + } + + // true if vertex v is in front of face f + bool visible(uint16_t v, uint16_t f) + { + uint16_t h = mFaces[f]; + if(h == sInvalid) + return false; + + uint16_t v0 = mHalfedges[h].mVertex; + h = mHalfedges[h].mNext; + uint16_t v1 = mHalfedges[h].mVertex; + h = mHalfedges[h].mNext; + uint16_t v2 = mHalfedges[h].mVertex; + h = mHalfedges[h].mNext; + + return det(mPoints[v], mPoints[v0], mPoints[v1], mPoints[v2]) < -1e-5f; + } + + uint16_t mNumTriangles; + physx::shdfnd::Array mHalfedges; + physx::shdfnd::Array mVertices; // vertex -> (boundary) halfedge + physx::shdfnd::Array mFaces; // face -> halfedge + physx::shdfnd::Array mPoints; +}; + +void ConvexMeshBuilder::buildMesh(uint16_t numPlanes,const physx::PxVec4 *planes) +{ + if(numPlanes < 4) + return; // todo: handle degenerate cases + + HalfedgeMesh mesh; + + // gather points (planes, that is) + mesh.mPoints.reserve(numPlanes); + for (uint32_t i=0; i face2Vertex(mesh.mFaces.size(), sInvalid); + for(uint32_t i=0; i(planes)); + + m.mVertexCount = mConvexMeshBuilder.mVertices.size(); + if ( m.mVertexCount ) + { + ret = true; + m.mTriCount = mConvexMeshBuilder.mIndices.size()/3; + m.mVertices = &mConvexMeshBuilder.mVertices[0]; + m.mIndices = &mConvexMeshBuilder.mIndices[0]; + } + return ret; + } + + virtual const HullEdge *getHullEdges(uint32_t planeCount,const physx::PxPlane *planes,uint32_t &edgeCount) + { + const HullEdge *ret = NULL; + + mEdges.clear(); + calculatePolygonEdges(mEdges,planeCount,planes); + if ( !mEdges.empty() ) + { + ret = &mEdges[0]; + edgeCount = mEdges.size(); + } + + return ret; + } + + virtual void release(void) + { + delete this; + } + physx::shdfnd::Array mEdges; + ConvexMeshBuilder mConvexMeshBuilder; +}; + +Hull2MeshEdges *createHull2MeshEdges(void) +{ + Hull2MeshEdgesImpl *ret = PX_NEW(Hull2MeshEdgesImpl); + return static_cast< Hull2MeshEdges *>(ret); +} -- cgit v1.2.3