2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages arising from the use of this software.
7 Permission is granted to anyone to use this software for any purpose,
8 including commercial applications, and to alter it and redistribute it freely,
9 subject to the following restrictions:
11 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.
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13 3. This notice may not be removed or altered from any source distribution.
15 ///btSparseSdf implementation by Nathanael Presson
17 #ifndef BT_SPARSE_SDF_H
18 #define BT_SPARSE_SDF_H
20 #include "BulletCollision/CollisionDispatch/btCollisionObject.h"
21 #include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
23 // Modified Paul Hsieh hash
24 template <const int DWORDLEN>
25 unsigned int HsiehHash(const void* pdata)
27 const unsigned short* data=(const unsigned short*)pdata;
28 unsigned hash=DWORDLEN<<2,tmp;
29 for(int i=0;i<DWORDLEN;++i)
32 tmp = (data[1]<<11)^hash;
33 hash = (hash<<16)^tmp;
37 hash^=hash<<3;hash+=hash>>5;
38 hash^=hash<<4;hash+=hash>>17;
39 hash^=hash<<25;hash+=hash>>6;
43 template <const int CELLSIZE>
57 btScalar d[CELLSIZE+1][CELLSIZE+1][CELLSIZE+1];
61 const btCollisionShape* pclient;
68 btAlignedObjectArray<Cell*> cells;
80 void Initialize(int hashsize=2383)
82 cells.resize(hashsize,0);
88 for(int i=0,ni=cells.size();i<ni;++i)
106 void GarbageCollect(int lifetime=256)
108 const int life=puid-lifetime;
109 for(int i=0;i<cells.size();++i)
111 Cell*& root=cells[i];
119 if(pp) pp->next=pn; else root=pn;
120 delete pc;pc=pp;--ncells;
125 //printf("GC[%d]: %d cells, PpQ: %f\r\n",puid,ncells,nprobes/(btScalar)nqueries);
128 ++puid; ///@todo: Reset puid's when int range limit is reached */
129 /* else setup a priority list... */
132 int RemoveReferences(btCollisionShape* pcs)
135 for(int i=0;i<cells.size();++i)
137 Cell*& root=cells[i];
145 if(pp) pp->next=pn; else root=pn;
146 delete pc;pc=pp;++refcount;
154 btScalar Evaluate( const btVector3& x,
155 const btCollisionShape* shape,
160 const btVector3 scx=x/voxelsz;
161 const IntFrac ix=Decompose(scx.x());
162 const IntFrac iy=Decompose(scx.y());
163 const IntFrac iz=Decompose(scx.z());
164 const unsigned h=Hash(ix.b,iy.b,iz.b,shape);
165 Cell*& root=cells[static_cast<int>(h%cells.size())];
188 c->c[0]=ix.b;c->c[1]=iy.b;c->c[2]=iz.b;
193 const int o[]={ ix.i,iy.i,iz.i};
194 const btScalar d[]={ c->d[o[0]+0][o[1]+0][o[2]+0],
195 c->d[o[0]+1][o[1]+0][o[2]+0],
196 c->d[o[0]+1][o[1]+1][o[2]+0],
197 c->d[o[0]+0][o[1]+1][o[2]+0],
198 c->d[o[0]+0][o[1]+0][o[2]+1],
199 c->d[o[0]+1][o[1]+0][o[2]+1],
200 c->d[o[0]+1][o[1]+1][o[2]+1],
201 c->d[o[0]+0][o[1]+1][o[2]+1]};
204 const btScalar gx[]={ d[1]-d[0],d[2]-d[3],
205 d[5]-d[4],d[6]-d[7]};
206 const btScalar gy[]={ d[3]-d[0],d[2]-d[1],
207 d[7]-d[4],d[6]-d[5]};
208 const btScalar gz[]={ d[4]-d[0],d[5]-d[1],
209 d[7]-d[3],d[6]-d[2]};
210 normal.setX(Lerp( Lerp(gx[0],gx[1],iy.f),
211 Lerp(gx[2],gx[3],iy.f),iz.f));
212 normal.setY(Lerp( Lerp(gy[0],gy[1],ix.f),
213 Lerp(gy[2],gy[3],ix.f),iz.f));
214 normal.setZ(Lerp( Lerp(gz[0],gz[1],ix.f),
215 Lerp(gz[2],gz[3],ix.f),iy.f));
216 normal = normal.normalized();
218 normal = btVector3(d[1]-d[0],d[3]-d[0],d[4]-d[0]).normalized();
221 const btScalar d0=Lerp(Lerp(d[0],d[1],ix.f),
222 Lerp(d[3],d[2],ix.f),iy.f);
223 const btScalar d1=Lerp(Lerp(d[4],d[5],ix.f),
224 Lerp(d[7],d[6],ix.f),iy.f);
225 return(Lerp(d0,d1,iz.f)-margin);
228 void BuildCell(Cell& c)
230 const btVector3 org=btVector3( (btScalar)c.c[0],
234 for(int k=0;k<=CELLSIZE;++k)
236 const btScalar z=voxelsz*k+org.z();
237 for(int j=0;j<=CELLSIZE;++j)
239 const btScalar y=voxelsz*j+org.y();
240 for(int i=0;i<=CELLSIZE;++i)
242 const btScalar x=voxelsz*i+org.x();
243 c.d[i][j][k]=DistanceToShape( btVector3(x,y,z),
250 static inline btScalar DistanceToShape(const btVector3& x,
251 const btCollisionShape* shape)
255 if(shape->isConvex())
257 btGjkEpaSolver2::sResults res;
258 const btConvexShape* csh=static_cast<const btConvexShape*>(shape);
259 return(btGjkEpaSolver2::SignedDistance(x,0,csh,unit,res));
264 static inline IntFrac Decompose(btScalar x)
266 /* That one need a lot of improvements... */
267 /* Remove test, faster floor... */
270 const int o=x<0?(int)(-x+1):0;
272 const btScalar k=(x-r.b)*CELLSIZE;
273 r.i=(int)k;r.f=k-r.i;r.b-=o;
277 static inline btScalar Lerp(btScalar a,btScalar b,btScalar t)
285 static inline unsigned int Hash(int x,int y,int z,const btCollisionShape* shape)
295 myset.x=x;myset.y=y;myset.z=z;myset.p=(void*)shape;
296 const void* ptr = &myset;
298 unsigned int result = HsiehHash<sizeof(btS)/4> (ptr);
306 #endif //BT_SPARSE_SDF_H