Blender V2.61 - r43446
|
00001 /* 00002 Bullet Continuous Collision Detection and Physics Library 00003 Copyright (c) 2003-2007 Erwin Coumans http://continuousphysics.com/Bullet/ 00004 00005 This software is provided 'as-is', without any express or implied warranty. 00006 In no event will the authors be held liable for any damages arising from the use of this software. 00007 Permission is granted to anyone to use this software for any purpose, 00008 including commercial applications, and to alter it and redistribute it freely, 00009 subject to the following restrictions: 00010 00011 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. 00012 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 00013 3. This notice may not be removed or altered from any source distribution. 00014 */ 00016 00017 #ifndef BT_DYNAMIC_BOUNDING_VOLUME_TREE_H 00018 #define BT_DYNAMIC_BOUNDING_VOLUME_TREE_H 00019 00020 #include "LinearMath/btAlignedObjectArray.h" 00021 #include "LinearMath/btVector3.h" 00022 #include "LinearMath/btTransform.h" 00023 #include "LinearMath/btAabbUtil2.h" 00024 00025 // 00026 // Compile time configuration 00027 // 00028 00029 00030 // Implementation profiles 00031 #define DBVT_IMPL_GENERIC 0 // Generic implementation 00032 #define DBVT_IMPL_SSE 1 // SSE 00033 00034 // Template implementation of ICollide 00035 #ifdef _WIN32 00036 #if (defined (_MSC_VER) && _MSC_VER >= 1400) 00037 #define DBVT_USE_TEMPLATE 1 00038 #else 00039 #define DBVT_USE_TEMPLATE 0 00040 #endif 00041 #else 00042 #define DBVT_USE_TEMPLATE 0 00043 #endif 00044 00045 // Use only intrinsics instead of inline asm 00046 #define DBVT_USE_INTRINSIC_SSE 1 00047 00048 // Using memmov for collideOCL 00049 #define DBVT_USE_MEMMOVE 1 00050 00051 // Enable benchmarking code 00052 #define DBVT_ENABLE_BENCHMARK 0 00053 00054 // Inlining 00055 #define DBVT_INLINE SIMD_FORCE_INLINE 00056 00057 // Specific methods implementation 00058 00059 //SSE gives errors on a MSVC 7.1 00060 #if defined (BT_USE_SSE) && defined (_WIN32) 00061 #define DBVT_SELECT_IMPL DBVT_IMPL_SSE 00062 #define DBVT_MERGE_IMPL DBVT_IMPL_SSE 00063 #define DBVT_INT0_IMPL DBVT_IMPL_SSE 00064 #else 00065 #define DBVT_SELECT_IMPL DBVT_IMPL_GENERIC 00066 #define DBVT_MERGE_IMPL DBVT_IMPL_GENERIC 00067 #define DBVT_INT0_IMPL DBVT_IMPL_GENERIC 00068 #endif 00069 00070 #if (DBVT_SELECT_IMPL==DBVT_IMPL_SSE)|| \ 00071 (DBVT_MERGE_IMPL==DBVT_IMPL_SSE)|| \ 00072 (DBVT_INT0_IMPL==DBVT_IMPL_SSE) 00073 #include <emmintrin.h> 00074 #endif 00075 00076 // 00077 // Auto config and checks 00078 // 00079 00080 #if DBVT_USE_TEMPLATE 00081 #define DBVT_VIRTUAL 00082 #define DBVT_VIRTUAL_DTOR(a) 00083 #define DBVT_PREFIX template <typename T> 00084 #define DBVT_IPOLICY T& policy 00085 #define DBVT_CHECKTYPE static const ICollide& typechecker=*(T*)1;(void)typechecker; 00086 #else 00087 #define DBVT_VIRTUAL_DTOR(a) virtual ~a() {} 00088 #define DBVT_VIRTUAL virtual 00089 #define DBVT_PREFIX 00090 #define DBVT_IPOLICY ICollide& policy 00091 #define DBVT_CHECKTYPE 00092 #endif 00093 00094 #if DBVT_USE_MEMMOVE 00095 #if !defined( __CELLOS_LV2__) && !defined(__MWERKS__) 00096 #include <memory.h> 00097 #endif 00098 #include <string.h> 00099 #endif 00100 00101 #ifndef DBVT_USE_TEMPLATE 00102 #error "DBVT_USE_TEMPLATE undefined" 00103 #endif 00104 00105 #ifndef DBVT_USE_MEMMOVE 00106 #error "DBVT_USE_MEMMOVE undefined" 00107 #endif 00108 00109 #ifndef DBVT_ENABLE_BENCHMARK 00110 #error "DBVT_ENABLE_BENCHMARK undefined" 00111 #endif 00112 00113 #ifndef DBVT_SELECT_IMPL 00114 #error "DBVT_SELECT_IMPL undefined" 00115 #endif 00116 00117 #ifndef DBVT_MERGE_IMPL 00118 #error "DBVT_MERGE_IMPL undefined" 00119 #endif 00120 00121 #ifndef DBVT_INT0_IMPL 00122 #error "DBVT_INT0_IMPL undefined" 00123 #endif 00124 00125 // 00126 // Defaults volumes 00127 // 00128 00129 /* btDbvtAabbMm */ 00130 struct btDbvtAabbMm 00131 { 00132 DBVT_INLINE btVector3 Center() const { return((mi+mx)/2); } 00133 DBVT_INLINE btVector3 Lengths() const { return(mx-mi); } 00134 DBVT_INLINE btVector3 Extents() const { return((mx-mi)/2); } 00135 DBVT_INLINE const btVector3& Mins() const { return(mi); } 00136 DBVT_INLINE const btVector3& Maxs() const { return(mx); } 00137 static inline btDbvtAabbMm FromCE(const btVector3& c,const btVector3& e); 00138 static inline btDbvtAabbMm FromCR(const btVector3& c,btScalar r); 00139 static inline btDbvtAabbMm FromMM(const btVector3& mi,const btVector3& mx); 00140 static inline btDbvtAabbMm FromPoints(const btVector3* pts,int n); 00141 static inline btDbvtAabbMm FromPoints(const btVector3** ppts,int n); 00142 DBVT_INLINE void Expand(const btVector3& e); 00143 DBVT_INLINE void SignedExpand(const btVector3& e); 00144 DBVT_INLINE bool Contain(const btDbvtAabbMm& a) const; 00145 DBVT_INLINE int Classify(const btVector3& n,btScalar o,int s) const; 00146 DBVT_INLINE btScalar ProjectMinimum(const btVector3& v,unsigned signs) const; 00147 DBVT_INLINE friend bool Intersect( const btDbvtAabbMm& a, 00148 const btDbvtAabbMm& b); 00149 00150 DBVT_INLINE friend bool Intersect( const btDbvtAabbMm& a, 00151 const btVector3& b); 00152 00153 DBVT_INLINE friend btScalar Proximity( const btDbvtAabbMm& a, 00154 const btDbvtAabbMm& b); 00155 DBVT_INLINE friend int Select( const btDbvtAabbMm& o, 00156 const btDbvtAabbMm& a, 00157 const btDbvtAabbMm& b); 00158 DBVT_INLINE friend void Merge( const btDbvtAabbMm& a, 00159 const btDbvtAabbMm& b, 00160 btDbvtAabbMm& r); 00161 DBVT_INLINE friend bool NotEqual( const btDbvtAabbMm& a, 00162 const btDbvtAabbMm& b); 00163 private: 00164 DBVT_INLINE void AddSpan(const btVector3& d,btScalar& smi,btScalar& smx) const; 00165 private: 00166 btVector3 mi,mx; 00167 }; 00168 00169 // Types 00170 typedef btDbvtAabbMm btDbvtVolume; 00171 00172 /* btDbvtNode */ 00173 struct btDbvtNode 00174 { 00175 btDbvtVolume volume; 00176 btDbvtNode* parent; 00177 DBVT_INLINE bool isleaf() const { return(childs[1]==0); } 00178 DBVT_INLINE bool isinternal() const { return(!isleaf()); } 00179 union 00180 { 00181 btDbvtNode* childs[2]; 00182 void* data; 00183 int dataAsInt; 00184 }; 00185 }; 00186 00190 struct btDbvt 00191 { 00192 /* Stack element */ 00193 struct sStkNN 00194 { 00195 const btDbvtNode* a; 00196 const btDbvtNode* b; 00197 sStkNN() {} 00198 sStkNN(const btDbvtNode* na,const btDbvtNode* nb) : a(na),b(nb) {} 00199 }; 00200 struct sStkNP 00201 { 00202 const btDbvtNode* node; 00203 int mask; 00204 sStkNP(const btDbvtNode* n,unsigned m) : node(n),mask(m) {} 00205 }; 00206 struct sStkNPS 00207 { 00208 const btDbvtNode* node; 00209 int mask; 00210 btScalar value; 00211 sStkNPS() {} 00212 sStkNPS(const btDbvtNode* n,unsigned m,btScalar v) : node(n),mask(m),value(v) {} 00213 }; 00214 struct sStkCLN 00215 { 00216 const btDbvtNode* node; 00217 btDbvtNode* parent; 00218 sStkCLN(const btDbvtNode* n,btDbvtNode* p) : node(n),parent(p) {} 00219 }; 00220 // Policies/Interfaces 00221 00222 /* ICollide */ 00223 struct ICollide 00224 { 00225 DBVT_VIRTUAL_DTOR(ICollide) 00226 DBVT_VIRTUAL void Process(const btDbvtNode*,const btDbvtNode*) {} 00227 DBVT_VIRTUAL void Process(const btDbvtNode*) {} 00228 DBVT_VIRTUAL void Process(const btDbvtNode* n,btScalar) { Process(n); } 00229 DBVT_VIRTUAL bool Descent(const btDbvtNode*) { return(true); } 00230 DBVT_VIRTUAL bool AllLeaves(const btDbvtNode*) { return(true); } 00231 }; 00232 /* IWriter */ 00233 struct IWriter 00234 { 00235 virtual ~IWriter() {} 00236 virtual void Prepare(const btDbvtNode* root,int numnodes)=0; 00237 virtual void WriteNode(const btDbvtNode*,int index,int parent,int child0,int child1)=0; 00238 virtual void WriteLeaf(const btDbvtNode*,int index,int parent)=0; 00239 }; 00240 /* IClone */ 00241 struct IClone 00242 { 00243 virtual ~IClone() {} 00244 virtual void CloneLeaf(btDbvtNode*) {} 00245 }; 00246 00247 // Constants 00248 enum { 00249 SIMPLE_STACKSIZE = 64, 00250 DOUBLE_STACKSIZE = SIMPLE_STACKSIZE*2 00251 }; 00252 00253 // Fields 00254 btDbvtNode* m_root; 00255 btDbvtNode* m_free; 00256 int m_lkhd; 00257 int m_leaves; 00258 unsigned m_opath; 00259 00260 00261 btAlignedObjectArray<sStkNN> m_stkStack; 00262 00263 00264 // Methods 00265 btDbvt(); 00266 ~btDbvt(); 00267 void clear(); 00268 bool empty() const { return(0==m_root); } 00269 void optimizeBottomUp(); 00270 void optimizeTopDown(int bu_treshold=128); 00271 void optimizeIncremental(int passes); 00272 btDbvtNode* insert(const btDbvtVolume& box,void* data); 00273 void update(btDbvtNode* leaf,int lookahead=-1); 00274 void update(btDbvtNode* leaf,btDbvtVolume& volume); 00275 bool update(btDbvtNode* leaf,btDbvtVolume& volume,const btVector3& velocity,btScalar margin); 00276 bool update(btDbvtNode* leaf,btDbvtVolume& volume,const btVector3& velocity); 00277 bool update(btDbvtNode* leaf,btDbvtVolume& volume,btScalar margin); 00278 void remove(btDbvtNode* leaf); 00279 void write(IWriter* iwriter) const; 00280 void clone(btDbvt& dest,IClone* iclone=0) const; 00281 static int maxdepth(const btDbvtNode* node); 00282 static int countLeaves(const btDbvtNode* node); 00283 static void extractLeaves(const btDbvtNode* node,btAlignedObjectArray<const btDbvtNode*>& leaves); 00284 #if DBVT_ENABLE_BENCHMARK 00285 static void benchmark(); 00286 #else 00287 static void benchmark(){} 00288 #endif 00289 // DBVT_IPOLICY must support ICollide policy/interface 00290 DBVT_PREFIX 00291 static void enumNodes( const btDbvtNode* root, 00292 DBVT_IPOLICY); 00293 DBVT_PREFIX 00294 static void enumLeaves( const btDbvtNode* root, 00295 DBVT_IPOLICY); 00296 DBVT_PREFIX 00297 void collideTT( const btDbvtNode* root0, 00298 const btDbvtNode* root1, 00299 DBVT_IPOLICY); 00300 00301 DBVT_PREFIX 00302 void collideTTpersistentStack( const btDbvtNode* root0, 00303 const btDbvtNode* root1, 00304 DBVT_IPOLICY); 00305 #if 0 00306 DBVT_PREFIX 00307 void collideTT( const btDbvtNode* root0, 00308 const btDbvtNode* root1, 00309 const btTransform& xform, 00310 DBVT_IPOLICY); 00311 DBVT_PREFIX 00312 void collideTT( const btDbvtNode* root0, 00313 const btTransform& xform0, 00314 const btDbvtNode* root1, 00315 const btTransform& xform1, 00316 DBVT_IPOLICY); 00317 #endif 00318 00319 DBVT_PREFIX 00320 void collideTV( const btDbvtNode* root, 00321 const btDbvtVolume& volume, 00322 DBVT_IPOLICY); 00325 DBVT_PREFIX 00326 static void rayTest( const btDbvtNode* root, 00327 const btVector3& rayFrom, 00328 const btVector3& rayTo, 00329 DBVT_IPOLICY); 00332 DBVT_PREFIX 00333 void rayTestInternal( const btDbvtNode* root, 00334 const btVector3& rayFrom, 00335 const btVector3& rayTo, 00336 const btVector3& rayDirectionInverse, 00337 unsigned int signs[3], 00338 btScalar lambda_max, 00339 const btVector3& aabbMin, 00340 const btVector3& aabbMax, 00341 DBVT_IPOLICY) const; 00342 00343 DBVT_PREFIX 00344 static void collideKDOP(const btDbvtNode* root, 00345 const btVector3* normals, 00346 const btScalar* offsets, 00347 int count, 00348 DBVT_IPOLICY); 00349 DBVT_PREFIX 00350 static void collideOCL( const btDbvtNode* root, 00351 const btVector3* normals, 00352 const btScalar* offsets, 00353 const btVector3& sortaxis, 00354 int count, 00355 DBVT_IPOLICY, 00356 bool fullsort=true); 00357 DBVT_PREFIX 00358 static void collideTU( const btDbvtNode* root, 00359 DBVT_IPOLICY); 00360 // Helpers 00361 static DBVT_INLINE int nearest(const int* i,const btDbvt::sStkNPS* a,btScalar v,int l,int h) 00362 { 00363 int m=0; 00364 while(l<h) 00365 { 00366 m=(l+h)>>1; 00367 if(a[i[m]].value>=v) l=m+1; else h=m; 00368 } 00369 return(h); 00370 } 00371 static DBVT_INLINE int allocate( btAlignedObjectArray<int>& ifree, 00372 btAlignedObjectArray<sStkNPS>& stock, 00373 const sStkNPS& value) 00374 { 00375 int i; 00376 if(ifree.size()>0) 00377 { i=ifree[ifree.size()-1];ifree.pop_back();stock[i]=value; } 00378 else 00379 { i=stock.size();stock.push_back(value); } 00380 return(i); 00381 } 00382 // 00383 private: 00384 btDbvt(const btDbvt&) {} 00385 }; 00386 00387 // 00388 // Inline's 00389 // 00390 00391 // 00392 inline btDbvtAabbMm btDbvtAabbMm::FromCE(const btVector3& c,const btVector3& e) 00393 { 00394 btDbvtAabbMm box; 00395 box.mi=c-e;box.mx=c+e; 00396 return(box); 00397 } 00398 00399 // 00400 inline btDbvtAabbMm btDbvtAabbMm::FromCR(const btVector3& c,btScalar r) 00401 { 00402 return(FromCE(c,btVector3(r,r,r))); 00403 } 00404 00405 // 00406 inline btDbvtAabbMm btDbvtAabbMm::FromMM(const btVector3& mi,const btVector3& mx) 00407 { 00408 btDbvtAabbMm box; 00409 box.mi=mi;box.mx=mx; 00410 return(box); 00411 } 00412 00413 // 00414 inline btDbvtAabbMm btDbvtAabbMm::FromPoints(const btVector3* pts,int n) 00415 { 00416 btDbvtAabbMm box; 00417 box.mi=box.mx=pts[0]; 00418 for(int i=1;i<n;++i) 00419 { 00420 box.mi.setMin(pts[i]); 00421 box.mx.setMax(pts[i]); 00422 } 00423 return(box); 00424 } 00425 00426 // 00427 inline btDbvtAabbMm btDbvtAabbMm::FromPoints(const btVector3** ppts,int n) 00428 { 00429 btDbvtAabbMm box; 00430 box.mi=box.mx=*ppts[0]; 00431 for(int i=1;i<n;++i) 00432 { 00433 box.mi.setMin(*ppts[i]); 00434 box.mx.setMax(*ppts[i]); 00435 } 00436 return(box); 00437 } 00438 00439 // 00440 DBVT_INLINE void btDbvtAabbMm::Expand(const btVector3& e) 00441 { 00442 mi-=e;mx+=e; 00443 } 00444 00445 // 00446 DBVT_INLINE void btDbvtAabbMm::SignedExpand(const btVector3& e) 00447 { 00448 if(e.x()>0) mx.setX(mx.x()+e[0]); else mi.setX(mi.x()+e[0]); 00449 if(e.y()>0) mx.setY(mx.y()+e[1]); else mi.setY(mi.y()+e[1]); 00450 if(e.z()>0) mx.setZ(mx.z()+e[2]); else mi.setZ(mi.z()+e[2]); 00451 } 00452 00453 // 00454 DBVT_INLINE bool btDbvtAabbMm::Contain(const btDbvtAabbMm& a) const 00455 { 00456 return( (mi.x()<=a.mi.x())&& 00457 (mi.y()<=a.mi.y())&& 00458 (mi.z()<=a.mi.z())&& 00459 (mx.x()>=a.mx.x())&& 00460 (mx.y()>=a.mx.y())&& 00461 (mx.z()>=a.mx.z())); 00462 } 00463 00464 // 00465 DBVT_INLINE int btDbvtAabbMm::Classify(const btVector3& n,btScalar o,int s) const 00466 { 00467 btVector3 pi,px; 00468 switch(s) 00469 { 00470 case (0+0+0): px=btVector3(mi.x(),mi.y(),mi.z()); 00471 pi=btVector3(mx.x(),mx.y(),mx.z());break; 00472 case (1+0+0): px=btVector3(mx.x(),mi.y(),mi.z()); 00473 pi=btVector3(mi.x(),mx.y(),mx.z());break; 00474 case (0+2+0): px=btVector3(mi.x(),mx.y(),mi.z()); 00475 pi=btVector3(mx.x(),mi.y(),mx.z());break; 00476 case (1+2+0): px=btVector3(mx.x(),mx.y(),mi.z()); 00477 pi=btVector3(mi.x(),mi.y(),mx.z());break; 00478 case (0+0+4): px=btVector3(mi.x(),mi.y(),mx.z()); 00479 pi=btVector3(mx.x(),mx.y(),mi.z());break; 00480 case (1+0+4): px=btVector3(mx.x(),mi.y(),mx.z()); 00481 pi=btVector3(mi.x(),mx.y(),mi.z());break; 00482 case (0+2+4): px=btVector3(mi.x(),mx.y(),mx.z()); 00483 pi=btVector3(mx.x(),mi.y(),mi.z());break; 00484 case (1+2+4): px=btVector3(mx.x(),mx.y(),mx.z()); 00485 pi=btVector3(mi.x(),mi.y(),mi.z());break; 00486 } 00487 if((btDot(n,px)+o)<0) return(-1); 00488 if((btDot(n,pi)+o)>=0) return(+1); 00489 return(0); 00490 } 00491 00492 // 00493 DBVT_INLINE btScalar btDbvtAabbMm::ProjectMinimum(const btVector3& v,unsigned signs) const 00494 { 00495 const btVector3* b[]={&mx,&mi}; 00496 const btVector3 p( b[(signs>>0)&1]->x(), 00497 b[(signs>>1)&1]->y(), 00498 b[(signs>>2)&1]->z()); 00499 return(btDot(p,v)); 00500 } 00501 00502 // 00503 DBVT_INLINE void btDbvtAabbMm::AddSpan(const btVector3& d,btScalar& smi,btScalar& smx) const 00504 { 00505 for(int i=0;i<3;++i) 00506 { 00507 if(d[i]<0) 00508 { smi+=mx[i]*d[i];smx+=mi[i]*d[i]; } 00509 else 00510 { smi+=mi[i]*d[i];smx+=mx[i]*d[i]; } 00511 } 00512 } 00513 00514 // 00515 DBVT_INLINE bool Intersect( const btDbvtAabbMm& a, 00516 const btDbvtAabbMm& b) 00517 { 00518 #if DBVT_INT0_IMPL == DBVT_IMPL_SSE 00519 const __m128 rt(_mm_or_ps( _mm_cmplt_ps(_mm_load_ps(b.mx),_mm_load_ps(a.mi)), 00520 _mm_cmplt_ps(_mm_load_ps(a.mx),_mm_load_ps(b.mi)))); 00521 const __int32* pu((const __int32*)&rt); 00522 return((pu[0]|pu[1]|pu[2])==0); 00523 #else 00524 return( (a.mi.x()<=b.mx.x())&& 00525 (a.mx.x()>=b.mi.x())&& 00526 (a.mi.y()<=b.mx.y())&& 00527 (a.mx.y()>=b.mi.y())&& 00528 (a.mi.z()<=b.mx.z())&& 00529 (a.mx.z()>=b.mi.z())); 00530 #endif 00531 } 00532 00533 00534 00535 // 00536 DBVT_INLINE bool Intersect( const btDbvtAabbMm& a, 00537 const btVector3& b) 00538 { 00539 return( (b.x()>=a.mi.x())&& 00540 (b.y()>=a.mi.y())&& 00541 (b.z()>=a.mi.z())&& 00542 (b.x()<=a.mx.x())&& 00543 (b.y()<=a.mx.y())&& 00544 (b.z()<=a.mx.z())); 00545 } 00546 00547 00548 00549 00550 00552 00553 00554 // 00555 DBVT_INLINE btScalar Proximity( const btDbvtAabbMm& a, 00556 const btDbvtAabbMm& b) 00557 { 00558 const btVector3 d=(a.mi+a.mx)-(b.mi+b.mx); 00559 return(btFabs(d.x())+btFabs(d.y())+btFabs(d.z())); 00560 } 00561 00562 00563 00564 // 00565 DBVT_INLINE int Select( const btDbvtAabbMm& o, 00566 const btDbvtAabbMm& a, 00567 const btDbvtAabbMm& b) 00568 { 00569 #if DBVT_SELECT_IMPL == DBVT_IMPL_SSE 00570 static ATTRIBUTE_ALIGNED16(const unsigned __int32) mask[]={0x7fffffff,0x7fffffff,0x7fffffff,0x7fffffff}; 00572 #if DBVT_USE_INTRINSIC_SSE 00573 00574 union btSSEUnion 00575 { 00576 __m128 ssereg; 00577 float floats[4]; 00578 int ints[4]; 00579 }; 00580 00581 __m128 omi(_mm_load_ps(o.mi)); 00582 omi=_mm_add_ps(omi,_mm_load_ps(o.mx)); 00583 __m128 ami(_mm_load_ps(a.mi)); 00584 ami=_mm_add_ps(ami,_mm_load_ps(a.mx)); 00585 ami=_mm_sub_ps(ami,omi); 00586 ami=_mm_and_ps(ami,_mm_load_ps((const float*)mask)); 00587 __m128 bmi(_mm_load_ps(b.mi)); 00588 bmi=_mm_add_ps(bmi,_mm_load_ps(b.mx)); 00589 bmi=_mm_sub_ps(bmi,omi); 00590 bmi=_mm_and_ps(bmi,_mm_load_ps((const float*)mask)); 00591 __m128 t0(_mm_movehl_ps(ami,ami)); 00592 ami=_mm_add_ps(ami,t0); 00593 ami=_mm_add_ss(ami,_mm_shuffle_ps(ami,ami,1)); 00594 __m128 t1(_mm_movehl_ps(bmi,bmi)); 00595 bmi=_mm_add_ps(bmi,t1); 00596 bmi=_mm_add_ss(bmi,_mm_shuffle_ps(bmi,bmi,1)); 00597 00598 btSSEUnion tmp; 00599 tmp.ssereg = _mm_cmple_ss(bmi,ami); 00600 return tmp.ints[0]&1; 00601 00602 #else 00603 ATTRIBUTE_ALIGNED16(__int32 r[1]); 00604 __asm 00605 { 00606 mov eax,o 00607 mov ecx,a 00608 mov edx,b 00609 movaps xmm0,[eax] 00610 movaps xmm5,mask 00611 addps xmm0,[eax+16] 00612 movaps xmm1,[ecx] 00613 movaps xmm2,[edx] 00614 addps xmm1,[ecx+16] 00615 addps xmm2,[edx+16] 00616 subps xmm1,xmm0 00617 subps xmm2,xmm0 00618 andps xmm1,xmm5 00619 andps xmm2,xmm5 00620 movhlps xmm3,xmm1 00621 movhlps xmm4,xmm2 00622 addps xmm1,xmm3 00623 addps xmm2,xmm4 00624 pshufd xmm3,xmm1,1 00625 pshufd xmm4,xmm2,1 00626 addss xmm1,xmm3 00627 addss xmm2,xmm4 00628 cmpless xmm2,xmm1 00629 movss r,xmm2 00630 } 00631 return(r[0]&1); 00632 #endif 00633 #else 00634 return(Proximity(o,a)<Proximity(o,b)?0:1); 00635 #endif 00636 } 00637 00638 // 00639 DBVT_INLINE void Merge( const btDbvtAabbMm& a, 00640 const btDbvtAabbMm& b, 00641 btDbvtAabbMm& r) 00642 { 00643 #if DBVT_MERGE_IMPL==DBVT_IMPL_SSE 00644 __m128 ami(_mm_load_ps(a.mi)); 00645 __m128 amx(_mm_load_ps(a.mx)); 00646 __m128 bmi(_mm_load_ps(b.mi)); 00647 __m128 bmx(_mm_load_ps(b.mx)); 00648 ami=_mm_min_ps(ami,bmi); 00649 amx=_mm_max_ps(amx,bmx); 00650 _mm_store_ps(r.mi,ami); 00651 _mm_store_ps(r.mx,amx); 00652 #else 00653 for(int i=0;i<3;++i) 00654 { 00655 if(a.mi[i]<b.mi[i]) r.mi[i]=a.mi[i]; else r.mi[i]=b.mi[i]; 00656 if(a.mx[i]>b.mx[i]) r.mx[i]=a.mx[i]; else r.mx[i]=b.mx[i]; 00657 } 00658 #endif 00659 } 00660 00661 // 00662 DBVT_INLINE bool NotEqual( const btDbvtAabbMm& a, 00663 const btDbvtAabbMm& b) 00664 { 00665 return( (a.mi.x()!=b.mi.x())|| 00666 (a.mi.y()!=b.mi.y())|| 00667 (a.mi.z()!=b.mi.z())|| 00668 (a.mx.x()!=b.mx.x())|| 00669 (a.mx.y()!=b.mx.y())|| 00670 (a.mx.z()!=b.mx.z())); 00671 } 00672 00673 // 00674 // Inline's 00675 // 00676 00677 // 00678 DBVT_PREFIX 00679 inline void btDbvt::enumNodes( const btDbvtNode* root, 00680 DBVT_IPOLICY) 00681 { 00682 DBVT_CHECKTYPE 00683 policy.Process(root); 00684 if(root->isinternal()) 00685 { 00686 enumNodes(root->childs[0],policy); 00687 enumNodes(root->childs[1],policy); 00688 } 00689 } 00690 00691 // 00692 DBVT_PREFIX 00693 inline void btDbvt::enumLeaves( const btDbvtNode* root, 00694 DBVT_IPOLICY) 00695 { 00696 DBVT_CHECKTYPE 00697 if(root->isinternal()) 00698 { 00699 enumLeaves(root->childs[0],policy); 00700 enumLeaves(root->childs[1],policy); 00701 } 00702 else 00703 { 00704 policy.Process(root); 00705 } 00706 } 00707 00708 // 00709 DBVT_PREFIX 00710 inline void btDbvt::collideTT( const btDbvtNode* root0, 00711 const btDbvtNode* root1, 00712 DBVT_IPOLICY) 00713 { 00714 DBVT_CHECKTYPE 00715 if(root0&&root1) 00716 { 00717 int depth=1; 00718 int treshold=DOUBLE_STACKSIZE-4; 00719 btAlignedObjectArray<sStkNN> stkStack; 00720 stkStack.resize(DOUBLE_STACKSIZE); 00721 stkStack[0]=sStkNN(root0,root1); 00722 do { 00723 sStkNN p=stkStack[--depth]; 00724 if(depth>treshold) 00725 { 00726 stkStack.resize(stkStack.size()*2); 00727 treshold=stkStack.size()-4; 00728 } 00729 if(p.a==p.b) 00730 { 00731 if(p.a->isinternal()) 00732 { 00733 stkStack[depth++]=sStkNN(p.a->childs[0],p.a->childs[0]); 00734 stkStack[depth++]=sStkNN(p.a->childs[1],p.a->childs[1]); 00735 stkStack[depth++]=sStkNN(p.a->childs[0],p.a->childs[1]); 00736 } 00737 } 00738 else if(Intersect(p.a->volume,p.b->volume)) 00739 { 00740 if(p.a->isinternal()) 00741 { 00742 if(p.b->isinternal()) 00743 { 00744 stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[0]); 00745 stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[0]); 00746 stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[1]); 00747 stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[1]); 00748 } 00749 else 00750 { 00751 stkStack[depth++]=sStkNN(p.a->childs[0],p.b); 00752 stkStack[depth++]=sStkNN(p.a->childs[1],p.b); 00753 } 00754 } 00755 else 00756 { 00757 if(p.b->isinternal()) 00758 { 00759 stkStack[depth++]=sStkNN(p.a,p.b->childs[0]); 00760 stkStack[depth++]=sStkNN(p.a,p.b->childs[1]); 00761 } 00762 else 00763 { 00764 policy.Process(p.a,p.b); 00765 } 00766 } 00767 } 00768 } while(depth); 00769 } 00770 } 00771 00772 00773 00774 DBVT_PREFIX 00775 inline void btDbvt::collideTTpersistentStack( const btDbvtNode* root0, 00776 const btDbvtNode* root1, 00777 DBVT_IPOLICY) 00778 { 00779 DBVT_CHECKTYPE 00780 if(root0&&root1) 00781 { 00782 int depth=1; 00783 int treshold=DOUBLE_STACKSIZE-4; 00784 00785 m_stkStack.resize(DOUBLE_STACKSIZE); 00786 m_stkStack[0]=sStkNN(root0,root1); 00787 do { 00788 sStkNN p=m_stkStack[--depth]; 00789 if(depth>treshold) 00790 { 00791 m_stkStack.resize(m_stkStack.size()*2); 00792 treshold=m_stkStack.size()-4; 00793 } 00794 if(p.a==p.b) 00795 { 00796 if(p.a->isinternal()) 00797 { 00798 m_stkStack[depth++]=sStkNN(p.a->childs[0],p.a->childs[0]); 00799 m_stkStack[depth++]=sStkNN(p.a->childs[1],p.a->childs[1]); 00800 m_stkStack[depth++]=sStkNN(p.a->childs[0],p.a->childs[1]); 00801 } 00802 } 00803 else if(Intersect(p.a->volume,p.b->volume)) 00804 { 00805 if(p.a->isinternal()) 00806 { 00807 if(p.b->isinternal()) 00808 { 00809 m_stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[0]); 00810 m_stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[0]); 00811 m_stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[1]); 00812 m_stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[1]); 00813 } 00814 else 00815 { 00816 m_stkStack[depth++]=sStkNN(p.a->childs[0],p.b); 00817 m_stkStack[depth++]=sStkNN(p.a->childs[1],p.b); 00818 } 00819 } 00820 else 00821 { 00822 if(p.b->isinternal()) 00823 { 00824 m_stkStack[depth++]=sStkNN(p.a,p.b->childs[0]); 00825 m_stkStack[depth++]=sStkNN(p.a,p.b->childs[1]); 00826 } 00827 else 00828 { 00829 policy.Process(p.a,p.b); 00830 } 00831 } 00832 } 00833 } while(depth); 00834 } 00835 } 00836 00837 #if 0 00838 // 00839 DBVT_PREFIX 00840 inline void btDbvt::collideTT( const btDbvtNode* root0, 00841 const btDbvtNode* root1, 00842 const btTransform& xform, 00843 DBVT_IPOLICY) 00844 { 00845 DBVT_CHECKTYPE 00846 if(root0&&root1) 00847 { 00848 int depth=1; 00849 int treshold=DOUBLE_STACKSIZE-4; 00850 btAlignedObjectArray<sStkNN> stkStack; 00851 stkStack.resize(DOUBLE_STACKSIZE); 00852 stkStack[0]=sStkNN(root0,root1); 00853 do { 00854 sStkNN p=stkStack[--depth]; 00855 if(Intersect(p.a->volume,p.b->volume,xform)) 00856 { 00857 if(depth>treshold) 00858 { 00859 stkStack.resize(stkStack.size()*2); 00860 treshold=stkStack.size()-4; 00861 } 00862 if(p.a->isinternal()) 00863 { 00864 if(p.b->isinternal()) 00865 { 00866 stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[0]); 00867 stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[0]); 00868 stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[1]); 00869 stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[1]); 00870 } 00871 else 00872 { 00873 stkStack[depth++]=sStkNN(p.a->childs[0],p.b); 00874 stkStack[depth++]=sStkNN(p.a->childs[1],p.b); 00875 } 00876 } 00877 else 00878 { 00879 if(p.b->isinternal()) 00880 { 00881 stkStack[depth++]=sStkNN(p.a,p.b->childs[0]); 00882 stkStack[depth++]=sStkNN(p.a,p.b->childs[1]); 00883 } 00884 else 00885 { 00886 policy.Process(p.a,p.b); 00887 } 00888 } 00889 } 00890 } while(depth); 00891 } 00892 } 00893 // 00894 DBVT_PREFIX 00895 inline void btDbvt::collideTT( const btDbvtNode* root0, 00896 const btTransform& xform0, 00897 const btDbvtNode* root1, 00898 const btTransform& xform1, 00899 DBVT_IPOLICY) 00900 { 00901 const btTransform xform=xform0.inverse()*xform1; 00902 collideTT(root0,root1,xform,policy); 00903 } 00904 #endif 00905 00906 // 00907 DBVT_PREFIX 00908 inline void btDbvt::collideTV( const btDbvtNode* root, 00909 const btDbvtVolume& vol, 00910 DBVT_IPOLICY) 00911 { 00912 DBVT_CHECKTYPE 00913 if(root) 00914 { 00915 ATTRIBUTE_ALIGNED16(btDbvtVolume) volume(vol); 00916 btAlignedObjectArray<const btDbvtNode*> stack; 00917 stack.resize(0); 00918 stack.reserve(SIMPLE_STACKSIZE); 00919 stack.push_back(root); 00920 do { 00921 const btDbvtNode* n=stack[stack.size()-1]; 00922 stack.pop_back(); 00923 if(Intersect(n->volume,volume)) 00924 { 00925 if(n->isinternal()) 00926 { 00927 stack.push_back(n->childs[0]); 00928 stack.push_back(n->childs[1]); 00929 } 00930 else 00931 { 00932 policy.Process(n); 00933 } 00934 } 00935 } while(stack.size()>0); 00936 } 00937 } 00938 00939 DBVT_PREFIX 00940 inline void btDbvt::rayTestInternal( const btDbvtNode* root, 00941 const btVector3& rayFrom, 00942 const btVector3& rayTo, 00943 const btVector3& rayDirectionInverse, 00944 unsigned int signs[3], 00945 btScalar lambda_max, 00946 const btVector3& aabbMin, 00947 const btVector3& aabbMax, 00948 DBVT_IPOLICY) const 00949 { 00950 (void) rayTo; 00951 DBVT_CHECKTYPE 00952 if(root) 00953 { 00954 btVector3 resultNormal; 00955 00956 int depth=1; 00957 int treshold=DOUBLE_STACKSIZE-2; 00958 btAlignedObjectArray<const btDbvtNode*> stack; 00959 stack.resize(DOUBLE_STACKSIZE); 00960 stack[0]=root; 00961 btVector3 bounds[2]; 00962 do 00963 { 00964 const btDbvtNode* node=stack[--depth]; 00965 bounds[0] = node->volume.Mins()-aabbMax; 00966 bounds[1] = node->volume.Maxs()-aabbMin; 00967 btScalar tmin=1.f,lambda_min=0.f; 00968 unsigned int result1=false; 00969 result1 = btRayAabb2(rayFrom,rayDirectionInverse,signs,bounds,tmin,lambda_min,lambda_max); 00970 if(result1) 00971 { 00972 if(node->isinternal()) 00973 { 00974 if(depth>treshold) 00975 { 00976 stack.resize(stack.size()*2); 00977 treshold=stack.size()-2; 00978 } 00979 stack[depth++]=node->childs[0]; 00980 stack[depth++]=node->childs[1]; 00981 } 00982 else 00983 { 00984 policy.Process(node); 00985 } 00986 } 00987 } while(depth); 00988 } 00989 } 00990 00991 // 00992 DBVT_PREFIX 00993 inline void btDbvt::rayTest( const btDbvtNode* root, 00994 const btVector3& rayFrom, 00995 const btVector3& rayTo, 00996 DBVT_IPOLICY) 00997 { 00998 DBVT_CHECKTYPE 00999 if(root) 01000 { 01001 btVector3 rayDir = (rayTo-rayFrom); 01002 rayDir.normalize (); 01003 01005 btVector3 rayDirectionInverse; 01006 rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[0]; 01007 rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[1]; 01008 rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[2]; 01009 unsigned int signs[3] = { rayDirectionInverse[0] < 0.0, rayDirectionInverse[1] < 0.0, rayDirectionInverse[2] < 0.0}; 01010 01011 btScalar lambda_max = rayDir.dot(rayTo-rayFrom); 01012 01013 btVector3 resultNormal; 01014 01015 btAlignedObjectArray<const btDbvtNode*> stack; 01016 01017 int depth=1; 01018 int treshold=DOUBLE_STACKSIZE-2; 01019 01020 stack.resize(DOUBLE_STACKSIZE); 01021 stack[0]=root; 01022 btVector3 bounds[2]; 01023 do { 01024 const btDbvtNode* node=stack[--depth]; 01025 01026 bounds[0] = node->volume.Mins(); 01027 bounds[1] = node->volume.Maxs(); 01028 01029 btScalar tmin=1.f,lambda_min=0.f; 01030 unsigned int result1 = btRayAabb2(rayFrom,rayDirectionInverse,signs,bounds,tmin,lambda_min,lambda_max); 01031 01032 #ifdef COMPARE_BTRAY_AABB2 01033 btScalar param=1.f; 01034 bool result2 = btRayAabb(rayFrom,rayTo,node->volume.Mins(),node->volume.Maxs(),param,resultNormal); 01035 btAssert(result1 == result2); 01036 #endif //TEST_BTRAY_AABB2 01037 01038 if(result1) 01039 { 01040 if(node->isinternal()) 01041 { 01042 if(depth>treshold) 01043 { 01044 stack.resize(stack.size()*2); 01045 treshold=stack.size()-2; 01046 } 01047 stack[depth++]=node->childs[0]; 01048 stack[depth++]=node->childs[1]; 01049 } 01050 else 01051 { 01052 policy.Process(node); 01053 } 01054 } 01055 } while(depth); 01056 01057 } 01058 } 01059 01060 // 01061 DBVT_PREFIX 01062 inline void btDbvt::collideKDOP(const btDbvtNode* root, 01063 const btVector3* normals, 01064 const btScalar* offsets, 01065 int count, 01066 DBVT_IPOLICY) 01067 { 01068 DBVT_CHECKTYPE 01069 if(root) 01070 { 01071 const int inside=(1<<count)-1; 01072 btAlignedObjectArray<sStkNP> stack; 01073 int signs[sizeof(unsigned)*8]; 01074 btAssert(count<int (sizeof(signs)/sizeof(signs[0]))); 01075 for(int i=0;i<count;++i) 01076 { 01077 signs[i]= ((normals[i].x()>=0)?1:0)+ 01078 ((normals[i].y()>=0)?2:0)+ 01079 ((normals[i].z()>=0)?4:0); 01080 } 01081 stack.reserve(SIMPLE_STACKSIZE); 01082 stack.push_back(sStkNP(root,0)); 01083 do { 01084 sStkNP se=stack[stack.size()-1]; 01085 bool out=false; 01086 stack.pop_back(); 01087 for(int i=0,j=1;(!out)&&(i<count);++i,j<<=1) 01088 { 01089 if(0==(se.mask&j)) 01090 { 01091 const int side=se.node->volume.Classify(normals[i],offsets[i],signs[i]); 01092 switch(side) 01093 { 01094 case -1: out=true;break; 01095 case +1: se.mask|=j;break; 01096 } 01097 } 01098 } 01099 if(!out) 01100 { 01101 if((se.mask!=inside)&&(se.node->isinternal())) 01102 { 01103 stack.push_back(sStkNP(se.node->childs[0],se.mask)); 01104 stack.push_back(sStkNP(se.node->childs[1],se.mask)); 01105 } 01106 else 01107 { 01108 if(policy.AllLeaves(se.node)) enumLeaves(se.node,policy); 01109 } 01110 } 01111 } while(stack.size()); 01112 } 01113 } 01114 01115 // 01116 DBVT_PREFIX 01117 inline void btDbvt::collideOCL( const btDbvtNode* root, 01118 const btVector3* normals, 01119 const btScalar* offsets, 01120 const btVector3& sortaxis, 01121 int count, 01122 DBVT_IPOLICY, 01123 bool fsort) 01124 { 01125 DBVT_CHECKTYPE 01126 if(root) 01127 { 01128 const unsigned srtsgns=(sortaxis[0]>=0?1:0)+ 01129 (sortaxis[1]>=0?2:0)+ 01130 (sortaxis[2]>=0?4:0); 01131 const int inside=(1<<count)-1; 01132 btAlignedObjectArray<sStkNPS> stock; 01133 btAlignedObjectArray<int> ifree; 01134 btAlignedObjectArray<int> stack; 01135 int signs[sizeof(unsigned)*8]; 01136 btAssert(count<int (sizeof(signs)/sizeof(signs[0]))); 01137 for(int i=0;i<count;++i) 01138 { 01139 signs[i]= ((normals[i].x()>=0)?1:0)+ 01140 ((normals[i].y()>=0)?2:0)+ 01141 ((normals[i].z()>=0)?4:0); 01142 } 01143 stock.reserve(SIMPLE_STACKSIZE); 01144 stack.reserve(SIMPLE_STACKSIZE); 01145 ifree.reserve(SIMPLE_STACKSIZE); 01146 stack.push_back(allocate(ifree,stock,sStkNPS(root,0,root->volume.ProjectMinimum(sortaxis,srtsgns)))); 01147 do { 01148 const int id=stack[stack.size()-1]; 01149 sStkNPS se=stock[id]; 01150 stack.pop_back();ifree.push_back(id); 01151 if(se.mask!=inside) 01152 { 01153 bool out=false; 01154 for(int i=0,j=1;(!out)&&(i<count);++i,j<<=1) 01155 { 01156 if(0==(se.mask&j)) 01157 { 01158 const int side=se.node->volume.Classify(normals[i],offsets[i],signs[i]); 01159 switch(side) 01160 { 01161 case -1: out=true;break; 01162 case +1: se.mask|=j;break; 01163 } 01164 } 01165 } 01166 if(out) continue; 01167 } 01168 if(policy.Descent(se.node)) 01169 { 01170 if(se.node->isinternal()) 01171 { 01172 const btDbvtNode* pns[]={ se.node->childs[0],se.node->childs[1]}; 01173 sStkNPS nes[]={ sStkNPS(pns[0],se.mask,pns[0]->volume.ProjectMinimum(sortaxis,srtsgns)), 01174 sStkNPS(pns[1],se.mask,pns[1]->volume.ProjectMinimum(sortaxis,srtsgns))}; 01175 const int q=nes[0].value<nes[1].value?1:0; 01176 int j=stack.size(); 01177 if(fsort&&(j>0)) 01178 { 01179 /* Insert 0 */ 01180 j=nearest(&stack[0],&stock[0],nes[q].value,0,stack.size()); 01181 stack.push_back(0); 01182 #if DBVT_USE_MEMMOVE 01183 memmove(&stack[j+1],&stack[j],sizeof(int)*(stack.size()-j-1)); 01184 #else 01185 for(int k=stack.size()-1;k>j;--k) stack[k]=stack[k-1]; 01186 #endif 01187 stack[j]=allocate(ifree,stock,nes[q]); 01188 /* Insert 1 */ 01189 j=nearest(&stack[0],&stock[0],nes[1-q].value,j,stack.size()); 01190 stack.push_back(0); 01191 #if DBVT_USE_MEMMOVE 01192 memmove(&stack[j+1],&stack[j],sizeof(int)*(stack.size()-j-1)); 01193 #else 01194 for(int k=stack.size()-1;k>j;--k) stack[k]=stack[k-1]; 01195 #endif 01196 stack[j]=allocate(ifree,stock,nes[1-q]); 01197 } 01198 else 01199 { 01200 stack.push_back(allocate(ifree,stock,nes[q])); 01201 stack.push_back(allocate(ifree,stock,nes[1-q])); 01202 } 01203 } 01204 else 01205 { 01206 policy.Process(se.node,se.value); 01207 } 01208 } 01209 } while(stack.size()); 01210 } 01211 } 01212 01213 // 01214 DBVT_PREFIX 01215 inline void btDbvt::collideTU( const btDbvtNode* root, 01216 DBVT_IPOLICY) 01217 { 01218 DBVT_CHECKTYPE 01219 if(root) 01220 { 01221 btAlignedObjectArray<const btDbvtNode*> stack; 01222 stack.reserve(SIMPLE_STACKSIZE); 01223 stack.push_back(root); 01224 do { 01225 const btDbvtNode* n=stack[stack.size()-1]; 01226 stack.pop_back(); 01227 if(policy.Descent(n)) 01228 { 01229 if(n->isinternal()) 01230 { stack.push_back(n->childs[0]);stack.push_back(n->childs[1]); } 01231 else 01232 { policy.Process(n); } 01233 } 01234 } while(stack.size()>0); 01235 } 01236 } 01237 01238 // 01239 // PP Cleanup 01240 // 01241 01242 #undef DBVT_USE_MEMMOVE 01243 #undef DBVT_USE_TEMPLATE 01244 #undef DBVT_VIRTUAL_DTOR 01245 #undef DBVT_VIRTUAL 01246 #undef DBVT_PREFIX 01247 #undef DBVT_IPOLICY 01248 #undef DBVT_CHECKTYPE 01249 #undef DBVT_IMPL_GENERIC 01250 #undef DBVT_IMPL_SSE 01251 #undef DBVT_USE_INTRINSIC_SSE 01252 #undef DBVT_SELECT_IMPL 01253 #undef DBVT_MERGE_IMPL 01254 #undef DBVT_INT0_IMPL 01255 01256 #endif