2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
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:
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.
17 Added by Roman Ponomarev (rponom@gmail.com)
20 Added support for ODE sover
27 #include "btBulletDynamicsCommon.h"
28 #include "LinearMath/btIDebugDraw.h"
30 #include "GLDebugDrawer.h"
33 #include <stdio.h> //printf debugging
35 #include "SliderConstraintDemo.h"
36 #include "GL_ShapeDrawer.h"
37 #include "GlutStuff.h"
41 #define SLIDER_DEMO_USE_ODE_SOLVER 0
42 #define SLIDER_DEMO_USE_6DOF 0
44 #define CUBE_HALF_EXTENTS 1.f
46 #define SLIDER_ENABLE_ALL_DEMOS 1
50 // A couple of sliders
51 #if SLIDER_DEMO_USE_6DOF
52 static btGeneric6DofConstraint *spSlider1, *spSlider2;
54 static btSliderConstraint *spSlider1, *spSlider2;
57 static btPoint2PointConstraint* spP2PConst;
58 static btHingeConstraint* spHingeConst;
62 static void draw_axes(const btRigidBody& rb, const btTransform& frame)
65 // draw world transform
66 btVector3 from = rb.getWorldTransform().getOrigin();
67 btVector3 to = from + rb.getWorldTransform().getBasis() * btVector3(5,0,0);
69 glColor3f(255.0F, 0.0F, 0.0F);
70 glVertex3d(from.getX(), from.getY(), from.getZ());
71 glVertex3d(to.getX(), to.getY(), to.getZ());
72 to = from + rb.getWorldTransform().getBasis() * btVector3(0,5,0);
74 glColor3f(0.0F, 255.0F, 0.0F);
75 glVertex3d(from.getX(), from.getY(), from.getZ());
76 glVertex3d(to.getX(), to.getY(), to.getZ());
77 to = from + rb.getWorldTransform().getBasis() * btVector3(0,0,5);
79 glColor3f(0.0F, 0.0F, 255.0F);
80 glVertex3d(from.getX(), from.getY(), from.getZ());
81 glVertex3d(to.getX(), to.getY(), to.getZ());
83 btTransform calc_frame = rb.getWorldTransform() * frame;
84 from = calc_frame.getOrigin();
85 to = from + calc_frame.getBasis() * btVector3(10,0,0);
87 glColor3f(255.0F, 0.0F, 0.0F);
88 glVertex3d(from.getX(), from.getY(), from.getZ());
89 glVertex3d(to.getX(), to.getY(), to.getZ());
90 to = from + calc_frame.getBasis() * btVector3(0,10,0);
92 glColor3f(0.0F, 255.0F, 0.0F);
93 glVertex3d(from.getX(), from.getY(), from.getZ());
94 glVertex3d(to.getX(), to.getY(), to.getZ());
95 to = from + calc_frame.getBasis() * btVector3(0,0,10);
97 glColor3f(0.0F, 0.0F, 255.0F);
98 glVertex3d(from.getX(), from.getY(), from.getZ());
99 glVertex3d(to.getX(), to.getY(), to.getZ());
105 #if SLIDER_DEMO_USE_6DOF
106 static void drawSlider(btGeneric6DofConstraint* pSlider)
108 draw_axes(pSlider->getRigidBodyA(), pSlider->getFrameOffsetA());
109 draw_axes(pSlider->getRigidBodyB(), pSlider->getFrameOffsetB());
112 static void drawSlider(btSliderConstraint* pSlider)
114 draw_axes(pSlider->getRigidBodyA(), pSlider->getFrameOffsetA());
115 draw_axes(pSlider->getRigidBodyB(), pSlider->getFrameOffsetB());
116 // draw limits in white
117 btVector3 from(pSlider->getLowerLinLimit(), 0, 0);
118 btVector3 to(pSlider->getUpperLinLimit(), 0, 0);
120 if(pSlider->getUseLinearReferenceFrameA())
122 trans = pSlider->getRigidBodyA().getWorldTransform() * pSlider->getFrameOffsetA();
126 trans = pSlider->getRigidBodyB().getWorldTransform() * pSlider->getFrameOffsetB();
131 glColor3f(255.0F, 255.0F, 255.0F);
132 glVertex3d(from.getX(), from.getY(), from.getZ());
133 glVertex3d(to.getX(), to.getY(), to.getZ());
140 void SliderConstraintDemo::initPhysics()
145 setCameraDistance(26.f);
148 m_collisionConfiguration = new btDefaultCollisionConfiguration();
149 m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration);
150 btVector3 worldMin(-1000,-1000,-1000);
151 btVector3 worldMax(1000,1000,1000);
152 m_overlappingPairCache = new btAxisSweep3(worldMin,worldMax);
154 #if SLIDER_DEMO_USE_ODE_SOLVER
155 m_constraintSolver = new btOdeQuickstepConstraintSolver();
157 m_constraintSolver = new btSequentialImpulseConstraintSolver();
160 btDiscreteDynamicsWorld* wp = new btDiscreteDynamicsWorld(m_dispatcher,m_overlappingPairCache,m_constraintSolver,m_collisionConfiguration);
161 // wp->getSolverInfo().m_numIterations = 20; // default is 10
162 m_dynamicsWorld = wp;
163 // wp->getSolverInfo().m_erp = 0.8;
166 //btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),50);
167 btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(50.),btScalar(50.),btScalar(50.)));
168 m_collisionShapes.push_back(groundShape);
169 btTransform groundTransform;
170 groundTransform.setIdentity();
171 groundTransform.setOrigin(btVector3(0,-76,0));
172 btRigidBody* groundBody;
173 groundBody = localCreateRigidBody(0, groundTransform, groundShape);
175 // add box shape (will be reused for all bodies)
176 btCollisionShape* shape = new btBoxShape(btVector3(CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS));
177 m_collisionShapes.push_back(shape);
178 // mass of dymamic bodies
179 btScalar mass = btScalar(1.);
181 // add dynamic rigid body A1
184 btVector3 worldPos(-20,0,0);
185 trans.setOrigin(worldPos);
186 btTransform frameInA, frameInB;
187 frameInA = btTransform::getIdentity();
188 frameInB = btTransform::getIdentity();
190 #if SLIDER_ENABLE_ALL_DEMOS
191 btRigidBody* pRbA1 = localCreateRigidBody(mass, trans, shape);
192 // btRigidBody* pRbA1 = localCreateRigidBody(0.f, trans, shape);
193 pRbA1->setActivationState(DISABLE_DEACTIVATION);
195 // add dynamic rigid body B1
196 worldPos.setValue(-30,0,0);
197 trans.setOrigin(worldPos);
198 btRigidBody* pRbB1 = localCreateRigidBody(mass, trans, shape);
199 // btRigidBody* pRbB1 = localCreateRigidBody(0.f, trans, shape);
200 pRbB1->setActivationState(DISABLE_DEACTIVATION);
202 // create slider constraint between A1 and B1 and add it to world
204 #if SLIDER_DEMO_USE_6DOF
205 spSlider1 = new btGeneric6DofConstraint(*pRbA1, *pRbB1, frameInA, frameInB, true);
206 btVector3 lowerSliderLimit = btVector3(-20,0,0);
207 btVector3 hiSliderLimit = btVector3(-10,0,0);
208 // btVector3 lowerSliderLimit = btVector3(-20,-5,-5);
209 // btVector3 hiSliderLimit = btVector3(-10,5,5);
210 spSlider1->setLinearLowerLimit(lowerSliderLimit);
211 spSlider1->setLinearUpperLimit(hiSliderLimit);
212 spSlider1->setAngularLowerLimit(btVector3(0,0,0));
213 spSlider1->setAngularUpperLimit(btVector3(0,0,0));
215 spSlider1 = new btSliderConstraint(*pRbA1, *pRbB1, frameInA, frameInB, true);
216 // spSlider1 = new btSliderConstraint(*pRbA1, *pRbB1, frameInA, frameInB, false);
217 spSlider1->setLowerLinLimit(-15.0F);
218 spSlider1->setUpperLinLimit(-5.0F);
219 // spSlider1->setLowerLinLimit(5.0F);
220 // spSlider1->setUpperLinLimit(15.0F);
221 // spSlider1->setLowerLinLimit(-10.0F);
222 // spSlider1->setUpperLinLimit(-10.0F);
224 spSlider1->setLowerAngLimit(-SIMD_PI / 3.0F);
225 spSlider1->setUpperAngLimit( SIMD_PI / 3.0F);
228 m_dynamicsWorld->addConstraint(spSlider1, true);
229 spSlider1->setDbgDrawSize(btScalar(5.f));
232 #if SLIDER_ENABLE_ALL_DEMOS
233 // add kinematic rigid body A2
234 // worldPos.setValue(20,4,0);
235 worldPos.setValue(5,-20,0);
236 trans.setOrigin(worldPos);
237 btRigidBody* pRbA2 = localCreateRigidBody(0., trans, shape);
238 // btRigidBody* pRbA2 = localCreateRigidBody(mass, trans, shape);
239 // btRigidBody* pRbA2 = localCreateRigidBody(mass * 10000, trans, shape);
240 pRbA2->setActivationState(DISABLE_DEACTIVATION);
242 // add dynamic rigid body B2
243 // worldPos.setValue(-20,4,0);
244 worldPos.setValue(-5,-20,0);
245 trans.setOrigin(worldPos);
246 // btRigidBody* pRbB2 = localCreateRigidBody(0., trans, shape);
247 btRigidBody* pRbB2 = localCreateRigidBody(mass, trans, shape);
248 // btRigidBody* pRbB2 = localCreateRigidBody(mass * 10000, trans, shape);
249 pRbB2->setActivationState(DISABLE_DEACTIVATION);
251 // frameInA.getBasis().setEulerZYX(1.f, 1.f, 1.f);
252 // frameInB.getBasis().setEulerZYX(1.f, 1.f, 1.f);
253 // frameInA.getBasis().setEulerZYX(1.f, 1.f, 1.f);
254 // frameInB.getBasis().setEulerZYX(1.f, 1.f, 1.f);
257 // frameInA.setOrigin(btVector3(-20., 5., 0));
258 // frameInB.setOrigin(btVector3( 20., 5., 0));
259 frameInA.setOrigin(btVector3(-5., 20., 0));
260 frameInB.setOrigin(btVector3( 5., 20., 0));
263 // create slider constraint between A2 and B2 and add it to world
264 #if SLIDER_DEMO_USE_6DOF
265 spSlider2 = new btGeneric6DofConstraint(*pRbA2, *pRbB2, frameInA, frameInB, true);
266 spSlider2->setLinearLowerLimit(lowerSliderLimit);
267 spSlider2->setLinearUpperLimit(hiSliderLimit);
268 spSlider2->setAngularLowerLimit(btVector3(0,0,0));
269 spSlider2->setAngularUpperLimit(btVector3(0,0,0));
271 spSlider2 = new btSliderConstraint(*pRbA2, *pRbB2, frameInA, frameInB, true);
272 // spSlider2 = new btSliderConstraint(*pRbA2, *pRbB2, frameInA, frameInB, false);
273 // spSlider2->setLowerLinLimit(0.0F);
274 // spSlider2->setUpperLinLimit(0.0F);
275 spSlider2->setLowerLinLimit(-2.0F);
276 spSlider2->setUpperLinLimit(2.0F);
277 // spSlider2->setLowerLinLimit(5.0F);
278 // spSlider2->setUpperLinLimit(25.0F);
279 // spSlider2->setUpperLinLimit(-5.0F);
280 // spSlider2->setUpperLinLimit(-9.99F);
283 // spSlider2->setLowerAngLimit(SIMD_PI / 2.0F);
284 // spSlider2->setUpperAngLimit(-SIMD_PI / 2.0F);
286 // spSlider2->setLowerAngLimit(-SIMD_PI / 2.0F);
287 // spSlider2->setUpperAngLimit(SIMD_PI / 2.0F);
289 // spSlider2->setLowerAngLimit(-SIMD_PI);
290 // spSlider2->setUpperAngLimit(SIMD_PI *0.8F);
293 // spSlider2->setLowerAngLimit(-0.01F);
294 // spSlider2->setUpperAngLimit(0.01F);
295 spSlider2->setLowerAngLimit(-1.570796326F * 0.5f);
296 spSlider2->setUpperAngLimit(1.570796326F * 0.5f);
297 // spSlider2->setLowerAngLimit(1.F);
298 // spSlider2->setUpperAngLimit(-1.F);
301 // spSlider2->setDampingLimLin(0.5f);
305 spSlider2->setPoweredLinMotor(true);
306 spSlider2->setMaxLinMotorForce(0.1);
307 spSlider2->setTargetLinMotorVelocity(-5.0);
309 spSlider2->setPoweredAngMotor(true);
310 // spSlider2->setMaxAngMotorForce(0.01);
311 spSlider2->setMaxAngMotorForce(10.0);
312 spSlider2->setTargetAngMotorVelocity(1.0);
314 // change default damping and restitution
316 spSlider2->setDampingDirLin(0.005F);
317 spSlider2->setRestitutionLimLin(1.1F);
321 // spSlider2->setDampingLimLin(0.1F); // linear bounce factor for ODE == 1.0 - DampingLimLin;
322 // spSlider2->setDampingLimAng(0.1F); // angular bounce factor for ODE == 1.0 - DampingLimAng;
323 // spSlider2->setSoftnessOrthoAng(0.1);
324 // spSlider2->setSoftnessOrthoLin(0.1);
325 // spSlider2->setSoftnessLimLin(0.1);
326 // spSlider2->setSoftnessLimAng(0.1);
328 m_dynamicsWorld->addConstraint(spSlider2, true);
329 spSlider2->setDbgDrawSize(btScalar(5.f));
332 #if SLIDER_ENABLE_ALL_DEMOS
334 // add dynamic rigid body A1
336 worldPos.setValue(20,0,0);
337 trans.setOrigin(worldPos);
338 btRigidBody* pRbA3 = localCreateRigidBody(0.0F, trans, shape);
339 pRbA3->setActivationState(DISABLE_DEACTIVATION);
341 // add dynamic rigid body B1
342 worldPos.setValue(25,0,0);
343 trans.setOrigin(worldPos);
344 btRigidBody* pRbB3 = localCreateRigidBody(mass, trans, shape);
345 pRbB3->setActivationState(DISABLE_DEACTIVATION);
347 btVector3 pivA( 2.5, 0., 0.);
348 btVector3 pivB(-2.5, 0., 0.);
349 spP2PConst = new btPoint2PointConstraint(*pRbA3, *pRbB3, pivA, pivB);
350 m_dynamicsWorld->addConstraint(spP2PConst, true);
351 spP2PConst->setDbgDrawSize(btScalar(5.f));
356 #if 0 // SLIDER_ENABLE_ALL_DEMOS
357 // add dynamic rigid body A4
359 worldPos.setValue(20,10,0);
360 trans.setOrigin(worldPos);
361 btRigidBody* pRbA4 = localCreateRigidBody(0.0F, trans, shape);
362 pRbA4->setActivationState(DISABLE_DEACTIVATION);
364 // add dynamic rigid body B1
365 worldPos.setValue(27,10,0);
366 trans.setOrigin(worldPos);
367 btRigidBody* pRbB4 = localCreateRigidBody(mass, trans, shape);
368 pRbB1->setActivationState(DISABLE_DEACTIVATION);
371 btVector3 pivA( 2., 0., 0.);
372 btVector3 pivB(-5., 0., 0.);
373 btVector3 axisA(0., 0., 1.);
374 btVector3 axisB(0., 0., 1.);
376 spHingeConst = new btHingeConstraint(*pRbA4, *pRbB4, pivA, pivB, axisA, axisB);
377 // spHingeConst->setLimit(-1.57, 1.57);
378 spHingeConst->setLimit(1.57, -1.57);
379 spHingeConst->enableAngularMotor(true, 10.0, 0.19);
381 m_dynamicsWorld->addConstraint(spHingeConst, true);
382 spHingeConst->setDbgDrawSize(btScalar(5.f));
386 } // SliderConstraintDemo::initPhysics()
390 SliderConstraintDemo::~SliderConstraintDemo()
392 //cleanup in the reverse order of creation/initialization
394 //removed/delete constraints
395 for (i=m_dynamicsWorld->getNumConstraints()-1; i>=0 ;i--)
397 btTypedConstraint* constraint = m_dynamicsWorld->getConstraint(i);
398 m_dynamicsWorld->removeConstraint(constraint);
401 //remove the rigidbodies from the dynamics world and delete them
402 for (i=m_dynamicsWorld->getNumCollisionObjects()-1; i>=0 ;i--)
404 btCollisionObject* obj = m_dynamicsWorld->getCollisionObjectArray()[i];
405 btRigidBody* body = btRigidBody::upcast(obj);
406 if (body && body->getMotionState())
408 delete body->getMotionState();
410 m_dynamicsWorld->removeCollisionObject( obj );
413 //delete collision shapes
414 for (int j=0;j<m_collisionShapes.size();j++)
416 btCollisionShape* shape = m_collisionShapes[j];
419 //delete dynamics world
420 delete m_dynamicsWorld;
422 delete m_constraintSolver;
424 delete m_overlappingPairCache;
427 delete m_collisionConfiguration;
428 } // SliderConstraintDemo::~SliderConstraintDemo()
432 void SliderConstraintDemo::clientMoveAndDisplay()
434 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
435 float dt = float(getDeltaTimeMicroseconds()) * 0.000001f;
436 //during idle mode, just run 1 simulation step maximum
437 int maxSimSubSteps = m_idle ? 1 : 1;
442 int numSimSteps = m_dynamicsWorld->stepSimulation(dt,maxSimSubSteps);
443 //optional but useful: debug drawing
444 m_dynamicsWorld->debugDrawWorld();
445 bool verbose = false;
449 printf("Interpolated transforms\n");
452 if (numSimSteps > maxSimSubSteps)
454 //detect dropping frames
455 printf("Dropped (%i) simulation steps out of %i\n",numSimSteps - maxSimSubSteps,numSimSteps);
458 printf("Simulated (%i) steps\n",numSimSteps);
463 // drawSlider(spSlider1);
464 // drawSlider(spSlider2);
467 } // SliderConstraintDemo::clientMoveAndDisplay()
471 void SliderConstraintDemo::displayCallback(void)
473 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
476 m_dynamicsWorld->debugDrawWorld();
478 // drawSlider(spSlider1);
479 // drawSlider(spSlider2);
483 } // SliderConstraintDemo::displayCallback()
486 void SliderConstraintDemo::keyboardCallback(unsigned char key, int x, int y)
495 offectOnOff = spSlider1->getUseFrameOffset();
496 offectOnOff = !offectOnOff;
497 spSlider1->setUseFrameOffset(offectOnOff);
498 printf("Slider1 %s frame offset\n", offectOnOff ? "uses" : "does not use");
499 offectOnOff = spSlider2->getUseFrameOffset();
500 offectOnOff = !offectOnOff;
501 spSlider2->setUseFrameOffset(offectOnOff);
502 printf("Slider2 %s frame offset\n", offectOnOff ? "uses" : "does not use");
507 DemoApplication::keyboardCallback(key, x, y);