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 void solveConstraints(btScalar timeStep);
67 void updateActivationState(btScalar timeStep);
72 btDeformableMultiBodyDynamicsWorld(btDispatcher* dispatcher, btBroadphaseInterface* pairCache, btDeformableMultiBodyConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration, btDeformableBodySolver* deformableBodySolver = 0);
74 virtual int stepSimulation(btScalar timeStep, int maxSubSteps = 1, btScalar fixedTimeStep = btScalar(1.) / btScalar(60.));
76 virtual void debugDrawWorld();
78 void setSolverCallback(btSolverCallback cb)
80 m_solverCallback = cb;
83 virtual ~btDeformableMultiBodyDynamicsWorld();
85 virtual btMultiBodyDynamicsWorld* getMultiBodyDynamicsWorld()
87 return (btMultiBodyDynamicsWorld*)(this);
90 virtual const btMultiBodyDynamicsWorld* getMultiBodyDynamicsWorld() const
92 return (const btMultiBodyDynamicsWorld*)(this);
95 virtual btDynamicsWorldType getWorldType() const
97 return BT_DEFORMABLE_MULTIBODY_DYNAMICS_WORLD;
100 virtual void predictUnconstraintMotion(btScalar timeStep);
102 virtual void addSoftBody(btSoftBody* body, int collisionFilterGroup = btBroadphaseProxy::DefaultFilter, int collisionFilterMask = btBroadphaseProxy::AllFilter);
104 btSoftBodyArray& getSoftBodyArray()
109 const btSoftBodyArray& getSoftBodyArray() const
114 btSoftBodyWorldInfo& getWorldInfo()
119 const btSoftBodyWorldInfo& getWorldInfo() const
124 virtual void setGravity(const btVector3& gravity);
126 void reinitialize(btScalar timeStep);
128 void applyRigidBodyGravity(btScalar timeStep);
130 void beforeSolverCallbacks(btScalar timeStep);
132 void afterSolverCallbacks(btScalar timeStep);
134 void addForce(btSoftBody* psb, btDeformableLagrangianForce* force);
136 void removeForce(btSoftBody* psb, btDeformableLagrangianForce* force);
138 void removeSoftBodyForce(btSoftBody* psb);
140 void removeSoftBody(btSoftBody* body);
142 void removeCollisionObject(btCollisionObject* collisionObject);
144 int getDrawFlags() const { return (m_drawFlags); }
145 void setDrawFlags(int f) { m_drawFlags = f; }
147 void setupConstraints();
149 void performDeformableCollisionDetection();
151 void solveMultiBodyConstraints();
153 void solveContactConstraints();
155 void sortConstraints();
157 void softBodySelfCollision();
159 void setImplicit(bool implicit)
161 m_implicit = implicit;
164 void setLineSearch(bool lineSearch)
166 m_lineSearch = lineSearch;
169 void setUseProjection(bool useProjection)
171 m_useProjection = useProjection;
174 void applyRepulsionForce(btScalar timeStep);
176 void performGeometricCollisions(btScalar timeStep);
178 struct btDeformableSingleRayCallback : public btBroadphaseRayCallback
180 btVector3 m_rayFromWorld;
181 btVector3 m_rayToWorld;
182 btTransform m_rayFromTrans;
183 btTransform m_rayToTrans;
184 btVector3 m_hitNormal;
186 const btDeformableMultiBodyDynamicsWorld* m_world;
187 btCollisionWorld::RayResultCallback& m_resultCallback;
189 btDeformableSingleRayCallback(const btVector3& rayFromWorld, const btVector3& rayToWorld, const btDeformableMultiBodyDynamicsWorld* world, btCollisionWorld::RayResultCallback& resultCallback)
190 : m_rayFromWorld(rayFromWorld),
191 m_rayToWorld(rayToWorld),
193 m_resultCallback(resultCallback)
195 m_rayFromTrans.setIdentity();
196 m_rayFromTrans.setOrigin(m_rayFromWorld);
197 m_rayToTrans.setIdentity();
198 m_rayToTrans.setOrigin(m_rayToWorld);
200 btVector3 rayDir = (rayToWorld - rayFromWorld);
203 ///what about division by zero? --> just set rayDirection[i] to INF/1e30
204 m_rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[0];
205 m_rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[1];
206 m_rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[2];
207 m_signs[0] = m_rayDirectionInverse[0] < 0.0;
208 m_signs[1] = m_rayDirectionInverse[1] < 0.0;
209 m_signs[2] = m_rayDirectionInverse[2] < 0.0;
211 m_lambda_max = rayDir.dot(m_rayToWorld - m_rayFromWorld);
214 virtual bool process(const btBroadphaseProxy* proxy)
216 ///terminate further ray tests, once the closestHitFraction reached zero
217 if (m_resultCallback.m_closestHitFraction == btScalar(0.f))
220 btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject;
222 //only perform raycast if filterMask matches
223 if (m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
225 //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
226 //btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
228 #ifdef RECALCULATE_AABB
229 btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
230 collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax);
232 //getBroadphase()->getAabb(collisionObject->getBroadphaseHandle(),collisionObjectAabbMin,collisionObjectAabbMax);
233 const btVector3& collisionObjectAabbMin = collisionObject->getBroadphaseHandle()->m_aabbMin;
234 const btVector3& collisionObjectAabbMax = collisionObject->getBroadphaseHandle()->m_aabbMax;
237 //btScalar hitLambda = m_resultCallback.m_closestHitFraction;
238 //culling already done by broadphase
239 //if (btRayAabb(m_rayFromWorld,m_rayToWorld,collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,m_hitNormal))
241 m_world->rayTestSingle(m_rayFromTrans, m_rayToTrans,
243 collisionObject->getCollisionShape(),
244 collisionObject->getWorldTransform(),
252 void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const
254 BT_PROFILE("rayTest");
255 /// use the broadphase to accelerate the search for objects, based on their aabb
256 /// and for each object with ray-aabb overlap, perform an exact ray test
257 btDeformableSingleRayCallback rayCB(rayFromWorld, rayToWorld, this, resultCallback);
259 #ifndef USE_BRUTEFORCE_RAYBROADPHASE
260 m_broadphasePairCache->rayTest(rayFromWorld, rayToWorld, rayCB);
262 for (int i = 0; i < this->getNumCollisionObjects(); i++)
264 rayCB.process(m_collisionObjects[i]->getBroadphaseHandle());
266 #endif //USE_BRUTEFORCE_RAYBROADPHASE
269 void rayTestSingle(const btTransform& rayFromTrans, const btTransform& rayToTrans,
270 btCollisionObject* collisionObject,
271 const btCollisionShape* collisionShape,
272 const btTransform& colObjWorldTransform,
273 RayResultCallback& resultCallback) const
275 if (collisionShape->isSoftBody())
277 btSoftBody* softBody = btSoftBody::upcast(collisionObject);
280 btSoftBody::sRayCast softResult;
281 if (softBody->rayFaceTest(rayFromTrans.getOrigin(), rayToTrans.getOrigin(), softResult))
283 if (softResult.fraction <= resultCallback.m_closestHitFraction)
285 btCollisionWorld::LocalShapeInfo shapeInfo;
286 shapeInfo.m_shapePart = 0;
287 shapeInfo.m_triangleIndex = softResult.index;
289 btVector3 rayDir = rayToTrans.getOrigin() - rayFromTrans.getOrigin();
290 btVector3 normal = -rayDir;
293 normal = softBody->m_faces[softResult.index].m_normal;
294 if (normal.dot(rayDir) > 0)
296 // normal always point toward origin of the ray
301 btCollisionWorld::LocalRayResult rayResult(collisionObject,
304 softResult.fraction);
305 bool normalInWorldSpace = true;
306 resultCallback.addSingleResult(rayResult, normalInWorldSpace);
313 btCollisionWorld::rayTestSingle(rayFromTrans, rayToTrans, collisionObject, collisionShape, colObjWorldTransform, resultCallback);
318 #endif //BT_DEFORMABLE_MULTIBODY_DYNAMICS_WORLD_H