btCompoundShape.cpp

Go to the documentation of this file.
00001 /*
00002 Bullet Continuous Collision Detection and Physics Library
00003 Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
00004 
00005 This software is provided 'as-is', without any express or implied warranty.
00006 In no event will the authors be held liable for any damages arising from the use of this software.
00007 Permission is granted to anyone to use this software for any purpose, 
00008 including commercial applications, and to alter it and redistribute it freely, 
00009 subject to the following restrictions:
00010 
00011 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.
00012 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
00013 3. This notice may not be removed or altered from any source distribution.
00014 */
00015 
00016 #include "btCompoundShape.h"
00017 #include "btCollisionShape.h"
00018 #include "BulletCollision/BroadphaseCollision/btDbvt.h"
00019 #include "LinearMath/btSerializer.h"
00020 
00021 btCompoundShape::btCompoundShape(bool enableDynamicAabbTree)
00022 : m_localAabbMin(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)),
00023 m_localAabbMax(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT)),
00024 m_dynamicAabbTree(0),
00025 m_updateRevision(1),
00026 m_collisionMargin(btScalar(0.)),
00027 m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.))
00028 {
00029         m_shapeType = COMPOUND_SHAPE_PROXYTYPE;
00030 
00031         if (enableDynamicAabbTree)
00032         {
00033                 void* mem = btAlignedAlloc(sizeof(btDbvt),16);
00034                 m_dynamicAabbTree = new(mem) btDbvt();
00035                 btAssert(mem==m_dynamicAabbTree);
00036         }
00037 }
00038 
00039 
00040 btCompoundShape::~btCompoundShape()
00041 {
00042         if (m_dynamicAabbTree)
00043         {
00044                 m_dynamicAabbTree->~btDbvt();
00045                 btAlignedFree(m_dynamicAabbTree);
00046         }
00047 }
00048 
00049 void    btCompoundShape::addChildShape(const btTransform& localTransform,btCollisionShape* shape)
00050 {
00051         m_updateRevision++;
00052         //m_childTransforms.push_back(localTransform);
00053         //m_childShapes.push_back(shape);
00054         btCompoundShapeChild child;
00055         child.m_transform = localTransform;
00056         child.m_childShape = shape;
00057         child.m_childShapeType = shape->getShapeType();
00058         child.m_childMargin = shape->getMargin();
00059 
00060         
00061         //extend the local aabbMin/aabbMax
00062         btVector3 localAabbMin,localAabbMax;
00063         shape->getAabb(localTransform,localAabbMin,localAabbMax);
00064         for (int i=0;i<3;i++)
00065         {
00066                 if (m_localAabbMin[i] > localAabbMin[i])
00067                 {
00068                         m_localAabbMin[i] = localAabbMin[i];
00069                 }
00070                 if (m_localAabbMax[i] < localAabbMax[i])
00071                 {
00072                         m_localAabbMax[i] = localAabbMax[i];
00073                 }
00074 
00075         }
00076         if (m_dynamicAabbTree)
00077         {
00078                 const btDbvtVolume      bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax);
00079                 int index = m_children.size();
00080                 child.m_node = m_dynamicAabbTree->insert(bounds,(void*)index);
00081         }
00082 
00083         m_children.push_back(child);
00084 
00085 }
00086 
00087 void    btCompoundShape::updateChildTransform(int childIndex, const btTransform& newChildTransform)
00088 {
00089         m_children[childIndex].m_transform = newChildTransform;
00090 
00091         if (m_dynamicAabbTree)
00092         {
00094                 btVector3 localAabbMin,localAabbMax;
00095                 m_children[childIndex].m_childShape->getAabb(newChildTransform,localAabbMin,localAabbMax);
00096                 ATTRIBUTE_ALIGNED16(btDbvtVolume)       bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax);
00097                 //int index = m_children.size()-1;
00098                 m_dynamicAabbTree->update(m_children[childIndex].m_node,bounds);
00099         }
00100 
00101         recalculateLocalAabb();
00102 }
00103 
00104 void btCompoundShape::removeChildShapeByIndex(int childShapeIndex)
00105 {
00106         m_updateRevision++;
00107         btAssert(childShapeIndex >=0 && childShapeIndex < m_children.size());
00108         if (m_dynamicAabbTree)
00109         {
00110                 m_dynamicAabbTree->remove(m_children[childShapeIndex].m_node);
00111         }
00112         m_children.swap(childShapeIndex,m_children.size()-1);
00113         m_children.pop_back();
00114 
00115 }
00116 
00117 
00118 
00119 void btCompoundShape::removeChildShape(btCollisionShape* shape)
00120 {
00121         m_updateRevision++;
00122         // Find the children containing the shape specified, and remove those children.
00123         //note: there might be multiple children using the same shape!
00124         for(int i = m_children.size()-1; i >= 0 ; i--)
00125         {
00126                 if(m_children[i].m_childShape == shape)
00127                 {
00128                         removeChildShapeByIndex(i);
00129                 }
00130         }
00131 
00132 
00133 
00134         recalculateLocalAabb();
00135 }
00136 
00137 void btCompoundShape::recalculateLocalAabb()
00138 {
00139         // Recalculate the local aabb
00140         // Brute force, it iterates over all the shapes left.
00141 
00142         m_localAabbMin = btVector3(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
00143         m_localAabbMax = btVector3(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT));
00144 
00145         //extend the local aabbMin/aabbMax
00146         for (int j = 0; j < m_children.size(); j++)
00147         {
00148                 btVector3 localAabbMin,localAabbMax;
00149                 m_children[j].m_childShape->getAabb(m_children[j].m_transform, localAabbMin, localAabbMax);
00150                 for (int i=0;i<3;i++)
00151                 {
00152                         if (m_localAabbMin[i] > localAabbMin[i])
00153                                 m_localAabbMin[i] = localAabbMin[i];
00154                         if (m_localAabbMax[i] < localAabbMax[i])
00155                                 m_localAabbMax[i] = localAabbMax[i];
00156                 }
00157         }
00158 }
00159 
00161 void btCompoundShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const
00162 {
00163         btVector3 localHalfExtents = btScalar(0.5)*(m_localAabbMax-m_localAabbMin);
00164         btVector3 localCenter = btScalar(0.5)*(m_localAabbMax+m_localAabbMin);
00165         
00166         //avoid an illegal AABB when there are no children
00167         if (!m_children.size())
00168         {
00169                 localHalfExtents.setValue(0,0,0);
00170                 localCenter.setValue(0,0,0);
00171         }
00172         localHalfExtents += btVector3(getMargin(),getMargin(),getMargin());
00173                 
00174 
00175         btMatrix3x3 abs_b = trans.getBasis().absolute();  
00176 
00177         btVector3 center = trans(localCenter);
00178 
00179         btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents),
00180                 abs_b[1].dot(localHalfExtents),
00181                 abs_b[2].dot(localHalfExtents));
00182         aabbMin = center-extent;
00183         aabbMax = center+extent;
00184         
00185 }
00186 
00187 void    btCompoundShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
00188 {
00189         //approximation: take the inertia from the aabb for now
00190         btTransform ident;
00191         ident.setIdentity();
00192         btVector3 aabbMin,aabbMax;
00193         getAabb(ident,aabbMin,aabbMax);
00194 
00195         btVector3 halfExtents = (aabbMax-aabbMin)*btScalar(0.5);
00196 
00197         btScalar lx=btScalar(2.)*(halfExtents.x());
00198         btScalar ly=btScalar(2.)*(halfExtents.y());
00199         btScalar lz=btScalar(2.)*(halfExtents.z());
00200 
00201         inertia[0] = mass/(btScalar(12.0)) * (ly*ly + lz*lz);
00202         inertia[1] = mass/(btScalar(12.0)) * (lx*lx + lz*lz);
00203         inertia[2] = mass/(btScalar(12.0)) * (lx*lx + ly*ly);
00204 
00205 }
00206 
00207 
00208 
00209 
00210 void btCompoundShape::calculatePrincipalAxisTransform(btScalar* masses, btTransform& principal, btVector3& inertia) const
00211 {
00212         int n = m_children.size();
00213 
00214         btScalar totalMass = 0;
00215         btVector3 center(0, 0, 0);
00216         int k;
00217 
00218         for (k = 0; k < n; k++)
00219         {
00220                 center += m_children[k].m_transform.getOrigin() * masses[k];
00221                 totalMass += masses[k];
00222         }
00223         center /= totalMass;
00224         principal.setOrigin(center);
00225 
00226         btMatrix3x3 tensor(0, 0, 0, 0, 0, 0, 0, 0, 0);
00227         for ( k = 0; k < n; k++)
00228         {
00229                 btVector3 i;
00230                 m_children[k].m_childShape->calculateLocalInertia(masses[k], i);
00231 
00232                 const btTransform& t = m_children[k].m_transform;
00233                 btVector3 o = t.getOrigin() - center;
00234 
00235                 //compute inertia tensor in coordinate system of compound shape
00236                 btMatrix3x3 j = t.getBasis().transpose();
00237                 j[0] *= i[0];
00238                 j[1] *= i[1];
00239                 j[2] *= i[2];
00240                 j = t.getBasis() * j;
00241 
00242                 //add inertia tensor
00243                 tensor[0] += j[0];
00244                 tensor[1] += j[1];
00245                 tensor[2] += j[2];
00246 
00247                 //compute inertia tensor of pointmass at o
00248                 btScalar o2 = o.length2();
00249                 j[0].setValue(o2, 0, 0);
00250                 j[1].setValue(0, o2, 0);
00251                 j[2].setValue(0, 0, o2);
00252                 j[0] += o * -o.x(); 
00253                 j[1] += o * -o.y(); 
00254                 j[2] += o * -o.z();
00255 
00256                 //add inertia tensor of pointmass
00257                 tensor[0] += masses[k] * j[0];
00258                 tensor[1] += masses[k] * j[1];
00259                 tensor[2] += masses[k] * j[2];
00260         }
00261 
00262         tensor.diagonalize(principal.getBasis(), btScalar(0.00001), 20);
00263         inertia.setValue(tensor[0][0], tensor[1][1], tensor[2][2]);
00264 }
00265 
00266 
00267 
00268 void btCompoundShape::setLocalScaling(const btVector3& scaling)
00269 {
00270 
00271         for(int i = 0; i < m_children.size(); i++)
00272         {
00273                 btTransform childTrans = getChildTransform(i);
00274                 btVector3 childScale = m_children[i].m_childShape->getLocalScaling();
00275 //              childScale = childScale * (childTrans.getBasis() * scaling);
00276                 childScale = childScale * scaling / m_localScaling;
00277                 m_children[i].m_childShape->setLocalScaling(childScale);
00278                 childTrans.setOrigin((childTrans.getOrigin())*scaling);
00279                 updateChildTransform(i, childTrans);
00280                 recalculateLocalAabb();
00281         }
00282         m_localScaling = scaling;
00283 }
00284 
00285 
00286 
00287 
00289 const char*     btCompoundShape::serialize(void* dataBuffer, btSerializer* serializer) const
00290 {
00291 
00292         btCompoundShapeData* shapeData = (btCompoundShapeData*) dataBuffer;
00293         btCollisionShape::serialize(&shapeData->m_collisionShapeData, serializer);
00294 
00295         shapeData->m_collisionMargin = float(m_collisionMargin);
00296         shapeData->m_numChildShapes = m_children.size();
00297         shapeData->m_childShapePtr = 0;
00298         if (shapeData->m_numChildShapes)
00299         {
00300                 btChunk* chunk = serializer->allocate(sizeof(btCompoundShapeChildData),shapeData->m_numChildShapes);
00301                 btCompoundShapeChildData* memPtr = (btCompoundShapeChildData*)chunk->m_oldPtr;
00302                 shapeData->m_childShapePtr = memPtr;
00303 
00304                 for (int i=0;i<shapeData->m_numChildShapes;i++,memPtr++)
00305                 {
00306                         memPtr->m_childMargin = float(m_children[i].m_childMargin);
00307                         memPtr->m_childShape = (btCollisionShapeData*)m_children[i].m_childShape;
00308                         //don't serialize shapes that already have been serialized
00309                         if (!serializer->findPointer(memPtr->m_childShape))
00310                         {
00311                                 btChunk* chunk = serializer->allocate(m_children[i].m_childShape->calculateSerializeBufferSize(),1);
00312                                 const char* structType = m_children[i].m_childShape->serialize(chunk->m_oldPtr,serializer);
00313                                 serializer->finalizeChunk(chunk,structType,BT_SHAPE_CODE,m_children[i].m_childShape);
00314                         } 
00315 
00316                         memPtr->m_childShapeType = m_children[i].m_childShapeType;
00317                         m_children[i].m_transform.serializeFloat(memPtr->m_transform);
00318                 }
00319                 serializer->finalizeChunk(chunk,"btCompoundShapeChildData",BT_ARRAY_CODE,chunk->m_oldPtr);
00320         }
00321         return "btCompoundShapeData";
00322 }
00323 

Generated on Mon Feb 15 22:17:02 2010 for Bullet Collision Detection & Physics Library by  doxygen 1.6.1