Imported Upstream version 2.81
[platform/upstream/libbullet.git] / Demos / RollingFrictionDemo / RollingFrictionDemo.cpp
1 /*\r
2 Bullet Continuous Collision Detection and Physics Library\r
3 Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/\r
4 \r
5 This software is provided 'as-is', without any express or implied warranty.\r
6 In no event will the authors be held liable for any damages arising from the use of this software.\r
7 Permission is granted to anyone to use this software for any purpose, \r
8 including commercial applications, and to alter it and redistribute it freely, \r
9 subject to the following restrictions:\r
10 \r
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.\r
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\r
13 3. This notice may not be removed or altered from any source distribution.\r
14 */\r
15 \r
16 \r
17 ///create 125 (5x5x5) dynamic object\r
18 #define ARRAY_SIZE_X 5\r
19 #define ARRAY_SIZE_Y 5\r
20 #define ARRAY_SIZE_Z 5\r
21 \r
22 //maximum number of objects (and allow user to shoot additional boxes)\r
23 #define MAX_PROXIES (ARRAY_SIZE_X*ARRAY_SIZE_Y*ARRAY_SIZE_Z + 1024)\r
24 \r
25 ///scaling of the objects (0.1 = 20 centimeter boxes )\r
26 #define SCALING 1.\r
27 #define START_POS_X -5\r
28 #define START_POS_Y -5\r
29 #define START_POS_Z -3\r
30 \r
31 #include "RollingFrictionDemo.h"\r
32 #include "GlutStuff.h"\r
33 ///btBulletDynamicsCommon.h is the main Bullet include file, contains most common include files.\r
34 #include "btBulletDynamicsCommon.h"\r
35 #include "GLDebugDrawer.h"\r
36 static GLDebugDrawer sDebugDraw;\r
37 #include <stdio.h> //printf debugging\r
38 \r
39 \r
40 void RollingFrictionDemo::clientMoveAndDisplay()\r
41 {\r
42         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); \r
43 \r
44         //simple dynamics world doesn't handle fixed-time-stepping\r
45         float ms = getDeltaTimeMicroseconds();\r
46         \r
47         ///step the simulation\r
48         if (m_dynamicsWorld)\r
49         {\r
50                 m_dynamicsWorld->stepSimulation(ms / 1000000.f);\r
51                 //optional but useful: debug drawing\r
52                 m_dynamicsWorld->debugDrawWorld();\r
53         }\r
54                 \r
55         renderme(); \r
56 \r
57         glFlush();\r
58 \r
59         swapBuffers();\r
60 \r
61 }\r
62 \r
63 \r
64 \r
65 void RollingFrictionDemo::displayCallback(void) {\r
66 \r
67         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); \r
68         \r
69         renderme();\r
70 \r
71         //optional but useful: debug drawing to detect problems\r
72         if (m_dynamicsWorld)\r
73                 m_dynamicsWorld->debugDrawWorld();\r
74 \r
75         glFlush();\r
76         swapBuffers();\r
77 }\r
78 \r
79 \r
80 \r
81 \r
82 \r
83 void    RollingFrictionDemo::initPhysics()\r
84 {\r
85         setTexturing(true);\r
86         setShadows(true);\r
87 \r
88         setCameraDistance(btScalar(SCALING*26.));\r
89 \r
90         ///collision configuration contains default setup for memory, collision setup\r
91         m_collisionConfiguration = new btDefaultCollisionConfiguration();\r
92         //m_collisionConfiguration->setConvexConvexMultipointIterations();\r
93 \r
94         ///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded)\r
95         m_dispatcher = new      btCollisionDispatcher(m_collisionConfiguration);\r
96 \r
97         m_broadphase = new btDbvtBroadphase();\r
98 \r
99         ///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded)\r
100         btSequentialImpulseConstraintSolver* sol = new btSequentialImpulseConstraintSolver;\r
101         m_solver = sol;\r
102 \r
103         m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration);\r
104         m_dynamicsWorld->setDebugDrawer(&sDebugDraw);\r
105 //      m_dynamicsWorld->getSolverInfo().m_singleAxisRollingFrictionThreshold = 0.f;//faster but lower quality\r
106         m_dynamicsWorld->setGravity(btVector3(0,-10,0));\r
107 \r
108         {\r
109 \r
110                 ///create a few basic rigid bodies\r
111                 btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(20.),btScalar(50.),btScalar(10.)));\r
112 \r
113         //      btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),50);\r
114         \r
115                 m_collisionShapes.push_back(groundShape);\r
116 \r
117                 btTransform groundTransform;\r
118                 groundTransform.setIdentity();\r
119                 groundTransform.setOrigin(btVector3(0,-50,0));\r
120                 groundTransform.setRotation(btQuaternion(btVector3(0,0,1),SIMD_PI*0.03));\r
121                 //We can also use DemoApplication::localCreateRigidBody, but for clarity it is provided here:\r
122                 btScalar mass(0.);\r
123 \r
124                 //rigidbody is dynamic if and only if mass is non zero, otherwise static\r
125                 bool isDynamic = (mass != 0.f);\r
126 \r
127                 btVector3 localInertia(0,0,0);\r
128                 if (isDynamic)\r
129                         groundShape->calculateLocalInertia(mass,localInertia);\r
130 \r
131                 //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects\r
132                 btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform);\r
133                 btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,groundShape,localInertia);\r
134                 btRigidBody* body = new btRigidBody(rbInfo);\r
135                 body->setFriction(1);\r
136                 body->setRollingFriction(1);\r
137                 //add the body to the dynamics world\r
138                 m_dynamicsWorld->addRigidBody(body);\r
139         }\r
140 \r
141         {\r
142 \r
143                 ///create a few basic rigid bodies\r
144                 btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(100.),btScalar(50.),btScalar(100.)));\r
145         \r
146                 m_collisionShapes.push_back(groundShape);\r
147 \r
148                 btTransform groundTransform;\r
149                 groundTransform.setIdentity();\r
150                 groundTransform.setOrigin(btVector3(0,-54,0));\r
151                 //We can also use DemoApplication::localCreateRigidBody, but for clarity it is provided here:\r
152                 btScalar mass(0.);\r
153 \r
154                 //rigidbody is dynamic if and only if mass is non zero, otherwise static\r
155                 bool isDynamic = (mass != 0.f);\r
156 \r
157                 btVector3 localInertia(0,0,0);\r
158                 if (isDynamic)\r
159                         groundShape->calculateLocalInertia(mass,localInertia);\r
160 \r
161                 //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects\r
162                 btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform);\r
163                 btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,groundShape,localInertia);\r
164                 btRigidBody* body = new btRigidBody(rbInfo);\r
165                 body->setFriction(1);\r
166                 body->setRollingFriction(1);\r
167                 //add the body to the dynamics world\r
168                 m_dynamicsWorld->addRigidBody(body);\r
169         }\r
170 \r
171         {\r
172                 //create a few dynamic rigidbodies\r
173                 // Re-using the same collision is better for memory usage and performance\r
174 #define NUM_SHAPES 10\r
175                 btCollisionShape* colShapes[NUM_SHAPES] = {\r
176                         new btSphereShape(btScalar(1.)),\r
177                         new btCapsuleShape(0.5,1),\r
178                         new btCapsuleShapeX(0.5,1),\r
179                         new btCapsuleShapeZ(0.5,1),\r
180                         new btConeShape(0.5,1),\r
181                         new btConeShapeX(0.5,1),\r
182                         new btConeShapeZ(0.5,1),\r
183                         new btCylinderShape(btVector3(0.5,1,0.5)),\r
184                         new btCylinderShapeX(btVector3(1,0.5,0.5)),\r
185                         new btCylinderShapeZ(btVector3(0.5,0.5,1)),\r
186                 };\r
187                 for (int i=0;i<NUM_SHAPES;i++)\r
188                         m_collisionShapes.push_back(colShapes[i]);\r
189 \r
190                 /// Create Dynamic Objects\r
191                 btTransform startTransform;\r
192                 startTransform.setIdentity();\r
193 \r
194                 btScalar        mass(1.f);\r
195 \r
196                 //rigidbody is dynamic if and only if mass is non zero, otherwise static\r
197                 \r
198                 float start_x = START_POS_X - ARRAY_SIZE_X/2;\r
199                 float start_y = START_POS_Y;\r
200                 float start_z = START_POS_Z - ARRAY_SIZE_Z/2;\r
201 \r
202                 {\r
203                         int shapeIndex = 0;\r
204                         for (int k=0;k<ARRAY_SIZE_Y;k++)\r
205                         {\r
206                                 for (int i=0;i<ARRAY_SIZE_X;i++)\r
207                                 {\r
208                                         for(int j = 0;j<ARRAY_SIZE_Z;j++)\r
209                                         {\r
210                                                 startTransform.setOrigin(SCALING*btVector3(\r
211                                                                                         btScalar(2.0*i + start_x),\r
212                                                                                         btScalar(20+2.0*k + start_y),\r
213                                                                                         btScalar(2.0*j + start_z)));\r
214 \r
215 \r
216                                                 shapeIndex++;\r
217                                                 btCollisionShape* colShape = colShapes[shapeIndex%NUM_SHAPES];\r
218                                                 bool isDynamic = (mass != 0.f);\r
219                                                 btVector3 localInertia(0,0,0);\r
220 \r
221                                                 if (isDynamic)\r
222                                                         colShape->calculateLocalInertia(mass,localInertia);\r
223 \r
224                                                 //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects\r
225                                                 btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform);\r
226                                                 btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,colShape,localInertia);\r
227                                                 btRigidBody* body = new btRigidBody(rbInfo);\r
228                                                 body->setFriction(1.f);\r
229                                                 body->setRollingFriction(.3);\r
230                                                 body->setAnisotropicFriction(colShape->getAnisotropicRollingFrictionDirection(),btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);\r
231 \r
232 \r
233                                                 m_dynamicsWorld->addRigidBody(body);\r
234                                         }\r
235                                 }\r
236                         }\r
237                 }\r
238         }\r
239 \r
240 \r
241 }\r
242 void    RollingFrictionDemo::clientResetScene()\r
243 {\r
244         exitPhysics();\r
245         initPhysics();\r
246 }\r
247         \r
248 \r
249 void    RollingFrictionDemo::exitPhysics()\r
250 {\r
251 \r
252         //cleanup in the reverse order of creation/initialization\r
253 \r
254         //remove the rigidbodies from the dynamics world and delete them\r
255         int i;\r
256         for (i=m_dynamicsWorld->getNumCollisionObjects()-1; i>=0 ;i--)\r
257         {\r
258                 btCollisionObject* obj = m_dynamicsWorld->getCollisionObjectArray()[i];\r
259                 btRigidBody* body = btRigidBody::upcast(obj);\r
260                 if (body && body->getMotionState())\r
261                 {\r
262                         delete body->getMotionState();\r
263                 }\r
264                 m_dynamicsWorld->removeCollisionObject( obj );\r
265                 delete obj;\r
266         }\r
267 \r
268         //delete collision shapes\r
269         for (int j=0;j<m_collisionShapes.size();j++)\r
270         {\r
271                 btCollisionShape* shape = m_collisionShapes[j];\r
272                 delete shape;\r
273         }\r
274         m_collisionShapes.clear();\r
275 \r
276         delete m_dynamicsWorld;\r
277         \r
278         delete m_solver;\r
279         \r
280         delete m_broadphase;\r
281         \r
282         delete m_dispatcher;\r
283 \r
284         delete m_collisionConfiguration;\r
285 \r
286         \r
287 }\r
288 \r
289 \r
290 \r
291 \r