Bullet Collision Detection & Physics Library
btSoftRigidDynamicsWorld.cpp
Go to the documentation of this file.
1 /*
2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
4 
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:
10 
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.
14 */
15 
17 #include "LinearMath/btQuickprof.h"
18 
19 //softbody & helpers
20 #include "btSoftBody.h"
21 #include "btSoftBodyHelpers.h"
22 #include "btSoftBodySolvers.h"
25 
27  btDispatcher* dispatcher,
28  btBroadphaseInterface* pairCache,
29  btConstraintSolver* constraintSolver,
30  btCollisionConfiguration* collisionConfiguration,
31  btSoftBodySolver* softBodySolver) : btDiscreteDynamicsWorld(dispatcher, pairCache, constraintSolver, collisionConfiguration),
32  m_softBodySolver(softBodySolver),
33  m_ownsSolver(false)
34 {
35  if (!m_softBodySolver)
36  {
37  void* ptr = btAlignedAlloc(sizeof(btDefaultSoftBodySolver), 16);
39  m_ownsSolver = true;
40  }
41 
43  m_drawNodeTree = true;
44  m_drawFaceTree = false;
45  m_drawClusterTree = false;
46  m_sbi.m_broadphase = pairCache;
47  m_sbi.m_dispatcher = dispatcher;
50 
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);
56 
58 }
59 
61 {
62  if (m_ownsSolver)
63  {
66  }
67 }
68 
70 {
72  {
73  BT_PROFILE("predictUnconstraintMotionSoftBody");
74  m_softBodySolver->predictMotion(float(timeStep));
75  }
76 }
77 
79 {
80  // Let the solver grab the soft bodies and if necessary optimize for it
82 
84  {
85  btAssert("Solver initialization failed\n");
86  }
87 
89 
92 
93  //self collisions
94  for (int i = 0; i < m_softBodies.size(); i++)
95  {
97  psb->defaultCollisionHandler(psb);
98  }
99 
102 
103  // End solver-wise simulation step
104  // ///////////////////////////////
105 }
106 
108 {
109  BT_PROFILE("solveSoftConstraints");
110 
111  if (m_softBodies.size())
112  {
114  }
115 
116  // Solve constraints solver-wise
118 }
119 
120 void btSoftRigidDynamicsWorld::addSoftBody(btSoftBody* body, int collisionFilterGroup, int collisionFilterMask)
121 {
122  m_softBodies.push_back(body);
123 
124  // Set the soft body solver that will deal with this body
125  // to be the world's solver
127 
129  collisionFilterGroup,
130  collisionFilterMask);
131 }
132 
134 {
135  m_softBodies.remove(body);
136 
138 }
139 
141 {
142  btSoftBody* body = btSoftBody::upcast(collisionObject);
143  if (body)
144  removeSoftBody(body);
145  else
147 }
148 
150 {
152 
153  if (getDebugDrawer())
154  {
155  int i;
156  for (i = 0; i < this->m_softBodies.size(); i++)
157  {
158  btSoftBody* psb = (btSoftBody*)this->m_softBodies[i];
160  {
163  }
164 
166  {
170  }
171  }
172  }
173 }
174 
176 {
182 
185 
186  btSoftSingleRayCallback(const btVector3& rayFromWorld, const btVector3& rayToWorld, const btSoftRigidDynamicsWorld* world, btCollisionWorld::RayResultCallback& resultCallback)
187  : m_rayFromWorld(rayFromWorld),
188  m_rayToWorld(rayToWorld),
189  m_world(world),
190  m_resultCallback(resultCallback)
191  {
196 
197  btVector3 rayDir = (rayToWorld - rayFromWorld);
198 
199  rayDir.normalize();
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;
207 
209  }
210 
211  virtual bool process(const btBroadphaseProxy* proxy)
212  {
215  return false;
216 
217  btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject;
218 
219  //only perform raycast if filterMask matches
220  if (m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
221  {
222  //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
223  //btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
224 #if 0
225 #ifdef RECALCULATE_AABB
226  btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
227  collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax);
228 #else
229  //getBroadphase()->getAabb(collisionObject->getBroadphaseHandle(),collisionObjectAabbMin,collisionObjectAabbMax);
230  const btVector3& collisionObjectAabbMin = collisionObject->getBroadphaseHandle()->m_aabbMin;
231  const btVector3& collisionObjectAabbMax = collisionObject->getBroadphaseHandle()->m_aabbMax;
232 #endif
233 #endif
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))
237  {
239  collisionObject,
240  collisionObject->getCollisionShape(),
241  collisionObject->getWorldTransform(),
243  }
244  }
245  return true;
246  }
247 };
248 
249 void btSoftRigidDynamicsWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const
250 {
251  BT_PROFILE("rayTest");
254  btSoftSingleRayCallback rayCB(rayFromWorld, rayToWorld, this, resultCallback);
255 
256 #ifndef USE_BRUTEFORCE_RAYBROADPHASE
257  m_broadphasePairCache->rayTest(rayFromWorld, rayToWorld, rayCB);
258 #else
259  for (int i = 0; i < this->getNumCollisionObjects(); i++)
260  {
261  rayCB.process(m_collisionObjects[i]->getBroadphaseHandle());
262  }
263 #endif //USE_BRUTEFORCE_RAYBROADPHASE
264 }
265 
266 void btSoftRigidDynamicsWorld::rayTestSingle(const btTransform& rayFromTrans, const btTransform& rayToTrans,
267  btCollisionObject* collisionObject,
268  const btCollisionShape* collisionShape,
269  const btTransform& colObjWorldTransform,
270  RayResultCallback& resultCallback)
271 {
272  if (collisionShape->isSoftBody())
273  {
274  btSoftBody* softBody = btSoftBody::upcast(collisionObject);
275  if (softBody)
276  {
277  btSoftBody::sRayCast softResult;
278  if (softBody->rayTest(rayFromTrans.getOrigin(), rayToTrans.getOrigin(), softResult))
279  {
280  if (softResult.fraction <= resultCallback.m_closestHitFraction)
281  {
283  shapeInfo.m_shapePart = 0;
284  shapeInfo.m_triangleIndex = softResult.index;
285  // get the normal
286  btVector3 rayDir = rayToTrans.getOrigin() - rayFromTrans.getOrigin();
287  btVector3 normal = -rayDir;
288  normal.normalize();
289 
290  if (softResult.feature == btSoftBody::eFeature::Face)
291  {
292  normal = softBody->m_faces[softResult.index].m_normal;
293  if (normal.dot(rayDir) > 0)
294  {
295  // normal always point toward origin of the ray
296  normal = -normal;
297  }
298  }
299 
300  btCollisionWorld::LocalRayResult rayResult(collisionObject,
301  &shapeInfo,
302  normal,
303  softResult.fraction);
304  bool normalInWorldSpace = true;
305  resultCallback.addSingleResult(rayResult, normalInWorldSpace);
306  }
307  }
308  }
309  }
310  else
311  {
312  btCollisionWorld::rayTestSingle(rayFromTrans, rayToTrans, collisionObject, collisionShape, colObjWorldTransform, resultCallback);
313  }
314 }
315 
317 {
318  int i;
319  //serialize all collision objects
320  for (i = 0; i < m_collisionObjects.size(); i++)
321  {
324  {
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);
329  }
330  }
331 }
332 
334 {
335  serializer->startSerialization();
336 
337  serializeDynamicsWorldInfo(serializer);
338 
339  serializeSoftBodies(serializer);
340 
341  serializeRigidBodies(serializer);
342 
343  serializeCollisionObjects(serializer);
344 
345  serializer->finishSerialization();
346 }
void setOrigin(const btVector3 &origin)
Set the translational element.
Definition: btTransform.h:146
virtual void internalSingleStepSimulation(btScalar timeStep)
virtual void finishSerialization()=0
void serializeDynamicsWorldInfo(btSerializer *serializer)
btSoftBodyArray & getSoftBodyArray()
void serializeCollisionObjects(btSerializer *serializer)
eFeature::_ feature
soft body
Definition: btSoftBody.h:193
void push_back(const T &_Val)
int index
feature type
Definition: btSoftBody.h:194
virtual bool checkInitialized()=0
Ensure that this solver is initialized.
virtual const char * serialize(void *dataBuffer, class btSerializer *serializer) const
fills the dataBuffer and returns the struct name (and 0 on failure)
const btSoftRigidDynamicsWorld * m_world
virtual void serialize(btSerializer *serializer)
Preliminary serialization test for Bullet 2.76. Loading those files requires a separate parser (see B...
void setValue(const btScalar &_x, const btScalar &_y, const btScalar &_z)
Definition: btVector3.h:640
btScalar water_offset
Definition: btSoftBody.h:47
void defaultCollisionHandler(const btCollisionObjectWrapper *pcoWrap)
void serializeSoftBodies(btSerializer *serializer)
virtual void addCollisionObject(btCollisionObject *collisionObject, int collisionFilterGroup=btBroadphaseProxy::DefaultFilter, int collisionFilterMask=btBroadphaseProxy::AllFilter)
void removeSoftBody(btSoftBody *body)
virtual void startSerialization()=0
btDiscreteDynamicsWorld provides discrete rigid body simulation those classes replace the obsolete Cc...
void setIdentity()
Set this transformation to the identity.
Definition: btTransform.h:166
#define btAssert(x)
Definition: btScalar.h:133
btCollisionConfiguration allows to configure Bullet collision detection stack allocator size...
btDispatcher * m_dispatcher
Definition: btSoftBody.h:51
The btCollisionShape class provides an interface for collision shapes that can be shared among btColl...
static void rayTestSingle(const btTransform &rayFromTrans, const btTransform &rayToTrans, btCollisionObject *collisionObject, const btCollisionShape *collisionShape, const btTransform &colObjWorldTransform, RayResultCallback &resultCallback)
rayTestSingle performs a raycast call and calls the resultCallback.
btScalar fraction
feature index
Definition: btSoftBody.h:195
#define BT_SOFTBODY_CODE
Definition: btSerializer.h:110
RayResultCallback is used to report new raycast results.
virtual void removeCollisionObject(btCollisionObject *collisionObject)
removeCollisionObject will first check if it is a rigid body, if so call removeRigidBody otherwise ca...
btVector3 water_normal
Definition: btSoftBody.h:49
static void DrawFaceTree(btSoftBody *psb, btIDebugDraw *idraw, int mindepth=0, int maxdepth=-1)
bool rayTest(const btVector3 &rayFrom, const btVector3 &rayTo, sRayCast &results)
Ray casting using rayFrom and rayTo in worldspace, (not direction!)
virtual void getAabb(const btTransform &t, btVector3 &aabbMin, btVector3 &aabbMax) const =0
getAabb returns the axis aligned bounding box in the coordinate frame of the given transform t...
btVector3 & normalize()
Normalize this vector x^2 + y^2 + z^2 = 1.
Definition: btVector3.h:303
btCollisionWorld::RayResultCallback & m_resultCallback
int getNumCollisionObjects() const
static void Draw(btSoftBody *psb, btIDebugDraw *idraw, int drawflags=fDrawFlags::Std)
btSparseSdf< 3 > m_sparsesdf
Definition: btSoftBody.h:53
static void solveClusters(const btAlignedObjectArray< btSoftBody *> &bodies)
virtual btScalar addSingleResult(LocalRayResult &rayResult, bool normalInWorldSpace)=0
btTransform & getWorldTransform()
btVector3 & getOrigin()
Return the origin vector translation.
Definition: btTransform.h:113
btBroadphaseProxy * getBroadphaseHandle()
virtual void predictMotion(float solverdt)=0
Predict motion of soft bodies into next timestep.
virtual void solveConstraints(float solverdt)=0
Solve constraints for a set of soft bodies.
virtual void removeCollisionObject(btCollisionObject *collisionObject)
removeCollisionObject will first check if it is a rigid body, if so call removeRigidBody otherwise ca...
btIDebugDraw * m_debugDrawer
virtual btIDebugDraw * getDebugDrawer()
const btSoftMultiBodyDynamicsWorld * m_world
static const btSoftBody * upcast(const btCollisionObject *colObj)
Definition: btSoftBody.h:962
virtual ~btSoftBodySolver()
virtual bool needsCollision(btBroadphaseProxy *proxy0) const
btScalar dot(const btVector3 &v) const
Return the dot product.
Definition: btVector3.h:229
virtual void optimize(btAlignedObjectArray< btSoftBody *> &softBodies, bool forceUpdate=false)=0
Optimize soft bodies in this solver.
virtual void predictUnconstraintMotion(btScalar timeStep)
virtual void internalSingleStepSimulation(btScalar timeStep)
#define btAlignedFree(ptr)
btCollisionObject can be used to manage collision detection objects.
static void rayTestSingle(const btTransform &rayFromTrans, const btTransform &rayToTrans, btCollisionObject *collisionObject, const btCollisionShape *collisionShape, const btTransform &colObjWorldTransform, RayResultCallback &resultCallback)
rayTestSingle performs a raycast call and calls the resultCallback.
LocalShapeInfo gives extra information for complex shapes Currently, only btTriangleMeshShape is avai...
virtual void removeCollisionObject(btCollisionObject *collisionObject)
virtual int calculateSerializeBufferSize() const
The btBroadphaseInterface class provides an interface to detect aabb-overlapping object pairs...
btSoftSingleRayCallback(const btVector3 &rayFromWorld, const btVector3 &rayToWorld, const btSoftRigidDynamicsWorld *world, btCollisionWorld::RayResultCallback &resultCallback)
The btBroadphaseProxy is the main class that can be used with the Bullet broadphases.
virtual void predictUnconstraintMotion(btScalar timeStep)
static void DrawNodeTree(btSoftBody *psb, btIDebugDraw *idraw, int mindepth=0, int maxdepth=-1)
btSoftBodySolver * m_softBodySolver
Solver classes that encapsulate multiple soft bodies for solving.
static void DrawClusterTree(btSoftBody *psb, btIDebugDraw *idraw, int mindepth=0, int maxdepth=-1)
btVector3 can be used to represent 3D points and vectors.
Definition: btVector3.h:80
virtual void updateSoftBodies()=0
Perform necessary per-step updates of soft bodies such as recomputing normals and bounding boxes...
int size() const
return the number of elements in the array
#define BT_PROFILE(name)
Definition: btQuickprof.h:198
The btTransform class supports rigid transforms with only translation and rotation and no scaling/she...
Definition: btTransform.h:28
void solveSoftBodiesConstraints(btScalar timeStep)
virtual void finalizeChunk(btChunk *chunk, const char *structType, int chunkCode, void *oldPtr)=0
virtual bool process(const btBroadphaseProxy *proxy)
void addSoftBody(btSoftBody *body, int collisionFilterGroup=btBroadphaseProxy::DefaultFilter, int collisionFilterMask=btBroadphaseProxy::AllFilter)
void remove(const T &key)
bool isSoftBody() const
int getInternalType() const
reserved for Bullet internal usage
virtual int getDebugMode() const =0
btAlignedObjectArray< btCollisionObject * > m_collisionObjects
void setSoftBodySolver(btSoftBodySolver *softBodySolver)
Definition: btSoftBody.h:937
btVector3 m_rayDirectionInverse
added some cached data to accelerate ray-AABB tests
float getTimeScale()
Return the timescale that the simulation is using.
btScalar water_density
Definition: btSoftBody.h:46
btBroadphaseInterface * m_broadphasePairCache
#define btAlignedAlloc(size, alignment)
virtual void rayTest(const btVector3 &rayFromWorld, const btVector3 &rayToWorld, RayResultCallback &resultCallback) const
rayTest performs a raycast on all objects in the btCollisionWorld, and calls the resultCallback This ...
btBroadphaseInterface * m_broadphase
Definition: btSoftBody.h:50
btScalar air_density
Definition: btSoftBody.h:45
void serializeRigidBodies(btSerializer *serializer)
btVector3 m_gravity
Definition: btSoftBody.h:52
btSoftRigidDynamicsWorld(btDispatcher *dispatcher, btBroadphaseInterface *pairCache, btConstraintSolver *constraintSolver, btCollisionConfiguration *collisionConfiguration, btSoftBodySolver *softBodySolver=0)
The btSoftBody is an class to simulate cloth and volumetric soft bodies.
Definition: btSoftBody.h:70
The btDispatcher interface class can be used in combination with broadphase to dispatch calculations ...
Definition: btDispatcher.h:76
void * m_oldPtr
Definition: btSerializer.h:52
virtual btChunk * allocate(size_t size, int numElements)=0
virtual void rayTest(const btVector3 &rayFrom, const btVector3 &rayTo, btBroadphaseRayCallback &rayCallback, const btVector3 &aabbMin=btVector3(0, 0, 0), const btVector3 &aabbMax=btVector3(0, 0, 0))=0
static void rayTestSingle(const btTransform &rayFromTrans, const btTransform &rayToTrans, btCollisionObject *collisionObject, const btCollisionShape *collisionShape, const btTransform &colObjWorldTransform, RayResultCallback &resultCallback)
rayTestSingle performs a raycast call and calls the resultCallback.
static void DrawFrame(btSoftBody *psb, btIDebugDraw *idraw)
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
Definition: btScalar.h:294
const btCollisionShape * getCollisionShape() const
void Reset()
Definition: btSparseSDF.h:93
void Initialize(int hashsize=2383, int clampCells=256 *1024)
Definition: btSparseSDF.h:84
tFaceArray m_faces
Definition: btSoftBody.h:693