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) 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 
60  if(min>max)
61  {
62  btScalar tmp = min;
63  min = max;
64  max = tmp;
65  }
66 }
67 
68 
69 static btVector3 convexHullSupport (const btVector3& localDirOrg, const btVector3* points, int numPoints, const btVector3& localScaling)
70 {
71 
72  btVector3 vec = localDirOrg * localScaling;
73 
74 #if defined (__CELLOS_LV2__) && defined (__SPU__)
75 
76  btVector3 localDir = vec;
77 
78  vec_float4 v_distMax = {-FLT_MAX,0,0,0};
79  vec_int4 v_idxMax = {-999,0,0,0};
80  int v=0;
81  int numverts = numPoints;
82 
83  for(;v<(int)numverts-4;v+=4) {
84  vec_float4 p0 = vec_dot3(points[v ].get128(),localDir.get128());
85  vec_float4 p1 = vec_dot3(points[v+1].get128(),localDir.get128());
86  vec_float4 p2 = vec_dot3(points[v+2].get128(),localDir.get128());
87  vec_float4 p3 = vec_dot3(points[v+3].get128(),localDir.get128());
88  const vec_int4 i0 = {v ,0,0,0};
89  const vec_int4 i1 = {v+1,0,0,0};
90  const vec_int4 i2 = {v+2,0,0,0};
91  const vec_int4 i3 = {v+3,0,0,0};
92  vec_uint4 retGt01 = spu_cmpgt(p0,p1);
93  vec_float4 pmax01 = spu_sel(p1,p0,retGt01);
94  vec_int4 imax01 = spu_sel(i1,i0,retGt01);
95  vec_uint4 retGt23 = spu_cmpgt(p2,p3);
96  vec_float4 pmax23 = spu_sel(p3,p2,retGt23);
97  vec_int4 imax23 = spu_sel(i3,i2,retGt23);
98  vec_uint4 retGt0123 = spu_cmpgt(pmax01,pmax23);
99  vec_float4 pmax0123 = spu_sel(pmax23,pmax01,retGt0123);
100  vec_int4 imax0123 = spu_sel(imax23,imax01,retGt0123);
101  vec_uint4 retGtMax = spu_cmpgt(v_distMax,pmax0123);
102  v_distMax = spu_sel(pmax0123,v_distMax,retGtMax);
103  v_idxMax = spu_sel(imax0123,v_idxMax,retGtMax);
104  }
105  for(;v<(int)numverts;v++) {
106  vec_float4 p = vec_dot3(points[v].get128(),localDir.get128());
107  const vec_int4 i = {v,0,0,0};
108  vec_uint4 retGtMax = spu_cmpgt(v_distMax,p);
109  v_distMax = spu_sel(p,v_distMax,retGtMax);
110  v_idxMax = spu_sel(i,v_idxMax,retGtMax);
111  }
112  int ptIndex = spu_extract(v_idxMax,0);
113  const btVector3& supVec= points[ptIndex] * localScaling;
114  return supVec;
115 #else
116 
117  btScalar maxDot;
118  long ptIndex = vec.maxDot( points, numPoints, maxDot);
119  btAssert(ptIndex >= 0);
120  btVector3 supVec = points[ptIndex] * localScaling;
121  return supVec;
122 #endif //__SPU__
123 }
124 
126 {
127  switch (m_shapeType)
128  {
130  {
131  return btVector3(0,0,0);
132  }
133  case BOX_SHAPE_PROXYTYPE:
134  {
135  btBoxShape* convexShape = (btBoxShape*)this;
136  const btVector3& halfExtents = convexShape->getImplicitShapeDimensions();
137 
138 #if defined( __APPLE__ ) && (defined( BT_USE_SSE )||defined( BT_USE_NEON ))
139  #if defined( BT_USE_SSE )
140  return btVector3( _mm_xor_ps( _mm_and_ps( localDir.mVec128, (__m128){-0.0f, -0.0f, -0.0f, -0.0f }), halfExtents.mVec128 ));
141  #elif defined( BT_USE_NEON )
142  return btVector3( (float32x4_t) (((uint32x4_t) localDir.mVec128 & (uint32x4_t){ 0x80000000, 0x80000000, 0x80000000, 0x80000000}) ^ (uint32x4_t) halfExtents.mVec128 ));
143  #else
144  #error unknown vector arch
145  #endif
146 #else
147  return btVector3(btFsels(localDir.x(), halfExtents.x(), -halfExtents.x()),
148  btFsels(localDir.y(), halfExtents.y(), -halfExtents.y()),
149  btFsels(localDir.z(), halfExtents.z(), -halfExtents.z()));
150 #endif
151  }
153  {
154  btTriangleShape* triangleShape = (btTriangleShape*)this;
155  btVector3 dir(localDir.getX(),localDir.getY(),localDir.getZ());
156  btVector3* vertices = &triangleShape->m_vertices1[0];
157  btVector3 dots = dir.dot3(vertices[0], vertices[1], vertices[2]);
158  btVector3 sup = vertices[dots.maxAxis()];
159  return btVector3(sup.getX(),sup.getY(),sup.getZ());
160  }
162  {
163  btCylinderShape* cylShape = (btCylinderShape*)this;
164  //mapping of halfextents/dimension onto radius/height depends on how cylinder local orientation is (upAxis)
165 
166  btVector3 halfExtents = cylShape->getImplicitShapeDimensions();
167  btVector3 v(localDir.getX(),localDir.getY(),localDir.getZ());
168  int cylinderUpAxis = cylShape->getUpAxis();
169  int XX(1),YY(0),ZZ(2);
170 
171  switch (cylinderUpAxis)
172  {
173  case 0:
174  {
175  XX = 1;
176  YY = 0;
177  ZZ = 2;
178  }
179  break;
180  case 1:
181  {
182  XX = 0;
183  YY = 1;
184  ZZ = 2;
185  }
186  break;
187  case 2:
188  {
189  XX = 0;
190  YY = 2;
191  ZZ = 1;
192 
193  }
194  break;
195  default:
196  btAssert(0);
197  break;
198  };
199 
200  btScalar radius = halfExtents[XX];
201  btScalar halfHeight = halfExtents[cylinderUpAxis];
202 
203  btVector3 tmp;
204  btScalar d ;
205 
206  btScalar s = btSqrt(v[XX] * v[XX] + v[ZZ] * v[ZZ]);
207  if (s != btScalar(0.0))
208  {
209  d = radius / s;
210  tmp[XX] = v[XX] * d;
211  tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
212  tmp[ZZ] = v[ZZ] * d;
213  return btVector3(tmp.getX(),tmp.getY(),tmp.getZ());
214  } else {
215  tmp[XX] = radius;
216  tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
217  tmp[ZZ] = btScalar(0.0);
218  return btVector3(tmp.getX(),tmp.getY(),tmp.getZ());
219  }
220  }
222  {
223  btVector3 vec0(localDir.getX(),localDir.getY(),localDir.getZ());
224 
225  btCapsuleShape* capsuleShape = (btCapsuleShape*)this;
226  btScalar halfHeight = capsuleShape->getHalfHeight();
227  int capsuleUpAxis = capsuleShape->getUpAxis();
228 
229  btScalar radius = capsuleShape->getRadius();
230  btVector3 supVec(0,0,0);
231 
232  btScalar maxDot(btScalar(-BT_LARGE_FLOAT));
233 
234  btVector3 vec = vec0;
235  btScalar lenSqr = vec.length2();
236  if (lenSqr < btScalar(0.0001))
237  {
238  vec.setValue(1,0,0);
239  } else
240  {
241  btScalar rlen = btScalar(1.) / btSqrt(lenSqr );
242  vec *= rlen;
243  }
244  btVector3 vtx;
245  btScalar newDot;
246  {
247  btVector3 pos(0,0,0);
248  pos[capsuleUpAxis] = halfHeight;
249 
250  //vtx = pos +vec*(radius);
251  vtx = pos +vec*(radius) - vec * capsuleShape->getMarginNV();
252  newDot = vec.dot(vtx);
253 
254 
255  if (newDot > maxDot)
256  {
257  maxDot = newDot;
258  supVec = vtx;
259  }
260  }
261  {
262  btVector3 pos(0,0,0);
263  pos[capsuleUpAxis] = -halfHeight;
264 
265  //vtx = pos +vec*(radius);
266  vtx = pos +vec*(radius) - vec * capsuleShape->getMarginNV();
267  newDot = vec.dot(vtx);
268  if (newDot > maxDot)
269  {
270  maxDot = newDot;
271  supVec = vtx;
272  }
273  }
274  return btVector3(supVec.getX(),supVec.getY(),supVec.getZ());
275  }
277  {
278  btConvexPointCloudShape* convexPointCloudShape = (btConvexPointCloudShape*)this;
279  btVector3* points = convexPointCloudShape->getUnscaledPoints ();
280  int numPoints = convexPointCloudShape->getNumPoints ();
281  return convexHullSupport (localDir, points, numPoints,convexPointCloudShape->getLocalScalingNV());
282  }
284  {
285  btConvexHullShape* convexHullShape = (btConvexHullShape*)this;
286  btVector3* points = convexHullShape->getUnscaledPoints();
287  int numPoints = convexHullShape->getNumPoints ();
288  return convexHullSupport (localDir, points, numPoints,convexHullShape->getLocalScalingNV());
289  }
290  default:
291 #ifndef __SPU__
292  return this->localGetSupportingVertexWithoutMargin (localDir);
293 #else
294  btAssert (0);
295 #endif
296  }
297 
298  // should never reach here
299  btAssert (0);
300  return btVector3 (btScalar(0.0f), btScalar(0.0f), btScalar(0.0f));
301 }
302 
304 {
305  btVector3 localDirNorm = localDir;
306  if (localDirNorm .length2() < (SIMD_EPSILON*SIMD_EPSILON))
307  {
308  localDirNorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.));
309  }
310  localDirNorm.normalize ();
311 
312  return localGetSupportVertexWithoutMarginNonVirtual(localDirNorm)+ getMarginNonVirtual() * localDirNorm;
313 }
314 
315 /* TODO: This should be bumped up to btCollisionShape () */
317 {
318  switch (m_shapeType)
319  {
321  {
322  btSphereShape* sphereShape = (btSphereShape*)this;
323  return sphereShape->getRadius ();
324  }
325  case BOX_SHAPE_PROXYTYPE:
326  {
327  btBoxShape* convexShape = (btBoxShape*)this;
328  return convexShape->getMarginNV ();
329  }
331  {
332  btTriangleShape* triangleShape = (btTriangleShape*)this;
333  return triangleShape->getMarginNV ();
334  }
336  {
337  btCylinderShape* cylShape = (btCylinderShape*)this;
338  return cylShape->getMarginNV();
339  }
341  {
342  btConeShape* conShape = (btConeShape*)this;
343  return conShape->getMarginNV();
344  }
346  {
347  btCapsuleShape* capsuleShape = (btCapsuleShape*)this;
348  return capsuleShape->getMarginNV();
349  }
351  /* fall through */
353  {
354  btPolyhedralConvexShape* convexHullShape = (btPolyhedralConvexShape*)this;
355  return convexHullShape->getMarginNV();
356  }
357  default:
358 #ifndef __SPU__
359  return this->getMargin ();
360 #else
361  btAssert (0);
362 #endif
363  }
364 
365  // should never reach here
366  btAssert (0);
367  return btScalar(0.0f);
368 }
369 #ifndef __SPU__
370 void btConvexShape::getAabbNonVirtual (const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
371 {
372  switch (m_shapeType)
373  {
375  {
376  btSphereShape* sphereShape = (btSphereShape*)this;
377  btScalar radius = sphereShape->getImplicitShapeDimensions().getX();// * convexShape->getLocalScaling().getX();
378  btScalar margin = radius + sphereShape->getMarginNonVirtual();
379  const btVector3& center = t.getOrigin();
380  btVector3 extent(margin,margin,margin);
381  aabbMin = center - extent;
382  aabbMax = center + extent;
383  }
384  break;
386  /* fall through */
387  case BOX_SHAPE_PROXYTYPE:
388  {
389  btBoxShape* convexShape = (btBoxShape*)this;
390  btScalar margin=convexShape->getMarginNonVirtual();
391  btVector3 halfExtents = convexShape->getImplicitShapeDimensions();
392  halfExtents += btVector3(margin,margin,margin);
393  btMatrix3x3 abs_b = t.getBasis().absolute();
394  btVector3 center = t.getOrigin();
395  btVector3 extent = halfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
396 
397  aabbMin = center - extent;
398  aabbMax = center + extent;
399  break;
400  }
402  {
403  btTriangleShape* triangleShape = (btTriangleShape*)this;
404  btScalar margin = triangleShape->getMarginNonVirtual();
405  for (int i=0;i<3;i++)
406  {
407  btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.));
408  vec[i] = btScalar(1.);
409 
411 
412  btVector3 tmp = t(sv);
413  aabbMax[i] = tmp[i]+margin;
414  vec[i] = btScalar(-1.);
416  aabbMin[i] = tmp[i]-margin;
417  }
418  }
419  break;
421  {
422  btCapsuleShape* capsuleShape = (btCapsuleShape*)this;
423  btVector3 halfExtents(capsuleShape->getRadius(),capsuleShape->getRadius(),capsuleShape->getRadius());
424  int m_upAxis = capsuleShape->getUpAxis();
425  halfExtents[m_upAxis] = capsuleShape->getRadius() + capsuleShape->getHalfHeight();
426  halfExtents += btVector3(capsuleShape->getMarginNonVirtual(),capsuleShape->getMarginNonVirtual(),capsuleShape->getMarginNonVirtual());
427  btMatrix3x3 abs_b = t.getBasis().absolute();
428  btVector3 center = t.getOrigin();
429  btVector3 extent = halfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
430  aabbMin = center - extent;
431  aabbMax = center + extent;
432  }
433  break;
436  {
438  btScalar margin = convexHullShape->getMarginNonVirtual();
439  convexHullShape->getNonvirtualAabb (t, aabbMin, aabbMax, margin);
440  }
441  break;
442  default:
443 #ifndef __SPU__
444  this->getAabb (t, aabbMin, aabbMax);
445 #else
446  btAssert (0);
447 #endif
448  break;
449  }
450 
451  // should never reach here
452  btAssert (0);
453 }
454 
455 #endif //__SPU__
#define SIMD_EPSILON
Definition: btScalar.h:448
const btVector3 & getLocalScalingNV() const
#define BT_LARGE_FLOAT
Definition: btScalar.h:268
virtual btVector3 localGetSupportingVertex(const btVector3 &vec) const =0
__m128 vec_float4
void setValue(const btScalar &_x, const btScalar &_y, const btScalar &_z)
Definition: btVector3.h:640
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)
__m128 vec_int4
The btCapsuleShape represents a capsule around the Y axis, there is also the btCapsuleShapeX aligned ...
btScalar btSqrt(btScalar y)
Definition: btScalar.h:387
#define btAssert(x)
Definition: btScalar.h:101
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:1000
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
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:297
const btScalar & x() const
Return the x value.
Definition: btVector3.h:575
const btScalar & getZ() const
Return the z value.
Definition: btVector3.h:565
virtual void project(const btTransform &trans, const btVector3 &dir, btScalar &min, btScalar &max) const
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'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:959
int getUpAxis() const
The btConeShape implements a cone shape primitive, centered around the origin and aligned with the Y ...
Definition: btConeShape.h:23
static float max(float a, float b)
void getAabbNonVirtual(const btTransform &t, btVector3 &aabbMin, btVector3 &aabbMax) const
const btScalar & getY() const
Return the y value.
Definition: btVector3.h:563
btMatrix3x3 & getBasis()
Return the basis matrix for the rotation.
Definition: btTransform.h:112
const btScalar & getX() const
Return the x value.
Definition: btVector3.h:561
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:577
static float min(float a, float b)
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:493
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
__m128 vec_uint4
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:718
btScalar getRadius() const
Definition: btSphereShape.h:47
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:266
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:475
const btScalar & z() const
Return the z value.
Definition: btVector3.h:579