forked from LeenkxTeam/LNXSDK
		
	
		
			
	
	
		
			1168 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			1168 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								Stan Melax Convex Hull Computation
							 | 
						||
| 
								 | 
							
								Copyright (c) 2003-2006 Stan Melax http://www.melax.com/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								This software is provided 'as-is', without any express or implied warranty.
							 | 
						||
| 
								 | 
							
								In no event will the authors be held liable for any damages arising from the use of this software.
							 | 
						||
| 
								 | 
							
								Permission is granted to anyone to use this software for any purpose, 
							 | 
						||
| 
								 | 
							
								including commercial applications, and to alter it and redistribute it freely, 
							 | 
						||
| 
								 | 
							
								subject to the following restrictions:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
							 | 
						||
| 
								 | 
							
								2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
							 | 
						||
| 
								 | 
							
								3. This notice may not be removed or altered from any source distribution.
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <string.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "btConvexHull.h"
							 | 
						||
| 
								 | 
							
								#include "btAlignedObjectArray.h"
							 | 
						||
| 
								 | 
							
								#include "btMinMax.h"
							 | 
						||
| 
								 | 
							
								#include "btVector3.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//----------------------------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class int3  
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
									int x,y,z;
							 | 
						||
| 
								 | 
							
									int3(){};
							 | 
						||
| 
								 | 
							
									int3(int _x,int _y, int _z){x=_x;y=_y;z=_z;}
							 | 
						||
| 
								 | 
							
									const int& operator[](int i) const {return (&x)[i];}
							 | 
						||
| 
								 | 
							
									int& operator[](int i) {return (&x)[i];}
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//------- btPlane ----------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								inline btPlane PlaneFlip(const btPlane &plane){return btPlane(-plane.normal,-plane.dist);}
							 | 
						||
| 
								 | 
							
								inline int operator==( const btPlane &a, const btPlane &b ) { return (a.normal==b.normal && a.dist==b.dist); }
							 | 
						||
| 
								 | 
							
								inline int coplanar( const btPlane &a, const btPlane &b ) { return (a==b || a==PlaneFlip(b)); }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//--------- Utility Functions ------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								btVector3  PlaneLineIntersection(const btPlane &plane, const btVector3 &p0, const btVector3 &p1);
							 | 
						||
| 
								 | 
							
								btVector3  PlaneProject(const btPlane &plane, const btVector3 &point);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								btVector3  ThreePlaneIntersection(const btPlane &p0,const btPlane &p1, const btPlane &p2);
							 | 
						||
| 
								 | 
							
								btVector3  ThreePlaneIntersection(const btPlane &p0,const btPlane &p1, const btPlane &p2)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									btVector3 N1 = p0.normal;
							 | 
						||
| 
								 | 
							
									btVector3 N2 = p1.normal;
							 | 
						||
| 
								 | 
							
									btVector3 N3 = p2.normal;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									btVector3 n2n3; n2n3 = N2.cross(N3);
							 | 
						||
| 
								 | 
							
									btVector3 n3n1; n3n1 = N3.cross(N1);
							 | 
						||
| 
								 | 
							
									btVector3 n1n2; n1n2 = N1.cross(N2);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									btScalar quotient = (N1.dot(n2n3));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									btAssert(btFabs(quotient) > btScalar(0.000001));
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									quotient = btScalar(-1.) / quotient;
							 | 
						||
| 
								 | 
							
									n2n3 *= p0.dist;
							 | 
						||
| 
								 | 
							
									n3n1 *= p1.dist;
							 | 
						||
| 
								 | 
							
									n1n2 *= p2.dist;
							 | 
						||
| 
								 | 
							
									btVector3 potentialVertex = n2n3;
							 | 
						||
| 
								 | 
							
									potentialVertex += n3n1;
							 | 
						||
| 
								 | 
							
									potentialVertex += n1n2;
							 | 
						||
| 
								 | 
							
									potentialVertex *= quotient;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									btVector3 result(potentialVertex.getX(),potentialVertex.getY(),potentialVertex.getZ());
							 | 
						||
| 
								 | 
							
									return result;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								btScalar   DistanceBetweenLines(const btVector3 &ustart, const btVector3 &udir, const btVector3 &vstart, const btVector3 &vdir, btVector3 *upoint=NULL, btVector3 *vpoint=NULL);
							 | 
						||
| 
								 | 
							
								btVector3  TriNormal(const btVector3 &v0, const btVector3 &v1, const btVector3 &v2);
							 | 
						||
| 
								 | 
							
								btVector3  NormalOf(const btVector3 *vert, const int n);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								btVector3 PlaneLineIntersection(const btPlane &plane, const btVector3 &p0, const btVector3 &p1)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									// returns the point where the line p0-p1 intersects the plane n&d
							 | 
						||
| 
								 | 
							
								    btVector3 dif;
							 | 
						||
| 
								 | 
							
										dif = p1-p0;
							 | 
						||
| 
								 | 
							
												btScalar dn= btDot(plane.normal,dif);
							 | 
						||
| 
								 | 
							
												btScalar t = -(plane.dist+btDot(plane.normal,p0) )/dn;
							 | 
						||
| 
								 | 
							
												return p0 + (dif*t);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								btVector3 PlaneProject(const btPlane &plane, const btVector3 &point)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									return point - plane.normal * (btDot(point,plane.normal)+plane.dist);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								btVector3 TriNormal(const btVector3 &v0, const btVector3 &v1, const btVector3 &v2)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									// return the normal of the triangle
							 | 
						||
| 
								 | 
							
									// inscribed by v0, v1, and v2
							 | 
						||
| 
								 | 
							
									btVector3 cp=btCross(v1-v0,v2-v1);
							 | 
						||
| 
								 | 
							
									btScalar m=cp.length();
							 | 
						||
| 
								 | 
							
									if(m==0) return btVector3(1,0,0);
							 | 
						||
| 
								 | 
							
									return cp*(btScalar(1.0)/m);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								btScalar DistanceBetweenLines(const btVector3 &ustart, const btVector3 &udir, const btVector3 &vstart, const btVector3 &vdir, btVector3 *upoint, btVector3 *vpoint)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									btVector3 cp;
							 | 
						||
| 
								 | 
							
									cp = btCross(udir,vdir).normalized();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									btScalar distu = -btDot(cp,ustart);
							 | 
						||
| 
								 | 
							
									btScalar distv = -btDot(cp,vstart);
							 | 
						||
| 
								 | 
							
									btScalar dist = (btScalar)fabs(distu-distv);
							 | 
						||
| 
								 | 
							
									if(upoint) 
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
										btPlane plane;
							 | 
						||
| 
								 | 
							
										plane.normal = btCross(vdir,cp).normalized();
							 | 
						||
| 
								 | 
							
										plane.dist = -btDot(plane.normal,vstart);
							 | 
						||
