cd_hull.cpp
Go to the documentation of this file.
1 
56 #include <stdio.h>
57 #include <stdlib.h>
58 #include <string.h>
59 #include <assert.h>
60 #include <math.h>
61 #include <float.h>
62 
63 
64 #include <stdarg.h>
65 #include <setjmp.h>
66 
67 #include "cd_hull.h"
68 
69 #define STANDALONE 1 // This #define is used when tranferring this source code to other projects
70 
71 #if STANDALONE
72 
73 #undef NX_ALLOC
74 #undef NX_FREE
75 
76 #define NX_ALLOC(x,y) malloc(x)
77 #define NX_FREE(x) free(x)
78 
79 #else
80 #include "Allocateable.h"
81 #endif
82 
83 namespace ConvexDecomposition
84 {
85 
86 //*****************************************************
87 //*** DARRAY.H
88 //*****************************************************
89 
90 template <class Type> class ArrayRet;
91 template <class Type> class Array
92 {
93  public:
94  Array(int s=0);
95  Array(Array<Type> &array);
96  Array(ArrayRet<Type> &array);
97  ~Array();
98  void allocate(int s);
99  void SetSize(int s);
100  void Pack();
101  Type& Add(Type);
102  void AddUnique(Type);
103  int Contains(Type);
104  void Insert(Type,int);
105  int IndexOf(Type);
106  void Remove(Type);
107  void DelIndex(int i);
108  Type * element;
109  int count;
111  const Type &operator[](int i) const { assert(i>=0 && i<count); return element[i]; }
112  Type &operator[](int i) { assert(i>=0 && i<count); return element[i]; }
113  Type &Pop() { assert(count); count--; return element[count]; }
116  // operator ArrayRet<Type> &() { return *(ArrayRet<Type> *)this;} // this worked but i suspect could be dangerous
117 };
118 
119 template <class Type> class ArrayRet:public Array<Type>
120 {
121 };
122 
123 template <class Type> Array<Type>::Array(int s)
124 {
125  count=0;
126  array_size = 0;
127  element = NULL;
128  if(s)
129  {
130  allocate(s);
131  }
132 }
133 
134 
135 template <class Type> Array<Type>::Array(Array<Type> &array)
136 {
137  count=0;
138  array_size = 0;
139  element = NULL;
140  for(int i=0;i<array.count;i++)
141  {
142  Add(array[i]);
143  }
144 }
145 
146 
147 template <class Type> Array<Type>::Array(ArrayRet<Type> &array)
148 {
149  *this = array;
150 }
151 template <class Type> Array<Type> &Array<Type>::operator=(ArrayRet<Type> &array)
152 {
153  count=array.count;
154  array_size = array.array_size;
155  element = array.element;
156  array.element=NULL;
157  array.count=0;
158  array.array_size=0;
159  return *this;
160 }
161 
162 
163 template <class Type> Array<Type> &Array<Type>::operator=(Array<Type> &array)
164 {
165  count=0;
166  for(int i=0;i<array.count;i++)
167  {
168  Add(array[i]);
169  }
170  return *this;
171 }
172 
173 template <class Type> Array<Type>::~Array()
174 {
175  if (element != NULL)
176  {
177  NX_FREE(element);
178  }
179  count=0;array_size=0;element=NULL;
180 }
181 
182 template <class Type> void Array<Type>::allocate(int s)
183 {
184  assert(s>0);
185  assert(s>=count);
186  Type *old = element;
187  array_size =s;
188  element = (Type *) NX_ALLOC( sizeof(Type)*array_size, CONVEX_TEMP );
189  assert(element);
190  for(int i=0;i<count;i++)
191  {
192  element[i]=old[i];
193  }
194  if(old)
195  {
196  NX_FREE(old);
197  }
198 }
199 
200 template <class Type> void Array<Type>::SetSize(int s)
201 {
202  if(s==0)
203  {
204  if(element)
205  {
206  NX_FREE(element);
207  element = NULL;
208  }
209  array_size = s;
210  }
211  else
212  {
213  allocate(s);
214  }
215  count=s;
216 }
217 
218 template <class Type> void Array<Type>::Pack()
219 {
220  allocate(count);
221 }
222 
223 template <class Type> Type& Array<Type>::Add(Type t)
224 {
225  assert(count<=array_size);
226  if(count==array_size)
227  {
228  allocate((array_size)?array_size *2:16);
229  }
230  element[count++] = t;
231  return element[count-1];
232 }
233 
234 template <class Type> int Array<Type>::Contains(Type t)
235 {
236  int i;
237  int found=0;
238  for(i=0;i<count;i++)
239  {
240  if(element[i] == t) found++;
241  }
242  return found;
243 }
244 
245 template <class Type> void Array<Type>::AddUnique(Type t)
246 {
247  if(!Contains(t)) Add(t);
248 }
249 
250 
251 template <class Type> void Array<Type>::DelIndex(int i)
252 {
253  assert(i<count);
254  count--;
255  while(i<count)
256  {
257  element[i] = element[i+1];
258  i++;
259  }
260 }
261 
262 template <class Type> void Array<Type>::Remove(Type t)
263 {
264  int i;
265  for(i=0;i<count;i++)
266  {
267  if(element[i] == t)
268  {
269  break;
270  }
271  }
272  assert(i<count); // assert object t is in the array.
273  DelIndex(i);
274  for(i=0;i<count;i++)
275  {
276  assert(element[i] != t);
277  }
278 }
279 
280 template <class Type> void Array<Type>::Insert(Type t,int k)
281 {
282  int i=count;
283  Add(t); // to allocate space
284  while(i>k)
285  {
286  element[i]=element[i-1];
287  i--;
288  }
289  assert(i==k);
290  element[k]=t;
291 }
292 
293 
294 template <class Type> int Array<Type>::IndexOf(Type t)
295 {
296  int i;
297  for(i=0;i<count;i++)
298  {
299  if(element[i] == t)
300  {
301  return i;
302  }
303  }
304  assert(0);
305  return -1;
306 }
307 
308 //****************************************************
309 //** VECMATH.H
310 //****************************************************
311 #ifndef PLUGIN_3DSMAX
312 #define PI (3.1415926535897932384626433832795f)
313 #endif
314 
315 #define DEG2RAD (PI / 180.0f)
316 #define RAD2DEG (180.0f / PI)
317 #define SQRT_OF_2 (1.4142135f)
318 #define OFFSET(Class,Member) (((char*) (&(((Class*)NULL)-> Member )))- ((char*)NULL))
319 
320 
321 
322 int argmin(double a[],int n);
323 double sqr(double a);
324 double clampf(double a) ;
325 double Round(double a,double precision);
326 double Interpolate(const double &f0,const double &f1,double alpha) ;
327 
328 template <class T>
329 void Swap(T &a,T &b)
330 {
331  T tmp = a;
332  a=b;
333  b=tmp;
334 }
335 
336 
337 
338 template <class T>
339 T Max(const T &a,const T &b)
340 {
341  return (a>b)?a:b;
342 }
343 
344 template <class T>
345 T Min(const T &a,const T &b)
346 {
347  return (a<b)?a:b;
348 }
349 
350 //----------------------------------
351 
352 class int3
353 {
354 public:
355  int x,y,z;
356  int3(){};
357  int3(int _x,int _y, int _z){x=_x;y=_y;z=_z;}
358  const int& operator[](int i) const {return (&x)[i];}
359  int& operator[](int i) {return (&x)[i];}
360 };
361 
362 
363 //-------- 2D --------
364 
365 class double2
366 {
367 public:
368  double x,y;
369  double2(){x=0;y=0;};
370  double2(double _x,double _y){x=_x;y=_y;}
371  double& operator[](int i) {assert(i>=0&&i<2);return ((double*)this)[i];}
372  const double& operator[](int i) const {assert(i>=0&&i<2);return ((double*)this)[i];}
373 };
374 inline double2 operator-( const double2& a, const double2& b ){return double2(a.x-b.x,a.y-b.y);}
375 inline double2 operator+( const double2& a, const double2& b ){return double2(a.x+b.x,a.y+b.y);}
376 
377 //--------- 3D ---------
378 
379 class double3 // 3D
380 {
381  public:
382  double x,y,z;
383  double3(){x=0;y=0;z=0;};
384  double3(double _x,double _y,double _z){x=_x;y=_y;z=_z;};
385  //operator double *() { return &x;};
386  double& operator[](int i) {assert(i>=0&&i<3);return ((double*)this)[i];}
387  const double& operator[](int i) const {assert(i>=0&&i<3);return ((double*)this)[i];}
388 # ifdef PLUGIN_3DSMAX
389  double3(const Point3 &p):x(p.x),y(p.y),z(p.z){}
390  operator Point3(){return *((Point3*)this);}
391 # endif
392 };
393 
394 
395 double3& operator+=( double3 &a, const double3& b );
396 double3& operator-=( double3 &a ,const double3& b );
397 double3& operator*=( double3 &v ,const double s );
398 double3& operator/=( double3 &v, const double s );
399 
400 double magnitude( const double3& v );
401 double3 normalize( const double3& v );
402 double3 safenormalize(const double3 &v);
403 double3 vabs(const double3 &v);
404 double3 operator+( const double3& a, const double3& b );
405 double3 operator-( const double3& a, const double3& b );
406 double3 operator-( const double3& v );
407 double3 operator*( const double3& v, const double s );
408 double3 operator*( const double s, const double3& v );
409 double3 operator/( const double3& v, const double s );
410 inline int operator==( const double3 &a, const double3 &b ) { return (a.x==b.x && a.y==b.y && a.z==b.z); }
411 inline int operator!=( const double3 &a, const double3 &b ) { return (a.x!=b.x || a.y!=b.y || a.z!=b.z); }
412 // due to ambiguity and inconsistent standards ther are no overloaded operators for mult such as va*vb.
413 double dot( const double3& a, const double3& b );
414 double3 cmul( const double3 &a, const double3 &b);
415 double3 cross( const double3& a, const double3& b );
416 double3 Interpolate(const double3 &v0,const double3 &v1,double alpha);
417 double3 Round(const double3& a,double precision);
418 double3 VectorMax(const double3 &a, const double3 &b);
419 double3 VectorMin(const double3 &a, const double3 &b);
420 
421 
422 
424 {
425  public:
426  double3 x,y,z; // the 3 rows of the Matrix
428  double3x3(double xx,double xy,double xz,double yx,double yy,double yz,double zx,double zy,double zz):x(xx,xy,xz),y(yx,yy,yz),z(zx,zy,zz){}
429  double3x3(double3 _x,double3 _y,double3 _z):x(_x),y(_y),z(_z){}
430  double3& operator[](int i) {assert(i>=0&&i<3);return (&x)[i];}
431  const double3& operator[](int i) const {assert(i>=0&&i<3);return (&x)[i];}
432  double& operator()(int r, int c) {assert(r>=0&&r<3&&c>=0&&c<3);return ((&x)[r])[c];}
433  const double& operator()(int r, int c) const {assert(r>=0&&r<3&&c>=0&&c<3);return ((&x)[r])[c];}
434 };
435 double3x3 Transpose( const double3x3& m );
436 double3 operator*( const double3& v , const double3x3& m );
437 double3 operator*( const double3x3& m , const double3& v );
438 double3x3 operator*( const double3x3& m , const double& s );
439 double3x3 operator*( const double3x3& ma, const double3x3& mb );
440 double3x3 operator/( const double3x3& a, const double& s ) ;
441 double3x3 operator+( const double3x3& a, const double3x3& b );
442 double3x3 operator-( const double3x3& a, const double3x3& b );
443 double3x3 &operator+=( double3x3& a, const double3x3& b );
444 double3x3 &operator-=( double3x3& a, const double3x3& b );
445 double3x3 &operator*=( double3x3& a, const double& s );
446 double Determinant(const double3x3& m );
447 double3x3 Inverse(const double3x3& a); // its just 3x3 so we simply do that cofactor method
448 
449 
450 //-------- 4D Math --------
451 
452 class double4
453 {
454 public:
455  double x,y,z,w;
456  double4(){x=0;y=0;z=0;w=0;};
457  double4(double _x,double _y,double _z,double _w){x=_x;y=_y;z=_z;w=_w;}
458  double4(const double3 &v,double _w){x=v.x;y=v.y;z=v.z;w=_w;}
459  //operator double *() { return &x;};
460  double& operator[](int i) {assert(i>=0&&i<4);return ((double*)this)[i];}
461  const double& operator[](int i) const {assert(i>=0&&i<4);return ((double*)this)[i];}
462  const double3& xyz() const { return *((double3*)this);}
463  double3& xyz() { return *((double3*)this);}
464 };
465 
466 
467 struct D3DXMATRIX;
468 
470 {
471  public:
472  double4 x,y,z,w; // the 4 rows
474  double4x4(const double4 &_x, const double4 &_y, const double4 &_z, const double4 &_w):x(_x),y(_y),z(_z),w(_w){}
475  double4x4(double m00, double m01, double m02, double m03,
476  double m10, double m11, double m12, double m13,
477  double m20, double m21, double m22, double m23,
478  double m30, double m31, double m32, double m33 )
479  :x(m00,m01,m02,m03),y(m10,m11,m12,m13),z(m20,m21,m22,m23),w(m30,m31,m32,m33){}
480  double& operator()(int r, int c) {assert(r>=0&&r<4&&c>=0&&c<4);return ((&x)[r])[c];}
481  const double& operator()(int r, int c) const {assert(r>=0&&r<4&&c>=0&&c<4);return ((&x)[r])[c];}
482  operator double* () {return &x.x;}
483  operator const double* () const {return &x.x;}
484  operator struct D3DXMATRIX* () { return (struct D3DXMATRIX*) this;}
485  operator const struct D3DXMATRIX* () const { return (struct D3DXMATRIX*) this;}
486 };
487 
488 
489 int operator==( const double4 &a, const double4 &b );
490 double4 Homogenize(const double3 &v3,const double &w=1.0f); // Turns a 3D double3 4D vector4 by appending w
491 double4 cmul( const double4 &a, const double4 &b);
492 double4 operator*( const double4 &v, double s);
493 double4 operator*( double s, const double4 &v);
494 double4 operator+( const double4 &a, const double4 &b);
495 double4 operator-( const double4 &a, const double4 &b);
496 double4x4 operator*( const double4x4& a, const double4x4& b );
497 double4 operator*( const double4& v, const double4x4& m );
498 double4x4 Inverse(const double4x4 &m);
499 double4x4 MatrixRigidInverse(const double4x4 &m);
500 double4x4 MatrixTranspose(const double4x4 &m);
501 double4x4 MatrixPerspectiveFov(double fovy, double Aspect, double zn, double zf );
502 double4x4 MatrixTranslation(const double3 &t);
503 double4x4 MatrixRotationZ(const double angle_radians);
504 double4x4 MatrixLookAt(const double3& eye, const double3& at, const double3& up);
505 int operator==( const double4x4 &a, const double4x4 &b );
506 
507 
508 //-------- Quaternion ------------
509 
510 class Quaternion :public double4
511 {
512  public:
513  Quaternion() { x = y = z = 0.0f; w = 1.0f; }
514  Quaternion( double3 v, double t ) { v = normalize(v); w = cos(t/2.0f); v = v*sin(t/2.0f); x = v.x; y = v.y; z = v.z; }
515  Quaternion(double _x, double _y, double _z, double _w){x=_x;y=_y;z=_z;w=_w;}
516  double angle() const { return acos(w)*2.0f; }
517  double3 axis() const { double3 a(x,y,z); if(fabs(angle())<0.0000001f) return double3(1,0,0); return a*(1/sin(angle()/2.0f)); }
518  double3 xdir() const { return double3( 1-2*(y*y+z*z), 2*(x*y+w*z), 2*(x*z-w*y) ); }
519  double3 ydir() const { return double3( 2*(x*y-w*z),1-2*(x*x+z*z), 2*(y*z+w*x) ); }
520  double3 zdir() const { return double3( 2*(x*z+w*y), 2*(y*z-w*x),1-2*(x*x+y*y) ); }
521  double3x3 getmatrix() const { return double3x3( xdir(), ydir(), zdir() ); }
522  operator double3x3() { return getmatrix(); }
523  void Normalize();
524 };
525 
526 Quaternion& operator*=(Quaternion& a, double s );
527 Quaternion operator*( const Quaternion& a, double s );
528 Quaternion operator*( const Quaternion& a, const Quaternion& b);
529 Quaternion operator+( const Quaternion& a, const Quaternion& b );
530 Quaternion normalize( Quaternion a );
531 double dot( const Quaternion &a, const Quaternion &b );
532 double3 operator*( const Quaternion& q, const double3& v );
533 double3 operator*( const double3& v, const Quaternion& q );
534 Quaternion slerp( Quaternion a, const Quaternion& b, double interp );
535 Quaternion Interpolate(const Quaternion &q0,const Quaternion &q1,double alpha);
536 Quaternion RotationArc(double3 v0, double3 v1 ); // returns quat q where q*v0=v1
537 Quaternion Inverse(const Quaternion &q);
538 double4x4 MatrixFromQuatVec(const Quaternion &q, const double3 &v);
539 
540 
541 //------ Euler Angle -----
542 
543 Quaternion YawPitchRoll( double yaw, double pitch, double roll );
544 double Yaw( const Quaternion& q );
545 double Pitch( const Quaternion& q );
546 double Roll( Quaternion q );
547 double Yaw( const double3& v );
548 double Pitch( const double3& v );
549 
550 
551 //------- Plane ----------
552 
553 class Plane
554 {
555  public:
557  double dist; // distance below origin - the D from plane equasion Ax+By+Cz+D=0
558  Plane(const double3 &n,double d):normal(n),dist(d){}
559  Plane():normal(),dist(0){}
560  void Transform(const double3 &position, const Quaternion &orientation);
561 };
562 
563 inline Plane PlaneFlip(const Plane &plane){return Plane(-plane.normal,-plane.dist);}
564 inline int operator==( const Plane &a, const Plane &b ) { return (a.normal==b.normal && a.dist==b.dist); }
565 inline int coplanar( const Plane &a, const Plane &b ) { return (a==b || a==PlaneFlip(b)); }
566 
567 
568 //--------- Utility Functions ------
569 
570 double3 PlaneLineIntersection(const Plane &plane, const double3 &p0, const double3 &p1);
571 double3 PlaneProject(const Plane &plane, const double3 &point);
572 double3 LineProject(const double3 &p0, const double3 &p1, const double3 &a); // projects a onto infinite line p0p1
573 double LineProjectTime(const double3 &p0, const double3 &p1, const double3 &a);
574 double3 ThreePlaneIntersection(const Plane &p0,const Plane &p1, const Plane &p2);
575 int PolyHit(const double3 *vert,const int n,const double3 &v0, const double3 &v1, double3 *impact=NULL, double3 *normal=NULL);
576 int BoxInside(const double3 &p,const double3 &bmin, const double3 &bmax) ;
577 int BoxIntersect(const double3 &v0, const double3 &v1, const double3 &bmin, const double3 &bmax, double3 *impact);
578 double DistanceBetweenLines(const double3 &ustart, const double3 &udir, const double3 &vstart, const double3 &vdir, double3 *upoint=NULL, double3 *vpoint=NULL);
579 double3 TriNormal(const double3 &v0, const double3 &v1, const double3 &v2);
580 double3 NormalOf(const double3 *vert, const int n);
581 Quaternion VirtualTrackBall(const double3 &cop, const double3 &cor, const double3 &dir0, const double3 &dir1);
582 
583 
584 
585 
586 //*****************************************************
587 // ** VECMATH.CPP
588 //*****************************************************
589 
590 
591 double sqr(double a) {return a*a;}
592 double clampf(double a) {return Min(1.0,Max(0.0,a));}
593 
594 
595 double Round(double a,double precision)
596 {
597  return floor(0.5f+a/precision)*precision;
598 }
599 
600 
601 double Interpolate(const double &f0,const double &f1,double alpha)
602 {
603  return f0*(1-alpha) + f1*alpha;
604 }
605 
606 
607 int argmin(double a[],int n)
608 {
609  int r=0;
610  for(int i=1;i<n;i++)
611  {
612  if(a[i]<a[r])
613  {
614  r = i;
615  }
616  }
617  return r;
618 }
619 
620 
621 
622 //------------ double3 (3D) --------------
623 
624 
625 
626 double3 operator+( const double3& a, const double3& b )
627 {
628  return double3(a.x+b.x, a.y+b.y, a.z+b.z);
629 }
630 
631 
632 double3 operator-( const double3& a, const double3& b )
633 {
634  return double3( a.x-b.x, a.y-b.y, a.z-b.z );
635 }
636 
637 
639 {
640  return double3( -v.x, -v.y, -v.z );
641 }
642 
643 
644 double3 operator*( const double3& v, double s )
645 {
646  return double3( v.x*s, v.y*s, v.z*s );
647 }
648 
649 
650 double3 operator*( double s, const double3& v )
651 {
652  return double3( v.x*s, v.y*s, v.z*s );
653 }
654 
655 
656 double3 operator/( const double3& v, double s )
657 {
658  return v*(1.0f/s);
659 }
660 
661 double dot( const double3& a, const double3& b )
662 {
663  return a.x*b.x + a.y*b.y + a.z*b.z;
664 }
665 
666 double3 cmul( const double3 &v1, const double3 &v2)
667 {
668  return double3(v1.x*v2.x, v1.y*v2.y, v1.z*v2.z);
669 }
670 
671 
672 double3 cross( const double3& a, const double3& b )
673 {
674  return double3( a.y*b.z - a.z*b.y,
675  a.z*b.x - a.x*b.z,
676  a.x*b.y - a.y*b.x );
677 }
678 
679 
680 
681 
683 {
684  a.x += b.x;
685  a.y += b.y;
686  a.z += b.z;
687  return a;
688 }
689 
690 
692 {
693  a.x -= b.x;
694  a.y -= b.y;
695  a.z -= b.z;
696  return a;
697 }
698 
699 
700 double3& operator*=(double3& v , double s )
701 {
702  v.x *= s;
703  v.y *= s;
704  v.z *= s;
705  return v;
706 }
707 
708 
709 double3& operator/=(double3& v , double s )
710 {
711  double sinv = 1.0f / s;
712  v.x *= sinv;
713  v.y *= sinv;
714  v.z *= sinv;
715  return v;
716 }
717 
719 {
720  return double3(fabs(v.x),fabs(v.y),fabs(v.z));
721 }
722 
723 
724 double magnitude( const double3& v )
725 {
726  return sqrt(sqr(v.x) + sqr( v.y)+ sqr(v.z));
727 }
728 
729 
730 
732 {
733  // this routine, normalize, is ok, provided magnitude works!!
734  double d=magnitude(v);
735  if (d==0)
736  {
737  printf("Cant normalize ZERO vector\n");
738  assert(0);// yes this could go here
739  d=0.1f;
740  }
741  d = 1/d;
742  return double3(v.x*d,v.y*d,v.z*d);
743 }
744 
746 {
747  if(magnitude(v)<=0.0f)
748  {
749  return double3(1,0,0);
750  }
751  return normalize(v);
752 }
753 
754 double3 Round(const double3 &a,double precision)
755 {
756  return double3(Round(a.x,precision),Round(a.y,precision),Round(a.z,precision));
757 }
758 
759 
760 double3 Interpolate(const double3 &v0,const double3 &v1,double alpha)
761 {
762  return v0*(1-alpha) + v1*alpha;
763 }
764 
765 double3 VectorMin(const double3 &a,const double3 &b)
766 {
767  return double3(Min(a.x,b.x),Min(a.y,b.y),Min(a.z,b.z));
768 }
769 double3 VectorMax(const double3 &a,const double3 &b)
770 {
771  return double3(Max(a.x,b.x),Max(a.y,b.y),Max(a.z,b.z));
772 }
773 
774 // the statement v1*v2 is ambiguous since there are 3 types
775 // of vector multiplication
776 // - componantwise (for example combining colors)
777 // - dot product
778 // - cross product
779 // Therefore we never declare/implement this function.
780 // So we will never see: double3 operator*(double3 a,double3 b)
781 
782 
783 
784 
785 //------------ double3x3 ---------------
786 double Determinant(const double3x3 &m)
787 {
788  return m.x.x*m.y.y*m.z.z + m.y.x*m.z.y*m.x.z + m.z.x*m.x.y*m.y.z
789  -m.x.x*m.z.y*m.y.z - m.y.x*m.x.y*m.z.z - m.z.x*m.y.y*m.x.z ;
790 }
791 
793 {
794  double3x3 b;
795  double d=Determinant(a);
796  assert(d!=0);
797  for(int i=0;i<3;i++)
798  {
799  for(int j=0;j<3;j++)
800  {
801  int i1=(i+1)%3;
802  int i2=(i+2)%3;
803  int j1=(j+1)%3;
804  int j2=(j+2)%3;
805  // reverse indexs i&j to take transpose
806  b[j][i] = (a[i1][j1]*a[i2][j2]-a[i1][j2]*a[i2][j1])/d;
807  }
808  }
809  // Matrix check=a*b; // Matrix 'check' should be the identity (or close to it)
810  return b;
811 }
812 
813 
815 {
816  return double3x3( double3(m.x.x,m.y.x,m.z.x),
817  double3(m.x.y,m.y.y,m.z.y),
818  double3(m.x.z,m.y.z,m.z.z));
819 }
820 
821 
822 double3 operator*(const double3& v , const double3x3 &m ) {
823  return double3((m.x.x*v.x + m.y.x*v.y + m.z.x*v.z),
824  (m.x.y*v.x + m.y.y*v.y + m.z.y*v.z),
825  (m.x.z*v.x + m.y.z*v.y + m.z.z*v.z));
826 }
827 double3 operator*(const double3x3 &m,const double3& v ) {
828  return double3(dot(m.x,v),dot(m.y,v),dot(m.z,v));
829 }
830 
831 
832 double3x3 operator*( const double3x3& a, const double3x3& b )
833 {
834  return double3x3(a.x*b,a.y*b,a.z*b);
835 }
836 
837 double3x3 operator*( const double3x3& a, const double& s )
838 {
839  return double3x3(a.x*s, a.y*s ,a.z*s);
840 }
841 double3x3 operator/( const double3x3& a, const double& s )
842 {
843  double t=1/s;
844  return double3x3(a.x*t, a.y*t ,a.z*t);
845 }
846 double3x3 operator+( const double3x3& a, const double3x3& b )
847 {
848  return double3x3(a.x+b.x, a.y+b.y, a.z+b.z);
849 }
850 double3x3 operator-( const double3x3& a, const double3x3& b )
851 {
852  return double3x3(a.x-b.x, a.y-b.y, a.z-b.z);
853 }
855 {
856  a.x+=b.x;
857  a.y+=b.y;
858  a.z+=b.z;
859  return a;
860 }
862 {
863  a.x-=b.x;
864  a.y-=b.y;
865  a.z-=b.z;
866  return a;
867 }
868 double3x3 &operator*=( double3x3& a, const double& s )
869 {
870  a.x*=s;
871  a.y*=s;
872  a.z*=s;
873  return a;
874 }
875 
876 
877 
878 double3 ThreePlaneIntersection(const Plane &p0,const Plane &p1, const Plane &p2){
880  double3x3 mi = Inverse(mp);
881  double3 b(p0.dist,p1.dist,p2.dist);
882  return -b * mi;
883 }
884 
885 
886 //--------------- 4D ----------------
887 
888 double4 operator*( const double4& v, const double4x4& m )
889 {
890  return v.x*m.x + v.y*m.y + v.z*m.z + v.w*m.w; // yes this actually works
891 }
892 
893 int operator==( const double4 &a, const double4 &b )
894 {
895  return (a.x==b.x && a.y==b.y && a.z==b.z && a.w==b.w);
896 }
897 
898 
899 // Dont implement m*v for now, since that might confuse us
900 // All our transforms are based on multiplying the "row" vector on the left
901 //double4 operator*(const double4x4& m , const double4& v )
902 //{
903 // return double4(dot(v,m.x),dot(v,m.y),dot(v,m.z),dot(v,m.w));
904 //}
905 
906 
907 
908 double4 cmul( const double4 &a, const double4 &b)
909 {
910  return double4(a.x*b.x,a.y*b.y,a.z*b.z,a.w*b.w);
911 }
912 
913 
914 double4 operator*( const double4 &v, double s)
915 {
916  return double4(v.x*s,v.y*s,v.z*s,v.w*s);
917 }
918 
919 
920 double4 operator*( double s, const double4 &v)
921 {
922  return double4(v.x*s,v.y*s,v.z*s,v.w*s);
923 }
924 
925 
926 double4 operator+( const double4 &a, const double4 &b)
927 {
928  return double4(a.x+b.x,a.y+b.y,a.z+b.z,a.w+b.w);
929 }
930 
931 
932 
933 double4 operator-( const double4 &a, const double4 &b)
934 {
935  return double4(a.x-b.x,a.y-b.y,a.z-b.z,a.w-b.w);
936 }
937 
938 
939 double4 Homogenize(const double3 &v3,const double &w)
940 {
941  return double4(v3.x,v3.y,v3.z,w);
942 }
943 
944 
945 
946 double4x4 operator*( const double4x4& a, const double4x4& b )
947 {
948  return double4x4(a.x*b,a.y*b,a.z*b,a.w*b);
949 }
950 
952 {
953  return double4x4(
954  m.x.x, m.y.x, m.z.x, m.w.x,
955  m.x.y, m.y.y, m.z.y, m.w.y,
956  m.x.z, m.y.z, m.z.z, m.w.z,
957  m.x.w, m.y.w, m.z.w, m.w.w );
958 }
959 
961 {
962  double4x4 trans_inverse = MatrixTranslation(-m.w.xyz());
963  double4x4 rot = m;
964  rot.w = double4(0,0,0,1);
965  return trans_inverse * MatrixTranspose(rot);
966 }
967 
968 
969 double4x4 MatrixPerspectiveFov(double fovy, double aspect, double zn, double zf )
970 {
971  double h = 1.0f/tan(fovy/2.0f); // view space height
972  double w = h / aspect ; // view space width
973  return double4x4(
974  w, 0, 0 , 0,
975  0, h, 0 , 0,
976  0, 0, zf/(zn-zf) , -1,
977  0, 0, zn*zf/(zn-zf) , 0 );
978 }
979 
980 
981 
982 double4x4 MatrixLookAt(const double3& eye, const double3& at, const double3& up)
983 {
984  double4x4 m;
985  m.w.w = 1.0f;
986  m.w.xyz() = eye;
987  m.z.xyz() = normalize(eye-at);
988  m.x.xyz() = normalize(cross(up,m.z.xyz()));
989  m.y.xyz() = cross(m.z.xyz(),m.x.xyz());
990  return MatrixRigidInverse(m);
991 }
992 
993 
995 {
996  return double4x4(
997  1, 0, 0, 0,
998  0, 1, 0, 0,
999  0, 0, 1, 0,
1000  t.x,t.y,t.z,1 );
1001 }
1002 
1003 
1004 double4x4 MatrixRotationZ(const double angle_radians)
1005 {
1006  double s = sin(angle_radians);
1007  double c = cos(angle_radians);
1008  return double4x4(
1009  c, s, 0, 0,
1010  -s, c, 0, 0,
1011  0, 0, 1, 0,
1012  0, 0, 0, 1 );
1013 }
1014 
1015 
1016 
1017 int operator==( const double4x4 &a, const double4x4 &b )
1018 {
1019  return (a.x==b.x && a.y==b.y && a.z==b.z && a.w==b.w);
1020 }
1021 
1022 
1024 {
1025  double4x4 d;
1026  double *dst = &d.x.x;
1027  double tmp[12]; /* temp array for pairs */
1028  double src[16]; /* array of transpose source matrix */
1029  double det; /* determinant */
1030  /* transpose matrix */
1031  for ( int i = 0; i < 4; i++) {
1032  src[i] = m(i,0) ;
1033  src[i + 4] = m(i,1);
1034  src[i + 8] = m(i,2);
1035  src[i + 12] = m(i,3);
1036  }
1037  /* calculate pairs for first 8 elements (cofactors) */
1038  tmp[0] = src[10] * src[15];
1039  tmp[1] = src[11] * src[14];
1040  tmp[2] = src[9] * src[15];
1041  tmp[3] = src[11] * src[13];
1042  tmp[4] = src[9] * src[14];
1043  tmp[5] = src[10] * src[13];
1044  tmp[6] = src[8] * src[15];
1045  tmp[7] = src[11] * src[12];
1046  tmp[8] = src[8] * src[14];
1047  tmp[9] = src[10] * src[12];
1048  tmp[10] = src[8] * src[13];
1049  tmp[11] = src[9] * src[12];
1050  /* calculate first 8 elements (cofactors) */
1051  dst[0] = tmp[0]*src[5] + tmp[3]*src[6] + tmp[4]*src[7];
1052  dst[0] -= tmp[1]*src[5] + tmp[2]*src[6] + tmp[5]*src[7];
1053  dst[1] = tmp[1]*src[4] + tmp[6]*src[6] + tmp[9]*src[7];
1054  dst[1] -= tmp[0]*src[4] + tmp[7]*src[6] + tmp[8]*src[7];
1055  dst[2] = tmp[2]*src[4] + tmp[7]*src[5] + tmp[10]*src[7];
1056  dst[2] -= tmp[3]*src[4] + tmp[6]*src[5] + tmp[11]*src[7];
1057  dst[3] = tmp[5]*src[4] + tmp[8]*src[5] + tmp[11]*src[6];
1058  dst[3] -= tmp[4]*src[4] + tmp[9]*src[5] + tmp[10]*src[6];
1059  dst[4] = tmp[1]*src[1] + tmp[2]*src[2] + tmp[5]*src[3];
1060  dst[4] -= tmp[0]*src[1] + tmp[3]*src[2] + tmp[4]*src[3];
1061  dst[5] = tmp[0]*src[0] + tmp[7]*src[2] + tmp[8]*src[3];
1062  dst[5] -= tmp[1]*src[0] + tmp[6]*src[2] + tmp[9]*src[3];
1063  dst[6] = tmp[3]*src[0] + tmp[6]*src[1] + tmp[11]*src[3];
1064  dst[6] -= tmp[2]*src[0] + tmp[7]*src[1] + tmp[10]*src[3];
1065  dst[7] = tmp[4]*src[0] + tmp[9]*src[1] + tmp[10]*src[2];
1066  dst[7] -= tmp[5]*src[0] + tmp[8]*src[1] + tmp[11]*src[2];
1067  /* calculate pairs for second 8 elements (cofactors) */
1068  tmp[0] = src[2]*src[7];
1069  tmp[1] = src[3]*src[6];
1070  tmp[2] = src[1]*src[7];
1071  tmp[3] = src[3]*src[5];
1072  tmp[4] = src[1]*src[6];
1073  tmp[5] = src[2]*src[5];
1074  tmp[6] = src[0]*src[7];
1075  tmp[7] = src[3]*src[4];
1076  tmp[8] = src[0]*src[6];
1077  tmp[9] = src[2]*src[4];
1078  tmp[10] = src[0]*src[5];
1079  tmp[11] = src[1]*src[4];
1080  /* calculate second 8 elements (cofactors) */
1081  dst[8] = tmp[0]*src[13] + tmp[3]*src[14] + tmp[4]*src[15];
1082  dst[8] -= tmp[1]*src[13] + tmp[2]*src[14] + tmp[5]*src[15];
1083  dst[9] = tmp[1]*src[12] + tmp[6]*src[14] + tmp[9]*src[15];
1084  dst[9] -= tmp[0]*src[12] + tmp[7]*src[14] + tmp[8]*src[15];
1085  dst[10] = tmp[2]*src[12] + tmp[7]*src[13] + tmp[10]*src[15];
1086  dst[10]-= tmp[3]*src[12] + tmp[6]*src[13] + tmp[11]*src[15];
1087  dst[11] = tmp[5]*src[12] + tmp[8]*src[13] + tmp[11]*src[14];
1088  dst[11]-= tmp[4]*src[12] + tmp[9]*src[13] + tmp[10]*src[14];
1089  dst[12] = tmp[2]*src[10] + tmp[5]*src[11] + tmp[1]*src[9];
1090  dst[12]-= tmp[4]*src[11] + tmp[0]*src[9] + tmp[3]*src[10];
1091  dst[13] = tmp[8]*src[11] + tmp[0]*src[8] + tmp[7]*src[10];
1092  dst[13]-= tmp[6]*src[10] + tmp[9]*src[11] + tmp[1]*src[8];
1093  dst[14] = tmp[6]*src[9] + tmp[11]*src[11] + tmp[3]*src[8];
1094  dst[14]-= tmp[10]*src[11] + tmp[2]*src[8] + tmp[7]*src[9];
1095  dst[15] = tmp[10]*src[10] + tmp[4]*src[8] + tmp[9]*src[9];
1096  dst[15]-= tmp[8]*src[9] + tmp[11]*src[10] + tmp[5]*src[8];
1097  /* calculate determinant */
1098  det=src[0]*dst[0]+src[1]*dst[1]+src[2]*dst[2]+src[3]*dst[3];
1099  /* calculate matrix inverse */
1100  det = 1/det;
1101  for ( int j = 0; j < 16; j++)
1102  dst[j] *= det;
1103  return d;
1104 }
1105 
1106 
1107 //--------- Quaternion --------------
1108 
1110 {
1111  Quaternion c;
1112  c.w = a.w*b.w - a.x*b.x - a.y*b.y - a.z*b.z;
1113  c.x = a.w*b.x + a.x*b.w + a.y*b.z - a.z*b.y;
1114  c.y = a.w*b.y - a.x*b.z + a.y*b.w + a.z*b.x;
1115  c.z = a.w*b.z + a.x*b.y - a.y*b.x + a.z*b.w;
1116  return c;
1117 }
1118 
1119 
1120 Quaternion operator*( const Quaternion& a, double b )
1121 {
1122  return Quaternion(a.x*b, a.y*b, a.z*b ,a.w*b);
1123 }
1124 
1126 {
1127  return Quaternion(-q.x,-q.y,-q.z,q.w);
1128 }
1129 
1130 Quaternion& operator*=( Quaternion& q, const double s )
1131 {
1132  q.x *= s;
1133  q.y *= s;
1134  q.z *= s;
1135  q.w *= s;
1136  return q;
1137 }
1139 {
1140  double m = sqrt(sqr(w)+sqr(x)+sqr(y)+sqr(z));
1141  if(m<0.000000001f) {
1142  w=1.0f;
1143  x=y=z=0.0f;
1144  return;
1145  }
1146  (*this) *= (1.0f/m);
1147 }
1148 
1149 double3 operator*( const Quaternion& q, const double3& v )
1150 {
1151  // The following is equivalent to:
1152  //return (q.getmatrix() * v);
1153  double qx2 = q.x*q.x;
1154  double qy2 = q.y*q.y;
1155  double qz2 = q.z*q.z;
1156 
1157  double qxqy = q.x*q.y;
1158  double qxqz = q.x*q.z;
1159  double qxqw = q.x*q.w;
1160  double qyqz = q.y*q.z;
1161  double qyqw = q.y*q.w;
1162  double qzqw = q.z*q.w;
1163  return double3(
1164  (1-2*(qy2+qz2))*v.x + (2*(qxqy-qzqw))*v.y + (2*(qxqz+qyqw))*v.z ,
1165  (2*(qxqy+qzqw))*v.x + (1-2*(qx2+qz2))*v.y + (2*(qyqz-qxqw))*v.z ,
1166  (2*(qxqz-qyqw))*v.x + (2*(qyqz+qxqw))*v.y + (1-2*(qx2+qy2))*v.z );
1167 }
1168 
1169 double3 operator*( const double3& v, const Quaternion& q )
1170 {
1171  assert(0); // must multiply with the quat on the left
1172  return double3(0.0f,0.0f,0.0f);
1173 }
1174 
1176 {
1177  return Quaternion(a.x+b.x, a.y+b.y, a.z+b.z, a.w+b.w);
1178 }
1179 
1180 double dot( const Quaternion &a,const Quaternion &b )
1181 {
1182  return (a.w*b.w + a.x*b.x + a.y*b.y + a.z*b.z);
1183 }
1184 
1186 {
1187  double m = sqrt(sqr(a.w)+sqr(a.x)+sqr(a.y)+sqr(a.z));
1188  if(m<0.000000001)
1189  {
1190  a.w=1;
1191  a.x=a.y=a.z=0;
1192  return a;
1193  }
1194  return a * (1/m);
1195 }
1196 
1197 Quaternion slerp( Quaternion a, const Quaternion& b, double interp )
1198 {
1199  if(dot(a,b) <0.0)
1200  {
1201  a.w=-a.w;
1202  a.x=-a.x;
1203  a.y=-a.y;
1204  a.z=-a.z;
1205  }
1206  double d = dot(a,b);
1207  if(d>=1.0) {
1208  return a;
1209  }
1210  double theta = acos(d);
1211  if(theta==0.0f) { return(a);}
1212  return a*(sin(theta-interp*theta)/sin(theta)) + b*(sin(interp*theta)/sin(theta));
1213 }
1214 
1215 
1216 Quaternion Interpolate(const Quaternion &q0,const Quaternion &q1,double alpha) {
1217  return slerp(q0,q1,alpha);
1218 }
1219 
1220 
1221 Quaternion YawPitchRoll( double yaw, double pitch, double roll )
1222 {
1223  roll *= DEG2RAD;
1224  yaw *= DEG2RAD;
1225  pitch *= DEG2RAD;
1226  return Quaternion(double3(0.0f,0.0f,1.0f),yaw)*Quaternion(double3(1.0f,0.0f,0.0f),pitch)*Quaternion(double3(0.0f,1.0f,0.0f),roll);
1227 }
1228 
1229 double Yaw( const Quaternion& q )
1230 {
1231  static double3 v;
1232  v=q.ydir();
1233  return (v.y==0.0&&v.x==0.0) ? 0.0: atan2(-v.x,v.y)*RAD2DEG;
1234 }
1235 
1236 double Pitch( const Quaternion& q )
1237 {
1238  static double3 v;
1239  v=q.ydir();
1240  return atan2(v.z,sqrt(sqr(v.x)+sqr(v.y)))*RAD2DEG;
1241 }
1242 
1243 double Roll( Quaternion q )
1244 {
1245  q = Quaternion(double3(0.0f,0.0f,1.0f),-Yaw(q)*DEG2RAD) *q;
1246  q = Quaternion(double3(1.0f,0.0f,0.0f),-Pitch(q)*DEG2RAD) *q;
1247  return atan2(-q.xdir().z,q.xdir().x)*RAD2DEG;
1248 }
1249 
1250 double Yaw( const double3& v )
1251 {
1252  return (v.y==0.0&&v.x==0.0) ? 0.0f: atan2(-v.x,v.y)*RAD2DEG;
1253 }
1254 
1255 double Pitch( const double3& v )
1256 {
1257  return atan2(v.z,sqrt(sqr(v.x)+sqr(v.y)))*RAD2DEG;
1258 }
1259 
1260 
1261 //------------- Plane --------------
1262 
1263 
1264 void Plane::Transform(const double3 &position, const Quaternion &orientation) {
1265  // Transforms the plane to the space defined by the
1266  // given position/orientation.
1267  static double3 newnormal;
1268  static double3 origin;
1269 
1270  newnormal = Inverse(orientation)*normal;
1271  origin = Inverse(orientation)*(-normal*dist - position);
1272 
1273  normal = newnormal;
1274  dist = -dot(newnormal, origin);
1275 }
1276 
1277 
1278 
1279 
1280 //--------- utility functions -------------
1281 
1282 // RotationArc()
1283 // Given two vectors v0 and v1 this function
1284 // returns quaternion q where q*v0==v1.
1285 // Routine taken from game programming gems.
1287  static Quaternion q;
1288  v0 = normalize(v0); // Comment these two lines out if you know its not needed.
1289  v1 = normalize(v1); // If vector is already unit length then why do it again?
1290  double3 c = cross(v0,v1);
1291  double d = dot(v0,v1);
1292  if(d<=-1.0f) { return Quaternion(1,0,0,0);} // 180 about x axis
1293  double s = sqrt((1+d)*2);
1294  q.x = c.x / s;
1295  q.y = c.y / s;
1296  q.z = c.z / s;
1297  q.w = s /2.0f;
1298  return q;
1299 }
1300 
1301 
1303 {
1304  // builds a 4x4 transformation matrix based on orientation q and translation v
1305  double qx2 = q.x*q.x;
1306  double qy2 = q.y*q.y;
1307  double qz2 = q.z*q.z;
1308 
1309  double qxqy = q.x*q.y;
1310  double qxqz = q.x*q.z;
1311  double qxqw = q.x*q.w;
1312  double qyqz = q.y*q.z;
1313  double qyqw = q.y*q.w;
1314  double qzqw = q.z*q.w;
1315 
1316  return double4x4(
1317  1-2*(qy2+qz2),
1318  2*(qxqy+qzqw),
1319  2*(qxqz-qyqw),
1320  0 ,
1321  2*(qxqy-qzqw),
1322  1-2*(qx2+qz2),
1323  2*(qyqz+qxqw),
1324  0 ,
1325  2*(qxqz+qyqw),
1326  2*(qyqz-qxqw),
1327  1-2*(qx2+qy2),
1328  0 ,
1329  v.x ,
1330  v.y ,
1331  v.z ,
1332  1.0f );
1333 }
1334 
1335 
1337 {
1338  // returns the point where the line p0-p1 intersects the plane n&d
1339  static double3 dif;
1340  dif = p1-p0;
1341  double dn= dot(plane.normal,dif);
1342  double t = -(plane.dist+dot(plane.normal,p0) )/dn;
1343  return p0 + (dif*t);
1344 }
1345 
1347 {
1348  return point - plane.normal * (dot(point,plane.normal)+plane.dist);
1349 }
1350 
1351 double3 LineProject(const double3 &p0, const double3 &p1, const double3 &a)
1352 {
1353  double3 w;
1354  w = p1-p0;
1355  double t= dot(w,(a-p0)) / (sqr(w.x)+sqr(w.y)+sqr(w.z));
1356  return p0+ w*t;
1357 }
1358 
1359 
1360 double LineProjectTime(const double3 &p0, const double3 &p1, const double3 &a)
1361 {
1362  double3 w;
1363  w = p1-p0;
1364  double t= dot(w,(a-p0)) / (sqr(w.x)+sqr(w.y)+sqr(w.z));
1365  return t;
1366 }
1367 
1368 
1369 
1370 double3 TriNormal(const double3 &v0, const double3 &v1, const double3 &v2)
1371 {
1372  // return the normal of the triangle
1373  // inscribed by v0, v1, and v2
1374  double3 cp=cross(v1-v0,v2-v1);
1375  double m=magnitude(cp);
1376  if(m==0) return double3(1,0,0);
1377  return cp*(1.0f/m);
1378 }
1379 
1380 
1381 
1382 int BoxInside(const double3 &p, const double3 &bmin, const double3 &bmax)
1383 {
1384  return (p.x >= bmin.x && p.x <=bmax.x &&
1385  p.y >= bmin.y && p.y <=bmax.y &&
1386  p.z >= bmin.z && p.z <=bmax.z );
1387 }
1388 
1389 
1390 int BoxIntersect(const double3 &v0, const double3 &v1, const double3 &bmin, const double3 &bmax,double3 *impact)
1391 {
1392  if(BoxInside(v0,bmin,bmax))
1393  {
1394  *impact=v0;
1395  return 1;
1396  }
1397  if(v0.x<=bmin.x && v1.x>=bmin.x)
1398  {
1399  double a = (bmin.x-v0.x)/(v1.x-v0.x);
1400  //v.x = bmin.x;
1401  double vy = (1-a) *v0.y + a*v1.y;
1402  double vz = (1-a) *v0.z + a*v1.z;
1403  if(vy>=bmin.y && vy<=bmax.y && vz>=bmin.z && vz<=bmax.z)
1404  {
1405  impact->x = bmin.x;
1406  impact->y = vy;
1407  impact->z = vz;
1408  return 1;
1409  }
1410  }
1411  else if(v0.x >= bmax.x && v1.x <= bmax.x)
1412  {
1413  double a = (bmax.x-v0.x)/(v1.x-v0.x);
1414  //v.x = bmax.x;
1415  double vy = (1-a) *v0.y + a*v1.y;
1416  double vz = (1-a) *v0.z + a*v1.z;
1417  if(vy>=bmin.y && vy<=bmax.y && vz>=bmin.z && vz<=bmax.z)
1418  {
1419  impact->x = bmax.x;
1420  impact->y = vy;
1421  impact->z = vz;
1422  return 1;
1423  }
1424  }
1425  if(v0.y<=bmin.y && v1.y>=bmin.y)
1426  {
1427  double a = (bmin.y-v0.y)/(v1.y-v0.y);
1428  double vx = (1-a) *v0.x + a*v1.x;
1429  //v.y = bmin.y;
1430  double vz = (1-a) *v0.z + a*v1.z;
1431  if(vx>=bmin.x && vx<=bmax.x && vz>=bmin.z && vz<=bmax.z)
1432  {
1433  impact->x = vx;
1434  impact->y = bmin.y;
1435  impact->z = vz;
1436  return 1;
1437  }
1438  }
1439  else if(v0.y >= bmax.y && v1.y <= bmax.y)
1440  {
1441  double a = (bmax.y-v0.y)/(v1.y-v0.y);
1442  double vx = (1-a) *v0.x + a*v1.x;
1443  // vy = bmax.y;
1444  double vz = (1-a) *v0.z + a*v1.z;
1445  if(vx>=bmin.x && vx<=bmax.x && vz>=bmin.z && vz<=bmax.z)
1446  {
1447  impact->x = vx;
1448  impact->y = bmax.y;
1449  impact->z = vz;
1450  return 1;
1451  }
1452  }
1453  if(v0.z<=bmin.z && v1.z>=bmin.z)
1454  {
1455  double a = (bmin.z-v0.z)/(v1.z-v0.z);
1456  double vx = (1-a) *v0.x + a*v1.x;
1457  double vy = (1-a) *v0.y + a*v1.y;
1458  // v.z = bmin.z;
1459  if(vy>=bmin.y && vy<=bmax.y && vx>=bmin.x && vx<=bmax.x)
1460  {
1461  impact->x = vx;
1462  impact->y = vy;
1463  impact->z = bmin.z;
1464  return 1;
1465  }
1466  }
1467  else if(v0.z >= bmax.z && v1.z <= bmax.z)
1468  {
1469  double a = (bmax.z-v0.z)/(v1.z-v0.z);
1470  double vx = (1-a) *v0.x + a*v1.x;
1471  double vy = (1-a) *v0.y + a*v1.y;
1472  // v.z = bmax.z;
1473  if(vy>=bmin.y && vy<=bmax.y && vx>=bmin.x && vx<=bmax.x)
1474  {
1475  impact->x = vx;
1476  impact->y = vy;
1477  impact->z = bmax.z;
1478  return 1;
1479  }
1480  }
1481  return 0;
1482 }
1483 
1484 
1485 double DistanceBetweenLines(const double3 &ustart, const double3 &udir, const double3 &vstart, const double3 &vdir, double3 *upoint, double3 *vpoint)
1486 {
1487  static double3 cp;
1488  cp = normalize(cross(udir,vdir));
1489 
1490  double distu = -dot(cp,ustart);
1491  double distv = -dot(cp,vstart);
1492  double dist = (double)fabs(distu-distv);
1493  if(upoint)
1494  {
1495  Plane plane;
1496  plane.normal = normalize(cross(vdir,cp));
1497  plane.dist = -dot(plane.normal,vstart);
1498  *upoint = PlaneLineIntersection(plane,ustart,ustart+udir);
1499  }
1500  if(vpoint)
1501  {
1502  Plane plane;
1503  plane.normal = normalize(cross(udir,cp));
1504  plane.dist = -dot(plane.normal,ustart);
1505  *vpoint = PlaneLineIntersection(plane,vstart,vstart+vdir);
1506  }
1507  return dist;
1508 }
1509 
1510 
1511 Quaternion VirtualTrackBall(const double3 &cop, const double3 &cor, const double3 &dir1, const double3 &dir2)
1512 {
1513  // routine taken from game programming gems.
1514  // Implement track ball functionality to spin stuf on the screen
1515  // cop center of projection
1516  // cor center of rotation
1517  // dir1 old mouse direction
1518  // dir2 new mouse direction
1519  // pretend there is a sphere around cor. Then find the points
1520  // where dir1 and dir2 intersect that sphere. Find the
1521  // rotation that takes the first point to the second.
1522  double m;
1523  // compute plane
1524  double3 nrml = cor - cop;
1525  double fudgefactor = 1.0f/(magnitude(nrml) * 0.25f); // since trackball proportional to distance from cop
1526  nrml = normalize(nrml);
1527  double dist = -dot(nrml,cor);
1528  double3 u= PlaneLineIntersection(Plane(nrml,dist),cop,cop+dir1);
1529  u=u-cor;
1530  u=u*fudgefactor;
1531  m= magnitude(u);
1532  if(m>1)
1533  {
1534  u/=m;
1535  }
1536  else
1537  {
1538  u=u - (nrml * sqrt(1-m*m));
1539  }
1540  double3 v= PlaneLineIntersection(Plane(nrml,dist),cop,cop+dir2);
1541  v=v-cor;
1542  v=v*fudgefactor;
1543  m= magnitude(v);
1544  if(m>1)
1545  {
1546  v/=m;
1547  }
1548  else
1549  {
1550  v=v - (nrml * sqrt(1-m*m));
1551  }
1552  return RotationArc(u,v);
1553 }
1554 
1555 
1557 int PolyHit(const double3 *vert, const int n, const double3 &v0, const double3 &v1, double3 *impact, double3 *normal)
1558 {
1559  countpolyhit++;
1560  int i;
1561  double3 nrml(0,0,0);
1562  for(i=0;i<n;i++)
1563  {
1564  int i1=(i+1)%n;
1565  int i2=(i+2)%n;
1566  nrml = nrml + cross(vert[i1]-vert[i],vert[i2]-vert[i1]);
1567  }
1568 
1569  double m = magnitude(nrml);
1570  if(m==0.0)
1571  {
1572  return 0;
1573  }
1574  nrml = nrml * (1.0f/m);
1575  double dist = -dot(nrml,vert[0]);
1576  double d0,d1;
1577  if((d0=dot(v0,nrml)+dist) <0 || (d1=dot(v1,nrml)+dist) >0)
1578  {
1579  return 0;
1580  }
1581 
1582  static double3 the_point;
1583  // By using the cached plane distances d0 and d1
1584  // we can optimize the following:
1585  // the_point = planelineintersection(nrml,dist,v0,v1);
1586  double a = d0/(d0-d1);
1587  the_point = v0*(1-a) + v1*a;
1588 
1589 
1590  int inside=1;
1591  for(int j=0;inside && j<n;j++)
1592  {
1593  // let inside = 0 if outside
1594  double3 pp1,pp2,side;
1595  pp1 = vert[j] ;
1596  pp2 = vert[(j+1)%n];
1597  side = cross((pp2-pp1),(the_point-pp1));
1598  inside = (dot(nrml,side) >= 0.0);
1599  }
1600  if(inside)
1601  {
1602  if(normal){*normal=nrml;}
1603  if(impact){*impact=the_point;}
1604  }
1605  return inside;
1606 }
1607 
1608 //****************************************************
1609 // HULL.H source code goes here
1610 //****************************************************
1612 {
1613 public:
1614 
1616  {
1617  mVcount = 0;
1618  mIndexCount = 0;
1619  mFaceCount = 0;
1620  mVertices = 0;
1621  mIndices = 0;
1622  }
1623 
1624  unsigned int mVcount;
1625  unsigned int mIndexCount;
1626  unsigned int mFaceCount;
1627  double *mVertices;
1628  unsigned int *mIndices;
1629 };
1630 
1631 bool ComputeHull(unsigned int vcount,const double *vertices,PHullResult &result,unsigned int maxverts,double inflate);
1632 void ReleaseHull(PHullResult &result);
1633 
1634 //*****************************************************
1635 // HULL.cpp source code goes here
1636 //*****************************************************
1637 
1638 
1639 #define REAL3 double3
1640 #define REAL double
1641 
1642 #define COPLANAR (0)
1643 #define UNDER (1)
1644 #define OVER (2)
1645 #define SPLIT (OVER|UNDER)
1646 #define PAPERWIDTH (0.001f)
1647 #define VOLUME_EPSILON (1e-20f)
1648 
1650 
1651 #if STANDALONE
1652 class ConvexH
1653 #else
1654 class ConvexH : public NxFoundation::NxAllocateable
1655 #endif
1656 {
1657  public:
1658  class HalfEdge
1659  {
1660  public:
1661  short ea; // the other half of the edge (index into edges list)
1662  unsigned char v; // the vertex at the start of this edge (index into vertices list)
1663  unsigned char p; // the facet on which this edge lies (index into facets list)
1665  HalfEdge(short _ea,unsigned char _v, unsigned char _p):ea(_ea),v(_v),p(_p){}
1666  };
1670  ConvexH(int vertices_size,int edges_size,int facets_size);
1671 };
1672 
1674 
1675 ConvexH::ConvexH(int vertices_size,int edges_size,int facets_size)
1676  :vertices(vertices_size)
1677  ,edges(edges_size)
1678  ,facets(facets_size)
1679 {
1680  vertices.count=vertices_size;
1681  edges.count = edges_size;
1682  facets.count = facets_size;
1683 }
1684 
1686 {
1687 #if STANDALONE
1688  ConvexH *dst = new ConvexH(src->vertices.count,src->edges.count,src->facets.count);
1689 #else
1690  ConvexH *dst = NX_NEW_MEM(ConvexH(src->vertices.count,src->edges.count,src->facets.count), CONVEX_TEMP);
1691 #endif
1692 
1693  memcpy(dst->vertices.element,src->vertices.element,sizeof(double3)*src->vertices.count);
1694  memcpy(dst->edges.element,src->edges.element,sizeof(HalfEdge)*src->edges.count);
1695  memcpy(dst->facets.element,src->facets.element,sizeof(Plane)*src->facets.count);
1696  return dst;
1697 }
1698 
1699 
1700 int PlaneTest(const Plane &p, const REAL3 &v) {
1701  REAL a = dot(v,p.normal)+p.dist;
1702  int flag = (a>planetestepsilon)?OVER:((a<-planetestepsilon)?UNDER:COPLANAR);
1703  return flag;
1704 }
1705 
1706 int SplitTest(ConvexH &convex,const Plane &plane) {
1707  int flag=0;
1708  for(int i=0;i<convex.vertices.count;i++) {
1709  flag |= PlaneTest(plane,convex.vertices[i]);
1710  }
1711  return flag;
1712 }
1713 
1714 class VertFlag
1715 {
1716 public:
1717  unsigned char planetest;
1718  unsigned char junk;
1719  unsigned char undermap;
1720  unsigned char overmap;
1721 };
1722 class EdgeFlag
1723 {
1724 public:
1725  unsigned char planetest;
1726  unsigned char fixes;
1727  short undermap;
1728  short overmap;
1729 };
1731 {
1732 public:
1733  unsigned char undermap;
1734  unsigned char overmap;
1735 };
1736 class Coplanar{
1737 public:
1738  unsigned short ea;
1739  unsigned char v0;
1740  unsigned char v1;
1741 };
1742 
1743 int AssertIntact(ConvexH &convex) {
1744  int i;
1745  int estart=0;
1746  for(i=0;i<convex.edges.count;i++) {
1747  if(convex.edges[estart].p!= convex.edges[i].p) {
1748  estart=i;
1749  }
1750  int inext = i+1;
1751  if(inext>= convex.edges.count || convex.edges[inext].p != convex.edges[i].p) {
1752  inext = estart;
1753  }
1754  assert(convex.edges[inext].p == convex.edges[i].p);
1755  HalfEdge &edge = convex.edges[i];
1756  int nb = convex.edges[i].ea;
1757  assert(nb!=255);
1758  if(nb==255 || nb==-1) return 0;
1759  assert(nb!=-1);
1760  assert(i== convex.edges[nb].ea);
1761  }
1762  for(i=0;i<convex.edges.count;i++) {
1763  assert(COPLANAR==PlaneTest(convex.facets[convex.edges[i].p],convex.vertices[convex.edges[i].v]));
1764  if(COPLANAR!=PlaneTest(convex.facets[convex.edges[i].p],convex.vertices[convex.edges[i].v])) return 0;
1765  if(convex.edges[estart].p!= convex.edges[i].p) {
1766  estart=i;
1767  }
1768  int i1 = i+1;
1769  if(i1>= convex.edges.count || convex.edges[i1].p != convex.edges[i].p) {
1770  i1 = estart;
1771  }
1772  int i2 = i1+1;
1773  if(i2>= convex.edges.count || convex.edges[i2].p != convex.edges[i].p) {
1774  i2 = estart;
1775  }
1776  if(i==i2) continue; // i sliced tangent to an edge and created 2 meaningless edges
1777  REAL3 localnormal = TriNormal(convex.vertices[convex.edges[i ].v],
1778  convex.vertices[convex.edges[i1].v],
1779  convex.vertices[convex.edges[i2].v]);
1780  //assert(dot(localnormal,convex.facets[convex.edges[i].p].normal)>0);//Commented out on Stan Melax' advice
1781  if(dot(localnormal,convex.facets[convex.edges[i].p].normal)<=0)return 0;
1782  }
1783  return 1;
1784 }
1785 
1786 // back to back quads
1788 {
1789 
1790 #if STANDALONE
1791  ConvexH *convex = new ConvexH(4,8,2);
1792 #else
1793  ConvexH *convex = NX_NEW_MEM(ConvexH(4,8,2), CONVEX_TEMP);
1794 #endif
1795 
1796  convex->vertices[0] = REAL3(0,0,0);
1797  convex->vertices[1] = REAL3(1,0,0);
1798  convex->vertices[2] = REAL3(1,1,0);
1799  convex->vertices[3] = REAL3(0,1,0);
1800  convex->facets[0] = Plane(REAL3(0,0,1),0);
1801  convex->facets[1] = Plane(REAL3(0,0,-1),0);
1802  convex->edges[0] = HalfEdge(7,0,0);
1803  convex->edges[1] = HalfEdge(6,1,0);
1804  convex->edges[2] = HalfEdge(5,2,0);
1805  convex->edges[3] = HalfEdge(4,3,0);
1806 
1807  convex->edges[4] = HalfEdge(3,0,1);
1808  convex->edges[5] = HalfEdge(2,3,1);
1809  convex->edges[6] = HalfEdge(1,2,1);
1810  convex->edges[7] = HalfEdge(0,1,1);
1811  AssertIntact(*convex);
1812  return convex;
1813 }
1814 
1816 {
1817 #if STANDALONE
1818  ConvexH *convex = new ConvexH(8,24,6);
1819 #else
1820  ConvexH *convex = NX_NEW_MEM(ConvexH(8,24,6), CONVEX_TEMP);
1821 #endif
1822  convex->vertices[0] = REAL3(0,0,0);
1823  convex->vertices[1] = REAL3(0,0,1);
1824  convex->vertices[2] = REAL3(0,1,0);
1825  convex->vertices[3] = REAL3(0,1,1);
1826  convex->vertices[4] = REAL3(1,0,0);
1827  convex->vertices[5] = REAL3(1,0,1);
1828  convex->vertices[6] = REAL3(1,1,0);
1829  convex->vertices[7] = REAL3(1,1,1);
1830 
1831  convex->facets[0] = Plane(REAL3(-1,0,0),0);
1832  convex->facets[1] = Plane(REAL3(1,0,0),-1);
1833  convex->facets[2] = Plane(REAL3(0,-1,0),0);
1834  convex->facets[3] = Plane(REAL3(0,1,0),-1);
1835  convex->facets[4] = Plane(REAL3(0,0,-1),0);
1836  convex->facets[5] = Plane(REAL3(0,0,1),-1);
1837 
1838  convex->edges[0 ] = HalfEdge(11,0,0);
1839  convex->edges[1 ] = HalfEdge(23,1,0);
1840  convex->edges[2 ] = HalfEdge(15,3,0);
1841  convex->edges[3 ] = HalfEdge(16,2,0);
1842 
1843  convex->edges[4 ] = HalfEdge(13,6,1);
1844  convex->edges[5 ] = HalfEdge(21,7,1);
1845  convex->edges[6 ] = HalfEdge( 9,5,1);
1846  convex->edges[7 ] = HalfEdge(18,4,1);
1847 
1848  convex->edges[8 ] = HalfEdge(19,0,2);
1849  convex->edges[9 ] = HalfEdge( 6,4,2);
1850  convex->edges[10] = HalfEdge(20,5,2);
1851  convex->edges[11] = HalfEdge( 0,1,2);
1852 
1853  convex->edges[12] = HalfEdge(22,3,3);
1854  convex->edges[13] = HalfEdge( 4,7,3);
1855  convex->edges[14] = HalfEdge(17,6,3);
1856  convex->edges[15] = HalfEdge( 2,2,3);
1857 
1858  convex->edges[16] = HalfEdge( 3,0,4);
1859  convex->edges[17] = HalfEdge(14,2,4);
1860  convex->edges[18] = HalfEdge( 7,6,4);
1861  convex->edges[19] = HalfEdge( 8,4,4);
1862 
1863  convex->edges[20] = HalfEdge(10,1,5);
1864  convex->edges[21] = HalfEdge( 5,5,5);
1865  convex->edges[22] = HalfEdge(12,7,5);
1866  convex->edges[23] = HalfEdge( 1,3,5);
1867 
1868 
1869  return convex;
1870 }
1871 ConvexH *ConvexHMakeCube(const REAL3 &bmin, const REAL3 &bmax) {
1872  ConvexH *convex = test_cube();
1873  convex->vertices[0] = REAL3(bmin.x,bmin.y,bmin.z);
1874  convex->vertices[1] = REAL3(bmin.x,bmin.y,bmax.z);
1875  convex->vertices[2] = REAL3(bmin.x,bmax.y,bmin.z);
1876  convex->vertices[3] = REAL3(bmin.x,bmax.y,bmax.z);
1877  convex->vertices[4] = REAL3(bmax.x,bmin.y,bmin.z);
1878  convex->vertices[5] = REAL3(bmax.x,bmin.y,bmax.z);
1879  convex->vertices[6] = REAL3(bmax.x,bmax.y,bmin.z);
1880  convex->vertices[7] = REAL3(bmax.x,bmax.y,bmax.z);
1881 
1882  convex->facets[0] = Plane(REAL3(-1,0,0), bmin.x);
1883  convex->facets[1] = Plane(REAL3(1,0,0), -bmax.x);
1884  convex->facets[2] = Plane(REAL3(0,-1,0), bmin.y);
1885  convex->facets[3] = Plane(REAL3(0,1,0), -bmax.y);
1886  convex->facets[4] = Plane(REAL3(0,0,-1), bmin.z);
1887  convex->facets[5] = Plane(REAL3(0,0,1), -bmax.z);
1888  return convex;
1889 }
1890 ConvexH *ConvexHCrop(ConvexH &convex,const Plane &slice)
1891 {
1892  int i;
1893  int vertcountunder=0;
1894  int vertcountover =0;
1895  int edgecountunder=0;
1896  int edgecountover =0;
1897  int planecountunder=0;
1898  int planecountover =0;
1899  static Array<int> vertscoplanar; // existing vertex members of convex that are coplanar
1900  vertscoplanar.count=0;
1901  static Array<int> edgesplit; // existing edges that members of convex that cross the splitplane
1902  edgesplit.count=0;
1903 
1904  assert(convex.edges.count<480);
1905 
1906  EdgeFlag edgeflag[512];
1907  VertFlag vertflag[256];
1908  PlaneFlag planeflag[128];
1909  HalfEdge tmpunderedges[512];
1910  Plane tmpunderplanes[128];
1911  Coplanar coplanaredges[512];
1912  int coplanaredges_num=0;
1913 
1914  Array<REAL3> createdverts;
1915  // do the side-of-plane tests
1916  for(i=0;i<convex.vertices.count;i++) {
1917  vertflag[i].planetest = PlaneTest(slice,convex.vertices[i]);
1918  if(vertflag[i].planetest == COPLANAR) {
1919  // ? vertscoplanar.Add(i);
1920  vertflag[i].undermap = vertcountunder++;
1921  vertflag[i].overmap = vertcountover++;
1922  }
1923  else if(vertflag[i].planetest == UNDER) {
1924  vertflag[i].undermap = vertcountunder++;
1925  }
1926  else {
1927  assert(vertflag[i].planetest == OVER);
1928  vertflag[i].overmap = vertcountover++;
1929  vertflag[i].undermap = (unsigned char)-1; // for debugging purposes
1930  }
1931  }
1932  int vertcountunderold = vertcountunder; // for debugging only
1933 
1934  int under_edge_count =0;
1935  int underplanescount=0;
1936  int e0=0;
1937 
1938  for(int currentplane=0; currentplane<convex.facets.count; currentplane++) {
1939  int estart =e0;
1940  int enextface;
1941  int planeside = 0;
1942  int e1 = e0+1;
1943  int eus=-1;
1944  int ecop=-1;
1945  int vout=-1;
1946  int vin =-1;
1947  int coplanaredge = -1;
1948  do{
1949 
1950  if(e1 >= convex.edges.count || convex.edges[e1].p!=currentplane) {
1951  enextface = e1;
1952  e1=estart;
1953  }
1954  HalfEdge &edge0 = convex.edges[e0];
1955  HalfEdge &edge1 = convex.edges[e1];
1956  HalfEdge &edgea = convex.edges[edge0.ea];
1957 
1958 
1959  planeside |= vertflag[edge0.v].planetest;
1960  //if((vertflag[edge0.v].planetest & vertflag[edge1.v].planetest) == COPLANAR) {
1961  // assert(ecop==-1);
1962  // ecop=e;
1963  //}
1964 
1965 
1966  if(vertflag[edge0.v].planetest == OVER && vertflag[edge1.v].planetest == OVER){
1967  // both endpoints over plane
1968  edgeflag[e0].undermap = -1;
1969  }
1970  else if((vertflag[edge0.v].planetest | vertflag[edge1.v].planetest) == UNDER) {
1971  // at least one endpoint under, the other coplanar or under
1972 
1973  edgeflag[e0].undermap = under_edge_count;
1974  tmpunderedges[under_edge_count].v = vertflag[edge0.v].undermap;
1975  tmpunderedges[under_edge_count].p = underplanescount;
1976  if(edge0.ea < e0) {
1977  // connect the neighbors
1978  assert(edgeflag[edge0.ea].undermap !=-1);
1979  tmpunderedges[under_edge_count].ea = edgeflag[edge0.ea].undermap;
1980  tmpunderedges[edgeflag[edge0.ea].undermap].ea = under_edge_count;
1981  }
1982  under_edge_count++;
1983  }
1984  else if((vertflag[edge0.v].planetest | vertflag[edge1.v].planetest) == COPLANAR) {
1985  // both endpoints coplanar
1986  // must check a 3rd point to see if UNDER
1987  int e2 = e1+1;
1988  if(e2>=convex.edges.count || convex.edges[e2].p!=currentplane) {
1989  e2 = estart;
1990  }
1991  assert(convex.edges[e2].p==currentplane);
1992  HalfEdge &edge2 = convex.edges[e2];
1993  if(vertflag[edge2.v].planetest==UNDER) {
1994 
1995  edgeflag[e0].undermap = under_edge_count;
1996  tmpunderedges[under_edge_count].v = vertflag[edge0.v].undermap;
1997  tmpunderedges[under_edge_count].p = underplanescount;
1998  tmpunderedges[under_edge_count].ea = -1;
1999  // make sure this edge is added to the "coplanar" list
2000  coplanaredge = under_edge_count;
2001  vout = vertflag[edge0.v].undermap;
2002  vin = vertflag[edge1.v].undermap;
2003  under_edge_count++;
2004  }
2005  else {
2006  edgeflag[e0].undermap = -1;
2007  }
2008  }
2009  else if(vertflag[edge0.v].planetest == UNDER && vertflag[edge1.v].planetest == OVER) {
2010  // first is under 2nd is over
2011 
2012  edgeflag[e0].undermap = under_edge_count;
2013  tmpunderedges[under_edge_count].v = vertflag[edge0.v].undermap;
2014  tmpunderedges[under_edge_count].p = underplanescount;
2015  if(edge0.ea < e0) {
2016  assert(edgeflag[edge0.ea].undermap !=-1);
2017  // connect the neighbors
2018  tmpunderedges[under_edge_count].ea = edgeflag[edge0.ea].undermap;
2019  tmpunderedges[edgeflag[edge0.ea].undermap].ea = under_edge_count;
2020  vout = tmpunderedges[edgeflag[edge0.ea].undermap].v;
2021  }
2022  else {
2023  Plane &p0 = convex.facets[edge0.p];
2024  Plane &pa = convex.facets[edgea.p];
2025  createdverts.Add(ThreePlaneIntersection(p0,pa,slice));
2026  //createdverts.Add(PlaneProject(slice,PlaneLineIntersection(slice,convex.vertices[edge0.v],convex.vertices[edgea.v])));
2027  //createdverts.Add(PlaneLineIntersection(slice,convex.vertices[edge0.v],convex.vertices[edgea.v]));
2028  vout = vertcountunder++;
2029  }
2030  under_edge_count++;
2032  // wheter or not we know v-in yet. ok i;ll try this now:
2033  tmpunderedges[under_edge_count].v = vout;
2034  tmpunderedges[under_edge_count].p = underplanescount;
2035  tmpunderedges[under_edge_count].ea = -1;
2036  coplanaredge = under_edge_count;
2037  under_edge_count++;
2038 
2039  if(vin!=-1) {
2040  // we previously processed an edge where we came under
2041  // now we know about vout as well
2042 
2043  // ADD THIS EDGE TO THE LIST OF EDGES THAT NEED NEIGHBOR ON PARTITION PLANE!!
2044  }
2045 
2046  }
2047  else if(vertflag[edge0.v].planetest == COPLANAR && vertflag[edge1.v].planetest == OVER) {
2048  // first is coplanar 2nd is over
2049 
2050  edgeflag[e0].undermap = -1;
2051  vout = vertflag[edge0.v].undermap;
2052  // I hate this but i have to make sure part of this face is UNDER before ouputting this vert
2053  int k=estart;
2054  assert(edge0.p == currentplane);
2055  while(!(planeside&UNDER) && k<convex.edges.count && convex.edges[k].p==edge0.p) {
2056  planeside |= vertflag[convex.edges[k].v].planetest;
2057  k++;
2058  }
2059  if(planeside&UNDER){
2060  tmpunderedges[under_edge_count].v = vout;
2061  tmpunderedges[under_edge_count].p = underplanescount;
2062  tmpunderedges[under_edge_count].ea = -1;
2063  coplanaredge = under_edge_count; // hmmm should make a note of the edge # for later on
2064  under_edge_count++;
2065 
2066  }
2067  }
2068  else if(vertflag[edge0.v].planetest == OVER && vertflag[edge1.v].planetest == UNDER) {
2069  // first is over next is under
2070  // new vertex!!!
2071  if (vin!=-1) return NULL;
2072  if(e0<edge0.ea) {
2073  Plane &p0 = convex.facets[edge0.p];
2074  Plane &pa = convex.facets[edgea.p];
2075  createdverts.Add(ThreePlaneIntersection(p0,pa,slice));
2076  //createdverts.Add(PlaneLineIntersection(slice,convex.vertices[edge0.v],convex.vertices[edgea.v]));
2077  //createdverts.Add(PlaneProject(slice,PlaneLineIntersection(slice,convex.vertices[edge0.v],convex.vertices[edgea.v])));
2078  vin = vertcountunder++;
2079  }
2080  else {
2081  // find the new vertex that was created by edge[edge0.ea]
2082  int nea = edgeflag[edge0.ea].undermap;
2083  assert(tmpunderedges[nea].p==tmpunderedges[nea+1].p);
2084  vin = tmpunderedges[nea+1].v;
2085  assert(vin < vertcountunder);
2086  assert(vin >= vertcountunderold); // for debugging only
2087  }
2088  if(vout!=-1) {
2089  // we previously processed an edge where we went over
2090  // now we know vin too
2091  // ADD THIS EDGE TO THE LIST OF EDGES THAT NEED NEIGHBOR ON PARTITION PLANE!!
2092  }
2093  // output edge
2094  tmpunderedges[under_edge_count].v = vin;
2095  tmpunderedges[under_edge_count].p = underplanescount;
2096  edgeflag[e0].undermap = under_edge_count;
2097  if(e0>edge0.ea) {
2098  assert(edgeflag[edge0.ea].undermap !=-1);
2099  // connect the neighbors
2100  tmpunderedges[under_edge_count].ea = edgeflag[edge0.ea].undermap;
2101  tmpunderedges[edgeflag[edge0.ea].undermap].ea = under_edge_count;
2102  }
2103  assert(edgeflag[e0].undermap == under_edge_count);
2104  under_edge_count++;
2105  }
2106  else if(vertflag[edge0.v].planetest == OVER && vertflag[edge1.v].planetest == COPLANAR) {
2107  // first is over next is coplanar
2108 
2109  edgeflag[e0].undermap = -1;
2110  vin = vertflag[edge1.v].undermap;
2111  if (vin==-1) return NULL;
2112  if(vout!=-1) {
2113  // we previously processed an edge where we came under
2114  // now we know both endpoints
2115  // ADD THIS EDGE TO THE LIST OF EDGES THAT NEED NEIGHBOR ON PARTITION PLANE!!
2116  }
2117 
2118  }
2119  else {
2120  assert(0);
2121  }
2122 
2123 
2124  e0=e1;
2125  e1++; // do the modulo at the beginning of the loop
2126 
2127  } while(e0!=estart) ;
2128  e0 = enextface;
2129  if(planeside&UNDER) {
2130  planeflag[currentplane].undermap = underplanescount;
2131  tmpunderplanes[underplanescount] = convex.facets[currentplane];
2132  underplanescount++;
2133  }
2134  else {
2135  planeflag[currentplane].undermap = 0;
2136  }
2137  if(vout>=0 && (planeside&UNDER)) {
2138  assert(vin>=0);
2139  assert(coplanaredge>=0);
2140  assert(coplanaredge!=511);
2141  coplanaredges[coplanaredges_num].ea = coplanaredge;
2142  coplanaredges[coplanaredges_num].v0 = vin;
2143  coplanaredges[coplanaredges_num].v1 = vout;
2144  coplanaredges_num++;
2145  }
2146  }
2147 
2148  // add the new plane to the mix:
2149  if(coplanaredges_num>0) {
2150  tmpunderplanes[underplanescount++]=slice;
2151  }
2152  for(i=0;i<coplanaredges_num-1;i++) {
2153  if(coplanaredges[i].v1 != coplanaredges[i+1].v0) {
2154  int j = 0;
2155  for(j=i+2;j<coplanaredges_num;j++) {
2156  if(coplanaredges[i].v1 == coplanaredges[j].v0) {
2157  Coplanar tmp = coplanaredges[i+1];
2158  coplanaredges[i+1] = coplanaredges[j];
2159  coplanaredges[j] = tmp;
2160  break;
2161  }
2162  }
2163  if(j>=coplanaredges_num)
2164  {
2165  // assert(j<coplanaredges_num);
2166  return NULL;
2167  }
2168  }
2169  }
2170 #if STANDALONE
2171  ConvexH *punder = new ConvexH(vertcountunder,under_edge_count+coplanaredges_num,underplanescount);
2172 #else
2173  ConvexH *punder = NX_NEW_MEM(ConvexH(vertcountunder,under_edge_count+coplanaredges_num,underplanescount), CONVEX_TEMP);
2174 #endif
2175 
2176  ConvexH &under = *punder;
2177  int k=0;
2178  for(i=0;i<convex.vertices.count;i++) {
2179  if(vertflag[i].planetest != OVER){
2180  under.vertices[k++] = convex.vertices[i];
2181  }
2182  }
2183  i=0;
2184  while(k<vertcountunder) {
2185  under.vertices[k++] = createdverts[i++];
2186  }
2187  assert(i==createdverts.count);
2188 
2189  for(i=0;i<coplanaredges_num;i++) {
2190  under.edges[under_edge_count+i].p = underplanescount-1;
2191  under.edges[under_edge_count+i].ea = coplanaredges[i].ea;
2192  tmpunderedges[coplanaredges[i].ea].ea = under_edge_count+i;
2193  under.edges[under_edge_count+i].v = coplanaredges[i].v0;
2194  }
2195 
2196  memcpy(under.edges.element,tmpunderedges,sizeof(HalfEdge)*under_edge_count);
2197  memcpy(under.facets.element,tmpunderplanes,sizeof(Plane)*underplanescount);
2198  return punder;
2199 }
2200 
2201 
2202 double minadjangle = 3.0f; // in degrees - result wont have two adjacent facets within this angle of each other.
2203 static int candidateplane(Plane *planes,int planes_count,ConvexH *convex,double epsilon)
2204 {
2205  int p =-1;
2206  REAL md=0;
2207  int i,j;
2208  double maxdot_minang = cos(DEG2RAD*minadjangle);
2209  for(i=0;i<planes_count;i++)
2210  {
2211  double d=0;
2212  double dmax=0;
2213  double dmin=0;
2214  for(j=0;j<convex->vertices.count;j++)
2215  {
2216  dmax = Max(dmax,dot(convex->vertices[j],planes[i].normal)+planes[i].dist);
2217  dmin = Min(dmin,dot(convex->vertices[j],planes[i].normal)+planes[i].dist);
2218  }
2219  double dr = dmax-dmin;
2220  if(dr<planetestepsilon) dr=1.0f; // shouldn't happen.
2221  d = dmax /dr;
2222  if(d<=md) continue;
2223  for(j=0;j<convex->facets.count;j++)
2224  {
2225  if(planes[i]==convex->facets[j])
2226  {
2227  d=0;continue;
2228  }
2229  if(dot(planes[i].normal,convex->facets[j].normal)>maxdot_minang)
2230  {
2231  for(int k=0;k<convex->edges.count;k++)
2232  {
2233  if(convex->edges[k].p!=j) continue;
2234  if(dot(convex->vertices[convex->edges[k].v],planes[i].normal)+planes[i].dist<0)
2235  {
2236  d=0; // so this plane wont get selected.
2237  break;
2238  }
2239  }
2240  }
2241  }
2242  if(d>md)
2243  {
2244  p=i;
2245  md=d;
2246  }
2247  }
2248  return (md>epsilon)?p:-1;
2249 }
2250 
2251 
2252 
2253 template<class T>
2254 inline int maxdir(const T *p,int count,const T &dir)
2255 {
2256  assert(count);
2257  int m=0;
2258  for(int i=1;i<count;i++)
2259  {
2260  if(dot(p[i],dir)>dot(p[m],dir)) m=i;
2261  }
2262  return m;
2263 }
2264 
2265 
2266 template<class T>
2267 int maxdirfiltered(const T *p,int count,const T &dir,Array<int> &allow)
2268 {
2269  assert(count);
2270  int m=-1;
2271  for(int i=0;i<count;i++) if(allow[i])
2272  {
2273  if(m==-1 || dot(p[i],dir)>dot(p[m],dir)) m=i;
2274  }
2275  assert(m!=-1);
2276  return m;
2277 }
2278 
2280 {
2281  double3 a=cross(v,double3(0,0,1));
2282  double3 b=cross(v,double3(0,1,0));
2283  return normalize((magnitude(a)>magnitude(b))?a:b);
2284 }
2285 
2286 
2287 template<class T>
2288 int maxdirsterid(const T *p,int count,const T &dir,Array<int> &allow)
2289 {
2290  int m=-1;
2291  while(m==-1)
2292  {
2293  m = maxdirfiltered(p,count,dir,allow);
2294  if(allow[m]==3) return m;
2295  T u = orth(dir);
2296  T v = cross(u,dir);
2297  int ma=-1;
2298  for(double x = 0.0f ; x<= 360.0f ; x+= 45.0f)
2299  {
2300  double s = sin(DEG2RAD*(x));
2301  double c = cos(DEG2RAD*(x));
2302  int mb = maxdirfiltered(p,count,dir+(u*s+v*c)*0.025f,allow);
2303  if(ma==m && mb==m)
2304  {
2305  allow[m]=3;
2306  return m;
2307  }
2308  if(ma!=-1 && ma!=mb) // Yuck - this is really ugly
2309  {
2310  int mc = ma;
2311  for(double xx = x-40.0f ; xx <= x ; xx+= 5.0f)
2312  {
2313  double s = sin(DEG2RAD*(xx));
2314  double c = cos(DEG2RAD*(xx));
2315  int md = maxdirfiltered(p,count,dir+(u*s+v*c)*0.025f,allow);
2316  if(mc==m && md==m)
2317  {
2318  allow[m]=3;
2319  return m;
2320  }
2321  mc=md;
2322  }
2323  }
2324  ma=mb;
2325  }
2326  allow[m]=0;
2327  m=-1;
2328  }
2329  assert(0);
2330  return m;
2331 }
2332 
2333 
2334 
2335 
2336 int operator ==(const int3 &a,const int3 &b)
2337 {
2338  for(int i=0;i<3;i++)
2339  {
2340  if(a[i]!=b[i]) return 0;
2341  }
2342  return 1;
2343 }
2344 
2346 {
2347  int tmp=a[0];
2348  a[0]=a[1];
2349  a[1]=a[2];
2350  a[2]=tmp;
2351  return a;
2352 }
2353 int isa(const int3 &a,const int3 &b)
2354 {
2355  return ( a==b || roll3(a)==b || a==roll3(b) );
2356 }
2357 int b2b(const int3 &a,const int3 &b)
2358 {
2359  return isa(a,int3(b[2],b[1],b[0]));
2360 }
2361 int above(double3* vertices,const int3& t, const double3 &p, double epsilon)
2362 {
2363  double3 n=TriNormal(vertices[t[0]],vertices[t[1]],vertices[t[2]]);
2364  return (dot(n,p-vertices[t[0]]) > epsilon); // EPSILON???
2365 }
2366 int hasedge(const int3 &t, int a,int b)
2367 {
2368  for(int i=0;i<3;i++)
2369  {
2370  int i1= (i+1)%3;
2371  if(t[i]==a && t[i1]==b) return 1;
2372  }
2373  return 0;
2374 }
2375 int hasvert(const int3 &t, int v)
2376 {
2377  return (t[0]==v || t[1]==v || t[2]==v) ;
2378 }
2379 int shareedge(const int3 &a,const int3 &b)
2380 {
2381  int i;
2382  for(i=0;i<3;i++)
2383  {
2384  int i1= (i+1)%3;
2385  if(hasedge(a,b[i1],b[i])) return 1;
2386  }
2387  return 0;
2388 }
2389 
2390 class Tri;
2391 
2392 static Array<Tri*> tris; // djs: For heaven's sake!!!!
2393 
2394 #if STANDALONE
2395 class Tri : public int3
2396 #else
2397 class Tri : public int3, public NxFoundation::NxAllocateable
2398 #endif
2399 {
2400 public:
2402  int id;
2403  int vmax;
2404  double rise;
2405  Tri(int a,int b,int c):int3(a,b,c),n(-1,-1,-1)
2406  {
2407  id = tris.count;
2408  tris.Add(this);
2409  vmax=-1;
2410  rise = 0.0f;
2411  }
2413  {
2414  assert(tris[id]==this);
2415  tris[id]=NULL;
2416  }
2417  int &neib(int a,int b);
2418 };
2419 
2420 
2421 int &Tri::neib(int a,int b)
2422 {
2423  static int er=-1;
2424  int i;
2425  for(i=0;i<3;i++)
2426  {
2427  int i1=(i+1)%3;
2428  int i2=(i+2)%3;
2429  if((*this)[i]==a && (*this)[i1]==b) return n[i2];
2430  if((*this)[i]==b && (*this)[i1]==a) return n[i2];
2431  }
2432  assert(0);
2433  return er;
2434 }
2435 void b2bfix(Tri* s,Tri*t)
2436 {
2437  int i;
2438  for(i=0;i<3;i++)
2439  {
2440  int i1=(i+1)%3;
2441  int i2=(i+2)%3;
2442  int a = (*s)[i1];
2443  int b = (*s)[i2];
2444  assert(tris[s->neib(a,b)]->neib(b,a) == s->id);
2445  assert(tris[t->neib(a,b)]->neib(b,a) == t->id);
2446  tris[s->neib(a,b)]->neib(b,a) = t->neib(b,a);
2447  tris[t->neib(b,a)]->neib(a,b) = s->neib(a,b);
2448  }
2449 }
2450 
2451 void removeb2b(Tri* s,Tri*t)
2452 {
2453  b2bfix(s,t);
2454  delete s;
2455  delete t;
2456 }
2457 
2458 void checkit(Tri *t)
2459 {
2460  int i;
2461  assert(tris[t->id]==t);
2462  for(i=0;i<3;i++)
2463  {
2464  int i1=(i+1)%3;
2465  int i2=(i+2)%3;
2466  int a = (*t)[i1];
2467  int b = (*t)[i2];
2468  assert(a!=b);
2469  assert( tris[t->n[i]]->neib(b,a) == t->id);
2470  }
2471 }
2472 void extrude(Tri *t0,int v)
2473 {
2474  int3 t= *t0;
2475  int n = tris.count;
2476 #if STANDALONE
2477  Tri* ta = new Tri(v,t[1],t[2]);
2478 #else
2479  Tri* ta = NX_NEW_MEM(Tri(v,t[1],t[2]), CONVEX_TEMP);
2480 #endif
2481  ta->n = int3(t0->n[0],n+1,n+2);
2482  tris[t0->n[0]]->neib(t[1],t[2]) = n+0;
2483 #if STANDALONE
2484  Tri* tb = new Tri(v,t[2],t[0]);
2485 #else
2486  Tri* tb = NX_NEW_MEM(Tri(v,t[2],t[0]), CONVEX_TEMP);
2487 #endif
2488  tb->n = int3(t0->n[1],n+2,n+0);
2489  tris[t0->n[1]]->neib(t[2],t[0]) = n+1;
2490 #if STANDALONE
2491  Tri* tc = new Tri(v,t[0],t[1]);
2492 #else
2493  Tri* tc = NX_NEW_MEM(Tri(v,t[0],t[1]), CONVEX_TEMP);
2494 #endif
2495  tc->n = int3(t0->n[2],n+0,n+1);
2496  tris[t0->n[2]]->neib(t[0],t[1]) = n+2;
2497  checkit(ta);
2498  checkit(tb);
2499  checkit(tc);
2500  if(hasvert(*tris[ta->n[0]],v)) removeb2b(ta,tris[ta->n[0]]);
2501  if(hasvert(*tris[tb->n[0]],v)) removeb2b(tb,tris[tb->n[0]]);
2502  if(hasvert(*tris[tc->n[0]],v)) removeb2b(tc,tris[tc->n[0]]);
2503  delete t0;
2504 
2505 }
2506 
2507 Tri *extrudable(double epsilon)
2508 {
2509  int i;
2510  Tri *t=NULL;
2511  for(i=0;i<tris.count;i++)
2512  {
2513  if(!t || (tris[i] && t->rise<tris[i]->rise))
2514  {
2515  t = tris[i];
2516  }
2517  }
2518  return (t->rise >epsilon)?t:NULL ;
2519 }
2520 
2521 class int4
2522 {
2523 public:
2524  int x,y,z,w;
2525  int4(){};
2526  int4(int _x,int _y, int _z,int _w){x=_x;y=_y;z=_z;w=_w;}
2527  const int& operator[](int i) const {return (&x)[i];}
2528  int& operator[](int i) {return (&x)[i];}
2529 };
2530 
2531 
2532 
2533 bool hasVolume(double3 *verts, int p0, int p1, int p2, int p3)
2534 {
2535  double3 result3 = cross(verts[p1]-verts[p0], verts[p2]-verts[p0]);
2536  if (magnitude(result3) < VOLUME_EPSILON && magnitude(result3) > -VOLUME_EPSILON) // Almost collinear or otherwise very close to each other
2537  return false;
2538  double result = dot(normalize(result3), verts[p3]-verts[p0]);
2539  return (result > VOLUME_EPSILON || result < -VOLUME_EPSILON); // Returns true iff volume is significantly non-zero
2540 }
2541 
2542 int4 FindSimplex(double3 *verts,int verts_count,Array<int> &allow)
2543 {
2544  double3 basis[3];
2545  basis[0] = double3( 0.01f, 0.02f, 1.0f );
2546  int p0 = maxdirsterid(verts,verts_count, basis[0],allow);
2547  int p1 = maxdirsterid(verts,verts_count,-basis[0],allow);
2548  basis[0] = verts[p0]-verts[p1];
2549  if(p0==p1 || basis[0]==double3(0,0,0))
2550  return int4(-1,-1,-1,-1);
2551  basis[1] = cross(double3( 1, 0.02f, 0),basis[0]);
2552  basis[2] = cross(double3(-0.02f, 1, 0),basis[0]);
2553  basis[1] = normalize( (magnitude(basis[1])>magnitude(basis[2])) ? basis[1]:basis[2]);
2554  int p2 = maxdirsterid(verts,verts_count,basis[1],allow);
2555  if(p2 == p0 || p2 == p1)
2556  {
2557  p2 = maxdirsterid(verts,verts_count,-basis[1],allow);
2558  }
2559  if(p2 == p0 || p2 == p1)
2560  return int4(-1,-1,-1,-1);
2561  basis[1] = verts[p2] - verts[p0];
2562  basis[2] = normalize(cross(basis[1],basis[0]));
2563  int p3 = maxdirsterid(verts,verts_count,basis[2],allow);
2564  if(p3==p0||p3==p1||p3==p2||!hasVolume(verts, p0, p1, p2, p3)) p3 = maxdirsterid(verts,verts_count,-basis[2],allow);
2565  if(p3==p0||p3==p1||p3==p2)
2566  return int4(-1,-1,-1,-1);
2567  assert(!(p0==p1||p0==p2||p0==p3||p1==p2||p1==p3||p2==p3));
2568  if(dot(verts[p3]-verts[p0],cross(verts[p1]-verts[p0],verts[p2]-verts[p0])) <0) {Swap(p2,p3);}
2569  return int4(p0,p1,p2,p3);
2570 }
2571 
2572 int calchullgen(double3 *verts,int verts_count, int vlimit)
2573 {
2574  if(verts_count <4) return 0;
2575  if(vlimit==0) vlimit=1000000000;
2576  int j;
2577  double3 bmin(*verts),bmax(*verts);
2578  Array<int> isextreme(verts_count);
2579  Array<int> allow(verts_count);
2580  for(j=0;j<verts_count;j++)
2581  {
2582  allow.Add(1);
2583  isextreme.Add(0);
2584  bmin = VectorMin(bmin,verts[j]);
2585  bmax = VectorMax(bmax,verts[j]);
2586  }
2587  double epsilon = magnitude(bmax-bmin) * 0.001f;
2588 
2589 
2590  int4 p = FindSimplex(verts,verts_count,allow);
2591  if(p.x==-1) return 0; // simplex failed
2592 
2593 
2594 
2595  double3 center = (verts[p[0]]+verts[p[1]]+verts[p[2]]+verts[p[3]]) /4.0f; // a valid interior point
2596 #if STANDALONE
2597  Tri *t0 = new Tri(p[2],p[3],p[1]); t0->n=int3(2,3,1);
2598  Tri *t1 = new Tri(p[3],p[2],p[0]); t1->n=int3(3,2,0);
2599  Tri *t2 = new Tri(p[0],p[1],p[3]); t2->n=int3(0,1,3);
2600  Tri *t3 = new Tri(p[1],p[0],p[2]); t3->n=int3(1,0,2);
2601 #else
2602  Tri *t0 = NX_NEW_MEM(Tri(p[2],p[3],p[1]); t0->n=int3(2,3,1), CONVEX_TEMP);
2603  Tri *t1 = NX_NEW_MEM(Tri(p[3],p[2],p[0]); t1->n=int3(3,2,0), CONVEX_TEMP);
2604  Tri *t2 = NX_NEW_MEM(Tri(p[0],p[1],p[3]); t2->n=int3(0,1,3), CONVEX_TEMP);
2605  Tri *t3 = NX_NEW_MEM(Tri(p[1],p[0],p[2]); t3->n=int3(1,0,2), CONVEX_TEMP);
2606 #endif
2607  isextreme[p[0]]=isextreme[p[1]]=isextreme[p[2]]=isextreme[p[3]]=1;
2608  checkit(t0);checkit(t1);checkit(t2);checkit(t3);
2609 
2610  for(j=0;j<tris.count;j++)
2611  {
2612  Tri *t=tris[j];
2613  assert(t);
2614  assert(t->vmax<0);
2615  double3 n=TriNormal(verts[(*t)[0]],verts[(*t)[1]],verts[(*t)[2]]);
2616  t->vmax = maxdirsterid(verts,verts_count,n,allow);
2617  t->rise = dot(n,verts[t->vmax]-verts[(*t)[0]]);
2618  }
2619  Tri *te;
2620  vlimit-=4;
2621  while(vlimit >0 && (te=extrudable(epsilon)))
2622  {
2623  int3 ti=*te;
2624  int v=te->vmax;
2625  assert(!isextreme[v]); // wtf we've already done this vertex
2626  isextreme[v]=1;
2627  //if(v==p0 || v==p1 || v==p2 || v==p3) continue; // done these already
2628  j=tris.count;
2629  int newstart=j;
2630  while(j--) {
2631  if(!tris[j]) continue;
2632  int3 t=*tris[j];
2633  if(above(verts,t,verts[v],0.01f*epsilon))
2634  {
2635  extrude(tris[j],v);
2636  }
2637  }
2638  // now check for those degenerate cases where we have a flipped triangle or a really skinny triangle
2639  j=tris.count;
2640  while(j--)
2641  {
2642  if(!tris[j]) continue;
2643  if(!hasvert(*tris[j],v)) break;
2644  int3 nt=*tris[j];
2645  if(above(verts,nt,center,0.01f*epsilon) || magnitude(cross(verts[nt[1]]-verts[nt[0]],verts[nt[2]]-verts[nt[1]]))< epsilon*epsilon*0.1f )
2646  {
2647  Tri *nb = tris[tris[j]->n[0]];
2648  assert(nb);assert(!hasvert(*nb,v));assert(nb->id<j);
2649  extrude(nb,v);
2650  j=tris.count;
2651  }
2652  }
2653  j=tris.count;
2654  while(j--)
2655  {
2656  Tri *t=tris[j];
2657  if(!t) continue;
2658  if(t->vmax>=0) break;
2659  double3 n=TriNormal(verts[(*t)[0]],verts[(*t)[1]],verts[(*t)[2]]);
2660  t->vmax = maxdirsterid(verts,verts_count,n,allow);
2661  if(isextreme[t->vmax])
2662  {
2663  t->vmax=-1; // already done that vertex - algorithm needs to be able to terminate.
2664  }
2665  else
2666  {
2667  t->rise = dot(n,verts[t->vmax]-verts[(*t)[0]]);
2668  }
2669  }
2670  vlimit --;
2671  }
2672  return 1;
2673 }
2674 
2675 int calchull(double3 *verts,int verts_count, int *&tris_out, int &tris_count,int vlimit)
2676 {
2677  int rc=calchullgen(verts,verts_count, vlimit) ;
2678  if(!rc) return 0;
2679  Array<int> ts;
2680  for(int i=0;i<tris.count;i++)if(tris[i])
2681  {
2682  for(int j=0;j<3;j++)ts.Add((*tris[i])[j]);
2683  delete tris[i];
2684  }
2685  tris_count = ts.count/3;
2686  tris_out = ts.element;
2687  ts.element=NULL; ts.count=ts.array_size=0;
2688  // please reset here, otherwise, we get a nice virtual function call (R6025) error with NxCooking library
2689  tris.SetSize( 0 );
2690  return 1;
2691 }
2692 
2693 static double area2(const double3 &v0,const double3 &v1,const double3 &v2)
2694 {
2695  double3 cp = cross(v0-v1,v2-v0);
2696  return dot(cp,cp);
2697 }
2698 int calchullpbev(double3 *verts,int verts_count,int vlimit, Array<Plane> &planes,double bevangle)
2699 {
2700  int i,j;
2701  Array<Plane> bplanes;
2702  planes.count=0;
2703  int rc = calchullgen(verts,verts_count,vlimit);
2704  if(!rc) return 0;
2705  extern double minadjangle; // default is 3.0f; // in degrees - result wont have two adjacent facets within this angle of each other.
2706  double maxdot_minang = cos(DEG2RAD*minadjangle);
2707  for(i=0;i<tris.count;i++)if(tris[i])
2708  {
2709  Plane p;
2710  Tri *t = tris[i];
2711  p.normal = TriNormal(verts[(*t)[0]],verts[(*t)[1]],verts[(*t)[2]]);
2712  p.dist = -dot(p.normal, verts[(*t)[0]]);
2713  for(j=0;j<3;j++)
2714  {
2715  if(t->n[j]<t->id) continue;
2716  Tri *s = tris[t->n[j]];
2717  REAL3 snormal = TriNormal(verts[(*s)[0]],verts[(*s)[1]],verts[(*s)[2]]);
2718  if(dot(snormal,p.normal)>=cos(bevangle*DEG2RAD)) continue;
2719  REAL3 e = verts[(*t)[(j+2)%3]] - verts[(*t)[(j+1)%3]];
2720  REAL3 n = (e!=REAL3(0,0,0))? cross(snormal,e)+cross(e,p.normal) : snormal+p.normal;
2721  assert(n!=REAL3(0,0,0));
2722  if(n==REAL3(0,0,0)) return 0;
2723  n=normalize(n);
2724  bplanes.Add(Plane(n,-dot(n,verts[maxdir(verts,verts_count,n)])));
2725  }
2726  }
2727  for(i=0;i<tris.count;i++)if(tris[i])for(j=i+1;j<tris.count;j++)if(tris[i] && tris[j])
2728  {
2729  Tri *ti = tris[i];
2730  Tri *tj = tris[j];
2731  REAL3 ni = TriNormal(verts[(*ti)[0]],verts[(*ti)[1]],verts[(*ti)[2]]);
2732  REAL3 nj = TriNormal(verts[(*tj)[0]],verts[(*tj)[1]],verts[(*tj)[2]]);
2733  if(dot(ni,nj)>maxdot_minang)
2734  {
2735  // somebody has to die, keep the biggest triangle
2736  if( area2(verts[(*ti)[0]],verts[(*ti)[1]],verts[(*ti)[2]]) < area2(verts[(*tj)[0]],verts[(*tj)[1]],verts[(*tj)[2]]))
2737  {
2738  delete tris[i]; tris[i]=NULL;
2739  }
2740  else
2741  {
2742  delete tris[j]; tris[j]=NULL;
2743  }
2744  }
2745  }
2746  for(i=0;i<tris.count;i++)if(tris[i])
2747  {
2748  Plane p;
2749  Tri *t = tris[i];
2750  p.normal = TriNormal(verts[(*t)[0]],verts[(*t)[1]],verts[(*t)[2]]);
2751  p.dist = -dot(p.normal, verts[(*t)[0]]);
2752  planes.Add(p);
2753  }
2754  for(i=0;i<bplanes.count;i++)
2755  {
2756  for(j=0;j<planes.count;j++)
2757  {
2758  if(dot(bplanes[i].normal,planes[j].normal)>maxdot_minang) break;
2759  }
2760  if(j==planes.count)
2761  {
2762  planes.Add(bplanes[i]);
2763  }
2764  }
2765  for(i=0;i<tris.count;i++)if(tris[i])
2766  {
2767  delete tris[i];
2768  }
2769  tris.count = 0; //bad place to do the tris.SetSize(0) fix, this line is executed many times, and will result in a whole lot of allocations if the array is totally cleared here
2770  return 1;
2771 }
2772 
2773 static int overhull(Plane *planes,int planes_count,double3 *verts, int verts_count,int maxplanes,
2774  double3 *&verts_out, int &verts_count_out, int *&faces_out, int &faces_count_out ,double inflate)
2775 {
2776  int i,j;
2777  if(verts_count <4) return 0;
2778  maxplanes = Min(maxplanes,planes_count);
2779  double3 bmin(verts[0]),bmax(verts[0]);
2780  for(i=0;i<verts_count;i++)
2781  {
2782  bmin = VectorMin(bmin,verts[i]);
2783  bmax = VectorMax(bmax,verts[i]);
2784  }
2785  double diameter = magnitude(bmax-bmin);
2786 // inflate *=diameter; // RELATIVE INFLATION
2787  bmin -= double3(inflate*2.5f,inflate*2.5f,inflate*2.5f);
2788  bmax += double3(inflate*2.5f,inflate*2.5f,inflate*2.5f);
2789  // 2 is from the formula:
2790  // D = d*|n1+n2|/(1-n1 dot n2), where d is "inflate" and
2791  // n1 and n2 are the normals of two planes at bevelAngle to each other
2792  // for 120 degrees, D is 2d
2793 
2794  //bmin -= double3(inflate,inflate,inflate);
2795  //bmax += double3(inflate,inflate,inflate);
2796  for(i=0;i<planes_count;i++)
2797  {
2798  planes[i].dist -= inflate;
2799  }
2800  double3 emin = bmin; // VectorMin(bmin,double3(0,0,0));
2801  double3 emax = bmax; // VectorMax(bmax,double3(0,0,0));
2802  double epsilon = 0.01f; // size of object is taken into account within candidate plane function. Used to multiply here by magnitude(emax-emin)
2803  planetestepsilon = magnitude(emax-emin) * PAPERWIDTH;
2804  // todo: add bounding cube planes to force bevel. or try instead not adding the diameter expansion ??? must think.
2805  // ConvexH *convex = ConvexHMakeCube(bmin - double3(diameter,diameter,diameter),bmax+double3(diameter,diameter,diameter));
2806  double maxdot_minang = cos(DEG2RAD*minadjangle);
2807  for(j=0;j<6;j++)
2808  {
2809  double3 n(0,0,0);
2810  n[j/2] = (j%2)? 1.0f : -1.0f;
2811  for(i=0;i<planes_count;i++)
2812  {
2813  if(dot(n,planes[i].normal)> maxdot_minang)
2814  {
2815  (*((j%2)?&bmax:&bmin)) += n * (diameter*0.5f);
2816  break;
2817  }
2818  }
2819  }
2820  ConvexH *c = ConvexHMakeCube(REAL3(bmin),REAL3(bmax));
2821  int k;
2822  while(maxplanes-- && (k=candidateplane(planes,planes_count,c,epsilon))>=0)
2823  {
2824  ConvexH *tmp = c;
2825  c = ConvexHCrop(*tmp,planes[k]);
2826  if(c==NULL) {c=tmp; break;} // might want to debug this case better!!!
2827  if(!AssertIntact(*c)) {c=tmp; break;} // might want to debug this case better too!!!
2828  delete tmp;
2829  }
2830 
2831  assert(AssertIntact(*c));
2832  //return c;
2833  faces_out = (int*)NX_ALLOC(sizeof(int)*(1+c->facets.count+c->edges.count), CONVEX_TEMP); // new int[1+c->facets.count+c->edges.count];
2834  faces_count_out=0;
2835  i=0;
2836  faces_out[faces_count_out++]=-1;
2837  k=0;
2838  while(i<c->edges.count)
2839  {
2840  j=1;
2841  while(j+i<c->edges.count && c->edges[i].p==c->edges[i+j].p) { j++; }
2842  faces_out[faces_count_out++]=j;
2843  while(j--)
2844  {
2845  faces_out[faces_count_out++] = c->edges[i].v;
2846  i++;
2847  }
2848  k++;
2849  }
2850  faces_out[0]=k; // number of faces.
2851  assert(k==c->facets.count);
2852  assert(faces_count_out == 1+c->facets.count+c->edges.count);
2853  verts_out = c->vertices.element; // new double3[c->vertices.count];
2854  verts_count_out = c->vertices.count;
2855  for(i=0;i<c->vertices.count;i++)
2856  {
2857  verts_out[i] = double3(c->vertices[i]);
2858  }
2859  c->vertices.count=c->vertices.array_size=0; c->vertices.element=NULL;
2860  delete c;
2861  return 1;
2862 }
2863 
2864 static int overhullv(double3 *verts, int verts_count,int maxplanes,
2865  double3 *&verts_out, int &verts_count_out, int *&faces_out, int &faces_count_out ,double inflate,double bevangle,int vlimit)
2866 {
2867  if(!verts_count) return 0;
2868  extern int calchullpbev(double3 *verts,int verts_count,int vlimit, Array<Plane> &planes,double bevangle) ;
2869  Array<Plane> planes;
2870  int rc=calchullpbev(verts,verts_count,vlimit,planes,bevangle) ;
2871  if(!rc) return 0;
2872  return overhull(planes.element,planes.count,verts,verts_count,maxplanes,verts_out,verts_count_out,faces_out,faces_count_out,inflate);
2873 }
2874 
2875 
2876 //*****************************************************
2877 //*****************************************************
2878 
2879 
2880 bool ComputeHull(unsigned int vcount,const double *vertices,PHullResult &result,unsigned int vlimit,double inflate)
2881 {
2882 
2883  int index_count;
2884  int *faces;
2885  double3 *verts_out;
2886  int verts_count_out;
2887 
2888  if(inflate==0.0f)
2889  {
2890  int *tris_out;
2891  int tris_count;
2892  int ret = calchull( (double3 *) vertices, (int) vcount, tris_out, tris_count, vlimit );
2893  if(!ret) return false;
2894  result.mIndexCount = (unsigned int) (tris_count*3);
2895  result.mFaceCount = (unsigned int) tris_count;
2896  result.mVertices = (double*) vertices;
2897  result.mVcount = (unsigned int) vcount;
2898  result.mIndices = (unsigned int *) tris_out;
2899  return true;
2900  }
2901 
2902  int ret = overhullv((double3*)vertices,vcount,35,verts_out,verts_count_out,faces,index_count,inflate,120.0f,vlimit);
2903  if(!ret) {
2904  tris.SetSize(0); //have to set the size to 0 in order to protect from a "pure virtual function call" problem
2905  return false;
2906  }
2907 
2908  Array<int3> tris;
2909  int n=faces[0];
2910  int k=1;
2911  for(int i=0;i<n;i++)
2912  {
2913  int pn = faces[k++];
2914  for(int j=2;j<pn;j++) tris.Add(int3(faces[k],faces[k+j-1],faces[k+j]));
2915  k+=pn;
2916  }
2917  assert(tris.count == index_count-1-(n*3));
2918  NX_FREE(faces); // PT: I added that. Is it ok ?
2919 
2920  result.mIndexCount = (unsigned int) (tris.count*3);
2921  result.mFaceCount = (unsigned int) tris.count;
2922  result.mVertices = (double*) verts_out;
2923  result.mVcount = (unsigned int) verts_count_out;
2924  result.mIndices = (unsigned int *) tris.element;
2925  tris.element=NULL; tris.count = tris.array_size=0;
2926  ConvexDecomposition::tris.SetSize(0); //have to set the size to 0 in order to protect from a "pure virtual function call" problem
2927 
2928  return true;
2929 }
2930 
2931 
2933 {
2934 NX_FREE(result.mIndices); // PT: I added that. Is it ok ?
2935 NX_FREE(result.mVertices); // PT: I added that. Is it ok ?
2936  result.mVcount = 0;
2937  result.mIndexCount = 0;
2938  result.mIndices = 0;
2939  result.mVertices = 0;
2940  result.mIndices = 0;
2941 }
2942 
2943 
2944 
2945 //****** HULLLIB source code
2946 
2947 
2948 HullError HullLibrary::CreateConvexHull(const HullDesc &desc, // describes the input request
2949  HullResult &result) // contains the resulst
2950 {
2951  HullError ret = QE_FAIL;
2952 
2953 
2954  PHullResult hr;
2955 
2956  unsigned int vcount = desc.mVcount;
2957  if ( vcount < 8 ) vcount = 8;
2958 
2959  double *vsource = (double *) NX_ALLOC( sizeof(double)*vcount*3, CONVEX_TEMP );
2960 
2961 
2962  double scale[3];
2963 
2964  unsigned int ovcount;
2965 
2966  bool ok = CleanupVertices(desc.mVcount,desc.mVertices, desc.mVertexStride, ovcount, vsource, desc.mNormalEpsilon, scale ); // normalize point cloud, remove duplicates!
2967 
2968  if ( ok )
2969  {
2970  double bmin[3];
2971  double bmax[3];
2972 
2973 
2974  if ( 1 ) // scale vertices back to their original size.
2975  {
2976 
2977  for (unsigned int i=0; i<ovcount; i++)
2978  {
2979  double *v = &vsource[i*3];
2980  v[0]*=scale[0];
2981  v[1]*=scale[1];
2982  v[2]*=scale[2];
2983 
2984  if ( i == 0 )
2985  {
2986  bmin[0] = bmax[0] = v[0];
2987  bmin[1] = bmax[1] = v[1];
2988  bmin[2] = bmax[2] = v[2];
2989  }
2990  else
2991  {
2992  if ( v[0] < bmin[0] ) bmin[0] = v[0];
2993  if ( v[1] < bmin[1] ) bmin[1] = v[1];
2994  if ( v[2] < bmin[2] ) bmin[2] = v[2];
2995  if ( v[0] > bmax[0] ) bmax[0] = v[0];
2996  if ( v[1] > bmax[1] ) bmax[1] = v[1];
2997  if ( v[2] > bmax[2] ) bmax[2] = v[2];
2998  }
2999 
3000  }
3001  }
3002 
3003  double skinwidth = 0;
3004 
3005  if ( desc.HasHullFlag(QF_SKIN_WIDTH) )
3006  {
3007  skinwidth = desc.mSkinWidth;
3008  if ( skinwidth < 0 ) // if it is a negative skinwidth we shrink the hull points relative to the center.
3009  {
3010  double center[3];
3011 
3012  center[0] = (bmax[0] - bmin[0])*0.5f + bmin[0];
3013  center[1] = (bmax[1] - bmin[1])*0.5f + bmin[1];
3014  center[2] = (bmax[2] - bmin[2])*0.5f + bmin[2];
3015 
3016  double dx = (bmax[0]-bmin[0])*0.5f;
3017  double dy = (bmax[1]-bmin[1])*0.5f;
3018  double dz = (bmax[2]-bmin[2])*0.5f;
3019  double dist = sqrt(dx*dx+dy*dy+dz*dz);
3020 
3021  skinwidth*=-1; // make it positive...
3022 
3023  double scale = 1.0f - (skinwidth/dist);
3024  if ( scale < 0.3f ) scale = 0.3f;
3025  for (unsigned int i=0; i<ovcount; i++)
3026  {
3027  double *v = &vsource[i*3];
3028 
3029  v[0]-=center[0];
3030  v[1]-=center[1];
3031  v[2]-=center[2];
3032 
3033  v[0]*=scale;
3034  v[1]*=scale;
3035  v[2]*=scale;
3036 
3037  v[0]+=center[0];
3038  v[1]+=center[1];
3039  v[2]+=center[2];
3040  }
3041  skinwidth = 0;
3042  }
3043  }
3044 
3045  ok = ComputeHull(ovcount,vsource,hr,desc.mMaxVertices,skinwidth);
3046 
3047  if ( ok )
3048  {
3049 
3050  // re-index triangle mesh so it refers to only used vertices, rebuild a new vertex table.
3051  double *vscratch = (double *) NX_ALLOC( sizeof(double)*hr.mVcount*3, CONVEX_TEMP );
3052  BringOutYourDead(hr.mVertices,hr.mVcount, vscratch, ovcount, hr.mIndices, hr.mIndexCount );
3053 
3054  ret = QE_OK;
3055 
3056  if ( desc.HasHullFlag(QF_TRIANGLES) ) // if he wants the results as triangle!
3057  {
3058  result.mPolygons = false;
3059  result.mNumOutputVertices = ovcount;
3060  result.mOutputVertices = (double *)NX_ALLOC( sizeof(double)*ovcount*3, CONVEX_TEMP );
3061  result.mNumFaces = hr.mFaceCount;
3062  result.mNumIndices = hr.mIndexCount;
3063 
3064  result.mIndices = (unsigned int *) NX_ALLOC( sizeof(unsigned int)*hr.mIndexCount, CONVEX_TEMP );
3065 
3066  memcpy(result.mOutputVertices, vscratch, sizeof(double)*3*ovcount );
3067 
3068  if ( desc.HasHullFlag(QF_REVERSE_ORDER) )
3069  {
3070 
3071  const unsigned int *source = hr.mIndices;
3072  unsigned int *dest = result.mIndices;
3073 
3074  for (unsigned int i=0; i<hr.mFaceCount; i++)
3075  {
3076  dest[0] = source[2];
3077  dest[1] = source[1];
3078  dest[2] = source[0];
3079  dest+=3;
3080  source+=3;
3081  }
3082 
3083  }
3084  else
3085  {
3086  memcpy(result.mIndices, hr.mIndices, sizeof(unsigned int)*hr.mIndexCount);
3087  }
3088  }
3089  else
3090  {
3091  result.mPolygons = true;
3092  result.mNumOutputVertices = ovcount;
3093  result.mOutputVertices = (double *)NX_ALLOC( sizeof(double)*ovcount*3, CONVEX_TEMP );
3094  result.mNumFaces = hr.mFaceCount;
3095  result.mNumIndices = hr.mIndexCount+hr.mFaceCount;
3096  result.mIndices = (unsigned int *) NX_ALLOC( sizeof(unsigned int)*result.mNumIndices, CONVEX_TEMP );
3097  memcpy(result.mOutputVertices, vscratch, sizeof(double)*3*ovcount );
3098 
3099  if ( 1 )
3100  {
3101  const unsigned int *source = hr.mIndices;
3102  unsigned int *dest = result.mIndices;
3103  for (unsigned int i=0; i<hr.mFaceCount; i++)
3104  {
3105  dest[0] = 3;
3106  if ( desc.HasHullFlag(QF_REVERSE_ORDER) )
3107  {
3108  dest[1] = source[2];
3109  dest[2] = source[1];
3110  dest[3] = source[0];
3111  }
3112  else
3113  {
3114  dest[1] = source[0];
3115  dest[2] = source[1];
3116  dest[3] = source[2];
3117  }
3118 
3119  dest+=4;
3120  source+=3;
3121  }
3122  }
3123  }
3124  // ReleaseHull frees memory for hr.mVertices, which can be the
3125  // same pointer as vsource, so be sure to set it to NULL if necessary
3126  if ( hr.mVertices == vsource) vsource = NULL;
3127 
3128  ReleaseHull(hr);
3129 
3130  if ( vscratch )
3131  {
3132  NX_FREE(vscratch);
3133  }
3134  }
3135  }
3136 
3137  // this pointer is usually freed in ReleaseHull()
3138  if ( vsource )
3139  {
3140  NX_FREE(vsource);
3141  }
3142 
3143 
3144  return ret;
3145 }
3146 
3147 
3148 
3149 HullError HullLibrary::ReleaseResult(HullResult &result) // release memory allocated for this result, we are done with it.
3150 {
3151  if ( result.mOutputVertices )
3152  {
3153  NX_FREE(result.mOutputVertices);
3154  result.mOutputVertices = 0;
3155  }
3156  if ( result.mIndices )
3157  {
3158  NX_FREE(result.mIndices);
3159  result.mIndices = 0;
3160  }
3161  return QE_OK;
3162 }
3163 
3164 
3165 static void AddPoint(unsigned int &vcount,double *p,double x,double y,double z)
3166 {
3167  double *dest = &p[vcount*3];
3168  dest[0] = x;
3169  dest[1] = y;
3170  dest[2] = z;
3171  vcount++;
3172 }
3173 
3174 
3175 double GetDist(double px,double py,double pz,const double *p2)
3176 {
3177 
3178  double dx = px - p2[0];
3179  double dy = py - p2[1];
3180  double dz = pz - p2[2];
3181 
3182  return dx*dx+dy*dy+dz*dz;
3183 }
3184 
3185 
3186 
3187 bool HullLibrary::CleanupVertices(unsigned int svcount,
3188  const double *svertices,
3189  unsigned int stride,
3190  unsigned int &vcount, // output number of vertices
3191  double *vertices, // location to store the results.
3192  double normalepsilon,
3193  double *scale)
3194 {
3195  if ( svcount == 0 ) return false;
3196 
3197 
3198  #define EPSILON 0.000001f // close enough to consider two doubleing point numbers to be 'the same'.
3199 
3200  bool ret = false;
3201 
3202  vcount = 0;
3203 
3204  double recip[3];
3205 
3206  if ( scale )
3207  {
3208  scale[0] = 1;
3209  scale[1] = 1;
3210  scale[2] = 1;
3211  }
3212 
3213  double bmin[3] = { FLT_MAX, FLT_MAX, FLT_MAX };
3214  double bmax[3] = { -FLT_MAX, -FLT_MAX, -FLT_MAX };
3215 
3216  const char *vtx = (const char *) svertices;
3217 
3218  if ( 1 )
3219  {
3220  for (unsigned int i=0; i<svcount; i++)
3221  {
3222  const double *p = (const double *) vtx;
3223 
3224  vtx+=stride;
3225 
3226  for (int j=0; j<3; j++)
3227  {
3228  if ( p[j] < bmin[j] ) bmin[j] = p[j];
3229  if ( p[j] > bmax[j] ) bmax[j] = p[j];
3230  }
3231  }
3232  }
3233 
3234  double dx = bmax[0] - bmin[0];
3235  double dy = bmax[1] - bmin[1];
3236  double dz = bmax[2] - bmin[2];
3237 
3238  double center[3];
3239 
3240  center[0] = dx*0.5f + bmin[0];
3241  center[1] = dy*0.5f + bmin[1];
3242  center[2] = dz*0.5f + bmin[2];
3243 
3244  if ( dx < EPSILON || dy < EPSILON || dz < EPSILON || svcount < 3 )
3245  {
3246 
3247  double len = FLT_MAX;
3248 
3249  if ( dx > EPSILON && dx < len ) len = dx;
3250  if ( dy > EPSILON && dy < len ) len = dy;
3251  if ( dz > EPSILON && dz < len ) len = dz;
3252 
3253  if ( len == FLT_MAX )
3254  {
3255  dx = dy = dz = 0.01f; // one centimeter
3256  }
3257  else
3258  {
3259  if ( dx < EPSILON ) dx = len * 0.05f; // 1/5th the shortest non-zero edge.
3260  if ( dy < EPSILON ) dy = len * 0.05f;
3261  if ( dz < EPSILON ) dz = len * 0.05f;
3262  }
3263 
3264  double x1 = center[0] - dx;
3265  double x2 = center[0] + dx;
3266 
3267  double y1 = center[1] - dy;
3268  double y2 = center[1] + dy;
3269 
3270  double z1 = center[2] - dz;
3271  double z2 = center[2] + dz;
3272 
3273  AddPoint(vcount,vertices,x1,y1,z1);
3274  AddPoint(vcount,vertices,x2,y1,z1);
3275  AddPoint(vcount,vertices,x2,y2,z1);
3276  AddPoint(vcount,vertices,x1,y2,z1);
3277  AddPoint(vcount,vertices,x1,y1,z2);
3278  AddPoint(vcount,vertices,x2,y1,z2);
3279  AddPoint(vcount,vertices,x2,y2,z2);
3280  AddPoint(vcount,vertices,x1,y2,z2);
3281 
3282  return true; // return cube
3283 
3284 
3285  }
3286  else
3287  {
3288  if ( scale )
3289  {
3290  scale[0] = dx;
3291  scale[1] = dy;
3292  scale[2] = dz;
3293 
3294  recip[0] = 1 / dx;
3295  recip[1] = 1 / dy;
3296  recip[2] = 1 / dz;
3297 
3298  center[0]*=recip[0];
3299  center[1]*=recip[1];
3300  center[2]*=recip[2];
3301 
3302  }
3303 
3304  }
3305 
3306 
3307 
3308  vtx = (const char *) svertices;
3309 
3310  for (unsigned int i=0; i<svcount; i++)
3311  {
3312 
3313  const double *p = (const double *)vtx;
3314  vtx+=stride;
3315 
3316  double px = p[0];
3317  double py = p[1];
3318  double pz = p[2];
3319 
3320  if ( scale )
3321  {
3322  px = px*recip[0]; // normalize
3323  py = py*recip[1]; // normalize
3324  pz = pz*recip[2]; // normalize
3325  }
3326 
3327  if ( 1 )
3328  {
3329  unsigned int j;
3330 
3331  for (j=0; j<vcount; j++)
3332  {
3333  double *v = &vertices[j*3];
3334 
3335  double x = v[0];
3336  double y = v[1];
3337  double z = v[2];
3338 
3339  double dx = fabs(x - px );
3340  double dy = fabs(y - py );
3341  double dz = fabs(z - pz );
3342 
3343  if ( dx < normalepsilon && dy < normalepsilon && dz < normalepsilon )
3344  {
3345  // ok, it is close enough to the old one
3346  // now let us see if it is further from the center of the point cloud than the one we already recorded.
3347  // in which case we keep this one instead.
3348 
3349  double dist1 = GetDist(px,py,pz,center);
3350  double dist2 = GetDist(v[0],v[1],v[2],center);
3351 
3352  if ( dist1 > dist2 )
3353  {
3354  v[0] = px;
3355  v[1] = py;
3356  v[2] = pz;
3357  }
3358 
3359  break;
3360  }
3361  }
3362 
3363  if ( j == vcount )
3364  {
3365  double *dest = &vertices[vcount*3];
3366  dest[0] = px;
3367  dest[1] = py;
3368  dest[2] = pz;
3369  vcount++;
3370  }
3371  }
3372  }
3373 
3374  // ok..now make sure we didn't prune so many vertices it is now invalid.
3375  if ( 1 )
3376  {
3377  double bmin[3] = { FLT_MAX, FLT_MAX, FLT_MAX };
3378  double bmax[3] = { -FLT_MAX, -FLT_MAX, -FLT_MAX };
3379 
3380  for (unsigned int i=0; i<vcount; i++)
3381  {
3382  const double *p = &vertices[i*3];
3383  for (int j=0; j<3; j++)
3384  {
3385  if ( p[j] < bmin[j] ) bmin[j] = p[j];
3386  if ( p[j] > bmax[j] ) bmax[j] = p[j];
3387  }
3388  }
3389 
3390  double dx = bmax[0] - bmin[0];
3391  double dy = bmax[1] - bmin[1];
3392  double dz = bmax[2] - bmin[2];
3393 
3394  if ( dx < EPSILON || dy < EPSILON || dz < EPSILON || vcount < 3)
3395  {
3396  double cx = dx*0.5f + bmin[0];
3397  double cy = dy*0.5f + bmin[1];
3398  double cz = dz*0.5f + bmin[2];
3399 
3400  double len = FLT_MAX;
3401 
3402  if ( dx >= EPSILON && dx < len ) len = dx;
3403  if ( dy >= EPSILON && dy < len ) len = dy;
3404  if ( dz >= EPSILON && dz < len ) len = dz;
3405 
3406  if ( len == FLT_MAX )
3407  {
3408  dx = dy = dz = 0.01f; // one centimeter
3409  }
3410  else
3411  {
3412  if ( dx < EPSILON ) dx = len * 0.05f; // 1/5th the shortest non-zero edge.
3413  if ( dy < EPSILON ) dy = len * 0.05f;
3414  if ( dz < EPSILON ) dz = len * 0.05f;
3415  }
3416 
3417  double x1 = cx - dx;
3418  double x2 = cx + dx;
3419 
3420  double y1 = cy - dy;
3421  double y2 = cy + dy;
3422 
3423  double z1 = cz - dz;
3424  double z2 = cz + dz;
3425 
3426  vcount = 0; // add box
3427 
3428  AddPoint(vcount,vertices,x1,y1,z1);
3429  AddPoint(vcount,vertices,x2,y1,z1);
3430  AddPoint(vcount,vertices,x2,y2,z1);
3431  AddPoint(vcount,vertices,x1,y2,z1);
3432  AddPoint(vcount,vertices,x1,y1,z2);
3433  AddPoint(vcount,vertices,x2,y1,z2);
3434  AddPoint(vcount,vertices,x2,y2,z2);
3435  AddPoint(vcount,vertices,x1,y2,z2);
3436 
3437  return true;
3438  }
3439  }
3440 
3441  return true;
3442 }
3443 
3444 void HullLibrary::BringOutYourDead(const double *verts,unsigned int vcount, double *overts,unsigned int &ocount,unsigned int *indices,unsigned indexcount)
3445 {
3446  unsigned int *used = (unsigned int *)NX_ALLOC(sizeof(unsigned int)*vcount, CONVEX_TEMP );
3447  memset(used,0,sizeof(unsigned int)*vcount);
3448 
3449  ocount = 0;
3450 
3451  for (unsigned int i=0; i<indexcount; i++)
3452  {
3453  unsigned int v = indices[i]; // original array index
3454 
3455  assert( v >= 0 && v < vcount );
3456 
3457  if ( used[v] ) // if already remapped
3458  {
3459  indices[i] = used[v]-1; // index to new array
3460  }
3461  else
3462  {
3463 
3464  indices[i] = ocount; // new index mapping
3465 
3466  overts[ocount*3+0] = verts[v*3+0]; // copy old vert to new vert array
3467  overts[ocount*3+1] = verts[v*3+1];
3468  overts[ocount*3+2] = verts[v*3+2];
3469 
3470  ocount++; // increment output vert count
3471 
3472  assert( ocount >=0 && ocount <= vcount );
3473 
3474  used[v] = ocount; // assign new index remapping
3475  }
3476  }
3477 
3478  NX_FREE(used);
3479 }
3480 
3481 
3482 //==================================================================================
3484 {
3485  HullError ret = QE_FAIL;
3486 
3487 
3488  const double *p = answer.mOutputVertices;
3489  const unsigned int *idx = answer.mIndices;
3490  unsigned int fcount = answer.mNumFaces;
3491 
3492  if ( p && idx && fcount )
3493  {
3494  ret = QE_OK;
3495 
3496  for (unsigned int i=0; i<fcount; i++)
3497  {
3498  unsigned int pcount = *idx++;
3499 
3500  unsigned int i1 = *idx++;
3501  unsigned int i2 = *idx++;
3502  unsigned int i3 = *idx++;
3503 
3504  const double *p1 = &p[i1*3];
3505  const double *p2 = &p[i2*3];
3506  const double *p3 = &p[i3*3];
3507 
3508  AddConvexTriangle(iface,p1,p2,p3);
3509 
3510  pcount-=3;
3511  while ( pcount )
3512  {
3513  i3 = *idx++;
3514  p2 = p3;
3515  p3 = &p[i3*3];
3516 
3517  AddConvexTriangle(iface,p1,p2,p3);
3518  pcount--;
3519  }
3520 
3521  }
3522  }
3523 
3524  return ret;
3525 }
3526 
3527 //==================================================================================
3528 void HullLibrary::AddConvexTriangle(ConvexHullTriangleInterface *callback,const double *p1,const double *p2,const double *p3)
3529 {
3530  ConvexHullVertex v1,v2,v3;
3531 
3532  #define TSCALE1 (1.0f/4.0f)
3533 
3534  v1.mPos[0] = p1[0];
3535  v1.mPos[1] = p1[1];
3536  v1.mPos[2] = p1[2];
3537 
3538  v2.mPos[0] = p2[0];
3539  v2.mPos[1] = p2[1];
3540  v2.mPos[2] = p2[2];
3541 
3542  v3.mPos[0] = p3[0];
3543  v3.mPos[1] = p3[1];
3544  v3.mPos[2] = p3[2];
3545 
3546  double n[3];
3547  ComputeNormal(n,p1,p2,p3);
3548 
3549  v1.mNormal[0] = n[0];
3550  v1.mNormal[1] = n[1];
3551  v1.mNormal[2] = n[2];
3552 
3553  v2.mNormal[0] = n[0];
3554  v2.mNormal[1] = n[1];
3555  v2.mNormal[2] = n[2];
3556 
3557  v3.mNormal[0] = n[0];
3558  v3.mNormal[1] = n[1];
3559  v3.mNormal[2] = n[2];
3560 
3561  const double *tp1 = p1;
3562  const double *tp2 = p2;
3563  const double *tp3 = p3;
3564 
3565  int i1 = 0;
3566  int i2 = 0;
3567 
3568  double nx = fabs(n[0]);
3569  double ny = fabs(n[1]);
3570  double nz = fabs(n[2]);
3571 
3572  if ( nx <= ny && nx <= nz )
3573  i1 = 0;
3574  if ( ny <= nx && ny <= nz )
3575  i1 = 1;
3576  if ( nz <= nx && nz <= ny )
3577  i1 = 2;
3578 
3579  switch ( i1 )
3580  {
3581  case 0:
3582  if ( ny < nz )
3583  i2 = 1;
3584  else
3585  i2 = 2;
3586  break;
3587  case 1:
3588  if ( nx < nz )
3589  i2 = 0;
3590  else
3591  i2 = 2;
3592  break;
3593  case 2:
3594  if ( nx < ny )
3595  i2 = 0;
3596  else
3597  i2 = 1;
3598  break;
3599  }
3600 
3601  v1.mTexel[0] = tp1[i1]*TSCALE1;
3602  v1.mTexel[1] = tp1[i2]*TSCALE1;
3603 
3604  v2.mTexel[0] = tp2[i1]*TSCALE1;
3605  v2.mTexel[1] = tp2[i2]*TSCALE1;
3606 
3607  v3.mTexel[0] = tp3[i1]*TSCALE1;
3608  v3.mTexel[1] = tp3[i2]*TSCALE1;
3609 
3610  callback->ConvexHullTriangle(v3,v2,v1);
3611 }
3612 
3613 //==================================================================================
3614 double HullLibrary::ComputeNormal(double *n,const double *A,const double *B,const double *C)
3615 {
3616  double vx,vy,vz,wx,wy,wz,vw_x,vw_y,vw_z,mag;
3617 
3618  vx = (B[0] - C[0]);
3619  vy = (B[1] - C[1]);
3620  vz = (B[2] - C[2]);
3621 
3622  wx = (A[0] - B[0]);
3623  wy = (A[1] - B[1]);
3624  wz = (A[2] - B[2]);
3625 
3626  vw_x = vy * wz - vz * wy;
3627  vw_y = vz * wx - vx * wz;
3628  vw_z = vx * wy - vy * wx;
3629 
3630  mag = sqrt((vw_x * vw_x) + (vw_y * vw_y) + (vw_z * vw_z));
3631 
3632  if ( mag < 0.000001f )
3633  {
3634  mag = 0;
3635  }
3636  else
3637  {
3638  mag = 1.0f/mag;
3639  }
3640 
3641  n[0] = vw_x * mag;
3642  n[1] = vw_y * mag;
3643  n[2] = vw_z * mag;
3644 
3645  return mag;
3646 }
3647 
3648 
3649 
3650 };
ConvexDecomposition::double4::operator[]
const double & operator[](int i) const
Definition: cd_hull.cpp:461
ConvexDecomposition::double4x4::x
double4 x
Definition: cd_hull.cpp:472
ConvexDecomposition::QF_TRIANGLES
@ QF_TRIANGLES
Definition: cd_hull.h:137
ConvexDecomposition::ConvexH::vertices
Array< REAL3 > vertices
Definition: cd_hull.cpp:1667
ConvexDecomposition::MatrixRotationZ
double4x4 MatrixRotationZ(const double angle_radians)
Definition: cd_hull.cpp:1004
NX_FREE
#define NX_FREE(x)
Definition: cd_hull.cpp:77
ConvexDecomposition::HullResult::mPolygons
bool mPolygons
Definition: cd_hull.h:77
ConvexDecomposition::Quaternion::zdir
double3 zdir() const
Definition: cd_hull.cpp:520
ConvexDecomposition::test_cube
ConvexH * test_cube()
Definition: cd_hull.cpp:1815
ConvexDecomposition::double3::double3
double3()
Definition: cd_hull.cpp:383
ConvexDecomposition::Array::operator[]
Type & operator[](int i)
Definition: cd_hull.cpp:112
ConvexDecomposition::HullLibrary::AddConvexTriangle
void AddConvexTriangle(ConvexHullTriangleInterface *callback, const double *p1, const double *p2, const double *p3)
Definition: cd_hull.cpp:3528
ConvexDecomposition::minadjangle
double minadjangle
Definition: cd_hull.cpp:2202
ConvexDecomposition::ConvexH
Definition: cd_hull.cpp:1652
ConvexDecomposition::plane::normal
point normal
Definition: planetri.cpp:198
ConvexDecomposition::int4::x
int x
Definition: cd_hull.cpp:2524
ConvexDecomposition::hasedge
int hasedge(const int3 &t, int a, int b)
Definition: cd_hull.cpp:2366
ConvexDecomposition::vabs
double3 vabs(const double3 &v)
Definition: cd_hull.cpp:718
ConvexDecomposition::HullDesc::mSkinWidth
double mSkinWidth
Definition: cd_hull.h:193
ConvexDecomposition::HullResult::mOutputVertices
double * mOutputVertices
Definition: cd_hull.h:79
ConvexDecomposition::double4x4::y
double4 y
Definition: cd_hull.cpp:472
ConvexDecomposition::HullDesc::mVcount
unsigned int mVcount
Definition: cd_hull.h:189
ConvexDecomposition::Plane::dist
double dist
Definition: cd_hull.cpp:557
ConvexDecomposition::Array::~Array
~Array()
Definition: cd_hull.cpp:173
ConvexDecomposition::Plane::Transform
void Transform(const double3 &position, const Quaternion &orientation)
Definition: cd_hull.cpp:1264
ConvexDecomposition::Determinant
double Determinant(const double3x3 &m)
Definition: cd_hull.cpp:786
ConvexDecomposition::operator+
double2 operator+(const double2 &a, const double2 &b)
Definition: cd_hull.cpp:375
ConvexDecomposition::double3x3::operator()
double & operator()(int r, int c)
Definition: cd_hull.cpp:432
ConvexDecomposition::EdgeFlag::fixes
unsigned char fixes
Definition: cd_hull.cpp:1726
ConvexDecomposition::Array::SetSize
void SetSize(int s)
Definition: cd_hull.cpp:200
ConvexDecomposition::MatrixTranspose
double4x4 MatrixTranspose(const double4x4 &m)
Definition: cd_hull.cpp:951
ConvexDecomposition::operator*=
double3 & operator*=(double3 &v, const double s)
Definition: cd_hull.cpp:700
ConvexDecomposition::FindSimplex
int4 FindSimplex(double3 *verts, int verts_count, Array< int > &allow)
Definition: cd_hull.cpp:2542
ConvexDecomposition::EdgeFlag::overmap
short overmap
Definition: cd_hull.cpp:1728
ConvexDecomposition::BoxIntersect
int BoxIntersect(const double3 &v0, const double3 &v1, const double3 &bmin, const double3 &bmax, double3 *impact)
Definition: cd_hull.cpp:1390
ConvexDecomposition::maxdir
int maxdir(const T *p, int count, const T &dir)
Definition: cd_hull.cpp:2254
ConvexDecomposition::ConvexH::facets
Array< Plane > facets
Definition: cd_hull.cpp:1669
ConvexDecomposition::Yaw
double Yaw(const Quaternion &q)
Definition: cd_hull.cpp:1229
OVER
#define OVER
Definition: cd_hull.cpp:1644
ConvexDecomposition::PlaneFlip
Plane PlaneFlip(const Plane &plane)
Definition: cd_hull.cpp:563
ConvexDecomposition::Array::Insert
void Insert(Type, int)
Definition: cd_hull.cpp:280
ConvexDecomposition::BoxInside
int BoxInside(const double3 &p, const double3 &bmin, const double3 &bmax)
Definition: cd_hull.cpp:1382
ConvexDecomposition::Homogenize
double4 Homogenize(const double3 &v3, const double &w=1.0f)
Definition: cd_hull.cpp:939
ConvexDecomposition::Array::operator=
Array< Type > & operator=(Array< Type > &array)
Definition: cd_hull.cpp:163
ConvexDecomposition::double3::z
double z
Definition: cd_hull.cpp:382
ConvexDecomposition::maxdirfiltered
int maxdirfiltered(const T *p, int count, const T &dir, Array< int > &allow)
Definition: cd_hull.cpp:2267
ConvexDecomposition::isa
int isa(const int3 &a, const int3 &b)
Definition: cd_hull.cpp:2353
ConvexDecomposition::operator-
double2 operator-(const double2 &a, const double2 &b)
Definition: cd_hull.cpp:374
ConvexDecomposition::double3::y
double y
Definition: cd_hull.cpp:382
ConvexDecomposition::area2
static double area2(const double3 &v0, const double3 &v1, const double3 &v2)
Definition: cd_hull.cpp:2693
ConvexDecomposition::Quaternion::getmatrix
double3x3 getmatrix() const
Definition: cd_hull.cpp:521
ConvexDecomposition::MatrixRigidInverse
double4x4 MatrixRigidInverse(const double4x4 &m)
Definition: cd_hull.cpp:960
ConvexDecomposition::double4::operator[]
double & operator[](int i)
Definition: cd_hull.cpp:460
ConvexDecomposition::Array::allocate
void allocate(int s)
Definition: cd_hull.cpp:182
ConvexDecomposition::calchullpbev
int calchullpbev(double3 *verts, int verts_count, int vlimit, Array< Plane > &planes, double bevangle)
Definition: cd_hull.cpp:2698
ConvexDecomposition::NormalOf
double3 NormalOf(const double3 *vert, const int n)
ConvexDecomposition::int3::y
int y
Definition: cd_hull.cpp:355
ConvexDecomposition::AddPoint
static void AddPoint(unsigned int &vcount, double *p, double x, double y, double z)
Definition: cd_hull.cpp:3165
ConvexDecomposition::calchull
int calchull(double3 *verts, int verts_count, int *&tris_out, int &tris_count, int vlimit)
Definition: cd_hull.cpp:2675
ConvexDecomposition::ConvexHMakeCube
ConvexH * ConvexHMakeCube(const REAL3 &bmin, const REAL3 &bmax)
Definition: cd_hull.cpp:1871
RAD2DEG
#define RAD2DEG
Definition: cd_hull.cpp:316
ConvexDecomposition::ConvexHullVertex::mPos
double mPos[3]
Definition: cd_hull.h:207
ConvexDecomposition::HullDesc
Definition: cd_hull.h:144
ConvexDecomposition::operator!=
int operator!=(const double3 &a, const double3 &b)
Definition: cd_hull.cpp:411
ConvexDecomposition::ConvexHullTriangleInterface::ConvexHullTriangle
virtual void ConvexHullTriangle(const ConvexHullVertex &v1, const ConvexHullVertex &v2, const ConvexHullVertex &v3)=0
ConvexDecomposition::Coplanar::ea
unsigned short ea
Definition: cd_hull.cpp:1738
ConvexDecomposition::HullResult::mNumOutputVertices
unsigned int mNumOutputVertices
Definition: cd_hull.h:78
ConvexDecomposition::int3::z
int z
Definition: cd_hull.cpp:355
ConvexDecomposition::double4x4::w
double4 w
Definition: cd_hull.cpp:472
ConvexDecomposition::Array::operator[]
const Type & operator[](int i) const
Definition: cd_hull.cpp:111
UNDER
#define UNDER
Definition: cd_hull.cpp:1643
ConvexDecomposition::Tri::id
int id
Definition: cd_hull.cpp:2402
ConvexDecomposition::double3::operator[]
double & operator[](int i)
Definition: cd_hull.cpp:386
ConvexDecomposition::clampf
double clampf(double a)
Definition: cd_hull.cpp:592
ConvexDecomposition::DistanceBetweenLines
double DistanceBetweenLines(const double3 &ustart, const double3 &udir, const double3 &vstart, const double3 &vdir, double3 *upoint=NULL, double3 *vpoint=NULL)
Definition: cd_hull.cpp:1485
ConvexDecomposition::operator-=
double3 & operator-=(double3 &a, const double3 &b)
Definition: cd_hull.cpp:691
ConvexDecomposition::HullLibrary::CreateConvexHull
HullError CreateConvexHull(const HullDesc &desc, HullResult &result)
Definition: cd_hull.cpp:2948
ConvexDecomposition::double3x3::y
double3 y
Definition: cd_hull.cpp:426
ConvexDecomposition::PHullResult::mFaceCount
unsigned int mFaceCount
Definition: cd_hull.cpp:1626
ConvexDecomposition::dot
double dot(const double3 &a, const double3 &b)
Definition: cd_hull.cpp:661
ConvexDecomposition::Inverse
double3x3 Inverse(const double3x3 &a)
Definition: cd_hull.cpp:792
ConvexDecomposition::Array::Pop
Type & Pop()
Definition: cd_hull.cpp:113
ConvexDecomposition::double3x3::double3x3
double3x3(double xx, double xy, double xz, double yx, double yy, double yz, double zx, double zy, double zz)
Definition: cd_hull.cpp:428
ConvexDecomposition::operator==
int operator==(const double3 &a, const double3 &b)
Definition: cd_hull.cpp:410
ConvexDecomposition::Transpose
double3x3 Transpose(const double3x3 &m)
Definition: cd_hull.cpp:814
ConvexDecomposition::MatrixTranslation
double4x4 MatrixTranslation(const double3 &t)
Definition: cd_hull.cpp:994
ConvexDecomposition::Array::Remove
void Remove(Type)
Definition: cd_hull.cpp:262
ConvexDecomposition::VertFlag::undermap
unsigned char undermap
Definition: cd_hull.cpp:1719
ConvexDecomposition::ConvexHullVertex::mNormal
double mNormal[3]
Definition: cd_hull.h:208
ConvexDecomposition::Plane
Definition: cd_hull.cpp:553
ConvexDecomposition::cmul
double3 cmul(const double3 &a, const double3 &b)
Definition: cd_hull.cpp:666
ConvexDecomposition::double3x3::operator[]
double3 & operator[](int i)
Definition: cd_hull.cpp:430
ConvexDecomposition::Tri
Definition: cd_hull.cpp:2395
ConvexDecomposition::VectorMax
double3 VectorMax(const double3 &a, const double3 &b)
Definition: cd_hull.cpp:769
ConvexDecomposition::double4x4::operator()
const double & operator()(int r, int c) const
Definition: cd_hull.cpp:481
ConvexDecomposition::Quaternion::axis
double3 axis() const
Definition: cd_hull.cpp:517
ConvexDecomposition::PolyHit
int PolyHit(const double3 *vert, const int n, const double3 &v0, const double3 &v1, double3 *impact=NULL, double3 *normal=NULL)
Definition: cd_hull.cpp:1557
ConvexDecomposition::b2b
int b2b(const int3 &a, const int3 &b)
Definition: cd_hull.cpp:2357
ConvexDecomposition::HullLibrary::ReleaseResult
HullError ReleaseResult(HullResult &result)
Definition: cd_hull.cpp:3149
ConvexDecomposition::HullLibrary::BringOutYourDead
void BringOutYourDead(const double *verts, unsigned int vcount, double *overts, unsigned int &ocount, unsigned int *indices, unsigned indexcount)
Definition: cd_hull.cpp:3444
ConvexDecomposition::double4::double4
double4(double _x, double _y, double _z, double _w)
Definition: cd_hull.cpp:457
ConvexDecomposition::PHullResult::mIndexCount
unsigned int mIndexCount
Definition: cd_hull.cpp:1625
ConvexDecomposition::ConvexH::HalfEdge::p
unsigned char p
Definition: cd_hull.cpp:1663
ConvexDecomposition::extrudable
Tri * extrudable(double epsilon)
Definition: cd_hull.cpp:2507
ConvexDecomposition::EdgeFlag::undermap
short undermap
Definition: cd_hull.cpp:1727
ConvexDecomposition::HullResult::mNumIndices
unsigned int mNumIndices
Definition: cd_hull.h:81
REAL3
#define REAL3
Definition: cd_hull.cpp:1639
ConvexDecomposition::Quaternion::Quaternion
Quaternion()
Definition: cd_hull.cpp:513
ConvexDecomposition::operator/=
double3 & operator/=(double3 &v, const double s)
Definition: cd_hull.cpp:709
ConvexDecomposition::VertFlag
Definition: cd_hull.cpp:1714
ConvexDecomposition::int4
Definition: cd_hull.cpp:2521
ConvexDecomposition::ConvexH::HalfEdge::HalfEdge
HalfEdge()
Definition: cd_hull.cpp:1664
ConvexDecomposition::Tri::neib
int & neib(int a, int b)
Definition: cd_hull.cpp:2421
ConvexDecomposition::HullResult
Definition: cd_hull.h:65
ConvexDecomposition::det
double det(const double *p1, const double *p2, const double *p3)
Definition: meshvolume.cpp:62
ConvexDecomposition::double4x4::double4x4
double4x4(const double4 &_x, const double4 &_y, const double4 &_z, const double4 &_w)
Definition: cd_hull.cpp:474
ConvexDecomposition::double3x3::double3x3
double3x3(double3 _x, double3 _y, double3 _z)
Definition: cd_hull.cpp:429
ConvexDecomposition::countpolyhit
int countpolyhit
Definition: cd_hull.cpp:1556
ConvexDecomposition::MatrixPerspectiveFov
double4x4 MatrixPerspectiveFov(double fovy, double Aspect, double zn, double zf)
Definition: cd_hull.cpp:969
ConvexDecomposition
Definition: bestfit.cpp:75
ConvexDecomposition::double2::y
double y
Definition: cd_hull.cpp:368
ConvexDecomposition::int3::x
int x
Definition: cd_hull.cpp:355
ConvexDecomposition::MatrixLookAt
double4x4 MatrixLookAt(const double3 &eye, const double3 &at, const double3 &up)
Definition: cd_hull.cpp:982
ConvexDecomposition::double4::double4
double4(const double3 &v, double _w)
Definition: cd_hull.cpp:458
ConvexDecomposition::TriNormal
double3 TriNormal(const double3 &v0, const double3 &v1, const double3 &v2)
Definition: cd_hull.cpp:1370
ConvexDecomposition::double3x3::x
double3 x
Definition: cd_hull.cpp:426
TSCALE1
#define TSCALE1
ConvexDecomposition::double3::operator[]
const double & operator[](int i) const
Definition: cd_hull.cpp:387
ConvexDecomposition::Array::array_size
int array_size
Definition: cd_hull.cpp:110
ConvexDecomposition::double2::operator[]
double & operator[](int i)
Definition: cd_hull.cpp:371
ConvexDecomposition::Array::IndexOf
int IndexOf(Type)
Definition: cd_hull.cpp:294
ConvexDecomposition::PHullResult::PHullResult
PHullResult(void)
Definition: cd_hull.cpp:1615
ConvexDecomposition::Interpolate
double Interpolate(const double &f0, const double &f1, double alpha)
Definition: cd_hull.cpp:601
ConvexDecomposition::operator/
double3 operator/(const double3 &v, const double s)
Definition: cd_hull.cpp:656
ConvexDecomposition::PHullResult::mIndices
unsigned int * mIndices
Definition: cd_hull.cpp:1628
ConvexDecomposition::overhullv
static int overhullv(double3 *verts, int verts_count, int maxplanes, double3 *&verts_out, int &verts_count_out, int *&faces_out, int &faces_count_out, double inflate, double bevangle, int vlimit)
Definition: cd_hull.cpp:2864
ConvexDecomposition::HullDesc::mMaxVertices
unsigned int mMaxVertices
Definition: cd_hull.h:194
ConvexDecomposition::double4::xyz
const double3 & xyz() const
Definition: cd_hull.cpp:462
ConvexDecomposition::HullError
HullError
Definition: cd_hull.h:197
ConvexDecomposition::double3x3::operator[]
const double3 & operator[](int i) const
Definition: cd_hull.cpp:431
ConvexDecomposition::ConvexH::HalfEdge::v
unsigned char v
Definition: cd_hull.cpp:1662
ConvexDecomposition::ConvexHullVertex::mTexel
double mTexel[2]
Definition: cd_hull.h:209
ConvexDecomposition::Quaternion::Quaternion
Quaternion(double _x, double _y, double _z, double _w)
Definition: cd_hull.cpp:515
ConvexDecomposition::double3
Definition: cd_hull.cpp:379
ConvexDecomposition::int4::operator[]
int & operator[](int i)
Definition: cd_hull.cpp:2528
ConvexDecomposition::double2::double2
double2()
Definition: cd_hull.cpp:369
ConvexDecomposition::double2::x
double x
Definition: cd_hull.cpp:368
ConvexDecomposition::double4::xyz
double3 & xyz()
Definition: cd_hull.cpp:463
ConvexDecomposition::double4::z
double z
Definition: cd_hull.cpp:455
ConvexDecomposition::HullDesc::mVertexStride
unsigned int mVertexStride
Definition: cd_hull.h:191
VOLUME_EPSILON
#define VOLUME_EPSILON
Definition: cd_hull.cpp:1647
ConvexDecomposition::HullLibrary::CleanupVertices
bool CleanupVertices(unsigned int svcount, const double *svertices, unsigned int stride, unsigned int &vcount, double *vertices, double normalepsilon, double *scale)
Definition: cd_hull.cpp:3187
ConvexDecomposition::double3x3::double3x3
double3x3()
Definition: cd_hull.cpp:427
ConvexDecomposition::Array
Definition: cd_hull.cpp:91
ConvexDecomposition::Array::count
int count
Definition: cd_hull.cpp:109
ConvexDecomposition::argmin
int argmin(double a[], int n)
Definition: cd_hull.cpp:607
ConvexDecomposition::ConvexH::ConvexH
ConvexH(int vertices_size, int edges_size, int facets_size)
Definition: cd_hull.cpp:1675
ConvexDecomposition::hasvert
int hasvert(const int3 &t, int v)
Definition: cd_hull.cpp:2375
ConvexDecomposition::ConvexH::HalfEdge
Definition: cd_hull.cpp:1658
ConvexDecomposition::Tri::~Tri
~Tri()
Definition: cd_hull.cpp:2412
ConvexDecomposition::PlaneFlag
Definition: cd_hull.cpp:1730
ConvexDecomposition::Quaternion::Quaternion
Quaternion(double3 v, double t)
Definition: cd_hull.cpp:514
ConvexDecomposition::double4::w
double w
Definition: cd_hull.cpp:455
ConvexDecomposition::ConvexHCrop
ConvexH * ConvexHCrop(ConvexH &convex, const Plane &slice)
Definition: cd_hull.cpp:1890
ConvexDecomposition::Plane::Plane
Plane()
Definition: cd_hull.cpp:559
ConvexDecomposition::calchullgen
int calchullgen(double3 *verts, int verts_count, int vlimit)
Definition: cd_hull.cpp:2572
ConvexDecomposition::Coplanar::v0
unsigned char v0
Definition: cd_hull.cpp:1739
ConvexDecomposition::QE_FAIL
@ QE_FAIL
Definition: cd_hull.h:200
ConvexDecomposition::PlaneFlag::overmap
unsigned char overmap
Definition: cd_hull.cpp:1734
ConvexDecomposition::Quaternion::Normalize
void Normalize()
Definition: cd_hull.cpp:1138
ConvexDecomposition::Round
double Round(double a, double precision)
Definition: cd_hull.cpp:595
ConvexDecomposition::tris
static Array< Tri * > tris
Definition: cd_hull.cpp:2390
ConvexDecomposition::ArrayRet
Definition: cd_hull.cpp:90
ConvexDecomposition::VertFlag::overmap
unsigned char overmap
Definition: cd_hull.cpp:1720
DEG2RAD
#define DEG2RAD
Definition: cd_hull.cpp:315
ConvexDecomposition::VirtualTrackBall
Quaternion VirtualTrackBall(const double3 &cop, const double3 &cor, const double3 &dir0, const double3 &dir1)
Definition: cd_hull.cpp:1511
ConvexDecomposition::slerp
Quaternion slerp(Quaternion a, const Quaternion &b, double interp)
Definition: cd_hull.cpp:1197
ConvexDecomposition::int4::w
int w
Definition: cd_hull.cpp:2524
ConvexDecomposition::int3
Definition: cd_hull.cpp:352
ConvexDecomposition::int4::y
int y
Definition: cd_hull.cpp:2524
ConvexDecomposition::GetDist
double GetDist(double px, double py, double pz, const double *p2)
Definition: cd_hull.cpp:3175
ConvexDecomposition::double3::double3
double3(double _x, double _y, double _z)
Definition: cd_hull.cpp:384
ConvexDecomposition::double4::x
double x
Definition: cd_hull.cpp:455
ConvexDecomposition::cross
double3 cross(const double3 &a, const double3 &b)
Definition: cd_hull.cpp:672
ConvexDecomposition::int4::int4
int4(int _x, int _y, int _z, int _w)
Definition: cd_hull.cpp:2526
ConvexDecomposition::double3x3::operator()
const double & operator()(int r, int c) const
Definition: cd_hull.cpp:433
ConvexDecomposition::safenormalize
double3 safenormalize(const double3 &v)
Definition: cd_hull.cpp:745
ConvexDecomposition::QF_REVERSE_ORDER
@ QF_REVERSE_ORDER
Definition: cd_hull.h:138
ConvexDecomposition::PHullResult::mVcount
unsigned int mVcount
Definition: cd_hull.cpp:1624
ConvexDecomposition::int3::int3
int3()
Definition: cd_hull.cpp:356
ConvexDecomposition::Quaternion::ydir
double3 ydir() const
Definition: cd_hull.cpp:519
ConvexDecomposition::EdgeFlag::planetest
unsigned char planetest
Definition: cd_hull.cpp:1725
ConvexDecomposition::orth
double3 orth(const double3 &v)
Definition: cd_hull.cpp:2279
ConvexDecomposition::double4x4::operator()
double & operator()(int r, int c)
Definition: cd_hull.cpp:480
ConvexDecomposition::double2::double2
double2(double _x, double _y)
Definition: cd_hull.cpp:370
ConvexDecomposition::Array::Pack
void Pack()
Definition: cd_hull.cpp:218
ConvexDecomposition::HullLibrary::ComputeNormal
double ComputeNormal(double *n, const double *A, const double *B, const double *C)
Definition: cd_hull.cpp:3614
ConvexDecomposition::Plane::Plane
Plane(const double3 &n, double d)
Definition: cd_hull.cpp:558
ConvexDecomposition::ThreePlaneIntersection
double3 ThreePlaneIntersection(const Plane &p0, const Plane &p1, const Plane &p2)
Definition: cd_hull.cpp:878
ConvexDecomposition::HullResult::mIndices
unsigned int * mIndices
Definition: cd_hull.h:82
ConvexDecomposition::VectorMin
double3 VectorMin(const double3 &a, const double3 &b)
Definition: cd_hull.cpp:765
ConvexDecomposition::Tri::Tri
Tri(int a, int b, int c)
Definition: cd_hull.cpp:2405
ConvexDecomposition::operator+=
double3 & operator+=(double3 &a, const double3 &b)
Definition: cd_hull.cpp:682
ConvexDecomposition::ConvexHullVertex
Definition: cd_hull.h:204
ConvexDecomposition::double4x4::z
double4 z
Definition: cd_hull.cpp:472
ConvexDecomposition::Array::Contains
int Contains(Type)
Definition: cd_hull.cpp:234
ConvexDecomposition::PHullResult
Definition: cd_hull.cpp:1611
ConvexDecomposition::Min
T Min(const T &a, const T &b)
Definition: cd_hull.cpp:345
ConvexDecomposition::overhull
static int overhull(Plane *planes, int planes_count, double3 *verts, int verts_count, int maxplanes, double3 *&verts_out, int &verts_count_out, int *&faces_out, int &faces_count_out, double inflate)
Definition: cd_hull.cpp:2773
ConvexDecomposition::Max
T Max(const T &a, const T &b)
Definition: cd_hull.cpp:339
ConvexDecomposition::Tri::vmax
int vmax
Definition: cd_hull.cpp:2403
ConvexDecomposition::HullResult::mNumFaces
unsigned int mNumFaces
Definition: cd_hull.h:80
ConvexDecomposition::Quaternion::xdir
double3 xdir() const
Definition: cd_hull.cpp:518
ConvexDecomposition::double4::y
double y
Definition: cd_hull.cpp:455
ConvexDecomposition::double4x4::double4x4
double4x4(double m00, double m01, double m02, double m03, double m10, double m11, double m12, double m13, double m20, double m21, double m22, double m23, double m30, double m31, double m32, double m33)
Definition: cd_hull.cpp:475
ConvexDecomposition::Array::Array
Array(int s=0)
Definition: cd_hull.cpp:123
ConvexDecomposition::ConvexH::edges
Array< HalfEdge > edges
Definition: cd_hull.cpp:1668
ConvexDecomposition::VertFlag::junk
unsigned char junk
Definition: cd_hull.cpp:1718
ConvexDecomposition::RotationArc
Quaternion RotationArc(double3 v0, double3 v1)
Definition: cd_hull.cpp:1286
ConvexDecomposition::MatrixFromQuatVec
double4x4 MatrixFromQuatVec(const Quaternion &q, const double3 &v)
Definition: cd_hull.cpp:1302
ConvexDecomposition::coplanar
int coplanar(const Plane &a, const Plane &b)
Definition: cd_hull.cpp:565
ConvexDecomposition::removeb2b
void removeb2b(Tri *s, Tri *t)
Definition: cd_hull.cpp:2451
ConvexDecomposition::int3::operator[]
const int & operator[](int i) const
Definition: cd_hull.cpp:358
ConvexDecomposition::double4
Definition: cd_hull.cpp:452
ConvexDecomposition::int3::int3
int3(int _x, int _y, int _z)
Definition: cd_hull.cpp:357
ConvexDecomposition::QF_SKIN_WIDTH
@ QF_SKIN_WIDTH
Definition: cd_hull.h:139
ConvexDecomposition::Coplanar
Definition: cd_hull.cpp:1736
ConvexDecomposition::normalize
double3 normalize(const double3 &v)
Definition: cd_hull.cpp:731
ConvexDecomposition::Array::DelIndex
void DelIndex(int i)
Definition: cd_hull.cpp:251
ConvexDecomposition::PlaneTest
int PlaneTest(const Plane &p, const REAL3 &v)
Definition: cd_hull.cpp:1700
ConvexDecomposition::PlaneLineIntersection
double3 PlaneLineIntersection(const Plane &plane, const double3 &p0, const double3 &p1)
Definition: cd_hull.cpp:1336
ConvexDecomposition::ReleaseHull
void ReleaseHull(PHullResult &result)
Definition: cd_hull.cpp:2932
ConvexDecomposition::PHullResult::mVertices
double * mVertices
Definition: cd_hull.cpp:1627
ConvexDecomposition::SplitTest
int SplitTest(ConvexH &convex, const Plane &plane)
Definition: cd_hull.cpp:1706
ConvexDecomposition::EPSILON
static const double EPSILON
Definition: triangulate.cpp:106
ConvexDecomposition::AssertIntact
int AssertIntact(ConvexH &convex)
Definition: cd_hull.cpp:1743
ConvexDecomposition::ConvexHDup
ConvexH * ConvexHDup(ConvexH *src)
Definition: cd_hull.cpp:1685
ConvexDecomposition::double4x4
Definition: cd_hull.cpp:469
ConvexDecomposition::Coplanar::v1
unsigned char v1
Definition: cd_hull.cpp:1740
cd_hull.h
ConvexDecomposition::checkit
void checkit(Tri *t)
Definition: cd_hull.cpp:2458
ConvexDecomposition::VertFlag::planetest
unsigned char planetest
Definition: cd_hull.cpp:1717
ConvexDecomposition::double3x3::z
double3 z
Definition: cd_hull.cpp:426
ConvexDecomposition::Swap
void Swap(T &a, T &b)
Definition: cd_hull.cpp:329
ConvexDecomposition::Array::element
Type * element
Definition: cd_hull.cpp:108
ConvexDecomposition::YawPitchRoll
Quaternion YawPitchRoll(double yaw, double pitch, double roll)
Definition: cd_hull.cpp:1221
ConvexDecomposition::QE_OK
@ QE_OK
Definition: cd_hull.h:199
ConvexDecomposition::HullDesc::mVertices
const double * mVertices
Definition: cd_hull.h:190
ConvexDecomposition::planetestepsilon
double planetestepsilon
Definition: cd_hull.cpp:1649
ConvexDecomposition::maxdirsterid
int maxdirsterid(const T *p, int count, const T &dir, Array< int > &allow)
Definition: cd_hull.cpp:2288
ConvexDecomposition::double4x4::double4x4
double4x4()
Definition: cd_hull.cpp:473
ConvexDecomposition::HullDesc::HasHullFlag
bool HasHullFlag(HullFlag flag) const
Definition: cd_hull.h:172
ConvexDecomposition::test_btbq
ConvexH * test_btbq()
Definition: cd_hull.cpp:1787
ConvexDecomposition::plane
Definition: planetri.cpp:182
ConvexDecomposition::ConvexH::HalfEdge::ea
short ea
Definition: cd_hull.cpp:1661
ConvexDecomposition::Plane::normal
double3 normal
Definition: cd_hull.cpp:556
ConvexDecomposition::HullLibrary::CreateTriangleMesh
HullError CreateTriangleMesh(HullResult &answer, ConvexHullTriangleInterface *iface)
Definition: cd_hull.cpp:3483
ConvexDecomposition::b2bfix
void b2bfix(Tri *s, Tri *t)
Definition: cd_hull.cpp:2435
ConvexDecomposition::roll3
int3 roll3(int3 a)
Definition: cd_hull.cpp:2345
ConvexDecomposition::ConvexH::HalfEdge::HalfEdge
HalfEdge(short _ea, unsigned char _v, unsigned char _p)
Definition: cd_hull.cpp:1665
ConvexDecomposition::LineProject
double3 LineProject(const double3 &p0, const double3 &p1, const double3 &a)
Definition: cd_hull.cpp:1351
ConvexDecomposition::EdgeFlag
Definition: cd_hull.cpp:1722
ConvexDecomposition::HullDesc::mNormalEpsilon
double mNormalEpsilon
Definition: cd_hull.h:192
ConvexDecomposition::Array::Add
Type & Add(Type)
Definition: cd_hull.cpp:223
ConvexDecomposition::Array::AddUnique
void AddUnique(Type)
Definition: cd_hull.cpp:245
ConvexDecomposition::double4::double4
double4()
Definition: cd_hull.cpp:456
NX_ALLOC
#define NX_ALLOC(x, y)
Definition: cd_hull.cpp:76
ConvexDecomposition::Quaternion::angle
double angle() const
Definition: cd_hull.cpp:516
ConvexDecomposition::ConvexHullTriangleInterface
Definition: cd_hull.h:213
ConvexDecomposition::candidateplane
static int candidateplane(Plane *planes, int planes_count, ConvexH *convex, double epsilon)
Definition: cd_hull.cpp:2203
PAPERWIDTH
#define PAPERWIDTH
Definition: cd_hull.cpp:1646
ConvexDecomposition::HalfEdge
ConvexH::HalfEdge HalfEdge
Definition: cd_hull.cpp:1673
ConvexDecomposition::shareedge
int shareedge(const int3 &a, const int3 &b)
Definition: cd_hull.cpp:2379
ConvexDecomposition::double2
Definition: cd_hull.cpp:365
ConvexDecomposition::Pitch
double Pitch(const Quaternion &q)
Definition: cd_hull.cpp:1236
ConvexDecomposition::PlaneFlag::undermap
unsigned char undermap
Definition: cd_hull.cpp:1733
ConvexDecomposition::Quaternion
Definition: cd_hull.cpp:510
REAL
#define REAL
Definition: cd_hull.cpp:1640
ConvexDecomposition::int4::int4
int4()
Definition: cd_hull.cpp:2525
ConvexDecomposition::PlaneProject
double3 PlaneProject(const Plane &plane, const double3 &point)
Definition: cd_hull.cpp:1346
ConvexDecomposition::point
Definition: planetri.cpp:128
COPLANAR
#define COPLANAR
Definition: cd_hull.cpp:1642
ConvexDecomposition::sqr
double sqr(double a)
Definition: cd_hull.cpp:591
ConvexDecomposition::LineProjectTime
double LineProjectTime(const double3 &p0, const double3 &p1, const double3 &a)
Definition: cd_hull.cpp:1360
ConvexDecomposition::magnitude
double magnitude(const double3 &v)
Definition: cd_hull.cpp:724
ConvexDecomposition::Tri::n
int3 n
Definition: cd_hull.cpp:2401
ConvexDecomposition::int3::operator[]
int & operator[](int i)
Definition: cd_hull.cpp:359
ConvexDecomposition::Roll
double Roll(Quaternion q)
Definition: cd_hull.cpp:1243
ConvexDecomposition::above
int above(double3 *vertices, const int3 &t, const double3 &p, double epsilon)
Definition: cd_hull.cpp:2361
ConvexDecomposition::int4::operator[]
const int & operator[](int i) const
Definition: cd_hull.cpp:2527
ConvexDecomposition::ComputeHull
bool ComputeHull(unsigned int vcount, const double *vertices, PHullResult &result, unsigned int maxverts, double inflate)
Definition: cd_hull.cpp:2880
ConvexDecomposition::double2::operator[]
const double & operator[](int i) const
Definition: cd_hull.cpp:372
ConvexDecomposition::Tri::rise
double rise
Definition: cd_hull.cpp:2404
ConvexDecomposition::extrude
void extrude(Tri *t0, int v)
Definition: cd_hull.cpp:2472
ConvexDecomposition::hasVolume
bool hasVolume(double3 *verts, int p0, int p1, int p2, int p3)
Definition: cd_hull.cpp:2533
ConvexDecomposition::double3::x
double x
Definition: cd_hull.cpp:382
ConvexDecomposition::double3x3
Definition: cd_hull.cpp:423
ConvexDecomposition::operator*
double3 operator*(const double3 &v, const double s)
Definition: cd_hull.cpp:644
ConvexDecomposition::int4::z
int z
Definition: cd_hull.cpp:2524


convex_decomposition
Author(s): John W. Ratcliff
autogenerated on Wed Mar 2 2022 00:04:59