Blender  V2.59
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_node = 0;
00056         child.m_transform = localTransform;
00057         child.m_childShape = shape;
00058         child.m_childShapeType = shape->getShapeType();
00059         child.m_childMargin = shape->getMargin();
00060 
00061         
00062         //extend the local aabbMin/aabbMax
00063         btVector3 localAabbMin,localAabbMax;
00064         shape->getAabb(localTransform,localAabbMin,localAabbMax);
00065         for (int i=0;i<3;i++)
00066         {
00067                 if (m_localAabbMin[i] > localAabbMin[i])
00068                 {
00069                         m_localAabbMin[i] = localAabbMin[i];
00070                 }
00071                 if (m_localAabbMax[i] < localAabbMax[i])
00072                 {
00073                         m_localAabbMax[i] = localAabbMax[i];
00074                 }
00075 
00076         }
00077         if (m_dynamicAabbTree)
00078         {
00079                 const btDbvtVolume      bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax);
00080                 int index = m_children.size();
00081                 child.m_node = m_dynamicAabbTree->insert(bounds,(void*)index);
00082         }
00083 
00084         m_children.push_back(child);
00085 
00086 }
00087 
00088 void    btCompoundShape::updateChildTransform(int childIndex, const btTransform& newChildTransform,bool shouldRecalculateLocalAabb)
00089 {
00090         m_children[childIndex].m_transform = newChildTransform;
00091 
00092         if (m_dynamicAabbTree)
00093         {
00095                 btVector3 localAabbMin,localAabbMax;
00096                 m_children[childIndex].m_childShape->getAabb(newChildTransform,localAabbMin,localAabbMax);
00097                 ATTRIBUTE_ALIGNED16(btDbvtVolume)       bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax);
00098                 //int index = m_children.size()-1;
00099                 m_dynamicAabbTree->update(m_children[childIndex].m_node,bounds);
00100         }
00101 
00102         if (shouldRecalculateLocalAabb)
00103         {
00104                 recalculateLocalAabb();
00105         }
00106 }
00107 
00108 void btCompoundShape::removeChildShapeByIndex(int childShapeIndex)
00109 {
00110         m_updateRevision++;
00111         btAssert(childShapeIndex >=0 && childShapeIndex < m_children.size());
00112         if (m_dynamicAabbTree)
00113         {
00114                 m_dynamicAabbTree->remove(m_children[childShapeIndex].m_node);
00115         }
00116         m_children.swap(childShapeIndex,m_children.size()-1);
00117     if (m_dynamicAabbTree) 
00118                 m_children[childShapeIndex].m_node->dataAsInt = childShapeIndex;
00119         m_children.pop_back();
00120 
00121 }
00122 
00123 
00124 
00125 void btCompoundShape::removeChildShape(btCollisionShape* shape)
00126 {
00127         m_updateRevision++;
00128         // Find the children containing the shape specified, and remove those children.
00129         //note: there might be multiple children using the same shape!
00130         for(int i = m_children.size()-1; i >= 0 ; i--)
00131         {
00132                 if(m_children[i].m_childShape == shape)
00133                 {
00134                         removeChildShapeByIndex(i);
00135                 }
00136         }
00137 
00138 
00139 
00140         recalculateLocalAabb();
00141 }
00142 
00143 void btCompoundShape::recalculateLocalAabb()
00144 {
00145         // Recalculate the local aabb
00146         // Brute force, it iterates over all the shapes left.
00147 
00148         m_localAabbMin = btVector3(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
00149         m_localAabbMax = btVector3(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT));
00150 
00151         //extend the local aabbMin/aabbMax
00152         for (int j = 0; j < m_children.size(); j++)
00153         {
00154                 btVector3 localAabbMin,localAabbMax;
00155                 m_children[j].m_childShape->getAabb(m_children[j].m_transform, localAabbMin, localAabbMax);
00156                 for (int i=0;i<3;i++)
00157                 {
00158                         if (m_localAabbMin[i] > localAabbMin[i])
00159                                 m_localAabbMin[i] = localAabbMin[i];
00160                         if (m_localAabbMax[i] < localAabbMax[i])
00161                                 m_localAabbMax[i] = localAabbMax[i];
00162                 }
00163         }
00164 }
00165 
00167 void btCompoundShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const
00168 {
00169         btVector3 localHalfExtents = btScalar(0.5)*(m_localAabbMax-m_localAabbMin);
00170         btVector3 localCenter = btScalar(0.5)*(m_localAabbMax+m_localAabbMin);
00171         
00172         //avoid an illegal AABB when there are no children
00173         if (!m_children.size())
00174         {
00175                 localHalfExtents.setValue(0,0,0);
00176                 localCenter.setValue(0,0,0);
00177         }
00178         localHalfExtents += btVector3(getMargin(),getMargin(),getMargin());
00179                 
00180 
00181         btMatrix3x3 abs_b = trans.getBasis().absolute();  
00182 
00183         btVector3 center = trans(localCenter);
00184 
00185         btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents),
00186                 abs_b[1].dot(localHalfExtents),
00187                 abs_b[2].dot(localHalfExtents));
00188         aabbMin = center-extent;
00189         aabbMax = center+extent;
00190         
00191 }
00192 
00193 void    btCompoundShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
00194 {
00195         //approximation: take the inertia from the aabb for now
00196         btTransform ident;
00197         ident.setIdentity();
00198         btVector3 aabbMin,aabbMax;
00199         getAabb(ident,aabbMin,aabbMax);
00200 
00201         btVector3 halfExtents = (aabbMax-aabbMin)*btScalar(0.5);
00202 
00203         btScalar lx=btScalar(2.)*(halfExtents.x());
00204         btScalar ly=btScalar(2.)*(halfExtents.y());
00205         btScalar lz=btScalar(2.)*(halfExtents.z());
00206 
00207         inertia[0] = mass/(btScalar(12.0)) * (ly*ly + lz*lz);
00208         inertia[1] = mass/(btScalar(12.0)) * (lx*lx + lz*lz);
00209         inertia[2] = mass/(btScalar(12.0)) * (lx*lx + ly*ly);
00210 
00211 }
00212 
00213 
00214 
00215 
00216 void btCompoundShape::calculatePrincipalAxisTransform(btScalar* masses, btTransform& principal, btVector3& inertia) const
00217 {
00218         int n = m_children.size();
00219 
00220         btScalar totalMass = 0;
00221         btVector3 center(0, 0, 0);
00222         int k;
00223 
00224         for (k = 0; k < n; k++)
00225         {
00226                 btAssert(masses[k]>0);
00227                 center += m_children[k].m_transform.getOrigin() * masses[k];
00228                 totalMass += masses[k];
00229         }
00230 
00231         btAssert(totalMass>0);
00232 
00233         center /= totalMass;
00234         principal.setOrigin(center);
00235 
00236         btMatrix3x3 tensor(0, 0, 0, 0, 0, 0, 0, 0, 0);
00237         for ( k = 0; k < n; k++)
00238         {
00239                 btVector3 i;
00240                 m_children[k].m_childShape->calculateLocalInertia(masses[k], i);
00241 
00242                 const btTransform& t = m_children[k].m_transform;
00243                 btVector3 o = t.getOrigin() - center;
00244 
00245                 //compute inertia tensor in coordinate system of compound shape
00246                 btMatrix3x3 j = t.getBasis().transpose();
00247                 j[0] *= i[0];
00248                 j[1] *= i[1];
00249                 j[2] *= i[2];
00250                 j = t.getBasis() * j;
00251 
00252                 //add inertia tensor
00253                 tensor[0] += j[0];
00254                 tensor[1] += j[1];
00255                 tensor[2] += j[2];
00256 
00257                 //compute inertia tensor of pointmass at o
00258                 btScalar o2 = o.length2();
00259                 j[0].setValue(o2, 0, 0);
00260                 j[1].setValue(0, o2, 0);
00261                 j[2].setValue(0, 0, o2);
00262                 j[0] += o * -o.x(); 
00263                 j[1] += o * -o.y(); 
00264                 j[2] += o * -o.z();
00265 
00266                 //add inertia tensor of pointmass
00267                 tensor[0] += masses[k] * j[0];
00268                 tensor[1] += masses[k] * j[1];
00269                 tensor[2] += masses[k] * j[2];
00270         }
00271 
00272         tensor.diagonalize(principal.getBasis(), btScalar(0.00001), 20);
00273         inertia.setValue(tensor[0][0], tensor[1][1], tensor[2][2]);
00274 }
00275 
00276 
00277 
00278 void btCompoundShape::setLocalScaling(const btVector3& scaling)
00279 {
00280 
00281         for(int i = 0; i < m_children.size(); i++)
00282         {
00283                 btTransform childTrans = getChildTransform(i);
00284                 btVector3 childScale = m_children[i].m_childShape->getLocalScaling();
00285 //              childScale = childScale * (childTrans.getBasis() * scaling);
00286                 childScale = childScale * scaling / m_localScaling;
00287                 m_children[i].m_childShape->setLocalScaling(childScale);
00288                 childTrans.setOrigin((childTrans.getOrigin())*scaling);
00289                 updateChildTransform(i, childTrans,false);
00290         }
00291         
00292         m_localScaling = scaling;
00293         recalculateLocalAabb();
00294 
00295 }
00296 
00297 
00298 void btCompoundShape::createAabbTreeFromChildren()
00299 {
00300     if ( !m_dynamicAabbTree )
00301     {
00302         void* mem = btAlignedAlloc(sizeof(btDbvt),16);
00303         m_dynamicAabbTree = new(mem) btDbvt();
00304         btAssert(mem==m_dynamicAabbTree);
00305 
00306         for ( int index = 0; index < m_children.size(); index++ )
00307         {
00308             btCompoundShapeChild &child = m_children[index];
00309 
00310             //extend the local aabbMin/aabbMax
00311             btVector3 localAabbMin,localAabbMax;
00312             child.m_childShape->getAabb(child.m_transform,localAabbMin,localAabbMax);
00313 
00314             const btDbvtVolume  bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax);
00315             child.m_node = m_dynamicAabbTree->insert(bounds,(void*)index);
00316         }
00317     }
00318 }
00319 
00320 
00322 const char*     btCompoundShape::serialize(void* dataBuffer, btSerializer* serializer) const
00323 {
00324 
00325         btCompoundShapeData* shapeData = (btCompoundShapeData*) dataBuffer;
00326         btCollisionShape::serialize(&shapeData->m_collisionShapeData, serializer);
00327 
00328         shapeData->m_collisionMargin = float(m_collisionMargin);
00329         shapeData->m_numChildShapes = m_children.size();
00330         shapeData->m_childShapePtr = 0;
00331         if (shapeData->m_numChildShapes)
00332         {
00333                 btChunk* chunk = serializer->allocate(sizeof(btCompoundShapeChildData),shapeData->m_numChildShapes);
00334                 btCompoundShapeChildData* memPtr = (btCompoundShapeChildData*)chunk->m_oldPtr;
00335                 shapeData->m_childShapePtr = (btCompoundShapeChildData*)serializer->getUniquePointer(memPtr);
00336 
00337                 for (int i=0;i<shapeData->m_numChildShapes;i++,memPtr++)
00338                 {
00339                         memPtr->m_childMargin = float(m_children[i].m_childMargin);
00340                         memPtr->m_childShape = (btCollisionShapeData*)serializer->getUniquePointer(m_children[i].m_childShape);
00341                         //don't serialize shapes that already have been serialized
00342                         if (!serializer->findPointer(m_children[i].m_childShape))
00343                         {
00344                                 btChunk* chunk = serializer->allocate(m_children[i].m_childShape->calculateSerializeBufferSize(),1);
00345                                 const char* structType = m_children[i].m_childShape->serialize(chunk->m_oldPtr,serializer);
00346                                 serializer->finalizeChunk(chunk,structType,BT_SHAPE_CODE,m_children[i].m_childShape);
00347                         } 
00348 
00349                         memPtr->m_childShapeType = m_children[i].m_childShapeType;
00350                         m_children[i].m_transform.serializeFloat(memPtr->m_transform);
00351                 }
00352                 serializer->finalizeChunk(chunk,"btCompoundShapeChildData",BT_ARRAY_CODE,chunk->m_oldPtr);
00353         }
00354         return "btCompoundShapeData";
00355 }
00356