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