aboutsummaryrefslogtreecommitdiff
path: root/APEX_1.4/shared/general/HACD/src/dgPolygonSoupBuilder.cpp
diff options
context:
space:
mode:
authorgit perforce import user <a@b>2016-10-25 12:29:14 -0600
committerSheikh Dawood Abdul Ajees <Sheikh Dawood Abdul Ajees>2016-10-25 18:56:37 -0500
commit3dfe2108cfab31ba3ee5527e217d0d8e99a51162 (patch)
treefa6485c169e50d7415a651bf838f5bcd0fd3bfbd /APEX_1.4/shared/general/HACD/src/dgPolygonSoupBuilder.cpp
downloadphysx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.tar.xz
physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.zip
Initial commit:
PhysX 3.4.0 Update @ 21294896 APEX 1.4.0 Update @ 21275617 [CL 21300167]
Diffstat (limited to 'APEX_1.4/shared/general/HACD/src/dgPolygonSoupBuilder.cpp')
-rw-r--r--APEX_1.4/shared/general/HACD/src/dgPolygonSoupBuilder.cpp962
1 files changed, 962 insertions, 0 deletions
diff --git a/APEX_1.4/shared/general/HACD/src/dgPolygonSoupBuilder.cpp b/APEX_1.4/shared/general/HACD/src/dgPolygonSoupBuilder.cpp
new file mode 100644
index 00000000..2fe00fc0
--- /dev/null
+++ b/APEX_1.4/shared/general/HACD/src/dgPolygonSoupBuilder.cpp
@@ -0,0 +1,962 @@
+/* Copyright (c) <2003-2011> <Julio Jerez, Newton Game Dynamics>
+*
+* This software is provided 'as-is', without any express or implied
+* warranty. In no event will the authors be held liable for any damages
+* arising from the use of this software.
+*
+* Permission is granted to anyone to use this software for any purpose,
+* including commercial applications, and to alter it and redistribute it
+* freely, subject to the following restrictions:
+*
+* 1. The origin of this software must not be misrepresented; you must not
+* claim that you wrote the original software. If you use this software
+* in a product, an acknowledgment in the product documentation would be
+* appreciated but is not required.
+*
+* 2. Altered source versions must be plainly marked as such, and must not be
+* misrepresented as being the original software.
+*
+* 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/****************************************************************************
+*
+* Visual C++ 6.0 created by: Julio Jerez
+*
+****************************************************************************/
+#include "dgStack.h"
+#include "dgMatrix.h"
+#include "dgPolyhedra.h"
+#include "dgPolygonSoupBuilder.h"
+
+#define DG_POINTS_RUN (512 * 1024)
+
+class dgPolySoupFilterAllocator: public dgPolyhedra
+{
+ public:
+ dgPolySoupFilterAllocator (void)
+ :dgPolyhedra ()
+ {
+ }
+
+ ~dgPolySoupFilterAllocator ()
+ {
+ }
+
+ int32_t AddFilterFace (uint32_t count, int32_t* const pool)
+ {
+ BeginFace();
+ HACD_ASSERT (count);
+ bool reduction = true;
+ while (reduction && !AddFace (int32_t (count), pool)) {
+ reduction = false;
+ if (count >3) {
+ for (uint32_t i = 0; i < count; i ++) {
+ for (uint32_t j = i + 1; j < count; j ++) {
+ if (pool[j] == pool[i]) {
+ for (i = j; i < count - 1; i ++) {
+ pool[i] = pool[i + 1];
+ }
+ count --;
+ i = count;
+ reduction = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+ EndFace();
+
+ HACD_ASSERT (reduction);
+ return reduction ? int32_t (count) : 0;
+ }
+};
+
+
+dgPolygonSoupDatabaseBuilder::dgPolygonSoupDatabaseBuilder (void)
+ :m_faceVertexCount(), m_vertexIndex(), m_normalIndex(), m_vertexPoints(), m_normalPoints()
+{
+ m_run = DG_POINTS_RUN;
+ m_faceCount = 0;
+ m_indexCount = 0;
+ m_vertexCount = 0;
+ m_normalCount = 0;
+}
+
+
+dgPolygonSoupDatabaseBuilder::~dgPolygonSoupDatabaseBuilder ()
+{
+}
+
+
+void dgPolygonSoupDatabaseBuilder::Begin()
+{
+ m_run = DG_POINTS_RUN;
+ m_faceCount = 0;
+ m_indexCount = 0;
+ m_vertexCount = 0;
+ m_normalCount = 0;
+}
+
+
+void dgPolygonSoupDatabaseBuilder::AddMesh (const float* const vertex, int32_t vertexCount, int32_t strideInBytes, int32_t faceCount,
+ const int32_t* const faceArray, const int32_t* const indexArray, const int32_t* const faceTagsData, const dgMatrix& worldMatrix)
+{
+ int32_t faces[256];
+ int32_t pool[2048];
+
+
+ m_vertexPoints[m_vertexCount + vertexCount].m_x = double (0.0f);
+ dgBigVector* const vertexPool = &m_vertexPoints[m_vertexCount];
+
+ worldMatrix.TransformTriplex (&vertexPool[0].m_x, sizeof (dgBigVector), vertex, strideInBytes, vertexCount);
+ for (int32_t i = 0; i < vertexCount; i ++) {
+ vertexPool[i].m_w = double (0.0f);
+ }
+
+ int32_t totalIndexCount = faceCount;
+ for (int32_t i = 0; i < faceCount; i ++) {
+ totalIndexCount += faceArray[i];
+ }
+
+ m_vertexIndex[m_indexCount + totalIndexCount] = 0;
+ m_faceVertexCount[m_faceCount + faceCount] = 0;
+
+ int32_t k = 0;
+ for (int32_t i = 0; i < faceCount; i ++) {
+ int32_t count = faceArray[i];
+ for (int32_t j = 0; j < count; j ++) {
+ int32_t index = indexArray[k];
+ pool[j] = index + m_vertexCount;
+ k ++;
+ }
+
+ int32_t convexFaces = 0;
+ if (count == 3) {
+ convexFaces = 1;
+ dgBigVector p0 (m_vertexPoints[pool[2]]);
+ for (int32_t i = 0; i < 3; i ++) {
+ dgBigVector p1 (m_vertexPoints[pool[i]]);
+ dgBigVector edge (p1 - p0);
+ double mag2 = edge % edge;
+ if (mag2 < float (1.0e-6f)) {
+ convexFaces = 0;
+ }
+ p0 = p1;
+ }
+
+ if (convexFaces) {
+ dgBigVector edge0 (m_vertexPoints[pool[2]] - m_vertexPoints[pool[0]]);
+ dgBigVector edge1 (m_vertexPoints[pool[1]] - m_vertexPoints[pool[0]]);
+ dgBigVector normal (edge0 * edge1);
+ double mag2 = normal % normal;
+ if (mag2 < float (1.0e-8f)) {
+ convexFaces = 0;
+ }
+ }
+
+ if (convexFaces) {
+ faces[0] = 3;
+ }
+
+ } else {
+ convexFaces = AddConvexFace (count, pool, faces);
+ }
+
+ int32_t index = 0;
+ for (int32_t k = 0; k < convexFaces; k ++) {
+ int32_t count = faces[k];
+ m_vertexIndex[m_indexCount] = faceTagsData[i];
+ m_indexCount ++;
+ for (int32_t j = 0; j < count; j ++) {
+ m_vertexIndex[m_indexCount] = pool[index];
+ index ++;
+ m_indexCount ++;
+ }
+ m_faceVertexCount[m_faceCount] = count + 1;
+ m_faceCount ++;
+ }
+ }
+ m_vertexCount += vertexCount;
+ m_run -= vertexCount;
+ if (m_run <= 0) {
+ PackArray();
+ }
+}
+
+void dgPolygonSoupDatabaseBuilder::PackArray()
+{
+ dgStack<int32_t> indexMapPool (m_vertexCount);
+ int32_t* const indexMap = &indexMapPool[0];
+ m_vertexCount = dgVertexListToIndexList (&m_vertexPoints[0].m_x, sizeof (dgBigVector), 3, m_vertexCount, &indexMap[0], float (1.0e-6f));
+
+ int32_t k = 0;
+ for (int32_t i = 0; i < m_faceCount; i ++) {
+ k ++;
+
+ int32_t count = m_faceVertexCount[i];
+ for (int32_t j = 1; j < count; j ++) {
+ int32_t index = m_vertexIndex[k];
+ index = indexMap[index];
+ m_vertexIndex[k] = index;
+ k ++;
+ }
+ }
+
+ m_run = DG_POINTS_RUN;
+}
+
+void dgPolygonSoupDatabaseBuilder::SingleFaceFixup()
+{
+ if (m_faceCount == 1) {
+ int32_t index = 0;
+ int32_t count = m_faceVertexCount[0];
+ for (int32_t j = 0; j < count; j ++) {
+ m_vertexIndex[m_indexCount] = m_vertexIndex[index];
+ index ++;
+ m_indexCount ++;
+ }
+ m_faceVertexCount[m_faceCount] = count;
+ m_faceCount ++;
+ }
+}
+
+void dgPolygonSoupDatabaseBuilder::EndAndOptimize(bool optimize)
+{
+ if (m_faceCount) {
+ dgStack<int32_t> indexMapPool (m_indexCount + m_vertexCount);
+
+ int32_t* const indexMap = &indexMapPool[0];
+ m_vertexCount = dgVertexListToIndexList (&m_vertexPoints[0].m_x, sizeof (dgBigVector), 3, m_vertexCount, &indexMap[0], float (1.0e-4f));
+
+ int32_t k = 0;
+ for (int32_t i = 0; i < m_faceCount; i ++) {
+ k ++;
+ int32_t count = m_faceVertexCount[i];
+ for (int32_t j = 1; j < count; j ++) {
+ int32_t index = m_vertexIndex[k];
+ index = indexMap[index];
+ m_vertexIndex[k] = index;
+ k ++;
+ }
+ }
+
+ OptimizeByIndividualFaces();
+ if (optimize) {
+ OptimizeByGroupID();
+ OptimizeByIndividualFaces();
+ }
+ }
+}
+
+
+void dgPolygonSoupDatabaseBuilder::OptimizeByGroupID()
+{
+ dgTree<int, int> attribFilter;
+ dgPolygonSoupDatabaseBuilder builder;
+ dgPolygonSoupDatabaseBuilder builderAux;
+ dgPolygonSoupDatabaseBuilder builderLeftOver;
+
+ builder.Begin();
+ int32_t polygonIndex = 0;
+ for (int32_t i = 0; i < m_faceCount; i ++) {
+ int32_t attribute = m_vertexIndex[polygonIndex];
+ if (!attribFilter.Find(attribute)) {
+ attribFilter.Insert (attribute, attribute);
+ builder.OptimizeByGroupID (*this, i, polygonIndex, builderLeftOver);
+ for (int32_t j = 0; builderLeftOver.m_faceCount && (j < 64); j ++) {
+ builderAux.m_faceVertexCount[builderLeftOver.m_faceCount] = 0;
+ builderAux.m_vertexIndex[builderLeftOver.m_indexCount] = 0;
+ builderAux.m_vertexPoints[builderLeftOver.m_vertexCount].m_x = float (0.0f);
+
+ memcpy (&builderAux.m_faceVertexCount[0], &builderLeftOver.m_faceVertexCount[0], sizeof (int32_t) * builderLeftOver.m_faceCount);
+ memcpy (&builderAux.m_vertexIndex[0], &builderLeftOver.m_vertexIndex[0], sizeof (int32_t) * builderLeftOver.m_indexCount);
+ memcpy (&builderAux.m_vertexPoints[0], &builderLeftOver.m_vertexPoints[0], sizeof (dgBigVector) * builderLeftOver.m_vertexCount);
+
+ builderAux.m_faceCount = builderLeftOver.m_faceCount;
+ builderAux.m_indexCount = builderLeftOver.m_indexCount;
+ builderAux.m_vertexCount = builderLeftOver.m_vertexCount;
+
+ int32_t prevFaceCount = builderLeftOver.m_faceCount;
+ builderLeftOver.m_faceCount = 0;
+ builderLeftOver.m_indexCount = 0;
+ builderLeftOver.m_vertexCount = 0;
+
+ builder.OptimizeByGroupID (builderAux, 0, 0, builderLeftOver);
+ if (prevFaceCount == builderLeftOver.m_faceCount) {
+ break;
+ }
+ }
+ HACD_ASSERT (builderLeftOver.m_faceCount == 0);
+ }
+ polygonIndex += m_faceVertexCount[i];
+ }
+// builder.End();
+ builder.Optimize(false);
+
+ m_faceVertexCount[builder.m_faceCount] = 0;
+ m_vertexIndex[builder.m_indexCount] = 0;
+ m_vertexPoints[builder.m_vertexCount].m_x = float (0.0f);
+
+ memcpy (&m_faceVertexCount[0], &builder.m_faceVertexCount[0], sizeof (int32_t) * builder.m_faceCount);
+ memcpy (&m_vertexIndex[0], &builder.m_vertexIndex[0], sizeof (int32_t) * builder.m_indexCount);
+ memcpy (&m_vertexPoints[0], &builder.m_vertexPoints[0], sizeof (dgBigVector) * builder.m_vertexCount);
+
+ m_faceCount = builder.m_faceCount;
+ m_indexCount = builder.m_indexCount;
+ m_vertexCount = builder.m_vertexCount;
+ m_normalCount = builder.m_normalCount;
+}
+
+
+void dgPolygonSoupDatabaseBuilder::OptimizeByGroupID (dgPolygonSoupDatabaseBuilder& source, int32_t faceNumber, int32_t faceIndexNumber, dgPolygonSoupDatabaseBuilder& leftOver)
+{
+ int32_t indexPool[1024 * 1];
+ int32_t atributeData[1024 * 1];
+ dgVector vertexPool[1024 * 1];
+ dgPolyhedra polyhedra;
+
+ int32_t attribute = source.m_vertexIndex[faceIndexNumber];
+ for (int32_t i = 0; i < int32_t (sizeof(atributeData) / sizeof (int32_t)); i ++) {
+ indexPool[i] = i;
+ atributeData[i] = attribute;
+ }
+
+ leftOver.Begin();
+ polyhedra.BeginFace ();
+ for (int32_t i = faceNumber; i < source.m_faceCount; i ++) {
+ int32_t indexCount;
+ indexCount = source.m_faceVertexCount[i];
+ HACD_ASSERT (indexCount < 1024);
+
+ if (source.m_vertexIndex[faceIndexNumber] == attribute) {
+ dgEdge* const face = polyhedra.AddFace(indexCount - 1, &source.m_vertexIndex[faceIndexNumber + 1]);
+ if (!face) {
+ int32_t faceArray;
+ for (int32_t j = 0; j < indexCount - 1; j ++) {
+ int32_t index;
+ index = source.m_vertexIndex[faceIndexNumber + j + 1];
+ vertexPool[j] = source.m_vertexPoints[index];
+ }
+ faceArray = indexCount - 1;
+ leftOver.AddMesh (&vertexPool[0].m_x, indexCount - 1, sizeof (dgVector), 1, &faceArray, indexPool, atributeData, dgGetIdentityMatrix());
+ } else {
+ // set the attribute
+ dgEdge* ptr = face;
+ do {
+ ptr->m_userData = uint64_t (attribute);
+ ptr = ptr->m_next;
+ } while (ptr != face);
+ }
+ }
+ faceIndexNumber += indexCount;
+ }
+
+ leftOver.Optimize(false);
+ polyhedra.EndFace();
+
+
+ dgPolyhedra facesLeft;
+ facesLeft.BeginFace();
+ polyhedra.ConvexPartition (&source.m_vertexPoints[0].m_x, sizeof (dgBigVector), &facesLeft);
+ facesLeft.EndFace();
+
+
+ int32_t mark = polyhedra.IncLRU();
+ dgPolyhedra::Iterator iter (polyhedra);
+ for (iter.Begin(); iter; iter ++) {
+ dgEdge* const edge = &(*iter);
+ if (edge->m_incidentFace < 0) {
+ continue;
+ }
+ if (edge->m_mark == mark) {
+ continue;
+ }
+
+ dgEdge* ptr = edge;
+ int32_t indexCount = 0;
+ do {
+ ptr->m_mark = mark;
+ vertexPool[indexCount] = source.m_vertexPoints[ptr->m_incidentVertex];
+ indexCount ++;
+ ptr = ptr->m_next;
+ } while (ptr != edge);
+
+ if (indexCount >= 3) {
+ AddMesh (&vertexPool[0].m_x, indexCount, sizeof (dgVector), 1, &indexCount, indexPool, atributeData, dgGetIdentityMatrix());
+ }
+ }
+
+
+ mark = facesLeft.IncLRU();
+ dgPolyhedra::Iterator iter1 (facesLeft);
+ for (iter1.Begin(); iter1; iter1 ++) {
+ dgEdge* const edge = &(*iter1);
+ if (edge->m_incidentFace < 0) {
+ continue;
+ }
+ if (edge->m_mark == mark) {
+ continue;
+ }
+
+ dgEdge* ptr = edge;
+ int32_t indexCount = 0;
+ do {
+ ptr->m_mark = mark;
+ vertexPool[indexCount] = source.m_vertexPoints[ptr->m_incidentVertex];
+ indexCount ++;
+ ptr = ptr->m_next;
+ } while (ptr != edge);
+ if (indexCount >= 3) {
+ AddMesh (&vertexPool[0].m_x, indexCount, sizeof (dgVector), 1, &indexCount, indexPool, atributeData, dgGetIdentityMatrix());
+ }
+ }
+}
+
+
+
+
+void dgPolygonSoupDatabaseBuilder::OptimizeByIndividualFaces()
+{
+ int32_t* const faceArray = &m_faceVertexCount[0];
+ int32_t* const indexArray = &m_vertexIndex[0];
+
+ int32_t* const oldFaceArray = &m_faceVertexCount[0];
+ int32_t* const oldIndexArray = &m_vertexIndex[0];
+
+ int32_t polygonIndex = 0;
+ int32_t newFaceCount = 0;
+ int32_t newIndexCount = 0;
+ for (int32_t i = 0; i < m_faceCount; i ++) {
+ int32_t oldCount = oldFaceArray[i];
+ int32_t count = FilterFace (oldCount - 1, &oldIndexArray[polygonIndex + 1]);
+ if (count) {
+ faceArray[newFaceCount] = count + 1;
+ for (int32_t j = 0; j < count + 1; j ++) {
+ indexArray[newIndexCount + j] = oldIndexArray[polygonIndex + j];
+ }
+ newFaceCount ++;
+ newIndexCount += (count + 1);
+ }
+ polygonIndex += oldCount;
+ }
+ HACD_ASSERT (polygonIndex == m_indexCount);
+ m_faceCount = newFaceCount;
+ m_indexCount = newIndexCount;
+}
+
+
+
+
+void dgPolygonSoupDatabaseBuilder::End(bool optimize)
+{
+ Optimize(optimize);
+
+ // build the normal array and adjacency array
+ // calculate all face the normals
+ int32_t indexCount = 0;
+ m_normalPoints[m_faceCount].m_x = double (0.0f);
+ for (int32_t i = 0; i < m_faceCount; i ++) {
+ int32_t faceIndexCount = m_faceVertexCount[i];
+
+ int32_t* const ptr = &m_vertexIndex[indexCount + 1];
+ dgBigVector v0 (&m_vertexPoints[ptr[0]].m_x);
+ dgBigVector v1 (&m_vertexPoints[ptr[1]].m_x);
+ dgBigVector e0 (v1 - v0);
+ dgBigVector normal (float (0.0f), float (0.0f), float (0.0f), float (0.0f));
+ for (int32_t j = 2; j < faceIndexCount - 1; j ++) {
+ dgBigVector v2 (&m_vertexPoints[ptr[j]].m_x);
+ dgBigVector e1 (v2 - v0);
+ normal += e0 * e1;
+ e0 = e1;
+ }
+ normal = normal.Scale (dgRsqrt (normal % normal));
+
+ m_normalPoints[i].m_x = normal.m_x;
+ m_normalPoints[i].m_y = normal.m_y;
+ m_normalPoints[i].m_z = normal.m_z;
+ indexCount += faceIndexCount;
+ }
+ // compress normals array
+ m_normalIndex[m_faceCount] = 0;
+ m_normalCount = dgVertexListToIndexList(&m_normalPoints[0].m_x, sizeof (dgBigVector), 3, m_faceCount, &m_normalIndex[0], float (1.0e-4f));
+}
+
+void dgPolygonSoupDatabaseBuilder::Optimize(bool optimize)
+{
+ #define DG_PATITION_SIZE (1024 * 4)
+ if (optimize && (m_faceCount > DG_PATITION_SIZE)) {
+
+ dgBigVector median (float (0.0f), float (0.0f), float (0.0f), float (0.0f));
+ dgBigVector varian (float (0.0f), float (0.0f), float (0.0f), float (0.0f));
+
+ dgStack<dgVector> pool (1024 * 2);
+ dgStack<int32_t> indexArray (1024 * 2);
+ int32_t polygonIndex = 0;
+ for (int32_t i = 0; i < m_faceCount; i ++) {
+
+ dgBigVector p0 (float ( 1.0e10f), float ( 1.0e10f), float ( 1.0e10f), float (0.0f));
+ dgBigVector p1 (float (-1.0e10f), float (-1.0e10f), float (-1.0e10f), float (0.0f));
+ int32_t count = m_faceVertexCount[i];
+
+ for (int32_t j = 1; j < count; j ++) {
+ int32_t k = m_vertexIndex[polygonIndex + j];
+ p0.m_x = GetMin (p0.m_x, double (m_vertexPoints[k].m_x));
+ p0.m_y = GetMin (p0.m_y, double (m_vertexPoints[k].m_y));
+ p0.m_z = GetMin (p0.m_z, double (m_vertexPoints[k].m_z));
+ p1.m_x = GetMax (p1.m_x, double (m_vertexPoints[k].m_x));
+ p1.m_y = GetMax (p1.m_y, double (m_vertexPoints[k].m_y));
+ p1.m_z = GetMax (p1.m_z, double (m_vertexPoints[k].m_z));
+ }
+
+ dgBigVector p ((p0 + p1).Scale (0.5f));
+ median += p;
+ varian += p.CompProduct (p);
+ polygonIndex += count;
+ }
+
+ varian = varian.Scale (float (m_faceCount)) - median.CompProduct(median);
+
+ int32_t axis = 0;
+ float maxVarian = float (-1.0e10f);
+ for (int32_t i = 0; i < 3; i ++) {
+ if (varian[i] > maxVarian) {
+ axis = i;
+ maxVarian = float (varian[i]);
+ }
+ }
+ dgBigVector center = median.Scale (float (1.0f) / float (m_faceCount));
+ double axisVal = center[axis];
+
+ dgPolygonSoupDatabaseBuilder left;
+ dgPolygonSoupDatabaseBuilder right;
+
+ left.Begin();
+ right.Begin();
+ polygonIndex = 0;
+ for (int32_t i = 0; i < m_faceCount; i ++) {
+ int32_t side = 0;
+ int32_t count = m_faceVertexCount[i];
+ for (int32_t j = 1; j < count; j ++) {
+ int32_t k;
+ k = m_vertexIndex[polygonIndex + j];
+ dgVector p (&m_vertexPoints[k].m_x);
+ if (p[axis] > axisVal) {
+ side = 1;
+ break;
+ }
+ }
+
+ int32_t faceArray = count - 1;
+ int32_t faceTagsData = m_vertexIndex[polygonIndex];
+ for (int32_t j = 1; j < count; j ++) {
+ int32_t k = m_vertexIndex[polygonIndex + j];
+ pool[j - 1] = m_vertexPoints[k];
+ indexArray[j - 1] = j - 1;
+ }
+
+ if (!side) {
+ left.AddMesh (&pool[0].m_x, count - 1, sizeof (dgVector), 1, &faceArray, &indexArray[0], &faceTagsData, dgGetIdentityMatrix());
+ } else {
+ right.AddMesh (&pool[0].m_x, count - 1, sizeof (dgVector), 1, &faceArray, &indexArray[0], &faceTagsData, dgGetIdentityMatrix());
+ }
+ polygonIndex += count;
+ }
+
+ left.Optimize(optimize);
+ right.Optimize(optimize);
+
+ m_faceCount = 0;
+ m_indexCount = 0;
+ m_vertexCount = 0;
+ m_normalCount = 0;
+ polygonIndex = 0;
+ for (int32_t i = 0; i < left.m_faceCount; i ++) {
+ int32_t count = left.m_faceVertexCount[i];
+ int32_t faceArray = count - 1;
+ int32_t faceTagsData = left.m_vertexIndex[polygonIndex];
+ for (int32_t j = 1; j < count; j ++) {
+ int32_t k = left.m_vertexIndex[polygonIndex + j];
+ pool[j - 1] = left.m_vertexPoints[k];
+ indexArray[j - 1] = j - 1;
+ }
+ AddMesh (&pool[0].m_x, count - 1, sizeof (dgVector), 1, &faceArray, &indexArray[0], &faceTagsData, dgGetIdentityMatrix());
+ polygonIndex += count;
+ }
+
+ polygonIndex = 0;
+ for (int32_t i = 0; i < right.m_faceCount; i ++) {
+ int32_t count = right.m_faceVertexCount[i];
+ int32_t faceArray = count - 1;
+ int32_t faceTagsData = right.m_vertexIndex[polygonIndex];
+ for (int32_t j = 1; j < count; j ++) {
+ int32_t k = right.m_vertexIndex[polygonIndex + j];
+ pool[j - 1] = right.m_vertexPoints[k];
+ indexArray[j - 1] = j - 1;
+ }
+ AddMesh (&pool[0].m_x, count - 1, sizeof (dgVector), 1, &faceArray, &indexArray[0], &faceTagsData, dgGetIdentityMatrix());
+ polygonIndex += count;
+ }
+
+ if (m_faceCount < DG_PATITION_SIZE) {
+ EndAndOptimize(optimize);
+ } else {
+ EndAndOptimize(false);
+ }
+
+ } else {
+ EndAndOptimize(optimize);
+ }
+}
+
+
+
+int32_t dgPolygonSoupDatabaseBuilder::FilterFace (int32_t count, int32_t* const pool)
+{
+ if (count == 3) {
+ dgBigVector p0 (m_vertexPoints[pool[2]]);
+ for (int32_t i = 0; i < 3; i ++) {
+ dgBigVector p1 (m_vertexPoints[pool[i]]);
+ dgBigVector edge (p1 - p0);
+ double mag2 = edge % edge;
+ if (mag2 < float (1.0e-6f)) {
+ count = 0;
+ }
+ p0 = p1;
+ }
+
+ if (count == 3) {
+ dgBigVector edge0 (m_vertexPoints[pool[2]] - m_vertexPoints[pool[0]]);
+ dgBigVector edge1 (m_vertexPoints[pool[1]] - m_vertexPoints[pool[0]]);
+ dgBigVector normal (edge0 * edge1);
+ double mag2 = normal % normal;
+ if (mag2 < float (1.0e-8f)) {
+ count = 0;
+ }
+ }
+ } else {
+ dgPolySoupFilterAllocator polyhedra;
+
+ count = polyhedra.AddFilterFace (uint32_t (count), pool);
+
+ if (!count) {
+ return 0;
+ }
+
+ dgEdge* edge = &polyhedra.GetRoot()->GetInfo();
+ if (edge->m_incidentFace < 0) {
+ edge = edge->m_twin;
+ }
+
+ bool flag = true;
+ while (flag) {
+ flag = false;
+ if (count >= 3) {
+ dgEdge* ptr = edge;
+
+ dgBigVector p0 (&m_vertexPoints[ptr->m_incidentVertex].m_x);
+ do {
+ dgBigVector p1 (&m_vertexPoints[ptr->m_next->m_incidentVertex].m_x);
+ dgBigVector e0 (p1 - p0);
+ double mag2 = e0 % e0;
+ if (mag2 < float (1.0e-6f)) {
+ count --;
+ flag = true;
+ edge = ptr->m_next;
+ ptr->m_prev->m_next = ptr->m_next;
+ ptr->m_next->m_prev = ptr->m_prev;
+ ptr->m_twin->m_next->m_prev = ptr->m_twin->m_prev;
+ ptr->m_twin->m_prev->m_next = ptr->m_twin->m_next;
+ break;
+ }
+ p0 = p1;
+ ptr = ptr->m_next;
+ } while (ptr != edge);
+ }
+ }
+ if (count >= 3) {
+ flag = true;
+ dgBigVector normal (polyhedra.FaceNormal (edge, &m_vertexPoints[0].m_x, sizeof (dgBigVector)));
+
+ HACD_ASSERT ((normal % normal) > float (1.0e-10f));
+ normal = normal.Scale (dgRsqrt (normal % normal + float (1.0e-20f)));
+
+ while (flag) {
+ flag = false;
+ if (count >= 3) {
+ dgEdge* ptr = edge;
+
+ dgBigVector p0 (&m_vertexPoints[ptr->m_prev->m_incidentVertex].m_x);
+ dgBigVector p1 (&m_vertexPoints[ptr->m_incidentVertex].m_x);
+ dgBigVector e0 (p1 - p0);
+ e0 = e0.Scale (dgRsqrt (e0 % e0 + float(1.0e-10f)));
+ do {
+ dgBigVector p2 (&m_vertexPoints[ptr->m_next->m_incidentVertex].m_x);
+ dgBigVector e1 (p2 - p1);
+
+ e1 = e1.Scale (dgRsqrt (e1 % e1 + float(1.0e-10f)));
+ double mag2 = e1 % e0;
+ if (mag2 > float (0.9999f)) {
+ count --;
+ flag = true;
+ edge = ptr->m_next;
+ ptr->m_prev->m_next = ptr->m_next;
+ ptr->m_next->m_prev = ptr->m_prev;
+ ptr->m_twin->m_next->m_prev = ptr->m_twin->m_prev;
+ ptr->m_twin->m_prev->m_next = ptr->m_twin->m_next;
+ break;
+ }
+
+ dgBigVector n (e0 * e1);
+ mag2 = n % normal;
+ if (mag2 < float (1.0e-5f)) {
+ count --;
+ flag = true;
+ edge = ptr->m_next;
+ ptr->m_prev->m_next = ptr->m_next;
+ ptr->m_next->m_prev = ptr->m_prev;
+ ptr->m_twin->m_next->m_prev = ptr->m_twin->m_prev;
+ ptr->m_twin->m_prev->m_next = ptr->m_twin->m_next;
+ break;
+ }
+
+ e0 = e1;
+ p1 = p2;
+ ptr = ptr->m_next;
+ } while (ptr != edge);
+ }
+ }
+ }
+
+ dgEdge* first = edge;
+ if (count >= 3) {
+ double best = float (2.0f);
+ dgEdge* ptr = edge;
+
+ dgBigVector p0 (&m_vertexPoints[ptr->m_incidentVertex].m_x);
+ dgBigVector p1 (&m_vertexPoints[ptr->m_next->m_incidentVertex].m_x);
+ dgBigVector e0 (p1 - p0);
+ e0 = e0.Scale (dgRsqrt (e0 % e0 + float(1.0e-10f)));
+ do {
+ dgBigVector p2 (&m_vertexPoints[ptr->m_next->m_next->m_incidentVertex].m_x);
+ dgBigVector e1 (p2 - p1);
+
+ e1 = e1.Scale (dgRsqrt (e1 % e1 + float(1.0e-10f)));
+ double mag2 = fabs (e1 % e0);
+ if (mag2 < best) {
+ best = mag2;
+ first = ptr;
+ }
+
+ e0 = e1;
+ p1 = p2;
+ ptr = ptr->m_next;
+ } while (ptr != edge);
+
+ count = 0;
+ ptr = first;
+ do {
+ pool[count] = ptr->m_incidentVertex;
+ count ++;
+ ptr = ptr->m_next;
+ } while (ptr != first);
+ }
+
+#ifdef _DEBUG
+ if (count >= 3) {
+ int32_t j0 = count - 2;
+ int32_t j1 = count - 1;
+ dgBigVector normal (polyhedra.FaceNormal (edge, &m_vertexPoints[0].m_x, sizeof (dgBigVector)));
+ for (int32_t j2 = 0; j2 < count; j2 ++) {
+ dgBigVector p0 (&m_vertexPoints[pool[j0]].m_x);
+ dgBigVector p1 (&m_vertexPoints[pool[j1]].m_x);
+ dgBigVector p2 (&m_vertexPoints[pool[j2]].m_x);
+ dgBigVector e0 ((p0 - p1));
+ dgBigVector e1 ((p2 - p1));
+
+ dgBigVector n (e1 * e0);
+ HACD_ASSERT ((n % normal) > float (0.0f));
+ j0 = j1;
+ j1 = j2;
+ }
+ }
+#endif
+ }
+
+ return (count >= 3) ? count : 0;
+}
+
+
+int32_t dgPolygonSoupDatabaseBuilder::AddConvexFace (int32_t count, int32_t* const pool, int32_t* const facesArray)
+{
+ dgPolySoupFilterAllocator polyhedra;
+
+ count = polyhedra.AddFilterFace(uint32_t (count), pool);
+
+ dgEdge* edge = &polyhedra.GetRoot()->GetInfo();
+ if (edge->m_incidentFace < 0) {
+ edge = edge->m_twin;
+ }
+
+
+ int32_t isconvex = 1;
+ int32_t facesCount = 0;
+
+ int32_t flag = 1;
+ while (flag) {
+ flag = 0;
+ if (count >= 3) {
+ dgEdge* ptr = edge;
+
+ dgBigVector p0 (&m_vertexPoints[ptr->m_incidentVertex].m_x);
+ do {
+ dgBigVector p1 (&m_vertexPoints[ptr->m_next->m_incidentVertex].m_x);
+ dgBigVector e0 (p1 - p0);
+ double mag2 = e0 % e0;
+ if (mag2 < float (1.0e-6f)) {
+ count --;
+ flag = 1;
+ edge = ptr->m_next;
+ ptr->m_prev->m_next = ptr->m_next;
+ ptr->m_next->m_prev = ptr->m_prev;
+ ptr->m_twin->m_next->m_prev = ptr->m_twin->m_prev;
+ ptr->m_twin->m_prev->m_next = ptr->m_twin->m_next;
+ break;
+ }
+ p0 = p1;
+ ptr = ptr->m_next;
+ } while (ptr != edge);
+ }
+ }
+ if (count >= 3) {
+ flag = 1;
+
+ while (flag) {
+ flag = 0;
+ if (count >= 3) {
+ dgEdge* ptr = edge;
+
+ dgBigVector p0 (&m_vertexPoints[ptr->m_prev->m_incidentVertex].m_x);
+ dgBigVector p1 (&m_vertexPoints[ptr->m_incidentVertex].m_x);
+ dgBigVector e0 (p1 - p0);
+ e0 = e0.Scale (dgRsqrt (e0 % e0 + float(1.0e-10f)));
+ do {
+ dgBigVector p2 (&m_vertexPoints[ptr->m_next->m_incidentVertex].m_x);
+ dgBigVector e1 (p2 - p1);
+
+ e1 = e1.Scale (dgRsqrt (e1 % e1 + float(1.0e-10f)));
+ double mag2 = e1 % e0;
+ if (mag2 > float (0.9999f)) {
+ count --;
+ flag = 1;
+ edge = ptr->m_next;
+ ptr->m_prev->m_next = ptr->m_next;
+ ptr->m_next->m_prev = ptr->m_prev;
+ ptr->m_twin->m_next->m_prev = ptr->m_twin->m_prev;
+ ptr->m_twin->m_prev->m_next = ptr->m_twin->m_next;
+ break;
+ }
+
+ e0 = e1;
+ p1 = p2;
+ ptr = ptr->m_next;
+ } while (ptr != edge);
+ }
+ }
+
+ dgBigVector normal (polyhedra.FaceNormal (edge, &m_vertexPoints[0].m_x, sizeof (dgBigVector)));
+ double mag2 = normal % normal;
+ if (mag2 < float (1.0e-8f)) {
+ return 0;
+ }
+ normal = normal.Scale (dgRsqrt (mag2));
+
+
+ if (count >= 3) {
+ dgEdge* ptr = edge;
+ dgBigVector p0 (&m_vertexPoints[ptr->m_prev->m_incidentVertex].m_x);
+ dgBigVector p1 (&m_vertexPoints[ptr->m_incidentVertex].m_x);
+ dgBigVector e0 (p1 - p0);
+ e0 = e0.Scale (dgRsqrt (e0 % e0 + float(1.0e-10f)));
+ do {
+ dgBigVector p2 (&m_vertexPoints[ptr->m_next->m_incidentVertex].m_x);
+ dgBigVector e1 (p2 - p1);
+
+ e1 = e1.Scale (dgRsqrt (e1 % e1 + float(1.0e-10f)));
+
+ dgBigVector n (e0 * e1);
+ double mag2 = n % normal;
+ if (mag2 < float (1.0e-5f)) {
+ isconvex = 0;
+ break;
+ }
+
+ e0 = e1;
+ p1 = p2;
+ ptr = ptr->m_next;
+ } while (ptr != edge);
+ }
+ }
+
+ if (isconvex) {
+ dgEdge* const first = edge;
+ if (count >= 3) {
+ count = 0;
+ dgEdge* ptr = first;
+ do {
+ pool[count] = ptr->m_incidentVertex;
+ count ++;
+ ptr = ptr->m_next;
+ } while (ptr != first);
+ facesArray[facesCount] = count;
+ facesCount = 1;
+ }
+ } else {
+ dgPolyhedra leftOver;
+ dgPolyhedra polyhedra2;
+ dgEdge* ptr = edge;
+ count = 0;
+ do {
+ pool[count] = ptr->m_incidentVertex;
+ count ++;
+ ptr = ptr->m_next;
+ } while (ptr != edge);
+
+
+ polyhedra2.BeginFace();
+ polyhedra2.AddFace (count, pool);
+ polyhedra2.EndFace();
+ leftOver.BeginFace();
+ polyhedra2.ConvexPartition (&m_vertexPoints[0].m_x, sizeof (dgTriplex), &leftOver);
+ leftOver.EndFace();
+
+ int32_t mark = polyhedra2.IncLRU();
+ int32_t index = 0;
+ dgPolyhedra::Iterator iter (polyhedra2);
+ for (iter.Begin(); iter; iter ++) {
+ dgEdge* const edge = &(*iter);
+ if (edge->m_incidentFace < 0) {
+ continue;
+ }
+ if (edge->m_mark == mark) {
+ continue;
+ }
+
+ ptr = edge;
+ count = 0;
+ do {
+ ptr->m_mark = mark;
+ pool[index] = ptr->m_incidentVertex;
+ index ++;
+ count ++;
+ ptr = ptr->m_next;
+ } while (ptr != edge);
+
+ facesArray[facesCount] = count;
+ facesCount ++;
+ }
+ }
+
+ return facesCount;
+}