2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2006 Erwin Coumans https://bulletphysics.org
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages arising from the use of this software.
7 Permission is granted to anyone to use this software for any purpose,
8 including commercial applications, and to alter it and redistribute it freely,
9 subject to the following restrictions:
11 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.
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13 3. This notice may not be removed or altered from any source distribution.
16 #include "btSoftRigidDynamicsWorld.h"
17 #include "LinearMath/btQuickprof.h"
20 #include "btSoftBody.h"
21 #include "btSoftBodyHelpers.h"
22 #include "btSoftBodySolvers.h"
23 #include "btDefaultSoftBodySolver.h"
24 #include "LinearMath/btSerializer.h"
26 btSoftRigidDynamicsWorld::btSoftRigidDynamicsWorld(
27 btDispatcher* dispatcher,
28 btBroadphaseInterface* pairCache,
29 btConstraintSolver* constraintSolver,
30 btCollisionConfiguration* collisionConfiguration,
31 btSoftBodySolver* softBodySolver) : btDiscreteDynamicsWorld(dispatcher, pairCache, constraintSolver, collisionConfiguration),
32 m_softBodySolver(softBodySolver),
35 if (!m_softBodySolver)
37 void* ptr = btAlignedAlloc(sizeof(btDefaultSoftBodySolver), 16);
38 m_softBodySolver = new (ptr) btDefaultSoftBodySolver();
42 m_drawFlags = fDrawFlags::Std;
43 m_drawNodeTree = true;
44 m_drawFaceTree = false;
45 m_drawClusterTree = false;
46 m_sbi.m_broadphase = pairCache;
47 m_sbi.m_dispatcher = dispatcher;
48 m_sbi.m_sparsesdf.Initialize();
49 m_sbi.m_sparsesdf.Reset();
51 m_sbi.air_density = (btScalar)1.2;
52 m_sbi.water_density = 0;
53 m_sbi.water_offset = 0;
54 m_sbi.water_normal = btVector3(0, 0, 0);
55 m_sbi.m_gravity.setValue(0, -10, 0);
57 m_sbi.m_sparsesdf.Initialize();
60 btSoftRigidDynamicsWorld::~btSoftRigidDynamicsWorld()
64 m_softBodySolver->~btSoftBodySolver();
65 btAlignedFree(m_softBodySolver);
69 void btSoftRigidDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
71 btDiscreteDynamicsWorld::predictUnconstraintMotion(timeStep);
73 BT_PROFILE("predictUnconstraintMotionSoftBody");
74 m_softBodySolver->predictMotion(float(timeStep));
78 void btSoftRigidDynamicsWorld::internalSingleStepSimulation(btScalar timeStep)
80 // Let the solver grab the soft bodies and if necessary optimize for it
81 m_softBodySolver->optimize(getSoftBodyArray());
83 if (!m_softBodySolver->checkInitialized())
85 btAssert("Solver initialization failed\n");
88 btDiscreteDynamicsWorld::internalSingleStepSimulation(timeStep);
90 ///solve soft bodies constraints
91 solveSoftBodiesConstraints(timeStep);
94 for (int i = 0; i < m_softBodies.size(); i++)
96 btSoftBody* psb = (btSoftBody*)m_softBodies[i];
97 psb->defaultCollisionHandler(psb);
100 ///update soft bodies
101 m_softBodySolver->updateSoftBodies();
103 // End solver-wise simulation step
104 // ///////////////////////////////
107 void btSoftRigidDynamicsWorld::solveSoftBodiesConstraints(btScalar timeStep)
109 BT_PROFILE("solveSoftConstraints");
111 if (m_softBodies.size())
113 btSoftBody::solveClusters(m_softBodies);
116 // Solve constraints solver-wise
117 m_softBodySolver->solveConstraints(timeStep * m_softBodySolver->getTimeScale());
120 void btSoftRigidDynamicsWorld::addSoftBody(btSoftBody* body, int collisionFilterGroup, int collisionFilterMask)
122 m_softBodies.push_back(body);
124 // Set the soft body solver that will deal with this body
125 // to be the world's solver
126 body->setSoftBodySolver(m_softBodySolver);
128 btCollisionWorld::addCollisionObject(body,
129 collisionFilterGroup,
130 collisionFilterMask);
133 void btSoftRigidDynamicsWorld::removeSoftBody(btSoftBody* body)
135 m_softBodies.remove(body);
137 btCollisionWorld::removeCollisionObject(body);
140 void btSoftRigidDynamicsWorld::removeCollisionObject(btCollisionObject* collisionObject)
142 btSoftBody* body = btSoftBody::upcast(collisionObject);
144 removeSoftBody(body);
146 btDiscreteDynamicsWorld::removeCollisionObject(collisionObject);
149 void btSoftRigidDynamicsWorld::debugDrawWorld()
151 btDiscreteDynamicsWorld::debugDrawWorld();
153 if (getDebugDrawer())
156 for (i = 0; i < this->m_softBodies.size(); i++)
158 btSoftBody* psb = (btSoftBody*)this->m_softBodies[i];
159 if (getDebugDrawer() && (getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe)))
161 btSoftBodyHelpers::DrawFrame(psb, m_debugDrawer);
162 btSoftBodyHelpers::Draw(psb, m_debugDrawer, m_drawFlags);
165 if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
167 if (m_drawNodeTree) btSoftBodyHelpers::DrawNodeTree(psb, m_debugDrawer);
168 if (m_drawFaceTree) btSoftBodyHelpers::DrawFaceTree(psb, m_debugDrawer);
169 if (m_drawClusterTree) btSoftBodyHelpers::DrawClusterTree(psb, m_debugDrawer);
175 struct btSoftSingleRayCallback : public btBroadphaseRayCallback
177 btVector3 m_rayFromWorld;
178 btVector3 m_rayToWorld;
179 btTransform m_rayFromTrans;
180 btTransform m_rayToTrans;
181 btVector3 m_hitNormal;
183 const btSoftRigidDynamicsWorld* m_world;
184 btCollisionWorld::RayResultCallback& m_resultCallback;
186 btSoftSingleRayCallback(const btVector3& rayFromWorld, const btVector3& rayToWorld, const btSoftRigidDynamicsWorld* world, btCollisionWorld::RayResultCallback& resultCallback)
187 : m_rayFromWorld(rayFromWorld),
188 m_rayToWorld(rayToWorld),
190 m_resultCallback(resultCallback)
192 m_rayFromTrans.setIdentity();
193 m_rayFromTrans.setOrigin(m_rayFromWorld);
194 m_rayToTrans.setIdentity();
195 m_rayToTrans.setOrigin(m_rayToWorld);
197 btVector3 rayDir = (rayToWorld - rayFromWorld);
200 ///what about division by zero? --> just set rayDirection[i] to INF/1e30
201 m_rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[0];
202 m_rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[1];
203 m_rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[2];
204 m_signs[0] = m_rayDirectionInverse[0] < 0.0;
205 m_signs[1] = m_rayDirectionInverse[1] < 0.0;
206 m_signs[2] = m_rayDirectionInverse[2] < 0.0;
208 m_lambda_max = rayDir.dot(m_rayToWorld - m_rayFromWorld);
211 virtual bool process(const btBroadphaseProxy* proxy)
213 ///terminate further ray tests, once the closestHitFraction reached zero
214 if (m_resultCallback.m_closestHitFraction == btScalar(0.f))
217 btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject;
219 //only perform raycast if filterMask matches
220 if (m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
222 //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
223 //btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
225 #ifdef RECALCULATE_AABB
226 btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
227 collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax);
229 //getBroadphase()->getAabb(collisionObject->getBroadphaseHandle(),collisionObjectAabbMin,collisionObjectAabbMax);
230 const btVector3& collisionObjectAabbMin = collisionObject->getBroadphaseHandle()->m_aabbMin;
231 const btVector3& collisionObjectAabbMax = collisionObject->getBroadphaseHandle()->m_aabbMax;
234 //btScalar hitLambda = m_resultCallback.m_closestHitFraction;
235 //culling already done by broadphase
236 //if (btRayAabb(m_rayFromWorld,m_rayToWorld,collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,m_hitNormal))
238 m_world->rayTestSingle(m_rayFromTrans, m_rayToTrans,
240 collisionObject->getCollisionShape(),
241 collisionObject->getWorldTransform(),
249 void btSoftRigidDynamicsWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const
251 BT_PROFILE("rayTest");
252 /// use the broadphase to accelerate the search for objects, based on their aabb
253 /// and for each object with ray-aabb overlap, perform an exact ray test
254 btSoftSingleRayCallback rayCB(rayFromWorld, rayToWorld, this, resultCallback);
256 #ifndef USE_BRUTEFORCE_RAYBROADPHASE
257 m_broadphasePairCache->rayTest(rayFromWorld, rayToWorld, rayCB);
259 for (int i = 0; i < this->getNumCollisionObjects(); i++)
261 rayCB.process(m_collisionObjects[i]->getBroadphaseHandle());
263 #endif //USE_BRUTEFORCE_RAYBROADPHASE
266 void btSoftRigidDynamicsWorld::rayTestSingle(const btTransform& rayFromTrans, const btTransform& rayToTrans,
267 btCollisionObject* collisionObject,
268 const btCollisionShape* collisionShape,
269 const btTransform& colObjWorldTransform,
270 RayResultCallback& resultCallback)
272 if (collisionShape->isSoftBody())
274 btSoftBody* softBody = btSoftBody::upcast(collisionObject);
277 btSoftBody::sRayCast softResult;
278 if (softBody->rayTest(rayFromTrans.getOrigin(), rayToTrans.getOrigin(), softResult))
280 if (softResult.fraction <= resultCallback.m_closestHitFraction)
282 btCollisionWorld::LocalShapeInfo shapeInfo;
283 shapeInfo.m_shapePart = 0;
284 shapeInfo.m_triangleIndex = softResult.index;
286 btVector3 rayDir = rayToTrans.getOrigin() - rayFromTrans.getOrigin();
287 btVector3 normal = -rayDir;
290 if (softResult.feature == btSoftBody::eFeature::Face)
292 normal = softBody->m_faces[softResult.index].m_normal;
293 if (normal.dot(rayDir) > 0)
295 // normal always point toward origin of the ray
300 btCollisionWorld::LocalRayResult rayResult(collisionObject,
303 softResult.fraction);
304 bool normalInWorldSpace = true;
305 resultCallback.addSingleResult(rayResult, normalInWorldSpace);
312 btCollisionWorld::rayTestSingle(rayFromTrans, rayToTrans, collisionObject, collisionShape, colObjWorldTransform, resultCallback);
316 void btSoftRigidDynamicsWorld::serializeSoftBodies(btSerializer* serializer)
319 //serialize all collision objects
320 for (i = 0; i < m_collisionObjects.size(); i++)
322 btCollisionObject* colObj = m_collisionObjects[i];
323 if (colObj->getInternalType() & btCollisionObject::CO_SOFT_BODY)
325 int len = colObj->calculateSerializeBufferSize();
326 btChunk* chunk = serializer->allocate(len, 1);
327 const char* structType = colObj->serialize(chunk->m_oldPtr, serializer);
328 serializer->finalizeChunk(chunk, structType, BT_SOFTBODY_CODE, colObj);
333 void btSoftRigidDynamicsWorld::serialize(btSerializer* serializer)
335 serializer->startSerialization();
337 serializeDynamicsWorldInfo(serializer);
339 serializeSoftBodies(serializer);
341 serializeRigidBodies(serializer);
343 serializeCollisionObjects(serializer);
345 serializer->finishSerialization();