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 #include "BulletCollision/CollisionShapes/btBox2dShape.h"
17 #include "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h"
18 #include "BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h"
19 #include "BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h"
20
21 #include "BulletCollision/CollisionShapes/btBox2dShape.h"
22 #include "BulletCollision/CollisionShapes/btConvex2dShape.h"
23 #include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h"
24
25 ///create 125 (5x5x5) dynamic object
26 #define ARRAY_SIZE_X 5
27 #define ARRAY_SIZE_Y 5
28 #define ARRAY_SIZE_Z 1
29
30 //maximum number of objects (and allow user to shoot additional boxes)
31 #define MAX_PROXIES (ARRAY_SIZE_X * ARRAY_SIZE_Y * ARRAY_SIZE_Z + 1024)
32
33 ///scaling of the objects (0.1 = 20 centimeter boxes )
34 #define SCALING 1
35 #define START_POS_X -5
36 #define START_POS_Y -5
37 #define START_POS_Z -3
38
39 #include "Planar2D.h"
40
41 ///btBulletDynamicsCommon.h is the main Bullet include file, contains most common include files.
42 #include "btBulletDynamicsCommon.h"
43 #include <stdio.h> //printf debugging
44
45 #include "LinearMath/btAlignedObjectArray.h"
46
47 class btBroadphaseInterface;
48 class btCollisionShape;
49 class btOverlappingPairCache;
50 class btCollisionDispatcher;
51 class btConstraintSolver;
52 struct btCollisionAlgorithmCreateFunc;
53 class btDefaultCollisionConfiguration;
54 class GL_DialogDynamicsWorld;
55
56 #include "../CommonInterfaces/CommonRigidBodyBase.h"
57
58 class Planar2D : public CommonRigidBodyBase
59 {
60 //keep the collision shapes, for deletion/cleanup
61 btAlignedObjectArray<btCollisionShape*> m_collisionShapes;
62
63 btBroadphaseInterface* m_broadphase;
64
65 btCollisionDispatcher* m_dispatcher;
66
67 btConstraintSolver* m_solver;
68
69 btDefaultCollisionConfiguration* m_collisionConfiguration;
70
71 btConvex2dConvex2dAlgorithm::CreateFunc* m_convexAlgo2d;
72 btVoronoiSimplexSolver* m_simplexSolver;
73 btMinkowskiPenetrationDepthSolver* m_pdSolver;
74 btBox2dBox2dCollisionAlgorithm::CreateFunc* m_box2dbox2dAlgo;
75
76 public:
Planar2D(struct GUIHelperInterface * helper)77 Planar2D(struct GUIHelperInterface* helper)
78 : CommonRigidBodyBase(helper)
79 {
80 }
~Planar2D()81 virtual ~Planar2D()
82 {
83 exitPhysics();
84 }
85
86 void initPhysics();
87
88 void exitPhysics();
89
resetCamera()90 void resetCamera()
91 {
92 float dist = 9;
93 float pitch = -11;
94 float yaw = 539;
95 float targetPos[3] = {8.6, 10.5, -20.6};
96 m_guiHelper->resetCamera(dist, yaw, pitch, targetPos[0], targetPos[1], targetPos[2]);
97 }
98 };
99
initPhysics()100 void Planar2D::initPhysics()
101 {
102 m_guiHelper->setUpAxis(1);
103
104 ///collision configuration contains default setup for memory, collision setup
105 m_collisionConfiguration = new btDefaultCollisionConfiguration();
106 //m_collisionConfiguration->setConvexConvexMultipointIterations();
107
108 ///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded)
109 m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration);
110
111 m_simplexSolver = new btVoronoiSimplexSolver();
112 m_pdSolver = new btMinkowskiPenetrationDepthSolver();
113
114 m_convexAlgo2d = new btConvex2dConvex2dAlgorithm::CreateFunc(m_simplexSolver, m_pdSolver);
115 m_box2dbox2dAlgo = new btBox2dBox2dCollisionAlgorithm::CreateFunc();
116
117 m_dispatcher->registerCollisionCreateFunc(CONVEX_2D_SHAPE_PROXYTYPE, CONVEX_2D_SHAPE_PROXYTYPE, m_convexAlgo2d);
118 m_dispatcher->registerCollisionCreateFunc(BOX_2D_SHAPE_PROXYTYPE, CONVEX_2D_SHAPE_PROXYTYPE, m_convexAlgo2d);
119 m_dispatcher->registerCollisionCreateFunc(CONVEX_2D_SHAPE_PROXYTYPE, BOX_2D_SHAPE_PROXYTYPE, m_convexAlgo2d);
120 m_dispatcher->registerCollisionCreateFunc(BOX_2D_SHAPE_PROXYTYPE, BOX_2D_SHAPE_PROXYTYPE, m_box2dbox2dAlgo);
121
122 m_broadphase = new btDbvtBroadphase();
123 //m_broadphase = new btSimpleBroadphase();
124
125 ///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded)
126 btSequentialImpulseConstraintSolver* sol = new btSequentialImpulseConstraintSolver;
127 m_solver = sol;
128
129 m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher, m_broadphase, m_solver, m_collisionConfiguration);
130 //m_dynamicsWorld->getSolverInfo().m_erp = 1.f;
131 //m_dynamicsWorld->getSolverInfo().m_numIterations = 4;
132 m_guiHelper->createPhysicsDebugDrawer(m_dynamicsWorld);
133
134 m_dynamicsWorld->setGravity(btVector3(0, -10, 0));
135
136 ///create a few basic rigid bodies
137 btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(150.), btScalar(50.), btScalar(150.)));
138 // btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),50);
139
140 m_collisionShapes.push_back(groundShape);
141
142 btTransform groundTransform;
143 groundTransform.setIdentity();
144 groundTransform.setOrigin(btVector3(0, -43, 0));
145
146 //We can also use DemoApplication::localCreateRigidBody, but for clarity it is provided here:
147 {
148 btScalar mass(0.);
149
150 //rigidbody is dynamic if and only if mass is non zero, otherwise static
151 bool isDynamic = (mass != 0.f);
152
153 btVector3 localInertia(0, 0, 0);
154 if (isDynamic)
155 groundShape->calculateLocalInertia(mass, localInertia);
156
157 //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
158 btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform);
159 btRigidBody::btRigidBodyConstructionInfo rbInfo(mass, myMotionState, groundShape, localInertia);
160 btRigidBody* body = new btRigidBody(rbInfo);
161
162 //add the body to the dynamics world
163 m_dynamicsWorld->addRigidBody(body);
164 }
165
166 {
167 //create a few dynamic rigidbodies
168 // Re-using the same collision is better for memory usage and performance
169
170 btScalar u = btScalar(1 * SCALING - 0.04);
171 btVector3 points[3] = {btVector3(0, u, 0), btVector3(-u, -u, 0), btVector3(u, -u, 0)};
172 btConvexShape* childShape0 = new btBoxShape(btVector3(btScalar(SCALING * 1), btScalar(SCALING * 1), btScalar(0.04)));
173 btConvexShape* colShape = new btConvex2dShape(childShape0);
174 //btCollisionShape* colShape = new btBox2dShape(btVector3(SCALING*1,SCALING*1,0.04));
175 btConvexShape* childShape1 = new btConvexHullShape(&points[0].getX(), 3);
176 btConvexShape* colShape2 = new btConvex2dShape(childShape1);
177 btConvexShape* childShape2 = new btCylinderShapeZ(btVector3(btScalar(SCALING * 1), btScalar(SCALING * 1), btScalar(0.04)));
178 btConvexShape* colShape3 = new btConvex2dShape(childShape2);
179
180 m_collisionShapes.push_back(colShape);
181 m_collisionShapes.push_back(colShape2);
182 m_collisionShapes.push_back(colShape3);
183
184 m_collisionShapes.push_back(childShape0);
185 m_collisionShapes.push_back(childShape1);
186 m_collisionShapes.push_back(childShape2);
187
188 //btUniformScalingShape* colShape = new btUniformScalingShape(convexColShape,1.f);
189 colShape->setMargin(btScalar(0.03));
190 //btCollisionShape* colShape = new btSphereShape(btScalar(1.));
191
192 /// Create Dynamic Objects
193 btTransform startTransform;
194 startTransform.setIdentity();
195
196 btScalar mass(1.f);
197
198 //rigidbody is dynamic if and only if mass is non zero, otherwise static
199 bool isDynamic = (mass != 0.f);
200
201 btVector3 localInertia(0, 0, 0);
202 if (isDynamic)
203 colShape->calculateLocalInertia(mass, localInertia);
204
205 // float start_x = START_POS_X - ARRAY_SIZE_X/2;
206 // float start_y = START_POS_Y;
207 // float start_z = START_POS_Z - ARRAY_SIZE_Z/2;
208
209 btVector3 x(-ARRAY_SIZE_X, 8.0f, -20.f);
210 btVector3 y;
211 btVector3 deltaX(SCALING * 1, SCALING * 2, 0.f);
212 btVector3 deltaY(SCALING * 2, 0.0f, 0.f);
213
214 for (int i = 0; i < ARRAY_SIZE_X; ++i)
215 {
216 y = x;
217
218 for (int j = i; j < ARRAY_SIZE_Y; ++j)
219 {
220 startTransform.setOrigin(y - btVector3(-10, 0, 0));
221
222 //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
223 btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform);
224 btRigidBody::btRigidBodyConstructionInfo rbInfo(0, 0, 0);
225 switch (j % 3)
226 {
227 #if 1
228 case 0:
229 rbInfo = btRigidBody::btRigidBodyConstructionInfo(mass, myMotionState, colShape, localInertia);
230 break;
231 case 1:
232 rbInfo = btRigidBody::btRigidBodyConstructionInfo(mass, myMotionState, colShape3, localInertia);
233 break;
234 #endif
235 default:
236 rbInfo = btRigidBody::btRigidBodyConstructionInfo(mass, myMotionState, colShape2, localInertia);
237 }
238 btRigidBody* body = new btRigidBody(rbInfo);
239 //body->setContactProcessingThreshold(colShape->getContactBreakingThreshold());
240 body->setActivationState(ISLAND_SLEEPING);
241 body->setLinearFactor(btVector3(1, 1, 0));
242 body->setAngularFactor(btVector3(0, 0, 1));
243
244 m_dynamicsWorld->addRigidBody(body);
245 body->setActivationState(ISLAND_SLEEPING);
246
247 // y += -0.8*deltaY;
248 y += deltaY;
249 }
250
251 x += deltaX;
252 }
253 }
254
255 m_guiHelper->autogenerateGraphicsObjects(m_dynamicsWorld);
256 }
257
exitPhysics()258 void Planar2D::exitPhysics()
259 {
260 //cleanup in the reverse order of creation/initialization
261
262 //remove the rigidbodies from the dynamics world and delete them
263 int i;
264 if (m_dynamicsWorld)
265 for (i = m_dynamicsWorld->getNumCollisionObjects() - 1; i >= 0; i--)
266 {
267 btCollisionObject* obj = m_dynamicsWorld->getCollisionObjectArray()[i];
268 btRigidBody* body = btRigidBody::upcast(obj);
269 if (body && body->getMotionState())
270 {
271 delete body->getMotionState();
272 }
273 m_dynamicsWorld->removeCollisionObject(obj);
274 delete obj;
275 }
276
277 //delete collision shapes
278 for (int j = 0; j < m_collisionShapes.size(); j++)
279 {
280 btCollisionShape* shape = m_collisionShapes[j];
281 delete shape;
282 }
283 m_collisionShapes.clear();
284
285 delete m_dynamicsWorld;
286
287 delete m_solver;
288
289 delete m_broadphase;
290
291 delete m_dispatcher;
292
293 delete m_collisionConfiguration;
294
295 delete m_convexAlgo2d;
296 delete m_pdSolver;
297 delete m_simplexSolver;
298 delete m_box2dbox2dAlgo;
299
300 m_dynamicsWorld = 0;
301 m_solver = 0;
302 m_broadphase = 0;
303 m_dispatcher = 0;
304 m_collisionConfiguration = 0;
305 m_convexAlgo2d = 0;
306 m_pdSolver = 0;
307 m_simplexSolver = 0;
308 m_box2dbox2dAlgo = 0;
309 }
310
Planar2DCreateFunc(struct CommonExampleOptions & options)311 CommonExampleInterface* Planar2DCreateFunc(struct CommonExampleOptions& options)
312 {
313 return new Planar2D(options.m_guiHelper);
314 }
315