1 /* 2 Copyright (c) 2011 Ole Kniemeyer, MAXON, www.maxon.net 3 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: 9 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. 13 */ 14 15 #include <string.h> 16 17 #include "btConvexHullComputer.h" 18 #include "btAlignedObjectArray.h" 19 #include "btMinMax.h" 20 #include "btVector3.h" 21 22 #ifdef __GNUC__ 23 #include <stdint.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; 29 #else 30 typedef int int32_t; 31 typedef long long int int64_t; 32 typedef unsigned int uint32_t; 33 typedef unsigned long long int uint64_t; 34 #endif 35 36 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 40 //#endif 41 42 43 //#define DEBUG_CONVEX_HULL 44 //#define SHOW_ITERATIONS 45 46 #if defined(DEBUG_CONVEX_HULL) || defined(SHOW_ITERATIONS) 47 #include <stdio.h> 48 #endif 49 50 // Convex hull implementation based on Preparata and Hong 51 // Ole Kniemeyer, MAXON Computer GmbH 52 class btConvexHullInternal 53 { 54 public: 55 56 class Point64 57 { 58 public: 59 int64_t x; 60 int64_t y; 61 int64_t z; 62 63 Point64(int64_t x, int64_t y, int64_t z): x(x), y(y), z(z) 64 { 65 } 66 67 bool isZero() 68 { 69 return (x == 0) && (y == 0) && (z == 0); 70 } 71 72 int64_t dot(const Point64& b) const 73 { 74 return x * b.x + y * b.y + z * b.z; 75 } 76 }; 77 78 class Point32 79 { 80 public: 81 int32_t x; 82 int32_t y; 83 int32_t z; 84 int index; 85 86 Point32() 87 { 88 } 89 90 Point32(int32_t x, int32_t y, int32_t z): x(x), y(y), z(z), index(-1) 91 { 92 } 93 94 bool operator==(const Point32& b) const 95 { 96 return (x == b.x) && (y == b.y) && (z == b.z); 97 } 98 99 bool operator!=(const Point32& b) const 100 { 101 return (x != b.x) || (y != b.y) || (z != b.z); 102 } 103 104 bool isZero() 105 { 106 return (x == 0) && (y == 0) && (z == 0); 107 } 108 109 Point64 cross(const Point32& b) const 110 { 111 return Point64(y * b.z - z * b.y, z * b.x - x * b.z, x * b.y - y * b.x); 112 } 113 114 Point64 cross(const Point64& b) const 115 { 116 return Point64(y * b.z - z * b.y, z * b.x - x * b.z, x * b.y - y * b.x); 117 } 118 119 int64_t dot(const Point32& b) const 120 { 121 return x * b.x + y * b.y + z * b.z; 122 } 123 124 int64_t dot(const Point64& b) const 125 { 126 return x * b.x + y * b.y + z * b.z; 127 } 128 129 Point32 operator+(const Point32& b) const 130 { 131 return Point32(x + b.x, y + b.y, z + b.z); 132 } 133 134 Point32 operator-(const Point32& b) const 135 { 136 return Point32(x - b.x, y - b.y, z - b.z); 137 } 138 }; 139 140 class Int128 141 { 142 public: 143 uint64_t low; 144 uint64_t high; 145 146 Int128() 147 { 148 } 149 150 Int128(uint64_t low, uint64_t high): low(low), high(high) 151 { 152 } 153 154 Int128(uint64_t low): low(low), high(0) 155 { 156 } 157 158 Int128(int64_t value): low(value), high((value >= 0) ? 0 : (uint64_t) -1LL) 159 { 160 } 161 162 static Int128 mul(int64_t a, int64_t b); 163 164 static Int128 mul(uint64_t a, uint64_t b); 165 166 Int128 operator-() const 167 { 168 return Int128((uint64_t) -(int64_t)low, ~high + (low == 0)); 169 } 170 171 Int128 operator+(const Int128& b) const 172 { 173 #ifdef USE_X86_64_ASM 174 Int128 result; 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) 179 : "cc" ); 180 return result; 181 #else 182 uint64_t lo = low + b.low; 183 return Int128(lo, high + b.high + (lo < low)); 184 #endif 185 } 186 187 Int128 operator-(const Int128& b) const 188 { 189 #ifdef USE_X86_64_ASM 190 Int128 result; 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) 195 : "cc" ); 196 return result; 197 #else 198 return *this + -b; 199 #endif 200 } 201 202 Int128& operator+=(const Int128& b) 203 { 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) 209 : "cc" ); 210 #else 211 uint64_t lo = low + b.low; 212 if (lo < low) 213 { 214 ++high; 215 } 216 low = lo; 217 high += b.high; 218 #endif 219 return *this; 220 } 221 222 Int128& operator++() 223 { 224 if (++low == 0) 225 { 226 ++high; 227 } 228 return *this; 229 } 230 231 Int128 operator*(int64_t b) const; 232 233 btScalar toScalar() const 234 { 235 return ((int64_t) high >= 0) ? btScalar(high) * (btScalar(0x100000000LL) * btScalar(0x100000000LL)) + btScalar(low) 236 : -(-*this).toScalar(); 237 } 238 239 int getSign() const 240 { 241 return ((int64_t) high < 0) ? -1 : (high || low) ? 1 : 0; 242 } 243 244 bool operator<(const Int128& b) const 245 { 246 return (high < b.high) || ((high == b.high) && (low < b.low)); 247 } 248 249 int ucmp(const Int128&b) const 250 { 251 if (high < b.high) 252 { 253 return -1; 254 } 255 if (high > b.high) 256 { 257 return 1; 258 } 259 if (low < b.low) 260 { 261 return -1; 262 } 263 if (low > b.low) 264 { 265 return 1; 266 } 267 return 0; 268 } 269 }; 270 271 272 class Rational64 273 { 274 private: 275 uint64_t m_numerator; 276 uint64_t m_denominator; 277 int sign; 278 279 public: 280 Rational64(int64_t numerator, int64_t denominator) 281 { 282 if (numerator > 0) 283 { 284 sign = 1; 285 m_numerator = (uint64_t) numerator; 286 } 287 else if (numerator < 0) 288 { 289 sign = -1; 290 m_numerator = (uint64_t) -numerator; 291 } 292 else 293 { 294 sign = 0; 295 m_numerator = 0; 296 } 297 if (denominator > 0) 298 { 299 m_denominator = (uint64_t) denominator; 300 } 301 else if (denominator < 0) 302 { 303 sign = -sign; 304 m_denominator = (uint64_t) -denominator; 305 } 306 else 307 { 308 m_denominator = 0; 309 } 310 } 311 312 bool isNegativeInfinity() const 313 { 314 return (sign < 0) && (m_denominator == 0); 315 } 316 317 bool isNaN() const 318 { 319 return (sign == 0) && (m_denominator == 0); 320 } 321 322 int compare(const Rational64& b) const; 323 324 btScalar toScalar() const 325 { 326 return sign * ((m_denominator == 0) ? SIMD_INFINITY : (btScalar) m_numerator / m_denominator); 327 } 328 }; 329 330 331 class Rational128 332 { 333 private: 334 Int128 numerator; 335 Int128 denominator; 336 int sign; 337 bool isInt64; 338 339 public: 340 Rational128(int64_t value) 341 { 342 if (value > 0) 343 { 344 sign = 1; 345 this->numerator = value; 346 } 347 else if (value < 0) 348 { 349 sign = -1; 350 this->numerator = -value; 351 } 352 else 353 { 354 sign = 0; 355 this->numerator = (uint64_t) 0; 356 } 357 this->denominator = (uint64_t) 1; 358 isInt64 = true; 359 } 360 361 Rational128(const Int128& numerator, const Int128& denominator) 362 { 363 sign = numerator.getSign(); 364 if (sign >= 0) 365 { 366 this->numerator = numerator; 367 } 368 else 369 { 370 this->numerator = -numerator; 371 } 372 int dsign = denominator.getSign(); 373 if (dsign >= 0) 374 { 375 this->denominator = denominator; 376 } 377 else 378 { 379 sign = -sign; 380 this->denominator = -denominator; 381 } 382 isInt64 = false; 383 } 384 385 int compare(const Rational128& b) const; 386 387 int compare(int64_t b) const; 388 389 btScalar toScalar() const 390 { 391 return sign * ((denominator.getSign() == 0) ? SIMD_INFINITY : numerator.toScalar() / denominator.toScalar()); 392 } 393 }; 394 395 class PointR128 396 { 397 public: 398 Int128 x; 399 Int128 y; 400 Int128 z; 401 Int128 denominator; 402 403 PointR128() 404 { 405 } 406 407 PointR128(Int128 x, Int128 y, Int128 z, Int128 denominator): x(x), y(y), z(z), denominator(denominator) 408 { 409 } 410 411 btScalar xvalue() const 412 { 413 return x.toScalar() / denominator.toScalar(); 414 } 415 416 btScalar yvalue() const 417 { 418 return y.toScalar() / denominator.toScalar(); 419 } 420 421 btScalar zvalue() const 422 { 423 return z.toScalar() / denominator.toScalar(); 424 } 425 }; 426 427 428 class Edge; 429 class Face; 430 431 class Vertex 432 { 433 public: 434 Vertex* next; 435 Vertex* prev; 436 Edge* edges; 437 Face* firstNearbyFace; 438 Face* lastNearbyFace; 439 PointR128 point128; 440 Point32 point; 441 int copy; 442 443 Vertex(): next(NULL), prev(NULL), edges(NULL), firstNearbyFace(NULL), lastNearbyFace(NULL), copy(-1) 444 { 445 } 446 447 #ifdef DEBUG_CONVEX_HULL 448 void print() 449 { 450 printf("V%d (%d, %d, %d)", point.index, point.x, point.y, point.z); 451 } 452 453 void printGraph(); 454 #endif 455 456 Point32 operator-(const Vertex& b) const 457 { 458 return point - b.point; 459 } 460 461 Rational128 dot(const Point64& b) const 462 { 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); 465 } 466 467 btScalar xvalue() const 468 { 469 return (point.index >= 0) ? btScalar(point.x) : point128.xvalue(); 470 } 471 472 btScalar yvalue() const 473 { 474 return (point.index >= 0) ? btScalar(point.y) : point128.yvalue(); 475 } 476 477 btScalar zvalue() const 478 { 479 return (point.index >= 0) ? btScalar(point.z) : point128.zvalue(); 480 } 481 482 void receiveNearbyFaces(Vertex* src) 483 { 484 if (lastNearbyFace) 485 { 486 lastNearbyFace->nextWithSameNearbyVertex = src->firstNearbyFace; 487 } 488 else 489 { 490 firstNearbyFace = src->firstNearbyFace; 491 } 492 if (src->lastNearbyFace) 493 { 494 lastNearbyFace = src->lastNearbyFace; 495 } 496 for (Face* f = src->firstNearbyFace; f; f = f->nextWithSameNearbyVertex) 497 { 498 btAssert(f->nearbyVertex == src); 499 f->nearbyVertex = this; 500 } 501 src->firstNearbyFace = NULL; 502 src->lastNearbyFace = NULL; 503 } 504 }; 505 506 507 class Edge 508 { 509 public: 510 Edge* next; 511 Edge* prev; 512 Edge* reverse; 513 Vertex* target; 514 Face* face; 515 int copy; 516 517 ~Edge() 518 { 519 next = NULL; 520 prev = NULL; 521 reverse = NULL; 522 target = NULL; 523 face = NULL; 524 } 525 526 void link(Edge* n) 527 { 528 btAssert(reverse->target == n->reverse->target); 529 next = n; 530 n->prev = this; 531 } 532 533 #ifdef DEBUG_CONVEX_HULL 534 void print() 535 { 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); 538 } 539 #endif 540 }; 541 542 class Face 543 { 544 public: 545 Face* next; 546 Vertex* nearbyVertex; 547 Face* nextWithSameNearbyVertex; 548 Point32 origin; 549 Point32 dir0; 550 Point32 dir1; 551 552 Face(): next(NULL), nearbyVertex(NULL), nextWithSameNearbyVertex(NULL) 553 { 554 } 555 556 void init(Vertex* a, Vertex* b, Vertex* c) 557 { 558 nearbyVertex = a; 559 origin = a->point; 560 dir0 = *b - *a; 561 dir1 = *c - *a; 562 if (a->lastNearbyFace) 563 { 564 a->lastNearbyFace->nextWithSameNearbyVertex = this; 565 } 566 else 567 { 568 a->firstNearbyFace = this; 569 } 570 a->lastNearbyFace = this; 571 } 572 573 Point64 getNormal() 574 { 575 return dir0.cross(dir1); 576 } 577 }; 578 579 template<typename UWord, typename UHWord> class DMul 580 { 581 private: 582 static uint32_t high(uint64_t value) 583 { 584 return (uint32_t) (value >> 32); 585 } 586 587 static uint32_t low(uint64_t value) 588 { 589 return (uint32_t) value; 590 } 591 592 static uint64_t mul(uint32_t a, uint32_t b) 593 { 594 return (uint64_t) a * (uint64_t) b; 595 } 596 597 static void shlHalf(uint64_t& value) 598 { 599 value <<= 32; 600 } 601 602 static uint64_t high(Int128 value) 603 { 604 return value.high; 605 } 606 607 static uint64_t low(Int128 value) 608 { 609 return value.low; 610 } 611 612 static Int128 mul(uint64_t a, uint64_t b) 613 { 614 return Int128::mul(a, b); 615 } 616 617 static void shlHalf(Int128& value) 618 { 619 value.high = value.low; 620 value.low = 0; 621 } 622 623 public: 624 625 static void mul(UWord a, UWord b, UWord& resLow, UWord& resHigh) 626 { 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)); 632 p11 += high(p01); 633 p11 += high(p10); 634 p11 += high(p0110); 635 shlHalf(p0110); 636 p00 += p0110; 637 if (p00 < p0110) 638 { 639 ++p11; 640 } 641 resLow = p00; 642 resHigh = p11; 643 } 644 }; 645 646 private: 647 648 class IntermediateHull 649 { 650 public: 651 Vertex* minXy; 652 Vertex* maxXy; 653 Vertex* minYx; 654 Vertex* maxYx; 655 656 IntermediateHull(): minXy(NULL), maxXy(NULL), minYx(NULL), maxYx(NULL) 657 { 658 } 659 660 void print(); 661 }; 662 663 enum Orientation {NONE, CLOCKWISE, COUNTER_CLOCKWISE}; 664 665 template <typename T> class PoolArray 666 { 667 private: 668 T* array; 669 int size; 670 671 public: 672 PoolArray<T>* next; 673 674 PoolArray(int size): size(size), next(NULL) 675 { 676 array = (T*) btAlignedAlloc(sizeof(T) * size, 16); 677 } 678 679 ~PoolArray() 680 { 681 btAlignedFree(array); 682 } 683 684 T* init() 685 { 686 T* o = array; 687 for (int i = 0; i < size; i++, o++) 688 { 689 o->next = (i+1 < size) ? o + 1 : NULL; 690 } 691 return array; 692 } 693 }; 694 695 template <typename T> class Pool 696 { 697 private: 698 PoolArray<T>* arrays; 699 PoolArray<T>* nextArray; 700 T* freeObjects; 701 int arraySize; 702 703 public: 704 Pool(): arrays(NULL), nextArray(NULL), freeObjects(NULL), arraySize(256) 705 { 706 } 707 708 ~Pool() 709 { 710 while (arrays) 711 { 712 PoolArray<T>* p = arrays; 713 arrays = p->next; 714 p->~PoolArray<T>(); 715 btAlignedFree(p); 716 } 717 } 718 719 void reset() 720 { 721 nextArray = arrays; 722 freeObjects = NULL; 723 } 724 725 void setArraySize(int arraySize) 726 { 727 this->arraySize = arraySize; 728 } 729 730 T* newObject() 731 { 732 T* o = freeObjects; 733 if (!o) 734 { 735 PoolArray<T>* p = nextArray; 736 if (p) 737 { 738 nextArray = p->next; 739 } 740 else 741 { 742 p = new(btAlignedAlloc(sizeof(PoolArray<T>), 16)) PoolArray<T>(arraySize); 743 p->next = arrays; 744 arrays = p; 745 } 746 o = p->init(); 747 } 748 freeObjects = o->next; 749 return new(o) T(); 750 }; 751 752 void freeObject(T* object) 753 { 754 object->~T(); 755 object->next = freeObjects; 756 freeObjects = object; 757 } 758 }; 759 760 btVector3 scaling; 761 btVector3 center; 762 Pool<Vertex> vertexPool; 763 Pool<Edge> edgePool; 764 Pool<Face> facePool; 765 btAlignedObjectArray<Vertex*> originalVertices; 766 int mergeStamp; 767 int minAxis; 768 int medAxis; 769 int maxAxis; 770 int usedEdgePairs; 771 int maxUsedEdgePairs; 772 773 static Orientation getOrientation(const Edge* prev, const Edge* next, const Point32& s, const Point32& t); 774 Edge* findMaxAngle(bool ccw, const Vertex* start, const Point32& s, const Point64& rxs, const Point64& sxrxs, Rational64& minCot); 775 void findEdgeForCoplanarFaces(Vertex* c0, Vertex* c1, Edge*& e0, Edge*& e1, Vertex* stop0, Vertex* stop1); 776 777 Edge* newEdgePair(Vertex* from, Vertex* to); 778 779 void removeEdgePair(Edge* edge) 780 { 781 Edge* n = edge->next; 782 Edge* r = edge->reverse; 783 784 btAssert(edge->target && r->target); 785 786 if (n != edge) 787 { 788 n->prev = edge->prev; 789 edge->prev->next = n; 790 r->target->edges = n; 791 } 792 else 793 { 794 r->target->edges = NULL; 795 } 796 797 n = r->next; 798 799 if (n != r) 800 { 801 n->prev = r->prev; 802 r->prev->next = n; 803 edge->target->edges = n; 804 } 805 else 806 { 807 edge->target->edges = NULL; 808 } 809 810 edgePool.freeObject(edge); 811 edgePool.freeObject(r); 812 usedEdgePairs--; 813 } 814 815 void computeInternal(int start, int end, IntermediateHull& result); 816 817 bool mergeProjection(IntermediateHull& h0, IntermediateHull& h1, Vertex*& c0, Vertex*& c1); 818 819 void merge(IntermediateHull& h0, IntermediateHull& h1); 820 821 btVector3 toBtVector(const Point32& v); 822 823 btVector3 getBtNormal(Face* face); 824 825 bool shiftFace(Face* face, btScalar amount, btAlignedObjectArray<Vertex*> stack); 826 827 public: 828 Vertex* vertexList; 829 830 void compute(const void* coords, bool doubleCoords, int stride, int count); 831 832 btVector3 getCoordinates(const Vertex* v); 833 834 btScalar shrink(btScalar amount, btScalar clampAmount); 835 }; 836 837 838 btConvexHullInternal::Int128 btConvexHullInternal::Int128::operator*(int64_t b) const 839 { 840 bool negative = (int64_t) high < 0; 841 Int128 a = negative ? -*this : *this; 842 if (b < 0) 843 { 844 negative = !negative; 845 b = -b; 846 } 847 Int128 result = mul(a.low, (uint64_t) b); 848 result.high += a.high * (uint64_t) b; 849 return negative ? -result : result; 850 } 851 852 btConvexHullInternal::Int128 btConvexHullInternal::Int128::mul(int64_t a, int64_t b) 853 { 854 Int128 result; 855 856 #ifdef USE_X86_64_ASM 857 __asm__ ("imulq %[b]" 858 : "=a" (result.low), "=d" (result.high) 859 : "0"(a), [b] "r"(b) 860 : "cc" ); 861 return result; 862 863 #else 864 bool negative = a < 0; 865 if (negative) 866 { 867 a = -a; 868 } 869 if (b < 0) 870 { 871 negative = !negative; 872 b = -b; 873 } 874 DMul<uint64_t, uint32_t>::mul((uint64_t) a, (uint64_t) b, result.low, result.high); 875 return negative ? -result : result; 876 #endif 877 } 878 879 btConvexHullInternal::Int128 btConvexHullInternal::Int128::mul(uint64_t a, uint64_t b) 880 { 881 Int128 result; 882 883 #ifdef USE_X86_64_ASM 884 __asm__ ("mulq %[b]" 885 : "=a" (result.low), "=d" (result.high) 886 : "0"(a), [b] "r"(b) 887 : "cc" ); 888 889 #else 890 DMul<uint64_t, uint32_t>::mul(a, b, result.low, result.high); 891 #endif 892 893 return result; 894 } 895 896 int btConvexHullInternal::Rational64::compare(const Rational64& b) const 897 { 898 if (sign != b.sign) 899 { 900 return sign - b.sign; 901 } 902 else if (sign == 0) 903 { 904 return 0; 905 } 906 907 // return (numerator * b.denominator > b.numerator * denominator) ? sign : (numerator * b.denominator < b.numerator * denominator) ? -sign : 0; 908 909 #ifdef USE_X86_64_ASM 910 911 int result; 912 int64_t tmp; 913 int64_t dummy; 914 __asm__ ("mulq %[bn]\n\t" 915 "movq %%rax, %[tmp]\n\t" 916 "movq %%rdx, %%rbx\n\t" 917 "movq %[tn], %%rax\n\t" 918 "mulq %[bd]\n\t" 919 "subq %[tmp], %%rax\n\t" 920 "sbbq %%rbx, %%rdx\n\t" // rdx:rax contains 128-bit-difference "numerator*b.denominator - b.numerator*denominator" 921 "setnsb %%bh\n\t" // bh=1 if difference is non-negative, bh=0 otherwise 922 "orq %%rdx, %%rax\n\t" 923 "setnzb %%bl\n\t" // bl=1 if difference if non-zero, bl=0 if it is zero 924 "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) 925 "shll $16, %%ebx\n\t" // ebx has same sign as difference 926 : "=&b"(result), [tmp] "=&r"(tmp), "=a"(dummy) 927 : "a"(denominator), [bn] "g"(b.numerator), [tn] "g"(numerator), [bd] "g"(b.denominator) 928 : "%rdx", "cc" ); 929 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) 930 // if sign is -1, all bits of result are inverted, which changes the sign of result (and again cannot result in zero) 931 : 0; 932 933 #else 934 935 return sign * Int128::mul(m_numerator, b.m_denominator).ucmp(Int128::mul(m_denominator, b.m_numerator)); 936 937 #endif 938 } 939 940 int btConvexHullInternal::Rational128::compare(const Rational128& b) const 941 { 942 if (sign != b.sign) 943 { 944 return sign - b.sign; 945 } 946 else if (sign == 0) 947 { 948 return 0; 949 } 950 if (isInt64) 951 { 952 return -b.compare(sign * (int64_t) numerator.low); 953 } 954 955 Int128 nbdLow, nbdHigh, dbnLow, dbnHigh; 956 DMul<Int128, uint64_t>::mul(numerator, b.denominator, nbdLow, nbdHigh); 957 DMul<Int128, uint64_t>::mul(denominator, b.numerator, dbnLow, dbnHigh); 958 959 int cmp = nbdHigh.ucmp(dbnHigh); 960 if (cmp) 961 { 962 return cmp * sign; 963 } 964 return nbdLow.ucmp(dbnLow) * sign; 965 } 966 967 int btConvexHullInternal::Rational128::compare(int64_t b) const 968 { 969 if (isInt64) 970 { 971 int64_t a = sign * (int64_t) numerator.low; 972 return (a > b) ? 1 : (a < b) ? -1 : 0; 973 } 974 if (b > 0) 975 { 976 if (sign <= 0) 977 { 978 return -1; 979 } 980 } 981 else if (b < 0) 982 { 983 if (sign >= 0) 984 { 985 return 1; 986 } 987 b = -b; 988 } 989 else 990 { 991 return sign; 992 } 993 994 return numerator.ucmp(denominator * b) * sign; 995 } 996 997 998 btConvexHullInternal::Edge* btConvexHullInternal::newEdgePair(Vertex* from, Vertex* to) 999 { 1000 btAssert(from && to); 1001 Edge* e = edgePool.newObject(); 1002 Edge* r = edgePool.newObject(); 1003 e->reverse = r; 1004 r->reverse = e; 1005 e->copy = mergeStamp; 1006 r->copy = mergeStamp; 1007 e->target = to; 1008 r->target = from; 1009 e->face = NULL; 1010 r->face = NULL; 1011 usedEdgePairs++; 1012 if (usedEdgePairs > maxUsedEdgePairs) 1013 { 1014 maxUsedEdgePairs = usedEdgePairs; 1015 } 1016 return e; 1017 } 1018 1019 bool btConvexHullInternal::mergeProjection(IntermediateHull& h0, IntermediateHull& h1, Vertex*& c0, Vertex*& c1) 1020 { 1021 Vertex* v0 = h0.maxYx; 1022 Vertex* v1 = h1.minYx; 1023 if ((v0->point.x == v1->point.x) && (v0->point.y == v1->point.y)) 1024 { 1025 btAssert(v0->point.z < v1->point.z); 1026 Vertex* v1p = v1->prev; 1027 if (v1p == v1) 1028 { 1029 c0 = v0; 1030 if (v1->edges) 1031 { 1032 btAssert(v1->edges->next == v1->edges); 1033 v1 = v1->edges->target; 1034 btAssert(v1->edges->next == v1->edges); 1035 } 1036 c1 = v1; 1037 return false; 1038 } 1039 Vertex* v1n = v1->next; 1040 v1p->next = v1n; 1041 v1n->prev = v1p; 1042 if (v1 == h1.minXy) 1043 { 1044 if ((v1n->point.x < v1p->point.x) || ((v1n->point.x == v1p->point.x) && (v1n->point.y < v1p->point.y))) 1045 { 1046 h1.minXy = v1n; 1047 } 1048 else 1049 { 1050 h1.minXy = v1p; 1051 } 1052 } 1053 if (v1 == h1.maxXy) 1054 { 1055 if ((v1n->point.x > v1p->point.x) || ((v1n->point.x == v1p->point.x) && (v1n->point.y > v1p->point.y))) 1056 { 1057 h1.maxXy = v1n; 1058 } 1059 else 1060 { 1061 h1.maxXy = v1p; 1062 } 1063 } 1064 } 1065 1066 v0 = h0.maxXy; 1067 v1 = h1.maxXy; 1068 Vertex* v00 = NULL; 1069 Vertex* v10 = NULL; 1070 int32_t sign = 1; 1071 1072 for (int side = 0; side <= 1; side++) 1073 { 1074 int32_t dx = (v1->point.x - v0->point.x) * sign; 1075 if (dx > 0) 1076 { 1077 while (true) 1078 { 1079 int32_t dy = v1->point.y - v0->point.y; 1080 1081 Vertex* w0 = side ? v0->next : v0->prev; 1082 if (w0 != v0) 1083 { 1084 int32_t dx0 = (w0->point.x - v0->point.x) * sign; 1085 int32_t dy0 = w0->point.y - v0->point.y; 1086 if ((dy0 <= 0) && ((dx0 == 0) || ((dx0 < 0) && (dy0 * dx <= dy * dx0)))) 1087 { 1088 v0 = w0; 1089 dx = (v1->point.x - v0->point.x) * sign; 1090 continue; 1091 } 1092 } 1093 1094 Vertex* w1 = side ? v1->next : v1->prev; 1095 if (w1 != v1) 1096 { 1097 int32_t dx1 = (w1->point.x - v1->point.x) * sign; 1098 int32_t dy1 = w1->point.y - v1->point.y; 1099 int32_t dxn = (w1->point.x - v0->point.x) * sign; 1100 if ((dxn > 0) && (dy1 < 0) && ((dx1 == 0) || ((dx1 < 0) && (dy1 * dx < dy * dx1)))) 1101 { 1102 v1 = w1; 1103 dx = dxn; 1104 continue; 1105 } 1106 } 1107 1108 break; 1109 } 1110 } 1111 else if (dx < 0) 1112 { 1113 while (true) 1114 { 1115 int32_t dy = v1->point.y - v0->point.y; 1116 1117 Vertex* w1 = side ? v1->prev : v1->next; 1118 if (w1 != v1) 1119 { 1120 int32_t dx1 = (w1->point.x - v1->point.x) * sign; 1121 int32_t dy1 = w1->point.y - v1->point.y; 1122 if ((dy1 >= 0) && ((dx1 == 0) || ((dx1 < 0) && (dy1 * dx <= dy * dx1)))) 1123 { 1124 v1 = w1; 1125 dx = (v1->point.x - v0->point.x) * sign; 1126 continue; 1127 } 1128 } 1129 1130 Vertex* w0 = side ? v0->prev : v0->next; 1131 if (w0 != v0) 1132 { 1133 int32_t dx0 = (w0->point.x - v0->point.x) * sign; 1134 int32_t dy0 = w0->point.y - v0->point.y; 1135 int32_t dxn = (v1->point.x - w0->point.x) * sign; 1136 if ((dxn < 0) && (dy0 > 0) && ((dx0 == 0) || ((dx0 < 0) && (dy0 * dx < dy * dx0)))) 1137 { 1138 v0 = w0; 1139 dx = dxn; 1140 continue; 1141 } 1142 } 1143 1144 break; 1145 } 1146 } 1147 else 1148 { 1149 int32_t x = v0->point.x; 1150 int32_t y0 = v0->point.y; 1151 Vertex* w0 = v0; 1152 Vertex* t; 1153 while (((t = side ? w0->next : w0->prev) != v0) && (t->point.x == x) && (t->point.y <= y0)) 1154 { 1155 w0 = t; 1156 y0 = t->point.y; 1157 } 1158 v0 = w0; 1159 1160 int32_t y1 = v1->point.y; 1161 Vertex* w1 = v1; 1162 while (((t = side ? w1->prev : w1->next) != v1) && (t->point.x == x) && (t->point.y >= y1)) 1163 { 1164 w1 = t; 1165 y1 = t->point.y; 1166 } 1167 v1 = w1; 1168 } 1169 1170 if (side == 0) 1171 { 1172 v00 = v0; 1173 v10 = v1; 1174 1175 v0 = h0.minXy; 1176 v1 = h1.minXy; 1177 sign = -1; 1178 } 1179 } 1180 1181 v0->prev = v1; 1182 v1->next = v0; 1183 1184 v00->next = v10; 1185 v10->prev = v00; 1186 1187 if (h1.minXy->point.x < h0.minXy->point.x) 1188 { 1189 h0.minXy = h1.minXy; 1190 } 1191 if (h1.maxXy->point.x >= h0.maxXy->point.x) 1192 { 1193 h0.maxXy = h1.maxXy; 1194 } 1195 1196 h0.maxYx = h1.maxYx; 1197 1198 c0 = v00; 1199 c1 = v10; 1200 1201 return true; 1202 } 1203 1204 void btConvexHullInternal::computeInternal(int start, int end, IntermediateHull& result) 1205 { 1206 int n = end - start; 1207 switch (n) 1208 { 1209 case 0: 1210 result.minXy = NULL; 1211 result.maxXy = NULL; 1212 result.minYx = NULL; 1213 result.maxYx = NULL; 1214 return; 1215 case 2: 1216 { 1217 Vertex* v = originalVertices[start]; 1218 Vertex* w = v + 1; 1219 if (v->point != w->point) 1220 { 1221 int32_t dx = v->point.x - w->point.x; 1222 int32_t dy = v->point.y - w->point.y; 1223 1224 if ((dx == 0) && (dy == 0)) 1225 { 1226 if (v->point.z > w->point.z) 1227 { 1228 Vertex* t = w; 1229 w = v; 1230 v = t; 1231 } 1232 btAssert(v->point.z < w->point.z); 1233 v->next = v; 1234 v->prev = v; 1235 result.minXy = v; 1236 result.maxXy = v; 1237 result.minYx = v; 1238 result.maxYx = v; 1239 } 1240 else 1241 { 1242 v->next = w; 1243 v->prev = w; 1244 w->next = v; 1245 w->prev = v; 1246 1247 if ((dx < 0) || ((dx == 0) && (dy < 0))) 1248 { 1249 result.minXy = v; 1250 result.maxXy = w; 1251 } 1252 else 1253 { 1254 result.minXy = w; 1255 result.maxXy = v; 1256 } 1257 1258 if ((dy < 0) || ((dy == 0) && (dx < 0))) 1259 { 1260 result.minYx = v; 1261 result.maxYx = w; 1262 } 1263 else 1264 { 1265 result.minYx = w; 1266 result.maxYx = v; 1267 } 1268 } 1269 1270 Edge* e = newEdgePair(v, w); 1271 e->link(e); 1272 v->edges = e; 1273 1274 e = e->reverse; 1275 e->link(e); 1276 w->edges = e; 1277 1278 return; 1279 } 1280 } 1281 // lint -fallthrough 1282 case 1: 1283 { 1284 Vertex* v = originalVertices[start]; 1285 v->edges = NULL; 1286 v->next = v; 1287 v->prev = v; 1288 1289 result.minXy = v; 1290 result.maxXy = v; 1291 result.minYx = v; 1292 result.maxYx = v; 1293 1294 return; 1295 } 1296 } 1297 1298 int split0 = start + n / 2; 1299 Point32 p = originalVertices[split0-1]->point; 1300 int split1 = split0; 1301 while ((split1 < end) && (originalVertices[split1]->point == p)) 1302 { 1303 split1++; 1304 } 1305 computeInternal(start, split0, result); 1306 IntermediateHull hull1; 1307 computeInternal(split1, end, hull1); 1308 #ifdef DEBUG_CONVEX_HULL 1309 printf("\n\nMerge\n"); 1310 result.print(); 1311 hull1.print(); 1312 #endif 1313 merge(result, hull1); 1314 #ifdef DEBUG_CONVEX_HULL 1315 printf("\n Result\n"); 1316 result.print(); 1317 #endif 1318 } 1319 1320 #ifdef DEBUG_CONVEX_HULL 1321 void btConvexHullInternal::IntermediateHull::print() 1322 { 1323 printf(" Hull\n"); 1324 for (Vertex* v = minXy; v; ) 1325 { 1326 printf(" "); 1327 v->print(); 1328 if (v == maxXy) 1329 { 1330 printf(" maxXy"); 1331 } 1332 if (v == minYx) 1333 { 1334 printf(" minYx"); 1335 } 1336 if (v == maxYx) 1337 { 1338 printf(" maxYx"); 1339 } 1340 if (v->next->prev != v) 1341 { 1342 printf(" Inconsistency"); 1343 } 1344 printf("\n"); 1345 v = v->next; 1346 if (v == minXy) 1347 { 1348 break; 1349 } 1350 } 1351 if (minXy) 1352 { 1353 minXy->copy = (minXy->copy == -1) ? -2 : -1; 1354 minXy->printGraph(); 1355 } 1356 } 1357 1358 void btConvexHullInternal::Vertex::printGraph() 1359 { 1360 print(); 1361 printf("\nEdges\n"); 1362 Edge* e = edges; 1363 if (e) 1364 { 1365 do 1366 { 1367 e->print(); 1368 printf("\n"); 1369 e = e->next; 1370 } while (e != edges); 1371 do 1372 { 1373 Vertex* v = e->target; 1374 if (v->copy != copy) 1375 { 1376 v->copy = copy; 1377 v->printGraph(); 1378 } 1379 e = e->next; 1380 } while (e != edges); 1381 } 1382 } 1383 #endif 1384 1385 btConvexHullInternal::Orientation btConvexHullInternal::getOrientation(const Edge* prev, const Edge* next, const Point32& s, const Point32& t) 1386 { 1387 btAssert(prev->reverse->target == next->reverse->target); 1388 if (prev->next == next) 1389 { 1390 if (prev->prev == next) 1391 { 1392 Point64 n = t.cross(s); 1393 Point64 m = (*prev->target - *next->reverse->target).cross(*next->target - *next->reverse->target); 1394 btAssert(!m.isZero()); 1395 int64_t dot = n.dot(m); 1396 btAssert(dot != 0); 1397 return (dot > 0) ? COUNTER_CLOCKWISE : CLOCKWISE; 1398 } 1399 return COUNTER_CLOCKWISE; 1400 } 1401 else if (prev->prev == next) 1402 { 1403 return CLOCKWISE; 1404 } 1405 else 1406 { 1407 return NONE; 1408 } 1409 } 1410 1411 btConvexHullInternal::Edge* btConvexHullInternal::findMaxAngle(bool ccw, const Vertex* start, const Point32& s, const Point64& rxs, const Point64& sxrxs, Rational64& minCot) 1412 { 1413 Edge* minEdge = NULL; 1414 1415 #ifdef DEBUG_CONVEX_HULL 1416 printf("find max edge for %d\n", start->point.index); 1417 #endif 1418 Edge* e = start->edges; 1419 if (e) 1420 { 1421 do 1422 { 1423 if (e->copy > mergeStamp) 1424 { 1425 Point32 t = *e->target - *start; 1426 Rational64 cot(t.dot(sxrxs), t.dot(rxs)); 1427 #ifdef DEBUG_CONVEX_HULL 1428 printf(" Angle is %f (%d) for ", (float) btAtan(cot.toScalar()), (int) cot.isNaN()); 1429 e->print(); 1430 #endif 1431 if (cot.isNaN()) 1432 { 1433 btAssert(ccw ? (t.dot(s) < 0) : (t.dot(s) > 0)); 1434 } 1435 else 1436 { 1437 int cmp; 1438 if (minEdge == NULL) 1439 { 1440 minCot = cot; 1441 minEdge = e; 1442 } 1443 else if ((cmp = cot.compare(minCot)) < 0) 1444 { 1445 minCot = cot; 1446 minEdge = e; 1447 } 1448 else if ((cmp == 0) && (ccw == (getOrientation(minEdge, e, s, t) == COUNTER_CLOCKWISE))) 1449 { 1450 minEdge = e; 1451 } 1452 } 1453 #ifdef DEBUG_CONVEX_HULL 1454 printf("\n"); 1455 #endif 1456 } 1457 e = e->next; 1458 } while (e != start->edges); 1459 } 1460 return minEdge; 1461 } 1462 1463 void btConvexHullInternal::findEdgeForCoplanarFaces(Vertex* c0, Vertex* c1, Edge*& e0, Edge*& e1, Vertex* stop0, Vertex* stop1) 1464 { 1465 Edge* start0 = e0; 1466 Edge* start1 = e1; 1467 Point32 et0 = start0 ? start0->target->point : c0->point; 1468 Point32 et1 = start1 ? start1->target->point : c1->point; 1469 Point32 s = c1->point - c0->point; 1470 Point64 normal = ((start0 ? start0 : start1)->target->point - c0->point).cross(s); 1471 int64_t dist = c0->point.dot(normal); 1472 btAssert(!start1 || (start1->target->point.dot(normal) == dist)); 1473 Point64 perp = s.cross(normal); 1474 btAssert(!perp.isZero()); 1475 1476 #ifdef DEBUG_CONVEX_HULL 1477 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); 1478 #endif 1479 1480 int64_t maxDot0 = et0.dot(perp); 1481 if (e0) 1482 { 1483 while (e0->target != stop0) 1484 { 1485 Edge* e = e0->reverse->prev; 1486 if (e->target->point.dot(normal) < dist) 1487 { 1488 break; 1489 } 1490 btAssert(e->target->point.dot(normal) == dist); 1491 if (e->copy == mergeStamp) 1492 { 1493 break; 1494 } 1495 int64_t dot = e->target->point.dot(perp); 1496 if (dot <= maxDot0) 1497 { 1498 break; 1499 } 1500 maxDot0 = dot; 1501 e0 = e; 1502 et0 = e->target->point; 1503 } 1504 } 1505 1506 int64_t maxDot1 = et1.dot(perp); 1507 if (e1) 1508 { 1509 while (e1->target != stop1) 1510 { 1511 Edge* e = e1->reverse->next; 1512 if (e->target->point.dot(normal) < dist) 1513 { 1514 break; 1515 } 1516 btAssert(e->target->point.dot(normal) == dist); 1517 if (e->copy == mergeStamp) 1518 { 1519 break; 1520 } 1521 int64_t dot = e->target->point.dot(perp); 1522 if (dot <= maxDot1) 1523 { 1524 break; 1525 } 1526 maxDot1 = dot; 1527 e1 = e; 1528 et1 = e->target->point; 1529 } 1530 } 1531 1532 #ifdef DEBUG_CONVEX_HULL 1533 printf(" Starting at %d %d\n", et0.index, et1.index); 1534 #endif 1535 1536 int64_t dx = maxDot1 - maxDot0; 1537 if (dx > 0) 1538 { 1539 while (true) 1540 { 1541 int64_t dy = (et1 - et0).dot(s); 1542 1543 if (e0 && (e0->target != stop0)) 1544 { 1545 Edge* f0 = e0->next->reverse; 1546 if (f0->copy > mergeStamp) 1547 { 1548 int64_t dx0 = (f0->target->point - et0).dot(perp); 1549 int64_t dy0 = (f0->target->point - et0).dot(s); 1550 if ((dx0 == 0) ? (dy0 < 0) : ((dx0 < 0) && (Rational64(dy0, dx0).compare(Rational64(dy, dx)) >= 0))) 1551 { 1552 et0 = f0->target->point; 1553 dx = (et1 - et0).dot(perp); 1554 e0 = (e0 == start0) ? NULL : f0; 1555 continue; 1556 } 1557 } 1558 } 1559 1560 if (e1 && (e1->target != stop1)) 1561 { 1562 Edge* f1 = e1->reverse->next; 1563 if (f1->copy > mergeStamp) 1564 { 1565 Point32 d1 = f1->target->point - et1; 1566 if (d1.dot(normal) == 0) 1567 { 1568 int64_t dx1 = d1.dot(perp); 1569 int64_t dy1 = d1.dot(s); 1570 int64_t dxn = (f1->target->point - et0).dot(perp); 1571 if ((dxn > 0) && ((dx1 == 0) ? (dy1 < 0) : ((dx1 < 0) && (Rational64(dy1, dx1).compare(Rational64(dy, dx)) > 0)))) 1572 { 1573 e1 = f1; 1574 et1 = e1->target->point; 1575 dx = dxn; 1576 continue; 1577 } 1578 } 1579 else 1580 { 1581 btAssert((e1 == start1) && (d1.dot(normal) < 0)); 1582 } 1583 } 1584 } 1585 1586 break; 1587 } 1588 } 1589 else if (dx < 0) 1590 { 1591 while (true) 1592 { 1593 int64_t dy = (et1 - et0).dot(s); 1594 1595 if (e1 && (e1->target != stop1)) 1596 { 1597 Edge* f1 = e1->prev->reverse; 1598 if (f1->copy > mergeStamp) 1599 { 1600 int64_t dx1 = (f1->target->point - et1).dot(perp); 1601 int64_t dy1 = (f1->target->point - et1).dot(s); 1602 if ((dx1 == 0) ? (dy1 > 0) : ((dx1 < 0) && (Rational64(dy1, dx1).compare(Rational64(dy, dx)) <= 0))) 1603 { 1604 et1 = f1->target->point; 1605 dx = (et1 - et0).dot(perp); 1606 e1 = (e1 == start1) ? NULL : f1; 1607 continue; 1608 } 1609 } 1610 } 1611 1612 if (e0 && (e0->target != stop0)) 1613 { 1614 Edge* f0 = e0->reverse->prev; 1615 if (f0->copy > mergeStamp) 1616 { 1617 Point32 d0 = f0->target->point - et0; 1618 if (d0.dot(normal) == 0) 1619 { 1620 int64_t dx0 = d0.dot(perp); 1621 int64_t dy0 = d0.dot(s); 1622 int64_t dxn = (et1 - f0->target->point).dot(perp); 1623 if ((dxn < 0) && ((dx0 == 0) ? (dy0 > 0) : ((dx0 < 0) && (Rational64(dy0, dx0).compare(Rational64(dy, dx)) < 0)))) 1624 { 1625 e0 = f0; 1626 et0 = e0->target->point; 1627 dx = dxn; 1628 continue; 1629 } 1630 } 1631 else 1632 { 1633 btAssert((e0 == start0) && (d0.dot(normal) < 0)); 1634 } 1635 } 1636 } 1637 1638 break; 1639 } 1640 } 1641 #ifdef DEBUG_CONVEX_HULL 1642 printf(" Advanced edges to %d %d\n", et0.index, et1.index); 1643 #endif 1644 } 1645 1646 1647 void btConvexHullInternal::merge(IntermediateHull& h0, IntermediateHull& h1) 1648 { 1649 if (!h1.maxXy) 1650 { 1651 return; 1652 } 1653 if (!h0.maxXy) 1654 { 1655 h0 = h1; 1656 return; 1657 } 1658 1659 mergeStamp--; 1660 1661 Vertex* c0 = NULL; 1662 Edge* toPrev0 = NULL; 1663 Edge* firstNew0 = NULL; 1664 Edge* pendingHead0 = NULL; 1665 Edge* pendingTail0 = NULL; 1666 Vertex* c1 = NULL; 1667 Edge* toPrev1 = NULL; 1668 Edge* firstNew1 = NULL; 1669 Edge* pendingHead1 = NULL; 1670 Edge* pendingTail1 = NULL; 1671 Point32 prevPoint; 1672 1673 if (mergeProjection(h0, h1, c0, c1)) 1674 { 1675 Point32 s = *c1 - *c0; 1676 Point64 normal = Point32(0, 0, -1).cross(s); 1677 Point64 t = s.cross(normal); 1678 btAssert(!t.isZero()); 1679 1680 Edge* e = c0->edges; 1681 Edge* start0 = NULL; 1682 if (e) 1683 { 1684 do 1685 { 1686 int64_t dot = (*e->target - *c0).dot(normal); 1687 btAssert(dot <= 0); 1688 if ((dot == 0) && ((*e->target - *c0).dot(t) > 0)) 1689 { 1690 if (!start0 || (getOrientation(start0, e, s, Point32(0, 0, -1)) == CLOCKWISE)) 1691 { 1692 start0 = e; 1693 } 1694 } 1695 e = e->next; 1696 } while (e != c0->edges); 1697 } 1698 1699 e = c1->edges; 1700 Edge* start1 = NULL; 1701 if (e) 1702 { 1703 do 1704 { 1705 int64_t dot = (*e->target - *c1).dot(normal); 1706 btAssert(dot <= 0); 1707 if ((dot == 0) && ((*e->target - *c1).dot(t) > 0)) 1708 { 1709 if (!start1 || (getOrientation(start1, e, s, Point32(0, 0, -1)) == COUNTER_CLOCKWISE)) 1710 { 1711 start1 = e; 1712 } 1713 } 1714 e = e->next; 1715 } while (e != c1->edges); 1716 } 1717 1718 if (start0 || start1) 1719 { 1720 findEdgeForCoplanarFaces(c0, c1, start0, start1, NULL, NULL); 1721 if (start0) 1722 { 1723 c0 = start0->target; 1724 } 1725 if (start1) 1726 { 1727 c1 = start1->target; 1728 } 1729 } 1730 1731 prevPoint = c1->point; 1732 prevPoint.z++; 1733 } 1734 else 1735 { 1736 prevPoint = c1->point; 1737 prevPoint.x++; 1738 } 1739 1740 Vertex* first0 = c0; 1741 Vertex* first1 = c1; 1742 bool firstRun = true; 1743 1744 while (true) 1745 { 1746 Point32 s = *c1 - *c0; 1747 Point32 r = prevPoint - c0->point; 1748 Point64 rxs = r.cross(s); 1749 Point64 sxrxs = s.cross(rxs); 1750 1751 #ifdef DEBUG_CONVEX_HULL 1752 printf("\n Checking %d %d\n", c0->point.index, c1->point.index); 1753 #endif 1754 Rational64 minCot0(0, 0); 1755 Edge* min0 = findMaxAngle(false, c0, s, rxs, sxrxs, minCot0); 1756 Rational64 minCot1(0, 0); 1757 Edge* min1 = findMaxAngle(true, c1, s, rxs, sxrxs, minCot1); 1758 if (!min0 && !min1) 1759 { 1760 Edge* e = newEdgePair(c0, c1); 1761 e->link(e); 1762 c0->edges = e; 1763 1764 e = e->reverse; 1765 e->link(e); 1766 c1->edges = e; 1767 return; 1768 } 1769 else 1770 { 1771 int cmp = !min0 ? 1 : !min1 ? -1 : minCot0.compare(minCot1); 1772 #ifdef DEBUG_CONVEX_HULL 1773 printf(" -> Result %d\n", cmp); 1774 #endif 1775 if (firstRun || ((cmp >= 0) ? !minCot1.isNegativeInfinity() : !minCot0.isNegativeInfinity())) 1776 { 1777 Edge* e = newEdgePair(c0, c1); 1778 if (pendingTail0) 1779 { 1780 pendingTail0->prev = e; 1781 } 1782 else 1783 { 1784 pendingHead0 = e; 1785 } 1786 e->next = pendingTail0; 1787 pendingTail0 = e; 1788 1789 e = e->reverse; 1790 if (pendingTail1) 1791 { 1792 pendingTail1->next = e; 1793 } 1794 else 1795 { 1796 pendingHead1 = e; 1797 } 1798 e->prev = pendingTail1; 1799 pendingTail1 = e; 1800 } 1801 1802 Edge* e0 = min0; 1803 Edge* e1 = min1; 1804 1805 #ifdef DEBUG_CONVEX_HULL 1806 printf(" Found min edges to %d %d\n", e0 ? e0->target->point.index : -1, e1 ? e1->target->point.index : -1); 1807 #endif 1808 1809 if (cmp == 0) 1810 { 1811 findEdgeForCoplanarFaces(c0, c1, e0, e1, NULL, NULL); 1812 } 1813 1814 if ((cmp >= 0) && e1) 1815 { 1816 if (toPrev1) 1817 { 1818 for (Edge* e = toPrev1->next, *n = NULL; e != min1; e = n) 1819 { 1820 n = e->next; 1821 removeEdgePair(e); 1822 } 1823 } 1824 1825 if (pendingTail1) 1826 { 1827 if (toPrev1) 1828 { 1829 toPrev1->link(pendingHead1); 1830 } 1831 else 1832 { 1833 min1->prev->link(pendingHead1); 1834 firstNew1 = pendingHead1; 1835 } 1836 pendingTail1->link(min1); 1837 pendingHead1 = NULL; 1838 pendingTail1 = NULL; 1839 } 1840 else if (!toPrev1) 1841 { 1842 firstNew1 = min1; 1843 } 1844 1845 prevPoint = c1->point; 1846 c1 = e1->target; 1847 toPrev1 = e1->reverse; 1848 } 1849 1850 if ((cmp <= 0) && e0) 1851 { 1852 if (toPrev0) 1853 { 1854 for (Edge* e = toPrev0->prev, *n = NULL; e != min0; e = n) 1855 { 1856 n = e->prev; 1857 removeEdgePair(e); 1858 } 1859 } 1860 1861 if (pendingTail0) 1862 { 1863 if (toPrev0) 1864 { 1865 pendingHead0->link(toPrev0); 1866 } 1867 else 1868 { 1869 pendingHead0->link(min0->next); 1870 firstNew0 = pendingHead0; 1871 } 1872 min0->link(pendingTail0); 1873 pendingHead0 = NULL; 1874 pendingTail0 = NULL; 1875 } 1876 else if (!toPrev0) 1877 { 1878 firstNew0 = min0; 1879 } 1880 1881 prevPoint = c0->point; 1882 c0 = e0->target; 1883 toPrev0 = e0->reverse; 1884 } 1885 } 1886 1887 if ((c0 == first0) && (c1 == first1)) 1888 { 1889 if (toPrev0 == NULL) 1890 { 1891 pendingHead0->link(pendingTail0); 1892 c0->edges = pendingTail0; 1893 } 1894 else 1895 { 1896 for (Edge* e = toPrev0->prev, *n = NULL; e != firstNew0; e = n) 1897 { 1898 n = e->prev; 1899 removeEdgePair(e); 1900 } 1901 if (pendingTail0) 1902 { 1903 pendingHead0->link(toPrev0); 1904 firstNew0->link(pendingTail0); 1905 } 1906 } 1907 1908 if (toPrev1 == NULL) 1909 { 1910 pendingTail1->link(pendingHead1); 1911 c1->edges = pendingTail1; 1912 } 1913 else 1914 { 1915 for (Edge* e = toPrev1->next, *n = NULL; e != firstNew1; e = n) 1916 { 1917 n = e->next; 1918 removeEdgePair(e); 1919 } 1920 if (pendingTail1) 1921 { 1922 toPrev1->link(pendingHead1); 1923 pendingTail1->link(firstNew1); 1924 } 1925 } 1926 1927 return; 1928 } 1929 1930 firstRun = false; 1931 } 1932 } 1933 1934 class pointCmp 1935 { 1936 public: 1937 1938 bool operator() ( const btConvexHullInternal::Point32& p, const btConvexHullInternal::Point32& q ) const 1939 { 1940 return (p.y < q.y) || ((p.y == q.y) && ((p.x < q.x) || ((p.x == q.x) && (p.z < q.z)))); 1941 } 1942 }; 1943 1944 void btConvexHullInternal::compute(const void* coords, bool doubleCoords, int stride, int count) 1945 { 1946 btVector3 min(btScalar(1e30), btScalar(1e30), btScalar(1e30)), max(btScalar(-1e30), btScalar(-1e30), btScalar(-1e30)); 1947 const char* ptr = (const char*) coords; 1948 if (doubleCoords) 1949 { 1950 for (int i = 0; i < count; i++) 1951 { 1952 const double* v = (const double*) ptr; 1953 btVector3 p((btScalar) v[0], (btScalar) v[1], (btScalar) v[2]); 1954 ptr += stride; 1955 min.setMin(p); 1956 max.setMax(p); 1957 } 1958 } 1959 else 1960 { 1961 for (int i = 0; i < count; i++) 1962 { 1963 const float* v = (const float*) ptr; 1964 btVector3 p(v[0], v[1], v[2]); 1965 ptr += stride; 1966 min.setMin(p); 1967 max.setMax(p); 1968 } 1969 } 1970 1971 btVector3 s = max - min; 1972 maxAxis = s.maxAxis(); 1973 minAxis = s.minAxis(); 1974 if (minAxis == maxAxis) 1975 { 1976 minAxis = (maxAxis + 1) % 3; 1977 } 1978 medAxis = 3 - maxAxis - minAxis; 1979 1980 s /= btScalar(10216); 1981 if (((medAxis + 1) % 3) != maxAxis) 1982 { 1983 s *= -1; 1984 } 1985 scaling = s; 1986 1987 if (s[0] != 0) 1988 { 1989 s[0] = btScalar(1) / s[0]; 1990 } 1991 if (s[1] != 0) 1992 { 1993 s[1] = btScalar(1) / s[1]; 1994 } 1995 if (s[2] != 0) 1996 { 1997 s[2] = btScalar(1) / s[2]; 1998 } 1999 2000 center = (min + max) * btScalar(0.5); 2001 2002 btAlignedObjectArray<Point32> points; 2003 points.resize(count); 2004 ptr = (const char*) coords; 2005 if (doubleCoords) 2006 { 2007 for (int i = 0; i < count; i++) 2008 { 2009 const double* v = (const double*) ptr; 2010 btVector3 p((btScalar) v[0], (btScalar) v[1], (btScalar) v[2]); 2011 ptr += stride; 2012 p = (p - center) * s; 2013 points[i].x = (int32_t) p[medAxis]; 2014 points[i].y = (int32_t) p[maxAxis]; 2015 points[i].z = (int32_t) p[minAxis]; 2016 points[i].index = i; 2017 } 2018 } 2019 else 2020 { 2021 for (int i = 0; i < count; i++) 2022 { 2023 const float* v = (const float*) ptr; 2024 btVector3 p(v[0], v[1], v[2]); 2025 ptr += stride; 2026 p = (p - center) * s; 2027 points[i].x = (int32_t) p[medAxis]; 2028 points[i].y = (int32_t) p[maxAxis]; 2029 points[i].z = (int32_t) p[minAxis]; 2030 points[i].index = i; 2031 } 2032 } 2033 points.quickSort(pointCmp()); 2034 2035 vertexPool.reset(); 2036 vertexPool.setArraySize(count); 2037 originalVertices.resize(count); 2038 for (int i = 0; i < count; i++) 2039 { 2040 Vertex* v = vertexPool.newObject(); 2041 v->edges = NULL; 2042 v->point = points[i]; 2043 v->copy = -1; 2044 originalVertices[i] = v; 2045 } 2046 2047 points.clear(); 2048 2049 edgePool.reset(); 2050 edgePool.setArraySize(6 * count); 2051 2052 usedEdgePairs = 0; 2053 maxUsedEdgePairs = 0; 2054 2055 mergeStamp = -3; 2056 2057 IntermediateHull hull; 2058 computeInternal(0, count, hull); 2059 vertexList = hull.minXy; 2060 #ifdef DEBUG_CONVEX_HULL 2061 printf("max. edges %d (3v = %d)", maxUsedEdgePairs, 3 * count); 2062 #endif 2063 } 2064 2065 btVector3 btConvexHullInternal::toBtVector(const Point32& v) 2066 { 2067 btVector3 p; 2068 p[medAxis] = btScalar(v.x); 2069 p[maxAxis] = btScalar(v.y); 2070 p[minAxis] = btScalar(v.z); 2071 return p * scaling; 2072 } 2073 2074 btVector3 btConvexHullInternal::getBtNormal(Face* face) 2075 { 2076 return toBtVector(face->dir0).cross(toBtVector(face->dir1)).normalized(); 2077 } 2078 2079 btVector3 btConvexHullInternal::getCoordinates(const Vertex* v) 2080 { 2081 btVector3 p; 2082 p[medAxis] = v->xvalue(); 2083 p[maxAxis] = v->yvalue(); 2084 p[minAxis] = v->zvalue(); 2085 return p * scaling + center; 2086 } 2087 2088 btScalar btConvexHullInternal::shrink(btScalar amount, btScalar clampAmount) 2089 { 2090 if (!vertexList) 2091 { 2092 return 0; 2093 } 2094 int stamp = --mergeStamp; 2095 btAlignedObjectArray<Vertex*> stack; 2096 vertexList->copy = stamp; 2097 stack.push_back(vertexList); 2098 btAlignedObjectArray<Face*> faces; 2099 2100 Point32 ref = vertexList->point; 2101 Int128 hullCenterX(0, 0); 2102 Int128 hullCenterY(0, 0); 2103 Int128 hullCenterZ(0, 0); 2104 Int128 volume(0, 0); 2105 2106 while (stack.size() > 0) 2107 { 2108 Vertex* v = stack[stack.size() - 1]; 2109 stack.pop_back(); 2110 Edge* e = v->edges; 2111 if (e) 2112 { 2113 do 2114 { 2115 if (e->target->copy != stamp) 2116 { 2117 e->target->copy = stamp; 2118 stack.push_back(e->target); 2119 } 2120 if (e->copy != stamp) 2121 { 2122 Face* face = facePool.newObject(); 2123 face->init(e->target, e->reverse->prev->target, v); 2124 faces.push_back(face); 2125 Edge* f = e; 2126 2127 Vertex* a = NULL; 2128 Vertex* b = NULL; 2129 do 2130 { 2131 if (a && b) 2132 { 2133 int64_t vol = (v->point - ref).dot((a->point - ref).cross(b->point - ref)); 2134 btAssert(vol >= 0); 2135 Point32 c = v->point + a->point + b->point + ref; 2136 hullCenterX += vol * c.x; 2137 hullCenterY += vol * c.y; 2138 hullCenterZ += vol * c.z; 2139 volume += vol; 2140 } 2141 2142 btAssert(f->copy != stamp); 2143 f->copy = stamp; 2144 f->face = face; 2145 2146 a = b; 2147 b = f->target; 2148 2149 f = f->reverse->prev; 2150 } while (f != e); 2151 } 2152 e = e->next; 2153 } while (e != v->edges); 2154 } 2155 } 2156 2157 if (volume.getSign() <= 0) 2158 { 2159 return 0; 2160 } 2161 2162 btVector3 hullCenter; 2163 hullCenter[medAxis] = hullCenterX.toScalar(); 2164 hullCenter[maxAxis] = hullCenterY.toScalar(); 2165 hullCenter[minAxis] = hullCenterZ.toScalar(); 2166 hullCenter /= 4 * volume.toScalar(); 2167 hullCenter *= scaling; 2168 2169 int faceCount = faces.size(); 2170 2171 if (clampAmount > 0) 2172 { 2173 btScalar minDist = SIMD_INFINITY; 2174 for (int i = 0; i < faceCount; i++) 2175 { 2176 btVector3 normal = getBtNormal(faces[i]); 2177 btScalar dist = normal.dot(toBtVector(faces[i]->origin) - hullCenter); 2178 if (dist < minDist) 2179 { 2180 minDist = dist; 2181 } 2182 } 2183 2184 if (minDist <= 0) 2185 { 2186 return 0; 2187 } 2188 2189 amount = btMin(amount, minDist * clampAmount); 2190 } 2191 2192 unsigned int seed = 243703; 2193 for (int i = 0; i < faceCount; i++, seed = 1664525 * seed + 1013904223) 2194 { 2195 btSwap(faces[i], faces[seed % faceCount]); 2196 } 2197 2198 for (int i = 0; i < faceCount; i++) 2199 { 2200 if (!shiftFace(faces[i], amount, stack)) 2201 { 2202 return -amount; 2203 } 2204 } 2205 2206 return amount; 2207 } 2208 2209 bool btConvexHullInternal::shiftFace(Face* face, btScalar amount, btAlignedObjectArray<Vertex*> stack) 2210 { 2211 btVector3 origShift = getBtNormal(face) * -amount; 2212 if (scaling[0] != 0) 2213 { 2214 origShift[0] /= scaling[0]; 2215 } 2216 if (scaling[1] != 0) 2217 { 2218 origShift[1] /= scaling[1]; 2219 } 2220 if (scaling[2] != 0) 2221 { 2222 origShift[2] /= scaling[2]; 2223 } 2224 Point32 shift((int32_t) origShift[medAxis], (int32_t) origShift[maxAxis], (int32_t) origShift[minAxis]); 2225 if (shift.isZero()) 2226 { 2227 return true; 2228 } 2229 Point64 normal = face->getNormal(); 2230 #ifdef DEBUG_CONVEX_HULL 2231 printf("\nShrinking face (%d %d %d) (%d %d %d) (%d %d %d) by (%d %d %d)\n", 2232 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 #endif 2234 int64_t origDot = face->origin.dot(normal); 2235 Point32 shiftedOrigin = face->origin + shift; 2236 int64_t shiftedDot = shiftedOrigin.dot(normal); 2237 btAssert(shiftedDot <= origDot); 2238 if (shiftedDot >= origDot) 2239 { 2240 return false; 2241 } 2242 2243 Edge* intersection = NULL; 2244 2245 Edge* startEdge = face->nearbyVertex->edges; 2246 #ifdef DEBUG_CONVEX_HULL 2247 printf("Start edge is "); 2248 startEdge->print(); 2249 printf(", normal is (%lld %lld %lld), shifted dot is %lld\n", normal.x, normal.y, normal.z, shiftedDot); 2250 #endif 2251 Rational128 optDot = face->nearbyVertex->dot(normal); 2252 int cmp = optDot.compare(shiftedDot); 2253 #ifdef SHOW_ITERATIONS 2254 int n = 0; 2255 #endif 2256 if (cmp >= 0) 2257 { 2258 Edge* e = startEdge; 2259 do 2260 { 2261 #ifdef SHOW_ITERATIONS 2262 n++; 2263 #endif 2264 Rational128 dot = e->target->dot(normal); 2265 btAssert(dot.compare(origDot) <= 0); 2266 #ifdef DEBUG_CONVEX_HULL 2267 printf("Moving downwards, edge is "); 2268 e->print(); 2269 printf(", dot is %f (%f %lld)\n", (float) dot.toScalar(), (float) optDot.toScalar(), shiftedDot); 2270 #endif 2271 if (dot.compare(optDot) < 0) 2272 { 2273 int c = dot.compare(shiftedDot); 2274 optDot = dot; 2275 e = e->reverse; 2276 startEdge = e; 2277 if (c < 0) 2278 { 2279 intersection = e; 2280 break; 2281 } 2282 cmp = c; 2283 } 2284 e = e->prev; 2285 } while (e != startEdge); 2286 2287 if (!intersection) 2288 { 2289 return false; 2290 } 2291 } 2292 else 2293 { 2294 Edge* e = startEdge; 2295 do 2296 { 2297 #ifdef SHOW_ITERATIONS 2298 n++; 2299 #endif 2300 Rational128 dot = e->target->dot(normal); 2301 btAssert(dot.compare(origDot) <= 0); 2302 #ifdef DEBUG_CONVEX_HULL 2303 printf("Moving upwards, edge is "); 2304 e->print(); 2305 printf(", dot is %f (%f %lld)\n", (float) dot.toScalar(), (float) optDot.toScalar(), shiftedDot); 2306 #endif 2307 if (dot.compare(optDot) > 0) 2308 { 2309 cmp = dot.compare(shiftedDot); 2310 if (cmp >= 0) 2311 { 2312 intersection = e; 2313 break; 2314 } 2315 optDot = dot; 2316 e = e->reverse; 2317 startEdge = e; 2318 } 2319 e = e->prev; 2320 } while (e != startEdge); 2321 2322 if (!intersection) 2323 { 2324 return true; 2325 } 2326 } 2327 2328 #ifdef SHOW_ITERATIONS 2329 printf("Needed %d iterations to find initial intersection\n", n); 2330 #endif 2331 2332 if (cmp == 0) 2333 { 2334 Edge* e = intersection->reverse->next; 2335 #ifdef SHOW_ITERATIONS 2336 n = 0; 2337 #endif 2338 while (e->target->dot(normal).compare(shiftedDot) <= 0) 2339 { 2340 #ifdef SHOW_ITERATIONS 2341 n++; 2342 #endif 2343 e = e->next; 2344 if (e == intersection->reverse) 2345 { 2346 return true; 2347 } 2348 #ifdef DEBUG_CONVEX_HULL 2349 printf("Checking for outwards edge, current edge is "); 2350 e->print(); 2351 printf("\n"); 2352 #endif 2353 } 2354 #ifdef SHOW_ITERATIONS 2355 printf("Needed %d iterations to check for complete containment\n", n); 2356 #endif 2357 } 2358 2359 Edge* firstIntersection = NULL; 2360 Edge* faceEdge = NULL; 2361 Edge* firstFaceEdge = NULL; 2362 2363 #ifdef SHOW_ITERATIONS 2364 int m = 0; 2365 #endif 2366 while (true) 2367 { 2368 #ifdef SHOW_ITERATIONS 2369 m++; 2370 #endif 2371 #ifdef DEBUG_CONVEX_HULL 2372 printf("Intersecting edge is "); 2373 intersection->print(); 2374 printf("\n"); 2375 #endif 2376 if (cmp == 0) 2377 { 2378 Edge* e = intersection->reverse->next; 2379 startEdge = e; 2380 #ifdef SHOW_ITERATIONS 2381 n = 0; 2382 #endif 2383 while (true) 2384 { 2385 #ifdef SHOW_ITERATIONS 2386 n++; 2387 #endif 2388 if (e->target->dot(normal).compare(shiftedDot) >= 0) 2389 { 2390 break; 2391 } 2392 intersection = e->reverse; 2393 e = e->next; 2394 if (e == startEdge) 2395 { 2396 return true; 2397 } 2398 } 2399 #ifdef SHOW_ITERATIONS 2400 printf("Needed %d iterations to advance intersection\n", n); 2401 #endif 2402 } 2403 2404 #ifdef DEBUG_CONVEX_HULL 2405 printf("Advanced intersecting edge to "); 2406 intersection->print(); 2407 printf(", cmp = %d\n", cmp); 2408 #endif 2409 2410 if (!firstIntersection) 2411 { 2412 firstIntersection = intersection; 2413 } 2414 else if (intersection == firstIntersection) 2415 { 2416 break; 2417 } 2418 2419 int prevCmp = cmp; 2420 Edge* prevIntersection = intersection; 2421 Edge* prevFaceEdge = faceEdge; 2422 2423 Edge* e = intersection->reverse; 2424 #ifdef SHOW_ITERATIONS 2425 n = 0; 2426 #endif 2427 while (true) 2428 { 2429 #ifdef SHOW_ITERATIONS 2430 n++; 2431 #endif 2432 e = e->reverse->prev; 2433 btAssert(e != intersection->reverse); 2434 cmp = e->target->dot(normal).compare(shiftedDot); 2435 #ifdef DEBUG_CONVEX_HULL 2436 printf("Testing edge "); 2437 e->print(); 2438 printf(" -> cmp = %d\n", cmp); 2439 #endif 2440 if (cmp >= 0) 2441 { 2442 intersection = e; 2443 break; 2444 } 2445 } 2446 #ifdef SHOW_ITERATIONS 2447 printf("Needed %d iterations to find other intersection of face\n", n); 2448 #endif 2449 2450 if (cmp > 0) 2451 { 2452 Vertex* removed = intersection->target; 2453 e = intersection->reverse; 2454 if (e->prev == e) 2455 { 2456 removed->edges = NULL; 2457 } 2458 else 2459 { 2460 removed->edges = e->prev; 2461 e->prev->link(e->next); 2462 e->link(e); 2463 } 2464 #ifdef DEBUG_CONVEX_HULL 2465 printf("1: Removed part contains (%d %d %d)\n", removed->point.x, removed->point.y, removed->point.z); 2466 #endif 2467 2468 Point64 n0 = intersection->face->getNormal(); 2469 Point64 n1 = intersection->reverse->face->getNormal(); 2470 int64_t m00 = face->dir0.dot(n0); 2471 int64_t m01 = face->dir1.dot(n0); 2472 int64_t m10 = face->dir0.dot(n1); 2473 int64_t m11 = face->dir1.dot(n1); 2474 int64_t r0 = (intersection->face->origin - shiftedOrigin).dot(n0); 2475 int64_t r1 = (intersection->reverse->face->origin - shiftedOrigin).dot(n1); 2476 Int128 det = Int128::mul(m00, m11) - Int128::mul(m01, m10); 2477 btAssert(det.getSign() != 0); 2478 Vertex* v = vertexPool.newObject(); 2479 v->point.index = -1; 2480 v->copy = -1; 2481 v->point128 = PointR128(Int128::mul(face->dir0.x * r0, m11) - Int128::mul(face->dir0.x * r1, m01) 2482 + Int128::mul(face->dir1.x * r1, m00) - Int128::mul(face->dir1.x * r0, m10) + det * shiftedOrigin.x, 2483 Int128::mul(face->dir0.y * r0, m11) - Int128::mul(face->dir0.y * r1, m01) 2484 + Int128::mul(face->dir1.y * r1, m00) - Int128::mul(face->dir1.y * r0, m10) + det * shiftedOrigin.y, 2485 Int128::mul(face->dir0.z * r0, m11) - Int128::mul(face->dir0.z * r1, m01) 2486 + Int128::mul(face->dir1.z * r1, m00) - Int128::mul(face->dir1.z * r0, m10) + det * shiftedOrigin.z, 2487 det); 2488 v->point.x = (int32_t) v->point128.xvalue(); 2489 v->point.y = (int32_t) v->point128.yvalue(); 2490 v->point.z = (int32_t) v->point128.zvalue(); 2491 intersection->target = v; 2492 v->edges = e; 2493 2494 stack.push_back(v); 2495 stack.push_back(removed); 2496 stack.push_back(NULL); 2497 } 2498 2499 if (cmp || prevCmp || (prevIntersection->reverse->next->target != intersection->target)) 2500 { 2501 faceEdge = newEdgePair(prevIntersection->target, intersection->target); 2502 if (prevCmp == 0) 2503 { 2504 faceEdge->link(prevIntersection->reverse->next); 2505 } 2506 if ((prevCmp == 0) || prevFaceEdge) 2507 { 2508 prevIntersection->reverse->link(faceEdge); 2509 } 2510 if (cmp == 0) 2511 { 2512 intersection->reverse->prev->link(faceEdge->reverse); 2513 } 2514 faceEdge->reverse->link(intersection->reverse); 2515 } 2516 else 2517 { 2518 faceEdge = prevIntersection->reverse->next; 2519 } 2520 2521 if (prevFaceEdge) 2522 { 2523 if (prevCmp > 0) 2524 { 2525 faceEdge->link(prevFaceEdge->reverse); 2526 } 2527 else if (faceEdge != prevFaceEdge->reverse) 2528 { 2529 stack.push_back(prevFaceEdge->target); 2530 while (faceEdge->next != prevFaceEdge->reverse) 2531 { 2532 Vertex* removed = faceEdge->next->target; 2533 removeEdgePair(faceEdge->next); 2534 stack.push_back(removed); 2535 #ifdef DEBUG_CONVEX_HULL 2536 printf("2: Removed part contains (%d %d %d)\n", removed->point.x, removed->point.y, removed->point.z); 2537 #endif 2538 } 2539 stack.push_back(NULL); 2540 } 2541 } 2542 faceEdge->face = face; 2543 faceEdge->reverse->face = intersection->face; 2544 2545 if (!firstFaceEdge) 2546 { 2547 firstFaceEdge = faceEdge; 2548 } 2549 } 2550 #ifdef SHOW_ITERATIONS 2551 printf("Needed %d iterations to process all intersections\n", m); 2552 #endif 2553 2554 if (cmp > 0) 2555 { 2556 firstFaceEdge->reverse->target = faceEdge->target; 2557 firstIntersection->reverse->link(firstFaceEdge); 2558 firstFaceEdge->link(faceEdge->reverse); 2559 } 2560 else if (firstFaceEdge != faceEdge->reverse) 2561 { 2562 stack.push_back(faceEdge->target); 2563 while (firstFaceEdge->next != faceEdge->reverse) 2564 { 2565 Vertex* removed = firstFaceEdge->next->target; 2566 removeEdgePair(firstFaceEdge->next); 2567 stack.push_back(removed); 2568 #ifdef DEBUG_CONVEX_HULL 2569 printf("3: Removed part contains (%d %d %d)\n", removed->point.x, removed->point.y, removed->point.z); 2570 #endif 2571 } 2572 stack.push_back(NULL); 2573 } 2574 2575 btAssert(stack.size() > 0); 2576 vertexList = stack[0]; 2577 2578 #ifdef DEBUG_CONVEX_HULL 2579 printf("Removing part\n"); 2580 #endif 2581 #ifdef SHOW_ITERATIONS 2582 n = 0; 2583 #endif 2584 int pos = 0; 2585 while (pos < stack.size()) 2586 { 2587 int end = stack.size(); 2588 while (pos < end) 2589 { 2590 Vertex* kept = stack[pos++]; 2591 #ifdef DEBUG_CONVEX_HULL 2592 kept->print(); 2593 #endif 2594 bool deeper = false; 2595 Vertex* removed; 2596 while ((removed = stack[pos++]) != NULL) 2597 { 2598 #ifdef SHOW_ITERATIONS 2599 n++; 2600 #endif 2601 kept->receiveNearbyFaces(removed); 2602 while (removed->edges) 2603 { 2604 if (!deeper) 2605 { 2606 deeper = true; 2607 stack.push_back(kept); 2608 } 2609 stack.push_back(removed->edges->target); 2610 removeEdgePair(removed->edges); 2611 } 2612 } 2613 if (deeper) 2614 { 2615 stack.push_back(NULL); 2616 } 2617 } 2618 } 2619 #ifdef SHOW_ITERATIONS 2620 printf("Needed %d iterations to remove part\n", n); 2621 #endif 2622 2623 stack.resize(0); 2624 face->origin = shiftedOrigin; 2625 2626 return true; 2627 } 2628 2629 2630 static int getVertexCopy(btConvexHullInternal::Vertex* vertex, btAlignedObjectArray<btConvexHullInternal::Vertex*>& vertices) 2631 { 2632 int index = vertex->copy; 2633 if (index < 0) 2634 { 2635 index = vertices.size(); 2636 vertex->copy = index; 2637 vertices.push_back(vertex); 2638 #ifdef DEBUG_CONVEX_HULL 2639 printf("Vertex %d gets index *%d\n", vertex->point.index, index); 2640 #endif 2641 } 2642 return index; 2643 } 2644 2645 btScalar btConvexHullComputer::compute(const void* coords, bool doubleCoords, int stride, int count, btScalar shrink, btScalar shrinkClamp) 2646 { 2647 if (count <= 0) 2648 { 2649 vertices.clear(); 2650 edges.clear(); 2651 faces.clear(); 2652 return 0; 2653 } 2654 2655 btConvexHullInternal hull; 2656 hull.compute(coords, doubleCoords, stride, count); 2657 2658 btScalar shift = 0; 2659 if ((shrink > 0) && ((shift = hull.shrink(shrink, shrinkClamp)) < 0)) 2660 { 2661 vertices.clear(); 2662 edges.clear(); 2663 faces.clear(); 2664 return shift; 2665 } 2666 2667 vertices.resize(0); 2668 edges.resize(0); 2669 faces.resize(0); 2670 2671 btAlignedObjectArray<btConvexHullInternal::Vertex*> oldVertices; 2672 getVertexCopy(hull.vertexList, oldVertices); 2673 int copied = 0; 2674 while (copied < oldVertices.size()) 2675 { 2676 btConvexHullInternal::Vertex* v = oldVertices[copied]; 2677 vertices.push_back(hull.getCoordinates(v)); 2678 btConvexHullInternal::Edge* firstEdge = v->edges; 2679 if (firstEdge) 2680 { 2681 int firstCopy = -1; 2682 int prevCopy = -1; 2683 btConvexHullInternal::Edge* e = firstEdge; 2684 do 2685 { 2686 if (e->copy < 0) 2687 { 2688 int s = edges.size(); 2689 edges.push_back(Edge()); 2690 edges.push_back(Edge()); 2691 Edge* c = &edges[s]; 2692 Edge* r = &edges[s + 1]; 2693 e->copy = s; 2694 e->reverse->copy = s + 1; 2695 c->reverse = 1; 2696 r->reverse = -1; 2697 c->targetVertex = getVertexCopy(e->target, oldVertices); 2698 r->targetVertex = copied; 2699 #ifdef DEBUG_CONVEX_HULL 2700 printf(" CREATE: Vertex *%d has edge to *%d\n", copied, c->getTargetVertex()); 2701 #endif 2702 } 2703 if (prevCopy >= 0) 2704 { 2705 edges[e->copy].next = prevCopy - e->copy; 2706 } 2707 else 2708 { 2709 firstCopy = e->copy; 2710 } 2711 prevCopy = e->copy; 2712 e = e->next; 2713 } while (e != firstEdge); 2714 edges[firstCopy].next = prevCopy - firstCopy; 2715 } 2716 copied++; 2717 } 2718 2719 for (int i = 0; i < copied; i++) 2720 { 2721 btConvexHullInternal::Vertex* v = oldVertices[i]; 2722 btConvexHullInternal::Edge* firstEdge = v->edges; 2723 if (firstEdge) 2724 { 2725 btConvexHullInternal::Edge* e = firstEdge; 2726 do 2727 { 2728 if (e->copy >= 0) 2729 { 2730 #ifdef DEBUG_CONVEX_HULL 2731 printf("Vertex *%d has edge to *%d\n", i, edges[e->copy].getTargetVertex()); 2732 #endif 2733 faces.push_back(e->copy); 2734 btConvexHullInternal::Edge* f = e; 2735 do 2736 { 2737 #ifdef DEBUG_CONVEX_HULL 2738 printf(" Face *%d\n", edges[f->copy].getTargetVertex()); 2739 #endif 2740 f->copy = -1; 2741 f = f->reverse->prev; 2742 } while (f != e); 2743 } 2744 e = e->next; 2745 } while (e != firstEdge); 2746 } 2747 } 2748 2749 return shift; 2750 } 2751 2752 2753 2754 2755 2756