cd_bullet.cpp
Go to the documentation of this file.
1 
10 #if _HAVE_BULLET
11 
12 #include "cd_bullet.h"
13 
14 #include "btBulletCollisionCommon.h"
15 #include "BulletCollision/CollisionShapes/btShapeHull.h"
16 
17 #if (USE_HACD)
18  #include "HACD/hacdHACD.h"
19 #else
20  #include "BulletCollision/Gimpact/btGImpactShape.h"
21  #include "BulletCollision/Gimpact/btCompoundFromGimpact.h"
22 #endif
23 
24 extern "C" {
25  #include "error.h"
26 }
27 
33 typedef struct {
34  btCollisionWorld *w;
35  boolean cont;
36 } TBulletInt;
37 
43 struct ContactCallback:public btCollisionWorld::ContactResultCallback {
44 
45  boolean info;
46  unsigned int nc;
47  double point[3];
48  double normal[3];
57  ContactCallback(boolean i):btCollisionWorld::ContactResultCallback()
58  {
59  nc=0;
60  info=i;
61  }
62 
78  virtual btScalar addSingleResult(btManifoldPoint& cp,
79  const btCollisionObjectWrapper* colObj0,int partId0,int index0,
80  const btCollisionObjectWrapper* colObj1,int partId1,int index1)
81  {
82  /* store the contact point and the normal (only of the last detected point) */
83  if (info)
84  {
85  unsigned int i;
86 
87  for(i=0;i<3;i++)
88  {
89  point[i]=cp.m_positionWorldOnB[i];
90  normal[i]=cp.m_normalWorldOnB[i];
91  }
92  }
93 
94  nc++; /* we detected one contact more */
95 
96  return(0); /* apparently not used */
97  }
98 };
99 
100 
101 void *InitBulletWorld(boolean cont)
102 {
103  btDefaultCollisionConfiguration *collisionConfiguration=new btDefaultCollisionConfiguration();
104  btCollisionDispatcher *dispatcher=new btCollisionDispatcher(collisionConfiguration);
105  /* AABB broadphase */
106  btBroadphaseInterface *broadphase=new btDbvtBroadphase();
107 
108  TBulletInt *b=new TBulletInt;
109 
110  b->w=new btCollisionWorld(dispatcher,broadphase,collisionConfiguration);
111  b->cont=cont;
112 
113  return((void*)b);
114 }
115 
116 void *DefineBulletSphere(boolean fixed,double r)
117 {
118  btSphereShape *sphere=new btSphereShape(r);
119 
120  btCollisionObject *o=new btCollisionObject();
121 
122  o->setCollisionShape(sphere);
123 
124  if (fixed)
125  o->setCollisionFlags(btCollisionObject::CF_STATIC_OBJECT);
126 
127  return((void*)o);
128 }
129 
130 void *DefineBulletCylinder(boolean fixed,double r,double l)
131 {
132  btCylinderShapeX *cylinder=new btCylinderShapeX(btVector3(l,r,r));
133 
134  btCollisionObject *o=new btCollisionObject();
135 
136  o->setCollisionShape(cylinder);
137  if (fixed)
138  o->setCollisionFlags(btCollisionObject::CF_STATIC_OBJECT);
139 
140  return((void*)o);
141 }
142 
143 void *DefineBulletMesh(boolean fixed,unsigned int nv,double **v,unsigned int nf,unsigned int *nvf,unsigned int **fv)
144 {
145 #if (ASSUME_CONVEX)
146  unsigned int i;
147 
148  btConvexHullShape *hull=new btConvexHullShape();
149 
150  for(i=0;i<nv;i++)
151  {
152  btVector3 pt(btScalar(v[i][0]),btScalar(v[i][1]),btScalar(v[i][2]));
153  hull->addPoint(pt,(i==(nv-1)));
154  }
155 
156  btCollisionObject *o=new btCollisionObject();
157 
158  #if (0)
159  // define a simplified hull-> get the hull of the hull
160  btShapeHull *shapeHull=new btShapeHull(hull);
161  shapeHull->buildHull(0);
162  btConvexHullShape* shull=new btConvexHullShape((btScalar*)shapeHull->getVertexPointer(),shapeHull->numVertices());
163 
164  shull->setMargin(0);
165 
166  o->setCollisionShape(shull);
167  #else
168  /* let's assume that the user already simplified the mesh if desired */
169  /* We have to set a negative margin to objects to enforc them to be in contact */
170  hull->setMargin(-0.15);
171  o->setCollisionShape(hull);
172  #endif
173 
174  if (fixed)
175  o->setCollisionFlags(btCollisionObject::CF_STATIC_OBJECT);
176 
177  return((void*)o);
178 #else
179  #if (USE_HACD)
180  /* convex decomposition code taken from the Bullet ConvexDecompsitionDemo */
181  /* This is completely impractical for large problems */
182 
183  std::vector< HACD::Vec3<HACD::Real> > points;
184  std::vector< HACD::Vec3<long> > triangles;
185 
186  for(unsigned int i=0; i<nv; i++ )
187  {
188  HACD::Vec3<HACD::Real> vertex(HACD::Real(v[i][0]),HACD::Real(v[i][1]),HACD::Real(v[i][2]));
189  points.push_back(vertex);
190  }
191 
192  for(unsigned int i=0;i<nf;i++)
193  {
194  for(unsigned int j=2;j<nvf[i];j++)
195  {
196  HACD::Vec3<long> triangle(long(fv[i][0]),long(fv[i][j-1]),long(fv[i][j]));
197  triangles.push_back(triangle);
198  }
199  }
200 
201  HACD::HACD myHACD;
202  myHACD.SetPoints(&points[0]);
203  myHACD.SetNPoints(points.size());
204  myHACD.SetTriangles(&triangles[0]);
205  myHACD.SetNTriangles(triangles.size());
206  myHACD.SetCompacityWeight(0.1);
207  myHACD.SetVolumeWeight(0.0);
208 
209  // HACD parameters
210  // Recommended parameters: 2 100 0 0 0 0
211  myHACD.SetNClusters(2); // minimum number of clusters
212  myHACD.SetNVerticesPerCH(100); // max of 100 vertices per convex-hull
213  myHACD.SetConcavity(100); // maximum concavity
214  myHACD.SetAddExtraDistPoints(false);
215  myHACD.SetAddNeighboursDistPoints(false);
216  myHACD.SetAddFacesPoints(false);
217 
218  fprintf(stderr,"computing hacd (%u)\n",nv);fflush(stderr);
219 
220 
221  myHACD.Compute();
222  size_t nClusters=myHACD.GetNClusters();
223 
224  fprintf(stderr,"computed hacd\n");fflush(stderr);
225 
226  btCompoundShape *compound=new btCompoundShape();
227  btTransform trans;
228  trans.setIdentity();
229 
230  for (unsigned int c=0;c<nClusters;c++)
231  {
232  //generate convex result
233  size_t nPoints=myHACD.GetNPointsCH(c);
234  size_t nTriangles=myHACD.GetNTrianglesCH(c);
235 
236  btScalar *vertices=new btScalar[nPoints*3];
237  int *triangles=new int[nTriangles*3];
238 
239  HACD::Vec3<HACD::Real> *pointsCH=new HACD::Vec3<HACD::Real>[nPoints];
240  HACD::Vec3<long> *trianglesCH=new HACD::Vec3<long>[nTriangles];
241  myHACD.GetCH(c,pointsCH,trianglesCH);
242 
243  // points
244  for(size_t v=0;v<nPoints;v++)
245  {
246  vertices[3*v]=pointsCH[v].X();
247  vertices[3*v+1]=pointsCH[v].Y();
248  vertices[3*v+2]=pointsCH[v].Z();
249  }
250 
251  // triangles
252  for(size_t f=0;f<nTriangles;f++)
253  {
254  triangles[3*f]=trianglesCH[f].X();
255  triangles[3*f+1]=trianglesCH[f].Y();
256  triangles[3*f+2]=trianglesCH[f].Z();
257  }
258 
259  delete [] pointsCH;
260  delete [] trianglesCH;
261 
262  btTriangleIndexVertexArray *indexVertexArrays=new btTriangleIndexVertexArray(nTriangles,triangles,3*sizeof(int),nPoints,vertices,3*sizeof(btScalar));
263  btConvexTriangleMeshShape *convexShape=new btConvexTriangleMeshShape(indexVertexArrays);
264 
265  compound->addChildShape(trans,convexShape);
266  }
267 
268  btCollisionObject *o=new btCollisionObject();
269 
270  o->setCollisionShape(compound);
271  if (fixed)
272  o->setCollisionFlags(btCollisionObject::CF_STATIC_OBJECT);
273 
274  return((void*)o);
275  #else
276 
277  btScalar vertex[3*nv];
278  unsigned int i,j,k,nt;
279 
280  /* Use a simple procedure to define a composed collision shape, one that does not requires the
281  Bullet extra libraries. In this procedure each triangle is transformed into a small
282  tetrahedron and all the tetrahedra define a composed shape. */
283 
284  /* transform from double to btScalar and store in an array */
285  k=0;
286  for(i=0;i<nv;i++)
287  {
288  for(j=0;j<3;j++)
289  vertex[k++]=btScalar(v[i][j]);
290  }
291 
292  /* Triangulate the faces in a simple way (typically they are already triangulated) */
293  nt=0; /* number of triangles */
294  for(i=0;i<nf;i++)
295  nt+=(nvf[i]-2);
296 
297  int triangle[3*nt];
298 
299  /* We assume that the faces are convex and easy to triangulate (if not
300  triangles already) */
301  k=0;
302  for(i=0;i<nf;i++)
303  {
304  for(j=2;j<nvf[i];j++)
305  {
306  triangle[k++]=fv[i][0];
307  triangle[k++]=fv[i][j-1];
308  triangle[k++]=fv[i][j];
309  }
310  }
311 
312  btTriangleIndexVertexArray *indexVertexArrays=new btTriangleIndexVertexArray(nt,triangle,3*sizeof(int),nv,vertex,3*sizeof(btScalar));
313  btGImpactMeshShape *trimesh=new btGImpactMeshShape(indexVertexArrays);
314 
315  trimesh->updateBound();
316 
317  btCollisionShape *mesh=btCreateCompoundFromGimpactShape(trimesh,0.00001);
318 
319  mesh->setMargin(0);
320 
321  btCollisionObject *o=new btCollisionObject();
322 
323  o->setCollisionShape(mesh);
324  if (fixed)
325  o->setCollisionFlags(btCollisionObject::CF_STATIC_OBJECT);
326 
327  return((void*)o);
328 
329  #endif
330 #endif
331 }
332 
333 boolean BulletTest(boolean info,
334  void *h1,THTransform *tr1,
335  void *h2,THTransform *tr2,
336  double *point,double *normal,
337  void *cw)
338 {
339  TBulletInt *bw;
340  btCollisionObject *o1,*o2;
341  btMatrix3x3 r1(HTransformGetElement(0,0,tr1),HTransformGetElement(0,1,tr1),HTransformGetElement(0,2,tr1),
344  btVector3 t1(HTransformGetElement(0,3,tr1),HTransformGetElement(1,3,tr1),HTransformGetElement(2,3,tr1));
345  btMatrix3x3 r2(HTransformGetElement(0,0,tr2),HTransformGetElement(0,1,tr2),HTransformGetElement(0,2,tr2),
348  btVector3 t2(HTransformGetElement(0,3,tr2),HTransformGetElement(1,3,tr2),HTransformGetElement(2,3,tr2));
349  ContactCallback resultCB(info);
350 
351  bw=(TBulletInt*)cw;
352 
353  if (bw->cont)
354  Error("Using BulletTest with a non-continuous collision Bullet init");
355 
356  o1=(btCollisionObject*)h1;
357  o2=(btCollisionObject*)h2;
358 
359  o1->getWorldTransform().setBasis(r1);
360  o1->getWorldTransform().setOrigin(t1);
361 
362  o2->getWorldTransform().setBasis(r2);
363  o2->getWorldTransform().setOrigin(t2);
364 
365  bw->w->contactPairTest(o1,o2,resultCB);
366 
367  if ((info)&&(resultCB.nc>0))
368  {
369  unsigned int i;
370 
371  for(i=0;i<3;i++)
372  {
373  point[i]=resultCB.point[i];
374  normal[i]=resultCB.normal[i];
375  }
376  }
377 
378  return(resultCB.nc>0);
379 }
380 
381 boolean BulletCTest(void *h1,THTransform *tr1,THTransform *tr2,
382  void *h2,THTransform *tr3,THTransform *tr4,
383  void *cw)
384 {
385  Error("BulletCTest not implemented yet");
386  return(false);
387 }
388 
389 void DeleteBulletObject(void *h)
390 {
391  btCollisionObject *o;
392 
393  o=(btCollisionObject*)h;
394 
395  delete o;
396 }
397 
398 void DeleteBulletWorld(void *cw)
399 {
400  TBulletInt *bw;
401 
402  bw=(TBulletInt*)cw;
403 
404  delete bw->w;
405  delete bw;
406 }
407 
408 #endif
A homgeneous transform in R^3.
void Error(const char *s)
General error function.
Definition: error.c:80
Error and warning functions.
Headers of the C interface for the Bullet collision detection library.
double HTransformGetElement(unsigned int i, unsigned int j, THTransform *t)
Gets an element in a homogeneous transform.
Definition: htransform.c:323