00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h"
00017 #include "BulletCollision/CollisionDispatch/btCollisionObject.h"
00018 #include "BulletCollision/CollisionShapes/btCompoundShape.h"
00019 #include "BulletCollision/BroadphaseCollision/btDbvt.h"
00020 #include "LinearMath/btIDebugDraw.h"
00021 #include "LinearMath/btAabbUtil2.h"
00022 #include "btManifoldResult.h"
00023
00024 btCompoundCollisionAlgorithm::btCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped)
00025 :btActivatingCollisionAlgorithm(ci,body0,body1),
00026 m_isSwapped(isSwapped),
00027 m_sharedManifold(ci.m_manifold)
00028 {
00029 m_ownsManifold = false;
00030
00031 btCollisionObject* colObj = m_isSwapped? body1 : body0;
00032 btAssert (colObj->getCollisionShape()->isCompound());
00033
00034 btCompoundShape* compoundShape = static_cast<btCompoundShape*>(colObj->getCollisionShape());
00035 m_compoundShapeRevision = compoundShape->getUpdateRevision();
00036
00037 preallocateChildAlgorithms(body0,body1);
00038 }
00039
00040 void btCompoundCollisionAlgorithm::preallocateChildAlgorithms(btCollisionObject* body0,btCollisionObject* body1)
00041 {
00042 btCollisionObject* colObj = m_isSwapped? body1 : body0;
00043 btCollisionObject* otherObj = m_isSwapped? body0 : body1;
00044 btAssert (colObj->getCollisionShape()->isCompound());
00045
00046 btCompoundShape* compoundShape = static_cast<btCompoundShape*>(colObj->getCollisionShape());
00047
00048 int numChildren = compoundShape->getNumChildShapes();
00049 int i;
00050
00051 m_childCollisionAlgorithms.resize(numChildren);
00052 for (i=0;i<numChildren;i++)
00053 {
00054 if (compoundShape->getDynamicAabbTree())
00055 {
00056 m_childCollisionAlgorithms[i] = 0;
00057 } else
00058 {
00059 btCollisionShape* tmpShape = colObj->getCollisionShape();
00060 btCollisionShape* childShape = compoundShape->getChildShape(i);
00061 colObj->internalSetTemporaryCollisionShape( childShape );
00062 m_childCollisionAlgorithms[i] = m_dispatcher->findAlgorithm(colObj,otherObj,m_sharedManifold);
00063 colObj->internalSetTemporaryCollisionShape( tmpShape );
00064 }
00065 }
00066 }
00067
00068 void btCompoundCollisionAlgorithm::removeChildAlgorithms()
00069 {
00070 int numChildren = m_childCollisionAlgorithms.size();
00071 int i;
00072 for (i=0;i<numChildren;i++)
00073 {
00074 if (m_childCollisionAlgorithms[i])
00075 {
00076 m_childCollisionAlgorithms[i]->~btCollisionAlgorithm();
00077 m_dispatcher->freeCollisionAlgorithm(m_childCollisionAlgorithms[i]);
00078 }
00079 }
00080 }
00081
00082 btCompoundCollisionAlgorithm::~btCompoundCollisionAlgorithm()
00083 {
00084 removeChildAlgorithms();
00085 }
00086
00087
00088
00089
00090 struct btCompoundLeafCallback : btDbvt::ICollide
00091 {
00092
00093 public:
00094
00095 btCollisionObject* m_compoundColObj;
00096 btCollisionObject* m_otherObj;
00097 btDispatcher* m_dispatcher;
00098 const btDispatcherInfo& m_dispatchInfo;
00099 btManifoldResult* m_resultOut;
00100 btCollisionAlgorithm** m_childCollisionAlgorithms;
00101 btPersistentManifold* m_sharedManifold;
00102
00103
00104
00105
00106 btCompoundLeafCallback (btCollisionObject* compoundObj,btCollisionObject* otherObj,btDispatcher* dispatcher,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut,btCollisionAlgorithm** childCollisionAlgorithms,btPersistentManifold* sharedManifold)
00107 :m_compoundColObj(compoundObj),m_otherObj(otherObj),m_dispatcher(dispatcher),m_dispatchInfo(dispatchInfo),m_resultOut(resultOut),
00108 m_childCollisionAlgorithms(childCollisionAlgorithms),
00109 m_sharedManifold(sharedManifold)
00110 {
00111
00112 }
00113
00114
00115 void ProcessChildShape(btCollisionShape* childShape,int index)
00116 {
00117
00118 btCompoundShape* compoundShape = static_cast<btCompoundShape*>(m_compoundColObj->getCollisionShape());
00119
00120
00121
00122 btTransform orgTrans = m_compoundColObj->getWorldTransform();
00123 btTransform orgInterpolationTrans = m_compoundColObj->getInterpolationWorldTransform();
00124 const btTransform& childTrans = compoundShape->getChildTransform(index);
00125 btTransform newChildWorldTrans = orgTrans*childTrans ;
00126
00127
00128 btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1;
00129 childShape->getAabb(newChildWorldTrans,aabbMin0,aabbMax0);
00130 m_otherObj->getCollisionShape()->getAabb(m_otherObj->getWorldTransform(),aabbMin1,aabbMax1);
00131
00132 if (TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1))
00133 {
00134
00135 m_compoundColObj->setWorldTransform( newChildWorldTrans);
00136 m_compoundColObj->setInterpolationWorldTransform(newChildWorldTrans);
00137
00138
00139 btCollisionShape* tmpShape = m_compoundColObj->getCollisionShape();
00140 m_compoundColObj->internalSetTemporaryCollisionShape( childShape );
00141
00142 if (!m_childCollisionAlgorithms[index])
00143 m_childCollisionAlgorithms[index] = m_dispatcher->findAlgorithm(m_compoundColObj,m_otherObj,m_sharedManifold);
00144
00146 if (m_resultOut->getBody0Internal() == m_compoundColObj)
00147 {
00148 m_resultOut->setShapeIdentifiersA(-1,index);
00149 } else
00150 {
00151 m_resultOut->setShapeIdentifiersB(-1,index);
00152 }
00153
00154 m_childCollisionAlgorithms[index]->processCollision(m_compoundColObj,m_otherObj,m_dispatchInfo,m_resultOut);
00155 if (m_dispatchInfo.m_debugDraw && (m_dispatchInfo.m_debugDraw->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
00156 {
00157 btVector3 worldAabbMin,worldAabbMax;
00158 m_dispatchInfo.m_debugDraw->drawAabb(aabbMin0,aabbMax0,btVector3(1,1,1));
00159 m_dispatchInfo.m_debugDraw->drawAabb(aabbMin1,aabbMax1,btVector3(1,1,1));
00160 }
00161
00162
00163 m_compoundColObj->internalSetTemporaryCollisionShape( tmpShape);
00164 m_compoundColObj->setWorldTransform( orgTrans );
00165 m_compoundColObj->setInterpolationWorldTransform(orgInterpolationTrans);
00166 }
00167 }
00168 void Process(const btDbvtNode* leaf)
00169 {
00170 int index = leaf->dataAsInt;
00171
00172 btCompoundShape* compoundShape = static_cast<btCompoundShape*>(m_compoundColObj->getCollisionShape());
00173 btCollisionShape* childShape = compoundShape->getChildShape(index);
00174 if (m_dispatchInfo.m_debugDraw && (m_dispatchInfo.m_debugDraw->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
00175 {
00176 btVector3 worldAabbMin,worldAabbMax;
00177 btTransform orgTrans = m_compoundColObj->getWorldTransform();
00178 btTransformAabb(leaf->volume.Mins(),leaf->volume.Maxs(),0.,orgTrans,worldAabbMin,worldAabbMax);
00179 m_dispatchInfo.m_debugDraw->drawAabb(worldAabbMin,worldAabbMax,btVector3(1,0,0));
00180 }
00181 ProcessChildShape(childShape,index);
00182
00183 }
00184 };
00185
00186
00187
00188
00189
00190
00191 void btCompoundCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
00192 {
00193 btCollisionObject* colObj = m_isSwapped? body1 : body0;
00194 btCollisionObject* otherObj = m_isSwapped? body0 : body1;
00195
00196
00197
00198 btAssert (colObj->getCollisionShape()->isCompound());
00199 btCompoundShape* compoundShape = static_cast<btCompoundShape*>(colObj->getCollisionShape());
00200
00203 if (compoundShape->getUpdateRevision() != m_compoundShapeRevision)
00204 {
00206 removeChildAlgorithms();
00207
00208 preallocateChildAlgorithms(body0,body1);
00209 }
00210
00211
00212 btDbvt* tree = compoundShape->getDynamicAabbTree();
00213
00214 btCompoundLeafCallback callback(colObj,otherObj,m_dispatcher,dispatchInfo,resultOut,&m_childCollisionAlgorithms[0],m_sharedManifold);
00215
00219 {
00220 int i;
00221 btManifoldArray manifoldArray;
00222 for (i=0;i<m_childCollisionAlgorithms.size();i++)
00223 {
00224 if (m_childCollisionAlgorithms[i])
00225 {
00226 m_childCollisionAlgorithms[i]->getAllContactManifolds(manifoldArray);
00227 for (int m=0;m<manifoldArray.size();m++)
00228 {
00229 if (manifoldArray[m]->getNumContacts())
00230 {
00231 resultOut->setPersistentManifold(manifoldArray[m]);
00232 resultOut->refreshContactPoints();
00233 resultOut->setPersistentManifold(0);
00234 }
00235 }
00236 manifoldArray.clear();
00237 }
00238 }
00239 }
00240
00241 if (tree)
00242 {
00243
00244 btVector3 localAabbMin,localAabbMax;
00245 btTransform otherInCompoundSpace;
00246 otherInCompoundSpace = colObj->getWorldTransform().inverse() * otherObj->getWorldTransform();
00247 otherObj->getCollisionShape()->getAabb(otherInCompoundSpace,localAabbMin,localAabbMax);
00248
00249 const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax);
00250
00251 tree->collideTV(tree->m_root,bounds,callback);
00252
00253 } else
00254 {
00255
00256 int numChildren = m_childCollisionAlgorithms.size();
00257 int i;
00258 for (i=0;i<numChildren;i++)
00259 {
00260 callback.ProcessChildShape(compoundShape->getChildShape(i),i);
00261 }
00262 }
00263
00264 {
00265
00266 int numChildren = m_childCollisionAlgorithms.size();
00267 int i;
00268 btManifoldArray manifoldArray;
00269
00270 for (i=0;i<numChildren;i++)
00271 {
00272 if (m_childCollisionAlgorithms[i])
00273 {
00274 btCollisionShape* childShape = compoundShape->getChildShape(i);
00275
00276 btTransform orgTrans = colObj->getWorldTransform();
00277 btTransform orgInterpolationTrans = colObj->getInterpolationWorldTransform();
00278 const btTransform& childTrans = compoundShape->getChildTransform(i);
00279 btTransform newChildWorldTrans = orgTrans*childTrans ;
00280
00281
00282 btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1;
00283 childShape->getAabb(newChildWorldTrans,aabbMin0,aabbMax0);
00284 otherObj->getCollisionShape()->getAabb(otherObj->getWorldTransform(),aabbMin1,aabbMax1);
00285
00286 if (!TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1))
00287 {
00288 m_childCollisionAlgorithms[i]->~btCollisionAlgorithm();
00289 m_dispatcher->freeCollisionAlgorithm(m_childCollisionAlgorithms[i]);
00290 m_childCollisionAlgorithms[i] = 0;
00291 }
00292
00293 }
00294
00295 }
00296
00297
00298
00299 }
00300 }
00301
00302 btScalar btCompoundCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
00303 {
00304
00305 btCollisionObject* colObj = m_isSwapped? body1 : body0;
00306 btCollisionObject* otherObj = m_isSwapped? body0 : body1;
00307
00308 btAssert (colObj->getCollisionShape()->isCompound());
00309
00310 btCompoundShape* compoundShape = static_cast<btCompoundShape*>(colObj->getCollisionShape());
00311
00312
00313
00314
00315
00316
00317
00318
00319 btScalar hitFraction = btScalar(1.);
00320
00321 int numChildren = m_childCollisionAlgorithms.size();
00322 int i;
00323 for (i=0;i<numChildren;i++)
00324 {
00325
00326 btCollisionShape* childShape = compoundShape->getChildShape(i);
00327
00328
00329 btTransform orgTrans = colObj->getWorldTransform();
00330
00331 const btTransform& childTrans = compoundShape->getChildTransform(i);
00332
00333 colObj->setWorldTransform( orgTrans*childTrans );
00334
00335 btCollisionShape* tmpShape = colObj->getCollisionShape();
00336 colObj->internalSetTemporaryCollisionShape( childShape );
00337 btScalar frac = m_childCollisionAlgorithms[i]->calculateTimeOfImpact(colObj,otherObj,dispatchInfo,resultOut);
00338 if (frac<hitFraction)
00339 {
00340 hitFraction = frac;
00341 }
00342
00343 colObj->internalSetTemporaryCollisionShape( tmpShape);
00344 colObj->setWorldTransform( orgTrans);
00345 }
00346 return hitFraction;
00347
00348 }
00349
00350
00351