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