| 
								 | 
							
										*upoint = PlaneLineIntersection(plane,ustart,ustart+udir);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									if(vpoint) 
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
										btPlane plane;
							 | 
						||
| 
								 | 
							
										plane.normal = btCross(udir,cp).normalized();
							 | 
						||
| 
								 | 
							
										plane.dist = -btDot(plane.normal,ustart);
							 | 
						||
| 
								 | 
							
										*vpoint = PlaneLineIntersection(plane,vstart,vstart+vdir);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									return dist;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define COPLANAR   (0)
							 | 
						||
| 
								 | 
							
								#define UNDER      (1)
							 | 
						||
| 
								 | 
							
								#define OVER       (2)
							 | 
						||
| 
								 | 
							
								#define SPLIT      (OVER|UNDER)
							 | 
						||
| 
								 | 
							
								#define PAPERWIDTH (btScalar(0.001))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								btScalar planetestepsilon = PAPERWIDTH;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								typedef ConvexH::HalfEdge HalfEdge;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								ConvexH::ConvexH(int vertices_size,int edges_size,int facets_size)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									vertices.resize(vertices_size);
							 | 
						||
| 
								 | 
							
									edges.resize(edges_size);
							 | 
						||
| 
								 | 
							
									facets.resize(facets_size);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int PlaneTest(const btPlane &p, const btVector3 &v);
							 | 
						||
