2 Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
4 Bullet Continuous Collision Detection and Physics Library
5 Copyright (c) 2019 Google Inc. http://bulletphysics.org
6 This software is provided 'as-is', without any express or implied warranty.
7 In no event will the authors be held liable for any damages arising from the use of this software.
8 Permission is granted to anyone to use this software for any purpose,
9 including commercial applications, and to alter it and redistribute it freely,
10 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 #ifndef BT_DEFORMABLE_MULTIBODY_DYNAMICS_WORLD_H
17 #define BT_DEFORMABLE_MULTIBODY_DYNAMICS_WORLD_H
19 #include "btSoftMultiBodyDynamicsWorld.h"
20 #include "btDeformableLagrangianForce.h"
21 #include "btDeformableMassSpringForce.h"
22 // #include "btDeformableBodySolver.h"
23 #include "btDeformableMultiBodyConstraintSolver.h"
24 #include "btSoftBodyHelpers.h"
25 #include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h"
27 typedef btAlignedObjectArray<btSoftBody*> btSoftBodyArray;
29 class btDeformableBodySolver;
30 class btDeformableLagrangianForce;
31 struct MultiBodyInplaceSolverIslandCallback;
32 struct DeformableBodyInplaceSolverIslandCallback;
33 class btDeformableMultiBodyConstraintSolver;
35 typedef btAlignedObjectArray<btSoftBody*> btSoftBodyArray;
37 class btDeformableMultiBodyDynamicsWorld : public btMultiBodyDynamicsWorld
39 typedef btAlignedObjectArray<btVector3> TVStack;
40 ///Solver classes that encapsulate multiple deformable bodies for solving
41 btDeformableBodySolver* m_deformableBodySolver;
42 btSoftBodyArray m_softBodies;
46 bool m_drawClusterTree;
47 btSoftBodyWorldInfo m_sbi;
48 btScalar m_internalTime;
53 DeformableBodyInplaceSolverIslandCallback* m_solverDeformableBodyIslandCallback;
55 typedef void (*btSolverCallback)(btScalar time, btDeformableMultiBodyDynamicsWorld* world);
56 btSolverCallback m_solverCallback;
59 virtual void internalSingleStepSimulation(btScalar timeStep);
61 virtual void integrateTransforms(btScalar timeStep);
63 void positionCorrection(btScalar timeStep);
65 // Modified by Samsung to compile under GCC13. 2024-01-10. eunkiki.hong@samsung.com
66 using btMultiBodyDynamicsWorld::solveConstraints;
67 void solveConstraints(btScalar timeStep);
69 void updateActivationState(btScalar timeStep);
74 btDeformableMultiBodyDynamicsWorld(btDispatcher* dispatcher, btBroadphaseInterface* pairCache, btDeformableMultiBodyConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration, btDeformableBodySolver* deformableBodySolver = 0);
76 virtual int stepSimulation(btScalar timeStep, int maxSubSteps = 1, btScalar fixedTimeStep = btScalar(1.) / btScalar(60.));
78 virtual void debugDrawWorld();
80 void setSolverCallback(btSolverCallback cb)
82 m_solverCallback = cb;
85 virtual ~btDeformableMultiBodyDynamicsWorld();
87 virtual btMultiBodyDynamicsWorld* getMultiBodyDynamicsWorld()
89 return (btMultiBodyDynamicsWorld*)(this);
92 virtual const btMultiBodyDynamicsWorld* getMultiBodyDynamicsWorld() const
94 return (const btMultiBodyDynamicsWorld*)(this);
97 virtual btDynamicsWorldType getWorldType() const
99 return BT_DEFORMABLE_MULTIBODY_DYNAMICS_WORLD;
102 virtual void predictUnconstraintMotion(btScalar timeStep);
104 virtual void addSoftBody(btSoftBody* body, int collisionFilterGroup = btBroadphaseProxy::DefaultFilter, int collisionFilterMask = btBroadphaseProxy::AllFilter);
106 btSoftBodyArray& getSoftBodyArray()
111 const btSoftBodyArray& getSoftBodyArray() const
116 btSoftBodyWorldInfo& getWorldInfo()
121 const btSoftBodyWorldInfo& getWorldInfo() const
126 virtual void setGravity(const btVector3& gravity);
128 void reinitialize(btScalar timeStep);
130 void applyRigidBodyGravity(btScalar timeStep);
132 void beforeSolverCallbacks(btScalar timeStep);
134 void afterSolverCallbacks(btScalar timeStep);
136 void addForce(btSoftBody* psb, btDeformableLagrangianForce* force);
138 void removeForce(btSoftBody* psb, btDeformableLagrangianForce* force);
140 void removeSoftBodyForce(btSoftBody* psb);
142 void removeSoftBody(btSoftBody* body);
144 void removeCollisionObject(btCollisionObject* collisionObject);
146 int getDrawFlags() const { return (m_drawFlags); }
147 void setDrawFlags(int f) { m_drawFlags = f; }
149 void setupConstraints();
151 void performDeformableCollisionDetection();
153 void solveMultiBodyConstraints();
155 void solveContactConstraints();
157 void sortConstraints();
159 void softBodySelfCollision();
161 void setImplicit(bool implicit)
163 m_implicit = implicit;
166 void setLineSearch(bool lineSearch)
168 m_lineSearch = lineSearch;
171 void setUseProjection(bool useProjection)
173 m_useProjection = useProjection;
176 void applyRepulsionForce(btScalar timeStep);
178 void performGeometricCollisions(btScalar timeStep);
180 struct btDeformableSingleRayCallback : public btBroadphaseRayCallback
182 btVector3 m_rayFromWorld;
183 btVector3 m_rayToWorld;
184 btTransform m_rayFromTrans;
185 btTransform m_rayToTrans;
186 btVector3 m_hitNormal;
188 const btDeformableMultiBodyDynamicsWorld* m_world;
189 btCollisionWorld::RayResultCallback& m_resultCallback;
191 btDeformableSingleRayCallback(const btVector3& rayFromWorld, const btVector3& rayToWorld, const btDeformableMultiBodyDynamicsWorld* world, btCollisionWorld::RayResultCallback& resultCallback)
192 : m_rayFromWorld(rayFromWorld),
193 m_rayToWorld(rayToWorld),
195 m_resultCallback(resultCallback)
197 m_rayFromTrans.setIdentity();
198 m_rayFromTrans.setOrigin(m_rayFromWorld);
199 m_rayToTrans.setIdentity();
200 m_rayToTrans.setOrigin(m_rayToWorld);
202 btVector3 rayDir = (rayToWorld - rayFromWorld);
205 ///what about division by zero? --> just set rayDirection[i] to INF/1e30
206 m_rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[0];
207 m_rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[1];
208 m_rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[2];
209 m_signs[0] = m_rayDirectionInverse[0] < 0.0;
210 m_signs[1] = m_rayDirectionInverse[1] < 0.0;
211 m_signs[2] = m_rayDirectionInverse[2] < 0.0;
213 m_lambda_max = rayDir.dot(m_rayToWorld - m_rayFromWorld);
216 virtual bool process(const btBroadphaseProxy* proxy)
218 ///terminate further ray tests, once the closestHitFraction reached zero
219 if (m_resultCallback.m_closestHitFraction == btScalar(0.f))
222 btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject;
224 //only perform raycast if filterMask matches
225 if (m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
227 //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
228 //btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
230 #ifdef RECALCULATE_AABB
231 btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
232 collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax);
234 //getBroadphase()->getAabb(collisionObject->getBroadphaseHandle(),collisionObjectAabbMin,collisionObjectAabbMax);
235 const btVector3& collisionObjectAabbMin = collisionObject->getBroadphaseHandle()->m_aabbMin;
236 const btVector3& collisionObjectAabbMax = collisionObject->getBroadphaseHandle()->m_aabbMax;
239 //btScalar hitLambda = m_resultCallback.m_closestHitFraction;
240 //culling already done by broadphase
241 //if (btRayAabb(m_rayFromWorld,m_rayToWorld,collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,m_hitNormal))
243 m_world->rayTestSingle(m_rayFromTrans, m_rayToTrans,
245 collisionObject->getCollisionShape(),
246 collisionObject->getWorldTransform(),
254 void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const
256 BT_PROFILE("rayTest");
257 /// use the broadphase to accelerate the search for objects, based on their aabb
258 /// and for each object with ray-aabb overlap, perform an exact ray test
259 btDeformableSingleRayCallback rayCB(rayFromWorld, rayToWorld, this, resultCallback);
261 #ifndef USE_BRUTEFORCE_RAYBROADPHASE
262 m_broadphasePairCache->rayTest(rayFromWorld, rayToWorld, rayCB);
264 for (int i = 0; i < this->getNumCollisionObjects(); i++)
266 rayCB.process(m_collisionObjects[i]->getBroadphaseHandle());
268 #endif //USE_BRUTEFORCE_RAYBROADPHASE
271 void rayTestSingle(const btTransform& rayFromTrans, const btTransform& rayToTrans,
272 btCollisionObject* collisionObject,
273 const btCollisionShape* collisionShape,
274 const btTransform& colObjWorldTransform,
275 RayResultCallback& resultCallback) const
277 if (collisionShape->isSoftBody())
279 btSoftBody* softBody = btSoftBody::upcast(collisionObject);
282 btSoftBody::sRayCast softResult;
283 if (softBody->rayFaceTest(rayFromTrans.getOrigin(), rayToTrans.getOrigin(), softResult))
285 if (softResult.fraction <= resultCallback.m_closestHitFraction)
287 btCollisionWorld::LocalShapeInfo shapeInfo;
288 shapeInfo.m_shapePart = 0;
289 shapeInfo.m_triangleIndex = softResult.index;
291 btVector3 rayDir = rayToTrans.getOrigin() - rayFromTrans.getOrigin();
292 btVector3 normal = -rayDir;
295 normal = softBody->m_faces[softResult.index].m_normal;
296 if (normal.dot(rayDir) > 0)
298 // normal always point toward origin of the ray
303 btCollisionWorld::LocalRayResult rayResult(collisionObject,
306 softResult.fraction);
307 bool normalInWorldSpace = true;
308 resultCallback.addSingleResult(rayResult, normalInWorldSpace);
315 btCollisionWorld::rayTestSingle(rayFromTrans, rayToTrans, collisionObject, collisionShape, colObjWorldTransform, resultCallback);
320 #endif //BT_DEFORMABLE_MULTIBODY_DYNAMICS_WORLD_H