00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "btSoftRigidDynamicsWorld.h"
00018 #include "LinearMath/btQuickprof.h"
00019
00020
00021 #include "btSoftBody.h"
00022 #include "btSoftBodyHelpers.h"
00023
00024
00025
00026
00027
00028 btSoftRigidDynamicsWorld::btSoftRigidDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration)
00029 :btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver,collisionConfiguration)
00030 {
00031 m_drawFlags = fDrawFlags::Std;
00032 m_drawNodeTree = true;
00033 m_drawFaceTree = false;
00034 m_drawClusterTree = false;
00035 m_sbi.m_broadphase = pairCache;
00036 m_sbi.m_dispatcher = dispatcher;
00037 m_sbi.m_sparsesdf.Initialize();
00038 m_sbi.m_sparsesdf.Reset();
00039
00040 }
00041
00042 btSoftRigidDynamicsWorld::~btSoftRigidDynamicsWorld()
00043 {
00044
00045 }
00046
00047 void btSoftRigidDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
00048 {
00049 btDiscreteDynamicsWorld::predictUnconstraintMotion( timeStep);
00050
00051 for ( int i=0;i<m_softBodies.size();++i)
00052 {
00053 btSoftBody* psb= m_softBodies[i];
00054
00055 psb->predictMotion(timeStep);
00056 }
00057 }
00058
00059 void btSoftRigidDynamicsWorld::internalSingleStepSimulation( btScalar timeStep)
00060 {
00061 btDiscreteDynamicsWorld::internalSingleStepSimulation( timeStep );
00062
00064 solveSoftBodiesConstraints();
00065
00066
00067 for ( int i=0;i<m_softBodies.size();i++)
00068 {
00069 btSoftBody* psb=(btSoftBody*)m_softBodies[i];
00070 psb->defaultCollisionHandler(psb);
00071 }
00072
00074 updateSoftBodies();
00075
00076 }
00077
00078 void btSoftRigidDynamicsWorld::updateSoftBodies()
00079 {
00080 BT_PROFILE("updateSoftBodies");
00081
00082 for ( int i=0;i<m_softBodies.size();i++)
00083 {
00084 btSoftBody* psb=(btSoftBody*)m_softBodies[i];
00085 psb->integrateMotion();
00086 }
00087 }
00088
00089 void btSoftRigidDynamicsWorld::solveSoftBodiesConstraints()
00090 {
00091 BT_PROFILE("solveSoftConstraints");
00092
00093 if(m_softBodies.size())
00094 {
00095 btSoftBody::solveClusters(m_softBodies);
00096 }
00097
00098 for(int i=0;i<m_softBodies.size();++i)
00099 {
00100 btSoftBody* psb=(btSoftBody*)m_softBodies[i];
00101 psb->solveConstraints();
00102 }
00103 }
00104
00105 void btSoftRigidDynamicsWorld::addSoftBody(btSoftBody* body,short int collisionFilterGroup,short int collisionFilterMask)
00106 {
00107 m_softBodies.push_back(body);
00108
00109 btCollisionWorld::addCollisionObject(body,
00110 collisionFilterGroup,
00111 collisionFilterMask);
00112
00113 }
00114
00115 void btSoftRigidDynamicsWorld::removeSoftBody(btSoftBody* body)
00116 {
00117 m_softBodies.remove(body);
00118
00119 btCollisionWorld::removeCollisionObject(body);
00120 }
00121
00122 void btSoftRigidDynamicsWorld::removeCollisionObject(btCollisionObject* collisionObject)
00123 {
00124 btSoftBody* body = btSoftBody::upcast(collisionObject);
00125 if (body)
00126 removeSoftBody(body);
00127 else
00128 btDiscreteDynamicsWorld::removeCollisionObject(collisionObject);
00129 }
00130
00131 void btSoftRigidDynamicsWorld::debugDrawWorld()
00132 {
00133 btDiscreteDynamicsWorld::debugDrawWorld();
00134
00135 if (getDebugDrawer())
00136 {
00137 int i;
00138 for ( i=0;i<this->m_softBodies.size();i++)
00139 {
00140 btSoftBody* psb=(btSoftBody*)this->m_softBodies[i];
00141 btSoftBodyHelpers::DrawFrame(psb,m_debugDrawer);
00142 btSoftBodyHelpers::Draw(psb,m_debugDrawer,m_drawFlags);
00143 if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
00144 {
00145 if(m_drawNodeTree) btSoftBodyHelpers::DrawNodeTree(psb,m_debugDrawer);
00146 if(m_drawFaceTree) btSoftBodyHelpers::DrawFaceTree(psb,m_debugDrawer);
00147 if(m_drawClusterTree) btSoftBodyHelpers::DrawClusterTree(psb,m_debugDrawer);
00148 }
00149 }
00150 }
00151 }
00152
00153
00154
00155
00156 struct btSoftSingleRayCallback : public btBroadphaseRayCallback
00157 {
00158 btVector3 m_rayFromWorld;
00159 btVector3 m_rayToWorld;
00160 btTransform m_rayFromTrans;
00161 btTransform m_rayToTrans;
00162 btVector3 m_hitNormal;
00163
00164 const btSoftRigidDynamicsWorld* m_world;
00165 btCollisionWorld::RayResultCallback& m_resultCallback;
00166
00167 btSoftSingleRayCallback(const btVector3& rayFromWorld,const btVector3& rayToWorld,const btSoftRigidDynamicsWorld* world,btCollisionWorld::RayResultCallback& resultCallback)
00168 :m_rayFromWorld(rayFromWorld),
00169 m_rayToWorld(rayToWorld),
00170 m_world(world),
00171 m_resultCallback(resultCallback)
00172 {
00173 m_rayFromTrans.setIdentity();
00174 m_rayFromTrans.setOrigin(m_rayFromWorld);
00175 m_rayToTrans.setIdentity();
00176 m_rayToTrans.setOrigin(m_rayToWorld);
00177
00178 btVector3 rayDir = (rayToWorld-rayFromWorld);
00179
00180 rayDir.normalize ();
00182 m_rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[0];
00183 m_rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[1];
00184 m_rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[2];
00185 m_signs[0] = m_rayDirectionInverse[0] < 0.0;
00186 m_signs[1] = m_rayDirectionInverse[1] < 0.0;
00187 m_signs[2] = m_rayDirectionInverse[2] < 0.0;
00188
00189 m_lambda_max = rayDir.dot(m_rayToWorld-m_rayFromWorld);
00190
00191 }
00192
00193
00194
00195 virtual bool process(const btBroadphaseProxy* proxy)
00196 {
00198 if (m_resultCallback.m_closestHitFraction == btScalar(0.f))
00199 return false;
00200
00201 btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject;
00202
00203
00204 if(m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
00205 {
00206
00207
00208 #if 0
00209 #ifdef RECALCULATE_AABB
00210 btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
00211 collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax);
00212 #else
00213
00214 const btVector3& collisionObjectAabbMin = collisionObject->getBroadphaseHandle()->m_aabbMin;
00215 const btVector3& collisionObjectAabbMax = collisionObject->getBroadphaseHandle()->m_aabbMax;
00216 #endif
00217 #endif
00218
00219
00220
00221 {
00222 m_world->rayTestSingle(m_rayFromTrans,m_rayToTrans,
00223 collisionObject,
00224 collisionObject->getCollisionShape(),
00225 collisionObject->getWorldTransform(),
00226 m_resultCallback);
00227 }
00228 }
00229 return true;
00230 }
00231 };
00232
00233 void btSoftRigidDynamicsWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const
00234 {
00235 BT_PROFILE("rayTest");
00238 btSoftSingleRayCallback rayCB(rayFromWorld,rayToWorld,this,resultCallback);
00239
00240 #ifndef USE_BRUTEFORCE_RAYBROADPHASE
00241 m_broadphasePairCache->rayTest(rayFromWorld,rayToWorld,rayCB);
00242 #else
00243 for (int i=0;i<this->getNumCollisionObjects();i++)
00244 {
00245 rayCB.process(m_collisionObjects[i]->getBroadphaseHandle());
00246 }
00247 #endif //USE_BRUTEFORCE_RAYBROADPHASE
00248
00249 }
00250
00251
00252 void btSoftRigidDynamicsWorld::rayTestSingle(const btTransform& rayFromTrans,const btTransform& rayToTrans,
00253 btCollisionObject* collisionObject,
00254 const btCollisionShape* collisionShape,
00255 const btTransform& colObjWorldTransform,
00256 RayResultCallback& resultCallback)
00257 {
00258 if (collisionShape->isSoftBody()) {
00259 btSoftBody* softBody = btSoftBody::upcast(collisionObject);
00260 if (softBody) {
00261 btSoftBody::sRayCast softResult;
00262 if (softBody->rayTest(rayFromTrans.getOrigin(), rayToTrans.getOrigin(), softResult))
00263 {
00264
00265 if (softResult.fraction<= resultCallback.m_closestHitFraction)
00266 {
00267
00268 btCollisionWorld::LocalShapeInfo shapeInfo;
00269 shapeInfo.m_shapePart = 0;
00270 shapeInfo.m_triangleIndex = softResult.index;
00271
00272 btVector3 normal = softBody->m_faces[softResult.index].m_normal;
00273 btVector3 rayDir = rayToTrans.getOrigin() - rayFromTrans.getOrigin();
00274 if (normal.dot(rayDir) > 0) {
00275
00276 normal = -normal;
00277 }
00278 btCollisionWorld::LocalRayResult rayResult
00279 (collisionObject,
00280 &shapeInfo,
00281 normal,
00282 softResult.fraction);
00283 bool normalInWorldSpace = true;
00284 resultCallback.addSingleResult(rayResult,normalInWorldSpace);
00285 }
00286 }
00287 }
00288 }
00289 else {
00290 btCollisionWorld::rayTestSingle(rayFromTrans,rayToTrans,collisionObject,collisionShape,colObjWorldTransform,resultCallback);
00291 }
00292 }