1 /*
2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2015 Google Inc. http://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 #include "SimpleCloth.h"
17 
18 #include "btBulletDynamicsCommon.h"
19 #include "LinearMath/btVector3.h"
20 #include "LinearMath/btAlignedObjectArray.h"
21 #include "../CommonInterfaces/CommonRigidBodyBase.h"
22 
23 #include "BulletSoftBody/btSoftRigidDynamicsWorld.h"
24 #include "BulletSoftBody/btSoftBodyHelpers.h"
25 #include "BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h"
26 
27 struct SimpleClothExample : public CommonRigidBodyBase
28 {
SimpleClothExampleSimpleClothExample29 	SimpleClothExample(struct GUIHelperInterface* helper)
30 		: CommonRigidBodyBase(helper)
31 	{
32 	}
~SimpleClothExampleSimpleClothExample33 	virtual ~SimpleClothExample() {}
34 	virtual void initPhysics();
35 	virtual void renderScene();
createEmptyDynamicsWorldSimpleClothExample36 	void createEmptyDynamicsWorld()
37 	{
38 		m_collisionConfiguration = new btSoftBodyRigidBodyCollisionConfiguration();
39 		m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration);
40 
41 		m_broadphase = new btDbvtBroadphase();
42 
43 		m_solver = new btSequentialImpulseConstraintSolver;
44 
45 		m_dynamicsWorld = new btSoftRigidDynamicsWorld(m_dispatcher, m_broadphase, m_solver, m_collisionConfiguration);
46 		m_dynamicsWorld->setGravity(btVector3(0, -10, 0));
47 
48 		softBodyWorldInfo.m_broadphase = m_broadphase;
49 		softBodyWorldInfo.m_dispatcher = m_dispatcher;
50 		softBodyWorldInfo.m_gravity = m_dynamicsWorld->getGravity();
51 		softBodyWorldInfo.m_sparsesdf.Initialize();
52 	}
getSoftDynamicsWorldSimpleClothExample53 	virtual btSoftRigidDynamicsWorld* getSoftDynamicsWorld()
54 	{
55 		///just make it a btSoftRigidDynamicsWorld please
56 		///or we will add type checking
57 		return (btSoftRigidDynamicsWorld*)m_dynamicsWorld;
58 	}
resetCameraSimpleClothExample59 	void resetCamera()
60 	{
61 		float dist = 41;
62 		float pitch = -35;
63 		float yaw = 52;
64 		float targetPos[3] = {0, 0.46, 0};
65 		m_guiHelper->resetCamera(dist, yaw, pitch, targetPos[0], targetPos[1], targetPos[2]);
66 	}
67 
68 	void createSoftBody(const btScalar size, const int num_x, const int num_z, const int fixed = 1 + 2);
69 	btSoftBodyWorldInfo softBodyWorldInfo;
70 };
71 
initPhysics()72 void SimpleClothExample::initPhysics()
73 {
74 	m_guiHelper->setUpAxis(1);
75 
76 	createEmptyDynamicsWorld();
77 
78 	m_guiHelper->createPhysicsDebugDrawer(m_dynamicsWorld);
79 
80 	if (m_dynamicsWorld->getDebugDrawer())
81 		m_dynamicsWorld->getDebugDrawer()->setDebugMode(btIDebugDraw::DBG_DrawWireframe + btIDebugDraw::DBG_DrawContactPoints);
82 
83 	///create a few basic rigid bodies
84 	btBoxShape* groundShape = createBoxShape(btVector3(btScalar(50.), btScalar(50.), btScalar(50.)));
85 	m_collisionShapes.push_back(groundShape);
86 
87 	btTransform groundTransform;
88 	groundTransform.setIdentity();
89 	groundTransform.setOrigin(btVector3(0, -50, 0));
90 	{
91 		btScalar mass(0.);
92 		createRigidBody(mass, groundTransform, groundShape, btVector4(0, 0, 1, 1));
93 	}
94 
95 	{
96 		const btScalar s = 4;  //size of cloth patch
97 		const int NUM_X = 31;  //vertices on X axis
98 		const int NUM_Z = 31;  //vertices on Z axis
99 		createSoftBody(s, NUM_X, NUM_Z);
100 	}
101 
102 	m_guiHelper->autogenerateGraphicsObjects(m_dynamicsWorld);
103 }
104 
createSoftBody(const btScalar s,const int numX,const int numY,const int fixed)105 void SimpleClothExample::createSoftBody(const btScalar s,
106 										const int numX,
107 										const int numY,
108 										const int fixed)
109 {
110 	btSoftBody* cloth = btSoftBodyHelpers::CreatePatch(softBodyWorldInfo,
111 													   btVector3(-s / 2, s + 1, 0),
112 													   btVector3(+s / 2, s + 1, 0),
113 													   btVector3(-s / 2, s + 1, +s),
114 													   btVector3(+s / 2, s + 1, +s),
115 													   numX, numY,
116 													   fixed, true);
117 
118 	cloth->getCollisionShape()->setMargin(0.001f);
119 	cloth->getCollisionShape()->setUserPointer((void*)cloth);
120 	cloth->generateBendingConstraints(2, cloth->appendMaterial());
121 	cloth->setTotalMass(10);
122 	//cloth->m_cfg.citerations = 10;
123 	//	cloth->m_cfg.diterations = 10;
124 	cloth->m_cfg.piterations = 5;
125 	cloth->m_cfg.kDP = 0.005f;
126 	getSoftDynamicsWorld()->addSoftBody(cloth);
127 }
128 
renderScene()129 void SimpleClothExample::renderScene()
130 {
131 	CommonRigidBodyBase::renderScene();
132 	btSoftRigidDynamicsWorld* softWorld = getSoftDynamicsWorld();
133 
134 	for (int i = 0; i < softWorld->getSoftBodyArray().size(); i++)
135 	{
136 		btSoftBody* psb = (btSoftBody*)softWorld->getSoftBodyArray()[i];
137 		//if (softWorld->getDebugDrawer() && !(softWorld->getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe)))
138 		{
139 			btSoftBodyHelpers::DrawFrame(psb, softWorld->getDebugDrawer());
140 			btSoftBodyHelpers::Draw(psb, softWorld->getDebugDrawer(), softWorld->getDrawFlags());
141 		}
142 	}
143 }
144 
ET_SimpleClothCreateFunc(CommonExampleOptions & options)145 CommonExampleInterface* ET_SimpleClothCreateFunc(CommonExampleOptions& options)
146 {
147 	return new SimpleClothExample(options.m_guiHelper);
148 }
149