aboutsummaryrefslogtreecommitdiff
path: root/APEX_1.4/shared/general/HACD/src/dgAABBPolygonSoup.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/dgAABBPolygonSoup.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/dgAABBPolygonSoup.cpp')
-rw-r--r--APEX_1.4/shared/general/HACD/src/dgAABBPolygonSoup.cpp1266
1 files changed, 1266 insertions, 0 deletions
diff --git a/APEX_1.4/shared/general/HACD/src/dgAABBPolygonSoup.cpp b/APEX_1.4/shared/general/HACD/src/dgAABBPolygonSoup.cpp
new file mode 100644
index 00000000..d7c7278b
--- /dev/null
+++ b/APEX_1.4/shared/general/HACD/src/dgAABBPolygonSoup.cpp
@@ -0,0 +1,1266 @@
+/* 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.
+*/
+
+/****************************************************************************
+*
+* File Name : Bitmap.C
+* Visual C++ 4.0 base by Julio Jerez
+*
+****************************************************************************/
+#include "dgHeap.h"
+#include "dgStack.h"
+#include "dgList.h"
+#include "dgMatrix.h"
+#include "dgPolygonSoupBuilder.h"
+#include "dgAABBPolygonSoup.h"
+#include "dgIntersections.h"
+
+#define DG_STACK_DEPTH 63
+
+class dgAABBTree
+{
+ class TreeNode
+ {
+ #define DG_INDEX_COUNT_BITS 6
+
+ public:
+ inline TreeNode ()
+ {
+ HACD_ALWAYS_ASSERT();
+ }
+
+ inline TreeNode (uint32_t node)
+ {
+ m_node = node;
+ HACD_ASSERT (!IsLeaf());
+ }
+
+ inline uint32_t IsLeaf () const
+ {
+ return m_node & 0x80000000;
+ }
+
+ inline uint32_t GetCount() const
+ {
+ HACD_ASSERT (IsLeaf());
+ return (m_node & (~0x80000000)) >> (32 - DG_INDEX_COUNT_BITS - 1);
+ }
+
+ inline uint32_t GetIndex() const
+ {
+ HACD_ASSERT (IsLeaf());
+ return m_node & (~(-(1 << (32 - DG_INDEX_COUNT_BITS - 1))));
+ }
+
+
+ inline TreeNode (uint32_t faceIndexCount, uint32_t faceIndexStart)
+ {
+ HACD_ASSERT (faceIndexCount < (1<<DG_INDEX_COUNT_BITS));
+ m_node = 0x80000000 | (faceIndexCount << (32 - DG_INDEX_COUNT_BITS - 1)) | faceIndexStart;
+ }
+
+ inline dgAABBTree* GetNode (const void* root) const
+ {
+ return ((dgAABBTree*) root) + m_node;
+ }
+
+ union {
+ uint32_t m_node;
+ };
+ };
+
+ class dgHeapNodePair
+ {
+ public:
+ int32_t m_nodeA;
+ int32_t m_nodeB;
+ };
+
+ class dgConstructionTree : public UANS::UserAllocated
+ {
+ public:
+ dgConstructionTree ()
+ {
+ }
+
+ ~dgConstructionTree ()
+ {
+ if (m_back) {
+ delete m_back;
+ }
+ if (m_front) {
+ delete m_front;
+ }
+ }
+
+ dgVector m_p0;
+ dgVector m_p1;
+ int32_t m_boxIndex;
+ float m_surfaceArea;
+ dgConstructionTree* m_back;
+ dgConstructionTree* m_front;
+ dgConstructionTree* m_parent;
+ };
+
+
+
+ public:
+ void CalcExtends (dgTriplex* const vertex, int32_t indexCount, const int32_t* const indexArray)
+ {
+ dgVector minP ( float (1.0e15f), float (1.0e15f), float (1.0e15f), float (0.0f));
+ dgVector maxP (-float (1.0e15f), -float (1.0e15f), -float (1.0e15f), float (0.0f));
+ for (int32_t i = 1; i < indexCount; i ++) {
+ int32_t index = indexArray[i];
+ dgVector p (&vertex[index].m_x);
+
+ minP.m_x = GetMin (p.m_x, minP.m_x);
+ minP.m_y = GetMin (p.m_y, minP.m_y);
+ minP.m_z = GetMin (p.m_z, minP.m_z);
+
+ maxP.m_x = GetMax (p.m_x, maxP.m_x);
+ maxP.m_y = GetMax (p.m_y, maxP.m_y);
+ maxP.m_z = GetMax (p.m_z, maxP.m_z);
+ }
+
+ vertex[m_minIndex].m_x = minP.m_x - float (1.0e-3f);
+ vertex[m_minIndex].m_y = minP.m_y - float (1.0e-3f);
+ vertex[m_minIndex].m_z = minP.m_z - float (1.0e-3f);
+ vertex[m_maxIndex].m_x = maxP.m_x + float (1.0e-3f);
+ vertex[m_maxIndex].m_y = maxP.m_y + float (1.0e-3f);
+ vertex[m_maxIndex].m_z = maxP.m_z + float (1.0e-3f);
+ }
+
+ int32_t BuildTree (dgConstructionTree* const root, dgAABBTree* const boxArray, dgAABBTree* const boxCopy, dgTriplex* const vertexArrayOut, int32_t &treeVCount)
+ {
+ TreeNode* parent[128];
+ dgConstructionTree* pool[128];
+
+ int32_t index = 0;
+ int32_t stack = 1;
+ parent[0] = NULL;
+ pool[0] = root;
+ while (stack) {
+ stack --;
+
+ dgConstructionTree* const node = pool[stack];
+ TreeNode* const parentNode = parent[stack];
+ if (node->m_boxIndex != -1) {
+ if (parentNode) {
+ *parentNode = boxCopy[node->m_boxIndex].m_back;
+ } else {
+
+ //HACD_ASSERT (boxCount == 1);
+ dgAABBTree* const newNode = &boxArray[index];
+ *newNode = boxCopy[node->m_boxIndex];
+ index ++;
+ }
+
+ } else {
+ dgAABBTree* const newNode = &boxArray[index];
+
+ newNode->m_minIndex = treeVCount;
+ vertexArrayOut[treeVCount].m_x = node->m_p0.m_x;
+ vertexArrayOut[treeVCount].m_y = node->m_p0.m_y;
+ vertexArrayOut[treeVCount].m_z = node->m_p0.m_z;
+
+ newNode->m_maxIndex = treeVCount + 1;
+ vertexArrayOut[treeVCount + 1].m_x = node->m_p1.m_x;
+ vertexArrayOut[treeVCount + 1].m_y = node->m_p1.m_y;
+ vertexArrayOut[treeVCount + 1].m_z = node->m_p1.m_z;
+ treeVCount += 2;
+
+ if (parentNode) {
+ *parentNode = TreeNode (uint32_t(index));
+ }
+ index ++;
+
+ pool[stack] = node->m_front;
+ parent[stack] = &newNode->m_front;
+ stack ++;
+ pool[stack] = node->m_back;
+ parent[stack] = &newNode->m_back;
+ stack ++;
+ }
+ }
+
+ // this object is not to be deleted when using stack allocation
+ //delete root;
+ return index;
+ }
+
+ void PushNodes (dgConstructionTree* const root, dgList<dgConstructionTree*>& list) const
+ {
+ if (root->m_back) {
+ PushNodes (root->m_back, list);
+ }
+ if (root->m_front) {
+ PushNodes (root->m_front, list);
+ }
+ if (root->m_boxIndex == -1) {
+ list.Append(root);
+ }
+ }
+
+ int32_t CalculateMaximunDepth (dgConstructionTree* tree) const
+ {
+ int32_t depthPool[128];
+ dgConstructionTree* pool[128];
+
+ depthPool[0] = 0;
+ pool[0] = tree;
+ int32_t stack = 1;
+
+ int32_t maxDepth = -1;
+ while (stack) {
+ stack --;
+
+ int32_t depth = depthPool[stack];
+ dgConstructionTree* const node = pool[stack];
+ maxDepth = GetMax(maxDepth, depth);
+
+ if (node->m_boxIndex == -1) {
+ HACD_ASSERT (node->m_back);
+ HACD_ASSERT (node->m_front);
+
+ depth ++;
+ depthPool[stack] = depth;
+ pool[stack] = node->m_back;
+ stack ++;
+
+ depthPool[stack] = depth;
+ pool[stack] = node->m_front;
+ stack ++;
+ }
+ }
+
+ return maxDepth + 1;
+ }
+
+ float CalculateArea (dgConstructionTree* const node0, dgConstructionTree* const node1) const
+ {
+ dgVector p0 (GetMin (node0->m_p0.m_x, node1->m_p0.m_x), GetMin (node0->m_p0.m_y, node1->m_p0.m_y), GetMin (node0->m_p0.m_z, node1->m_p0.m_z), float (0.0f));
+ dgVector p1 (GetMax (node0->m_p1.m_x, node1->m_p1.m_x), GetMax (node0->m_p1.m_y, node1->m_p1.m_y), GetMax (node0->m_p1.m_z, node1->m_p1.m_z), float (0.0f));
+ dgVector side0 (p1 - p0);
+ dgVector side1 (side0.m_y, side0.m_z, side0.m_x, float (0.0f));
+ return side0 % side1;
+ }
+
+ void SetBox (dgConstructionTree* const node) const
+ {
+ node->m_p0.m_x = GetMin (node->m_back->m_p0.m_x, node->m_front->m_p0.m_x);
+ node->m_p0.m_y = GetMin (node->m_back->m_p0.m_y, node->m_front->m_p0.m_y);
+ node->m_p0.m_z = GetMin (node->m_back->m_p0.m_z, node->m_front->m_p0.m_z);
+ node->m_p1.m_x = GetMax (node->m_back->m_p1.m_x, node->m_front->m_p1.m_x);
+ node->m_p1.m_y = GetMax (node->m_back->m_p1.m_y, node->m_front->m_p1.m_y);
+ node->m_p1.m_z = GetMax (node->m_back->m_p1.m_z, node->m_front->m_p1.m_z);
+ dgVector side0 (node->m_p1 - node->m_p0);
+ dgVector side1 (side0.m_y, side0.m_z, side0.m_x, float (0.0f));
+ node->m_surfaceArea = side0 % side1;
+ }
+
+ void ImproveNodeFitness (dgConstructionTree* const node) const
+ {
+ HACD_ASSERT (node->m_back);
+ HACD_ASSERT (node->m_front);
+
+ if (node->m_parent) {
+ if (node->m_parent->m_back == node) {
+ float cost0 = node->m_surfaceArea;
+ float cost1 = CalculateArea (node->m_front, node->m_parent->m_front);
+ float cost2 = CalculateArea (node->m_back, node->m_parent->m_front);
+ if ((cost1 <= cost0) && (cost1 <= cost2)) {
+ dgConstructionTree* const parent = node->m_parent;
+ node->m_p0 = parent->m_p0;
+ node->m_p1 = parent->m_p1;
+ node->m_surfaceArea = parent->m_surfaceArea;
+ if (parent->m_parent) {
+ if (parent->m_parent->m_back == parent) {
+ parent->m_parent->m_back = node;
+ } else {
+ HACD_ASSERT (parent->m_parent->m_front == parent);
+ parent->m_parent->m_front = node;
+ }
+ }
+ node->m_parent = parent->m_parent;
+ parent->m_parent = node;
+ node->m_front->m_parent = parent;
+ parent->m_back = node->m_front;
+ node->m_front = parent;
+ SetBox (parent);
+ } else if ((cost2 <= cost0) && (cost2 <= cost1)) {
+ dgConstructionTree* const parent = node->m_parent;
+ node->m_p0 = parent->m_p0;
+ node->m_p1 = parent->m_p1;
+ node->m_surfaceArea = parent->m_surfaceArea;
+ if (parent->m_parent) {
+ if (parent->m_parent->m_back == parent) {
+ parent->m_parent->m_back = node;
+ } else {
+ HACD_ASSERT (parent->m_parent->m_front == parent);
+ parent->m_parent->m_front = node;
+ }
+ }
+ node->m_parent = parent->m_parent;
+ parent->m_parent = node;
+ node->m_back->m_parent = parent;
+ parent->m_back = node->m_back;
+ node->m_back = parent;
+ SetBox (parent);
+ }
+
+ } else {
+
+ float cost0 = node->m_surfaceArea;
+ float cost1 = CalculateArea (node->m_back, node->m_parent->m_back);
+ float cost2 = CalculateArea (node->m_front, node->m_parent->m_back);
+ if ((cost1 <= cost0) && (cost1 <= cost2)) {
+ dgConstructionTree* const parent = node->m_parent;
+ node->m_p0 = parent->m_p0;
+ node->m_p1 = parent->m_p1;
+ node->m_surfaceArea = parent->m_surfaceArea;
+ if (parent->m_parent) {
+ if (parent->m_parent->m_back == parent) {
+ parent->m_parent->m_back = node;
+ } else {
+ HACD_ASSERT (parent->m_parent->m_front == parent);
+ parent->m_parent->m_front = node;
+ }
+ }
+ node->m_parent = parent->m_parent;
+ parent->m_parent = node;
+ node->m_back->m_parent = parent;
+ parent->m_front = node->m_back;
+ node->m_back = parent;
+ SetBox (parent);
+ } else if ((cost2 <= cost0) && (cost2 <= cost1)) {
+ dgConstructionTree* const parent = node->m_parent;
+ node->m_p0 = parent->m_p0;
+ node->m_p1 = parent->m_p1;
+ node->m_surfaceArea = parent->m_surfaceArea;
+ if (parent->m_parent) {
+ if (parent->m_parent->m_back == parent) {
+ parent->m_parent->m_back = node;
+ } else {
+ HACD_ASSERT (parent->m_parent->m_front == parent);
+ parent->m_parent->m_front = node;
+ }
+ }
+ node->m_parent = parent->m_parent;
+ parent->m_parent = node;
+ node->m_front->m_parent = parent;
+ parent->m_front = node->m_front;
+ node->m_front = parent;
+ SetBox (parent);
+ }
+ }
+ }
+ }
+
+ double TotalFitness (dgList<dgConstructionTree*>& nodeList) const
+ {
+ double cost = float (0.0f);
+ for (dgList<dgConstructionTree*>::dgListNode* node = nodeList.GetFirst(); node; node = node->GetNext()) {
+ dgConstructionTree* const box = node->GetInfo();
+ cost += box->m_surfaceArea;
+ }
+ return cost;
+ }
+
+ dgConstructionTree* ImproveTotalFitness (dgConstructionTree* const root, dgAABBTree* const boxArray)
+ {
+ HACD_FORCE_PARAMETER_REFERENCE(boxArray);
+ dgList<dgConstructionTree*> nodesList;
+
+ dgConstructionTree* newRoot = root;
+ PushNodes (root, nodesList);
+ if (nodesList.GetCount()) {
+ int32_t maxPasses = CalculateMaximunDepth (root) * 2;
+ double newCost = TotalFitness (nodesList);
+ double prevCost = newCost;
+ do {
+ prevCost = newCost;
+ for (dgList<dgConstructionTree*>::dgListNode* node = nodesList.GetFirst(); node; node = node->GetNext()) {
+ dgConstructionTree* const box = node->GetInfo();
+ ImproveNodeFitness (box);
+ }
+
+ newCost = TotalFitness (nodesList);
+ maxPasses --;
+ } while (maxPasses && (newCost < prevCost));
+
+ newRoot = nodesList.GetLast()->GetInfo();
+ while (newRoot->m_parent) {
+ newRoot = newRoot->m_parent;
+ }
+ }
+
+ return newRoot;
+ }
+
+ dgConstructionTree* BuildTree (int32_t firstBox, int32_t lastBox, dgAABBTree* const boxArray, const dgTriplex* const vertexArray, dgConstructionTree* parent)
+ {
+ dgConstructionTree* const tree = HACD_NEW(dgConstructionTree);
+ HACD_ASSERT (firstBox >= 0);
+ HACD_ASSERT (lastBox >= 0);
+
+ tree->m_parent = parent;
+
+ if (lastBox == firstBox) {
+ int32_t j0 = boxArray[firstBox].m_minIndex;
+ int32_t j1 = boxArray[firstBox].m_maxIndex;
+ tree->m_p0 = dgVector (vertexArray[j0].m_x, vertexArray[j0].m_y, vertexArray[j0].m_z, float (0.0f));
+ tree->m_p1 = dgVector (vertexArray[j1].m_x, vertexArray[j1].m_y, vertexArray[j1].m_z, float (0.0f));
+
+ tree->m_boxIndex = firstBox;
+ tree->m_back = NULL;
+ tree->m_front = NULL;
+ } else {
+
+ struct dgSpliteInfo
+ {
+ dgSpliteInfo (dgAABBTree* const boxArray, int32_t boxCount, const dgTriplex* const vertexArray, const dgConstructionTree* const /*tree*/)
+ {
+
+ dgVector minP ( float (1.0e15f), float (1.0e15f), float (1.0e15f), float (0.0f));
+ dgVector maxP (-float (1.0e15f), -float (1.0e15f), -float (1.0e15f), float (0.0f));
+
+ if (boxCount == 2) {
+ m_axis = 1;
+
+ for (int32_t i = 0; i < boxCount; i ++) {
+ int32_t j0 = boxArray[i].m_minIndex;
+ int32_t j1 = boxArray[i].m_maxIndex;
+
+ dgVector p0 (vertexArray[j0].m_x, vertexArray[j0].m_y, vertexArray[j0].m_z, float (0.0f));
+ dgVector p1 (vertexArray[j1].m_x, vertexArray[j1].m_y, vertexArray[j1].m_z, float (0.0f));
+
+ minP.m_x = GetMin (p0.m_x, minP.m_x);
+ minP.m_y = GetMin (p0.m_y, minP.m_y);
+ minP.m_z = GetMin (p0.m_z, minP.m_z);
+
+ maxP.m_x = GetMax (p1.m_x, maxP.m_x);
+ maxP.m_y = GetMax (p1.m_y, maxP.m_y);
+ maxP.m_z = GetMax (p1.m_z, maxP.m_z);
+ }
+
+ } else {
+ dgVector median (float (0.0f), float (0.0f), float (0.0f), float (0.0f));
+ dgVector varian (float (0.0f), float (0.0f), float (0.0f), float (0.0f));
+ for (int32_t i = 0; i < boxCount; i ++) {
+
+ int32_t j0 = boxArray[i].m_minIndex;
+ int32_t j1 = boxArray[i].m_maxIndex;
+
+ dgVector p0 (vertexArray[j0].m_x, vertexArray[j0].m_y, vertexArray[j0].m_z, float (0.0f));
+ dgVector p1 (vertexArray[j1].m_x, vertexArray[j1].m_y, vertexArray[j1].m_z, float (0.0f));
+
+ minP.m_x = GetMin (p0.m_x, minP.m_x);
+ minP.m_y = GetMin (p0.m_y, minP.m_y);
+ minP.m_z = GetMin (p0.m_z, minP.m_z);
+
+ maxP.m_x = GetMax (p1.m_x, maxP.m_x);
+ maxP.m_y = GetMax (p1.m_y, maxP.m_y);
+ maxP.m_z = GetMax (p1.m_z, maxP.m_z);
+
+ dgVector p ((p0 + p1).Scale (0.5f));
+
+ median += p;
+ varian += p.CompProduct (p);
+ }
+
+ varian = varian.Scale (float (boxCount)) - median.CompProduct(median);
+
+
+ int32_t index = 0;
+ float maxVarian = float (-1.0e10f);
+ for (int32_t i = 0; i < 3; i ++) {
+ if (varian[i] > maxVarian) {
+ index = i;
+ maxVarian = varian[i];
+ }
+ }
+
+ dgVector center = median.Scale (float (1.0f) / float (boxCount));
+
+ float test = center[index];
+
+ int32_t i0 = 0;
+ int32_t i1 = boxCount - 1;
+ int32_t step = sizeof (dgTriplex) / sizeof (float);
+ const float* const points = &vertexArray[0].m_x;
+ do {
+ for (; i0 <= i1; i0 ++) {
+ int32_t j0 = boxArray[i0].m_minIndex;
+ int32_t j1 = boxArray[i0].m_maxIndex;
+
+ float val = (points[j0 * step + index] + points[j1 * step + index]) * float (0.5f);
+ if (val > test) {
+ break;
+ }
+ }
+
+ for (; i1 >= i0; i1 --) {
+ int32_t j0 = boxArray[i1].m_minIndex;
+ int32_t j1 = boxArray[i1].m_maxIndex;
+
+ float val = (points[j0 * step + index] + points[j1 * step + index]) * float (0.5f);
+ if (val < test) {
+ break;
+ }
+ }
+
+ if (i0 < i1) {
+ Swap(boxArray[i0], boxArray[i1]);
+ i0++;
+ i1--;
+ }
+ } while (i0 <= i1);
+
+ if (i0 > 0){
+ i0 --;
+ }
+ if ((i0 + 1) >= boxCount) {
+ i0 = boxCount - 2;
+ }
+
+ m_axis = i0 + 1;
+ }
+
+ HACD_ASSERT (maxP.m_x - minP.m_x >= float (0.0f));
+ HACD_ASSERT (maxP.m_y - minP.m_y >= float (0.0f));
+ HACD_ASSERT (maxP.m_z - minP.m_z >= float (0.0f));
+ m_p0 = minP;
+ m_p1 = maxP;
+ }
+
+ int32_t m_axis;
+ dgVector m_p0;
+ dgVector m_p1;
+ };
+
+ dgSpliteInfo info (&boxArray[firstBox], lastBox - firstBox + 1, vertexArray, tree);
+
+ tree->m_boxIndex = -1;
+ tree->m_p0 = info.m_p0;
+ tree->m_p1 = info.m_p1;
+
+ tree->m_front = BuildTree (firstBox + info.m_axis, lastBox, boxArray, vertexArray, tree);
+ tree->m_back = BuildTree (firstBox, firstBox + info.m_axis - 1, boxArray, vertexArray, tree);
+ }
+
+ dgVector side0 (tree->m_p1 - tree->m_p0);
+ dgVector side1 (side0.m_y, side0.m_z, side0.m_x, float (0.0f));
+ tree->m_surfaceArea = side0 % side1;
+
+ return tree;
+ }
+
+
+ int32_t BuildTopDown (int32_t boxCount, dgAABBTree* const boxArray, dgTriplex* const vertexArrayOut, int32_t &treeVCount, bool optimizedBuild)
+ {
+ dgStack <dgAABBTree> boxCopy (boxCount);
+ memcpy (&boxCopy[0], boxArray, boxCount * sizeof (dgAABBTree));
+
+ dgConstructionTree* tree = BuildTree (0, boxCount - 1, &boxCopy[0], vertexArrayOut, NULL);
+
+ optimizedBuild = true;
+ if (optimizedBuild) {
+ tree = ImproveTotalFitness (tree, &boxCopy[0]);
+ }
+
+ int32_t count = BuildTree (tree, boxArray, &boxCopy[0], vertexArrayOut, treeVCount);
+ delete tree;
+ return count;
+ }
+
+ HACD_FORCE_INLINE int32_t BoxIntersect (const dgTriplex* const vertexArray, const dgVector& min, const dgVector& max) const
+ {
+ dgVector boxP0 (vertexArray[m_minIndex].m_x, vertexArray[m_minIndex].m_y, vertexArray[m_minIndex].m_z, float (0.0f));
+ dgVector boxP1 (vertexArray[m_maxIndex].m_x, vertexArray[m_maxIndex].m_y, vertexArray[m_maxIndex].m_z, float (0.0f));
+ return dgOverlapTest (boxP0, boxP1, min, max) - 1;
+ }
+
+
+ HACD_FORCE_INLINE int32_t RayTest (const dgFastRayTest& ray, const dgTriplex* const vertexArray) const
+ {
+ float tmin = 0.0f;
+ float tmax = 1.0f;
+
+ dgVector minBox (&vertexArray[m_minIndex].m_x);
+ dgVector maxBox (&vertexArray[m_maxIndex].m_x);
+
+ for (int32_t i = 0; i < 3; i++) {
+ if (ray.m_isParallel[i]) {
+ if (ray.m_p0[i] < minBox[i] || ray.m_p0[i] > maxBox[i]) {
+ return 0;
+ }
+ } else {
+ float t1 = (minBox[i] - ray.m_p0[i]) * ray.m_dpInv[i];
+ float t2 = (maxBox[i] - ray.m_p0[i]) * ray.m_dpInv[i];
+
+ if (t1 > t2) {
+ Swap(t1, t2);
+ }
+ if (t1 > tmin) {
+ tmin = t1;
+ }
+ if (t2 < tmax) {
+ tmax = t2;
+ }
+ if (tmin > tmax) {
+ return 0;
+ }
+ }
+ }
+
+ return 0xffffffff;
+ }
+
+
+ void ForAllSectors (const int32_t* const indexArray, const float* const vertexArray, const dgVector& min, const dgVector& max, dgAABBIntersectCallback callback, void* const context) const
+ {
+ int32_t stack;
+ const dgAABBTree *stackPool[DG_STACK_DEPTH];
+
+ stack = 1;
+ stackPool[0] = this;
+ while (stack) {
+ stack --;
+ const dgAABBTree* const me = stackPool[stack];
+
+ if (me->BoxIntersect ((dgTriplex*) vertexArray, min, max) >= 0) {
+
+ if (me->m_back.IsLeaf()) {
+ int32_t index = int32_t (me->m_back.GetIndex());
+ int32_t vCount = int32_t ((me->m_back.GetCount() >> 1) - 1);
+ if ((vCount > 0) && callback(context, vertexArray, sizeof (dgTriplex), &indexArray[index + 1], vCount) == t_StopSearh) {
+ return;
+ }
+
+ } else {
+ HACD_ASSERT (stack < DG_STACK_DEPTH);
+ stackPool[stack] = me->m_back.GetNode(this);
+ stack++;
+ }
+
+ if (me->m_front.IsLeaf()) {
+ int32_t index = int32_t (me->m_front.GetIndex());
+ int32_t vCount = int32_t ((me->m_front.GetCount() >> 1) - 1);
+ if ((vCount > 0) && callback(context, vertexArray, sizeof (dgTriplex), &indexArray[index + 1], vCount) == t_StopSearh) {
+ return;
+ }
+
+ } else {
+ HACD_ASSERT (stack < DG_STACK_DEPTH);
+ stackPool[stack] = me->m_front.GetNode(this);
+ stack ++;
+ }
+ }
+ }
+ }
+
+
+ void ForAllSectorsRayHit (const dgFastRayTest& raySrc, const int32_t* indexArray, const float* vertexArray, dgRayIntersectCallback callback, void* const context) const
+ {
+ const dgAABBTree *stackPool[DG_STACK_DEPTH];
+ dgFastRayTest ray (raySrc);
+
+ int32_t stack = 1;
+ float maxParam = float (1.0f);
+
+ stackPool[0] = this;
+ while (stack) {
+ stack --;
+ const dgAABBTree *const me = stackPool[stack];
+ if (me->RayTest (ray, (dgTriplex*) vertexArray)) {
+
+ if (me->m_back.IsLeaf()) {
+ int32_t vCount = int32_t ((me->m_back.GetCount() >> 1) - 1);
+ if (vCount > 0) {
+ int32_t index = int32_t (me->m_back.GetIndex());
+ float param = callback(context, vertexArray, sizeof (dgTriplex), &indexArray[index + 1], vCount);
+ HACD_ASSERT (param >= float (0.0f));
+ if (param < maxParam) {
+ maxParam = param;
+ if (maxParam == float (0.0f)) {
+ break;
+ }
+ ray.Reset (maxParam) ;
+ }
+ }
+
+ } else {
+ HACD_ASSERT (stack < DG_STACK_DEPTH);
+ stackPool[stack] = me->m_back.GetNode(this);
+ stack++;
+ }
+
+ if (me->m_front.IsLeaf()) {
+ int32_t vCount = int32_t ((me->m_front.GetCount() >> 1) - 1);
+ if (vCount > 0) {
+ int32_t index = int32_t (me->m_front.GetIndex());
+ float param = callback(context, vertexArray, sizeof (dgTriplex), &indexArray[index + 1], vCount);
+ HACD_ASSERT (param >= float (0.0f));
+ if (param < maxParam) {
+ maxParam = param;
+ if (maxParam == float (0.0f)) {
+ break;
+ }
+ ray.Reset (maxParam);
+ }
+ }
+
+ } else {
+ HACD_ASSERT (stack < DG_STACK_DEPTH);
+ stackPool[stack] = me->m_front.GetNode(this);
+ stack ++;
+ }
+ }
+ }
+ }
+
+
+ dgVector ForAllSectorsSupportVertex (const dgVector& dir, const int32_t* const indexArray, const float* const vertexArray) const
+ {
+ float aabbProjection[DG_STACK_DEPTH];
+ const dgAABBTree *stackPool[DG_STACK_DEPTH];
+
+ int32_t stack = 1;
+ stackPool[0] = this;
+ aabbProjection[0] = float (1.0e10f);
+ const dgTriplex* const boxArray = (dgTriplex*)vertexArray;
+ dgVector supportVertex (float (0.0f), float (0.0f), float (0.0f), float (0.0f));
+
+ float maxProj = float (-1.0e20f);
+ int32_t ix = (dir[0] > float (0.0f)) ? 1 : 0;
+ int32_t iy = (dir[1] > float (0.0f)) ? 1 : 0;
+ int32_t iz = (dir[2] > float (0.0f)) ? 1 : 0;
+
+ while (stack) {
+ float boxSupportValue;
+
+ stack--;
+ boxSupportValue = aabbProjection[stack];
+ if (boxSupportValue > maxProj) {
+ float backSupportDist = float (0.0f);
+ float frontSupportDist = float (0.0f);
+ const dgAABBTree* const me = stackPool[stack];
+ if (me->m_back.IsLeaf()) {
+ backSupportDist = float (-1.0e20f);
+ int32_t index = int32_t (me->m_back.GetIndex());
+ int32_t vCount = int32_t ((me->m_back.GetCount() >> 1) - 1);
+
+ dgVector vertex (float (0.0f), float (0.0f), float (0.0f), float (0.0f));
+ for (int32_t j = 0; j < vCount; j ++) {
+ int32_t i0 = indexArray[index + j + 1] * int32_t (sizeof (dgTriplex) / sizeof (float));
+ dgVector p (&vertexArray[i0]);
+ float dist = p % dir;
+ if (dist > backSupportDist) {
+ backSupportDist = dist;
+ vertex = p;
+ }
+ }
+
+ if (backSupportDist > maxProj) {
+ maxProj = backSupportDist;
+ supportVertex = vertex;
+ }
+
+ } else {
+ dgVector box[2];
+ const dgAABBTree* const node = me->m_back.GetNode(this);
+ box[0].m_x = boxArray[node->m_minIndex].m_x;
+ box[0].m_y = boxArray[node->m_minIndex].m_y;
+ box[0].m_z = boxArray[node->m_minIndex].m_z;
+ box[1].m_x = boxArray[node->m_maxIndex].m_x;
+ box[1].m_y = boxArray[node->m_maxIndex].m_y;
+ box[1].m_z = boxArray[node->m_maxIndex].m_z;
+
+ dgVector supportPoint (box[ix].m_x, box[iy].m_y, box[iz].m_z, float (0.0));
+ backSupportDist = supportPoint % dir;
+ }
+
+ if (me->m_front.IsLeaf()) {
+ frontSupportDist = float (-1.0e20f);
+ int32_t index = int32_t (me->m_front.GetIndex());
+ int32_t vCount = int32_t ((me->m_front.GetCount() >> 1) - 1);
+
+ dgVector vertex (float (0.0f), float (0.0f), float (0.0f), float (0.0f));
+ for (int32_t j = 0; j < vCount; j ++) {
+ int32_t i0 = indexArray[index + j + 1] * int32_t (sizeof (dgTriplex) / sizeof (float));
+ dgVector p (&vertexArray[i0]);
+ float dist = p % dir;
+ if (dist > frontSupportDist) {
+ frontSupportDist = dist;
+ vertex = p;
+ }
+ }
+ if (frontSupportDist > maxProj) {
+ maxProj = frontSupportDist;
+ supportVertex = vertex;
+ }
+
+ } else {
+ dgVector box[2];
+ const dgAABBTree* const node = me->m_front.GetNode(this);
+ box[0].m_x = boxArray[node->m_minIndex].m_x;
+ box[0].m_y = boxArray[node->m_minIndex].m_y;
+ box[0].m_z = boxArray[node->m_minIndex].m_z;
+ box[1].m_x = boxArray[node->m_maxIndex].m_x;
+ box[1].m_y = boxArray[node->m_maxIndex].m_y;
+ box[1].m_z = boxArray[node->m_maxIndex].m_z;
+
+ dgVector supportPoint (box[ix].m_x, box[iy].m_y, box[iz].m_z, float (0.0));
+ frontSupportDist = supportPoint % dir;
+ }
+
+ if (frontSupportDist >= backSupportDist) {
+ if (!me->m_back.IsLeaf()) {
+ aabbProjection[stack] = backSupportDist;
+ stackPool[stack] = me->m_back.GetNode(this);
+ stack++;
+ }
+
+ if (!me->m_front.IsLeaf()) {
+ aabbProjection[stack] = frontSupportDist;
+ stackPool[stack] = me->m_front.GetNode(this);
+ stack++;
+ }
+
+ } else {
+
+ if (!me->m_front.IsLeaf()) {
+ aabbProjection[stack] = frontSupportDist;
+ stackPool[stack] = me->m_front.GetNode(this);
+ stack++;
+ }
+
+ if (!me->m_back.IsLeaf()) {
+ aabbProjection[stack] = backSupportDist;
+ stackPool[stack] = me->m_back.GetNode(this);
+ stack++;
+ }
+ }
+ }
+ }
+
+ return supportVertex;
+ }
+
+
+ private:
+
+ int32_t GetAxis (dgConstructionTree** boxArray, int32_t boxCount) const
+ {
+ int32_t axis;
+ float maxVal;
+ dgVector median (float (0.0f), float (0.0f), float (0.0f), float (0.0f));
+ dgVector varian (float (0.0f), float (0.0f), float (0.0f), float (0.0f));
+ for (int32_t i = 0; i < boxCount; i ++) {
+
+ median += boxArray[i]->m_p0;
+ median += boxArray[i]->m_p1;
+
+ varian += boxArray[i]->m_p0.CompProduct(boxArray[i]->m_p0);
+ varian += boxArray[i]->m_p1.CompProduct(boxArray[i]->m_p1);
+ }
+
+ boxCount *= 2;
+ varian.m_x = boxCount * varian.m_x - median.m_x * median.m_x;
+ varian.m_y = boxCount * varian.m_y - median.m_y * median.m_y;
+ varian.m_z = boxCount * varian.m_z - median.m_z * median.m_z;
+
+ axis = 0;
+ maxVal = varian[0];
+ for (int32_t i = 1; i < 3; i ++) {
+ if (varian[i] > maxVal) {
+ axis = i;
+ maxVal = varian[i];
+ }
+ }
+
+ return axis;
+ }
+
+/*
+ class DG_AABB_CMPBOX
+ {
+ public:
+ int32_t m_axis;
+ const dgTriplex* m_points;
+ };
+ static inline int32_t CompareBox (const dgAABBTree* const boxA, const dgAABBTree* const boxB, void* const context)
+ {
+ DG_AABB_CMPBOX& info = *((DG_AABB_CMPBOX*)context);
+
+ int32_t axis = info.m_axis;
+ const float* p0 = &info.m_points[boxA->m_minIndex].m_x;
+ const float* p1 = &info.m_points[boxB->m_minIndex].m_x;
+
+ if (p0[axis] < p1[axis]) {
+ return -1;
+ } else if (p0[axis] > p1[axis]) {
+ return 1;
+ }
+ return 0;
+ }
+*/
+
+ static inline int32_t CompareBox (const dgConstructionTree* const boxA, const dgConstructionTree* const boxB, void* const context)
+ {
+ int32_t axis;
+
+ axis = *((int32_t*) context);
+
+ if (boxA->m_p0[axis] < boxB->m_p0[axis]) {
+ return -1;
+ } else if (boxA->m_p0[axis] > boxB->m_p0[axis]) {
+ return 1;
+ }
+ return 0;
+ }
+
+
+
+
+ int32_t m_minIndex;
+ int32_t m_maxIndex;
+ TreeNode m_back;
+ TreeNode m_front;
+ friend class dgAABBPolygonSoup;
+};
+
+
+
+dgAABBPolygonSoup::dgAABBPolygonSoup ()
+ :dgPolygonSoupDatabase()
+{
+ m_aabb = NULL;
+ m_indices = NULL;
+ m_indexCount = 0;
+ m_nodesCount = 0;
+}
+
+dgAABBPolygonSoup::~dgAABBPolygonSoup ()
+{
+ if (m_aabb) {
+ HACD_FREE (m_aabb);
+ HACD_FREE (m_indices);
+ }
+}
+
+
+void* dgAABBPolygonSoup::GetRootNode() const
+{
+ return m_aabb;
+}
+
+void* dgAABBPolygonSoup::GetBackNode(const void* const root) const
+{
+ dgAABBTree* const node = (dgAABBTree*) root;
+ return node->m_back.IsLeaf() ? NULL : node->m_back.GetNode(m_aabb);
+}
+
+void* dgAABBPolygonSoup::GetFrontNode(const void* const root) const
+{
+ dgAABBTree* const node = (dgAABBTree*) root;
+ return node->m_front.IsLeaf() ? NULL : node->m_front.GetNode(m_aabb);
+}
+
+
+void dgAABBPolygonSoup::GetNodeAABB(const void* const root, dgVector& p0, dgVector& p1) const
+{
+ dgAABBTree* const node = (dgAABBTree*) root;
+ const dgTriplex* const vertex = (dgTriplex*) m_localVertex;
+
+ p0 = dgVector (vertex[node->m_minIndex].m_x, vertex[node->m_minIndex].m_y, vertex[node->m_minIndex].m_z, float (0.0f));
+ p1 = dgVector (vertex[node->m_maxIndex].m_x, vertex[node->m_maxIndex].m_y, vertex[node->m_maxIndex].m_z, float (0.0f));
+}
+
+
+void dgAABBPolygonSoup::ForAllSectors (
+ const dgVector& min,
+ const dgVector& max,
+ dgAABBIntersectCallback callback,
+ void* const context) const
+{
+ dgAABBTree* tree;
+
+ if (m_aabb) {
+ tree = (dgAABBTree*) m_aabb;
+ tree->ForAllSectors (m_indices, m_localVertex, min, max, callback, context);
+ }
+}
+
+dgVector dgAABBPolygonSoup::ForAllSectorsSupportVectex (const dgVector& dir) const
+{
+ dgAABBTree* tree;
+
+ if (m_aabb) {
+ tree = (dgAABBTree*) m_aabb;
+ return tree->ForAllSectorsSupportVertex (dir, m_indices, m_localVertex);
+ } else {
+ return dgVector (0, 0, 0, 0);
+ }
+}
+
+
+void dgAABBPolygonSoup::GetAABB (dgVector& p0, dgVector& p1) const
+{
+ if (m_aabb) {
+ dgAABBTree* tree;
+ tree = (dgAABBTree*) m_aabb;
+ p0 = dgVector (&m_localVertex[tree->m_minIndex * 3]);
+ p1 = dgVector (&m_localVertex[tree->m_maxIndex * 3]);
+ } else {
+ p0 = dgVector (float (0.0f), float (0.0f), float (0.0f), float (0.0f));
+ p1 = dgVector (float (0.0f), float (0.0f), float (0.0f), float (0.0f));
+ }
+}
+
+
+void dgAABBPolygonSoup::ForAllSectorsRayHit (const dgFastRayTest& ray, dgRayIntersectCallback callback, void* const context) const
+{
+ dgAABBTree* tree;
+
+ if (m_aabb) {
+ tree = (dgAABBTree*) m_aabb;
+ tree->ForAllSectorsRayHit (ray, m_indices, m_localVertex, callback, context);
+ }
+}
+
+dgIntersectStatus dgAABBPolygonSoup::CalculateThisFaceEdgeNormals (void *context, const float* const polygon, int32_t strideInBytes, const int32_t* const indexArray, int32_t indexCount)
+{
+ AdjacentdFaces& adjacentFaces = *((AdjacentdFaces*)context);
+
+ int32_t count = adjacentFaces.m_count;
+ int32_t stride = int32_t (strideInBytes / sizeof (float));
+
+ int32_t j0 = indexArray[indexCount - 1];
+ for (int32_t j = 0; j < indexCount; j ++) {
+ int32_t j1 = indexArray[j];
+ int64_t key = (int64_t (j0) << 32) + j1;
+ for (int32_t i = 0; i < count; i ++) {
+ if (adjacentFaces.m_edgeMap[i] == key) {
+ float maxDist = float (0.0f);
+ for (int32_t k = 0; k < indexCount; k ++) {
+ dgVector r (&polygon[indexArray[k] * stride]);
+ float dist = adjacentFaces.m_normal.Evalue(r);
+ if (dgAbsf (dist) > dgAbsf (maxDist)) {
+ maxDist = dist;
+ }
+ }
+ if (maxDist < float (1.0e-4f)) {
+ adjacentFaces.m_index[i + count + 1] = indexArray[indexCount];
+ }
+ break;
+ }
+ }
+
+ j0 = j1;
+ }
+
+ return t_ContinueSearh;
+}
+
+
+dgIntersectStatus dgAABBPolygonSoup::CalculateAllFaceEdgeNormals (void *context, const float* const polygon, int32_t strideInBytes, const int32_t* const indexArray, int32_t indexCount)
+{
+ dgAABBPolygonSoup* const me = (dgAABBPolygonSoup*) context;
+
+ int32_t stride = int32_t (strideInBytes / sizeof (float));
+
+ AdjacentdFaces adjacentFaces;
+ adjacentFaces.m_count = indexCount;
+ adjacentFaces.m_index = (int32_t*) indexArray;
+ dgVector n (&polygon[indexArray[indexCount] * stride]);
+ dgVector p (&polygon[indexArray[0] * stride]);
+ adjacentFaces.m_normal = dgPlane (n, - (n % p));
+
+ HACD_ASSERT (indexCount < int32_t (sizeof (adjacentFaces.m_edgeMap) / sizeof (adjacentFaces.m_edgeMap[0])));
+
+ int32_t edgeIndex = indexCount - 1;
+ int32_t i0 = indexArray[indexCount - 1];
+ dgVector p0 ( float (1.0e15f), float (1.0e15f), float (1.0e15f), float (0.0f));
+ dgVector p1 (-float (1.0e15f), -float (1.0e15f), -float (1.0e15f), float (0.0f));
+ for (int32_t i = 0; i < indexCount; i ++) {
+ int32_t i1 = indexArray[i];
+ int32_t index = i1 * stride;
+ dgVector p (&polygon[index]);
+
+ p0.m_x = GetMin (p.m_x, p0.m_x);
+ p0.m_y = GetMin (p.m_y, p0.m_y);
+ p0.m_z = GetMin (p.m_z, p0.m_z);
+
+ p1.m_x = GetMax (p.m_x, p1.m_x);
+ p1.m_y = GetMax (p.m_y, p1.m_y);
+ p1.m_z = GetMax (p.m_z, p1.m_z);
+
+ adjacentFaces.m_edgeMap[edgeIndex] = (int64_t (i1) << 32) + i0;
+ edgeIndex = i;
+ i0 = i1;
+ }
+
+ p0.m_x -= float (0.5f);
+ p0.m_y -= float (0.5f);
+ p0.m_z -= float (0.5f);
+ p1.m_x += float (0.5f);
+ p1.m_y += float (0.5f);
+ p1.m_z += float (0.5f);
+
+ me->ForAllSectors (p0, p1, CalculateThisFaceEdgeNormals, &adjacentFaces);
+
+ return t_ContinueSearh;
+}
+
+float dgAABBPolygonSoup::CalculateFaceMaxSize (dgTriplex* const vertex, int32_t indexCount, const int32_t* const indexArray) const
+{
+ float maxSize = float (0.0f);
+ int32_t index = indexArray[indexCount - 1];
+ dgVector p0 (vertex[index].m_x, vertex[index].m_y, vertex[index].m_z, float (0.0f));
+ for (int32_t i = 0; i < indexCount; i ++) {
+ int32_t index = indexArray[i];
+ dgVector p1 (vertex[index].m_x, vertex[index].m_y, vertex[index].m_z, float (0.0f));
+
+ dgVector dir (p1 - p0);
+ dir = dir.Scale (dgRsqrt (dir % dir));
+
+ float maxVal = float (-1.0e10f);
+ float minVal = float ( 1.0e10f);
+ for (int32_t j = 0; j < indexCount; j ++) {
+ int32_t index = indexArray[j];
+ dgVector q (vertex[index].m_x, vertex[index].m_y, vertex[index].m_z, float (0.0f));
+ float val = dir % q;
+ minVal = GetMin(minVal, val);
+ maxVal = GetMax(maxVal, val);
+ }
+
+ float size = maxVal - minVal;
+ maxSize = GetMax(maxSize, size);
+ p0 = p1;
+ }
+
+ return maxSize;
+}
+
+void dgAABBPolygonSoup::CalculateAdjacendy ()
+{
+ dgVector p0;
+ dgVector p1;
+ GetAABB (p0, p1);
+ ForAllSectors (p0, p1, CalculateAllFaceEdgeNormals, this);
+}
+
+void dgAABBPolygonSoup::Create (const dgPolygonSoupDatabaseBuilder& builder, bool optimizedBuild)
+{
+ if (builder.m_faceCount == 0) {
+ return;
+ }
+
+ m_strideInBytes = sizeof (dgTriplex);
+ m_indexCount = builder.m_indexCount * 2 + builder.m_faceCount;
+ m_indices = (int32_t*) HACD_ALLOC (sizeof (int32_t) * m_indexCount);
+ m_aabb = (dgAABBTree*) HACD_ALLOC (sizeof (dgAABBTree) * builder.m_faceCount);
+ m_localVertex = (float*) HACD_ALLOC (sizeof (dgTriplex) * (builder.m_vertexCount + builder.m_normalCount + builder.m_faceCount * 4));
+
+ dgAABBTree* const tree = (dgAABBTree*) m_aabb;
+ dgTriplex* const tmpVertexArray = (dgTriplex*)m_localVertex;
+
+ for (int32_t i = 0; i < builder.m_vertexCount; i ++) {
+ tmpVertexArray[i].m_x = float (builder.m_vertexPoints[i].m_x);
+ tmpVertexArray[i].m_y = float (builder.m_vertexPoints[i].m_y);
+ tmpVertexArray[i].m_z = float (builder.m_vertexPoints[i].m_z);
+ }
+
+ for (int32_t i = 0; i < builder.m_normalCount; i ++) {
+ tmpVertexArray[i + builder.m_vertexCount].m_x = float (builder.m_normalPoints[i].m_x);
+ tmpVertexArray[i + builder.m_vertexCount].m_y = float (builder.m_normalPoints[i].m_y);
+ tmpVertexArray[i + builder.m_vertexCount].m_z = float (builder.m_normalPoints[i].m_z);
+ }
+
+ int32_t polygonIndex = 0;
+ int32_t* indexMap = m_indices;
+ const int32_t* const indices = &builder.m_vertexIndex[0];
+ for (int32_t i = 0; i < builder.m_faceCount; i ++) {
+
+ int32_t indexCount = builder.m_faceVertexCount[i];
+ dgAABBTree& box = tree[i];
+
+ box.m_minIndex = builder.m_normalCount + builder.m_vertexCount + i * 2;
+ box.m_maxIndex = builder.m_normalCount + builder.m_vertexCount + i * 2 + 1;
+
+ box.m_front = dgAABBTree::TreeNode(0, 0);
+ box.m_back = dgAABBTree::TreeNode (uint32_t (indexCount * 2), uint32_t (indexMap - m_indices));
+ box.CalcExtends (&tmpVertexArray[0], indexCount, &indices[polygonIndex]);
+
+ for (int32_t j = 0; j < indexCount; j ++) {
+ indexMap[0] = indices[polygonIndex + j];
+ indexMap ++;
+ }
+
+ indexMap[0] = builder.m_vertexCount + builder.m_normalIndex[i];
+ indexMap ++;
+ for (int32_t j = 1; j < indexCount; j ++) {
+ indexMap[0] = -1;
+ indexMap ++;
+ }
+
+ float faceSize = CalculateFaceMaxSize (&tmpVertexArray[0], indexCount - 1, &indices[polygonIndex + 1]);
+ indexMap[0] = int32_t (faceSize);
+ indexMap ++;
+ polygonIndex += indexCount;
+ }
+
+ int32_t extraVertexCount = builder.m_normalCount + builder.m_vertexCount + builder.m_faceCount * 2;
+// if (optimizedBuild) {
+// m_nodesCount = tree->BuildBottomUp (builder.m_allocator, builder.m_faceCount, tree, &tmpVertexArray[0], extraVertexCount);
+// } else {
+// m_nodesCount = tree->BuildTopDown (builder.m_allocator, builder.m_faceCount, tree, &tmpVertexArray[0], extraVertexCount);
+// }
+
+// m_nodesCount = tree->BuildBottomUp (builder.m_allocator, builder.m_faceCount, tree, &tmpVertexArray[0], extraVertexCount, optimizedBuild);
+ m_nodesCount = tree->BuildTopDown (builder.m_faceCount, tree, &tmpVertexArray[0], extraVertexCount, optimizedBuild);
+
+ m_localVertex[tree->m_minIndex * 3 + 0] -= float (0.1f);
+ m_localVertex[tree->m_minIndex * 3 + 1] -= float (0.1f);
+ m_localVertex[tree->m_minIndex * 3 + 2] -= float (0.1f);
+ m_localVertex[tree->m_maxIndex * 3 + 0] += float (0.1f);
+ m_localVertex[tree->m_maxIndex * 3 + 1] += float (0.1f);
+ m_localVertex[tree->m_maxIndex * 3 + 2] += float (0.1f);
+
+
+ extraVertexCount -= (builder.m_normalCount + builder.m_vertexCount);
+
+ dgStack<int32_t> indexArray (extraVertexCount);
+ extraVertexCount = dgVertexListToIndexList (&tmpVertexArray[builder.m_normalCount + builder.m_vertexCount].m_x, sizeof (dgTriplex), sizeof (dgTriplex), 0, extraVertexCount, &indexArray[0], float (1.0e-6f));
+
+ for (int32_t i = 0; i < m_nodesCount; i ++) {
+ dgAABBTree& box = tree[i];
+
+ int32_t j = box.m_minIndex - builder.m_normalCount - builder.m_vertexCount;
+ box.m_minIndex = indexArray[j] + builder.m_normalCount + builder.m_vertexCount;
+ j = box.m_maxIndex - builder.m_normalCount - builder.m_vertexCount;
+ box.m_maxIndex = indexArray[j] + builder.m_normalCount + builder.m_vertexCount;
+ }
+
+ m_vertexCount = extraVertexCount + builder.m_normalCount + builder.m_vertexCount;
+}
+