2 Copyright (c) 2011 Ole Kniemeyer, MAXON, www.maxon.net
4 This software is provided 'as-is', without any express or implied warranty.
5 In no event will the authors be held liable for any damages arising from the use of this software.
6 Permission is granted to anyone to use this software for any purpose,
7 including commercial applications, and to alter it and redistribute it freely,
8 subject to the following restrictions:
10 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.
11 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
12 3. This notice may not be removed or altered from any source distribution.
17 #include "btConvexHullComputer.h"
18 #include "btAlignedObjectArray.h"
20 #include "btVector3.h"
24 #elif defined(_MSC_VER)
25 typedef __int32 int32_t;
26 typedef __int64 int64_t;
27 typedef unsigned __int32 uint32_t;
28 typedef unsigned __int64 uint64_t;
31 typedef long long int int64_t;
32 typedef unsigned int uint32_t;
33 typedef unsigned long long int uint64_t;
37 //The definition of USE_X86_64_ASM is moved into the build system. You can enable it manually by commenting out the following lines
38 //#if (defined(__GNUC__) && defined(__x86_64__) && !defined(__ICL)) // || (defined(__ICL) && defined(_M_X64)) bug in Intel compiler, disable inline assembly
39 // #define USE_X86_64_ASM
43 //#define DEBUG_CONVEX_HULL
44 //#define SHOW_ITERATIONS
46 #if defined(DEBUG_CONVEX_HULL) || defined(SHOW_ITERATIONS)
50 // Convex hull implementation based on Preparata and Hong
51 // Ole Kniemeyer, MAXON Computer GmbH
52 class btConvexHullInternal
63 Point64(int64_t x, int64_t y, int64_t z): x(x), y(y), z(z)
69 return (x == 0) && (y == 0) && (z == 0);
72 int64_t dot(const Point64& b) const
74 return x * b.x + y * b.y + z * b.z;
90 Point32(int32_t x, int32_t y, int32_t z): x(x), y(y), z(z), index(-1)
94 bool operator==(const Point32& b) const
96 return (x == b.x) && (y == b.y) && (z == b.z);
99 bool operator!=(const Point32& b) const
101 return (x != b.x) || (y != b.y) || (z != b.z);
106 return (x == 0) && (y == 0) && (z == 0);
109 Point64 cross(const Point32& b) const
111 return Point64(y * b.z - z * b.y, z * b.x - x * b.z, x * b.y - y * b.x);
114 Point64 cross(const Point64& b) const
116 return Point64(y * b.z - z * b.y, z * b.x - x * b.z, x * b.y - y * b.x);
119 int64_t dot(const Point32& b) const
121 return x * b.x + y * b.y + z * b.z;
124 int64_t dot(const Point64& b) const
126 return x * b.x + y * b.y + z * b.z;
129 Point32 operator+(const Point32& b) const
131 return Point32(x + b.x, y + b.y, z + b.z);
134 Point32 operator-(const Point32& b) const
136 return Point32(x - b.x, y - b.y, z - b.z);
150 Int128(uint64_t low, uint64_t high): low(low), high(high)
154 Int128(uint64_t low): low(low), high(0)
158 Int128(int64_t value): low(value), high((value >= 0) ? 0 : (uint64_t) -1LL)
162 static Int128 mul(int64_t a, int64_t b);
164 static Int128 mul(uint64_t a, uint64_t b);
166 Int128 operator-() const
168 return Int128((uint64_t) -(int64_t)low, ~high + (low == 0));
171 Int128 operator+(const Int128& b) const
173 #ifdef USE_X86_64_ASM
175 __asm__ ("addq %[bl], %[rl]\n\t"
176 "adcq %[bh], %[rh]\n\t"
177 : [rl] "=r" (result.low), [rh] "=r" (result.high)
178 : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high)
182 uint64_t lo = low + b.low;
183 return Int128(lo, high + b.high + (lo < low));
187 Int128 operator-(const Int128& b) const
189 #ifdef USE_X86_64_ASM
191 __asm__ ("subq %[bl], %[rl]\n\t"
192 "sbbq %[bh], %[rh]\n\t"
193 : [rl] "=r" (result.low), [rh] "=r" (result.high)
194 : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high)
202 Int128& operator+=(const Int128& b)
204 #ifdef USE_X86_64_ASM
205 __asm__ ("addq %[bl], %[rl]\n\t"
206 "adcq %[bh], %[rh]\n\t"
207 : [rl] "=r" (low), [rh] "=r" (high)
208 : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high)
211 uint64_t lo = low + b.low;
231 Int128 operator*(int64_t b) const;
233 btScalar toScalar() const
235 return ((int64_t) high >= 0) ? btScalar(high) * (btScalar(0x100000000LL) * btScalar(0x100000000LL)) + btScalar(low)
236 : -(-*this).toScalar();
241 return ((int64_t) high < 0) ? -1 : (high || low) ? 1 : 0;
244 bool operator<(const Int128& b) const
246 return (high < b.high) || ((high == b.high) && (low < b.low));
249 int ucmp(const Int128&b) const
275 uint64_t m_numerator;
276 uint64_t m_denominator;
280 Rational64(int64_t numerator, int64_t denominator)
285 m_numerator = (uint64_t) numerator;
287 else if (numerator < 0)
290 m_numerator = (uint64_t) -numerator;
299 m_denominator = (uint64_t) denominator;
301 else if (denominator < 0)
304 m_denominator = (uint64_t) -denominator;
312 bool isNegativeInfinity() const
314 return (sign < 0) && (m_denominator == 0);
319 return (sign == 0) && (m_denominator == 0);
322 int compare(const Rational64& b) const;
324 btScalar toScalar() const
326 return sign * ((m_denominator == 0) ? SIMD_INFINITY : (btScalar) m_numerator / m_denominator);
340 Rational128(int64_t value)
345 this->numerator = value;
350 this->numerator = -value;
355 this->numerator = (uint64_t) 0;
357 this->denominator = (uint64_t) 1;
361 Rational128(const Int128& numerator, const Int128& denominator)
363 sign = numerator.getSign();
366 this->numerator = numerator;
370 this->numerator = -numerator;
372 int dsign = denominator.getSign();
375 this->denominator = denominator;
380 this->denominator = -denominator;
385 int compare(const Rational128& b) const;
387 int compare(int64_t b) const;
389 btScalar toScalar() const
391 return sign * ((denominator.getSign() == 0) ? SIMD_INFINITY : numerator.toScalar() / denominator.toScalar());
407 PointR128(Int128 x, Int128 y, Int128 z, Int128 denominator): x(x), y(y), z(z), denominator(denominator)
411 btScalar xvalue() const
413 return x.toScalar() / denominator.toScalar();
416 btScalar yvalue() const
418 return y.toScalar() / denominator.toScalar();
421 btScalar zvalue() const
423 return z.toScalar() / denominator.toScalar();
437 Face* firstNearbyFace;
438 Face* lastNearbyFace;
443 Vertex(): next(NULL), prev(NULL), edges(NULL), firstNearbyFace(NULL), lastNearbyFace(NULL), copy(-1)
447 #ifdef DEBUG_CONVEX_HULL
450 printf("V%d (%d, %d, %d)", point.index, point.x, point.y, point.z);
456 Point32 operator-(const Vertex& b) const
458 return point - b.point;
461 Rational128 dot(const Point64& b) const
463 return (point.index >= 0) ? Rational128(point.dot(b))
464 : Rational128(point128.x * b.x + point128.y * b.y + point128.z * b.z, point128.denominator);
467 btScalar xvalue() const
469 return (point.index >= 0) ? btScalar(point.x) : point128.xvalue();
472 btScalar yvalue() const
474 return (point.index >= 0) ? btScalar(point.y) : point128.yvalue();
477 btScalar zvalue() const
479 return (point.index >= 0) ? btScalar(point.z) : point128.zvalue();
482 void receiveNearbyFaces(Vertex* src)
486 lastNearbyFace->nextWithSameNearbyVertex = src->firstNearbyFace;
490 firstNearbyFace = src->firstNearbyFace;
492 if (src->lastNearbyFace)
494 lastNearbyFace = src->lastNearbyFace;
496 for (Face* f = src->firstNearbyFace; f; f = f->nextWithSameNearbyVertex)
498 btAssert(f->nearbyVertex == src);
499 f->nearbyVertex = this;
501 src->firstNearbyFace = NULL;
502 src->lastNearbyFace = NULL;
528 btAssert(reverse->target == n->reverse->target);
533 #ifdef DEBUG_CONVEX_HULL
536 printf("E%p : %d -> %d, n=%p p=%p (0 %d\t%d\t%d) -> (%d %d %d)", this, reverse->target->point.index, target->point.index, next, prev,
537 reverse->target->point.x, reverse->target->point.y, reverse->target->point.z, target->point.x, target->point.y, target->point.z);
546 Vertex* nearbyVertex;
547 Face* nextWithSameNearbyVertex;
552 Face(): next(NULL), nearbyVertex(NULL), nextWithSameNearbyVertex(NULL)
556 void init(Vertex* a, Vertex* b, Vertex* c)
562 if (a->lastNearbyFace)
564 a->lastNearbyFace->nextWithSameNearbyVertex = this;
568 a->firstNearbyFace = this;
570 a->lastNearbyFace = this;
575 return dir0.cross(dir1);
579 template<typename UWord, typename UHWord> class DMul
582 static uint32_t high(uint64_t value)
589 struct { uint32_t low, high; } value32;
591 cast_helper(uint64_t value) : value64(value) {}
593 return cast_helper(value).value32.high;
596 static uint32_t low(uint64_t value)
598 return (uint32_t) value;
601 static uint64_t mul(uint32_t a, uint32_t b)
603 return (uint64_t) a * (uint64_t) b;
606 static void shlHalf(uint64_t& value)
611 static uint64_t high(Int128 value)
616 static uint64_t low(Int128 value)
621 static Int128 mul(uint64_t a, uint64_t b)
623 return Int128::mul(a, b);
626 static void shlHalf(Int128& value)
628 value.high = value.low;
634 static void mul(UWord a, UWord b, UWord& resLow, UWord& resHigh)
636 UWord p00 = mul(low(a), low(b));
637 UWord p01 = mul(low(a), high(b));
638 UWord p10 = mul(high(a), low(b));
639 UWord p11 = mul(high(a), high(b));
640 UWord p0110 = UWord(low(p01)) + UWord(low(p10));
657 class IntermediateHull
665 IntermediateHull(): minXy(NULL), maxXy(NULL), minYx(NULL), maxYx(NULL)
672 enum Orientation {NONE, CLOCKWISE, COUNTER_CLOCKWISE};
674 template <typename T> class PoolArray
683 PoolArray(int size): size(size), next(NULL)
685 array = (T*) btAlignedAlloc(sizeof(T) * size, 16);
690 btAlignedFree(array);
696 for (int i = 0; i < size; i++, o++)
698 o->next = (i+1 < size) ? o + 1 : NULL;
704 template <typename T> class Pool
707 PoolArray<T>* arrays;
708 PoolArray<T>* nextArray;
713 Pool(): arrays(NULL), nextArray(NULL), freeObjects(NULL), arraySize(256)
721 PoolArray<T>* p = arrays;
734 void setArraySize(int arraySize)
736 this->arraySize = arraySize;
744 PoolArray<T>* p = nextArray;
751 p = new(btAlignedAlloc(sizeof(PoolArray<T>), 16)) PoolArray<T>(arraySize);
757 freeObjects = o->next;
761 void freeObject(T* object)
764 object->next = freeObjects;
765 freeObjects = object;
771 Pool<Vertex> vertexPool;
774 btAlignedObjectArray<Vertex*> originalVertices;
780 int maxUsedEdgePairs;
782 static Orientation getOrientation(const Edge* prev, const Edge* next, const Point32& s, const Point32& t);
783 Edge* findMaxAngle(bool ccw, const Vertex* start, const Point32& s, const Point64& rxs, const Point64& sxrxs, Rational64& minCot);
784 void findEdgeForCoplanarFaces(Vertex* c0, Vertex* c1, Edge*& e0, Edge*& e1, Vertex* stop0, Vertex* stop1);
786 Edge* newEdgePair(Vertex* from, Vertex* to);
788 void removeEdgePair(Edge* edge)
790 Edge* n = edge->next;
791 Edge* r = edge->reverse;
793 btAssert(edge->target && r->target);
797 n->prev = edge->prev;
798 edge->prev->next = n;
799 r->target->edges = n;
803 r->target->edges = NULL;
812 edge->target->edges = n;
816 edge->target->edges = NULL;
819 edgePool.freeObject(edge);
820 edgePool.freeObject(r);
824 void computeInternal(int start, int end, IntermediateHull& result);
826 bool mergeProjection(IntermediateHull& h0, IntermediateHull& h1, Vertex*& c0, Vertex*& c1);
828 void merge(IntermediateHull& h0, IntermediateHull& h1);
830 btVector3 toBtVector(const Point32& v);
832 btVector3 getBtNormal(Face* face);
834 bool shiftFace(Face* face, btScalar amount, btAlignedObjectArray<Vertex*> stack);
839 void compute(const void* coords, bool doubleCoords, int stride, int count);
841 btVector3 getCoordinates(const Vertex* v);
843 btScalar shrink(btScalar amount, btScalar clampAmount);
847 btConvexHullInternal::Int128 btConvexHullInternal::Int128::operator*(int64_t b) const
849 bool negative = (int64_t) high < 0;
850 Int128 a = negative ? -*this : *this;
853 negative = !negative;
856 Int128 result = mul(a.low, (uint64_t) b);
857 result.high += a.high * (uint64_t) b;
858 return negative ? -result : result;
861 btConvexHullInternal::Int128 btConvexHullInternal::Int128::mul(int64_t a, int64_t b)
865 #ifdef USE_X86_64_ASM
866 __asm__ ("imulq %[b]"
867 : "=a" (result.low), "=d" (result.high)
873 bool negative = a < 0;
880 negative = !negative;
883 DMul<uint64_t, uint32_t>::mul((uint64_t) a, (uint64_t) b, result.low, result.high);
884 return negative ? -result : result;
888 btConvexHullInternal::Int128 btConvexHullInternal::Int128::mul(uint64_t a, uint64_t b)
892 #ifdef USE_X86_64_ASM
894 : "=a" (result.low), "=d" (result.high)
899 DMul<uint64_t, uint32_t>::mul(a, b, result.low, result.high);
905 int btConvexHullInternal::Rational64::compare(const Rational64& b) const
909 return sign - b.sign;
916 // return (numerator * b.denominator > b.numerator * denominator) ? sign : (numerator * b.denominator < b.numerator * denominator) ? -sign : 0;
918 #ifdef USE_X86_64_ASM
923 __asm__ ("mulq %[bn]\n\t"
924 "movq %%rax, %[tmp]\n\t"
925 "movq %%rdx, %%rbx\n\t"
926 "movq %[tn], %%rax\n\t"
928 "subq %[tmp], %%rax\n\t"
929 "sbbq %%rbx, %%rdx\n\t" // rdx:rax contains 128-bit-difference "numerator*b.denominator - b.numerator*denominator"
930 "setnsb %%bh\n\t" // bh=1 if difference is non-negative, bh=0 otherwise
931 "orq %%rdx, %%rax\n\t"
932 "setnzb %%bl\n\t" // bl=1 if difference if non-zero, bl=0 if it is zero
933 "decb %%bh\n\t" // now bx=0x0000 if difference is zero, 0xff01 if it is negative, 0x0001 if it is positive (i.e., same sign as difference)
934 "shll $16, %%ebx\n\t" // ebx has same sign as difference
935 : "=&b"(result), [tmp] "=&r"(tmp), "=a"(dummy)
936 : "a"(denominator), [bn] "g"(b.numerator), [tn] "g"(numerator), [bd] "g"(b.denominator)
938 return result ? result ^ sign // if sign is +1, only bit 0 of result is inverted, which does not change the sign of result (and cannot result in zero)
939 // if sign is -1, all bits of result are inverted, which changes the sign of result (and again cannot result in zero)
944 return sign * Int128::mul(m_numerator, b.m_denominator).ucmp(Int128::mul(m_denominator, b.m_numerator));
949 int btConvexHullInternal::Rational128::compare(const Rational128& b) const
953 return sign - b.sign;
961 return -b.compare(sign * (int64_t) numerator.low);
964 Int128 nbdLow, nbdHigh, dbnLow, dbnHigh;
965 DMul<Int128, uint64_t>::mul(numerator, b.denominator, nbdLow, nbdHigh);
966 DMul<Int128, uint64_t>::mul(denominator, b.numerator, dbnLow, dbnHigh);
968 int cmp = nbdHigh.ucmp(dbnHigh);
973 return nbdLow.ucmp(dbnLow) * sign;
976 int btConvexHullInternal::Rational128::compare(int64_t b) const
980 int64_t a = sign * (int64_t) numerator.low;
981 return (a > b) ? 1 : (a < b) ? -1 : 0;
1003 return numerator.ucmp(denominator * b) * sign;
1007 btConvexHullInternal::Edge* btConvexHullInternal::newEdgePair(Vertex* from, Vertex* to)
1009 btAssert(from && to);
1010 Edge* e = edgePool.newObject();
1011 Edge* r = edgePool.newObject();
1014 e->copy = mergeStamp;
1015 r->copy = mergeStamp;
1021 if (usedEdgePairs > maxUsedEdgePairs)
1023 maxUsedEdgePairs = usedEdgePairs;
1028 bool btConvexHullInternal::mergeProjection(IntermediateHull& h0, IntermediateHull& h1, Vertex*& c0, Vertex*& c1)
1030 Vertex* v0 = h0.maxYx;
1031 Vertex* v1 = h1.minYx;
1032 if ((v0->point.x == v1->point.x) && (v0->point.y == v1->point.y))
1034 btAssert(v0->point.z < v1->point.z);
1035 Vertex* v1p = v1->prev;
1041 btAssert(v1->edges->next == v1->edges);
1042 v1 = v1->edges->target;
1043 btAssert(v1->edges->next == v1->edges);
1048 Vertex* v1n = v1->next;
1053 if ((v1n->point.x < v1p->point.x) || ((v1n->point.x == v1p->point.x) && (v1n->point.y < v1p->point.y)))
1064 if ((v1n->point.x > v1p->point.x) || ((v1n->point.x == v1p->point.x) && (v1n->point.y > v1p->point.y)))
1081 for (int side = 0; side <= 1; side++)
1083 int32_t dx = (v1->point.x - v0->point.x) * sign;
1088 int32_t dy = v1->point.y - v0->point.y;
1090 Vertex* w0 = side ? v0->next : v0->prev;
1093 int32_t dx0 = (w0->point.x - v0->point.x) * sign;
1094 int32_t dy0 = w0->point.y - v0->point.y;
1095 if ((dy0 <= 0) && ((dx0 == 0) || ((dx0 < 0) && (dy0 * dx <= dy * dx0))))
1098 dx = (v1->point.x - v0->point.x) * sign;
1103 Vertex* w1 = side ? v1->next : v1->prev;
1106 int32_t dx1 = (w1->point.x - v1->point.x) * sign;
1107 int32_t dy1 = w1->point.y - v1->point.y;
1108 int32_t dxn = (w1->point.x - v0->point.x) * sign;
1109 if ((dxn > 0) && (dy1 < 0) && ((dx1 == 0) || ((dx1 < 0) && (dy1 * dx < dy * dx1))))
1124 int32_t dy = v1->point.y - v0->point.y;
1126 Vertex* w1 = side ? v1->prev : v1->next;
1129 int32_t dx1 = (w1->point.x - v1->point.x) * sign;
1130 int32_t dy1 = w1->point.y - v1->point.y;
1131 if ((dy1 >= 0) && ((dx1 == 0) || ((dx1 < 0) && (dy1 * dx <= dy * dx1))))
1134 dx = (v1->point.x - v0->point.x) * sign;
1139 Vertex* w0 = side ? v0->prev : v0->next;
1142 int32_t dx0 = (w0->point.x - v0->point.x) * sign;
1143 int32_t dy0 = w0->point.y - v0->point.y;
1144 int32_t dxn = (v1->point.x - w0->point.x) * sign;
1145 if ((dxn < 0) && (dy0 > 0) && ((dx0 == 0) || ((dx0 < 0) && (dy0 * dx < dy * dx0))))
1158 int32_t x = v0->point.x;
1159 int32_t y0 = v0->point.y;
1162 while (((t = side ? w0->next : w0->prev) != v0) && (t->point.x == x) && (t->point.y <= y0))
1169 int32_t y1 = v1->point.y;
1171 while (((t = side ? w1->prev : w1->next) != v1) && (t->point.x == x) && (t->point.y >= y1))
1196 if (h1.minXy->point.x < h0.minXy->point.x)
1198 h0.minXy = h1.minXy;
1200 if (h1.maxXy->point.x >= h0.maxXy->point.x)
1202 h0.maxXy = h1.maxXy;
1205 h0.maxYx = h1.maxYx;
1213 void btConvexHullInternal::computeInternal(int start, int end, IntermediateHull& result)
1215 int n = end - start;
1219 result.minXy = NULL;
1220 result.maxXy = NULL;
1221 result.minYx = NULL;
1222 result.maxYx = NULL;
1226 Vertex* v = originalVertices[start];
1228 if (v->point != w->point)
1230 int32_t dx = v->point.x - w->point.x;
1231 int32_t dy = v->point.y - w->point.y;
1233 if ((dx == 0) && (dy == 0))
1235 if (v->point.z > w->point.z)
1241 btAssert(v->point.z < w->point.z);
1256 if ((dx < 0) || ((dx == 0) && (dy < 0)))
1267 if ((dy < 0) || ((dy == 0) && (dx < 0)))
1279 Edge* e = newEdgePair(v, w);
1290 // lint -fallthrough
1293 Vertex* v = originalVertices[start];
1307 int split0 = start + n / 2;
1308 Point32 p = originalVertices[split0-1]->point;
1309 int split1 = split0;
1310 while ((split1 < end) && (originalVertices[split1]->point == p))
1314 computeInternal(start, split0, result);
1315 IntermediateHull hull1;
1316 computeInternal(split1, end, hull1);
1317 #ifdef DEBUG_CONVEX_HULL
1318 printf("\n\nMerge\n");
1322 merge(result, hull1);
1323 #ifdef DEBUG_CONVEX_HULL
1324 printf("\n Result\n");
1329 #ifdef DEBUG_CONVEX_HULL
1330 void btConvexHullInternal::IntermediateHull::print()
1333 for (Vertex* v = minXy; v; )
1349 if (v->next->prev != v)
1351 printf(" Inconsistency");
1362 minXy->copy = (minXy->copy == -1) ? -2 : -1;
1363 minXy->printGraph();
1367 void btConvexHullInternal::Vertex::printGraph()
1370 printf("\nEdges\n");
1379 } while (e != edges);
1382 Vertex* v = e->target;
1383 if (v->copy != copy)
1389 } while (e != edges);
1394 btConvexHullInternal::Orientation btConvexHullInternal::getOrientation(const Edge* prev, const Edge* next, const Point32& s, const Point32& t)
1396 btAssert(prev->reverse->target == next->reverse->target);
1397 if (prev->next == next)
1399 if (prev->prev == next)
1401 Point64 n = t.cross(s);
1402 Point64 m = (*prev->target - *next->reverse->target).cross(*next->target - *next->reverse->target);
1403 btAssert(!m.isZero());
1404 int64_t dot = n.dot(m);
1406 return (dot > 0) ? COUNTER_CLOCKWISE : CLOCKWISE;
1408 return COUNTER_CLOCKWISE;
1410 else if (prev->prev == next)
1420 btConvexHullInternal::Edge* btConvexHullInternal::findMaxAngle(bool ccw, const Vertex* start, const Point32& s, const Point64& rxs, const Point64& sxrxs, Rational64& minCot)
1422 Edge* minEdge = NULL;
1424 #ifdef DEBUG_CONVEX_HULL
1425 printf("find max edge for %d\n", start->point.index);
1427 Edge* e = start->edges;
1432 if (e->copy > mergeStamp)
1434 Point32 t = *e->target - *start;
1435 Rational64 cot(t.dot(sxrxs), t.dot(rxs));
1436 #ifdef DEBUG_CONVEX_HULL
1437 printf(" Angle is %f (%d) for ", (float) btAtan(cot.toScalar()), (int) cot.isNaN());
1442 btAssert(ccw ? (t.dot(s) < 0) : (t.dot(s) > 0));
1447 if (minEdge == NULL)
1452 else if ((cmp = cot.compare(minCot)) < 0)
1457 else if ((cmp == 0) && (ccw == (getOrientation(minEdge, e, s, t) == COUNTER_CLOCKWISE)))
1462 #ifdef DEBUG_CONVEX_HULL
1467 } while (e != start->edges);
1472 void btConvexHullInternal::findEdgeForCoplanarFaces(Vertex* c0, Vertex* c1, Edge*& e0, Edge*& e1, Vertex* stop0, Vertex* stop1)
1476 Point32 et0 = start0 ? start0->target->point : c0->point;
1477 Point32 et1 = start1 ? start1->target->point : c1->point;
1478 Point32 s = c1->point - c0->point;
1479 Point64 normal = ((start0 ? start0 : start1)->target->point - c0->point).cross(s);
1480 int64_t dist = c0->point.dot(normal);
1481 btAssert(!start1 || (start1->target->point.dot(normal) == dist));
1482 Point64 perp = s.cross(normal);
1483 btAssert(!perp.isZero());
1485 #ifdef DEBUG_CONVEX_HULL
1486 printf(" Advancing %d %d (%p %p, %d %d)\n", c0->point.index, c1->point.index, start0, start1, start0 ? start0->target->point.index : -1, start1 ? start1->target->point.index : -1);
1489 int64_t maxDot0 = et0.dot(perp);
1492 while (e0->target != stop0)
1494 Edge* e = e0->reverse->prev;
1495 if (e->target->point.dot(normal) < dist)
1499 btAssert(e->target->point.dot(normal) == dist);
1500 if (e->copy == mergeStamp)
1504 int64_t dot = e->target->point.dot(perp);
1511 et0 = e->target->point;
1515 int64_t maxDot1 = et1.dot(perp);
1518 while (e1->target != stop1)
1520 Edge* e = e1->reverse->next;
1521 if (e->target->point.dot(normal) < dist)
1525 btAssert(e->target->point.dot(normal) == dist);
1526 if (e->copy == mergeStamp)
1530 int64_t dot = e->target->point.dot(perp);
1537 et1 = e->target->point;
1541 #ifdef DEBUG_CONVEX_HULL
1542 printf(" Starting at %d %d\n", et0.index, et1.index);
1545 int64_t dx = maxDot1 - maxDot0;
1550 int64_t dy = (et1 - et0).dot(s);
1552 if (e0 && (e0->target != stop0))
1554 Edge* f0 = e0->next->reverse;
1555 if (f0->copy > mergeStamp)
1557 int64_t dx0 = (f0->target->point - et0).dot(perp);
1558 int64_t dy0 = (f0->target->point - et0).dot(s);
1559 if ((dx0 == 0) ? (dy0 < 0) : ((dx0 < 0) && (Rational64(dy0, dx0).compare(Rational64(dy, dx)) >= 0)))
1561 et0 = f0->target->point;
1562 dx = (et1 - et0).dot(perp);
1563 e0 = (e0 == start0) ? NULL : f0;
1569 if (e1 && (e1->target != stop1))
1571 Edge* f1 = e1->reverse->next;
1572 if (f1->copy > mergeStamp)
1574 Point32 d1 = f1->target->point - et1;
1575 if (d1.dot(normal) == 0)
1577 int64_t dx1 = d1.dot(perp);
1578 int64_t dy1 = d1.dot(s);
1579 int64_t dxn = (f1->target->point - et0).dot(perp);
1580 if ((dxn > 0) && ((dx1 == 0) ? (dy1 < 0) : ((dx1 < 0) && (Rational64(dy1, dx1).compare(Rational64(dy, dx)) > 0))))
1583 et1 = e1->target->point;
1590 btAssert((e1 == start1) && (d1.dot(normal) < 0));
1602 int64_t dy = (et1 - et0).dot(s);
1604 if (e1 && (e1->target != stop1))
1606 Edge* f1 = e1->prev->reverse;
1607 if (f1->copy > mergeStamp)
1609 int64_t dx1 = (f1->target->point - et1).dot(perp);
1610 int64_t dy1 = (f1->target->point - et1).dot(s);
1611 if ((dx1 == 0) ? (dy1 > 0) : ((dx1 < 0) && (Rational64(dy1, dx1).compare(Rational64(dy, dx)) <= 0)))
1613 et1 = f1->target->point;
1614 dx = (et1 - et0).dot(perp);
1615 e1 = (e1 == start1) ? NULL : f1;
1621 if (e0 && (e0->target != stop0))
1623 Edge* f0 = e0->reverse->prev;
1624 if (f0->copy > mergeStamp)
1626 Point32 d0 = f0->target->point - et0;
1627 if (d0.dot(normal) == 0)
1629 int64_t dx0 = d0.dot(perp);
1630 int64_t dy0 = d0.dot(s);
1631 int64_t dxn = (et1 - f0->target->point).dot(perp);
1632 if ((dxn < 0) && ((dx0 == 0) ? (dy0 > 0) : ((dx0 < 0) && (Rational64(dy0, dx0).compare(Rational64(dy, dx)) < 0))))
1635 et0 = e0->target->point;
1642 btAssert((e0 == start0) && (d0.dot(normal) < 0));
1650 #ifdef DEBUG_CONVEX_HULL
1651 printf(" Advanced edges to %d %d\n", et0.index, et1.index);
1656 void btConvexHullInternal::merge(IntermediateHull& h0, IntermediateHull& h1)
1671 Edge* toPrev0 = NULL;
1672 Edge* firstNew0 = NULL;
1673 Edge* pendingHead0 = NULL;
1674 Edge* pendingTail0 = NULL;
1676 Edge* toPrev1 = NULL;
1677 Edge* firstNew1 = NULL;
1678 Edge* pendingHead1 = NULL;
1679 Edge* pendingTail1 = NULL;
1682 if (mergeProjection(h0, h1, c0, c1))
1684 Point32 s = *c1 - *c0;
1685 Point64 normal = Point32(0, 0, -1).cross(s);
1686 Point64 t = s.cross(normal);
1687 btAssert(!t.isZero());
1689 Edge* e = c0->edges;
1690 Edge* start0 = NULL;
1695 int64_t dot = (*e->target - *c0).dot(normal);
1697 if ((dot == 0) && ((*e->target - *c0).dot(t) > 0))
1699 if (!start0 || (getOrientation(start0, e, s, Point32(0, 0, -1)) == CLOCKWISE))
1705 } while (e != c0->edges);
1709 Edge* start1 = NULL;
1714 int64_t dot = (*e->target - *c1).dot(normal);
1716 if ((dot == 0) && ((*e->target - *c1).dot(t) > 0))
1718 if (!start1 || (getOrientation(start1, e, s, Point32(0, 0, -1)) == COUNTER_CLOCKWISE))
1724 } while (e != c1->edges);
1727 if (start0 || start1)
1729 findEdgeForCoplanarFaces(c0, c1, start0, start1, NULL, NULL);
1732 c0 = start0->target;
1736 c1 = start1->target;
1740 prevPoint = c1->point;
1745 prevPoint = c1->point;
1749 Vertex* first0 = c0;
1750 Vertex* first1 = c1;
1751 bool firstRun = true;
1755 Point32 s = *c1 - *c0;
1756 Point32 r = prevPoint - c0->point;
1757 Point64 rxs = r.cross(s);
1758 Point64 sxrxs = s.cross(rxs);
1760 #ifdef DEBUG_CONVEX_HULL
1761 printf("\n Checking %d %d\n", c0->point.index, c1->point.index);
1763 Rational64 minCot0(0, 0);
1764 Edge* min0 = findMaxAngle(false, c0, s, rxs, sxrxs, minCot0);
1765 Rational64 minCot1(0, 0);
1766 Edge* min1 = findMaxAngle(true, c1, s, rxs, sxrxs, minCot1);
1769 Edge* e = newEdgePair(c0, c1);
1780 int cmp = !min0 ? 1 : !min1 ? -1 : minCot0.compare(minCot1);
1781 #ifdef DEBUG_CONVEX_HULL
1782 printf(" -> Result %d\n", cmp);
1784 if (firstRun || ((cmp >= 0) ? !minCot1.isNegativeInfinity() : !minCot0.isNegativeInfinity()))
1786 Edge* e = newEdgePair(c0, c1);
1789 pendingTail0->prev = e;
1795 e->next = pendingTail0;
1801 pendingTail1->next = e;
1807 e->prev = pendingTail1;
1814 #ifdef DEBUG_CONVEX_HULL
1815 printf(" Found min edges to %d %d\n", e0 ? e0->target->point.index : -1, e1 ? e1->target->point.index : -1);
1820 findEdgeForCoplanarFaces(c0, c1, e0, e1, NULL, NULL);
1823 if ((cmp >= 0) && e1)
1827 for (Edge* e = toPrev1->next, *n = NULL; e != min1; e = n)
1838 toPrev1->link(pendingHead1);
1842 min1->prev->link(pendingHead1);
1843 firstNew1 = pendingHead1;
1845 pendingTail1->link(min1);
1846 pendingHead1 = NULL;
1847 pendingTail1 = NULL;
1854 prevPoint = c1->point;
1856 toPrev1 = e1->reverse;
1859 if ((cmp <= 0) && e0)
1863 for (Edge* e = toPrev0->prev, *n = NULL; e != min0; e = n)
1874 pendingHead0->link(toPrev0);
1878 pendingHead0->link(min0->next);
1879 firstNew0 = pendingHead0;
1881 min0->link(pendingTail0);
1882 pendingHead0 = NULL;
1883 pendingTail0 = NULL;
1890 prevPoint = c0->point;
1892 toPrev0 = e0->reverse;
1896 if ((c0 == first0) && (c1 == first1))
1898 if (toPrev0 == NULL)
1900 pendingHead0->link(pendingTail0);
1901 c0->edges = pendingTail0;
1905 for (Edge* e = toPrev0->prev, *n = NULL; e != firstNew0; e = n)
1912 pendingHead0->link(toPrev0);
1913 firstNew0->link(pendingTail0);
1917 if (toPrev1 == NULL)
1919 pendingTail1->link(pendingHead1);
1920 c1->edges = pendingTail1;
1924 for (Edge* e = toPrev1->next, *n = NULL; e != firstNew1; e = n)
1931 toPrev1->link(pendingHead1);
1932 pendingTail1->link(firstNew1);
1944 static bool pointCmp(const btConvexHullInternal::Point32& p, const btConvexHullInternal::Point32& q)
1946 return (p.y < q.y) || ((p.y == q.y) && ((p.x < q.x) || ((p.x == q.x) && (p.z < q.z))));
1949 void btConvexHullInternal::compute(const void* coords, bool doubleCoords, int stride, int count)
1951 btVector3 min(btScalar(1e30), btScalar(1e30), btScalar(1e30)), max(btScalar(-1e30), btScalar(-1e30), btScalar(-1e30));
1952 const char* ptr = (const char*) coords;
1955 for (int i = 0; i < count; i++)
1957 const double* v = (const double*) ptr;
1958 btVector3 p((btScalar) v[0], (btScalar) v[1], (btScalar) v[2]);
1966 for (int i = 0; i < count; i++)
1968 const float* v = (const float*) ptr;
1969 btVector3 p(v[0], v[1], v[2]);
1976 btVector3 s = max - min;
1977 maxAxis = s.maxAxis();
1978 minAxis = s.minAxis();
1979 if (minAxis == maxAxis)
1981 minAxis = (maxAxis + 1) % 3;
1983 medAxis = 3 - maxAxis - minAxis;
1985 s /= btScalar(10216);
1986 if (((medAxis + 1) % 3) != maxAxis)
1994 s[0] = btScalar(1) / s[0];
1998 s[1] = btScalar(1) / s[1];
2002 s[2] = btScalar(1) / s[2];
2005 center = (min + max) * btScalar(0.5);
2007 btAlignedObjectArray<Point32> points;
2008 points.resize(count);
2009 ptr = (const char*) coords;
2012 for (int i = 0; i < count; i++)
2014 const double* v = (const double*) ptr;
2015 btVector3 p((btScalar) v[0], (btScalar) v[1], (btScalar) v[2]);
2017 p = (p - center) * s;
2018 points[i].x = (int32_t) p[medAxis];
2019 points[i].y = (int32_t) p[maxAxis];
2020 points[i].z = (int32_t) p[minAxis];
2021 points[i].index = i;
2026 for (int i = 0; i < count; i++)
2028 const float* v = (const float*) ptr;
2029 btVector3 p(v[0], v[1], v[2]);
2031 p = (p - center) * s;
2032 points[i].x = (int32_t) p[medAxis];
2033 points[i].y = (int32_t) p[maxAxis];
2034 points[i].z = (int32_t) p[minAxis];
2035 points[i].index = i;
2038 points.quickSort(pointCmp);
2041 vertexPool.setArraySize(count);
2042 originalVertices.resize(count);
2043 for (int i = 0; i < count; i++)
2045 Vertex* v = vertexPool.newObject();
2047 v->point = points[i];
2049 originalVertices[i] = v;
2055 edgePool.setArraySize(6 * count);
2058 maxUsedEdgePairs = 0;
2062 IntermediateHull hull;
2063 computeInternal(0, count, hull);
2064 vertexList = hull.minXy;
2065 #ifdef DEBUG_CONVEX_HULL
2066 printf("max. edges %d (3v = %d)", maxUsedEdgePairs, 3 * count);
2070 btVector3 btConvexHullInternal::toBtVector(const Point32& v)
2073 p[medAxis] = btScalar(v.x);
2074 p[maxAxis] = btScalar(v.y);
2075 p[minAxis] = btScalar(v.z);
2079 btVector3 btConvexHullInternal::getBtNormal(Face* face)
2081 return toBtVector(face->dir0).cross(toBtVector(face->dir1)).normalized();
2084 btVector3 btConvexHullInternal::getCoordinates(const Vertex* v)
2087 p[medAxis] = v->xvalue();
2088 p[maxAxis] = v->yvalue();
2089 p[minAxis] = v->zvalue();
2090 return p * scaling + center;
2093 btScalar btConvexHullInternal::shrink(btScalar amount, btScalar clampAmount)
2099 int stamp = --mergeStamp;
2100 btAlignedObjectArray<Vertex*> stack;
2101 vertexList->copy = stamp;
2102 stack.push_back(vertexList);
2103 btAlignedObjectArray<Face*> faces;
2105 Point32 ref = vertexList->point;
2106 Int128 hullCenterX(0, 0);
2107 Int128 hullCenterY(0, 0);
2108 Int128 hullCenterZ(0, 0);
2109 Int128 volume(0, 0);
2111 while (stack.size() > 0)
2113 Vertex* v = stack[stack.size() - 1];
2120 if (e->target->copy != stamp)
2122 e->target->copy = stamp;
2123 stack.push_back(e->target);
2125 if (e->copy != stamp)
2127 Face* face = facePool.newObject();
2128 face->init(e->target, e->reverse->prev->target, v);
2129 faces.push_back(face);
2138 int64_t vol = (v->point - ref).dot((a->point - ref).cross(b->point - ref));
2140 Point32 c = v->point + a->point + b->point + ref;
2141 hullCenterX += vol * c.x;
2142 hullCenterY += vol * c.y;
2143 hullCenterZ += vol * c.z;
2147 btAssert(f->copy != stamp);
2154 f = f->reverse->prev;
2158 } while (e != v->edges);
2162 if (volume.getSign() <= 0)
2167 btVector3 hullCenter;
2168 hullCenter[medAxis] = hullCenterX.toScalar();
2169 hullCenter[maxAxis] = hullCenterY.toScalar();
2170 hullCenter[minAxis] = hullCenterZ.toScalar();
2171 hullCenter /= 4 * volume.toScalar();
2172 hullCenter *= scaling;
2174 int faceCount = faces.size();
2176 if (clampAmount > 0)
2178 btScalar minDist = SIMD_INFINITY;
2179 for (int i = 0; i < faceCount; i++)
2181 btVector3 normal = getBtNormal(faces[i]);
2182 btScalar dist = normal.dot(toBtVector(faces[i]->origin) - hullCenter);
2194 amount = btMin(amount, minDist * clampAmount);
2197 unsigned int seed = 243703;
2198 for (int i = 0; i < faceCount; i++, seed = 1664525 * seed + 1013904223)
2200 btSwap(faces[i], faces[seed % faceCount]);
2203 for (int i = 0; i < faceCount; i++)
2205 if (!shiftFace(faces[i], amount, stack))
2214 bool btConvexHullInternal::shiftFace(Face* face, btScalar amount, btAlignedObjectArray<Vertex*> stack)
2216 btVector3 origShift = getBtNormal(face) * -amount;
2217 if (scaling[0] != 0)
2219 origShift[0] /= scaling[0];
2221 if (scaling[1] != 0)
2223 origShift[1] /= scaling[1];
2225 if (scaling[2] != 0)
2227 origShift[2] /= scaling[2];
2229 Point32 shift((int32_t) origShift[medAxis], (int32_t) origShift[maxAxis], (int32_t) origShift[minAxis]);
2234 Point64 normal = face->getNormal();
2235 #ifdef DEBUG_CONVEX_HULL
2236 printf("\nShrinking face (%d %d %d) (%d %d %d) (%d %d %d) by (%d %d %d)\n",
2237 face->origin.x, face->origin.y, face->origin.z, face->dir0.x, face->dir0.y, face->dir0.z, face->dir1.x, face->dir1.y, face->dir1.z, shift.x, shift.y, shift.z);
2239 int64_t origDot = face->origin.dot(normal);
2240 Point32 shiftedOrigin = face->origin + shift;
2241 int64_t shiftedDot = shiftedOrigin.dot(normal);
2242 btAssert(shiftedDot <= origDot);
2243 if (shiftedDot >= origDot)
2248 Edge* intersection = NULL;
2250 Edge* startEdge = face->nearbyVertex->edges;
2251 #ifdef DEBUG_CONVEX_HULL
2252 printf("Start edge is ");
2254 printf(", normal is (%lld %lld %lld), shifted dot is %lld\n", normal.x, normal.y, normal.z, shiftedDot);
2256 Rational128 optDot = face->nearbyVertex->dot(normal);
2257 int cmp = optDot.compare(shiftedDot);
2258 #ifdef SHOW_ITERATIONS
2263 Edge* e = startEdge;
2266 #ifdef SHOW_ITERATIONS
2269 Rational128 dot = e->target->dot(normal);
2270 btAssert(dot.compare(origDot) <= 0);
2271 #ifdef DEBUG_CONVEX_HULL
2272 printf("Moving downwards, edge is ");
2274 printf(", dot is %f (%f %lld)\n", (float) dot.toScalar(), (float) optDot.toScalar(), shiftedDot);
2276 if (dot.compare(optDot) < 0)
2278 int c = dot.compare(shiftedDot);
2290 } while (e != startEdge);
2299 Edge* e = startEdge;
2302 #ifdef SHOW_ITERATIONS
2305 Rational128 dot = e->target->dot(normal);
2306 btAssert(dot.compare(origDot) <= 0);
2307 #ifdef DEBUG_CONVEX_HULL
2308 printf("Moving upwards, edge is ");
2310 printf(", dot is %f (%f %lld)\n", (float) dot.toScalar(), (float) optDot.toScalar(), shiftedDot);
2312 if (dot.compare(optDot) > 0)
2314 cmp = dot.compare(shiftedDot);
2325 } while (e != startEdge);
2333 #ifdef SHOW_ITERATIONS
2334 printf("Needed %d iterations to find initial intersection\n", n);
2339 Edge* e = intersection->reverse->next;
2340 #ifdef SHOW_ITERATIONS
2343 while (e->target->dot(normal).compare(shiftedDot) <= 0)
2345 #ifdef SHOW_ITERATIONS
2349 if (e == intersection->reverse)
2353 #ifdef DEBUG_CONVEX_HULL
2354 printf("Checking for outwards edge, current edge is ");
2359 #ifdef SHOW_ITERATIONS
2360 printf("Needed %d iterations to check for complete containment\n", n);
2364 Edge* firstIntersection = NULL;
2365 Edge* faceEdge = NULL;
2366 Edge* firstFaceEdge = NULL;
2368 #ifdef SHOW_ITERATIONS
2373 #ifdef SHOW_ITERATIONS
2376 #ifdef DEBUG_CONVEX_HULL
2377 printf("Intersecting edge is ");
2378 intersection->print();
2383 Edge* e = intersection->reverse->next;
2385 #ifdef SHOW_ITERATIONS
2390 #ifdef SHOW_ITERATIONS
2393 if (e->target->dot(normal).compare(shiftedDot) >= 0)
2397 intersection = e->reverse;
2404 #ifdef SHOW_ITERATIONS
2405 printf("Needed %d iterations to advance intersection\n", n);
2409 #ifdef DEBUG_CONVEX_HULL
2410 printf("Advanced intersecting edge to ");
2411 intersection->print();
2412 printf(", cmp = %d\n", cmp);
2415 if (!firstIntersection)
2417 firstIntersection = intersection;
2419 else if (intersection == firstIntersection)
2425 Edge* prevIntersection = intersection;
2426 Edge* prevFaceEdge = faceEdge;
2428 Edge* e = intersection->reverse;
2429 #ifdef SHOW_ITERATIONS
2434 #ifdef SHOW_ITERATIONS
2437 e = e->reverse->prev;
2438 btAssert(e != intersection->reverse);
2439 cmp = e->target->dot(normal).compare(shiftedDot);
2440 #ifdef DEBUG_CONVEX_HULL
2441 printf("Testing edge ");
2443 printf(" -> cmp = %d\n", cmp);
2451 #ifdef SHOW_ITERATIONS
2452 printf("Needed %d iterations to find other intersection of face\n", n);
2457 Vertex* removed = intersection->target;
2458 e = intersection->reverse;
2461 removed->edges = NULL;
2465 removed->edges = e->prev;
2466 e->prev->link(e->next);
2469 #ifdef DEBUG_CONVEX_HULL
2470 printf("1: Removed part contains (%d %d %d)\n", removed->point.x, removed->point.y, removed->point.z);
2473 Point64 n0 = intersection->face->getNormal();
2474 Point64 n1 = intersection->reverse->face->getNormal();
2475 int64_t m00 = face->dir0.dot(n0);
2476 int64_t m01 = face->dir1.dot(n0);
2477 int64_t m10 = face->dir0.dot(n1);
2478 int64_t m11 = face->dir1.dot(n1);
2479 int64_t r0 = (intersection->face->origin - shiftedOrigin).dot(n0);
2480 int64_t r1 = (intersection->reverse->face->origin - shiftedOrigin).dot(n1);
2481 Int128 det = Int128::mul(m00, m11) - Int128::mul(m01, m10);
2482 btAssert(det.getSign() != 0);
2483 Vertex* v = vertexPool.newObject();
2484 v->point.index = -1;
2486 v->point128 = PointR128(Int128::mul(face->dir0.x * r0, m11) - Int128::mul(face->dir0.x * r1, m01)
2487 + Int128::mul(face->dir1.x * r1, m00) - Int128::mul(face->dir1.x * r0, m10) + det * shiftedOrigin.x,
2488 Int128::mul(face->dir0.y * r0, m11) - Int128::mul(face->dir0.y * r1, m01)
2489 + Int128::mul(face->dir1.y * r1, m00) - Int128::mul(face->dir1.y * r0, m10) + det * shiftedOrigin.y,
2490 Int128::mul(face->dir0.z * r0, m11) - Int128::mul(face->dir0.z * r1, m01)
2491 + Int128::mul(face->dir1.z * r1, m00) - Int128::mul(face->dir1.z * r0, m10) + det * shiftedOrigin.z,
2493 v->point.x = (int32_t) v->point128.xvalue();
2494 v->point.y = (int32_t) v->point128.yvalue();
2495 v->point.z = (int32_t) v->point128.zvalue();
2496 intersection->target = v;
2500 stack.push_back(removed);
2501 stack.push_back(NULL);
2504 if (cmp || prevCmp || (prevIntersection->reverse->next->target != intersection->target))
2506 faceEdge = newEdgePair(prevIntersection->target, intersection->target);
2509 faceEdge->link(prevIntersection->reverse->next);
2511 if ((prevCmp == 0) || prevFaceEdge)
2513 prevIntersection->reverse->link(faceEdge);
2517 intersection->reverse->prev->link(faceEdge->reverse);
2519 faceEdge->reverse->link(intersection->reverse);
2523 faceEdge = prevIntersection->reverse->next;
2530 faceEdge->link(prevFaceEdge->reverse);
2532 else if (faceEdge != prevFaceEdge->reverse)
2534 stack.push_back(prevFaceEdge->target);
2535 while (faceEdge->next != prevFaceEdge->reverse)
2537 Vertex* removed = faceEdge->next->target;
2538 removeEdgePair(faceEdge->next);
2539 stack.push_back(removed);
2540 #ifdef DEBUG_CONVEX_HULL
2541 printf("2: Removed part contains (%d %d %d)\n", removed->point.x, removed->point.y, removed->point.z);
2544 stack.push_back(NULL);
2547 faceEdge->face = face;
2548 faceEdge->reverse->face = intersection->face;
2552 firstFaceEdge = faceEdge;
2555 #ifdef SHOW_ITERATIONS
2556 printf("Needed %d iterations to process all intersections\n", m);
2561 firstFaceEdge->reverse->target = faceEdge->target;
2562 firstIntersection->reverse->link(firstFaceEdge);
2563 firstFaceEdge->link(faceEdge->reverse);
2565 else if (firstFaceEdge != faceEdge->reverse)
2567 stack.push_back(faceEdge->target);
2568 while (firstFaceEdge->next != faceEdge->reverse)
2570 Vertex* removed = firstFaceEdge->next->target;
2571 removeEdgePair(firstFaceEdge->next);
2572 stack.push_back(removed);
2573 #ifdef DEBUG_CONVEX_HULL
2574 printf("3: Removed part contains (%d %d %d)\n", removed->point.x, removed->point.y, removed->point.z);
2577 stack.push_back(NULL);
2580 btAssert(stack.size() > 0);
2581 vertexList = stack[0];
2583 #ifdef DEBUG_CONVEX_HULL
2584 printf("Removing part\n");
2586 #ifdef SHOW_ITERATIONS
2590 while (pos < stack.size())
2592 int end = stack.size();
2595 Vertex* kept = stack[pos++];
2596 #ifdef DEBUG_CONVEX_HULL
2599 bool deeper = false;
2601 while ((removed = stack[pos++]) != NULL)
2603 #ifdef SHOW_ITERATIONS
2606 kept->receiveNearbyFaces(removed);
2607 while (removed->edges)
2612 stack.push_back(kept);
2614 stack.push_back(removed->edges->target);
2615 removeEdgePair(removed->edges);
2620 stack.push_back(NULL);
2624 #ifdef SHOW_ITERATIONS
2625 printf("Needed %d iterations to remove part\n", n);
2629 face->origin = shiftedOrigin;
2635 static int getVertexCopy(btConvexHullInternal::Vertex* vertex, btAlignedObjectArray<btConvexHullInternal::Vertex*>& vertices)
2637 int index = vertex->copy;
2640 index = vertices.size();
2641 vertex->copy = index;
2642 vertices.push_back(vertex);
2643 #ifdef DEBUG_CONVEX_HULL
2644 printf("Vertex %d gets index *%d\n", vertex->point.index, index);
2650 btScalar btConvexHullComputer::compute(const void* coords, bool doubleCoords, int stride, int count, btScalar shrink, btScalar shrinkClamp)
2660 btConvexHullInternal hull;
2661 hull.compute(coords, doubleCoords, stride, count);
2664 if ((shrink > 0) && ((shift = hull.shrink(shrink, shrinkClamp)) < 0))
2676 btAlignedObjectArray<btConvexHullInternal::Vertex*> oldVertices;
2677 getVertexCopy(hull.vertexList, oldVertices);
2679 while (copied < oldVertices.size())
2681 btConvexHullInternal::Vertex* v = oldVertices[copied];
2682 vertices.push_back(hull.getCoordinates(v));
2683 btConvexHullInternal::Edge* firstEdge = v->edges;
2688 btConvexHullInternal::Edge* e = firstEdge;
2693 int s = edges.size();
2694 edges.push_back(Edge());
2695 edges.push_back(Edge());
2696 Edge* c = &edges[s];
2697 Edge* r = &edges[s + 1];
2699 e->reverse->copy = s + 1;
2702 c->targetVertex = getVertexCopy(e->target, oldVertices);
2703 r->targetVertex = copied;
2704 #ifdef DEBUG_CONVEX_HULL
2705 printf(" CREATE: Vertex *%d has edge to *%d\n", copied, c->getTargetVertex());
2710 edges[e->copy].next = prevCopy - e->copy;
2714 firstCopy = e->copy;
2718 } while (e != firstEdge);
2719 edges[firstCopy].next = prevCopy - firstCopy;
2724 for (int i = 0; i < copied; i++)
2726 btConvexHullInternal::Vertex* v = oldVertices[i];
2727 btConvexHullInternal::Edge* firstEdge = v->edges;
2730 btConvexHullInternal::Edge* e = firstEdge;
2735 #ifdef DEBUG_CONVEX_HULL
2736 printf("Vertex *%d has edge to *%d\n", i, edges[e->copy].getTargetVertex());
2738 faces.push_back(e->copy);
2739 btConvexHullInternal::Edge* f = e;
2742 #ifdef DEBUG_CONVEX_HULL
2743 printf(" Face *%d\n", edges[f->copy].getTargetVertex());
2746 f = f->reverse->prev;
2750 } while (e != firstEdge);