00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
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
00053
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
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
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
00123
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
00140
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
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
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
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
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
00243 tensor[0] += j[0];
00244 tensor[1] += j[1];
00245 tensor[2] += j[2];
00246
00247
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
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
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
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