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