1 /*
2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2006 Erwin Coumans https://bulletphysics.org
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 ///btSoftBody implementation by Nathanael Presson
17
18 #include "btBulletDynamicsCommon.h"
19 #include "BulletSoftBody/btSoftRigidDynamicsWorld.h"
20
21 #include "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h"
22 #include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
23 #include "LinearMath/btQuickprof.h"
24 #include "LinearMath/btIDebugDraw.h"
25
26 #include "BunnyMesh.h"
27 #include "TorusMesh.h"
28 #include <stdio.h> //printf debugging
29 #include "LinearMath/btConvexHull.h"
30 #include "BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h"
31 #include "BulletSoftBody/btSoftBodyHelpers.h"
32
33 #include "SoftDemo.h"
34 #include "GL_ShapeDrawer.h"
35
36 #include "LinearMath/btAlignedObjectArray.h"
37 #include "BulletSoftBody/btSoftBody.h"
38
39 class btBroadphaseInterface;
40 class btCollisionShape;
41 class btOverlappingPairCache;
42 class btCollisionDispatcher;
43 class btConstraintSolver;
44 struct btCollisionAlgorithmCreateFunc;
45 class btDefaultCollisionConfiguration;
46
47 ///collisions between two btSoftBody's
48 class btSoftSoftCollisionAlgorithm;
49
50 ///collisions between a btSoftBody and a btRigidBody
51 class btSoftRididCollisionAlgorithm;
52 class btSoftRigidDynamicsWorld;
53
54 #include "../CommonInterfaces/CommonRigidBodyBase.h"
55
56 class SoftDemo : public CommonRigidBodyBase
57 {
58 public:
59 btAlignedObjectArray<btSoftSoftCollisionAlgorithm*> m_SoftSoftCollisionAlgorithms;
60
61 btAlignedObjectArray<btSoftRididCollisionAlgorithm*> m_SoftRigidCollisionAlgorithms;
62
63 btSoftBodyWorldInfo m_softBodyWorldInfo;
64
65 bool m_autocam;
66 bool m_cutting;
67 bool m_raycast;
68 btScalar m_animtime;
69 btClock m_clock;
70 int m_lastmousepos[2];
71 btVector3 m_impact;
72 btSoftBody::sRayCast m_results;
73 btSoftBody::Node* m_node;
74 btVector3 m_goal;
75 bool m_drag;
76
77 //keep the collision shapes, for deletion/cleanup
78 btAlignedObjectArray<btCollisionShape*> m_collisionShapes;
79
80 btBroadphaseInterface* m_broadphase;
81
82 btCollisionDispatcher* m_dispatcher;
83
84 btConstraintSolver* m_solver;
85
86 btCollisionAlgorithmCreateFunc* m_boxBoxCF;
87
88 btDefaultCollisionConfiguration* m_collisionConfiguration;
89
90 public:
91 void initPhysics();
92
93 void exitPhysics();
94
resetCamera()95 virtual void resetCamera()
96 {
97 //@todo depends on current_demo?
98 float dist = 45;
99 float pitch = -31;
100 float yaw = 27;
101 float targetPos[3] = {10 - 1, 0};
102 m_guiHelper->resetCamera(dist, yaw, pitch, targetPos[0], targetPos[1], targetPos[2]);
103 }
104
SoftDemo(struct GUIHelperInterface * helper)105 SoftDemo(struct GUIHelperInterface* helper)
106 : CommonRigidBodyBase(helper),
107 m_drag(false)
108
109 {
110 }
~SoftDemo()111 virtual ~SoftDemo()
112 {
113 btAssert(m_dynamicsWorld == 0);
114 }
115
116 //virtual void clientMoveAndDisplay();
117
118 //virtual void displayCallback();
119
120 void createStack(btCollisionShape* boxShape, float halfCubeSize, int size, float zPos);
121
122 virtual void setDrawClusters(bool drawClusters);
123
getSoftDynamicsWorld() const124 virtual const btSoftRigidDynamicsWorld* getSoftDynamicsWorld() const
125 {
126 ///just make it a btSoftRigidDynamicsWorld please
127 ///or we will add type checking
128 return (btSoftRigidDynamicsWorld*)m_dynamicsWorld;
129 }
130
getSoftDynamicsWorld()131 virtual btSoftRigidDynamicsWorld* getSoftDynamicsWorld()
132 {
133 ///just make it a btSoftRigidDynamicsWorld please
134 ///or we will add type checking
135 return (btSoftRigidDynamicsWorld*)m_dynamicsWorld;
136 }
137
138 //
139 //void clientResetScene();
140 void renderme();
141 void keyboardCallback(unsigned char key, int x, int y);
142 void mouseFunc(int button, int state, int x, int y);
143 void mouseMotionFunc(int x, int y);
144
getGUIHelper()145 GUIHelperInterface* getGUIHelper()
146 {
147 return m_guiHelper;
148 }
149
renderScene()150 virtual void renderScene()
151 {
152 CommonRigidBodyBase::renderScene();
153 btSoftRigidDynamicsWorld* softWorld = getSoftDynamicsWorld();
154
155 for (int i = 0; i < softWorld->getSoftBodyArray().size(); i++)
156 {
157 btSoftBody* psb = (btSoftBody*)softWorld->getSoftBodyArray()[i];
158 //if (softWorld->getDebugDrawer() && !(softWorld->getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe)))
159 {
160 btSoftBodyHelpers::DrawFrame(psb, softWorld->getDebugDrawer());
161 btSoftBodyHelpers::Draw(psb, softWorld->getDebugDrawer(), softWorld->getDrawFlags());
162 }
163 }
164 }
165 };
166
167 #define MACRO_SOFT_DEMO(a) \
168 class SoftDemo##a : public SoftDemo \
169 { \
170 public: \
171 static DemoApplication* Create() \
172 { \
173 SoftDemo* demo = new SoftDemo##a; \
174 extern int current_demo; \
175 current_demo = a; \
176 demo->initPhysics(); \
177 return demo; \
178 } \
179 };
180
181 //MACRO_SOFT_DEMO(0) //Init_Cloth
182 #if 0
183 MACRO_SOFT_DEMO(1) //Init_Pressure
184 MACRO_SOFT_DEMO(2)//Init_Volume
185 MACRO_SOFT_DEMO(3)//Init_Ropes
186 MACRO_SOFT_DEMO(4)//Init_Ropes_Attach
187 MACRO_SOFT_DEMO(5)//Init_ClothAttach
188 MACRO_SOFT_DEMO(6)//Init_Sticks
189 MACRO_SOFT_DEMO(7)//Init_Collide
190 MACRO_SOFT_DEMO(8)//Init_Collide2
191 MACRO_SOFT_DEMO(9)//Init_Collide3
192 MACRO_SOFT_DEMO(10)//Init_Impact
193 MACRO_SOFT_DEMO(11)//Init_Aero
194 MACRO_SOFT_DEMO(12)//Init_Friction
195 MACRO_SOFT_DEMO(13)//Init_Torus
196 MACRO_SOFT_DEMO(14)//Init_TorusMatch
197 MACRO_SOFT_DEMO(15)//Init_Bunny
198 MACRO_SOFT_DEMO(16)//Init_BunnyMatch
199 MACRO_SOFT_DEMO(17)//Init_Cutting1
200 MACRO_SOFT_DEMO(18)//Init_ClusterDeform
201 MACRO_SOFT_DEMO(19)//Init_ClusterCollide1
202 MACRO_SOFT_DEMO(20)//Init_ClusterCollide2
203 MACRO_SOFT_DEMO(21)//Init_ClusterSocket
204 MACRO_SOFT_DEMO(22)//Init_ClusterHinge
205 MACRO_SOFT_DEMO(23)//Init_ClusterCombine
206 MACRO_SOFT_DEMO(24)//Init_ClusterCar
207 MACRO_SOFT_DEMO(25)//Init_ClusterRobot
208 MACRO_SOFT_DEMO(26)//Init_ClusterStackSoft
209 MACRO_SOFT_DEMO(27)//Init_ClusterStackMixed
210 MACRO_SOFT_DEMO(28)//Init_TetraCube
211 MACRO_SOFT_DEMO(29)//Init_TetraBunny
212
213 #endif
214
215 extern float eye[3];
216 extern int glutScreenWidth;
217 extern int glutScreenHeight;
218
219 //static bool sDemoMode = false;
220
221 const int maxProxies = 32766;
222 //const int maxOverlap = 65535;
223
224 static btVector3* gGroundVertices = 0;
225 static int* gGroundIndices = 0;
226 //static btBvhTriangleMeshShape* trimeshShape =0;
227 //static btRigidBody* staticBody = 0;
228 static float waveheight = 5.f;
229
230 const float TRIANGLE_SIZE = 8.f;
231 int current_demo = 20;
232 #define DEMO_MODE_TIMEOUT 15.f //15 seconds for each demo
233
234 #ifdef _DEBUG
235 //const int gNumObjects = 1;
236 #else
237 //const int gNumObjects = 1;//try this in release mode: 3000. never go above 16384, unless you increate maxNumObjects value in DemoApplication.cp
238 #endif
239
240 //const int maxNumObjects = 32760;
241
242 #define CUBE_HALF_EXTENTS 1.5
243 #define EXTRA_HEIGHT -10.f
244
245 //
createStack(btCollisionShape * boxShape,float halfCubeSize,int size,float zPos)246 void SoftDemo::createStack(btCollisionShape* boxShape, float halfCubeSize, int size, float zPos)
247 {
248 btTransform trans;
249 trans.setIdentity();
250
251 for (int i = 0; i < size; i++)
252 {
253 // This constructs a row, from left to right
254 int rowSize = size - i;
255 for (int j = 0; j < rowSize; j++)
256 {
257 btVector3 pos;
258 pos.setValue(
259 -rowSize * halfCubeSize + halfCubeSize + j * 2.0f * halfCubeSize,
260 halfCubeSize + i * halfCubeSize * 2.0f,
261 zPos);
262
263 trans.setOrigin(pos);
264 btScalar mass = 1.f;
265
266 btRigidBody* body = 0;
267 body = createRigidBody(mass, trans, boxShape);
268 }
269 }
270 }
271
272 ////////////////////////////////////
273 ///for mouse picking
pickingPreTickCallback(btDynamicsWorld * world,btScalar timeStep)274 void pickingPreTickCallback(btDynamicsWorld* world, btScalar timeStep)
275 {
276 SoftDemo* softDemo = (SoftDemo*)world->getWorldUserInfo();
277
278 if (softDemo->m_drag)
279 {
280 const int x = softDemo->m_lastmousepos[0];
281 const int y = softDemo->m_lastmousepos[1];
282 float rf[3];
283 softDemo->getGUIHelper()->getRenderInterface()->getActiveCamera()->getCameraPosition(rf);
284 float target[3];
285 softDemo->getGUIHelper()->getRenderInterface()->getActiveCamera()->getCameraTargetPosition(target);
286 btVector3 cameraTargetPosition(target[0], target[1], target[2]);
287
288 const btVector3 cameraPosition(rf[0], rf[1], rf[2]);
289 const btVector3 rayFrom = cameraPosition;
290
291 const btVector3 rayTo = softDemo->getRayTo(x, y);
292 const btVector3 rayDir = (rayTo - rayFrom).normalized();
293 const btVector3 N = (cameraTargetPosition - cameraPosition).normalized();
294 const btScalar O = btDot(softDemo->m_impact, N);
295 const btScalar den = btDot(N, rayDir);
296 if ((den * den) > 0)
297 {
298 const btScalar num = O - btDot(N, rayFrom);
299 const btScalar hit = num / den;
300 if ((hit > 0) && (hit < 1500))
301 {
302 softDemo->m_goal = rayFrom + rayDir * hit;
303 }
304 }
305 btVector3 delta = softDemo->m_goal - softDemo->m_node->m_x;
306 static const btScalar maxdrag = 10;
307 if (delta.length2() > (maxdrag * maxdrag))
308 {
309 delta = delta.normalized() * maxdrag;
310 }
311 softDemo->m_node->m_v += delta / timeStep;
312 }
313 }
314
315 //
316 // ImplicitShape
317 //
318
319 //
320 struct ImplicitSphere : btSoftBody::ImplicitFn
321 {
322 btVector3 center;
323 btScalar sqradius;
ImplicitSphereImplicitSphere324 ImplicitSphere() {}
ImplicitSphereImplicitSphere325 ImplicitSphere(const btVector3& c, btScalar r) : center(c), sqradius(r * r) {}
EvalImplicitSphere326 btScalar Eval(const btVector3& x)
327 {
328 return ((x - center).length2() - sqradius);
329 }
330 };
331
332 //
333 // Tetra meshes
334 //
335
336 struct TetraBunny
337 {
338 #include "bunny.inl"
339 };
340
341 struct TetraCube
342 {
343 #include "cube.inl"
344 };
345
346 //
347 // Random
348 //
349
UnitRand()350 static inline btScalar UnitRand()
351 {
352 return (rand() / (btScalar)RAND_MAX);
353 }
354
SignedUnitRand()355 static inline btScalar SignedUnitRand()
356 {
357 return (UnitRand() * 2 - 1);
358 }
359
Vector3Rand()360 static inline btVector3 Vector3Rand()
361 {
362 const btVector3 p = btVector3(SignedUnitRand(), SignedUnitRand(), SignedUnitRand());
363 return (p.normalized());
364 }
365
366 //
367 // Rb rain
368 //
Ctor_RbUpStack(SoftDemo * pdemo,int count)369 static void Ctor_RbUpStack(SoftDemo* pdemo, int count)
370 {
371 float mass = 10;
372
373 btCompoundShape* cylinderCompound = new btCompoundShape;
374 btCollisionShape* cylinderShape = new btCylinderShapeX(btVector3(4, 1, 1));
375 btCollisionShape* boxShape = new btBoxShape(btVector3(4, 1, 1));
376 btTransform localTransform;
377 localTransform.setIdentity();
378 cylinderCompound->addChildShape(localTransform, boxShape);
379 btQuaternion orn(SIMD_HALF_PI, 0, 0);
380 localTransform.setRotation(orn);
381 // localTransform.setOrigin(btVector3(1,1,1));
382 cylinderCompound->addChildShape(localTransform, cylinderShape);
383
384 btCollisionShape* shape[] = {cylinderCompound,
385 new btBoxShape(btVector3(1, 1, 1)),
386 new btSphereShape(1.5)
387
388 };
389 static const int nshapes = sizeof(shape) / sizeof(shape[0]);
390 for (int i = 0; i < count; ++i)
391 {
392 btTransform startTransform;
393 startTransform.setIdentity();
394 startTransform.setOrigin(btVector3(0, 2 + 6 * i, 0));
395 pdemo->createRigidBody(mass, startTransform, shape[i % nshapes]);
396 //pdemo->createRigidBody(mass,startTransform,shape[0]);
397 }
398 }
399
400 //
401 // Big ball
402 //
Ctor_BigBall(SoftDemo * pdemo,btScalar mass=10)403 static void Ctor_BigBall(SoftDemo* pdemo, btScalar mass = 10)
404 {
405 btTransform startTransform;
406 startTransform.setIdentity();
407 startTransform.setOrigin(btVector3(0, 13, 0));
408 pdemo->createRigidBody(mass, startTransform, new btSphereShape(3));
409 }
410
411 //
412 // Big plate
413 //
Ctor_BigPlate(SoftDemo * pdemo,btScalar mass=15,btScalar height=4)414 static btRigidBody* Ctor_BigPlate(SoftDemo* pdemo, btScalar mass = 15, btScalar height = 4)
415 {
416 btTransform startTransform;
417 startTransform.setIdentity();
418 startTransform.setOrigin(btVector3(0, height, 0.5));
419 btRigidBody* body = pdemo->createRigidBody(mass, startTransform, new btBoxShape(btVector3(5, 1, 5)));
420 body->setFriction(1);
421 return (body);
422 }
423
424 //
425 // Linear stair
426 //
Ctor_LinearStair(SoftDemo * pdemo,const btVector3 & org,const btVector3 & sizes,btScalar angle,int count)427 static void Ctor_LinearStair(SoftDemo* pdemo, const btVector3& org, const btVector3& sizes, btScalar angle, int count)
428 {
429 btBoxShape* shape = new btBoxShape(sizes);
430 for (int i = 0; i < count; ++i)
431 {
432 btTransform startTransform;
433 startTransform.setIdentity();
434 startTransform.setOrigin(org + btVector3(sizes.x() * i * 2, sizes.y() * i * 2, 0));
435 btRigidBody* body = pdemo->createRigidBody(0, startTransform, shape);
436 body->setFriction(1);
437 }
438 }
439
440 //
441 // Softbox
442 //
Ctor_SoftBox(SoftDemo * pdemo,const btVector3 & p,const btVector3 & s)443 static btSoftBody* Ctor_SoftBox(SoftDemo* pdemo, const btVector3& p, const btVector3& s)
444 {
445 const btVector3 h = s * 0.5;
446 const btVector3 c[] = {p + h * btVector3(-1, -1, -1),
447 p + h * btVector3(+1, -1, -1),
448 p + h * btVector3(-1, +1, -1),
449 p + h * btVector3(+1, +1, -1),
450 p + h * btVector3(-1, -1, +1),
451 p + h * btVector3(+1, -1, +1),
452 p + h * btVector3(-1, +1, +1),
453 p + h * btVector3(+1, +1, +1)};
454 btSoftBody* psb = btSoftBodyHelpers::CreateFromConvexHull(pdemo->m_softBodyWorldInfo, c, 8);
455 psb->generateBendingConstraints(2);
456 pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
457
458 return (psb);
459 }
460
461 //
462 // SoftBoulder
463 //
Ctor_SoftBoulder(SoftDemo * pdemo,const btVector3 & p,const btVector3 & s,int np,int id)464 static btSoftBody* Ctor_SoftBoulder(SoftDemo* pdemo, const btVector3& p, const btVector3& s, int np, int id)
465 {
466 btAlignedObjectArray<btVector3> pts;
467 if (id) srand(id);
468 for (int i = 0; i < np; ++i)
469 {
470 pts.push_back(Vector3Rand() * s + p);
471 }
472 btSoftBody* psb = btSoftBodyHelpers::CreateFromConvexHull(pdemo->m_softBodyWorldInfo, &pts[0], pts.size());
473 psb->generateBendingConstraints(2);
474 pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
475
476 return (psb);
477 }
478
479 //#define TRACEDEMO { pdemo->demoname=__FUNCTION__+5;printf("Launching demo: " __FUNCTION__ "\r\n"); }
480
481 //
482 // Basic ropes
483 //
Init_Ropes(SoftDemo * pdemo)484 static void Init_Ropes(SoftDemo* pdemo)
485 {
486 //TRACEDEMO
487 const int n = 15;
488 for (int i = 0; i < n; ++i)
489 {
490 btSoftBody* psb = btSoftBodyHelpers::CreateRope(pdemo->m_softBodyWorldInfo, btVector3(-10, 0, i * 0.25),
491 btVector3(10, 0, i * 0.25),
492 16,
493 1 + 2);
494 psb->m_cfg.piterations = 4;
495 psb->m_materials[0]->m_kLST = 0.1 + (i / (btScalar)(n - 1)) * 0.9;
496 psb->setTotalMass(20);
497 pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
498 }
499 }
500
501 //
502 // Rope attach
503 //
Init_RopeAttach(SoftDemo * pdemo)504 static void Init_RopeAttach(SoftDemo* pdemo)
505 {
506 //TRACEDEMO
507 pdemo->m_softBodyWorldInfo.m_sparsesdf.RemoveReferences(0);
508 struct Functors
509 {
510 static btSoftBody* CtorRope(SoftDemo* pdemo, const btVector3& p)
511 {
512 btSoftBody* psb = btSoftBodyHelpers::CreateRope(pdemo->m_softBodyWorldInfo, p, p + btVector3(10, 0, 0), 8, 1);
513 psb->setTotalMass(50);
514 pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
515 return (psb);
516 }
517 };
518 btTransform startTransform;
519 startTransform.setIdentity();
520 startTransform.setOrigin(btVector3(12, 8, 0));
521 btRigidBody* body = pdemo->createRigidBody(50, startTransform, new btBoxShape(btVector3(2, 6, 2)));
522 btSoftBody* psb0 = Functors::CtorRope(pdemo, btVector3(0, 8, -1));
523 btSoftBody* psb1 = Functors::CtorRope(pdemo, btVector3(0, 8, +1));
524 psb0->appendAnchor(psb0->m_nodes.size() - 1, body);
525 psb1->appendAnchor(psb1->m_nodes.size() - 1, body);
526 }
527
528 //
529 // Cloth attach
530 //
Init_ClothAttach(SoftDemo * pdemo)531 static void Init_ClothAttach(SoftDemo* pdemo)
532 {
533 //TRACEDEMO
534 const btScalar s = 4;
535 const btScalar h = 6;
536 const int r = 9;
537 btSoftBody* psb = btSoftBodyHelpers::CreatePatch(pdemo->m_softBodyWorldInfo, btVector3(-s, h, -s),
538 btVector3(+s, h, -s),
539 btVector3(-s, h, +s),
540 btVector3(+s, h, +s), r, r, 4 + 8, true);
541 pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
542
543 btTransform startTransform;
544 startTransform.setIdentity();
545 startTransform.setOrigin(btVector3(0, h, -(s + 3.5)));
546 btRigidBody* body = pdemo->createRigidBody(20, startTransform, new btBoxShape(btVector3(s, 1, 3)));
547 psb->appendAnchor(0, body);
548 psb->appendAnchor(r - 1, body);
549 pdemo->m_cutting = true;
550 }
551
552 //
553 // Impact
554 //
Init_Impact(SoftDemo * pdemo)555 static void Init_Impact(SoftDemo* pdemo)
556 {
557 //TRACEDEMO
558 btSoftBody* psb = btSoftBodyHelpers::CreateRope(pdemo->m_softBodyWorldInfo, btVector3(0, 0, 0),
559 btVector3(0, -1, 0),
560 0,
561 1);
562 pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
563 psb->m_cfg.kCHR = 0.5;
564 btTransform startTransform;
565 startTransform.setIdentity();
566 startTransform.setOrigin(btVector3(0, 20, 0));
567 pdemo->createRigidBody(10, startTransform, new btBoxShape(btVector3(2, 2, 2)));
568 }
569
Init_CapsuleCollision(SoftDemo * pdemo)570 static void Init_CapsuleCollision(SoftDemo* pdemo)
571 {
572 #ifdef USE_AMD_OPENCL
573 btAlignedObjectArray<btSoftBody*> emptyArray;
574 if (g_openCLSIMDSolver)
575 g_openCLSIMDSolver->optimize(emptyArray);
576 #endif //USE_AMD_OPENCL
577
578 //TRACEDEMO
579 const btScalar s = 4;
580 const btScalar h = 6;
581 const int r = 20;
582
583 btTransform startTransform;
584 startTransform.setIdentity();
585 startTransform.setOrigin(btVector3(0, h - 2, 0));
586
587 btCollisionShape* capsuleShape = new btCapsuleShapeX(1, 5);
588 capsuleShape->setMargin(0.5);
589
590 // capsule->setLocalScaling(btVector3(5,1,1));
591 // btRigidBody* body=pdemo->createRigidBody(20,startTransform,capsuleShape);
592 btRigidBody* body = pdemo->createRigidBody(0, startTransform, capsuleShape);
593 body->setFriction(0.8f);
594
595 int fixed = 0; //4+8;
596 btSoftBody* psb = btSoftBodyHelpers::CreatePatch(pdemo->m_softBodyWorldInfo, btVector3(-s, h, -s),
597 btVector3(+s, h, -s),
598 btVector3(-s, h, +s),
599 btVector3(+s, h, +s), r, r, fixed, true);
600 pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
601 psb->setTotalMass(0.1);
602
603 psb->m_cfg.piterations = 10;
604 psb->m_cfg.citerations = 10;
605 psb->m_cfg.diterations = 10;
606 // psb->m_cfg.viterations = 10;
607
608 // psb->appendAnchor(0,body);
609 // psb->appendAnchor(r-1,body);
610 // pdemo->m_cutting=true;
611 }
612
613 //
614 // Collide
615 //
Init_Collide(SoftDemo * pdemo)616 static void Init_Collide(SoftDemo* pdemo)
617 {
618 //TRACEDEMO
619 struct Functor
620 {
621 static btSoftBody* Create(SoftDemo* pdemo, const btVector3& x, const btVector3& a)
622 {
623 btSoftBody* psb = btSoftBodyHelpers::CreateFromTriMesh(pdemo->m_softBodyWorldInfo, gVertices,
624 &gIndices[0][0],
625 NUM_TRIANGLES);
626 psb->generateBendingConstraints(2);
627 psb->m_cfg.piterations = 2;
628 psb->m_cfg.collisions |= btSoftBody::fCollision::VF_SS;
629 psb->randomizeConstraints();
630 btMatrix3x3 m;
631 m.setEulerZYX(a.x(), a.y(), a.z());
632 psb->transform(btTransform(m, x));
633 psb->scale(btVector3(2, 2, 2));
634 psb->setTotalMass(50, true);
635 pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
636 return (psb);
637 }
638 };
639 for (int i = 0; i < 3; ++i)
640 {
641 Functor::Create(pdemo, btVector3(3 * i, 2, 0), btVector3(SIMD_PI / 2 * (1 - (i & 1)), SIMD_PI / 2 * (i & 1), 0));
642 }
643 pdemo->m_cutting = true;
644 }
645
646 //
647 // Collide2
648 //
Init_Collide2(SoftDemo * pdemo)649 static void Init_Collide2(SoftDemo* pdemo)
650 {
651 //TRACEDEMO
652 struct Functor
653 {
654 static btSoftBody* Create(SoftDemo* pdemo, const btVector3& x, const btVector3& a)
655 {
656 btSoftBody* psb = btSoftBodyHelpers::CreateFromTriMesh(pdemo->m_softBodyWorldInfo, gVerticesBunny,
657 &gIndicesBunny[0][0],
658 BUNNY_NUM_TRIANGLES);
659 btSoftBody::Material* pm = psb->appendMaterial();
660 pm->m_kLST = 0.5;
661 pm->m_flags -= btSoftBody::fMaterial::DebugDraw;
662 psb->generateBendingConstraints(2, pm);
663 psb->m_cfg.piterations = 2;
664 psb->m_cfg.kDF = 0.5;
665 psb->m_cfg.collisions |= btSoftBody::fCollision::VF_SS;
666 psb->randomizeConstraints();
667 btMatrix3x3 m;
668 m.setEulerZYX(a.x(), a.y(), a.z());
669 psb->transform(btTransform(m, x));
670 psb->scale(btVector3(6, 6, 6));
671 psb->setTotalMass(100, true);
672 pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
673 return (psb);
674 }
675 };
676 for (int i = 0; i < 3; ++i)
677 {
678 Functor::Create(pdemo, btVector3(0, -1 + 5 * i, 0), btVector3(0, SIMD_PI / 2 * (i & 1), 0));
679 }
680 pdemo->m_cutting = true;
681 }
682
683 //
684 // Collide3
685 //
Init_Collide3(SoftDemo * pdemo)686 static void Init_Collide3(SoftDemo* pdemo)
687 {
688 //TRACEDEMO
689 {
690 const btScalar s = 8;
691 btSoftBody* psb = btSoftBodyHelpers::CreatePatch(pdemo->m_softBodyWorldInfo, btVector3(-s, 0, -s),
692 btVector3(+s, 0, -s),
693 btVector3(-s, 0, +s),
694 btVector3(+s, 0, +s),
695 15, 15, 1 + 2 + 4 + 8, true);
696 psb->m_materials[0]->m_kLST = 0.4;
697 psb->m_cfg.collisions |= btSoftBody::fCollision::VF_SS;
698 psb->setTotalMass(150);
699 pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
700 }
701 {
702 const btScalar s = 4;
703 const btVector3 o = btVector3(5, 10, 0);
704 btSoftBody* psb = btSoftBodyHelpers::CreatePatch(pdemo->m_softBodyWorldInfo,
705 btVector3(-s, 0, -s) + o,
706 btVector3(+s, 0, -s) + o,
707 btVector3(-s, 0, +s) + o,
708 btVector3(+s, 0, +s) + o,
709 7, 7, 0, true);
710 btSoftBody::Material* pm = psb->appendMaterial();
711 pm->m_kLST = 0.1;
712 pm->m_flags -= btSoftBody::fMaterial::DebugDraw;
713 psb->generateBendingConstraints(2, pm);
714 psb->m_materials[0]->m_kLST = 0.5;
715 psb->m_cfg.collisions |= btSoftBody::fCollision::VF_SS;
716 psb->setTotalMass(150);
717 pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
718 pdemo->m_cutting = true;
719 }
720 }
721
722 //
723 // Aerodynamic forces, 50x1g flyers
724 //
Init_Aero(SoftDemo * pdemo)725 static void Init_Aero(SoftDemo* pdemo)
726 {
727 //TRACEDEMO
728 const btScalar s = 2;
729 const btScalar h = 10;
730 const int segments = 6;
731 const int count = 50;
732 for (int i = 0; i < count; ++i)
733 {
734 btSoftBody* psb = btSoftBodyHelpers::CreatePatch(pdemo->m_softBodyWorldInfo, btVector3(-s, h, -s),
735 btVector3(+s, h, -s),
736 btVector3(-s, h, +s),
737 btVector3(+s, h, +s),
738 segments, segments,
739 0, true);
740 btSoftBody::Material* pm = psb->appendMaterial();
741 pm->m_flags -= btSoftBody::fMaterial::DebugDraw;
742 psb->generateBendingConstraints(2, pm);
743 psb->m_cfg.kLF = 0.004;
744 psb->m_cfg.kDG = 0.0003;
745 psb->m_cfg.aeromodel = btSoftBody::eAeroModel::V_TwoSided;
746 btTransform trs;
747 btQuaternion rot;
748 btVector3 ra = Vector3Rand() * 0.1;
749 btVector3 rp = Vector3Rand() * 15 + btVector3(0, 20, 80);
750 rot.setEuler(SIMD_PI / 8 + ra.x(), -SIMD_PI / 7 + ra.y(), ra.z());
751 trs.setIdentity();
752 trs.setOrigin(rp);
753 trs.setRotation(rot);
754 psb->transform(trs);
755 psb->setTotalMass(0.1);
756 psb->addForce(btVector3(0, 2, 0), 0);
757 pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
758 }
759 pdemo->m_autocam = true;
760 }
761
Init_Aero2(SoftDemo * pdemo)762 static void Init_Aero2(SoftDemo* pdemo)
763 {
764 //TRACEDEMO
765 const btScalar s = 5;
766 //psb->getWorldInfo()->m_gravity.setValue(0,0,0);
767
768 const int segments = 10;
769 const int count = 5;
770 btVector3 pos(-s * segments, 0, 0);
771 btScalar gap = 0.5;
772
773 for (int i = 0; i < count; ++i)
774 {
775 btSoftBody* psb = btSoftBodyHelpers::CreatePatch(pdemo->m_softBodyWorldInfo, btVector3(-s, 0, -s * 3),
776 btVector3(+s, 0, -s * 3),
777 btVector3(-s, 0, +s),
778 btVector3(+s, 0, +s),
779 segments, segments * 3,
780 1 + 2, true);
781
782 psb->getCollisionShape()->setMargin(0.5);
783 btSoftBody::Material* pm = psb->appendMaterial();
784 pm->m_kLST = 0.0004;
785 pm->m_flags -= btSoftBody::fMaterial::DebugDraw;
786 psb->generateBendingConstraints(2, pm);
787
788 psb->m_cfg.kLF = 0.05;
789 psb->m_cfg.kDG = 0.01;
790
791 //psb->m_cfg.kLF = 0.004;
792 //psb->m_cfg.kDG = 0.0003;
793
794 psb->m_cfg.piterations = 2;
795 psb->m_cfg.aeromodel = btSoftBody::eAeroModel::V_TwoSidedLiftDrag;
796
797 psb->setWindVelocity(btVector3(4, -12.0, -25.0));
798
799 btTransform trs;
800 btQuaternion rot;
801 pos += btVector3(s * 2 + gap, 0, 0);
802 rot.setRotation(btVector3(1, 0, 0), btScalar(SIMD_PI / 2));
803 trs.setIdentity();
804 trs.setOrigin(pos);
805 trs.setRotation(rot);
806 psb->transform(trs);
807 psb->setTotalMass(2.0);
808
809 //this could help performance in some cases
810 btSoftBodyHelpers::ReoptimizeLinkOrder(psb);
811
812 pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
813 }
814
815 pdemo->m_autocam = true;
816 }
817
818 //
819 // Friction
820 //
Init_Friction(SoftDemo * pdemo)821 static void Init_Friction(SoftDemo* pdemo)
822 {
823 //TRACEDEMO
824 const btScalar bs = 2;
825 const btScalar ts = bs + bs / 4;
826 for (int i = 0, ni = 20; i < ni; ++i)
827 {
828 const btVector3 p(-ni * ts / 2 + i * ts, -10 + bs, 40);
829 btSoftBody* psb = Ctor_SoftBox(pdemo, p, btVector3(bs, bs, bs));
830 psb->m_cfg.kDF = 0.1 * ((i + 1) / (btScalar)ni);
831 psb->addVelocity(btVector3(0, 0, -10));
832 }
833 }
834
835 //
836 // Pressure
837 //
Init_Pressure(SoftDemo * pdemo)838 static void Init_Pressure(SoftDemo* pdemo)
839 {
840 //TRACEDEMO
841 btSoftBody* psb = btSoftBodyHelpers::CreateEllipsoid(pdemo->m_softBodyWorldInfo, btVector3(35, 25, 0),
842 btVector3(1, 1, 1) * 3,
843 512);
844 psb->m_materials[0]->m_kLST = 0.1;
845 psb->m_cfg.kDF = 1;
846 psb->m_cfg.kDP = 0.001; // fun factor...
847 psb->m_cfg.kPR = 2500;
848 psb->setTotalMass(30, true);
849 pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
850
851 Ctor_BigPlate(pdemo);
852 Ctor_LinearStair(pdemo, btVector3(0, 0, 0), btVector3(2, 1, 5), 0, 10);
853 pdemo->m_autocam = true;
854 }
855
856 //
857 // Volume conservation
858 //
Init_Volume(SoftDemo * pdemo)859 static void Init_Volume(SoftDemo* pdemo)
860 {
861 //TRACEDEMO
862 btSoftBody* psb = btSoftBodyHelpers::CreateEllipsoid(pdemo->m_softBodyWorldInfo, btVector3(35, 25, 0),
863 btVector3(1, 1, 1) * 3,
864 512);
865 psb->m_materials[0]->m_kLST = 0.45;
866 psb->m_cfg.kVC = 20;
867 psb->setTotalMass(50, true);
868 psb->setPose(true, false);
869 pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
870
871 Ctor_BigPlate(pdemo);
872 Ctor_LinearStair(pdemo, btVector3(0, 0, 0), btVector3(2, 1, 5), 0, 10);
873 pdemo->m_autocam = true;
874 }
875
876 //
877 // Stick+Bending+Rb's
878 //
Init_Sticks(SoftDemo * pdemo)879 static void Init_Sticks(SoftDemo* pdemo)
880 {
881 //TRACEDEMO
882 const int n = 16;
883 const int sg = 4;
884 const btScalar sz = 5;
885 const btScalar hg = 4;
886 const btScalar in = 1 / (btScalar)(n - 1);
887 for (int y = 0; y < n; ++y)
888 {
889 for (int x = 0; x < n; ++x)
890 {
891 const btVector3 org(-sz + sz * 2 * x * in,
892 -10,
893 -sz + sz * 2 * y * in);
894 btSoftBody* psb = btSoftBodyHelpers::CreateRope(pdemo->m_softBodyWorldInfo, org,
895 org + btVector3(hg * 0.001, hg, 0),
896 sg,
897 1);
898 psb->m_cfg.kDP = 0.005;
899 psb->m_cfg.kCHR = 0.1;
900 for (int i = 0; i < 3; ++i)
901 {
902 psb->generateBendingConstraints(2 + i);
903 }
904 psb->setMass(1, 0);
905 psb->setTotalMass(0.01);
906 pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
907 }
908 }
909 Ctor_BigBall(pdemo);
910 }
911
912 //
913 // Bending
914 //
Init_Bending(SoftDemo * pdemo)915 static void Init_Bending(SoftDemo* pdemo)
916 {
917 //TRACEDEMO
918 const btScalar s = 4;
919 const btVector3 x[] = {btVector3(-s, 0, -s),
920 btVector3(+s, 0, -s),
921 btVector3(+s, 0, +s),
922 btVector3(-s, 0, +s)};
923 const btScalar m[] = {0, 0, 0, 1};
924 btSoftBody* psb = new btSoftBody(&pdemo->m_softBodyWorldInfo, 4, x, m);
925 psb->appendLink(0, 1);
926 psb->appendLink(1, 2);
927 psb->appendLink(2, 3);
928 psb->appendLink(3, 0);
929 psb->appendLink(0, 2);
930
931 pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
932 }
933
934 //
935 // 100kg cloth locked at corners, 10 falling 10kg rb's.
936 //
Init_Cloth(SoftDemo * pdemo)937 static void Init_Cloth(SoftDemo* pdemo)
938 {
939 //TRACEDEMO
940 const btScalar s = 8;
941 btSoftBody* psb = btSoftBodyHelpers::CreatePatch(pdemo->m_softBodyWorldInfo, btVector3(-s, 0, -s),
942 btVector3(+s, 0, -s),
943 btVector3(-s, 0, +s),
944 btVector3(+s, 0, +s),
945 31, 31,
946 // 31,31,
947 1 + 2 + 4 + 8, true);
948
949 psb->getCollisionShape()->setMargin(0.5);
950 btSoftBody::Material* pm = psb->appendMaterial();
951 pm->m_kLST = 0.4;
952 pm->m_flags -= btSoftBody::fMaterial::DebugDraw;
953 psb->generateBendingConstraints(2, pm);
954 psb->setTotalMass(150);
955 pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
956
957 Ctor_RbUpStack(pdemo, 10);
958 pdemo->m_cutting = true;
959 }
960
961 //
962 // 100kg Stanford's bunny
963 //
Init_Bunny(SoftDemo * pdemo)964 static void Init_Bunny(SoftDemo* pdemo)
965 {
966 //TRACEDEMO
967 btSoftBody* psb = btSoftBodyHelpers::CreateFromTriMesh(pdemo->m_softBodyWorldInfo, gVerticesBunny,
968 &gIndicesBunny[0][0],
969 BUNNY_NUM_TRIANGLES);
970 btSoftBody::Material* pm = psb->appendMaterial();
971 pm->m_kLST = 0.5;
972 pm->m_flags -= btSoftBody::fMaterial::DebugDraw;
973 psb->generateBendingConstraints(2, pm);
974 psb->m_cfg.piterations = 2;
975 psb->m_cfg.kDF = 0.5;
976 psb->randomizeConstraints();
977 psb->scale(btVector3(6, 6, 6));
978 psb->setTotalMass(100, true);
979 pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
980 pdemo->m_cutting = true;
981 }
982
983 //
984 // 100kg Stanford's bunny with pose matching
985 //
Init_BunnyMatch(SoftDemo * pdemo)986 static void Init_BunnyMatch(SoftDemo* pdemo)
987 {
988 //TRACEDEMO
989 btSoftBody* psb = btSoftBodyHelpers::CreateFromTriMesh(pdemo->m_softBodyWorldInfo, gVerticesBunny,
990 &gIndicesBunny[0][0],
991 BUNNY_NUM_TRIANGLES);
992 psb->m_cfg.kDF = 0.5;
993 psb->m_cfg.kMT = 0.05;
994 psb->m_cfg.piterations = 5;
995 psb->randomizeConstraints();
996 psb->scale(btVector3(6, 6, 6));
997 psb->setTotalMass(100, true);
998 psb->setPose(false, true);
999 pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
1000 }
1001
1002 //
1003 // 50Kg Torus
1004 //
Init_Torus(SoftDemo * pdemo)1005 static void Init_Torus(SoftDemo* pdemo)
1006 {
1007 //TRACEDEMO
1008 btSoftBody* psb = btSoftBodyHelpers::CreateFromTriMesh(pdemo->m_softBodyWorldInfo, gVertices,
1009 &gIndices[0][0],
1010 NUM_TRIANGLES);
1011 psb->generateBendingConstraints(2);
1012 psb->m_cfg.piterations = 2;
1013 psb->randomizeConstraints();
1014 btMatrix3x3 m;
1015 m.setEulerZYX(SIMD_PI / 2, 0, 0);
1016 psb->transform(btTransform(m, btVector3(0, 4, 0)));
1017 psb->scale(btVector3(2, 2, 2));
1018 psb->setTotalMass(50, true);
1019 pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
1020 pdemo->m_cutting = true;
1021 }
1022
1023 //
1024 // 50Kg Torus with pose matching
1025 //
Init_TorusMatch(SoftDemo * pdemo)1026 static void Init_TorusMatch(SoftDemo* pdemo)
1027 {
1028 //TRACEDEMO
1029 btSoftBody* psb = btSoftBodyHelpers::CreateFromTriMesh(pdemo->m_softBodyWorldInfo, gVertices,
1030 &gIndices[0][0],
1031 NUM_TRIANGLES);
1032 psb->m_materials[0]->m_kLST = 0.1;
1033 psb->m_cfg.kMT = 0.05;
1034 psb->randomizeConstraints();
1035 btMatrix3x3 m;
1036 m.setEulerZYX(SIMD_PI / 2, 0, 0);
1037 psb->transform(btTransform(m, btVector3(0, 4, 0)));
1038 psb->scale(btVector3(2, 2, 2));
1039 psb->setTotalMass(50, true);
1040 psb->setPose(false, true);
1041 pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
1042 }
1043
1044 //
1045 // Cutting1
1046 //
Init_Cutting1(SoftDemo * pdemo)1047 static void Init_Cutting1(SoftDemo* pdemo)
1048 {
1049 const btScalar s = 6;
1050 const btScalar h = 2;
1051 const int r = 16;
1052 const btVector3 p[] = {btVector3(+s, h, -s),
1053 btVector3(-s, h, -s),
1054 btVector3(+s, h, +s),
1055 btVector3(-s, h, +s)};
1056 btSoftBody* psb = btSoftBodyHelpers::CreatePatch(pdemo->m_softBodyWorldInfo, p[0], p[1], p[2], p[3], r, r, 1 + 2 + 4 + 8, true);
1057 pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
1058 psb->m_cfg.piterations = 1;
1059 pdemo->m_cutting = true;
1060 }
1061
1062 //
1063 // Clusters
1064 //
1065
1066 //
Ctor_Gear(SoftDemo * pdemo,const btVector3 & pos,btScalar speed)1067 static void Ctor_Gear(SoftDemo* pdemo, const btVector3& pos, btScalar speed)
1068 {
1069 btTransform startTransform;
1070 startTransform.setIdentity();
1071 startTransform.setOrigin(pos);
1072 btCompoundShape* shape = new btCompoundShape();
1073 #if 1
1074 shape->addChildShape(btTransform(btQuaternion(0, 0, 0)), new btBoxShape(btVector3(5, 1, 6)));
1075 shape->addChildShape(btTransform(btQuaternion(0, 0, SIMD_HALF_PI)), new btBoxShape(btVector3(5, 1, 6)));
1076 #else
1077 shape->addChildShape(btTransform(btQuaternion(0, 0, 0)), new btCylinderShapeZ(btVector3(5, 1, 7)));
1078 shape->addChildShape(btTransform(btQuaternion(0, 0, SIMD_HALF_PI)), new btBoxShape(btVector3(4, 1, 8)));
1079 #endif
1080 btRigidBody* body = pdemo->createRigidBody(10, startTransform, shape);
1081 body->setFriction(1);
1082 btDynamicsWorld* world = pdemo->getDynamicsWorld();
1083 btHingeConstraint* hinge = new btHingeConstraint(*body, btTransform::getIdentity());
1084 if (speed != 0) hinge->enableAngularMotor(true, speed, 3);
1085 world->addConstraint(hinge);
1086 }
1087
1088 //
Ctor_ClusterBunny(SoftDemo * pdemo,const btVector3 & x,const btVector3 & a)1089 static btSoftBody* Ctor_ClusterBunny(SoftDemo* pdemo, const btVector3& x, const btVector3& a)
1090 {
1091 btSoftBody* psb = btSoftBodyHelpers::CreateFromTriMesh(pdemo->m_softBodyWorldInfo, gVerticesBunny, &gIndicesBunny[0][0], BUNNY_NUM_TRIANGLES);
1092 btSoftBody::Material* pm = psb->appendMaterial();
1093 pm->m_kLST = 1;
1094 pm->m_flags -= btSoftBody::fMaterial::DebugDraw;
1095 psb->generateBendingConstraints(2, pm);
1096 psb->m_cfg.piterations = 2;
1097 psb->m_cfg.kDF = 1;
1098 psb->m_cfg.collisions = btSoftBody::fCollision::CL_SS +
1099 btSoftBody::fCollision::CL_RS;
1100 psb->randomizeConstraints();
1101 btMatrix3x3 m;
1102 m.setEulerZYX(a.x(), a.y(), a.z());
1103 psb->transform(btTransform(m, x));
1104 psb->scale(btVector3(8, 8, 8));
1105 psb->setTotalMass(150, true);
1106 psb->generateClusters(1);
1107 pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
1108 return (psb);
1109 }
1110
1111 //
Ctor_ClusterTorus(SoftDemo * pdemo,const btVector3 & x,const btVector3 & a,const btVector3 & s=btVector3 (2,2,2))1112 static btSoftBody* Ctor_ClusterTorus(SoftDemo* pdemo, const btVector3& x, const btVector3& a, const btVector3& s = btVector3(2, 2, 2))
1113 {
1114 btSoftBody* psb = btSoftBodyHelpers::CreateFromTriMesh(pdemo->m_softBodyWorldInfo, gVertices, &gIndices[0][0], NUM_TRIANGLES);
1115 btSoftBody::Material* pm = psb->appendMaterial();
1116 pm->m_kLST = 1;
1117 pm->m_flags -= btSoftBody::fMaterial::DebugDraw;
1118 psb->generateBendingConstraints(2, pm);
1119 psb->m_cfg.piterations = 2;
1120 psb->m_cfg.collisions = btSoftBody::fCollision::CL_SS +
1121 btSoftBody::fCollision::CL_RS;
1122 psb->randomizeConstraints();
1123 psb->scale(s);
1124 psb->rotate(btQuaternion(a[0], a[1], a[2]));
1125 psb->translate(x);
1126 psb->setTotalMass(50, true);
1127 psb->generateClusters(64);
1128 pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
1129 return (psb);
1130 }
1131
1132 //
1133 static struct MotorControl : btSoftBody::AJoint::IControl
1134 {
MotorControlMotorControl1135 MotorControl()
1136 {
1137 goal = 0;
1138 maxtorque = 0;
1139 }
SpeedMotorControl1140 btScalar Speed(btSoftBody::AJoint*, btScalar current)
1141 {
1142 return (current + btMin(maxtorque, btMax(-maxtorque, goal - current)));
1143 }
1144 btScalar goal;
1145 btScalar maxtorque;
1146 } motorcontrol;
1147
1148 //
1149 struct SteerControl : btSoftBody::AJoint::IControl
1150 {
SteerControlSteerControl1151 SteerControl(btScalar s)
1152 {
1153 angle = 0;
1154 sign = s;
1155 }
PrepareSteerControl1156 void Prepare(btSoftBody::AJoint* joint)
1157 {
1158 joint->m_refs[0][0] = btCos(angle * sign);
1159 joint->m_refs[0][2] = btSin(angle * sign);
1160 }
SpeedSteerControl1161 btScalar Speed(btSoftBody::AJoint* joint, btScalar current)
1162 {
1163 return (motorcontrol.Speed(joint, current));
1164 }
1165 btScalar angle;
1166 btScalar sign;
1167 };
1168
1169 static SteerControl steercontrol_f(+1);
1170 static SteerControl steercontrol_r(-1);
1171
1172 //
Init_ClusterDeform(SoftDemo * pdemo)1173 static void Init_ClusterDeform(SoftDemo* pdemo)
1174 {
1175 btSoftBody* psb = Ctor_ClusterTorus(pdemo, btVector3(0, 0, 0), btVector3(SIMD_PI / 2, 0, SIMD_HALF_PI));
1176 psb->generateClusters(8);
1177 psb->m_cfg.kDF = 1;
1178 }
1179
1180 //
Init_ClusterCollide1(SoftDemo * pdemo)1181 static void Init_ClusterCollide1(SoftDemo* pdemo)
1182 {
1183 const btScalar s = 8;
1184 btSoftBody* psb = btSoftBodyHelpers::CreatePatch(pdemo->m_softBodyWorldInfo, btVector3(-s, 0, -s),
1185 btVector3(+s, 0, -s),
1186 btVector3(-s, 0, +s),
1187 btVector3(+s, 0, +s),
1188 17, 17, //9,9,//31,31,
1189 1 + 2 + 4 + 8,
1190 true);
1191 btSoftBody::Material* pm = psb->appendMaterial();
1192 pm->m_kLST = 0.4;
1193 pm->m_flags -= btSoftBody::fMaterial::DebugDraw;
1194 psb->m_cfg.kDF = 1;
1195 psb->m_cfg.kSRHR_CL = 1;
1196 psb->m_cfg.kSR_SPLT_CL = 0;
1197 psb->m_cfg.collisions = btSoftBody::fCollision::CL_SS +
1198
1199 btSoftBody::fCollision::CL_RS;
1200 psb->generateBendingConstraints(2, pm);
1201
1202 psb->getCollisionShape()->setMargin(0.05);
1203 psb->setTotalMass(50);
1204
1205 ///pass zero in generateClusters to create cluster for each tetrahedron or triangle
1206 psb->generateClusters(0);
1207 //psb->generateClusters(64);
1208
1209 pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
1210
1211 Ctor_RbUpStack(pdemo, 10);
1212 }
1213
1214 //
Init_ClusterCollide2(SoftDemo * pdemo)1215 static void Init_ClusterCollide2(SoftDemo* pdemo)
1216 {
1217 struct Functor
1218 {
1219 static btSoftBody* Create(SoftDemo* pdemo, const btVector3& x, const btVector3& a)
1220 {
1221 btSoftBody* psb = btSoftBodyHelpers::CreateFromTriMesh(pdemo->m_softBodyWorldInfo, gVertices,
1222 &gIndices[0][0],
1223 NUM_TRIANGLES);
1224 btSoftBody::Material* pm = psb->appendMaterial();
1225 pm->m_flags -= btSoftBody::fMaterial::DebugDraw;
1226 psb->generateBendingConstraints(2, pm);
1227 psb->m_cfg.piterations = 2;
1228 psb->m_cfg.kDF = 1;
1229 psb->m_cfg.kSSHR_CL = 1;
1230 psb->m_cfg.kSS_SPLT_CL = 0;
1231 psb->m_cfg.kSKHR_CL = 0.1f;
1232 psb->m_cfg.kSK_SPLT_CL = 1;
1233 psb->m_cfg.collisions = btSoftBody::fCollision::CL_SS +
1234 btSoftBody::fCollision::CL_RS;
1235 psb->randomizeConstraints();
1236 btMatrix3x3 m;
1237 m.setEulerZYX(a.x(), a.y(), a.z());
1238 psb->transform(btTransform(m, x));
1239 psb->scale(btVector3(2, 2, 2));
1240 psb->setTotalMass(50, true);
1241 psb->generateClusters(16);
1242 pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
1243 return (psb);
1244 }
1245 };
1246 for (int i = 0; i < 3; ++i)
1247 {
1248 Functor::Create(pdemo, btVector3(3 * i, 2, 0), btVector3(SIMD_PI / 2 * (1 - (i & 1)), SIMD_PI / 2 * (i & 1), 0));
1249 }
1250 }
1251
1252 //
Init_ClusterSocket(SoftDemo * pdemo)1253 static void Init_ClusterSocket(SoftDemo* pdemo)
1254 {
1255 btSoftBody* psb = Ctor_ClusterTorus(pdemo, btVector3(0, 0, 0), btVector3(SIMD_PI / 2, 0, SIMD_HALF_PI));
1256 btRigidBody* prb = Ctor_BigPlate(pdemo, 50, 8);
1257 psb->m_cfg.kDF = 1;
1258 btSoftBody::LJoint::Specs lj;
1259 lj.position = btVector3(0, 5, 0);
1260 psb->appendLinearJoint(lj, prb);
1261 }
1262
1263 //
Init_ClusterHinge(SoftDemo * pdemo)1264 static void Init_ClusterHinge(SoftDemo* pdemo)
1265 {
1266 btSoftBody* psb = Ctor_ClusterTorus(pdemo, btVector3(0, 0, 0), btVector3(SIMD_PI / 2, 0, SIMD_HALF_PI));
1267 btRigidBody* prb = Ctor_BigPlate(pdemo, 50, 8);
1268 psb->m_cfg.kDF = 1;
1269 btSoftBody::AJoint::Specs aj;
1270 aj.axis = btVector3(0, 0, 1);
1271 psb->appendAngularJoint(aj, prb);
1272 }
1273
1274 //
Init_ClusterCombine(SoftDemo * pdemo)1275 static void Init_ClusterCombine(SoftDemo* pdemo)
1276 {
1277 const btVector3 sz(2, 4, 2);
1278 btSoftBody* psb0 = Ctor_ClusterTorus(pdemo, btVector3(0, 8, 0), btVector3(SIMD_PI / 2, 0, SIMD_HALF_PI), sz);
1279 btSoftBody* psb1 = Ctor_ClusterTorus(pdemo, btVector3(0, 8, 10), btVector3(SIMD_PI / 2, 0, SIMD_HALF_PI), sz);
1280 btSoftBody* psbs[] = {psb0, psb1};
1281 for (int j = 0; j < 2; ++j)
1282 {
1283 psbs[j]->m_cfg.kDF = 1;
1284 psbs[j]->m_cfg.kDP = 0;
1285 psbs[j]->m_cfg.piterations = 1;
1286 psbs[j]->m_clusters[0]->m_matching = 0.05;
1287 psbs[j]->m_clusters[0]->m_ndamping = 0.05;
1288 }
1289 btSoftBody::AJoint::Specs aj;
1290 aj.axis = btVector3(0, 0, 1);
1291 aj.icontrol = &motorcontrol;
1292 psb0->appendAngularJoint(aj, psb1);
1293
1294 btSoftBody::LJoint::Specs lj;
1295 lj.position = btVector3(0, 8, 5);
1296 psb0->appendLinearJoint(lj, psb1);
1297 }
1298
1299 //
Init_ClusterCar(SoftDemo * pdemo)1300 static void Init_ClusterCar(SoftDemo* pdemo)
1301 {
1302 // pdemo->setAzi(180);
1303 const btVector3 origin(100, 80, 0);
1304 const btQuaternion orientation(-SIMD_PI / 2, 0, 0);
1305 const btScalar widthf = 8;
1306 const btScalar widthr = 9;
1307 const btScalar length = 8;
1308 const btScalar height = 4;
1309 const btVector3 wheels[] = {
1310 btVector3(+widthf, -height, +length), // Front left
1311 btVector3(-widthf, -height, +length), // Front right
1312 btVector3(+widthr, -height, -length), // Rear left
1313 btVector3(-widthr, -height, -length), // Rear right
1314 };
1315 btSoftBody* pa = Ctor_ClusterBunny(pdemo, btVector3(0, 0, 0), btVector3(0, 0, 0));
1316 btSoftBody* pfl = Ctor_ClusterTorus(pdemo, wheels[0], btVector3(0, 0, SIMD_HALF_PI), btVector3(2, 4, 2));
1317 btSoftBody* pfr = Ctor_ClusterTorus(pdemo, wheels[1], btVector3(0, 0, SIMD_HALF_PI), btVector3(2, 4, 2));
1318 btSoftBody* prl = Ctor_ClusterTorus(pdemo, wheels[2], btVector3(0, 0, SIMD_HALF_PI), btVector3(2, 5, 2));
1319 btSoftBody* prr = Ctor_ClusterTorus(pdemo, wheels[3], btVector3(0, 0, SIMD_HALF_PI), btVector3(2, 5, 2));
1320
1321 pfl->m_cfg.kDF =
1322 pfr->m_cfg.kDF =
1323 prl->m_cfg.kDF =
1324 prr->m_cfg.kDF = 1;
1325
1326 btSoftBody::LJoint::Specs lspecs;
1327 lspecs.cfm = 1;
1328 lspecs.erp = 1;
1329 lspecs.position = btVector3(0, 0, 0);
1330
1331 lspecs.position = wheels[0];
1332 pa->appendLinearJoint(lspecs, pfl);
1333 lspecs.position = wheels[1];
1334 pa->appendLinearJoint(lspecs, pfr);
1335 lspecs.position = wheels[2];
1336 pa->appendLinearJoint(lspecs, prl);
1337 lspecs.position = wheels[3];
1338 pa->appendLinearJoint(lspecs, prr);
1339
1340 btSoftBody::AJoint::Specs aspecs;
1341 aspecs.cfm = 1;
1342 aspecs.erp = 1;
1343 aspecs.axis = btVector3(1, 0, 0);
1344
1345 aspecs.icontrol = &steercontrol_f;
1346 pa->appendAngularJoint(aspecs, pfl);
1347 pa->appendAngularJoint(aspecs, pfr);
1348
1349 aspecs.icontrol = &motorcontrol;
1350 pa->appendAngularJoint(aspecs, prl);
1351 pa->appendAngularJoint(aspecs, prr);
1352
1353 pa->rotate(orientation);
1354 pfl->rotate(orientation);
1355 pfr->rotate(orientation);
1356 prl->rotate(orientation);
1357 prr->rotate(orientation);
1358 pa->translate(origin);
1359 pfl->translate(origin);
1360 pfr->translate(origin);
1361 prl->translate(origin);
1362 prr->translate(origin);
1363 pfl->m_cfg.piterations =
1364 pfr->m_cfg.piterations =
1365 prl->m_cfg.piterations =
1366 prr->m_cfg.piterations = 1;
1367 pfl->m_clusters[0]->m_matching =
1368 pfr->m_clusters[0]->m_matching =
1369 prl->m_clusters[0]->m_matching =
1370 prr->m_clusters[0]->m_matching = 0.05;
1371 pfl->m_clusters[0]->m_ndamping =
1372 pfr->m_clusters[0]->m_ndamping =
1373 prl->m_clusters[0]->m_ndamping =
1374 prr->m_clusters[0]->m_ndamping = 0.05;
1375
1376 Ctor_LinearStair(pdemo, btVector3(0, -8, 0), btVector3(3, 2, 40), 0, 20);
1377 Ctor_RbUpStack(pdemo, 50);
1378 pdemo->m_autocam = true;
1379 }
1380
1381 //
Init_ClusterRobot(SoftDemo * pdemo)1382 static void Init_ClusterRobot(SoftDemo* pdemo)
1383 {
1384 struct Functor
1385 {
1386 static btSoftBody* CreateBall(SoftDemo* pdemo, const btVector3& pos)
1387 {
1388 btSoftBody* psb = btSoftBodyHelpers::CreateEllipsoid(pdemo->m_softBodyWorldInfo, pos, btVector3(1, 1, 1) * 3, 512);
1389 psb->m_materials[0]->m_kLST = 0.45;
1390 psb->m_cfg.kVC = 20;
1391 psb->setTotalMass(50, true);
1392 psb->setPose(true, false);
1393 psb->generateClusters(1);
1394 pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
1395 return (psb);
1396 }
1397 };
1398 const btVector3 base = btVector3(0, 25, 8);
1399 btSoftBody* psb0 = Functor::CreateBall(pdemo, base + btVector3(-8, 0, 0));
1400 btSoftBody* psb1 = Functor::CreateBall(pdemo, base + btVector3(+8, 0, 0));
1401 btSoftBody* psb2 = Functor::CreateBall(pdemo, base + btVector3(0, 0, +8 * btSqrt(2)));
1402 const btVector3 ctr = (psb0->clusterCom(0) + psb1->clusterCom(0) + psb2->clusterCom(0)) / 3;
1403 btCylinderShape* pshp = new btCylinderShape(btVector3(8, 1, 8));
1404 btRigidBody* prb = pdemo->createRigidBody(50, btTransform(btQuaternion(0, 0, 0), ctr + btVector3(0, 5, 0)), pshp);
1405 btSoftBody::LJoint::Specs ls;
1406 ls.erp = 0.5f;
1407 ls.position = psb0->clusterCom(0);
1408 psb0->appendLinearJoint(ls, prb);
1409 ls.position = psb1->clusterCom(0);
1410 psb1->appendLinearJoint(ls, prb);
1411 ls.position = psb2->clusterCom(0);
1412 psb2->appendLinearJoint(ls, prb);
1413
1414 btBoxShape* pbox = new btBoxShape(btVector3(20, 1, 40));
1415 btRigidBody* pgrn;
1416 pgrn = pdemo->createRigidBody(0, btTransform(btQuaternion(0, -SIMD_HALF_PI / 2, 0), btVector3(0, 0, 0)), pbox);
1417
1418 pdemo->m_autocam = true;
1419 }
1420
1421 //
Init_ClusterStackSoft(SoftDemo * pdemo)1422 static void Init_ClusterStackSoft(SoftDemo* pdemo)
1423 {
1424 for (int i = 0; i < 10; ++i)
1425 {
1426 btSoftBody* psb = Ctor_ClusterTorus(pdemo, btVector3(0, -9 + 8.25 * i, 0), btVector3(0, 0, 0));
1427 psb->m_cfg.kDF = 1;
1428 }
1429 }
1430
1431 //
Init_ClusterStackMixed(SoftDemo * pdemo)1432 static void Init_ClusterStackMixed(SoftDemo* pdemo)
1433 {
1434 for (int i = 0; i < 10; ++i)
1435 {
1436 if ((i + 1) & 1)
1437 {
1438 Ctor_BigPlate(pdemo, 50, -9 + 4.25 * i);
1439 }
1440 else
1441 {
1442 btSoftBody* psb = Ctor_ClusterTorus(pdemo, btVector3(0, -9 + 4.25 * i, 0), btVector3(0, 0, 0));
1443 psb->m_cfg.kDF = 1;
1444 }
1445 }
1446 }
1447
1448 //
1449 // TetraBunny
1450 //
Init_TetraBunny(SoftDemo * pdemo)1451 static void Init_TetraBunny(SoftDemo* pdemo)
1452 {
1453 btSoftBody* psb = btSoftBodyHelpers::CreateFromTetGenData(pdemo->m_softBodyWorldInfo,
1454 TetraBunny::getElements(),
1455 0,
1456 TetraBunny::getNodes(),
1457 false, true, true);
1458 pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
1459 psb->rotate(btQuaternion(SIMD_PI / 2, 0, 0));
1460 psb->setVolumeMass(150);
1461 psb->m_cfg.piterations = 2;
1462 //psb->m_cfg.piterations=1;
1463 pdemo->m_cutting = false;
1464 //psb->getCollisionShape()->setMargin(0.01);
1465 psb->m_cfg.collisions = btSoftBody::fCollision::CL_SS + btSoftBody::fCollision::CL_RS
1466 //+ btSoftBody::fCollision::CL_SELF
1467 ;
1468
1469 ///pass zero in generateClusters to create cluster for each tetrahedron or triangle
1470 psb->generateClusters(0);
1471 //psb->m_materials[0]->m_kLST=.2;
1472 psb->m_cfg.kDF = 10.;
1473 }
1474
1475 //
1476 // TetraCube
1477 //
Init_TetraCube(SoftDemo * pdemo)1478 static void Init_TetraCube(SoftDemo* pdemo)
1479 {
1480 btSoftBody* psb = btSoftBodyHelpers::CreateFromTetGenData(pdemo->m_softBodyWorldInfo,
1481 TetraCube::getElements(),
1482 0,
1483 TetraCube::getNodes(),
1484 false, true, true);
1485 pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
1486 psb->scale(btVector3(4, 4, 4));
1487 psb->translate(btVector3(0, 5, 0));
1488 psb->setVolumeMass(300);
1489
1490 ///fix one vertex
1491 //psb->setMass(0,0);
1492 //psb->setMass(10,0);
1493 //psb->setMass(20,0);
1494 psb->m_cfg.piterations = 1;
1495 //psb->generateClusters(128);
1496 psb->generateClusters(16);
1497 //psb->getCollisionShape()->setMargin(0.5);
1498
1499 psb->getCollisionShape()->setMargin(0.01);
1500 psb->m_cfg.collisions = btSoftBody::fCollision::CL_SS + btSoftBody::fCollision::CL_RS
1501 //+ btSoftBody::fCollision::CL_SELF
1502 ;
1503 psb->m_materials[0]->m_kLST = 0.8;
1504 pdemo->m_cutting = false;
1505 }
1506
1507 /* Init */
1508 void (*demofncs[])(SoftDemo*) =
1509 {
1510 Init_Cloth,
1511 Init_Pressure,
1512 Init_Volume,
1513 Init_Ropes,
1514 Init_RopeAttach,
1515 Init_ClothAttach,
1516 Init_Sticks,
1517 Init_CapsuleCollision,
1518 Init_Collide,
1519 Init_Collide2,
1520 Init_Collide3,
1521 Init_Impact,
1522 Init_Aero,
1523 Init_Aero2,
1524 Init_Friction,
1525 Init_Torus,
1526 Init_TorusMatch,
1527 Init_Bunny,
1528 Init_BunnyMatch,
1529 Init_Cutting1,
1530 Init_ClusterDeform,
1531 Init_ClusterCollide1,
1532 Init_ClusterCollide2,
1533 Init_ClusterSocket,
1534 Init_ClusterHinge,
1535 Init_ClusterCombine,
1536 Init_ClusterCar,
1537 Init_ClusterRobot,
1538 Init_ClusterStackSoft,
1539 Init_ClusterStackMixed,
1540 Init_TetraCube,
1541 Init_TetraBunny,
1542 };
1543
1544 #if 0
1545 void SoftDemo::clientResetScene()
1546 {
1547 m_azi = 0;
1548 m_cameraDistance = 30.f;
1549 m_cameraTargetPosition.setValue(0,0,0);
1550
1551
1552 /* Clean up */
1553 for(int i=m_dynamicsWorld->getNumCollisionObjects()-1;i>=0;i--)
1554 {
1555 btCollisionObject* obj=m_dynamicsWorld->getCollisionObjectArray()[i];
1556 btRigidBody* body=btRigidBody::upcast(obj);
1557 if(body&&body->getMotionState())
1558 {
1559 delete body->getMotionState();
1560 }
1561 while(m_dynamicsWorld->getNumConstraints())
1562 {
1563 btTypedConstraint* pc=m_dynamicsWorld->getConstraint(0);
1564 m_dynamicsWorld->removeConstraint(pc);
1565 delete pc;
1566 }
1567 btSoftBody* softBody = btSoftBody::upcast(obj);
1568 if (softBody)
1569 {
1570 getSoftDynamicsWorld()->removeSoftBody(softBody);
1571 } else
1572 {
1573 btRigidBody* body = btRigidBody::upcast(obj);
1574 if (body)
1575 m_dynamicsWorld->removeRigidBody(body);
1576 else
1577 m_dynamicsWorld->removeCollisionObject(obj);
1578 }
1579 delete obj;
1580 }
1581
1582
1583
1584 }
1585
1586 #if 0
1587 void SoftDemo::clientMoveAndDisplay()
1588 {
1589 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
1590
1591
1592
1593
1594 float ms = getDeltaTimeMicroseconds();
1595 float dt = ms / 1000000.f;//1.0/60.;
1596
1597
1598
1599 if (m_dynamicsWorld)
1600 {
1601
1602 if (sDemoMode)
1603 {
1604 static float demoCounter = DEMO_MODE_TIMEOUT;
1605 demoCounter-= dt;
1606 if (demoCounter<0)
1607 {
1608
1609 demoCounter=DEMO_MODE_TIMEOUT;
1610 current_demo++;
1611 current_demo=current_demo%(sizeof(demofncs)/sizeof(demofncs[0]));
1612 clientResetScene();
1613 }
1614 }
1615
1616
1617 //#define FIXED_STEP
1618 #ifdef FIXED_STEP
1619 m_dynamicsWorld->stepSimulation(dt=1.0f/60.f,0);
1620
1621 #else
1622 //during idle mode, just run 1 simulation step maximum, otherwise 4 at max
1623 // int maxSimSubSteps = m_idle ? 1 : 4;
1624 //if (m_idle)
1625 // dt = 1.0/420.f;
1626
1627 int numSimSteps;
1628 numSimSteps = m_dynamicsWorld->stepSimulation(dt);
1629 //numSimSteps = m_dynamicsWorld->stepSimulation(dt,10,1./240.f);
1630
1631 #ifdef VERBOSE_TIMESTEPPING_CONSOLEOUTPUT
1632 if (!numSimSteps)
1633 printf("Interpolated transforms\n");
1634 else
1635 {
1636 if (numSimSteps > maxSimSubSteps)
1637 {
1638 //detect dropping frames
1639 printf("Dropped (%i) simulation steps out of %i\n",numSimSteps - maxSimSubSteps,numSimSteps);
1640 } else
1641 {
1642 printf("Simulated (%i) steps\n",numSimSteps);
1643 }
1644 }
1645 #endif //VERBOSE_TIMESTEPPING_CONSOLEOUTPUT
1646
1647 #endif
1648
1649 #ifdef USE_AMD_OPENCL
1650 if (g_openCLSIMDSolver)
1651 g_openCLSIMDSolver->copyBackToSoftBodies();
1652 #endif //USE_AMD_OPENCL
1653
1654 if(m_drag)
1655 {
1656 m_node->m_v*=0;
1657 }
1658
1659 m_softBodyWorldInfo.m_sparsesdf.GarbageCollect();
1660
1661 //optional but useful: debug drawing
1662
1663 }
1664
1665 #ifdef USE_QUICKPROF
1666 btProfiler::beginBlock("render");
1667 #endif //USE_QUICKPROF
1668
1669 renderme();
1670
1671 //render the graphics objects, with center of mass shift
1672
1673 updateCamera();
1674
1675 #ifdef USE_QUICKPROF
1676 btProfiler::endBlock("render");
1677 #endif
1678 glFlush();
1679
1680 swapBuffers();
1681
1682 }
1683 #endif
1684
1685 #if 0
1686 void SoftDemo::renderme()
1687 {
1688 btIDebugDraw* idraw=m_dynamicsWorld->getDebugDrawer();
1689
1690 glDisable(GL_TEXTURE_2D);
1691 glDisable(GL_LIGHTING);
1692 m_dynamicsWorld->debugDrawWorld();
1693
1694 //int debugMode = m_dynamicsWorld->getDebugDrawer()? m_dynamicsWorld->getDebugDrawer()->getDebugMode() : -1;
1695
1696 btSoftRigidDynamicsWorld* softWorld = (btSoftRigidDynamicsWorld*)m_dynamicsWorld;
1697 //btIDebugDraw* sdraw = softWorld ->getDebugDrawer();
1698
1699
1700 for ( int i=0;i<softWorld->getSoftBodyArray().size();i++)
1701 {
1702 btSoftBody* psb=(btSoftBody*)softWorld->getSoftBodyArray()[i];
1703 if (softWorld->getDebugDrawer() && !(softWorld->getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe)))
1704 {
1705 btSoftBodyHelpers::DrawFrame(psb,softWorld->getDebugDrawer());
1706 btSoftBodyHelpers::Draw(psb,softWorld->getDebugDrawer(),softWorld->getDrawFlags());
1707 }
1708 }
1709
1710 /* Bodies */
1711 btVector3 ps(0,0,0);
1712 int nps=0;
1713
1714 btSoftBodyArray& sbs=getSoftDynamicsWorld()->getSoftBodyArray();
1715 for(int ib=0;ib<sbs.size();++ib)
1716 {
1717 btSoftBody* psb=sbs[ib];
1718 nps+=psb->m_nodes.size();
1719 for(int i=0;i<psb->m_nodes.size();++i)
1720 {
1721 ps+=psb->m_nodes[i].m_x;
1722 }
1723 }
1724 ps/=nps;
1725 if(m_autocam)
1726 m_cameraTargetPosition+=(ps-m_cameraTargetPosition)*0.05;
1727 /* Anm */
1728 if(!isIdle())
1729 m_animtime=m_clock.getTimeMilliseconds()/1000.f;
1730 /* Ray cast */
1731 if(m_raycast)
1732 {
1733 /* Prepare rays */
1734 const int res=64;
1735 const btScalar fres=res-1;
1736 const btScalar size=8;
1737 const btScalar dist=10;
1738 btTransform trs;
1739 trs.setOrigin(ps);
1740 btScalar rayLength = 1000.f;
1741
1742 const btScalar angle=m_animtime*0.2;
1743 trs.setRotation(btQuaternion(angle,SIMD_PI/4,0));
1744 btVector3 dir=trs.getBasis()*btVector3(0,-1,0);
1745 trs.setOrigin(ps-dir*dist);
1746 btAlignedObjectArray<btVector3> origins;
1747 btAlignedObjectArray<btScalar> fractions;
1748 origins.resize(res*res);
1749 fractions.resize(res*res,1.f);
1750 for(int y=0;y<res;++y)
1751 {
1752 for(int x=0;x<res;++x)
1753 {
1754 const int idx=y*res+x;
1755 origins[idx]=trs*btVector3(-size+size*2*x/fres,dist,-size+size*2*y/fres);
1756 }
1757 }
1758 /* Cast rays */
1759 {
1760 m_clock.reset();
1761 if (sbs.size())
1762 {
1763 btVector3* org=&origins[0];
1764 btScalar* fraction=&fractions[0];
1765 btSoftBody** psbs=&sbs[0];
1766 btSoftBody::sRayCast results;
1767 for(int i=0,ni=origins.size(),nb=sbs.size();i<ni;++i)
1768 {
1769 for(int ib=0;ib<nb;++ib)
1770 {
1771 btVector3 rayFrom = *org;
1772 btVector3 rayTo = rayFrom+dir*rayLength;
1773 if(psbs[ib]->rayTest(rayFrom,rayTo,results))
1774 {
1775 *fraction=results.fraction;
1776 }
1777 }
1778 ++org;++fraction;
1779 }
1780 long ms=btMax<long>(m_clock.getTimeMilliseconds(),1);
1781 long rayperseconds=(1000*(origins.size()*sbs.size()))/ms;
1782 printf("%d ms (%d rays/s)\r\n",int(ms),int(rayperseconds));
1783 }
1784 }
1785 /* Draw rays */
1786 const btVector3 c[]={ origins[0],
1787 origins[res-1],
1788 origins[res*(res-1)],
1789 origins[res*(res-1)+res-1]};
1790 idraw->drawLine(c[0],c[1],btVector3(0,0,0));
1791 idraw->drawLine(c[1],c[3],btVector3(0,0,0));
1792 idraw->drawLine(c[3],c[2],btVector3(0,0,0));
1793 idraw->drawLine(c[2],c[0],btVector3(0,0,0));
1794 for(int i=0,ni=origins.size();i<ni;++i)
1795 {
1796 const btScalar fraction=fractions[i];
1797 const btVector3& org=origins[i];
1798 if(fraction<1.f)
1799 {
1800 idraw->drawLine(org,org+dir*rayLength*fraction,btVector3(1,0,0));
1801 }
1802 else
1803 {
1804 idraw->drawLine(org,org-dir*rayLength*0.1,btVector3(0,0,0));
1805 }
1806 }
1807 #undef RES
1808 }
1809 /* Water level */
1810 static const btVector3 axis[]={btVector3(1,0,0),
1811 btVector3(0,1,0),
1812 btVector3(0,0,1)};
1813 if(m_softBodyWorldInfo.water_density>0)
1814 {
1815 const btVector3 c= btVector3((btScalar)0.25,(btScalar)0.25,1);
1816 const btScalar a= (btScalar)0.5;
1817 const btVector3 n= m_softBodyWorldInfo.water_normal;
1818 const btVector3 o= -n*m_softBodyWorldInfo.water_offset;
1819 const btVector3 x= btCross(n,axis[n.minAxis()]).normalized();
1820 const btVector3 y= btCross(x,n).normalized();
1821 const btScalar s= 25;
1822 idraw->drawTriangle(o-x*s-y*s,o+x*s-y*s,o+x*s+y*s,c,a);
1823 idraw->drawTriangle(o-x*s-y*s,o+x*s+y*s,o-x*s+y*s,c,a);
1824 }
1825 //
1826
1827 int lineWidth=280;
1828 int xStart = m_glutScreenWidth - lineWidth;
1829 int yStart = 20;
1830
1831 if((getDebugMode() & btIDebugDraw::DBG_NoHelpText)==0)
1832 {
1833 setOrthographicProjection();
1834 glDisable(GL_LIGHTING);
1835 glColor3f(0, 0, 0);
1836 char buf[124];
1837
1838 glRasterPos3f(xStart, yStart, 0);
1839 if (sDemoMode)
1840 {
1841 sprintf(buf,"d to toggle demo mode (on)");
1842 } else
1843 {
1844 sprintf(buf,"d to toggle demo mode (off)");
1845 }
1846 GLDebugDrawString(xStart,20,buf);
1847 glRasterPos3f(xStart, yStart, 0);
1848 sprintf(buf,"] for next demo (%d)",current_demo);
1849 yStart+=20;
1850 GLDebugDrawString(xStart,yStart,buf);
1851 glRasterPos3f(xStart, yStart, 0);
1852 sprintf(buf,"c to visualize clusters");
1853 yStart+=20;
1854 GLDebugDrawString(xStart,yStart,buf);
1855 glRasterPos3f(xStart, yStart, 0);
1856 sprintf(buf,"; to toggle camera mode");
1857 yStart+=20;
1858 GLDebugDrawString(xStart,yStart,buf);
1859 glRasterPos3f(xStart, yStart, 0);
1860 sprintf(buf,"n,m,l,k for power and steering");
1861 yStart+=20;
1862 GLDebugDrawString(xStart,yStart,buf);
1863
1864
1865 resetPerspectiveProjection();
1866 glEnable(GL_LIGHTING);
1867 }
1868
1869 DemoApplication::renderme();
1870
1871 }
1872 #endif
1873 #endif
1874
setDrawClusters(bool drawClusters)1875 void SoftDemo::setDrawClusters(bool drawClusters)
1876 {
1877 if (drawClusters)
1878 {
1879 getSoftDynamicsWorld()->setDrawFlags(getSoftDynamicsWorld()->getDrawFlags() | fDrawFlags::Clusters);
1880 }
1881 else
1882 {
1883 getSoftDynamicsWorld()->setDrawFlags(getSoftDynamicsWorld()->getDrawFlags() & (~fDrawFlags::Clusters));
1884 }
1885 }
1886
1887 #if 0
1888 void SoftDemo::keyboardCallback(unsigned char key, int x, int y)
1889 {
1890 switch(key)
1891 {
1892 case 'd': sDemoMode = !sDemoMode; break;
1893 case 'n': motorcontrol.maxtorque=10;motorcontrol.goal+=1;break;
1894 case 'm': motorcontrol.maxtorque=10;motorcontrol.goal-=1;break;
1895 case 'l': steercontrol_f.angle+=0.1;steercontrol_r.angle+=0.1;break;
1896 case 'k': steercontrol_f.angle-=0.1;steercontrol_r.angle-=0.1;break;
1897 case ']': ++current_demo;clientResetScene();break;
1898 case '[': --current_demo;clientResetScene();break;
1899 case ',': m_raycast=!m_raycast;break;
1900 case ';': m_autocam=!m_autocam;break;
1901 case 'c': getSoftDynamicsWorld()->setDrawFlags(getSoftDynamicsWorld()->getDrawFlags()^fDrawFlags::Clusters);break;
1902 case '`':
1903 {
1904 btSoftBodyArray& sbs=getSoftDynamicsWorld()->getSoftBodyArray();
1905 for(int ib=0;ib<sbs.size();++ib)
1906 {
1907 btSoftBody* psb=sbs[ib];
1908 psb->staticSolve(128);
1909 }
1910 }
1911 break;
1912 default: DemoApplication::keyboardCallback(key,x,y);
1913 }
1914 }
1915 #endif
1916 //
mouseMotionFunc(int x,int y)1917 void SoftDemo::mouseMotionFunc(int x, int y)
1918 {
1919 if (m_node && (m_results.fraction < 1.f))
1920 {
1921 if (!m_drag)
1922 {
1923 #define SQ(_x_) (_x_) * (_x_)
1924 if ((SQ(x - m_lastmousepos[0]) + SQ(y - m_lastmousepos[1])) > 6)
1925 {
1926 m_drag = true;
1927 }
1928 #undef SQ
1929 }
1930 if (m_drag)
1931 {
1932 m_lastmousepos[0] = x;
1933 m_lastmousepos[1] = y;
1934 }
1935 }
1936 }
1937
1938 #if 0
1939 //
1940 void SoftDemo::mouseFunc(int button, int state, int x, int y)
1941 {
1942 if(button==0)
1943 {
1944 switch(state)
1945 {
1946 case 0:
1947 {
1948 m_results.fraction=1.f;
1949 DemoApplication::mouseFunc(button,state,x,y);
1950 if(!m_pickConstraint)
1951 {
1952 const btVector3 rayFrom=m_cameraPosition;
1953 const btVector3 rayTo=getRayTo(x,y);
1954 const btVector3 rayDir=(rayTo-rayFrom).normalized();
1955 btSoftBodyArray& sbs=getSoftDynamicsWorld()->getSoftBodyArray();
1956 for(int ib=0;ib<sbs.size();++ib)
1957 {
1958 btSoftBody* psb=sbs[ib];
1959 btSoftBody::sRayCast res;
1960 if(psb->rayTest(rayFrom,rayTo,res))
1961 {
1962 m_results=res;
1963 }
1964 }
1965 if(m_results.fraction<1.f)
1966 {
1967 m_impact = rayFrom+(rayTo-rayFrom)*m_results.fraction;
1968 m_drag = m_cutting ? false : true;
1969 m_lastmousepos[0] = x;
1970 m_lastmousepos[1] = y;
1971 m_node = 0;
1972 switch(m_results.feature)
1973 {
1974 case btSoftBody::eFeature::Tetra:
1975 {
1976 btSoftBody::Tetra& tet=m_results.body->m_tetras[m_results.index];
1977 m_node=tet.m_n[0];
1978 for(int i=1;i<4;++i)
1979 {
1980 if( (m_node->m_x-m_impact).length2()>
1981 (tet.m_n[i]->m_x-m_impact).length2())
1982 {
1983 m_node=tet.m_n[i];
1984 }
1985 }
1986 break;
1987 }
1988 case btSoftBody::eFeature::Face:
1989 {
1990 btSoftBody::Face& f=m_results.body->m_faces[m_results.index];
1991 m_node=f.m_n[0];
1992 for(int i=1;i<3;++i)
1993 {
1994 if( (m_node->m_x-m_impact).length2()>
1995 (f.m_n[i]->m_x-m_impact).length2())
1996 {
1997 m_node=f.m_n[i];
1998 }
1999 }
2000 }
2001 break;
2002 }
2003 if(m_node) m_goal=m_node->m_x;
2004 return;
2005 }
2006 }
2007 }
2008 break;
2009 case 1:
2010 if((!m_drag)&&m_cutting&&(m_results.fraction<1.f))
2011 {
2012 ImplicitSphere isphere(m_impact,1);
2013 printf("Mass before: %f\r\n",m_results.body->getTotalMass());
2014 m_results.body->refine(&isphere,0.0001,true);
2015 printf("Mass after: %f\r\n",m_results.body->getTotalMass());
2016 }
2017 m_results.fraction=1.f;
2018 m_drag=false;
2019 DemoApplication::mouseFunc(button,state,x,y);
2020 break;
2021 }
2022 }
2023 else
2024 {
2025 DemoApplication::mouseFunc(button,state,x,y);
2026 }
2027 }
2028 #endif
2029
initPhysics()2030 void SoftDemo::initPhysics()
2031 {
2032 ///create concave ground mesh
2033
2034 m_guiHelper->setUpAxis(1);
2035 // m_azi = 0;
2036
2037 //reset and disable motorcontrol at the start
2038 motorcontrol.goal = 0;
2039 motorcontrol.maxtorque = 0;
2040
2041 btCollisionShape* groundShape = 0;
2042 {
2043 int i;
2044 int j;
2045
2046 const int NUM_VERTS_X = 30;
2047 const int NUM_VERTS_Y = 30;
2048 const int totalVerts = NUM_VERTS_X * NUM_VERTS_Y;
2049 const int totalTriangles = 2 * (NUM_VERTS_X - 1) * (NUM_VERTS_Y - 1);
2050
2051 gGroundVertices = new btVector3[totalVerts];
2052 gGroundIndices = new int[totalTriangles * 3];
2053
2054 btScalar offset(-50);
2055
2056 for (i = 0; i < NUM_VERTS_X; i++)
2057 {
2058 for (j = 0; j < NUM_VERTS_Y; j++)
2059 {
2060 gGroundVertices[i + j * NUM_VERTS_X].setValue((i - NUM_VERTS_X * 0.5f) * TRIANGLE_SIZE,
2061 //0.f,
2062 waveheight * sinf((float)i) * cosf((float)j + offset),
2063 (j - NUM_VERTS_Y * 0.5f) * TRIANGLE_SIZE);
2064 }
2065 }
2066
2067 int vertStride = sizeof(btVector3);
2068 int indexStride = 3 * sizeof(int);
2069
2070 int index = 0;
2071 for (i = 0; i < NUM_VERTS_X - 1; i++)
2072 {
2073 for (int j = 0; j < NUM_VERTS_Y - 1; j++)
2074 {
2075 gGroundIndices[index++] = j * NUM_VERTS_X + i;
2076 gGroundIndices[index++] = (j + 1) * NUM_VERTS_X + i + 1;
2077 gGroundIndices[index++] = j * NUM_VERTS_X + i + 1;
2078 ;
2079
2080 gGroundIndices[index++] = j * NUM_VERTS_X + i;
2081 gGroundIndices[index++] = (j + 1) * NUM_VERTS_X + i;
2082 gGroundIndices[index++] = (j + 1) * NUM_VERTS_X + i + 1;
2083 }
2084 }
2085
2086 btTriangleIndexVertexArray* indexVertexArrays = new btTriangleIndexVertexArray(totalTriangles,
2087 gGroundIndices,
2088 indexStride,
2089 totalVerts, (btScalar*)&gGroundVertices[0].x(), vertStride);
2090
2091 bool useQuantizedAabbCompression = true;
2092
2093 groundShape = new btBvhTriangleMeshShape(indexVertexArrays, useQuantizedAabbCompression);
2094 groundShape->setMargin(0.5);
2095 }
2096
2097 m_collisionShapes.push_back(groundShape);
2098
2099 btCollisionShape* groundBox = new btBoxShape(btVector3(100, CUBE_HALF_EXTENTS, 100));
2100 m_collisionShapes.push_back(groundBox);
2101
2102 btCompoundShape* cylinderCompound = new btCompoundShape;
2103 btCollisionShape* cylinderShape = new btCylinderShape(btVector3(CUBE_HALF_EXTENTS, CUBE_HALF_EXTENTS, CUBE_HALF_EXTENTS));
2104 btTransform localTransform;
2105 localTransform.setIdentity();
2106 cylinderCompound->addChildShape(localTransform, cylinderShape);
2107 btQuaternion orn(btVector3(0, 1, 0), SIMD_PI);
2108 localTransform.setRotation(orn);
2109 cylinderCompound->addChildShape(localTransform, cylinderShape);
2110
2111 m_collisionShapes.push_back(cylinderCompound);
2112
2113 m_dispatcher = 0;
2114
2115 ///register some softbody collision algorithms on top of the default btDefaultCollisionConfiguration
2116 m_collisionConfiguration = new btSoftBodyRigidBodyCollisionConfiguration();
2117
2118 m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration);
2119 m_softBodyWorldInfo.m_dispatcher = m_dispatcher;
2120
2121 ////////////////////////////
2122 ///Register softbody versus softbody collision algorithm
2123
2124 ///Register softbody versus rigidbody collision algorithm
2125
2126 ////////////////////////////
2127
2128 btVector3 worldAabbMin(-1000, -1000, -1000);
2129 btVector3 worldAabbMax(1000, 1000, 1000);
2130
2131 m_broadphase = new btAxisSweep3(worldAabbMin, worldAabbMax, maxProxies);
2132
2133 m_softBodyWorldInfo.m_broadphase = m_broadphase;
2134
2135 btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver();
2136
2137 m_solver = solver;
2138
2139 btSoftBodySolver* softBodySolver = 0;
2140 #ifdef USE_AMD_OPENCL
2141
2142 static bool once = true;
2143 if (once)
2144 {
2145 once = false;
2146 initCL(0, 0);
2147 }
2148
2149 if (g_openCLSIMDSolver)
2150 delete g_openCLSIMDSolver;
2151 if (g_softBodyOutput)
2152 delete g_softBodyOutput;
2153
2154 if (1)
2155 {
2156 g_openCLSIMDSolver = new btOpenCLSoftBodySolverSIMDAware(g_cqCommandQue, g_cxMainContext);
2157 // g_openCLSIMDSolver = new btOpenCLSoftBodySolver( g_cqCommandQue, g_cxMainContext);
2158 g_openCLSIMDSolver->setCLFunctions(new CachingCLFunctions(g_cqCommandQue, g_cxMainContext));
2159 }
2160
2161 softBodySolver = g_openCLSIMDSolver;
2162 g_softBodyOutput = new btSoftBodySolverOutputCLtoCPU;
2163 #endif //USE_AMD_OPENCL
2164
2165 btDiscreteDynamicsWorld* world = new btSoftRigidDynamicsWorld(m_dispatcher, m_broadphase, m_solver, m_collisionConfiguration, softBodySolver);
2166 m_dynamicsWorld = world;
2167 m_dynamicsWorld->setInternalTickCallback(pickingPreTickCallback, this, true);
2168
2169 m_dynamicsWorld->getDispatchInfo().m_enableSPU = true;
2170 m_dynamicsWorld->setGravity(btVector3(0, -10, 0));
2171 m_softBodyWorldInfo.m_gravity.setValue(0, -10, 0);
2172 m_guiHelper->createPhysicsDebugDrawer(world);
2173 // clientResetScene();
2174
2175 m_softBodyWorldInfo.m_sparsesdf.Initialize();
2176 // clientResetScene();
2177
2178 //create ground object
2179 btTransform tr;
2180 tr.setIdentity();
2181 tr.setOrigin(btVector3(0, -12, 0));
2182
2183 btCollisionObject* newOb = new btCollisionObject();
2184 newOb->setWorldTransform(tr);
2185 newOb->setInterpolationWorldTransform(tr);
2186 int lastDemo = (sizeof(demofncs) / sizeof(demofncs[0])) - 1;
2187
2188 if (current_demo < 0)
2189 current_demo = lastDemo;
2190 if (current_demo > lastDemo)
2191 current_demo = 0;
2192
2193 if (current_demo > 19)
2194 {
2195 newOb->setCollisionShape(m_collisionShapes[0]);
2196 }
2197 else
2198 {
2199 newOb->setCollisionShape(m_collisionShapes[1]);
2200 }
2201
2202 m_dynamicsWorld->addCollisionObject(newOb);
2203
2204 m_softBodyWorldInfo.m_sparsesdf.Reset();
2205
2206 motorcontrol.goal = 0;
2207 motorcontrol.maxtorque = 0;
2208
2209 m_softBodyWorldInfo.air_density = (btScalar)1.2;
2210 m_softBodyWorldInfo.water_density = 0;
2211 m_softBodyWorldInfo.water_offset = 0;
2212 m_softBodyWorldInfo.water_normal = btVector3(0, 0, 0);
2213 m_softBodyWorldInfo.m_gravity.setValue(0, -10, 0);
2214
2215 m_autocam = false;
2216 m_raycast = false;
2217 m_cutting = false;
2218 m_results.fraction = 1.f;
2219
2220 demofncs[current_demo](this);
2221
2222 m_guiHelper->autogenerateGraphicsObjects(m_dynamicsWorld);
2223 }
2224
exitPhysics()2225 void SoftDemo::exitPhysics()
2226 {
2227 //cleanup in the reverse order of creation/initialization
2228
2229 //remove the rigidbodies from the dynamics world and delete them
2230 int i;
2231 for (i = m_dynamicsWorld->getNumCollisionObjects() - 1; i >= 0; i--)
2232 {
2233 btCollisionObject* obj = m_dynamicsWorld->getCollisionObjectArray()[i];
2234 btRigidBody* body = btRigidBody::upcast(obj);
2235 if (body && body->getMotionState())
2236 {
2237 delete body->getMotionState();
2238 }
2239 m_dynamicsWorld->removeCollisionObject(obj);
2240 delete obj;
2241 }
2242
2243 //delete collision shapes
2244 for (int j = 0; j < m_collisionShapes.size(); j++)
2245 {
2246 btCollisionShape* shape = m_collisionShapes[j];
2247 m_collisionShapes[j] = 0;
2248 delete shape;
2249 }
2250
2251 //delete dynamics world
2252 delete m_dynamicsWorld;
2253 m_dynamicsWorld = 0;
2254
2255 //delete solver
2256 delete m_solver;
2257
2258 //delete broadphase
2259 delete m_broadphase;
2260
2261 //delete dispatcher
2262 delete m_dispatcher;
2263
2264 delete m_collisionConfiguration;
2265 }
2266
SoftDemoCreateFunc(struct CommonExampleOptions & options)2267 class CommonExampleInterface* SoftDemoCreateFunc(struct CommonExampleOptions& options)
2268 {
2269 current_demo = options.m_option;
2270 return new SoftDemo(options.m_guiHelper);
2271 }
2272