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 
16 
18 #include "LinearMath/btQuickprof.h"
19 
20 //softbody & helpers
21 #include "btSoftBody.h"
22 #include "btSoftBodyHelpers.h"
23 #include "btSoftBodySolvers.h"
26 
27 
29  btDispatcher* dispatcher,
30  btBroadphaseInterface* pairCache,
31  btConstraintSolver* constraintSolver,
32  btCollisionConfiguration* collisionConfiguration,
33  btSoftBodySolver *softBodySolver ) :
34  btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver,collisionConfiguration),
35  m_softBodySolver( softBodySolver ),
36  m_ownsSolver(false)
37 {
38  if( !m_softBodySolver )
39  {
40  void* ptr = btAlignedAlloc(sizeof(btDefaultSoftBodySolver),16);
42  m_ownsSolver = true;
43  }
44 
46  m_drawNodeTree = true;
47  m_drawFaceTree = false;
48  m_drawClusterTree = false;
49  m_sbi.m_broadphase = pairCache;
50  m_sbi.m_dispatcher = dispatcher;
53 
54  m_sbi.air_density = (btScalar)1.2;
55  m_sbi.water_density = 0;
56  m_sbi.water_offset = 0;
57  m_sbi.water_normal = btVector3(0,0,0);
58  m_sbi.m_gravity.setValue(0,-10,0);
59 
61 
62 
63 }
64 
66 {
67  if (m_ownsSolver)
68  {
71  }
72 }
73 
75 {
77  {
78  BT_PROFILE("predictUnconstraintMotionSoftBody");
79  m_softBodySolver->predictMotion( timeStep );
80  }
81 }
82 
84 {
85 
86  // Let the solver grab the soft bodies and if necessary optimize for it
88 
90  {
91  btAssert( "Solver initialization failed\n" );
92  }
93 
95 
97  solveSoftBodiesConstraints( timeStep );
98 
99  //self collisions
100  for ( int i=0;i<m_softBodies.size();i++)
101  {
103  psb->defaultCollisionHandler(psb);
104  }
105 
108 
109  // End solver-wise simulation step
110  // ///////////////////////////////
111 
112 }
113 
115 {
116  BT_PROFILE("solveSoftConstraints");
117 
118  if(m_softBodies.size())
119  {
121  }
122 
123  // Solve constraints solver-wise
125 
126 }
127 
128 void btSoftRigidDynamicsWorld::addSoftBody(btSoftBody* body,short int collisionFilterGroup,short int collisionFilterMask)
129 {
130  m_softBodies.push_back(body);
131 
132  // Set the soft body solver that will deal with this body
133  // to be the world's solver
135 
137  collisionFilterGroup,
138  collisionFilterMask);
139 
140 }
141 
143 {
144  m_softBodies.remove(body);
145 
147 }
148 
150 {
151  btSoftBody* body = btSoftBody::upcast(collisionObject);
152  if (body)
153  removeSoftBody(body);
154  else
156 }
157 
159 {
161 
162  if (getDebugDrawer())
163  {
164  int i;
165  for ( i=0;i<this->m_softBodies.size();i++)
166  {
167  btSoftBody* psb=(btSoftBody*)this->m_softBodies[i];
169  {
172  }
173 
175  {
179  }
180  }
181  }
182 }
183 
184 
185 
186 
188 {
194 
197 
198  btSoftSingleRayCallback(const btVector3& rayFromWorld,const btVector3& rayToWorld,const btSoftRigidDynamicsWorld* world,btCollisionWorld::RayResultCallback& resultCallback)
199  :m_rayFromWorld(rayFromWorld),
200  m_rayToWorld(rayToWorld),
201  m_world(world),
202  m_resultCallback(resultCallback)
203  {
208 
209  btVector3 rayDir = (rayToWorld-rayFromWorld);
210 
211  rayDir.normalize ();
213  m_rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[0];
214  m_rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[1];
215  m_rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[2];
216  m_signs[0] = m_rayDirectionInverse[0] < 0.0;
217  m_signs[1] = m_rayDirectionInverse[1] < 0.0;
218  m_signs[2] = m_rayDirectionInverse[2] < 0.0;
219 
221 
222  }
223 
224 
225 
226  virtual bool process(const btBroadphaseProxy* proxy)
227  {
230  return false;
231 
232  btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject;
233 
234  //only perform raycast if filterMask matches
235  if(m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
236  {
237  //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
238  //btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
239 #if 0
240 #ifdef RECALCULATE_AABB
241  btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
242  collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax);
243 #else
244  //getBroadphase()->getAabb(collisionObject->getBroadphaseHandle(),collisionObjectAabbMin,collisionObjectAabbMax);
245  const btVector3& collisionObjectAabbMin = collisionObject->getBroadphaseHandle()->m_aabbMin;
246  const btVector3& collisionObjectAabbMax = collisionObject->getBroadphaseHandle()->m_aabbMax;
247 #endif
248 #endif
249  //btScalar hitLambda = m_resultCallback.m_closestHitFraction;
250  //culling already done by broadphase
251  //if (btRayAabb(m_rayFromWorld,m_rayToWorld,collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,m_hitNormal))
252  {
254  collisionObject,
255  collisionObject->getCollisionShape(),
256  collisionObject->getWorldTransform(),
258  }
259  }
260  return true;
261  }
262 };
263 
264 void btSoftRigidDynamicsWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const
265 {
266  BT_PROFILE("rayTest");
269  btSoftSingleRayCallback rayCB(rayFromWorld,rayToWorld,this,resultCallback);
270 
271 #ifndef USE_BRUTEFORCE_RAYBROADPHASE
272  m_broadphasePairCache->rayTest(rayFromWorld,rayToWorld,rayCB);
273 #else
274  for (int i=0;i<this->getNumCollisionObjects();i++)
275  {
276  rayCB.process(m_collisionObjects[i]->getBroadphaseHandle());
277  }
278 #endif //USE_BRUTEFORCE_RAYBROADPHASE
279 
280 }
281 
282 
283 void btSoftRigidDynamicsWorld::rayTestSingle(const btTransform& rayFromTrans,const btTransform& rayToTrans,
284  btCollisionObject* collisionObject,
285  const btCollisionShape* collisionShape,
286  const btTransform& colObjWorldTransform,
287  RayResultCallback& resultCallback)
288 {
289  if (collisionShape->isSoftBody()) {
290  btSoftBody* softBody = btSoftBody::upcast(collisionObject);
291  if (softBody) {
292  btSoftBody::sRayCast softResult;
293  if (softBody->rayTest(rayFromTrans.getOrigin(), rayToTrans.getOrigin(), softResult))
294  {
295 
296  if (softResult.fraction<= resultCallback.m_closestHitFraction)
297  {
298 
300  shapeInfo.m_shapePart = 0;
301  shapeInfo.m_triangleIndex = softResult.index;
302  // get the normal
303  btVector3 rayDir = rayToTrans.getOrigin() - rayFromTrans.getOrigin();
304  btVector3 normal=-rayDir;
305  normal.normalize();
306 
307  if (softResult.feature == btSoftBody::eFeature::Face)
308  {
309  normal = softBody->m_faces[softResult.index].m_normal;
310  if (normal.dot(rayDir) > 0) {
311  // normal always point toward origin of the ray
312  normal = -normal;
313  }
314  }
315 
317  (collisionObject,
318  &shapeInfo,
319  normal,
320  softResult.fraction);
321  bool normalInWorldSpace = true;
322  resultCallback.addSingleResult(rayResult,normalInWorldSpace);
323  }
324  }
325  }
326  }
327  else {
328  btCollisionWorld::rayTestSingle(rayFromTrans,rayToTrans,collisionObject,collisionShape,colObjWorldTransform,resultCallback);
329  }
330 }
331 
332 
334 {
335  int i;
336  //serialize all collision objects
337  for (i=0;i<m_collisionObjects.size();i++)
338  {
341  {
342  int len = colObj->calculateSerializeBufferSize();
343  btChunk* chunk = serializer->allocate(len,1);
344  const char* structType = colObj->serialize(chunk->m_oldPtr, serializer);
345  serializer->finalizeChunk(chunk,structType,BT_SOFTBODY_CODE,colObj);
346  }
347  }
348 
349 }
350 
352 {
353 
354  serializer->startSerialization();
355 
356  serializeDynamicsWorldInfo( serializer);
357 
358  serializeSoftBodies(serializer);
359 
360  serializeRigidBodies(serializer);
361 
362  serializeCollisionObjects(serializer);
363 
364  serializer->finishSerialization();
365 }
366 
367