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 "b3ConvexHullComputer.h"
18 #include "Bullet3Common/b3AlignedObjectArray.h"
19 #include "Bullet3Common/b3MinMax.h"
20 #include "Bullet3Common/b3Vector3.h"
24 typedef int32_t btInt32_t;
25 typedef int64_t btInt64_t;
26 typedef uint32_t btUint32_t;
27 typedef uint64_t btUint64_t;
28 #elif defined(_MSC_VER)
29 typedef __int32 btInt32_t;
30 typedef __int64 btInt64_t;
31 typedef unsigned __int32 btUint32_t;
32 typedef unsigned __int64 btUint64_t;
34 typedef int btInt32_t;
35 typedef long long int btInt64_t;
36 typedef unsigned int btUint32_t;
37 typedef unsigned long long int btUint64_t;
40 //The definition of USE_X86_64_ASM is moved into the build system. You can enable it manually by commenting out the following lines
41 //#if (defined(__GNUC__) && defined(__x86_64__) && !defined(__ICL)) // || (defined(__ICL) && defined(_M_X64)) bug in Intel compiler, disable inline assembly
42 // #define USE_X86_64_ASM
45 //#define DEBUG_CONVEX_HULL
46 //#define SHOW_ITERATIONS
48 #if defined(DEBUG_CONVEX_HULL) || defined(SHOW_ITERATIONS)
52 // Convex hull implementation based on Preparata and Hong
53 // Ole Kniemeyer, MAXON Computer GmbH
54 class b3ConvexHullInternal
64 Point64(btInt64_t x, btInt64_t y, btInt64_t z) : x(x), y(y), z(z)
70 return (x == 0) && (y == 0) && (z == 0);
73 btInt64_t dot(const Point64& b) const
75 return x * b.x + y * b.y + z * b.z;
91 Point32(btInt32_t x, btInt32_t y, btInt32_t z) : x(x), y(y), z(z), index(-1)
95 bool operator==(const Point32& b) const
97 return (x == b.x) && (y == b.y) && (z == b.z);
100 bool operator!=(const Point32& b) const
102 return (x != b.x) || (y != b.y) || (z != b.z);
107 return (x == 0) && (y == 0) && (z == 0);
110 Point64 cross(const Point32& b) const
112 return Point64(y * b.z - z * b.y, z * b.x - x * b.z, x * b.y - y * b.x);
115 Point64 cross(const Point64& b) const
117 return Point64(y * b.z - z * b.y, z * b.x - x * b.z, x * b.y - y * b.x);
120 btInt64_t dot(const Point32& b) const
122 return x * b.x + y * b.y + z * b.z;
125 btInt64_t dot(const Point64& b) const
127 return x * b.x + y * b.y + z * b.z;
130 Point32 operator+(const Point32& b) const
132 return Point32(x + b.x, y + b.y, z + b.z);
135 Point32 operator-(const Point32& b) const
137 return Point32(x - b.x, y - b.y, z - b.z);
151 Int128(btUint64_t low, btUint64_t high) : low(low), high(high)
155 Int128(btUint64_t low) : low(low), high(0)
159 Int128(btInt64_t value) : low(value), high((value >= 0) ? 0 : (btUint64_t)-1LL)
163 static Int128 mul(btInt64_t a, btInt64_t b);
165 static Int128 mul(btUint64_t a, btUint64_t b);
167 Int128 operator-() const
169 return Int128((btUint64_t) - (btInt64_t)low, ~high + (low == 0));
172 Int128 operator+(const Int128& b) const
174 #ifdef USE_X86_64_ASM
177 "addq %[bl], %[rl]\n\t"
178 "adcq %[bh], %[rh]\n\t"
179 : [rl] "=r"(result.low), [rh] "=r"(result.high)
180 : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high)
184 btUint64_t lo = low + b.low;
185 return Int128(lo, high + b.high + (lo < low));
189 Int128 operator-(const Int128& b) const
191 #ifdef USE_X86_64_ASM
194 "subq %[bl], %[rl]\n\t"
195 "sbbq %[bh], %[rh]\n\t"
196 : [rl] "=r"(result.low), [rh] "=r"(result.high)
197 : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high)
205 Int128& operator+=(const Int128& b)
207 #ifdef USE_X86_64_ASM
209 "addq %[bl], %[rl]\n\t"
210 "adcq %[bh], %[rh]\n\t"
211 : [rl] "=r"(low), [rh] "=r"(high)
212 : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high)
215 btUint64_t lo = low + b.low;
235 Int128 operator*(btInt64_t b) const;
237 b3Scalar toScalar() const
239 return ((btInt64_t)high >= 0) ? b3Scalar(high) * (b3Scalar(0x100000000LL) * b3Scalar(0x100000000LL)) + b3Scalar(low)
240 : -(-*this).toScalar();
245 return ((btInt64_t)high < 0) ? -1 : (high || low) ? 1 : 0;
248 bool operator<(const Int128& b) const
250 return (high < b.high) || ((high == b.high) && (low < b.low));
253 int ucmp(const Int128& b) const
278 btUint64_t m_numerator;
279 btUint64_t m_denominator;
283 Rational64(btInt64_t numerator, btInt64_t denominator)
288 m_numerator = (btUint64_t)numerator;
290 else if (numerator < 0)
293 m_numerator = (btUint64_t)-numerator;
302 m_denominator = (btUint64_t)denominator;
304 else if (denominator < 0)
307 m_denominator = (btUint64_t)-denominator;
315 bool isNegativeInfinity() const
317 return (sign < 0) && (m_denominator == 0);
322 return (sign == 0) && (m_denominator == 0);
325 int compare(const Rational64& b) const;
327 b3Scalar toScalar() const
329 return sign * ((m_denominator == 0) ? B3_INFINITY : (b3Scalar)m_numerator / m_denominator);
342 Rational128(btInt64_t value)
347 this->numerator = value;
352 this->numerator = -value;
357 this->numerator = (btUint64_t)0;
359 this->denominator = (btUint64_t)1;
363 Rational128(const Int128& numerator, const Int128& denominator)
365 sign = numerator.getSign();
368 this->numerator = numerator;
372 this->numerator = -numerator;
374 int dsign = denominator.getSign();
377 this->denominator = denominator;
382 this->denominator = -denominator;
387 int compare(const Rational128& b) const;
389 int compare(btInt64_t b) const;
391 b3Scalar toScalar() const
393 return sign * ((denominator.getSign() == 0) ? B3_INFINITY : numerator.toScalar() / denominator.toScalar());
409 PointR128(Int128 x, Int128 y, Int128 z, Int128 denominator) : x(x), y(y), z(z), denominator(denominator)
413 b3Scalar xvalue() const
415 return x.toScalar() / denominator.toScalar();
418 b3Scalar yvalue() const
420 return y.toScalar() / denominator.toScalar();
423 b3Scalar zvalue() const
425 return z.toScalar() / denominator.toScalar();
438 Face* firstNearbyFace;
439 Face* lastNearbyFace;
444 Vertex() : next(NULL), prev(NULL), edges(NULL), firstNearbyFace(NULL), lastNearbyFace(NULL), copy(-1)
448 #ifdef DEBUG_CONVEX_HULL
451 b3Printf("V%d (%d, %d, %d)", point.index, point.x, point.y, point.z);
457 Point32 operator-(const Vertex& b) const
459 return point - b.point;
462 Rational128 dot(const Point64& b) const
464 return (point.index >= 0) ? Rational128(point.dot(b))
465 : Rational128(point128.x * b.x + point128.y * b.y + point128.z * b.z, point128.denominator);
468 b3Scalar xvalue() const
470 return (point.index >= 0) ? b3Scalar(point.x) : point128.xvalue();
473 b3Scalar yvalue() const
475 return (point.index >= 0) ? b3Scalar(point.y) : point128.yvalue();
478 b3Scalar zvalue() const
480 return (point.index >= 0) ? b3Scalar(point.z) : point128.zvalue();
483 void receiveNearbyFaces(Vertex* src)
487 lastNearbyFace->nextWithSameNearbyVertex = src->firstNearbyFace;
491 firstNearbyFace = src->firstNearbyFace;
493 if (src->lastNearbyFace)
495 lastNearbyFace = src->lastNearbyFace;
497 for (Face* f = src->firstNearbyFace; f; f = f->nextWithSameNearbyVertex)
499 b3Assert(f->nearbyVertex == src);
500 f->nearbyVertex = this;
502 src->firstNearbyFace = NULL;
503 src->lastNearbyFace = NULL;
528 b3Assert(reverse->target == n->reverse->target);
533 #ifdef DEBUG_CONVEX_HULL
536 b3Printf("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>
583 static btUint32_t high(btUint64_t value)
585 return (btUint32_t)(value >> 32);
588 static btUint32_t low(btUint64_t value)
590 return (btUint32_t)value;
593 static btUint64_t mul(btUint32_t a, btUint32_t b)
595 return (btUint64_t)a * (btUint64_t)b;
598 static void shlHalf(btUint64_t& value)
603 static btUint64_t high(Int128 value)
608 static btUint64_t low(Int128 value)
613 static Int128 mul(btUint64_t a, btUint64_t b)
615 return Int128::mul(a, b);
618 static void shlHalf(Int128& value)
620 value.high = value.low;
625 static void mul(UWord a, UWord b, UWord& resLow, UWord& resHigh)
627 UWord p00 = mul(low(a), low(b));
628 UWord p01 = mul(low(a), high(b));
629 UWord p10 = mul(high(a), low(b));
630 UWord p11 = mul(high(a), high(b));
631 UWord p0110 = UWord(low(p01)) + UWord(low(p10));
647 class IntermediateHull
655 IntermediateHull() : minXy(NULL), maxXy(NULL), minYx(NULL), maxYx(NULL)
669 template <typename T>
679 PoolArray(int size) : size(size), next(NULL)
681 array = (T*)b3AlignedAlloc(sizeof(T) * size, 16);
686 b3AlignedFree(array);
692 for (int i = 0; i < size; i++, o++)
694 o->next = (i + 1 < size) ? o + 1 : NULL;
700 template <typename T>
704 PoolArray<T>* arrays;
705 PoolArray<T>* nextArray;
710 Pool() : arrays(NULL), nextArray(NULL), freeObjects(NULL), arraySize(256)
718 PoolArray<T>* p = arrays;
731 void setArraySize(int arraySize)
733 this->arraySize = arraySize;
741 PoolArray<T>* p = nextArray;
748 p = new (b3AlignedAlloc(sizeof(PoolArray<T>), 16)) PoolArray<T>(arraySize);
754 freeObjects = o->next;
758 void freeObject(T* object)
761 object->next = freeObjects;
762 freeObjects = object;
768 Pool<Vertex> vertexPool;
771 b3AlignedObjectArray<Vertex*> originalVertices;
777 int maxUsedEdgePairs;
779 static Orientation getOrientation(const Edge* prev, const Edge* next, const Point32& s, const Point32& t);
780 Edge* findMaxAngle(bool ccw, const Vertex* start, const Point32& s, const Point64& rxs, const Point64& sxrxs, Rational64& minCot);
781 void findEdgeForCoplanarFaces(Vertex* c0, Vertex* c1, Edge*& e0, Edge*& e1, Vertex* stop0, Vertex* stop1);
783 Edge* newEdgePair(Vertex* from, Vertex* to);
785 void removeEdgePair(Edge* edge)
787 Edge* n = edge->next;
788 Edge* r = edge->reverse;
790 b3Assert(edge->target && r->target);
794 n->prev = edge->prev;
795 edge->prev->next = n;
796 r->target->edges = n;
800 r->target->edges = NULL;
809 edge->target->edges = n;
813 edge->target->edges = NULL;
816 edgePool.freeObject(edge);
817 edgePool.freeObject(r);
821 void computeInternal(int start, int end, IntermediateHull& result);
823 bool mergeProjection(IntermediateHull& h0, IntermediateHull& h1, Vertex*& c0, Vertex*& c1);
825 void merge(IntermediateHull& h0, IntermediateHull& h1);
827 b3Vector3 toBtVector(const Point32& v);
829 b3Vector3 getBtNormal(Face* face);
831 bool shiftFace(Face* face, b3Scalar amount, b3AlignedObjectArray<Vertex*> stack);
836 void compute(const void* coords, bool doubleCoords, int stride, int count);
838 b3Vector3 getCoordinates(const Vertex* v);
840 b3Scalar shrink(b3Scalar amount, b3Scalar clampAmount);
843 b3ConvexHullInternal::Int128 b3ConvexHullInternal::Int128::operator*(btInt64_t b) const
845 bool negative = (btInt64_t)high < 0;
846 Int128 a = negative ? -*this : *this;
849 negative = !negative;
852 Int128 result = mul(a.low, (btUint64_t)b);
853 result.high += a.high * (btUint64_t)b;
854 return negative ? -result : result;
857 b3ConvexHullInternal::Int128 b3ConvexHullInternal::Int128::mul(btInt64_t a, btInt64_t b)
861 #ifdef USE_X86_64_ASM
863 : "=a"(result.low), "=d"(result.high)
869 bool negative = a < 0;
876 negative = !negative;
879 DMul<btUint64_t, btUint32_t>::mul((btUint64_t)a, (btUint64_t)b, result.low, result.high);
880 return negative ? -result : result;
884 b3ConvexHullInternal::Int128 b3ConvexHullInternal::Int128::mul(btUint64_t a, btUint64_t b)
888 #ifdef USE_X86_64_ASM
890 : "=a"(result.low), "=d"(result.high)
895 DMul<btUint64_t, btUint32_t>::mul(a, b, result.low, result.high);
901 int b3ConvexHullInternal::Rational64::compare(const Rational64& b) const
905 return sign - b.sign;
912 // return (numerator * b.denominator > b.numerator * denominator) ? sign : (numerator * b.denominator < b.numerator * denominator) ? -sign : 0;
914 #ifdef USE_X86_64_ASM
921 "movq %%rax, %[tmp]\n\t"
922 "movq %%rdx, %%rbx\n\t"
923 "movq %[tn], %%rax\n\t"
925 "subq %[tmp], %%rax\n\t"
926 "sbbq %%rbx, %%rdx\n\t" // rdx:rax contains 128-bit-difference "numerator*b.denominator - b.numerator*denominator"
927 "setnsb %%bh\n\t" // bh=1 if difference is non-negative, bh=0 otherwise
928 "orq %%rdx, %%rax\n\t"
929 "setnzb %%bl\n\t" // bl=1 if difference if non-zero, bl=0 if it is zero
930 "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)
931 "shll $16, %%ebx\n\t" // ebx has same sign as difference
932 : "=&b"(result), [tmp] "=&r"(tmp), "=a"(dummy)
933 : "a"(denominator), [bn] "g"(b.numerator), [tn] "g"(numerator), [bd] "g"(b.denominator)
935 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)
936 // if sign is -1, all bits of result are inverted, which changes the sign of result (and again cannot result in zero)
941 return sign * Int128::mul(m_numerator, b.m_denominator).ucmp(Int128::mul(m_denominator, b.m_numerator));
946 int b3ConvexHullInternal::Rational128::compare(const Rational128& b) const
950 return sign - b.sign;
958 return -b.compare(sign * (btInt64_t)numerator.low);
961 Int128 nbdLow, nbdHigh, dbnLow, dbnHigh;
962 DMul<Int128, btUint64_t>::mul(numerator, b.denominator, nbdLow, nbdHigh);
963 DMul<Int128, btUint64_t>::mul(denominator, b.numerator, dbnLow, dbnHigh);
965 int cmp = nbdHigh.ucmp(dbnHigh);
970 return nbdLow.ucmp(dbnLow) * sign;
973 int b3ConvexHullInternal::Rational128::compare(btInt64_t b) const
977 btInt64_t a = sign * (btInt64_t)numerator.low;
978 return (a > b) ? 1 : (a < b) ? -1 : 0;
1000 return numerator.ucmp(denominator * b) * sign;
1003 b3ConvexHullInternal::Edge* b3ConvexHullInternal::newEdgePair(Vertex* from, Vertex* to)
1005 b3Assert(from && to);
1006 Edge* e = edgePool.newObject();
1007 Edge* r = edgePool.newObject();
1010 e->copy = mergeStamp;
1011 r->copy = mergeStamp;
1017 if (usedEdgePairs > maxUsedEdgePairs)
1019 maxUsedEdgePairs = usedEdgePairs;
1024 bool b3ConvexHullInternal::mergeProjection(IntermediateHull& h0, IntermediateHull& h1, Vertex*& c0, Vertex*& c1)
1026 Vertex* v0 = h0.maxYx;
1027 Vertex* v1 = h1.minYx;
1028 if ((v0->point.x == v1->point.x) && (v0->point.y == v1->point.y))
1030 b3Assert(v0->point.z < v1->point.z);
1031 Vertex* v1p = v1->prev;
1037 b3Assert(v1->edges->next == v1->edges);
1038 v1 = v1->edges->target;
1039 b3Assert(v1->edges->next == v1->edges);
1044 Vertex* v1n = v1->next;
1049 if ((v1n->point.x < v1p->point.x) || ((v1n->point.x == v1p->point.x) && (v1n->point.y < v1p->point.y)))
1060 if ((v1n->point.x > v1p->point.x) || ((v1n->point.x == v1p->point.x) && (v1n->point.y > v1p->point.y)))
1077 for (int side = 0; side <= 1; side++)
1079 btInt32_t dx = (v1->point.x - v0->point.x) * sign;
1084 btInt32_t dy = v1->point.y - v0->point.y;
1086 Vertex* w0 = side ? v0->next : v0->prev;
1089 btInt32_t dx0 = (w0->point.x - v0->point.x) * sign;
1090 btInt32_t dy0 = w0->point.y - v0->point.y;
1091 if ((dy0 <= 0) && ((dx0 == 0) || ((dx0 < 0) && (dy0 * dx <= dy * dx0))))
1094 dx = (v1->point.x - v0->point.x) * sign;
1099 Vertex* w1 = side ? v1->next : v1->prev;
1102 btInt32_t dx1 = (w1->point.x - v1->point.x) * sign;
1103 btInt32_t dy1 = w1->point.y - v1->point.y;
1104 btInt32_t dxn = (w1->point.x - v0->point.x) * sign;
1105 if ((dxn > 0) && (dy1 < 0) && ((dx1 == 0) || ((dx1 < 0) && (dy1 * dx < dy * dx1))))
1120 btInt32_t dy = v1->point.y - v0->point.y;
1122 Vertex* w1 = side ? v1->prev : v1->next;
1125 btInt32_t dx1 = (w1->point.x - v1->point.x) * sign;
1126 btInt32_t dy1 = w1->point.y - v1->point.y;
1127 if ((dy1 >= 0) && ((dx1 == 0) || ((dx1 < 0) && (dy1 * dx <= dy * dx1))))
1130 dx = (v1->point.x - v0->point.x) * sign;
1135 Vertex* w0 = side ? v0->prev : v0->next;
1138 btInt32_t dx0 = (w0->point.x - v0->point.x) * sign;
1139 btInt32_t dy0 = w0->point.y - v0->point.y;
1140 btInt32_t dxn = (v1->point.x - w0->point.x) * sign;
1141 if ((dxn < 0) && (dy0 > 0) && ((dx0 == 0) || ((dx0 < 0) && (dy0 * dx < dy * dx0))))
1154 btInt32_t x = v0->point.x;
1155 btInt32_t y0 = v0->point.y;
1158 while (((t = side ? w0->next : w0->prev) != v0) && (t->point.x == x) && (t->point.y <= y0))
1165 btInt32_t y1 = v1->point.y;
1167 while (((t = side ? w1->prev : w1->next) != v1) && (t->point.x == x) && (t->point.y >= y1))
1192 if (h1.minXy->point.x < h0.minXy->point.x)
1194 h0.minXy = h1.minXy;
1196 if (h1.maxXy->point.x >= h0.maxXy->point.x)
1198 h0.maxXy = h1.maxXy;
1201 h0.maxYx = h1.maxYx;
1209 void b3ConvexHullInternal::computeInternal(int start, int end, IntermediateHull& result)
1211 int n = end - start;
1215 result.minXy = NULL;
1216 result.maxXy = NULL;
1217 result.minYx = NULL;
1218 result.maxYx = NULL;
1222 Vertex* v = originalVertices[start];
1224 if (v->point != w->point)
1226 btInt32_t dx = v->point.x - w->point.x;
1227 btInt32_t dy = v->point.y - w->point.y;
1229 if ((dx == 0) && (dy == 0))
1231 if (v->point.z > w->point.z)
1237 b3Assert(v->point.z < w->point.z);
1252 if ((dx < 0) || ((dx == 0) && (dy < 0)))
1263 if ((dy < 0) || ((dy == 0) && (dx < 0)))
1275 Edge* e = newEdgePair(v, w);
1286 // lint -fallthrough
1289 Vertex* v = originalVertices[start];
1303 int split0 = start + n / 2;
1304 Point32 p = originalVertices[split0 - 1]->point;
1305 int split1 = split0;
1306 while ((split1 < end) && (originalVertices[split1]->point == p))
1310 computeInternal(start, split0, result);
1311 IntermediateHull hull1;
1312 computeInternal(split1, end, hull1);
1313 #ifdef DEBUG_CONVEX_HULL
1314 b3Printf("\n\nMerge\n");
1318 merge(result, hull1);
1319 #ifdef DEBUG_CONVEX_HULL
1320 b3Printf("\n Result\n");
1325 #ifdef DEBUG_CONVEX_HULL
1326 void b3ConvexHullInternal::IntermediateHull::print()
1328 b3Printf(" Hull\n");
1329 for (Vertex* v = minXy; v;)
1345 if (v->next->prev != v)
1347 b3Printf(" Inconsistency");
1358 minXy->copy = (minXy->copy == -1) ? -2 : -1;
1359 minXy->printGraph();
1363 void b3ConvexHullInternal::Vertex::printGraph()
1366 b3Printf("\nEdges\n");
1375 } while (e != edges);
1378 Vertex* v = e->target;
1379 if (v->copy != copy)
1385 } while (e != edges);
1390 b3ConvexHullInternal::Orientation b3ConvexHullInternal::getOrientation(const Edge* prev, const Edge* next, const Point32& s, const Point32& t)
1392 b3Assert(prev->reverse->target == next->reverse->target);
1393 if (prev->next == next)
1395 if (prev->prev == next)
1397 Point64 n = t.cross(s);
1398 Point64 m = (*prev->target - *next->reverse->target).cross(*next->target - *next->reverse->target);
1399 b3Assert(!m.isZero());
1400 btInt64_t dot = n.dot(m);
1402 return (dot > 0) ? COUNTER_CLOCKWISE : CLOCKWISE;
1404 return COUNTER_CLOCKWISE;
1406 else if (prev->prev == next)
1416 b3ConvexHullInternal::Edge* b3ConvexHullInternal::findMaxAngle(bool ccw, const Vertex* start, const Point32& s, const Point64& rxs, const Point64& sxrxs, Rational64& minCot)
1418 Edge* minEdge = NULL;
1420 #ifdef DEBUG_CONVEX_HULL
1421 b3Printf("find max edge for %d\n", start->point.index);
1423 Edge* e = start->edges;
1428 if (e->copy > mergeStamp)
1430 Point32 t = *e->target - *start;
1431 Rational64 cot(t.dot(sxrxs), t.dot(rxs));
1432 #ifdef DEBUG_CONVEX_HULL
1433 b3Printf(" Angle is %f (%d) for ", (float)b3Atan(cot.toScalar()), (int)cot.isNaN());
1438 b3Assert(ccw ? (t.dot(s) < 0) : (t.dot(s) > 0));
1443 if (minEdge == NULL)
1448 else if ((cmp = cot.compare(minCot)) < 0)
1453 else if ((cmp == 0) && (ccw == (getOrientation(minEdge, e, s, t) == COUNTER_CLOCKWISE)))
1458 #ifdef DEBUG_CONVEX_HULL
1463 } while (e != start->edges);
1468 void b3ConvexHullInternal::findEdgeForCoplanarFaces(Vertex* c0, Vertex* c1, Edge*& e0, Edge*& e1, Vertex* stop0, Vertex* stop1)
1472 Point32 et0 = start0 ? start0->target->point : c0->point;
1473 Point32 et1 = start1 ? start1->target->point : c1->point;
1474 Point32 s = c1->point - c0->point;
1475 Point64 normal = ((start0 ? start0 : start1)->target->point - c0->point).cross(s);
1476 btInt64_t dist = c0->point.dot(normal);
1477 b3Assert(!start1 || (start1->target->point.dot(normal) == dist));
1478 Point64 perp = s.cross(normal);
1479 b3Assert(!perp.isZero());
1481 #ifdef DEBUG_CONVEX_HULL
1482 b3Printf(" 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);
1485 btInt64_t maxDot0 = et0.dot(perp);
1488 while (e0->target != stop0)
1490 Edge* e = e0->reverse->prev;
1491 if (e->target->point.dot(normal) < dist)
1495 b3Assert(e->target->point.dot(normal) == dist);
1496 if (e->copy == mergeStamp)
1500 btInt64_t dot = e->target->point.dot(perp);
1507 et0 = e->target->point;
1511 btInt64_t maxDot1 = et1.dot(perp);
1514 while (e1->target != stop1)
1516 Edge* e = e1->reverse->next;
1517 if (e->target->point.dot(normal) < dist)
1521 b3Assert(e->target->point.dot(normal) == dist);
1522 if (e->copy == mergeStamp)
1526 btInt64_t dot = e->target->point.dot(perp);
1533 et1 = e->target->point;
1537 #ifdef DEBUG_CONVEX_HULL
1538 b3Printf(" Starting at %d %d\n", et0.index, et1.index);
1541 btInt64_t dx = maxDot1 - maxDot0;
1546 btInt64_t dy = (et1 - et0).dot(s);
1548 if (e0 && (e0->target != stop0))
1550 Edge* f0 = e0->next->reverse;
1551 if (f0->copy > mergeStamp)
1553 btInt64_t dx0 = (f0->target->point - et0).dot(perp);
1554 btInt64_t dy0 = (f0->target->point - et0).dot(s);
1555 if ((dx0 == 0) ? (dy0 < 0) : ((dx0 < 0) && (Rational64(dy0, dx0).compare(Rational64(dy, dx)) >= 0)))
1557 et0 = f0->target->point;
1558 dx = (et1 - et0).dot(perp);
1559 e0 = (e0 == start0) ? NULL : f0;
1565 if (e1 && (e1->target != stop1))
1567 Edge* f1 = e1->reverse->next;
1568 if (f1->copy > mergeStamp)
1570 Point32 d1 = f1->target->point - et1;
1571 if (d1.dot(normal) == 0)
1573 btInt64_t dx1 = d1.dot(perp);
1574 btInt64_t dy1 = d1.dot(s);
1575 btInt64_t dxn = (f1->target->point - et0).dot(perp);
1576 if ((dxn > 0) && ((dx1 == 0) ? (dy1 < 0) : ((dx1 < 0) && (Rational64(dy1, dx1).compare(Rational64(dy, dx)) > 0))))
1579 et1 = e1->target->point;
1586 b3Assert((e1 == start1) && (d1.dot(normal) < 0));
1598 btInt64_t dy = (et1 - et0).dot(s);
1600 if (e1 && (e1->target != stop1))
1602 Edge* f1 = e1->prev->reverse;
1603 if (f1->copy > mergeStamp)
1605 btInt64_t dx1 = (f1->target->point - et1).dot(perp);
1606 btInt64_t dy1 = (f1->target->point - et1).dot(s);
1607 if ((dx1 == 0) ? (dy1 > 0) : ((dx1 < 0) && (Rational64(dy1, dx1).compare(Rational64(dy, dx)) <= 0)))
1609 et1 = f1->target->point;
1610 dx = (et1 - et0).dot(perp);
1611 e1 = (e1 == start1) ? NULL : f1;
1617 if (e0 && (e0->target != stop0))
1619 Edge* f0 = e0->reverse->prev;
1620 if (f0->copy > mergeStamp)
1622 Point32 d0 = f0->target->point - et0;
1623 if (d0.dot(normal) == 0)
1625 btInt64_t dx0 = d0.dot(perp);
1626 btInt64_t dy0 = d0.dot(s);
1627 btInt64_t dxn = (et1 - f0->target->point).dot(perp);
1628 if ((dxn < 0) && ((dx0 == 0) ? (dy0 > 0) : ((dx0 < 0) && (Rational64(dy0, dx0).compare(Rational64(dy, dx)) < 0))))
1631 et0 = e0->target->point;
1638 b3Assert((e0 == start0) && (d0.dot(normal) < 0));
1646 #ifdef DEBUG_CONVEX_HULL
1647 b3Printf(" Advanced edges to %d %d\n", et0.index, et1.index);
1651 void b3ConvexHullInternal::merge(IntermediateHull& h0, IntermediateHull& h1)
1666 Edge* toPrev0 = NULL;
1667 Edge* firstNew0 = NULL;
1668 Edge* pendingHead0 = NULL;
1669 Edge* pendingTail0 = NULL;
1671 Edge* toPrev1 = NULL;
1672 Edge* firstNew1 = NULL;
1673 Edge* pendingHead1 = NULL;
1674 Edge* pendingTail1 = NULL;
1677 if (mergeProjection(h0, h1, c0, c1))
1679 Point32 s = *c1 - *c0;
1680 Point64 normal = Point32(0, 0, -1).cross(s);
1681 Point64 t = s.cross(normal);
1682 b3Assert(!t.isZero());
1684 Edge* e = c0->edges;
1685 Edge* start0 = NULL;
1690 btInt64_t dot = (*e->target - *c0).dot(normal);
1692 if ((dot == 0) && ((*e->target - *c0).dot(t) > 0))
1694 if (!start0 || (getOrientation(start0, e, s, Point32(0, 0, -1)) == CLOCKWISE))
1700 } while (e != c0->edges);
1704 Edge* start1 = NULL;
1709 btInt64_t dot = (*e->target - *c1).dot(normal);
1711 if ((dot == 0) && ((*e->target - *c1).dot(t) > 0))
1713 if (!start1 || (getOrientation(start1, e, s, Point32(0, 0, -1)) == COUNTER_CLOCKWISE))
1719 } while (e != c1->edges);
1722 if (start0 || start1)
1724 findEdgeForCoplanarFaces(c0, c1, start0, start1, NULL, NULL);
1727 c0 = start0->target;
1731 c1 = start1->target;
1735 prevPoint = c1->point;
1740 prevPoint = c1->point;
1744 Vertex* first0 = c0;
1745 Vertex* first1 = c1;
1746 bool firstRun = true;
1750 Point32 s = *c1 - *c0;
1751 Point32 r = prevPoint - c0->point;
1752 Point64 rxs = r.cross(s);
1753 Point64 sxrxs = s.cross(rxs);
1755 #ifdef DEBUG_CONVEX_HULL
1756 b3Printf("\n Checking %d %d\n", c0->point.index, c1->point.index);
1758 Rational64 minCot0(0, 0);
1759 Edge* min0 = findMaxAngle(false, c0, s, rxs, sxrxs, minCot0);
1760 Rational64 minCot1(0, 0);
1761 Edge* min1 = findMaxAngle(true, c1, s, rxs, sxrxs, minCot1);
1764 Edge* e = newEdgePair(c0, c1);
1775 int cmp = !min0 ? 1 : !min1 ? -1 : minCot0.compare(minCot1);
1776 #ifdef DEBUG_CONVEX_HULL
1777 b3Printf(" -> Result %d\n", cmp);
1779 if (firstRun || ((cmp >= 0) ? !minCot1.isNegativeInfinity() : !minCot0.isNegativeInfinity()))
1781 Edge* e = newEdgePair(c0, c1);
1784 pendingTail0->prev = e;
1790 e->next = pendingTail0;
1796 pendingTail1->next = e;
1802 e->prev = pendingTail1;
1809 #ifdef DEBUG_CONVEX_HULL
1810 b3Printf(" Found min edges to %d %d\n", e0 ? e0->target->point.index : -1, e1 ? e1->target->point.index : -1);
1815 findEdgeForCoplanarFaces(c0, c1, e0, e1, NULL, NULL);
1818 if ((cmp >= 0) && e1)
1822 for (Edge *e = toPrev1->next, *n = NULL; e != min1; e = n)
1833 toPrev1->link(pendingHead1);
1837 min1->prev->link(pendingHead1);
1838 firstNew1 = pendingHead1;
1840 pendingTail1->link(min1);
1841 pendingHead1 = NULL;
1842 pendingTail1 = NULL;
1849 prevPoint = c1->point;
1851 toPrev1 = e1->reverse;
1854 if ((cmp <= 0) && e0)
1858 for (Edge *e = toPrev0->prev, *n = NULL; e != min0; e = n)
1869 pendingHead0->link(toPrev0);
1873 pendingHead0->link(min0->next);
1874 firstNew0 = pendingHead0;
1876 min0->link(pendingTail0);
1877 pendingHead0 = NULL;
1878 pendingTail0 = NULL;
1885 prevPoint = c0->point;
1887 toPrev0 = e0->reverse;
1891 if ((c0 == first0) && (c1 == first1))
1893 if (toPrev0 == NULL)
1895 pendingHead0->link(pendingTail0);
1896 c0->edges = pendingTail0;
1900 for (Edge *e = toPrev0->prev, *n = NULL; e != firstNew0; e = n)
1907 pendingHead0->link(toPrev0);
1908 firstNew0->link(pendingTail0);
1912 if (toPrev1 == NULL)
1914 pendingTail1->link(pendingHead1);
1915 c1->edges = pendingTail1;
1919 for (Edge *e = toPrev1->next, *n = NULL; e != firstNew1; e = n)
1926 toPrev1->link(pendingHead1);
1927 pendingTail1->link(firstNew1);
1938 static bool b3PointCmp(const b3ConvexHullInternal::Point32& p, const b3ConvexHullInternal::Point32& q)
1940 return (p.y < q.y) || ((p.y == q.y) && ((p.x < q.x) || ((p.x == q.x) && (p.z < q.z))));
1943 void b3ConvexHullInternal::compute(const void* coords, bool doubleCoords, int stride, int count)
1945 b3Vector3 min = b3MakeVector3(b3Scalar(1e30), b3Scalar(1e30), b3Scalar(1e30)), max = b3MakeVector3(b3Scalar(-1e30), b3Scalar(-1e30), b3Scalar(-1e30));
1946 const char* ptr = (const char*)coords;
1949 for (int i = 0; i < count; i++)
1951 const double* v = (const double*)ptr;
1952 b3Vector3 p = b3MakeVector3((b3Scalar)v[0], (b3Scalar)v[1], (b3Scalar)v[2]);
1960 for (int i = 0; i < count; i++)
1962 const float* v = (const float*)ptr;
1963 b3Vector3 p = b3MakeVector3(v[0], v[1], v[2]);
1970 b3Vector3 s = max - min;
1971 maxAxis = s.maxAxis();
1972 minAxis = s.minAxis();
1973 if (minAxis == maxAxis)
1975 minAxis = (maxAxis + 1) % 3;
1977 medAxis = 3 - maxAxis - minAxis;
1979 s /= b3Scalar(10216);
1980 if (((medAxis + 1) % 3) != maxAxis)
1988 s[0] = b3Scalar(1) / s[0];
1992 s[1] = b3Scalar(1) / s[1];
1996 s[2] = b3Scalar(1) / s[2];
1999 center = (min + max) * b3Scalar(0.5);
2001 b3AlignedObjectArray<Point32> points;
2002 points.resize(count);
2003 ptr = (const char*)coords;
2006 for (int i = 0; i < count; i++)
2008 const double* v = (const double*)ptr;
2009 b3Vector3 p = b3MakeVector3((b3Scalar)v[0], (b3Scalar)v[1], (b3Scalar)v[2]);
2011 p = (p - center) * s;
2012 points[i].x = (btInt32_t)p[medAxis];
2013 points[i].y = (btInt32_t)p[maxAxis];
2014 points[i].z = (btInt32_t)p[minAxis];
2015 points[i].index = i;
2020 for (int i = 0; i < count; i++)
2022 const float* v = (const float*)ptr;
2023 b3Vector3 p = b3MakeVector3(v[0], v[1], v[2]);
2025 p = (p - center) * s;
2026 points[i].x = (btInt32_t)p[medAxis];
2027 points[i].y = (btInt32_t)p[maxAxis];
2028 points[i].z = (btInt32_t)p[minAxis];
2029 points[i].index = i;
2032 points.quickSort(b3PointCmp);
2035 vertexPool.setArraySize(count);
2036 originalVertices.resize(count);
2037 for (int i = 0; i < count; i++)
2039 Vertex* v = vertexPool.newObject();
2041 v->point = points[i];
2043 originalVertices[i] = v;
2049 edgePool.setArraySize(6 * count);
2052 maxUsedEdgePairs = 0;
2056 IntermediateHull hull;
2057 computeInternal(0, count, hull);
2058 vertexList = hull.minXy;
2059 #ifdef DEBUG_CONVEX_HULL
2060 b3Printf("max. edges %d (3v = %d)", maxUsedEdgePairs, 3 * count);
2064 b3Vector3 b3ConvexHullInternal::toBtVector(const Point32& v)
2067 p[medAxis] = b3Scalar(v.x);
2068 p[maxAxis] = b3Scalar(v.y);
2069 p[minAxis] = b3Scalar(v.z);
2073 b3Vector3 b3ConvexHullInternal::getBtNormal(Face* face)
2075 return toBtVector(face->dir0).cross(toBtVector(face->dir1)).normalized();
2078 b3Vector3 b3ConvexHullInternal::getCoordinates(const Vertex* v)
2081 p[medAxis] = v->xvalue();
2082 p[maxAxis] = v->yvalue();
2083 p[minAxis] = v->zvalue();
2084 return p * scaling + center;
2087 b3Scalar b3ConvexHullInternal::shrink(b3Scalar amount, b3Scalar clampAmount)
2093 int stamp = --mergeStamp;
2094 b3AlignedObjectArray<Vertex*> stack;
2095 vertexList->copy = stamp;
2096 stack.push_back(vertexList);
2097 b3AlignedObjectArray<Face*> faces;
2099 Point32 ref = vertexList->point;
2100 Int128 hullCenterX(0, 0);
2101 Int128 hullCenterY(0, 0);
2102 Int128 hullCenterZ(0, 0);
2103 Int128 volume(0, 0);
2105 while (stack.size() > 0)
2107 Vertex* v = stack[stack.size() - 1];
2114 if (e->target->copy != stamp)
2116 e->target->copy = stamp;
2117 stack.push_back(e->target);
2119 if (e->copy != stamp)
2121 Face* face = facePool.newObject();
2122 face->init(e->target, e->reverse->prev->target, v);
2123 faces.push_back(face);
2132 btInt64_t vol = (v->point - ref).dot((a->point - ref).cross(b->point - ref));
2134 Point32 c = v->point + a->point + b->point + ref;
2135 hullCenterX += vol * c.x;
2136 hullCenterY += vol * c.y;
2137 hullCenterZ += vol * c.z;
2141 b3Assert(f->copy != stamp);
2148 f = f->reverse->prev;
2152 } while (e != v->edges);
2156 if (volume.getSign() <= 0)
2161 b3Vector3 hullCenter;
2162 hullCenter[medAxis] = hullCenterX.toScalar();
2163 hullCenter[maxAxis] = hullCenterY.toScalar();
2164 hullCenter[minAxis] = hullCenterZ.toScalar();
2165 hullCenter /= 4 * volume.toScalar();
2166 hullCenter *= scaling;
2168 int faceCount = faces.size();
2170 if (clampAmount > 0)
2172 b3Scalar minDist = B3_INFINITY;
2173 for (int i = 0; i < faceCount; i++)
2175 b3Vector3 normal = getBtNormal(faces[i]);
2176 b3Scalar dist = normal.dot(toBtVector(faces[i]->origin) - hullCenter);
2188 amount = b3Min(amount, minDist * clampAmount);
2191 unsigned int seed = 243703;
2192 for (int i = 0; i < faceCount; i++, seed = 1664525 * seed + 1013904223)
2194 b3Swap(faces[i], faces[seed % faceCount]);
2197 for (int i = 0; i < faceCount; i++)
2199 if (!shiftFace(faces[i], amount, stack))
2208 bool b3ConvexHullInternal::shiftFace(Face* face, b3Scalar amount, b3AlignedObjectArray<Vertex*> stack)
2210 b3Vector3 origShift = getBtNormal(face) * -amount;
2211 if (scaling[0] != 0)
2213 origShift[0] /= scaling[0];
2215 if (scaling[1] != 0)
2217 origShift[1] /= scaling[1];
2219 if (scaling[2] != 0)
2221 origShift[2] /= scaling[2];
2223 Point32 shift((btInt32_t)origShift[medAxis], (btInt32_t)origShift[maxAxis], (btInt32_t)origShift[minAxis]);
2228 Point64 normal = face->getNormal();
2229 #ifdef DEBUG_CONVEX_HULL
2230 b3Printf("\nShrinking face (%d %d %d) (%d %d %d) (%d %d %d) by (%d %d %d)\n",
2231 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);
2233 btInt64_t origDot = face->origin.dot(normal);
2234 Point32 shiftedOrigin = face->origin + shift;
2235 btInt64_t shiftedDot = shiftedOrigin.dot(normal);
2236 b3Assert(shiftedDot <= origDot);
2237 if (shiftedDot >= origDot)
2242 Edge* intersection = NULL;
2244 Edge* startEdge = face->nearbyVertex->edges;
2245 #ifdef DEBUG_CONVEX_HULL
2246 b3Printf("Start edge is ");
2248 b3Printf(", normal is (%lld %lld %lld), shifted dot is %lld\n", normal.x, normal.y, normal.z, shiftedDot);
2250 Rational128 optDot = face->nearbyVertex->dot(normal);
2251 int cmp = optDot.compare(shiftedDot);
2252 #ifdef SHOW_ITERATIONS
2257 Edge* e = startEdge;
2260 #ifdef SHOW_ITERATIONS
2263 Rational128 dot = e->target->dot(normal);
2264 b3Assert(dot.compare(origDot) <= 0);
2265 #ifdef DEBUG_CONVEX_HULL
2266 b3Printf("Moving downwards, edge is ");
2268 b3Printf(", dot is %f (%f %lld)\n", (float)dot.toScalar(), (float)optDot.toScalar(), shiftedDot);
2270 if (dot.compare(optDot) < 0)
2272 int c = dot.compare(shiftedDot);
2284 } while (e != startEdge);
2293 Edge* e = startEdge;
2296 #ifdef SHOW_ITERATIONS
2299 Rational128 dot = e->target->dot(normal);
2300 b3Assert(dot.compare(origDot) <= 0);
2301 #ifdef DEBUG_CONVEX_HULL
2302 b3Printf("Moving upwards, edge is ");
2304 b3Printf(", dot is %f (%f %lld)\n", (float)dot.toScalar(), (float)optDot.toScalar(), shiftedDot);
2306 if (dot.compare(optDot) > 0)
2308 cmp = dot.compare(shiftedDot);
2319 } while (e != startEdge);
2327 #ifdef SHOW_ITERATIONS
2328 b3Printf("Needed %d iterations to find initial intersection\n", n);
2333 Edge* e = intersection->reverse->next;
2334 #ifdef SHOW_ITERATIONS
2337 while (e->target->dot(normal).compare(shiftedDot) <= 0)
2339 #ifdef SHOW_ITERATIONS
2343 if (e == intersection->reverse)
2347 #ifdef DEBUG_CONVEX_HULL
2348 b3Printf("Checking for outwards edge, current edge is ");
2353 #ifdef SHOW_ITERATIONS
2354 b3Printf("Needed %d iterations to check for complete containment\n", n);
2358 Edge* firstIntersection = NULL;
2359 Edge* faceEdge = NULL;
2360 Edge* firstFaceEdge = NULL;
2362 #ifdef SHOW_ITERATIONS
2367 #ifdef SHOW_ITERATIONS
2370 #ifdef DEBUG_CONVEX_HULL
2371 b3Printf("Intersecting edge is ");
2372 intersection->print();
2377 Edge* e = intersection->reverse->next;
2379 #ifdef SHOW_ITERATIONS
2384 #ifdef SHOW_ITERATIONS
2387 if (e->target->dot(normal).compare(shiftedDot) >= 0)
2391 intersection = e->reverse;
2398 #ifdef SHOW_ITERATIONS
2399 b3Printf("Needed %d iterations to advance intersection\n", n);
2403 #ifdef DEBUG_CONVEX_HULL
2404 b3Printf("Advanced intersecting edge to ");
2405 intersection->print();
2406 b3Printf(", cmp = %d\n", cmp);
2409 if (!firstIntersection)
2411 firstIntersection = intersection;
2413 else if (intersection == firstIntersection)
2419 Edge* prevIntersection = intersection;
2420 Edge* prevFaceEdge = faceEdge;
2422 Edge* e = intersection->reverse;
2423 #ifdef SHOW_ITERATIONS
2428 #ifdef SHOW_ITERATIONS
2431 e = e->reverse->prev;
2432 b3Assert(e != intersection->reverse);
2433 cmp = e->target->dot(normal).compare(shiftedDot);
2434 #ifdef DEBUG_CONVEX_HULL
2435 b3Printf("Testing edge ");
2437 b3Printf(" -> cmp = %d\n", cmp);
2445 #ifdef SHOW_ITERATIONS
2446 b3Printf("Needed %d iterations to find other intersection of face\n", n);
2451 Vertex* removed = intersection->target;
2452 e = intersection->reverse;
2455 removed->edges = NULL;
2459 removed->edges = e->prev;
2460 e->prev->link(e->next);
2463 #ifdef DEBUG_CONVEX_HULL
2464 b3Printf("1: Removed part contains (%d %d %d)\n", removed->point.x, removed->point.y, removed->point.z);
2467 Point64 n0 = intersection->face->getNormal();
2468 Point64 n1 = intersection->reverse->face->getNormal();
2469 btInt64_t m00 = face->dir0.dot(n0);
2470 btInt64_t m01 = face->dir1.dot(n0);
2471 btInt64_t m10 = face->dir0.dot(n1);
2472 btInt64_t m11 = face->dir1.dot(n1);
2473 btInt64_t r0 = (intersection->face->origin - shiftedOrigin).dot(n0);
2474 btInt64_t r1 = (intersection->reverse->face->origin - shiftedOrigin).dot(n1);
2475 Int128 det = Int128::mul(m00, m11) - Int128::mul(m01, m10);
2476 b3Assert(det.getSign() != 0);
2477 Vertex* v = vertexPool.newObject();
2478 v->point.index = -1;
2480 v->point128 = PointR128(Int128::mul(face->dir0.x * r0, m11) - Int128::mul(face->dir0.x * r1, m01) + Int128::mul(face->dir1.x * r1, m00) - Int128::mul(face->dir1.x * r0, m10) + det * shiftedOrigin.x,
2481 Int128::mul(face->dir0.y * r0, m11) - Int128::mul(face->dir0.y * r1, m01) + Int128::mul(face->dir1.y * r1, m00) - Int128::mul(face->dir1.y * r0, m10) + det * shiftedOrigin.y,
2482 Int128::mul(face->dir0.z * r0, m11) - Int128::mul(face->dir0.z * r1, m01) + Int128::mul(face->dir1.z * r1, m00) - Int128::mul(face->dir1.z * r0, m10) + det * shiftedOrigin.z,
2484 v->point.x = (btInt32_t)v->point128.xvalue();
2485 v->point.y = (btInt32_t)v->point128.yvalue();
2486 v->point.z = (btInt32_t)v->point128.zvalue();
2487 intersection->target = v;
2491 stack.push_back(removed);
2492 stack.push_back(NULL);
2495 if (cmp || prevCmp || (prevIntersection->reverse->next->target != intersection->target))
2497 faceEdge = newEdgePair(prevIntersection->target, intersection->target);
2500 faceEdge->link(prevIntersection->reverse->next);
2502 if ((prevCmp == 0) || prevFaceEdge)
2504 prevIntersection->reverse->link(faceEdge);
2508 intersection->reverse->prev->link(faceEdge->reverse);
2510 faceEdge->reverse->link(intersection->reverse);
2514 faceEdge = prevIntersection->reverse->next;
2521 faceEdge->link(prevFaceEdge->reverse);
2523 else if (faceEdge != prevFaceEdge->reverse)
2525 stack.push_back(prevFaceEdge->target);
2526 while (faceEdge->next != prevFaceEdge->reverse)
2528 Vertex* removed = faceEdge->next->target;
2529 removeEdgePair(faceEdge->next);
2530 stack.push_back(removed);
2531 #ifdef DEBUG_CONVEX_HULL
2532 b3Printf("2: Removed part contains (%d %d %d)\n", removed->point.x, removed->point.y, removed->point.z);
2535 stack.push_back(NULL);
2538 faceEdge->face = face;
2539 faceEdge->reverse->face = intersection->face;
2543 firstFaceEdge = faceEdge;
2546 #ifdef SHOW_ITERATIONS
2547 b3Printf("Needed %d iterations to process all intersections\n", m);
2552 firstFaceEdge->reverse->target = faceEdge->target;
2553 firstIntersection->reverse->link(firstFaceEdge);
2554 firstFaceEdge->link(faceEdge->reverse);
2556 else if (firstFaceEdge != faceEdge->reverse)
2558 stack.push_back(faceEdge->target);
2559 while (firstFaceEdge->next != faceEdge->reverse)
2561 Vertex* removed = firstFaceEdge->next->target;
2562 removeEdgePair(firstFaceEdge->next);
2563 stack.push_back(removed);
2564 #ifdef DEBUG_CONVEX_HULL
2565 b3Printf("3: Removed part contains (%d %d %d)\n", removed->point.x, removed->point.y, removed->point.z);
2568 stack.push_back(NULL);
2571 b3Assert(stack.size() > 0);
2572 vertexList = stack[0];
2574 #ifdef DEBUG_CONVEX_HULL
2575 b3Printf("Removing part\n");
2577 #ifdef SHOW_ITERATIONS
2581 while (pos < stack.size())
2583 int end = stack.size();
2586 Vertex* kept = stack[pos++];
2587 #ifdef DEBUG_CONVEX_HULL
2590 bool deeper = false;
2592 while ((removed = stack[pos++]) != NULL)
2594 #ifdef SHOW_ITERATIONS
2597 kept->receiveNearbyFaces(removed);
2598 while (removed->edges)
2603 stack.push_back(kept);
2605 stack.push_back(removed->edges->target);
2606 removeEdgePair(removed->edges);
2611 stack.push_back(NULL);
2615 #ifdef SHOW_ITERATIONS
2616 b3Printf("Needed %d iterations to remove part\n", n);
2620 face->origin = shiftedOrigin;
2625 static int getVertexCopy(b3ConvexHullInternal::Vertex* vertex, b3AlignedObjectArray<b3ConvexHullInternal::Vertex*>& vertices)
2627 int index = vertex->copy;
2630 index = vertices.size();
2631 vertex->copy = index;
2632 vertices.push_back(vertex);
2633 #ifdef DEBUG_CONVEX_HULL
2634 b3Printf("Vertex %d gets index *%d\n", vertex->point.index, index);
2640 b3Scalar b3ConvexHullComputer::compute(const void* coords, bool doubleCoords, int stride, int count, b3Scalar shrink, b3Scalar shrinkClamp)
2650 b3ConvexHullInternal hull;
2651 hull.compute(coords, doubleCoords, stride, count);
2654 if ((shrink > 0) && ((shift = hull.shrink(shrink, shrinkClamp)) < 0))
2666 b3AlignedObjectArray<b3ConvexHullInternal::Vertex*> oldVertices;
2667 getVertexCopy(hull.vertexList, oldVertices);
2669 while (copied < oldVertices.size())
2671 b3ConvexHullInternal::Vertex* v = oldVertices[copied];
2672 vertices.push_back(hull.getCoordinates(v));
2673 b3ConvexHullInternal::Edge* firstEdge = v->edges;
2678 b3ConvexHullInternal::Edge* e = firstEdge;
2683 int s = edges.size();
2684 edges.push_back(Edge());
2685 edges.push_back(Edge());
2686 Edge* c = &edges[s];
2687 Edge* r = &edges[s + 1];
2689 e->reverse->copy = s + 1;
2692 c->targetVertex = getVertexCopy(e->target, oldVertices);
2693 r->targetVertex = copied;
2694 #ifdef DEBUG_CONVEX_HULL
2695 b3Printf(" CREATE: Vertex *%d has edge to *%d\n", copied, c->getTargetVertex());
2700 edges[e->copy].next = prevCopy - e->copy;
2704 firstCopy = e->copy;
2708 } while (e != firstEdge);
2709 edges[firstCopy].next = prevCopy - firstCopy;
2714 for (int i = 0; i < copied; i++)
2716 b3ConvexHullInternal::Vertex* v = oldVertices[i];
2717 b3ConvexHullInternal::Edge* firstEdge = v->edges;
2720 b3ConvexHullInternal::Edge* e = firstEdge;
2725 #ifdef DEBUG_CONVEX_HULL
2726 b3Printf("Vertex *%d has edge to *%d\n", i, edges[e->copy].getTargetVertex());
2728 faces.push_back(e->copy);
2729 b3ConvexHullInternal::Edge* f = e;
2732 #ifdef DEBUG_CONVEX_HULL
2733 b3Printf(" Face *%d\n", edges[f->copy].getTargetVertex());
2736 f = f->reverse->prev;
2740 } while (e != firstEdge);