Bullet Collision Detection & Physics Library
btSparseSDF.h
Go to the documentation of this file.
1 /*
2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
4 
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:
10 
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.
14 */
16 
17 #ifndef BT_SPARSE_SDF_H
18 #define BT_SPARSE_SDF_H
19 
22 
23 // Modified Paul Hsieh hash
24 template <const int DWORDLEN>
25 unsigned int HsiehHash(const void* pdata)
26 {
27  const unsigned short* data=(const unsigned short*)pdata;
28  unsigned hash=DWORDLEN<<2,tmp;
29  for(int i=0;i<DWORDLEN;++i)
30  {
31  hash += data[0];
32  tmp = (data[1]<<11)^hash;
33  hash = (hash<<16)^tmp;
34  data += 2;
35  hash += hash>>11;
36  }
37  hash^=hash<<3;hash+=hash>>5;
38  hash^=hash<<4;hash+=hash>>17;
39  hash^=hash<<25;hash+=hash>>6;
40  return(hash);
41 }
42 
43 template <const int CELLSIZE>
45 {
46  //
47  // Inner types
48  //
49  struct IntFrac
50  {
51  int b;
52  int i;
54  };
55  struct Cell
56  {
57  btScalar d[CELLSIZE+1][CELLSIZE+1][CELLSIZE+1];
58  int c[3];
59  int puid;
60  unsigned hash;
63  };
64  //
65  // Fields
66  //
67 
70  int puid;
71  int ncells;
73  int nprobes;
74  int nqueries;
75 
76  //
77  // Methods
78  //
79 
80  //
81  void Initialize(int hashsize=2383, int clampCells = 256*1024)
82  {
83  //avoid a crash due to running out of memory, so clamp the maximum number of cells allocated
84  //if this limit is reached, the SDF is reset (at the cost of some performance during the reset)
85  m_clampCells = clampCells;
86  cells.resize(hashsize,0);
87  Reset();
88  }
89  //
90  void Reset()
91  {
92  for(int i=0,ni=cells.size();i<ni;++i)
93  {
94  Cell* pc=cells[i];
95  cells[i]=0;
96  while(pc)
97  {
98  Cell* pn=pc->next;
99  delete pc;
100  pc=pn;
101  }
102  }
103  voxelsz =0.25;
104  puid =0;
105  ncells =0;
106  nprobes =1;
107  nqueries =1;
108  }
109  //
110  void GarbageCollect(int lifetime=256)
111  {
112  const int life=puid-lifetime;
113  for(int i=0;i<cells.size();++i)
114  {
115  Cell*& root=cells[i];
116  Cell* pp=0;
117  Cell* pc=root;
118  while(pc)
119  {
120  Cell* pn=pc->next;
121  if(pc->puid<life)
122  {
123  if(pp) pp->next=pn; else root=pn;
124  delete pc;pc=pp;--ncells;
125  }
126  pp=pc;pc=pn;
127  }
128  }
129  //printf("GC[%d]: %d cells, PpQ: %f\r\n",puid,ncells,nprobes/(btScalar)nqueries);
130  nqueries=1;
131  nprobes=1;
132  ++puid;
133  /* else setup a priority list... */
134  }
135  //
137  {
138  int refcount=0;
139  for(int i=0;i<cells.size();++i)
140  {
141  Cell*& root=cells[i];
142  Cell* pp=0;
143  Cell* pc=root;
144  while(pc)
145  {
146  Cell* pn=pc->next;
147  if(pc->pclient==pcs)
148  {
149  if(pp) pp->next=pn; else root=pn;
150  delete pc;pc=pp;++refcount;
151  }
152  pp=pc;pc=pn;
153  }
154  }
155  return(refcount);
156  }
157  //
159  const btCollisionShape* shape,
160  btVector3& normal,
161  btScalar margin)
162  {
163  /* Lookup cell */
164  const btVector3 scx=x/voxelsz;
165  const IntFrac ix=Decompose(scx.x());
166  const IntFrac iy=Decompose(scx.y());
167  const IntFrac iz=Decompose(scx.z());
168  const unsigned h=Hash(ix.b,iy.b,iz.b,shape);
169  Cell*& root=cells[static_cast<int>(h%cells.size())];
170  Cell* c=root;
171  ++nqueries;
172  while(c)
173  {
174  ++nprobes;
175  if( (c->hash==h) &&
176  (c->c[0]==ix.b) &&
177  (c->c[1]==iy.b) &&
178  (c->c[2]==iz.b) &&
179  (c->pclient==shape))
180  { break; }
181  else
182  { c=c->next; }
183  }
184  if(!c)
185  {
186  ++nprobes;
187  ++ncells;
188  int sz = sizeof(Cell);
189  if (ncells>m_clampCells)
190  {
191  static int numResets=0;
192  numResets++;
193 // printf("numResets=%d\n",numResets);
194  Reset();
195  }
196 
197  c=new Cell();
198  c->next=root;root=c;
199  c->pclient=shape;
200  c->hash=h;
201  c->c[0]=ix.b;c->c[1]=iy.b;c->c[2]=iz.b;
202  BuildCell(*c);
203  }
204  c->puid=puid;
205  /* Extract infos */
206  const int o[]={ ix.i,iy.i,iz.i};
207  const btScalar d[]={ c->d[o[0]+0][o[1]+0][o[2]+0],
208  c->d[o[0]+1][o[1]+0][o[2]+0],
209  c->d[o[0]+1][o[1]+1][o[2]+0],
210  c->d[o[0]+0][o[1]+1][o[2]+0],
211  c->d[o[0]+0][o[1]+0][o[2]+1],
212  c->d[o[0]+1][o[1]+0][o[2]+1],
213  c->d[o[0]+1][o[1]+1][o[2]+1],
214  c->d[o[0]+0][o[1]+1][o[2]+1]};
215  /* Normal */
216 #if 1
217  const btScalar gx[]={ d[1]-d[0],d[2]-d[3],
218  d[5]-d[4],d[6]-d[7]};
219  const btScalar gy[]={ d[3]-d[0],d[2]-d[1],
220  d[7]-d[4],d[6]-d[5]};
221  const btScalar gz[]={ d[4]-d[0],d[5]-d[1],
222  d[7]-d[3],d[6]-d[2]};
223  normal.setX(Lerp( Lerp(gx[0],gx[1],iy.f),
224  Lerp(gx[2],gx[3],iy.f),iz.f));
225  normal.setY(Lerp( Lerp(gy[0],gy[1],ix.f),
226  Lerp(gy[2],gy[3],ix.f),iz.f));
227  normal.setZ(Lerp( Lerp(gz[0],gz[1],ix.f),
228  Lerp(gz[2],gz[3],ix.f),iy.f));
229  normal = normal.normalized();
230 #else
231  normal = btVector3(d[1]-d[0],d[3]-d[0],d[4]-d[0]).normalized();
232 #endif
233  /* Distance */
234  const btScalar d0=Lerp(Lerp(d[0],d[1],ix.f),
235  Lerp(d[3],d[2],ix.f),iy.f);
236  const btScalar d1=Lerp(Lerp(d[4],d[5],ix.f),
237  Lerp(d[7],d[6],ix.f),iy.f);
238  return(Lerp(d0,d1,iz.f)-margin);
239  }
240  //
241  void BuildCell(Cell& c)
242  {
243  const btVector3 org=btVector3( (btScalar)c.c[0],
244  (btScalar)c.c[1],
245  (btScalar)c.c[2]) *
246  CELLSIZE*voxelsz;
247  for(int k=0;k<=CELLSIZE;++k)
248  {
249  const btScalar z=voxelsz*k+org.z();
250  for(int j=0;j<=CELLSIZE;++j)
251  {
252  const btScalar y=voxelsz*j+org.y();
253  for(int i=0;i<=CELLSIZE;++i)
254  {
255  const btScalar x=voxelsz*i+org.x();
256  c.d[i][j][k]=DistanceToShape( btVector3(x,y,z),
257  c.pclient);
258  }
259  }
260  }
261  }
262  //
263  static inline btScalar DistanceToShape(const btVector3& x,
264  const btCollisionShape* shape)
265  {
266  btTransform unit;
267  unit.setIdentity();
268  if(shape->isConvex())
269  {
271  const btConvexShape* csh=static_cast<const btConvexShape*>(shape);
272  return(btGjkEpaSolver2::SignedDistance(x,0,csh,unit,res));
273  }
274  return(0);
275  }
276  //
277  static inline IntFrac Decompose(btScalar x)
278  {
279  /* That one need a lot of improvements... */
280  /* Remove test, faster floor... */
281  IntFrac r;
282  x/=CELLSIZE;
283  const int o=x<0?(int)(-x+1):0;
284  x+=o;r.b=(int)x;
285  const btScalar k=(x-r.b)*CELLSIZE;
286  r.i=(int)k;r.f=k-r.i;r.b-=o;
287  return(r);
288  }
289  //
290  static inline btScalar Lerp(btScalar a,btScalar b,btScalar t)
291  {
292  return(a+(b-a)*t);
293  }
294 
295 
296 
297  //
298  static inline unsigned int Hash(int x,int y,int z,const btCollisionShape* shape)
299  {
300  struct btS
301  {
302  int x,y,z;
303  void* p;
304  };
305 
306  btS myset;
307 
308  myset.x=x;myset.y=y;myset.z=z;myset.p=(void*)shape;
309  const void* ptr = &myset;
310 
311  unsigned int result = HsiehHash<sizeof(btS)/4> (ptr);
312 
313 
314  return result;
315  }
316 };
317 
318 
319 #endif //BT_SPARSE_SDF_H
void GarbageCollect(int lifetime=256)
Definition: btSparseSDF.h:110
void BuildCell(Cell &c)
Definition: btSparseSDF.h:241
The btAlignedObjectArray template class uses a subset of the stl::vector interface for its methods It...
void setZ(btScalar _z)
Set the z value.
Definition: btVector3.h:571
void setIdentity()
Set this transformation to the identity.
Definition: btTransform.h:172
unsigned int HsiehHash(const void *pdata)
btSparseSdf implementation by Nathanael Presson
Definition: btSparseSDF.h:25
The btCollisionShape class provides an interface for collision shapes that can be shared among btColl...
btAlignedObjectArray< Cell * > cells
Definition: btSparseSDF.h:68
const btScalar & x() const
Return the x value.
Definition: btVector3.h:575
The btConvexShape is an abstract shape interface, implemented by all convex shapes such as btBoxShape...
Definition: btConvexShape.h:31
void setX(btScalar _x)
Set the x value.
Definition: btVector3.h:567
int RemoveReferences(btCollisionShape *pcs)
Definition: btSparseSDF.h:136
static btScalar Lerp(btScalar a, btScalar b, btScalar t)
Definition: btSparseSDF.h:290
void setY(btScalar _y)
Set the y value.
Definition: btVector3.h:569
const btScalar & y() const
Return the y value.
Definition: btVector3.h:577
btVector3 can be used to represent 3D points and vectors.
Definition: btVector3.h:83
The btTransform class supports rigid transforms with only translation and rotation and no scaling/she...
Definition: btTransform.h:34
bool isConvex() const
btScalar d[CELLSIZE+1][CELLSIZE+1][CELLSIZE+1]
Definition: btSparseSDF.h:57
btVector3 normalized() const
Return a normalized version of this vector.
Definition: btVector3.h:951
btScalar Evaluate(const btVector3 &x, const btCollisionShape *shape, btVector3 &normal, btScalar margin)
Definition: btSparseSDF.h:158
static unsigned int Hash(int x, int y, int z, const btCollisionShape *shape)
Definition: btSparseSDF.h:298
static btScalar SignedDistance(const btVector3 &position, btScalar margin, const btConvexShape *shape, const btTransform &wtrs, sResults &results)
Definition: btGjkEpa2.cpp:949
const btCollisionShape * pclient
Definition: btSparseSDF.h:61
btScalar voxelsz
Definition: btSparseSDF.h:69
static IntFrac Decompose(btScalar x)
Definition: btSparseSDF.h:277
int m_clampCells
Definition: btSparseSDF.h:72
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
Definition: btScalar.h:266
static btScalar DistanceToShape(const btVector3 &x, const btCollisionShape *shape)
Definition: btSparseSDF.h:263
void Reset()
Definition: btSparseSDF.h:90
void Initialize(int hashsize=2383, int clampCells=256 *1024)
Definition: btSparseSDF.h:81
const btScalar & z() const
Return the z value.
Definition: btVector3.h:579