Bullet Collision Detection & Physics Library
btCompoundShape.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 #include "btCompoundShape.h"
17 #include "btCollisionShape.h"
20 
21 btCompoundShape::btCompoundShape(bool enableDynamicAabbTree)
24 m_dynamicAabbTree(0),
25 m_updateRevision(1),
26 m_collisionMargin(btScalar(0.)),
27 m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.))
28 {
30 
31  if (enableDynamicAabbTree)
32  {
33  void* mem = btAlignedAlloc(sizeof(btDbvt),16);
34  m_dynamicAabbTree = new(mem) btDbvt();
36  }
37 }
38 
39 
41 {
43  {
46  }
47 }
48 
50 {
52  //m_childTransforms.push_back(localTransform);
53  //m_childShapes.push_back(shape);
55  child.m_node = 0;
56  child.m_transform = localTransform;
57  child.m_childShape = shape;
58  child.m_childShapeType = shape->getShapeType();
59  child.m_childMargin = shape->getMargin();
60 
61 
62  //extend the local aabbMin/aabbMax
63  btVector3 localAabbMin,localAabbMax;
64  shape->getAabb(localTransform,localAabbMin,localAabbMax);
65  for (int i=0;i<3;i++)
66  {
67  if (m_localAabbMin[i] > localAabbMin[i])
68  {
69  m_localAabbMin[i] = localAabbMin[i];
70  }
71  if (m_localAabbMax[i] < localAabbMax[i])
72  {
73  m_localAabbMax[i] = localAabbMax[i];
74  }
75 
76  }
78  {
79  const btDbvtVolume bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax);
80  int index = m_children.size();
81  child.m_node = m_dynamicAabbTree->insert(bounds,(void*)index);
82  }
83 
84  m_children.push_back(child);
85 
86 }
87 
88 void btCompoundShape::updateChildTransform(int childIndex, const btTransform& newChildTransform,bool shouldRecalculateLocalAabb)
89 {
90  m_children[childIndex].m_transform = newChildTransform;
91 
93  {
95  btVector3 localAabbMin,localAabbMax;
96  m_children[childIndex].m_childShape->getAabb(newChildTransform,localAabbMin,localAabbMax);
97  ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax);
98  //int index = m_children.size()-1;
99  m_dynamicAabbTree->update(m_children[childIndex].m_node,bounds);
100  }
101 
102  if (shouldRecalculateLocalAabb)
103  {
105  }
106 }
107 
109 {
111  btAssert(childShapeIndex >=0 && childShapeIndex < m_children.size());
112  if (m_dynamicAabbTree)
113  {
114  m_dynamicAabbTree->remove(m_children[childShapeIndex].m_node);
115  }
116  m_children.swap(childShapeIndex,m_children.size()-1);
117  if (m_dynamicAabbTree)
118  m_children[childShapeIndex].m_node->dataAsInt = childShapeIndex;
120 
121 }
122 
123 
124 
126 {
128  // Find the children containing the shape specified, and remove those children.
129  //note: there might be multiple children using the same shape!
130  for(int i = m_children.size()-1; i >= 0 ; i--)
131  {
132  if(m_children[i].m_childShape == shape)
133  {
135  }
136  }
137 
138 
139 
141 }
142 
144 {
145  // Recalculate the local aabb
146  // Brute force, it iterates over all the shapes left.
147 
150 
151  //extend the local aabbMin/aabbMax
152  for (int j = 0; j < m_children.size(); j++)
153  {
154  btVector3 localAabbMin,localAabbMax;
155  m_children[j].m_childShape->getAabb(m_children[j].m_transform, localAabbMin, localAabbMax);
156  for (int i=0;i<3;i++)
157  {
158  if (m_localAabbMin[i] > localAabbMin[i])
159  m_localAabbMin[i] = localAabbMin[i];
160  if (m_localAabbMax[i] < localAabbMax[i])
161  m_localAabbMax[i] = localAabbMax[i];
162  }
163  }
164 }
165 
167 void btCompoundShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const
168 {
169  btVector3 localHalfExtents = btScalar(0.5)*(m_localAabbMax-m_localAabbMin);
170  btVector3 localCenter = btScalar(0.5)*(m_localAabbMax+m_localAabbMin);
171 
172  //avoid an illegal AABB when there are no children
173  if (!m_children.size())
174  {
175  localHalfExtents.setValue(0,0,0);
176  localCenter.setValue(0,0,0);
177  }
178  localHalfExtents += btVector3(getMargin(),getMargin(),getMargin());
179 
180 
181  btMatrix3x3 abs_b = trans.getBasis().absolute();
182 
183  btVector3 center = trans(localCenter);
184 
185  btVector3 extent = localHalfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
186  aabbMin = center-extent;
187  aabbMax = center+extent;
188 
189 }
190 
192 {
193  //approximation: take the inertia from the aabb for now
194  btTransform ident;
195  ident.setIdentity();
196  btVector3 aabbMin,aabbMax;
197  getAabb(ident,aabbMin,aabbMax);
198 
199  btVector3 halfExtents = (aabbMax-aabbMin)*btScalar(0.5);
200 
201  btScalar lx=btScalar(2.)*(halfExtents.x());
202  btScalar ly=btScalar(2.)*(halfExtents.y());
203  btScalar lz=btScalar(2.)*(halfExtents.z());
204 
205  inertia[0] = mass/(btScalar(12.0)) * (ly*ly + lz*lz);
206  inertia[1] = mass/(btScalar(12.0)) * (lx*lx + lz*lz);
207  inertia[2] = mass/(btScalar(12.0)) * (lx*lx + ly*ly);
208 
209 }
210 
211 
212 
213 
215 {
216  int n = m_children.size();
217 
218  btScalar totalMass = 0;
219  btVector3 center(0, 0, 0);
220  int k;
221 
222  for (k = 0; k < n; k++)
223  {
224  btAssert(masses[k]>0);
225  center += m_children[k].m_transform.getOrigin() * masses[k];
226  totalMass += masses[k];
227  }
228 
229  btAssert(totalMass>0);
230 
231  center /= totalMass;
232  principal.setOrigin(center);
233 
234  btMatrix3x3 tensor(0, 0, 0, 0, 0, 0, 0, 0, 0);
235  for ( k = 0; k < n; k++)
236  {
237  btVector3 i;
238  m_children[k].m_childShape->calculateLocalInertia(masses[k], i);
239 
240  const btTransform& t = m_children[k].m_transform;
241  btVector3 o = t.getOrigin() - center;
242 
243  //compute inertia tensor in coordinate system of compound shape
244  btMatrix3x3 j = t.getBasis().transpose();
245  j[0] *= i[0];
246  j[1] *= i[1];
247  j[2] *= i[2];
248  j = t.getBasis() * j;
249 
250  //add inertia tensor
251  tensor[0] += j[0];
252  tensor[1] += j[1];
253  tensor[2] += j[2];
254 
255  //compute inertia tensor of pointmass at o
256  btScalar o2 = o.length2();
257  j[0].setValue(o2, 0, 0);
258  j[1].setValue(0, o2, 0);
259  j[2].setValue(0, 0, o2);
260  j[0] += o * -o.x();
261  j[1] += o * -o.y();
262  j[2] += o * -o.z();
263 
264  //add inertia tensor of pointmass
265  tensor[0] += masses[k] * j[0];
266  tensor[1] += masses[k] * j[1];
267  tensor[2] += masses[k] * j[2];
268  }
269 
270  tensor.diagonalize(principal.getBasis(), btScalar(0.00001), 20);
271  inertia.setValue(tensor[0][0], tensor[1][1], tensor[2][2]);
272 }
273 
274 
275 
276 
277 
279 {
280 
281  for(int i = 0; i < m_children.size(); i++)
282  {
283  btTransform childTrans = getChildTransform(i);
284  btVector3 childScale = m_children[i].m_childShape->getLocalScaling();
285 // childScale = childScale * (childTrans.getBasis() * scaling);
286  childScale = childScale * scaling / m_localScaling;
287  m_children[i].m_childShape->setLocalScaling(childScale);
288  childTrans.setOrigin((childTrans.getOrigin()) * scaling / m_localScaling);
289  updateChildTransform(i, childTrans,false);
290  }
291 
292  m_localScaling = scaling;
294 
295 }
296 
297 
299 {
300  if ( !m_dynamicAabbTree )
301  {
302  void* mem = btAlignedAlloc(sizeof(btDbvt),16);
303  m_dynamicAabbTree = new(mem) btDbvt();
305 
306  for ( int index = 0; index < m_children.size(); index++ )
307  {
308  btCompoundShapeChild &child = m_children[index];
309 
310  //extend the local aabbMin/aabbMax
311  btVector3 localAabbMin,localAabbMax;
312  child.m_childShape->getAabb(child.m_transform,localAabbMin,localAabbMax);
313 
314  const btDbvtVolume bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax);
315  child.m_node = m_dynamicAabbTree->insert(bounds,(void*)index);
316  }
317  }
318 }
319 
320 
322 const char* btCompoundShape::serialize(void* dataBuffer, btSerializer* serializer) const
323 {
324 
325  btCompoundShapeData* shapeData = (btCompoundShapeData*) dataBuffer;
326  btCollisionShape::serialize(&shapeData->m_collisionShapeData, serializer);
327 
328  shapeData->m_collisionMargin = float(m_collisionMargin);
329  shapeData->m_numChildShapes = m_children.size();
330  shapeData->m_childShapePtr = 0;
331  if (shapeData->m_numChildShapes)
332  {
333  btChunk* chunk = serializer->allocate(sizeof(btCompoundShapeChildData),shapeData->m_numChildShapes);
335  shapeData->m_childShapePtr = (btCompoundShapeChildData*)serializer->getUniquePointer(memPtr);
336 
337  for (int i=0;i<shapeData->m_numChildShapes;i++,memPtr++)
338  {
339  memPtr->m_childMargin = float(m_children[i].m_childMargin);
340  memPtr->m_childShape = (btCollisionShapeData*)serializer->getUniquePointer(m_children[i].m_childShape);
341  //don't serialize shapes that already have been serialized
342  if (!serializer->findPointer(m_children[i].m_childShape))
343  {
344  btChunk* chunk = serializer->allocate(m_children[i].m_childShape->calculateSerializeBufferSize(),1);
345  const char* structType = m_children[i].m_childShape->serialize(chunk->m_oldPtr,serializer);
346  serializer->finalizeChunk(chunk,structType,BT_SHAPE_CODE,m_children[i].m_childShape);
347  }
348 
349  memPtr->m_childShapeType = m_children[i].m_childShapeType;
350  m_children[i].m_transform.serializeFloat(memPtr->m_transform);
351  }
352  serializer->finalizeChunk(chunk,"btCompoundShapeChildData",BT_ARRAY_CODE,chunk->m_oldPtr);
353  }
354  return "btCompoundShapeData";
355 }
356 
void setOrigin(const btVector3 &origin)
Set the translational element.
Definition: btTransform.h:150
virtual btScalar getMargin() const
btVector3 m_localAabbMax
void push_back(const T &_Val)
btCompoundShape(bool enableDynamicAabbTree=true)
virtual void recalculateLocalAabb()
Re-calculate the local Aabb.
btCompoundShapeChildData * m_childShapePtr
int getShapeType() const
#define BT_LARGE_FLOAT
Definition: btScalar.h:268
~btDbvt()
Definition: btDbvt.cpp:419
void setValue(const btScalar &_x, const btScalar &_y, const btScalar &_z)
Definition: btVector3.h:640
btDbvt * m_dynamicAabbTree
btAlignedObjectArray< btCompoundShapeChild > m_children
virtual void * getUniquePointer(void *oldPtr)=0
void setIdentity()
Set this transformation to the identity.
Definition: btTransform.h:172
#define btAssert(x)
Definition: btScalar.h:101
The btDbvt class implements a fast dynamic bounding volume tree based on axis aligned bounding boxes ...
Definition: btDbvt.h:194
The btCollisionShape class provides an interface for collision shapes that can be shared among btColl...
btDbvtNode * insert(const btDbvtVolume &box, void *data)
Definition: btDbvt.cpp:483
btCollisionShape * m_childShape
void addChildShape(const btTransform &localTransform, btCollisionShape *shape)
btCollisionShapeData m_collisionShapeData
struct btDbvtNode * m_node
virtual const char * serialize(void *dataBuffer, btSerializer *serializer) const
fills the dataBuffer and returns the struct name (and 0 on failure)
void calculatePrincipalAxisTransform(btScalar *masses, btTransform &principal, btVector3 &inertia) const
computes the exact moment of inertia and the transform from the coordinate system defined by the prin...
void swap(int index0, int index1)
virtual void getAabb(const btTransform &t, btVector3 &aabbMin, btVector3 &aabbMax) const =0
getAabb returns the axis aligned bounding box in the coordinate frame of the given transform t...
const btScalar & x() const
Return the x value.
Definition: btVector3.h:575
int m_updateRevision
increment m_updateRevision when adding/removing/replacing child shapes, so that some caches can be up...
btVector3 m_localAabbMin
void update(btDbvtNode *leaf, int lookahead=-1)
Definition: btDbvt.cpp:492
int size() const
return the number of elements in the array
virtual void getAabb(const btTransform &t, btVector3 &aabbMin, btVector3 &aabbMax) const
getAabb's default implementation is brute force, expected derived classes to implement a fast dedicat...
btVector3 & getOrigin()
Return the origin vector translation.
Definition: btTransform.h:117
btMatrix3x3 absolute() const
Return the matrix with all values non negative.
Definition: btMatrix3x3.h:959
void diagonalize(btMatrix3x3 &rot, btScalar threshold, int maxSteps)
diagonalizes this matrix by the Jacobi method.
Definition: btMatrix3x3.h:639
btTransform & getChildTransform(int index)
static btDbvtAabbMm FromMM(const btVector3 &mi, const btVector3 &mx)
Definition: btDbvt.h:411
btTransformFloatData m_transform
#define btAlignedFree(ptr)
btVector3 m_localScaling
btMatrix3x3 & getBasis()
Return the basis matrix for the rotation.
Definition: btTransform.h:112
void setValue(const btScalar &xx, const btScalar &xy, const btScalar &xz, const btScalar &yx, const btScalar &yy, const btScalar &yz, const btScalar &zx, const btScalar &zy, const btScalar &zz)
Set the values of the matrix explicitly (row major)
Definition: btMatrix3x3.h:198
btScalar m_collisionMargin
const btScalar & y() const
Return the y value.
Definition: btVector3.h:577
#define BT_ARRAY_CODE
Definition: btSerializer.h:121
btVector3 can be used to represent 3D points and vectors.
Definition: btVector3.h:83
#define ATTRIBUTE_ALIGNED16(a)
Definition: btScalar.h:59
btScalar length2() const
Return the length of the vector squared.
Definition: btVector3.h:257
virtual ~btCompoundShape()
void updateChildTransform(int childIndex, const btTransform &newChildTransform, bool shouldRecalculateLocalAabb=true)
set a new transform for a child, and update internal data structures (local aabb and dynamic tree) ...
The btTransform class supports rigid transforms with only translation and rotation and no scaling/she...
Definition: btTransform.h:34
virtual void finalizeChunk(btChunk *chunk, const char *structType, int chunkCode, void *oldPtr)=0
void createAabbTreeFromChildren()
do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 ...
btMatrix3x3 transpose() const
Return the transpose of the matrix.
Definition: btMatrix3x3.h:980
virtual btScalar getMargin() const =0
virtual void setLocalScaling(const btVector3 &scaling)
btVector3 dot3(const btVector3 &v0, const btVector3 &v1, const btVector3 &v2) const
Definition: btVector3.h:718
#define btAlignedAlloc(size, alignment)
The btMatrix3x3 class implements a 3x3 rotation matrix, to perform linear algebra in combination with...
Definition: btMatrix3x3.h:48
do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 ...
void removeChildShapeByIndex(int childShapeindex)
virtual void removeChildShape(btCollisionShape *shape)
Remove all children shapes that contain the specified shape.
virtual void * findPointer(void *oldPtr)=0
btCollisionShapeData * m_childShape
#define BT_SHAPE_CODE
Definition: btSerializer.h:120
void * m_oldPtr
Definition: btSerializer.h:56
do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64 ...
void remove(btDbvtNode *leaf)
Definition: btDbvt.cpp:555
virtual btChunk * allocate(size_t size, int numElements)=0
virtual void calculateLocalInertia(btScalar mass, btVector3 &inertia) const
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
Definition: btScalar.h:266
static btDbvtVolume bounds(const tNodeArray &leaves)
Definition: btDbvt.cpp:249
virtual const char * serialize(void *dataBuffer, btSerializer *serializer) const
fills the dataBuffer and returns the struct name (and 0 on failure)
const btScalar & z() const
Return the z value.
Definition: btVector3.h:579