Bullet Collision Detection & Physics Library
btConvexShape.cpp
Go to the documentation of this file.
1 /*
2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
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 */
15 
16 #if defined (_WIN32) || defined (__i386__)
17 #define BT_USE_SSE_IN_API
18 #endif
19 
20 #include "btConvexShape.h"
21 #include "btTriangleShape.h"
22 #include "btSphereShape.h"
23 #include "btCylinderShape.h"
24 #include "btConeShape.h"
25 #include "btCapsuleShape.h"
26 #include "btConvexHullShape.h"
28 
30 #if defined (__CELLOS_LV2__) && defined (__SPU__)
31 #include <spu_intrinsics.h>
32 static inline vec_float4 vec_dot3( vec_float4 vec0, vec_float4 vec1 )
33 {
34  vec_float4 result;
35  result = spu_mul( vec0, vec1 );
36  result = spu_madd( spu_rlqwbyte( vec0, 4 ), spu_rlqwbyte( vec1, 4 ), result );
37  return spu_madd( spu_rlqwbyte( vec0, 8 ), spu_rlqwbyte( vec1, 8 ), result );
38 }
39 #endif //__SPU__
40 
42 {
43 }
44 
46 {
47 
48 }
49 
50 
51 void btConvexShape::project(const btTransform& trans, const btVector3& dir, btScalar& min, btScalar& max, btVector3& witnesPtMin,btVector3& witnesPtMax) const
52 {
53  btVector3 localAxis = dir*trans.getBasis();
54  btVector3 vtx1 = trans(localGetSupportingVertex(localAxis));
55  btVector3 vtx2 = trans(localGetSupportingVertex(-localAxis));
56 
57  min = vtx1.dot(dir);
58  max = vtx2.dot(dir);
59  witnesPtMax = vtx2;
60  witnesPtMin = vtx1;
61 
62  if(min>max)
63  {
64  btScalar tmp = min;
65  min = max;
66  max = tmp;
67  witnesPtMax = vtx1;
68  witnesPtMin = vtx2;
69  }
70 }
71 
72 
73 static btVector3 convexHullSupport (const btVector3& localDirOrg, const btVector3* points, int numPoints, const btVector3& localScaling)
74 {
75 
76  btVector3 vec = localDirOrg * localScaling;
77 
78 #if defined (__CELLOS_LV2__) && defined (__SPU__)
79 
80  btVector3 localDir = vec;
81 
82  vec_float4 v_distMax = {-FLT_MAX,0,0,0};
83  vec_int4 v_idxMax = {-999,0,0,0};
84  int v=0;
85  int numverts = numPoints;
86 
87  for(;v<(int)numverts-4;v+=4) {
88  vec_float4 p0 = vec_dot3(points[v ].get128(),localDir.get128());
89  vec_float4 p1 = vec_dot3(points[v+1].get128(),localDir.get128());
90  vec_float4 p2 = vec_dot3(points[v+2].get128(),localDir.get128());
91  vec_float4 p3 = vec_dot3(points[v+3].get128(),localDir.get128());
92  const vec_int4 i0 = {v ,0,0,0};
93  const vec_int4 i1 = {v+1,0,0,0};
94  const vec_int4 i2 = {v+2,0,0,0};
95  const vec_int4 i3 = {v+3,0,0,0};
96  vec_uint4 retGt01 = spu_cmpgt(p0,p1);
97  vec_float4 pmax01 = spu_sel(p1,p0,retGt01);
98  vec_int4 imax01 = spu_sel(i1,i0,retGt01);
99  vec_uint4 retGt23 = spu_cmpgt(p2,p3);
100  vec_float4 pmax23 = spu_sel(p3,p2,retGt23);
101  vec_int4 imax23 = spu_sel(i3,i2,retGt23);
102  vec_uint4 retGt0123 = spu_cmpgt(pmax01,pmax23);
103  vec_float4 pmax0123 = spu_sel(pmax23,pmax01,retGt0123);
104  vec_int4 imax0123 = spu_sel(imax23,imax01,retGt0123);
105  vec_uint4 retGtMax = spu_cmpgt(v_distMax,pmax0123);
106  v_distMax = spu_sel(pmax0123,v_distMax,retGtMax);
107  v_idxMax = spu_sel(imax0123,v_idxMax,retGtMax);
108  }
109  for(;v<(int)numverts;v++) {
110  vec_float4 p = vec_dot3(points[v].get128(),localDir.get128());
111  const vec_int4 i = {v,0,0,0};
112  vec_uint4 retGtMax = spu_cmpgt(v_distMax,p);
113  v_distMax = spu_sel(p,v_distMax,retGtMax);
114  v_idxMax = spu_sel(i,v_idxMax,retGtMax);
115  }
116  int ptIndex = spu_extract(v_idxMax,0);
117  const btVector3& supVec= points[ptIndex] * localScaling;
118  return supVec;
119 #else
120 
121  btScalar maxDot;
122  long ptIndex = vec.maxDot( points, numPoints, maxDot);
123  btAssert(ptIndex >= 0);
124  if (ptIndex<0)
125  {
126  ptIndex = 0;
127  }
128  btVector3 supVec = points[ptIndex] * localScaling;
129  return supVec;
130 #endif //__SPU__
131 }
132 
134 {
135  switch (m_shapeType)
136  {
138  {
139  return btVector3(0,0,0);
140  }
141  case BOX_SHAPE_PROXYTYPE:
142  {
143  btBoxShape* convexShape = (btBoxShape*)this;
144  const btVector3& halfExtents = convexShape->getImplicitShapeDimensions();
145 
146 #if defined( __APPLE__ ) && (defined( BT_USE_SSE )||defined( BT_USE_NEON ))
147  #if defined( BT_USE_SSE )
148  return btVector3( _mm_xor_ps( _mm_and_ps( localDir.mVec128, (__m128){-0.0f, -0.0f, -0.0f, -0.0f }), halfExtents.mVec128 ));
149  #elif defined( BT_USE_NEON )
150  return btVector3( (float32x4_t) (((uint32x4_t) localDir.mVec128 & (uint32x4_t){ 0x80000000, 0x80000000, 0x80000000, 0x80000000}) ^ (uint32x4_t) halfExtents.mVec128 ));
151  #else
152  #error unknown vector arch
153  #endif
154 #else
155  return btVector3(btFsels(localDir.x(), halfExtents.x(), -halfExtents.x()),
156  btFsels(localDir.y(), halfExtents.y(), -halfExtents.y()),
157  btFsels(localDir.z(), halfExtents.z(), -halfExtents.z()));
158 #endif
159  }
161  {
162  btTriangleShape* triangleShape = (btTriangleShape*)this;
163  btVector3 dir(localDir.getX(),localDir.getY(),localDir.getZ());
164  btVector3* vertices = &triangleShape->m_vertices1[0];
165  btVector3 dots = dir.dot3(vertices[0], vertices[1], vertices[2]);
166  btVector3 sup = vertices[dots.maxAxis()];
167  return btVector3(sup.getX(),sup.getY(),sup.getZ());
168  }
170  {
171  btCylinderShape* cylShape = (btCylinderShape*)this;
172  //mapping of halfextents/dimension onto radius/height depends on how cylinder local orientation is (upAxis)
173 
174  btVector3 halfExtents = cylShape->getImplicitShapeDimensions();
175  btVector3 v(localDir.getX(),localDir.getY(),localDir.getZ());
176  int cylinderUpAxis = cylShape->getUpAxis();
177  int XX(1),YY(0),ZZ(2);
178 
179  switch (cylinderUpAxis)
180  {
181  case 0:
182  {
183  XX = 1;
184  YY = 0;
185  ZZ = 2;
186  }
187  break;
188  case 1:
189  {
190  XX = 0;
191  YY = 1;
192  ZZ = 2;
193  }
194  break;
195  case 2:
196  {
197  XX = 0;
198  YY = 2;
199  ZZ = 1;
200 
201  }
202  break;
203  default:
204  btAssert(0);
205  break;
206  };
207 
208  btScalar radius = halfExtents[XX];
209  btScalar halfHeight = halfExtents[cylinderUpAxis];
210 
211  btVector3 tmp;
212  btScalar d ;
213 
214  btScalar s = btSqrt(v[XX] * v[XX] + v[ZZ] * v[ZZ]);
215  if (s != btScalar(0.0))
216  {
217  d = radius / s;
218  tmp[XX] = v[XX] * d;
219  tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
220  tmp[ZZ] = v[ZZ] * d;
221  return btVector3(tmp.getX(),tmp.getY(),tmp.getZ());
222  } else {
223  tmp[XX] = radius;
224  tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
225  tmp[ZZ] = btScalar(0.0);
226  return btVector3(tmp.getX(),tmp.getY(),tmp.getZ());
227  }
228  }
230  {
231  btVector3 vec0(localDir.getX(),localDir.getY(),localDir.getZ());
232 
233  btCapsuleShape* capsuleShape = (btCapsuleShape*)this;
234  btScalar halfHeight = capsuleShape->getHalfHeight();
235  int capsuleUpAxis = capsuleShape->getUpAxis();
236 
237  btVector3 supVec(0,0,0);
238 
239  btScalar maxDot(btScalar(-BT_LARGE_FLOAT));
240 
241  btVector3 vec = vec0;
242  btScalar lenSqr = vec.length2();
243  if (lenSqr < SIMD_EPSILON*SIMD_EPSILON)
244  {
245  vec.setValue(1,0,0);
246  } else
247  {
248  btScalar rlen = btScalar(1.) / btSqrt(lenSqr );
249  vec *= rlen;
250  }
251  btVector3 vtx;
252  btScalar newDot;
253  {
254  btVector3 pos(0,0,0);
255  pos[capsuleUpAxis] = halfHeight;
256 
257  vtx = pos;
258  newDot = vec.dot(vtx);
259 
260 
261  if (newDot > maxDot)
262  {
263  maxDot = newDot;
264  supVec = vtx;
265  }
266  }
267  {
268  btVector3 pos(0,0,0);
269  pos[capsuleUpAxis] = -halfHeight;
270 
271  vtx = pos;
272  newDot = vec.dot(vtx);
273  if (newDot > maxDot)
274  {
275  maxDot = newDot;
276  supVec = vtx;
277  }
278  }
279  return btVector3(supVec.getX(),supVec.getY(),supVec.getZ());
280  }
282  {
283  btConvexPointCloudShape* convexPointCloudShape = (btConvexPointCloudShape*)this;
284  btVector3* points = convexPointCloudShape->getUnscaledPoints ();
285  int numPoints = convexPointCloudShape->getNumPoints ();
286  return convexHullSupport (localDir, points, numPoints,convexPointCloudShape->getLocalScalingNV());
287  }
289  {
290  btConvexHullShape* convexHullShape = (btConvexHullShape*)this;
291  btVector3* points = convexHullShape->getUnscaledPoints();
292  int numPoints = convexHullShape->getNumPoints ();
293  return convexHullSupport (localDir, points, numPoints,convexHullShape->getLocalScalingNV());
294  }
295  default:
296 #ifndef __SPU__
297  return this->localGetSupportingVertexWithoutMargin (localDir);
298 #else
299  btAssert (0);
300 #endif
301  }
302 
303  // should never reach here
304  btAssert (0);
305  return btVector3 (btScalar(0.0f), btScalar(0.0f), btScalar(0.0f));
306 }
307 
309 {
310  btVector3 localDirNorm = localDir;
311  if (localDirNorm .length2() < (SIMD_EPSILON*SIMD_EPSILON))
312  {
313  localDirNorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.));
314  }
315  localDirNorm.normalize ();
316 
317  return localGetSupportVertexWithoutMarginNonVirtual(localDirNorm)+ getMarginNonVirtual() * localDirNorm;
318 }
319 
320 /* TODO: This should be bumped up to btCollisionShape () */
322 {
323  switch (m_shapeType)
324  {
326  {
327  btSphereShape* sphereShape = (btSphereShape*)this;
328  return sphereShape->getRadius ();
329  }
330  case BOX_SHAPE_PROXYTYPE:
331  {
332  btBoxShape* convexShape = (btBoxShape*)this;
333  return convexShape->getMarginNV ();
334  }
336  {
337  btTriangleShape* triangleShape = (btTriangleShape*)this;
338  return triangleShape->getMarginNV ();
339  }
341  {
342  btCylinderShape* cylShape = (btCylinderShape*)this;
343  return cylShape->getMarginNV();
344  }
346  {
347  btConeShape* conShape = (btConeShape*)this;
348  return conShape->getMarginNV();
349  }
351  {
352  btCapsuleShape* capsuleShape = (btCapsuleShape*)this;
353  return capsuleShape->getMarginNV();
354  }
356  /* fall through */
358  {
359  btPolyhedralConvexShape* convexHullShape = (btPolyhedralConvexShape*)this;
360  return convexHullShape->getMarginNV();
361  }
362  default:
363 #ifndef __SPU__
364  return this->getMargin ();
365 #else
366  btAssert (0);
367 #endif
368  }
369 
370  // should never reach here
371  btAssert (0);
372  return btScalar(0.0f);
373 }
374 #ifndef __SPU__
375 void btConvexShape::getAabbNonVirtual (const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
376 {
377  switch (m_shapeType)
378  {
380  {
381  btSphereShape* sphereShape = (btSphereShape*)this;
382  btScalar radius = sphereShape->getImplicitShapeDimensions().getX();// * convexShape->getLocalScaling().getX();
383  btScalar margin = radius + sphereShape->getMarginNonVirtual();
384  const btVector3& center = t.getOrigin();
385  btVector3 extent(margin,margin,margin);
386  aabbMin = center - extent;
387  aabbMax = center + extent;
388  }
389  break;
391  /* fall through */
392  case BOX_SHAPE_PROXYTYPE:
393  {
394  btBoxShape* convexShape = (btBoxShape*)this;
395  btScalar margin=convexShape->getMarginNonVirtual();
396  btVector3 halfExtents = convexShape->getImplicitShapeDimensions();
397  halfExtents += btVector3(margin,margin,margin);
398  btMatrix3x3 abs_b = t.getBasis().absolute();
399  btVector3 center = t.getOrigin();
400  btVector3 extent = halfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
401 
402  aabbMin = center - extent;
403  aabbMax = center + extent;
404  break;
405  }
407  {
408  btTriangleShape* triangleShape = (btTriangleShape*)this;
409  btScalar margin = triangleShape->getMarginNonVirtual();
410  for (int i=0;i<3;i++)
411  {
412  btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.));
413  vec[i] = btScalar(1.);
414 
416 
417  btVector3 tmp = t(sv);
418  aabbMax[i] = tmp[i]+margin;
419  vec[i] = btScalar(-1.);
421  aabbMin[i] = tmp[i]-margin;
422  }
423  }
424  break;
426  {
427  btCapsuleShape* capsuleShape = (btCapsuleShape*)this;
428  btVector3 halfExtents(capsuleShape->getRadius(),capsuleShape->getRadius(),capsuleShape->getRadius());
429  int m_upAxis = capsuleShape->getUpAxis();
430  halfExtents[m_upAxis] = capsuleShape->getRadius() + capsuleShape->getHalfHeight();
431  btMatrix3x3 abs_b = t.getBasis().absolute();
432  btVector3 center = t.getOrigin();
433  btVector3 extent = halfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
434  aabbMin = center - extent;
435  aabbMax = center + extent;
436  }
437  break;
440  {
442  btScalar margin = convexHullShape->getMarginNonVirtual();
443  convexHullShape->getNonvirtualAabb (t, aabbMin, aabbMax, margin);
444  }
445  break;
446  default:
447 #ifndef __SPU__
448  this->getAabb (t, aabbMin, aabbMax);
449 #else
450  btAssert (0);
451 #endif
452  break;
453  }
454 
455  // should never reach here
456  btAssert (0);
457 }
458 
459 #endif //__SPU__
#define SIMD_EPSILON
Definition: btScalar.h:521
const btVector3 & getLocalScalingNV() const
#define BT_LARGE_FLOAT
Definition: btScalar.h:294
virtual btVector3 localGetSupportingVertex(const btVector3 &vec) const =0
void setValue(const btScalar &_x, const btScalar &_y, const btScalar &_z)
Definition: btVector3.h:652
void getNonvirtualAabb(const btTransform &trans, btVector3 &aabbMin, btVector3 &aabbMax, btScalar margin) const
static btVector3 convexHullSupport(const btVector3 &localDirOrg, const btVector3 *points, int numPoints, const btVector3 &localScaling)
The btCapsuleShape represents a capsule around the Y axis, there is also the btCapsuleShapeX aligned ...
btScalar btSqrt(btScalar y)
Definition: btScalar.h:444
#define btAssert(x)
Definition: btScalar.h:131
long maxDot(const btVector3 *array, long array_count, btScalar &dotOut) const
returns index of maximum dot product between this and vectors in array[]
Definition: btVector3.h:1015
btVector3 localGetSupportVertexWithoutMarginNonVirtual(const btVector3 &vec) const
The btSphereShape implements an implicit sphere, centered around a local origin with radius...
Definition: btSphereShape.h:22
btScalar getRadius() const
int getNumPoints() const
virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3 &vec) const =0
btScalar getMarginNonVirtual() const
int getUpAxis() const
btScalar dot(const btVector3 &v) const
Return the dot product.
Definition: btVector3.h:235
btVector3 & normalize()
Normalize this vector x^2 + y^2 + z^2 = 1.
Definition: btVector3.h:309
const btScalar & x() const
Return the x value.
Definition: btVector3.h:587
const btScalar & getZ() const
Return the z value.
Definition: btVector3.h:577
btVector3 * getUnscaledPoints()
virtual ~btConvexShape()
btVector3 & getOrigin()
Return the origin vector translation.
Definition: btTransform.h:117
void getAabb(const btTransform &t, btVector3 &aabbMin, btVector3 &aabbMax) const =0
getAabb&#39;s default implementation is brute force, expected derived classes to implement a fast dedicat...
btMatrix3x3 absolute() const
Return the matrix with all values non negative.
Definition: btMatrix3x3.h:1009
int getUpAxis() const
The btConeShape implements a cone shape primitive, centered around the origin and aligned with the Y ...
Definition: btConeShape.h:23
void getAabbNonVirtual(const btTransform &t, btVector3 &aabbMin, btVector3 &aabbMax) const
const btScalar & getY() const
Return the y value.
Definition: btVector3.h:575
btMatrix3x3 & getBasis()
Return the basis matrix for the rotation.
Definition: btTransform.h:112
const btScalar & getX() const
Return the x value.
Definition: btVector3.h:573
The btPolyhedralConvexShape is an internal interface class for polyhedral convex shapes.
btVector3 localGetSupportVertexNonVirtual(const btVector3 &vec) const
virtual btScalar getMargin() const =0
const btScalar & y() const
Return the y value.
Definition: btVector3.h:589
The btBoxShape is a box primitive around the origin, its sides axis aligned with length specified by ...
Definition: btBoxShape.h:26
#define btFsels(a, b, c)
Definition: btScalar.h:581
btVector3 can be used to represent 3D points and vectors.
Definition: btVector3.h:83
btScalar length2() const
Return the length of the vector squared.
Definition: btVector3.h:257
btScalar getMarginNV() const
The btTransform class supports rigid transforms with only translation and rotation and no scaling/she...
Definition: btTransform.h:34
The btPolyhedralConvexAabbCachingShape adds aabb caching to the btPolyhedralConvexShape.
const btVector3 & getImplicitShapeDimensions() const
The btCylinderShape class implements a cylinder shape primitive, centered around the origin...
btVector3 dot3(const btVector3 &v0, const btVector3 &v1, const btVector3 &v2) const
Definition: btVector3.h:733
btScalar getRadius() const
Definition: btSphereShape.h:50
The btMatrix3x3 class implements a 3x3 rotation matrix, to perform linear algebra in combination with...
Definition: btMatrix3x3.h:48
The btConvexHullShape implements an implicit convex hull of an array of vertices. ...
The btConvexPointCloudShape implements an implicit convex hull of an array of vertices.
btScalar getHalfHeight() const
btVector3 m_vertices1[3]
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
Definition: btScalar.h:292
btConvexShape()
not supported on IBM SDK, until we fix the alignment of btVector3
int maxAxis() const
Return the axis with the largest value Note return values are 0,1,2 for x, y, or z.
Definition: btVector3.h:487
virtual void project(const btTransform &trans, const btVector3 &dir, btScalar &minProj, btScalar &maxProj, btVector3 &witnesPtMin, btVector3 &witnesPtMax) const
const btScalar & z() const
Return the z value.
Definition: btVector3.h:591