| 
								 | 
							
								int PlaneTest(const btPlane &p, const btVector3 &v) {
							 | 
						||
| 
								 | 
							
									btScalar a  = btDot(v,p.normal)+p.dist;
							 | 
						||
| 
								 | 
							
									int   flag = (a>planetestepsilon)?OVER:((a<-planetestepsilon)?UNDER:COPLANAR);
							 | 
						||
| 
								 | 
							
									return flag;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int SplitTest(ConvexH &convex,const btPlane &plane);
							 | 
						||
| 
								 | 
							
								int SplitTest(ConvexH &convex,const btPlane &plane) {
							 | 
						||
| 
								 | 
							
									int flag=0;
							 | 
						||
| 
								 | 
							
									for(int i=0;i<convex.vertices.size();i++) {
							 | 
						||
| 
								 | 
							
										flag |= PlaneTest(plane,convex.vertices[i]);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									return flag;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class VertFlag
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
									unsigned char planetest;
							 | 
						||
| 
								 | 
							
									unsigned char junk;
							 | 
						||
| 
								 | 
							
									unsigned char undermap;
							 | 
						||
| 
								 | 
							
									unsigned char overmap;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								class EdgeFlag 
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
									unsigned char planetest;
							 | 
						||
| 
								 | 
							
									unsigned char fixes;
							 | 
						||
| 
								 | 
							
									short undermap;
							 | 
						||
| 
								 | 
							
									short overmap;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								class PlaneFlag
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
									unsigned char undermap;
							 | 
						||
| 
								 | 
							
									unsigned char overmap;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								class Coplanar{
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
									unsigned short ea;
							 | 
						||
| 
								 | 
							
									unsigned char v0;
							 | 
						||
| 
								 | 
							
									unsigned char v1;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template<class T>
							 | 
						||
| 
								 | 
							
								int maxdirfiltered(const T *p,int count,const T &dir,btAlignedObjectArray<int> &allow)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									btAssert(count);
							 | 
						||
| 
								 | 
							
									int m=-1;
							 | 
						||
| 
								 | 
							
									for(int i=0;i<count;i++) 
							 | 
						||
| 
								 | 
							
										if(allow[i])
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											if(m==-1 || btDot(p[i],dir)>btDot(p[m],dir))
							 | 
						||
| 
								 | 
							
												m=i;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									btAssert(m!=-1);
							 | 
						||
| 
								 | 
							
									return m;
							 | 
						||
| 
								 | 
							
								} 
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								btVector3 orth(const btVector3 &v);
							 | 
						||
| 
								 | 
							
								btVector3 orth(const btVector3 &v)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									btVector3 a=btCross(v,btVector3(0,0,1));
							 | 
						||
| 
								 | 
							
									btVector3 b=btCross(v,btVector3(0,1,0));
							 | 
						||
| 
								 | 
							
									if (a.length() > b.length())
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										return a.normalized();
							 | 
						||
| 
								 | 
							
									} else {
							 | 
						||
| 
								 | 
							
										return b.normalized();
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template<class T>
							 | 
						||
| 
								 | 
							
								int maxdirsterid(const T *p,int count,const T &dir,btAlignedObjectArray<int> &allow)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									int m=-1;
							 | 
						||
| 
								 | 
							
									while(m==-1)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										m = maxdirfiltered(p,count,dir,allow);
							 | 
						||
| 
								 | 
							
										if(allow[m]==3) return m;
							 | 
						||
| 
								 | 
							
										T u = orth(dir);
							 | 
						||
| 
								 | 
							
										T v = btCross(u,dir);
							 | 
						||
| 
								 | 
							
										int ma=-1;
							 | 
						||
| 
								 | 
							
										for(btScalar x = btScalar(0.0) ; x<= btScalar(360.0) ; x+= btScalar(45.0))
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											btScalar s = btSin(SIMD_RADS_PER_DEG*(x));
							 | 
						||
| 
								 | 
							
											btScalar c = btCos(SIMD_RADS_PER_DEG*(x));
							 | 
						||
| 
								 | 
							
											int mb = maxdirfiltered(p,count,dir+(u*s+v*c)*btScalar(0.025),allow);
							 | 
						||
| 
								 | 
							
											if(ma==m && mb==m)
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												allow[m]=3;
							 | 
						||
| 
								 | 
							
												return m;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											if(ma!=-1 && ma!=mb)  // Yuck - this is really ugly
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												int mc = ma;
							 | 
						||
| 
								 | 
							
												for(btScalar xx = x-btScalar(40.0) ; xx <= x ; xx+= btScalar(5.0))
							 | 
						||
| 
								 | 
							
												{
							 | 
						||
| 
								 | 
							
													btScalar s = btSin(SIMD_RADS_PER_DEG*(xx));
							 | 
						||
| 
								 | 
							
													btScalar c = btCos(SIMD_RADS_PER_DEG*(xx));
							 | 
						||
| 
								 | 
							
													int md = maxdirfiltered(p,count,dir+(u*s+v*c)*btScalar(0.025),allow);
							 | 
						||
| 
								 | 
							
													if(mc==m && md==m)
							 | 
						||
| 
								 | 
							
													{
							 | 
						||
| 
								 | 
							
														allow[m]=3;
							 | 
						||
| 
								 | 
							
														return m;
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
													mc=md;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											ma=mb;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										allow[m]=0;
							 | 
						||
| 
								 | 
							
										m=-1;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									btAssert(0);
							 | 
						||
| 
								 | 
							
									return m;
							 | 
						||
| 
								 | 
							
								} 
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int operator ==(const int3 &a,const int3 &b);
							 | 
						||
| 
								 | 
							
								int operator ==(const int3 &a,const int3 &b) 
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									for(int i=0;i<3;i++) 
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										if(a[i]!=b[i]) return 0;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									return 1;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int above(btVector3* vertices,const int3& t, const btVector3 &p, btScalar epsilon);
							 | 
						||
| 
								 | 
							
								int above(btVector3* vertices,const int3& t, const btVector3 &p, btScalar epsilon) 
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									btVector3 n=TriNormal(vertices[t[0]],vertices[t[1]],vertices[t[2]]);
							 | 
						||
| 
								 | 
							
									return (btDot(n,p-vertices[t[0]]) > epsilon); // EPSILON???
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								int hasedge(const int3 &t, int a,int b);
							 | 
						||
| 
								 | 
							
								int hasedge(const int3 &t, int a,int b)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									for(int i=0;i<3;i++)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										int i1= (i+1)%3;
							 | 
						||
| 
								 | 
							
										if(t[i]==a && t[i1]==b) return 1;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									return 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								int hasvert(const int3 &t, int v);
							 | 
						||
| 
								 | 
							
								int hasvert(const int3 &t, int v)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									return (t[0]==v || t[1]==v || t[2]==v) ;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								int shareedge(const int3 &a,const int3 &b);
							 | 
						||
| 
								 | 
							
								int shareedge(const int3 &a,const int3 &b)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									int i;
							 | 
						||
| 
								 | 
							
									for(i=0;i<3;i++)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										int i1= (i+1)%3;
							 | 
						||
| 
								 | 
							
										if(hasedge(a,b[i1],b[i])) return 1;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									return 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class btHullTriangle;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class btHullTriangle : public int3
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
									int3 n;
							 | 
						||
| 
								 | 
							
									int id;
							 | 
						||
| 
								 | 
							
									int vmax;
							 | 
						||
| 
								 | 
							
									btScalar rise;
							 | 
						||
| 
								 | 
							
									btHullTriangle(int a,int b,int c):int3(a,b,c),n(-1,-1,-1)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										vmax=-1;
							 | 
						||
| 
								 | 
							
										rise = btScalar(0.0);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									~btHullTriangle()
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									int &neib(int a,int b);
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int &btHullTriangle::neib(int a,int b)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									static int er=-1;
							 | 
						||
| 
								 | 
							
									int i;
							 | 
						||
| 
								 | 
							
									for(i=0;i<3;i++) 
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										int i1=(i+1)%3;
							 | 
						||
| 
								 | 
							
										int i2=(i+2)%3;
							 | 
						||
| 
								 | 
							
										if((*this)[i]==a && (*this)[i1]==b) return n[i2];
							 | 
						||
| 
								 | 
							
										if((*this)[i]==b && (*this)[i1]==a) return n[i2];
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									btAssert(0);
							 | 
						||
| 
								 | 
							
									return er;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								void HullLibrary::b2bfix(btHullTriangle* s,btHullTriangle*t)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									int i;
							 | 
						||
| 
								 | 
							
									for(i=0;i<3;i++) 
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										int i1=(i+1)%3;
							 | 
						||
| 
								 | 
							
										int i2=(i+2)%3;
							 | 
						||
| 
								 | 
							
										int a = (*s)[i1];
							 | 
						||
| 
								 | 
							
										int b = (*s)[i2];
							 | 
						||
| 
								 | 
							
										btAssert(m_tris[s->neib(a,b)]->neib(b,a) == s->id);
							 | 
						||
| 
								 | 
							
										btAssert(m_tris[t->neib(a,b)]->neib(b,a) == t->id);
							 | 
						||
| 
								 | 
							
										m_tris[s->neib(a,b)]->neib(b,a) = t->neib(b,a);
							 | 
						||
| 
								 | 
							
										m_tris[t->neib(b,a)]->neib(a,b) = s->neib(a,b);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void HullLibrary::removeb2b(btHullTriangle* s,btHullTriangle*t)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									b2bfix(s,t);
							 | 
						||
| 
								 | 
							
									deAllocateTriangle(s);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									deAllocateTriangle(t);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void HullLibrary::checkit(btHullTriangle *t)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									(void)t;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									int i;
							 | 
						||
| 
								 | 
							
									btAssert(m_tris[t->id]==t);
							 | 
						||
| 
								 | 
							
									for(i=0;i<3;i++)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										int i1=(i+1)%3;
							 | 
						||
| 
								 | 
							
										int i2=(i+2)%3;
							 | 
						||
| 
								 | 
							
										int a = (*t)[i1];
							 | 
						||
| 
								 | 
							
										int b = (*t)[i2];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// release compile fix
							 | 
						||
| 
								 | 
							
										(void)i1;
							 | 
						||
| 
								 | 
							
										(void)i2;
							 | 
						||
| 
								 | 
							
										(void)a;
							 | 
						||
| 
								 | 
							
										(void)b;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										btAssert(a!=b);
							 | 
						||
| 
								 | 
							
										btAssert( m_tris[t->n[i]]->neib(b,a) == t->id);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								btHullTriangle*	HullLibrary::allocateTriangle(int a,int b,int c)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									void* mem = btAlignedAlloc(sizeof(btHullTriangle),16);
							 | 
						||
| 
								 | 
							
									btHullTriangle* tr = new (mem)btHullTriangle(a,b,c);
							 | 
						||
| 
								 | 
							
									tr->id = m_tris.size();
							 | 
						||
| 
								 | 
							
									m_tris.push_back(tr);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return tr;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void	HullLibrary::deAllocateTriangle(btHullTriangle* tri)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									btAssert(m_tris[tri->id]==tri);
							 | 
						||
| 
								 | 
							
									m_tris[tri->id]=NULL;
							 | 
						||
| 
								 | 
							
									tri->~btHullTriangle();
							 | 
						||
| 
								 | 
							
									btAlignedFree(tri);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void HullLibrary::extrude(btHullTriangle *t0,int v)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									int3 t= *t0;
							 | 
						||
| 
								 | 
							
									int n = m_tris.size();
							 | 
						||
| 
								 | 
							
									btHullTriangle* ta = allocateTriangle(v,t[1],t[2]);
							 | 
						||
| 
								 | 
							
									ta->n = int3(t0->n[0],n+1,n+2);
							 | 
						||
| 
								 | 
							
									m_tris[t0->n[0]]->neib(t[1],t[2]) = n+0;
							 | 
						||
| 
								 | 
							
									btHullTriangle* tb = allocateTriangle(v,t[2],t[0]);
							 | 
						||
| 
								 | 
							
									tb->n = int3(t0->n[1],n+2,n+0);
							 | 
						||
| 
								 | 
							
									m_tris[t0->n[1]]->neib(t[2],t[0]) = n+1;
							 | 
						||
| 
								 | 
							
									btHullTriangle* tc = allocateTriangle(v,t[0],t[1]);
							 | 
						||
| 
								 | 
							
									tc->n = int3(t0->n[2],n+0,n+1);
							 | 
						||
| 
								 | 
							
									m_tris[t0->n[2]]->neib(t[0],t[1]) = n+2;
							 | 
						||
| 
								 | 
							
									checkit(ta);
							 | 
						||
| 
								 | 
							
									checkit(tb);
							 | 
						||
| 
								 | 
							
									checkit(tc);
							 | 
						||
| 
								 | 
							
									if(hasvert(*m_tris[ta->n[0]],v)) removeb2b(ta,m_tris[ta->n[0]]);
							 | 
						||
| 
								 | 
							
									if(hasvert(*m_tris[tb->n[0]],v)) removeb2b(tb,m_tris[tb->n[0]]);
							 | 
						||
| 
								 | 
							
									if(hasvert(*m_tris[tc->n[0]],v)) removeb2b(tc,m_tris[tc->n[0]]);
							 | 
						||
| 
								 | 
							
									deAllocateTriangle(t0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								btHullTriangle* HullLibrary::extrudable(btScalar epsilon)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									int i;
							 | 
						||
| 
								 | 
							
									btHullTriangle *t=NULL;
							 | 
						||
| 
								 | 
							
									for(i=0;i<m_tris.size();i++)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										if(!t || (m_tris[i] && t->rise<m_tris[i]->rise))
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											t = m_tris[i];
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									return (t->rise >epsilon)?t:NULL ;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int4 HullLibrary::FindSimplex(btVector3 *verts,int verts_count,btAlignedObjectArray<int> &allow)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									btVector3 basis[3];
							 | 
						||
| 
								 | 
							
									basis[0] = btVector3( btScalar(0.01), btScalar(0.02), btScalar(1.0) );      
							 | 
						||
| 
								 | 
							
									int p0 = maxdirsterid(verts,verts_count, basis[0],allow);   
							 | 
						||
| 
								 | 
							
									int	p1 = maxdirsterid(verts,verts_count,-basis[0],allow);
							 | 
						||
| 
								 | 
							
									basis[0] = verts[p0]-verts[p1];
							 | 
						||
| 
								 | 
							
									if(p0==p1 || basis[0]==btVector3(0,0,0)) 
							 | 
						||
| 
								 | 
							
										return int4(-1,-1,-1,-1);
							 | 
						||
| 
								 | 
							
									basis[1] = btCross(btVector3(     btScalar(1),btScalar(0.02), btScalar(0)),basis[0]);
							 | 
						||
| 
								 | 
							
									basis[2] = btCross(btVector3(btScalar(-0.02),     btScalar(1), btScalar(0)),basis[0]);
							 | 
						||
| 
								 | 
							
									if (basis[1].length() > basis[2].length())
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										basis[1].normalize();
							 | 
						||
| 
								 | 
							
									} else {
							 | 
						||
| 
								 | 
							
										basis[1] = basis[2];
							 | 
						||
| 
								 | 
							
										basis[1].normalize ();
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									int p2 = maxdirsterid(verts,verts_count,basis[1],allow);
							 | 
						||
| 
								 | 
							
									if(p2 == p0 || p2 == p1)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										p2 = maxdirsterid(verts,verts_count,-basis[1],allow);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									if(p2 == p0 || p2 == p1) 
							 | 
						||
| 
								 | 
							
										return int4(-1,-1,-1,-1);
							 | 
						||
| 
								 | 
							
									basis[1] = verts[p2] - verts[p0];
							 | 
						||
| 
								 | 
							
									basis[2] = btCross(basis[1],basis[0]).normalized();
							 | 
						||
| 
								 | 
							
									int p3 = maxdirsterid(verts,verts_count,basis[2],allow);
							 | 
						||
| 
								 | 
							
									if(p3==p0||p3==p1||p3==p2) p3 = maxdirsterid(verts,verts_count,-basis[2],allow);
							 | 
						||
| 
								 | 
							
									if(p3==p0||p3==p1||p3==p2) 
							 | 
						||
| 
								 | 
							
										return int4(-1,-1,-1,-1);
							 | 
						||
| 
								 | 
							
									btAssert(!(p0==p1||p0==p2||p0==p3||p1==p2||p1==p3||p2==p3));
							 | 
						||
| 
								 | 
							
									if(btDot(verts[p3]-verts[p0],btCross(verts[p1]-verts[p0],verts[p2]-verts[p0])) <0) {btSwap(p2,p3);}
							 | 
						||
| 
								 | 
							
									return int4(p0,p1,p2,p3);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int HullLibrary::calchullgen(btVector3 *verts,int verts_count, int vlimit)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									if(verts_count <4) return 0;
							 | 
						||
| 
								 | 
							
									if(vlimit==0) vlimit=1000000000;
							 | 
						||
| 
								 | 
							
									int j;
							 | 
						||
| 
								 | 
							
									btVector3 bmin(*verts),bmax(*verts);
							 | 
						||
| 
								 | 
							
									btAlignedObjectArray<int> isextreme;
							 | 
						||
| 
								 | 
							
									isextreme.reserve(verts_count);
							 | 
						||
| 
								 | 
							
									btAlignedObjectArray<int> allow;
							 | 
						||
| 
								 | 
							
									allow.reserve(verts_count);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									for(j=0;j<verts_count;j++) 
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										allow.push_back(1);
							 | 
						||
| 
								 | 
							
										isextreme.push_back(0);
							 | 
						||
| 
								 | 
							
										bmin.setMin (verts[j]);
							 | 
						||
| 
								 | 
							
										bmax.setMax (verts[j]);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									btScalar epsilon = (bmax-bmin).length() * btScalar(0.001);
							 | 
						||
| 
								 | 
							
									btAssert (epsilon != 0.0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									int4 p = FindSimplex(verts,verts_count,allow);
							 | 
						||
| 
								 | 
							
									if(p.x==-1) return 0; // simplex failed
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									btVector3 center = (verts[p[0]]+verts[p[1]]+verts[p[2]]+verts[p[3]]) / btScalar(4.0);  // a valid interior point
							 | 
						||
| 
								 | 
							
									btHullTriangle *t0 = allocateTriangle(p[2],p[3],p[1]); t0->n=int3(2,3,1);
							 | 
						||
| 
								 | 
							
									btHullTriangle *t1 = allocateTriangle(p[3],p[2],p[0]); t1->n=int3(3,2,0);
							 | 
						||
| 
								 | 
							
									btHullTriangle *t2 = allocateTriangle(p[0],p[1],p[3]); t2->n=int3(0,1,3);
							 | 
						||
| 
								 | 
							
									btHullTriangle *t3 = allocateTriangle(p[1],p[0],p[2]); t3->n=int3(1,0,2);
							 | 
						||
| 
								 | 
							
									isextreme[p[0]]=isextreme[p[1]]=isextreme[p[2]]=isextreme[p[3]]=1;
							 | 
						||
| 
								 | 
							
									checkit(t0);checkit(t1);checkit(t2);checkit(t3);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									for(j=0;j<m_tris.size();j++)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										btHullTriangle *t=m_tris[j];
							 | 
						||
| 
								 | 
							
										btAssert(t);
							 | 
						||
| 
								 | 
							
										btAssert(t->vmax<0);
							 | 
						||
| 
								 | 
							
										btVector3 n=TriNormal(verts[(*t)[0]],verts[(*t)[1]],verts[(*t)[2]]);
							 | 
						||
| 
								 | 
							
										t->vmax = maxdirsterid(verts,verts_count,n,allow);
							 | 
						||
| 
								 | 
							
										t->rise = btDot(n,verts[t->vmax]-verts[(*t)[0]]);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									btHullTriangle *te;
							 | 
						||
| 
								 | 
							
									vlimit-=4;
							 | 
						||
| 
								 | 
							
									while(vlimit >0 && ((te=extrudable(epsilon)) != 0))
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										//int3 ti=*te;
							 | 
						||
| 
								 | 
							
										int v=te->vmax;
							 | 
						||
| 
								 | 
							
										btAssert(v != -1);
							 | 
						||
| 
								 | 
							
										btAssert(!isextreme[v]);  // wtf we've already done this vertex
							 | 
						||
| 
								 | 
							
										isextreme[v]=1;
							 | 
						||
| 
								 | 
							
										//if(v==p0 || v==p1 || v==p2 || v==p3) continue; // done these already
							 | 
						||
| 
								 | 
							
										j=m_tris.size();
							 | 
						||
| 
								 | 
							
										while(j--) {
							 | 
						||
| 
								 | 
							
											if(!m_tris[j]) continue;
							 | 
						||
| 
								 | 
							
											int3 t=*m_tris[j];
							 | 
						||
| 
								 | 
							
											if(above(verts,t,verts[v],btScalar(0.01)*epsilon)) 
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												extrude(m_tris[j],v);
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										// now check for those degenerate cases where we have a flipped triangle or a really skinny triangle
							 | 
						||
| 
								 | 
							
										j=m_tris.size();
							 | 
						||
| 
								 | 
							
										while(j--)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											if(!m_tris[j]) continue;
							 | 
						||
| 
								 | 
							
											if(!hasvert(*m_tris[j],v)) break;
							 | 
						||
| 
								 | 
							
											int3 nt=*m_tris[j];
							 | 
						||
| 
								 | 
							
											if(above(verts,nt,center,btScalar(0.01)*epsilon)  || btCross(verts[nt[1]]-verts[nt[0]],verts[nt[2]]-verts[nt[1]]).length()< epsilon*epsilon*btScalar(0.1) )
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												btHullTriangle *nb = m_tris[m_tris[j]->n[0]];
							 | 
						||
| 
								 | 
							
												btAssert(nb);btAssert(!hasvert(*nb,v));btAssert(nb->id<j);
							 | 
						||
| 
								 | 
							
												extrude(nb,v);
							 | 
						||
| 
								 | 
							
												j=m_tris.size(); 
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										} 
							 | 
						||
| 
								 | 
							
										j=m_tris.size();
							 | 
						||
| 
								 | 
							
										while(j--)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											btHullTriangle *t=m_tris[j];
							 | 
						||
| 
								 | 
							
											if(!t) continue;
							 | 
						||
| 
								 | 
							
											if(t->vmax>=0) break;
							 | 
						||
| 
								 | 
							
											btVector3 n=TriNormal(verts[(*t)[0]],verts[(*t)[1]],verts[(*t)[2]]);
							 | 
						||
| 
								 | 
							
											t->vmax = maxdirsterid(verts,verts_count,n,allow);
							 | 
						||
| 
								 | 
							
											if(isextreme[t->vmax]) 
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												t->vmax=-1; // already done that vertex - algorithm needs to be able to terminate.
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											else
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												t->rise = btDot(n,verts[t->vmax]-verts[(*t)[0]]);
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										vlimit --;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									return 1;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int HullLibrary::calchull(btVector3 *verts,int verts_count, TUIntArray& tris_out, int &tris_count,int vlimit) 
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									int rc=calchullgen(verts,verts_count,  vlimit) ;
							 | 
						||
| 
								 | 
							
									if(!rc) return 0;
							 | 
						||
| 
								 | 
							
									btAlignedObjectArray<int> ts;
							 | 
						||
| 
								 | 
							
									int i;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									for(i=0;i<m_tris.size();i++)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										if(m_tris[i])
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											for(int j=0;j<3;j++)
							 | 
						||
| 
								 | 
							
												ts.push_back((*m_tris[i])[j]);
							 | 
						||
| 
								 | 
							
											deAllocateTriangle(m_tris[i]);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									tris_count = ts.size()/3;
							 | 
						||
| 
								 | 
							
									tris_out.resize(ts.size());
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									for (i=0;i<ts.size();i++)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										tris_out[i] = static_cast<unsigned int>(ts[i]);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									m_tris.resize(0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return 1;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								bool HullLibrary::ComputeHull(unsigned int vcount,const btVector3 *vertices,PHullResult &result,unsigned int vlimit)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									int    tris_count;
							 | 
						||
| 
								 | 
							
									int ret = calchull( (btVector3 *) vertices, (int) vcount, result.m_Indices, tris_count, static_cast<int>(vlimit) );
							 | 
						||
| 
								 | 
							
									if(!ret) return false;
							 | 
						||
| 
								 | 
							
									result.mIndexCount = (unsigned int) (tris_count*3);
							 | 
						||
| 
								 | 
							
									result.mFaceCount  = (unsigned int) tris_count;
							 | 
						||
| 
								 | 
							
									result.mVertices   = (btVector3*) vertices;
							 | 
						||
| 
								 | 
							
									result.mVcount     = (unsigned int) vcount;
							 | 
						||
| 
								 | 
							
									return true;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void ReleaseHull(PHullResult &result);
							 | 
						||
| 
								 | 
							
								void ReleaseHull(PHullResult &result)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									if ( result.m_Indices.size() )
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										result.m_Indices.clear();
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									result.mVcount = 0;
							 | 
						||
| 
								 | 
							
									result.mIndexCount = 0;
							 | 
						||
| 
								 | 
							
									result.mVertices = 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//*********************************************************************
							 | 
						||
| 
								 | 
							
								//*********************************************************************
							 | 
						||
| 
								 | 
							
								//********  HullLib header
							 | 
						||
| 
								 | 
							
								//*********************************************************************
							 | 
						||
| 
								 | 
							
								//*********************************************************************
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//*********************************************************************
							 | 
						||
| 
								 | 
							
								//*********************************************************************
							 | 
						||
| 
								 | 
							
								//********  HullLib implementation
							 | 
						||
| 
								 | 
							
								//*********************************************************************
							 | 
						||
| 
								 | 
							
								//*********************************************************************
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								HullError HullLibrary::CreateConvexHull(const HullDesc       &desc,           // describes the input request
							 | 
						||
| 
								 | 
							
																													HullResult           &result)         // contains the resulst
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									HullError ret = QE_FAIL;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									PHullResult hr;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									unsigned int vcount = desc.mVcount;
							 | 
						||
| 
								 | 
							
									if ( vcount < 8 ) vcount = 8;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									btAlignedObjectArray<btVector3> vertexSource;
							 | 
						||
| 
								 | 
							
									vertexSource.resize(static_cast<int>(vcount));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									btVector3 scale;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									unsigned int ovcount;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									bool ok = CleanupVertices(desc.mVcount,desc.mVertices, desc.mVertexStride, ovcount, &vertexSource[0], desc.mNormalEpsilon, scale ); // normalize point cloud, remove duplicates!
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if ( ok )
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//		if ( 1 ) // scale vertices back to their original size.
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											for (unsigned int i=0; i<ovcount; i++)
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												btVector3& v = vertexSource[static_cast<int>(i)];
							 | 
						||
| 
								 | 
							
												v[0]*=scale[0];
							 | 
						||
| 
								 | 
							
												v[1]*=scale[1];
							 | 
						||
| 
								 | 
							
												v[2]*=scale[2];
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										ok = ComputeHull(ovcount,&vertexSource[0],hr,desc.mMaxVertices);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if ( ok )
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											// re-index triangle mesh so it refers to only used vertices, rebuild a new vertex table.
							 | 
						||
| 
								 | 
							
											btAlignedObjectArray<btVector3>	vertexScratch;
							 | 
						||
| 
								 | 
							
											vertexScratch.resize(static_cast<int>(hr.mVcount));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											BringOutYourDead(hr.mVertices,hr.mVcount, &vertexScratch[0], ovcount, &hr.m_Indices[0], hr.mIndexCount );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											ret = QE_OK;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if ( desc.HasHullFlag(QF_TRIANGLES) ) // if he wants the results as triangle!
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												result.mPolygons          = false;
							 | 
						||
| 
								 | 
							
												result.mNumOutputVertices = ovcount;
							 | 
						||
| 
								 | 
							
												result.m_OutputVertices.resize(static_cast<int>(ovcount));
							 | 
						||
| 
								 | 
							
												result.mNumFaces          = hr.mFaceCount;
							 | 
						||
| 
								 | 
							
												result.mNumIndices        = hr.mIndexCount;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												result.m_Indices.resize(static_cast<int>(hr.mIndexCount));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												memcpy(&result.m_OutputVertices[0], &vertexScratch[0], sizeof(btVector3)*ovcount );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  			if ( desc.HasHullFlag(QF_REVERSE_ORDER) )
							 | 
						||
| 
								 | 
							
												{
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													const unsigned int *source = &hr.m_Indices[0];
							 | 
						||
| 
								 | 
							
													unsigned int *dest   = &result.m_Indices[0];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													for (unsigned int i=0; i<hr.mFaceCount; i++)
							 | 
						||
| 
								 | 
							
													{
							 | 
						||
| 
								 | 
							
														dest[0] = source[2];
							 | 
						||
| 
								 | 
							
														dest[1] = source[1];
							 | 
						||
| 
								 | 
							
														dest[2] = source[0];
							 | 
						||
| 
								 | 
							
														dest+=3;
							 | 
						||
| 
								 | 
							
														source+=3;
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												else
							 | 
						||
| 
								 | 
							
												{
							 | 
						||
| 
								 | 
							
													memcpy(&result.m_Indices[0], &hr.m_Indices[0], sizeof(unsigned int)*hr.mIndexCount);
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											else
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												result.mPolygons          = true;
							 | 
						||
| 
								 | 
							
												result.mNumOutputVertices = ovcount;
							 | 
						||
| 
								 | 
							
												result.m_OutputVertices.resize(static_cast<int>(ovcount));
							 | 
						||
| 
								 | 
							
												result.mNumFaces          = hr.mFaceCount;
							 | 
						||
| 
								 | 
							
												result.mNumIndices        = hr.mIndexCount+hr.mFaceCount;
							 | 
						||
| 
								 | 
							
												result.m_Indices.resize(static_cast<int>(result.mNumIndices));
							 | 
						||
| 
								 | 
							
												memcpy(&result.m_OutputVertices[0], &vertexScratch[0], sizeof(btVector3)*ovcount );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//				if ( 1 )
							 | 
						||
| 
								 | 
							
												{
							 | 
						||
| 
								 | 
							
													const unsigned int *source = &hr.m_Indices[0];
							 | 
						||
| 
								 | 
							
													unsigned int *dest   = &result.m_Indices[0];
							 | 
						||
| 
								 | 
							
													for (unsigned int i=0; i<hr.mFaceCount; i++)
							 | 
						||
| 
								 | 
							
													{
							 | 
						||
| 
								 | 
							
														dest[0] = 3;
							 | 
						||
| 
								 | 
							
														if ( desc.HasHullFlag(QF_REVERSE_ORDER) )
							 | 
						||
| 
								 | 
							
														{
							 | 
						||
| 
								 | 
							
															dest[1] = source[2];
							 | 
						||
| 
								 | 
							
															dest[2] = source[1];
							 | 
						||
| 
								 | 
							
															dest[3] = source[0];
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
														else
							 | 
						||
| 
								 | 
							
														{
							 | 
						||
| 
								 | 
							
															dest[1] = source[0];
							 | 
						||
| 
								 | 
							
															dest[2] = source[1];
							 | 
						||
| 
								 | 
							
															dest[3] = source[2];
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														dest+=4;
							 | 
						||
| 
								 | 
							
														source+=3;
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											ReleaseHull(hr);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return ret;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								HullError HullLibrary::ReleaseResult(HullResult &result) // release memory allocated for this result, we are done with it.
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									if ( result.m_OutputVertices.size())
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										result.mNumOutputVertices=0;
							 | 
						||
| 
								 | 
							
										result.m_OutputVertices.clear();
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									if ( result.m_Indices.size() )
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										result.mNumIndices=0;
							 | 
						||
| 
								 | 
							
										result.m_Indices.clear();
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									return QE_OK;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void addPoint(unsigned int &vcount,btVector3 *p,btScalar x,btScalar y,btScalar z)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									// XXX, might be broken
							 | 
						||
| 
								 | 
							
									btVector3& dest = p[vcount];
							 | 
						||
| 
								 | 
							
									dest[0] = x;
							 | 
						||
| 
								 | 
							
									dest[1] = y;
							 | 
						||
| 
								 | 
							
									dest[2] = z;
							 | 
						||
| 
								 | 
							
									vcount++;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								btScalar GetDist(btScalar px,btScalar py,btScalar pz,const btScalar *p2);
							 | 
						||
| 
								 | 
							
								btScalar GetDist(btScalar px,btScalar py,btScalar pz,const btScalar *p2)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									btScalar dx = px - p2[0];
							 | 
						||
| 
								 | 
							
									btScalar dy = py - p2[1];
							 | 
						||
| 
								 | 
							
									btScalar dz = pz - p2[2];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return dx*dx+dy*dy+dz*dz;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								bool  HullLibrary::CleanupVertices(unsigned int svcount,
							 | 
						||
| 
								 | 
							
												   const btVector3 *svertices,
							 | 
						||
| 
								 | 
							
												   unsigned int stride,
							 | 
						||
| 
								 | 
							
												   unsigned int &vcount,       // output number of vertices
							 | 
						||
| 
								 | 
							
												   btVector3 *vertices,                 // location to store the results.
							 | 
						||
| 
								 | 
							
												   btScalar  normalepsilon,
							 | 
						||
| 
								 | 
							
												   btVector3& scale)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									if ( svcount == 0 ) return false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									m_vertexIndexMapping.resize(0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define EPSILON btScalar(0.000001) /* close enough to consider two btScalaring point numbers to be 'the same'. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									vcount = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									btScalar recip[3]={0.f,0.f,0.f};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if ( scale )
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										scale[0] = 1;
							 | 
						||
| 
								 | 
							
										scale[1] = 1;
							 | 
						||
| 
								 | 
							
										scale[2] = 1;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									btScalar bmin[3] = {  FLT_MAX,  FLT_MAX,  FLT_MAX };
							 | 
						||
| 
								 | 
							
									btScalar bmax[3] = { -FLT_MAX, -FLT_MAX, -FLT_MAX };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									const char *vtx = (const char *) svertices;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//	if ( 1 )
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										for (unsigned int i=0; i<svcount; i++)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											const btScalar *p = (const btScalar *) vtx;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											vtx+=stride;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											for (int j=0; j<3; j++)
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												if ( p[j] < bmin[j] ) bmin[j] = p[j];
							 | 
						||
| 
								 | 
							
												if ( p[j] > bmax[j] ) bmax[j] = p[j];
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									btScalar dx = bmax[0] - bmin[0];
							 | 
						||
| 
								 | 
							
									btScalar dy = bmax[1] - bmin[1];
							 | 
						||
| 
								 | 
							
									btScalar dz = bmax[2] - bmin[2];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									btVector3 center;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									center[0] = dx*btScalar(0.5) + bmin[0];
							 | 
						||
| 
								 | 
							
									center[1] = dy*btScalar(0.5) + bmin[1];
							 | 
						||
| 
								 | 
							
									center[2] = dz*btScalar(0.5) + bmin[2];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if ( dx < EPSILON || dy < EPSILON || dz < EPSILON || svcount < 3 )
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										btScalar len = FLT_MAX;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if ( dx > EPSILON && dx < len ) len = dx;
							 | 
						||
| 
								 | 
							
										if ( dy > EPSILON && dy < len ) len = dy;
							 | 
						||
| 
								 | 
							
										if ( dz > EPSILON && dz < len ) len = dz;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if ( len == FLT_MAX )
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											dx = dy = dz = btScalar(0.01); // one centimeter
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										else
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											if ( dx < EPSILON ) dx = len * btScalar(0.05); // 1/5th the shortest non-zero edge.
							 | 
						||
| 
								 | 
							
											if ( dy < EPSILON ) dy = len * btScalar(0.05);
							 | 
						||
| 
								 | 
							
											if ( dz < EPSILON ) dz = len * btScalar(0.05);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										btScalar x1 = center[0] - dx;
							 | 
						||
| 
								 | 
							
										btScalar x2 = center[0] + dx;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										btScalar y1 = center[1] - dy;
							 | 
						||
| 
								 | 
							
										btScalar y2 = center[1] + dy;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										btScalar z1 = center[2] - dz;
							 | 
						||
| 
								 | 
							
										btScalar z2 = center[2] + dz;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										addPoint(vcount,vertices,x1,y1,z1);
							 | 
						||
| 
								 | 
							
										addPoint(vcount,vertices,x2,y1,z1);
							 | 
						||
| 
								 | 
							
										addPoint(vcount,vertices,x2,y2,z1);
							 | 
						||
| 
								 | 
							
										addPoint(vcount,vertices,x1,y2,z1);
							 | 
						||
| 
								 | 
							
										addPoint(vcount,vertices,x1,y1,z2);
							 | 
						||
| 
								 | 
							
										addPoint(vcount,vertices,x2,y1,z2);
							 | 
						||
| 
								 | 
							
										addPoint(vcount,vertices,x2,y2,z2);
							 | 
						||
| 
								 | 
							
										addPoint(vcount,vertices,x1,y2,z2);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return true; // return cube
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									else
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										if ( scale )
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											scale[0] = dx;
							 | 
						||
| 
								 | 
							
											scale[1] = dy;
							 | 
						||
| 
								 | 
							
											scale[2] = dz;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											recip[0] = 1 / dx;
							 | 
						||
| 
								 | 
							
											recip[1] = 1 / dy;
							 | 
						||
| 
								 | 
							
											recip[2] = 1 / dz;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											center[0]*=recip[0];
							 | 
						||
| 
								 | 
							
											center[1]*=recip[1];
							 | 
						||
| 
								 | 
							
											center[2]*=recip[2];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									vtx = (const char *) svertices;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									for (unsigned int i=0; i<svcount; i++)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										const btVector3 *p = (const btVector3 *)vtx;
							 | 
						||
| 
								 | 
							
										vtx+=stride;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										btScalar px = p->getX();
							 | 
						||
| 
								 | 
							
										btScalar py = p->getY();
							 | 
						||
| 
								 | 
							
										btScalar pz = p->getZ();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if ( scale )
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											px = px*recip[0]; // normalize
							 | 
						||
| 
								 | 
							
											py = py*recip[1]; // normalize
							 | 
						||
| 
								 | 
							
											pz = pz*recip[2]; // normalize
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//		if ( 1 )
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											unsigned int j;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											for (j=0; j<vcount; j++)
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												/// XXX might be broken
							 | 
						||
| 
								 | 
							
												btVector3& v = vertices[j];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												btScalar x = v[0];
							 | 
						||
| 
								 | 
							
												btScalar y = v[1];
							 | 
						||
| 
								 | 
							
												btScalar z = v[2];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												btScalar dx = btFabs(x - px );
							 | 
						||
| 
								 | 
							
												btScalar dy = btFabs(y - py );
							 | 
						||
| 
								 | 
							
												btScalar dz = btFabs(z - pz );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												if ( dx < normalepsilon && dy < normalepsilon && dz < normalepsilon )
							 | 
						||
| 
								 | 
							
												{
							 | 
						||
| 
								 | 
							
													// ok, it is close enough to the old one
							 | 
						||
| 
								 | 
							
													// now let us see if it is further from the center of the point cloud than the one we already recorded.
							 | 
						||
| 
								 | 
							
													// in which case we keep this one instead.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													btScalar dist1 = GetDist(px,py,pz,center);
							 | 
						||
| 
								 | 
							
													btScalar dist2 = GetDist(v[0],v[1],v[2],center);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													if ( dist1 > dist2 )
							 | 
						||
| 
								 | 
							
													{
							 | 
						||
| 
								 | 
							
														v[0] = px;
							 | 
						||
| 
								 | 
							
														v[1] = py;
							 | 
						||
| 
								 | 
							
														v[2] = pz;
							 | 
						||
| 
								 | 
							
														
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													break;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if ( j == vcount )
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												btVector3& dest = vertices[vcount];
							 | 
						||
| 
								 | 
							
												dest[0] = px;
							 | 
						||
| 
								 | 
							
												dest[1] = py;
							 | 
						||
| 
								 | 
							
												dest[2] = pz;
							 | 
						||
| 
								 | 
							
												vcount++;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											m_vertexIndexMapping.push_back(j);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// ok..now make sure we didn't prune so many vertices it is now invalid.
							 | 
						||
| 
								 | 
							
								//	if ( 1 )
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										btScalar bmin[3] = {  FLT_MAX,  FLT_MAX,  FLT_MAX };
							 | 
						||
| 
								 | 
							
										btScalar bmax[3] = { -FLT_MAX, -FLT_MAX, -FLT_MAX };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										for (unsigned int i=0; i<vcount; i++)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											const btVector3& p = vertices[i];
							 | 
						||
| 
								 | 
							
											for (int j=0; j<3; j++)
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												if ( p[j] < bmin[j] ) bmin[j] = p[j];
							 | 
						||
| 
								 | 
							
												if ( p[j] > bmax[j] ) bmax[j] = p[j];
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										btScalar dx = bmax[0] - bmin[0];
							 | 
						||
| 
								 | 
							
										btScalar dy = bmax[1] - bmin[1];
							 | 
						||
| 
								 | 
							
										btScalar dz = bmax[2] - bmin[2];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if ( dx < EPSILON || dy < EPSILON || dz < EPSILON || vcount < 3)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											btScalar cx = dx*btScalar(0.5) + bmin[0];
							 | 
						||
| 
								 | 
							
											btScalar cy = dy*btScalar(0.5) + bmin[1];
							 | 
						||
| 
								 | 
							
											btScalar cz = dz*btScalar(0.5) + bmin[2];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											btScalar len = FLT_MAX;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if ( dx >= EPSILON && dx < len ) len = dx;
							 | 
						||
| 
								 | 
							
											if ( dy >= EPSILON && dy < len ) len = dy;
							 | 
						||
| 
								 | 
							
											if ( dz >= EPSILON && dz < len ) len = dz;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if ( len == FLT_MAX )
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												dx = dy = dz = btScalar(0.01); // one centimeter
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											else
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												if ( dx < EPSILON ) dx = len * btScalar(0.05); // 1/5th the shortest non-zero edge.
							 | 
						||
| 
								 | 
							
												if ( dy < EPSILON ) dy = len * btScalar(0.05);
							 | 
						||
| 
								 | 
							
												if ( dz < EPSILON ) dz = len * btScalar(0.05);
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											btScalar x1 = cx - dx;
							 | 
						||
| 
								 | 
							
											btScalar x2 = cx + dx;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											btScalar y1 = cy - dy;
							 | 
						||
| 
								 | 
							
											btScalar y2 = cy + dy;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											btScalar z1 = cz - dz;
							 | 
						||
| 
								 | 
							
											btScalar z2 = cz + dz;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											vcount = 0; // add box
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											addPoint(vcount,vertices,x1,y1,z1);
							 | 
						||
| 
								 | 
							
											addPoint(vcount,vertices,x2,y1,z1);
							 | 
						||
| 
								 | 
							
											addPoint(vcount,vertices,x2,y2,z1);
							 | 
						||
| 
								 | 
							
											addPoint(vcount,vertices,x1,y2,z1);
							 | 
						||
| 
								 | 
							
											addPoint(vcount,vertices,x1,y1,z2);
							 | 
						||
| 
								 | 
							
											addPoint(vcount,vertices,x2,y1,z2);
							 | 
						||
| 
								 | 
							
											addPoint(vcount,vertices,x2,y2,z2);
							 | 
						||
| 
								 | 
							
											addPoint(vcount,vertices,x1,y2,z2);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											return true;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return true;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void HullLibrary::BringOutYourDead(const btVector3* verts,unsigned int vcount, btVector3* overts,unsigned int &ocount,unsigned int *indices,unsigned indexcount)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									btAlignedObjectArray<int>tmpIndices;
							 | 
						||
| 
								 | 
							
									tmpIndices.resize(m_vertexIndexMapping.size());
							 | 
						||
| 
								 | 
							
									int i;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									for (i=0;i<m_vertexIndexMapping.size();i++)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										tmpIndices[i] = m_vertexIndexMapping[i];
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									TUIntArray usedIndices;
							 | 
						||
| 
								 | 
							
									usedIndices.resize(static_cast<int>(vcount));
							 | 
						||
| 
								 | 
							
									memset(&usedIndices[0],0,sizeof(unsigned int)*vcount);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									ocount = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									for (i=0; i<int (indexcount); i++)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										unsigned int v = indices[i]; // original array index
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										btAssert( v >= 0 && v < vcount );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if ( usedIndices[static_cast<int>(v)] ) // if already remapped
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											indices[i] = usedIndices[static_cast<int>(v)]-1; // index to new array
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										else
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											indices[i] = ocount;      // new index mapping
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											overts[ocount][0] = verts[v][0]; // copy old vert to new vert array
							 | 
						||
| 
								 | 
							
											overts[ocount][1] = verts[v][1];
							 | 
						||
| 
								 | 
							
											overts[ocount][2] = verts[v][2];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											for (int k=0;k<m_vertexIndexMapping.size();k++)
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												if (tmpIndices[k]==int(v))
							 | 
						||
| 
								 | 
							
													m_vertexIndexMapping[k]=ocount;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											ocount++; // increment output vert count
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											btAssert( ocount >=0 && ocount <= vcount );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											usedIndices[static_cast<int>(v)] = ocount; // assign new index remapping
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
								}
							 |