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.
16 ///September 2006: VehicleDemo is work in progress, this file is mostly just a placeholder
17 ///This VehicleDemo file is very early in development, please check it later
18 ///@todo is a basic engine model:
19 ///A function that maps user input (throttle) into torque/force applied on the wheels
21 #include "btBulletDynamicsCommon.h"
22 #include "BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h"
23 #include "GLDebugFont.h"
26 #define M_PI 3.14159265358979323846
30 #define M_PI_2 1.57079632679489661923
34 #define M_PI_4 0.785398163397448309616
37 //#define LIFT_EPS 0.0000001f
39 // By default, Bullet Vehicle uses Y as up axis.
40 // You can override the up axis, for example Z-axis up. Enable this define to see how to:
41 //#define FORCE_ZAXIS_UP 1
48 btVector3 wheelDirectionCS0(0,0,-1);
49 btVector3 wheelAxleCS(1,0,0);
54 btVector3 wheelDirectionCS0(0,-1,0);
55 btVector3 wheelAxleCS(-1,0,0);
58 #include "GLDebugDrawer.h"
59 #include <stdio.h> //printf debugging
61 #include "GL_ShapeDrawer.h"
63 #include "GlutStuff.h"
64 #include "ForkLiftDemo.h"
67 const int maxProxies = 32766;
68 const int maxOverlap = 65535;
70 ///btRaycastVehicle is the interface for the constraint that implements the raycast vehicle
71 ///notice that for higher-quality slow-moving vehicles, another approach might be better
72 ///implementing explicit hinged-wheel constraints with cylinder collision, rather then raycasts
73 float gEngineForce = 0.f;
75 float defaultBreakingForce = 10.f;
76 float gBreakingForce = 100.f;
78 float maxEngineForce = 1000.f;//this should be engine/velocity dependent
79 float maxBreakingForce = 100.f;
81 float gVehicleSteering = 0.f;
82 float steeringIncrement = 0.04f;
83 float steeringClamp = 0.3f;
84 float wheelRadius = 0.5f;
85 float wheelWidth = 0.4f;
86 float wheelFriction = 1000;//BT_LARGE_FLOAT;
87 float suspensionStiffness = 20.f;
88 float suspensionDamping = 2.3f;
89 float suspensionCompression = 4.4f;
90 float rollInfluence = 0.1f;//1.0f;
93 btScalar suspensionRestLength(0.6);
95 #define CUBE_HALF_EXTENTS 1
99 ////////////////////////////////////
104 ForkLiftDemo::ForkLiftDemo()
110 m_indexVertexArrays(0),
113 m_minCameraDistance(3.f),
114 m_maxCameraDistance(10.f)
118 m_cameraPosition = btVector3(30,30,30);
119 m_useDefaultCamera = false;
126 void ForkLiftDemo::termPhysics()
128 //cleanup in the reverse order of creation/initialization
130 //remove the rigidbodies from the dynamics world and delete them
132 for (i=m_dynamicsWorld->getNumCollisionObjects()-1; i>=0 ;i--)
134 btCollisionObject* obj = m_dynamicsWorld->getCollisionObjectArray()[i];
135 btRigidBody* body = btRigidBody::upcast(obj);
136 if (body && body->getMotionState())
139 while (body->getNumConstraintRefs())
141 btTypedConstraint* constraint = body->getConstraintRef(0);
142 m_dynamicsWorld->removeConstraint(constraint);
145 delete body->getMotionState();
146 m_dynamicsWorld->removeRigidBody(body);
149 m_dynamicsWorld->removeCollisionObject( obj );
154 //delete collision shapes
155 for (int j=0;j<m_collisionShapes.size();j++)
157 btCollisionShape* shape = m_collisionShapes[j];
161 delete m_indexVertexArrays;
164 //delete dynamics world
165 delete m_dynamicsWorld;
167 delete m_vehicleRayCaster;
174 delete m_constraintSolver;
177 delete m_overlappingPairCache;
182 delete m_collisionConfiguration;
186 ForkLiftDemo::~ForkLiftDemo()
191 void ForkLiftDemo::initPhysics()
194 #ifdef FORCE_ZAXIS_UP
195 m_cameraUp = btVector3(0,0,1);
199 btCollisionShape* groundShape = new btBoxShape(btVector3(50,3,50));
200 m_collisionShapes.push_back(groundShape);
201 m_collisionConfiguration = new btDefaultCollisionConfiguration();
202 m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration);
203 btVector3 worldMin(-1000,-1000,-1000);
204 btVector3 worldMax(1000,1000,1000);
205 m_overlappingPairCache = new btAxisSweep3(worldMin,worldMax);
206 m_constraintSolver = new btSequentialImpulseConstraintSolver();
207 m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_overlappingPairCache,m_constraintSolver,m_collisionConfiguration);
208 #ifdef FORCE_ZAXIS_UP
209 m_dynamicsWorld->setGravity(btVector3(0,0,-10));
212 //m_dynamicsWorld->setGravity(btVector3(0,0,0));
215 tr.setOrigin(btVector3(0,-10,0));
217 //either use heightfield or triangle mesh
220 //create ground object
221 localCreateRigidBody(0,tr,groundShape);
223 #ifdef FORCE_ZAXIS_UP
224 // indexRightAxis = 0;
226 // indexForwardAxis = 1;
227 btCollisionShape* chassisShape = new btBoxShape(btVector3(1.f,2.f, 0.5f));
228 btCompoundShape* compound = new btCompoundShape();
229 btTransform localTrans;
230 localTrans.setIdentity();
231 //localTrans effectively shifts the center of mass with respect to the chassis
232 localTrans.setOrigin(btVector3(0,0,1));
234 btCollisionShape* chassisShape = new btBoxShape(btVector3(1.f,0.5f,2.f));
235 m_collisionShapes.push_back(chassisShape);
237 btCompoundShape* compound = new btCompoundShape();
238 m_collisionShapes.push_back(compound);
239 btTransform localTrans;
240 localTrans.setIdentity();
241 //localTrans effectively shifts the center of mass with respect to the chassis
242 localTrans.setOrigin(btVector3(0,1,0));
245 compound->addChildShape(localTrans,chassisShape);
248 btCollisionShape* suppShape = new btBoxShape(btVector3(0.5f,0.1f,0.5f));
249 btTransform suppLocalTrans;
250 suppLocalTrans.setIdentity();
251 //localTrans effectively shifts the center of mass with respect to the chassis
252 suppLocalTrans.setOrigin(btVector3(0,1.0,2.5));
253 compound->addChildShape(suppLocalTrans, suppShape);
256 tr.setOrigin(btVector3(0,0.f,0));
258 m_carChassis = localCreateRigidBody(800,tr,compound);//chassisShape);
259 //m_carChassis->setDamping(0.2,0.2);
261 m_wheelShape = new btCylinderShapeX(btVector3(wheelWidth,wheelRadius,wheelRadius));
264 btCollisionShape* liftShape = new btBoxShape(btVector3(0.5f,2.0f,0.05f));
265 m_collisionShapes.push_back(liftShape);
266 btTransform liftTrans;
267 m_liftStartPos = btVector3(0.0f, 2.5f, 3.05f);
268 liftTrans.setIdentity();
269 liftTrans.setOrigin(m_liftStartPos);
270 m_liftBody = localCreateRigidBody(10,liftTrans, liftShape);
272 btTransform localA, localB;
273 localA.setIdentity();
274 localB.setIdentity();
275 localA.getBasis().setEulerZYX(0, M_PI_2, 0);
276 localA.setOrigin(btVector3(0.0, 1.0, 3.05));
277 localB.getBasis().setEulerZYX(0, M_PI_2, 0);
278 localB.setOrigin(btVector3(0.0, -1.5, -0.05));
279 m_liftHinge = new btHingeConstraint(*m_carChassis,*m_liftBody, localA, localB);
280 // m_liftHinge->setLimit(-LIFT_EPS, LIFT_EPS);
281 m_liftHinge->setLimit(0.0f, 0.0f);
282 m_dynamicsWorld->addConstraint(m_liftHinge, true);
284 btCollisionShape* forkShapeA = new btBoxShape(btVector3(1.0f,0.1f,0.1f));
285 m_collisionShapes.push_back(forkShapeA);
286 btCompoundShape* forkCompound = new btCompoundShape();
287 m_collisionShapes.push_back(forkCompound);
288 btTransform forkLocalTrans;
289 forkLocalTrans.setIdentity();
290 forkCompound->addChildShape(forkLocalTrans, forkShapeA);
292 btCollisionShape* forkShapeB = new btBoxShape(btVector3(0.1f,0.02f,0.6f));
293 m_collisionShapes.push_back(forkShapeB);
294 forkLocalTrans.setIdentity();
295 forkLocalTrans.setOrigin(btVector3(-0.9f, -0.08f, 0.7f));
296 forkCompound->addChildShape(forkLocalTrans, forkShapeB);
298 btCollisionShape* forkShapeC = new btBoxShape(btVector3(0.1f,0.02f,0.6f));
299 m_collisionShapes.push_back(forkShapeC);
300 forkLocalTrans.setIdentity();
301 forkLocalTrans.setOrigin(btVector3(0.9f, -0.08f, 0.7f));
302 forkCompound->addChildShape(forkLocalTrans, forkShapeC);
304 btTransform forkTrans;
305 m_forkStartPos = btVector3(0.0f, 0.6f, 3.2f);
306 forkTrans.setIdentity();
307 forkTrans.setOrigin(m_forkStartPos);
308 m_forkBody = localCreateRigidBody(5, forkTrans, forkCompound);
310 localA.setIdentity();
311 localB.setIdentity();
312 localA.getBasis().setEulerZYX(0, 0, M_PI_2);
313 localA.setOrigin(btVector3(0.0f, -1.9f, 0.05f));
314 localB.getBasis().setEulerZYX(0, 0, M_PI_2);
315 localB.setOrigin(btVector3(0.0, 0.0, -0.1));
316 m_forkSlider = new btSliderConstraint(*m_liftBody, *m_forkBody, localA, localB, true);
317 m_forkSlider->setLowerLinLimit(0.1f);
318 m_forkSlider->setUpperLinLimit(0.1f);
319 // m_forkSlider->setLowerAngLimit(-LIFT_EPS);
320 // m_forkSlider->setUpperAngLimit(LIFT_EPS);
321 m_forkSlider->setLowerAngLimit(0.0f);
322 m_forkSlider->setUpperAngLimit(0.0f);
323 m_dynamicsWorld->addConstraint(m_forkSlider, true);
326 btCompoundShape* loadCompound = new btCompoundShape();
327 m_collisionShapes.push_back(loadCompound);
328 btCollisionShape* loadShapeA = new btBoxShape(btVector3(2.0f,0.5f,0.5f));
329 m_collisionShapes.push_back(loadShapeA);
330 btTransform loadTrans;
331 loadTrans.setIdentity();
332 loadCompound->addChildShape(loadTrans, loadShapeA);
333 btCollisionShape* loadShapeB = new btBoxShape(btVector3(0.1f,1.0f,1.0f));
334 m_collisionShapes.push_back(loadShapeB);
335 loadTrans.setIdentity();
336 loadTrans.setOrigin(btVector3(2.1f, 0.0f, 0.0f));
337 loadCompound->addChildShape(loadTrans, loadShapeB);
338 btCollisionShape* loadShapeC = new btBoxShape(btVector3(0.1f,1.0f,1.0f));
339 m_collisionShapes.push_back(loadShapeC);
340 loadTrans.setIdentity();
341 loadTrans.setOrigin(btVector3(-2.1f, 0.0f, 0.0f));
342 loadCompound->addChildShape(loadTrans, loadShapeC);
343 loadTrans.setIdentity();
344 m_loadStartPos = btVector3(0.0f, -3.5f, 7.0f);
345 loadTrans.setOrigin(m_loadStartPos);
346 m_loadBody = localCreateRigidBody(4, loadTrans, loadCompound);
356 m_vehicleRayCaster = new btDefaultVehicleRaycaster(m_dynamicsWorld);
357 m_vehicle = new btRaycastVehicle(m_tuning,m_carChassis,m_vehicleRayCaster);
359 ///never deactivate the vehicle
360 m_carChassis->setActivationState(DISABLE_DEACTIVATION);
362 m_dynamicsWorld->addVehicle(m_vehicle);
364 float connectionHeight = 1.2f;
367 bool isFrontWheel=true;
369 //choose coordinate system
370 m_vehicle->setCoordinateSystem(rightIndex,upIndex,forwardIndex);
372 #ifdef FORCE_ZAXIS_UP
373 btVector3 connectionPointCS0(CUBE_HALF_EXTENTS-(0.3*wheelWidth),2*CUBE_HALF_EXTENTS-wheelRadius, connectionHeight);
375 btVector3 connectionPointCS0(CUBE_HALF_EXTENTS-(0.3*wheelWidth),connectionHeight,2*CUBE_HALF_EXTENTS-wheelRadius);
378 m_vehicle->addWheel(connectionPointCS0,wheelDirectionCS0,wheelAxleCS,suspensionRestLength,wheelRadius,m_tuning,isFrontWheel);
379 #ifdef FORCE_ZAXIS_UP
380 connectionPointCS0 = btVector3(-CUBE_HALF_EXTENTS+(0.3*wheelWidth),2*CUBE_HALF_EXTENTS-wheelRadius, connectionHeight);
382 connectionPointCS0 = btVector3(-CUBE_HALF_EXTENTS+(0.3*wheelWidth),connectionHeight,2*CUBE_HALF_EXTENTS-wheelRadius);
385 m_vehicle->addWheel(connectionPointCS0,wheelDirectionCS0,wheelAxleCS,suspensionRestLength,wheelRadius,m_tuning,isFrontWheel);
386 #ifdef FORCE_ZAXIS_UP
387 connectionPointCS0 = btVector3(-CUBE_HALF_EXTENTS+(0.3*wheelWidth),-2*CUBE_HALF_EXTENTS+wheelRadius, connectionHeight);
389 connectionPointCS0 = btVector3(-CUBE_HALF_EXTENTS+(0.3*wheelWidth),connectionHeight,-2*CUBE_HALF_EXTENTS+wheelRadius);
390 #endif //FORCE_ZAXIS_UP
391 isFrontWheel = false;
392 m_vehicle->addWheel(connectionPointCS0,wheelDirectionCS0,wheelAxleCS,suspensionRestLength,wheelRadius,m_tuning,isFrontWheel);
393 #ifdef FORCE_ZAXIS_UP
394 connectionPointCS0 = btVector3(CUBE_HALF_EXTENTS-(0.3*wheelWidth),-2*CUBE_HALF_EXTENTS+wheelRadius, connectionHeight);
396 connectionPointCS0 = btVector3(CUBE_HALF_EXTENTS-(0.3*wheelWidth),connectionHeight,-2*CUBE_HALF_EXTENTS+wheelRadius);
398 m_vehicle->addWheel(connectionPointCS0,wheelDirectionCS0,wheelAxleCS,suspensionRestLength,wheelRadius,m_tuning,isFrontWheel);
400 for (int i=0;i<m_vehicle->getNumWheels();i++)
402 btWheelInfo& wheel = m_vehicle->getWheelInfo(i);
403 wheel.m_suspensionStiffness = suspensionStiffness;
404 wheel.m_wheelsDampingRelaxation = suspensionDamping;
405 wheel.m_wheelsDampingCompression = suspensionCompression;
406 wheel.m_frictionSlip = wheelFriction;
407 wheel.m_rollInfluence = rollInfluence;
412 setCameraDistance(26.f);
417 //to be implemented by the demo
418 void ForkLiftDemo::renderme()
423 ATTRIBUTE_ALIGNED16(btScalar) m[16];
426 btVector3 wheelColor(1,0,0);
428 btVector3 worldBoundsMin,worldBoundsMax;
429 getDynamicsWorld()->getBroadphase()->getBroadphaseAabb(worldBoundsMin,worldBoundsMax);
433 for (i=0;i<m_vehicle->getNumWheels();i++)
435 //synchronize the wheels with the (interpolated) chassis worldtransform
436 m_vehicle->updateWheelTransform(i,true);
437 //draw wheels (cylinders)
438 m_vehicle->getWheelInfo(i).m_worldTransform.getOpenGLMatrix(m);
439 m_shapeDrawer->drawOpenGL(m,m_wheelShape,wheelColor,getDebugMode(),worldBoundsMin,worldBoundsMax);
444 int xStart = m_glutScreenWidth - lineWidth;
447 if((getDebugMode() & btIDebugDraw::DBG_NoHelpText)==0)
449 setOrthographicProjection();
450 glDisable(GL_LIGHTING);
454 glRasterPos3f(xStart, yStart, 0);
455 sprintf(buf,"SHIFT+Cursor Left/Right - rotate lift");
456 GLDebugDrawString(xStart,20,buf);
458 glRasterPos3f(xStart, yStart, 0);
459 sprintf(buf,"SHIFT+Cursor UP/Down - move fork up/down");
461 GLDebugDrawString(xStart,yStart,buf);
462 glRasterPos3f(xStart, yStart, 0);
463 sprintf(buf,"F5 - toggle camera mode");
465 GLDebugDrawString(xStart,yStart,buf);
466 glRasterPos3f(xStart, yStart, 0);
467 sprintf(buf,"Click inside this window for keyboard focus");
469 GLDebugDrawString(xStart,yStart,buf);
472 resetPerspectiveProjection();
473 glEnable(GL_LIGHTING);
475 DemoApplication::renderme();
478 void ForkLiftDemo::clientMoveAndDisplay()
481 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
486 m_vehicle->applyEngineForce(gEngineForce,wheelIndex);
487 m_vehicle->setBrake(gBreakingForce,wheelIndex);
489 m_vehicle->applyEngineForce(gEngineForce,wheelIndex);
490 m_vehicle->setBrake(gBreakingForce,wheelIndex);
494 m_vehicle->setSteeringValue(gVehicleSteering,wheelIndex);
496 m_vehicle->setSteeringValue(gVehicleSteering,wheelIndex);
501 float dt = getDeltaTimeMicroseconds() * 0.000001f;
505 //during idle mode, just run 1 simulation step maximum
506 int maxSimSubSteps = m_idle ? 1 : 2;
511 numSimSteps = m_dynamicsWorld->stepSimulation(dt,maxSimSubSteps);
514 //#define VERBOSE_FEEDBACK
515 #ifdef VERBOSE_FEEDBACK
517 printf("Interpolated transforms\n");
520 if (numSimSteps > maxSimSubSteps)
522 //detect dropping frames
523 printf("Dropped (%i) simulation steps out of %i\n",numSimSteps - maxSimSubSteps,numSimSteps);
526 printf("Simulated (%i) steps\n",numSimSteps);
529 #endif //VERBOSE_FEEDBACK
540 btProfiler::beginBlock("render");
541 #endif //USE_QUICKPROF
546 //optional but useful: debug drawing
548 m_dynamicsWorld->debugDrawWorld();
551 btProfiler::endBlock("render");
562 void ForkLiftDemo::displayCallback(void)
564 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
568 //optional but useful: debug drawing
570 m_dynamicsWorld->debugDrawWorld();
578 void ForkLiftDemo::clientResetScene()
580 gVehicleSteering = 0.f;
581 gBreakingForce = defaultBreakingForce;
584 m_carChassis->setCenterOfMassTransform(btTransform::getIdentity());
585 m_carChassis->setLinearVelocity(btVector3(0,0,0));
586 m_carChassis->setAngularVelocity(btVector3(0,0,0));
587 m_dynamicsWorld->getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(m_carChassis->getBroadphaseHandle(),getDynamicsWorld()->getDispatcher());
590 m_vehicle->resetSuspension();
591 for (int i=0;i<m_vehicle->getNumWheels();i++)
593 //synchronize the wheels with the (interpolated) chassis worldtransform
594 m_vehicle->updateWheelTransform(i,true);
597 btTransform liftTrans;
598 liftTrans.setIdentity();
599 liftTrans.setOrigin(m_liftStartPos);
600 m_liftBody->activate();
601 m_liftBody->setCenterOfMassTransform(liftTrans);
602 m_liftBody->setLinearVelocity(btVector3(0,0,0));
603 m_liftBody->setAngularVelocity(btVector3(0,0,0));
605 btTransform forkTrans;
606 forkTrans.setIdentity();
607 forkTrans.setOrigin(m_forkStartPos);
608 m_forkBody->activate();
609 m_forkBody->setCenterOfMassTransform(forkTrans);
610 m_forkBody->setLinearVelocity(btVector3(0,0,0));
611 m_forkBody->setAngularVelocity(btVector3(0,0,0));
613 // m_liftHinge->setLimit(-LIFT_EPS, LIFT_EPS);
614 m_liftHinge->setLimit(0.0f, 0.0f);
615 m_liftHinge->enableAngularMotor(false, 0, 0);
618 m_forkSlider->setLowerLinLimit(0.1f);
619 m_forkSlider->setUpperLinLimit(0.1f);
620 m_forkSlider->setPoweredLinMotor(false);
622 btTransform loadTrans;
623 loadTrans.setIdentity();
624 loadTrans.setOrigin(m_loadStartPos);
625 m_loadBody->activate();
626 m_loadBody->setCenterOfMassTransform(loadTrans);
627 m_loadBody->setLinearVelocity(btVector3(0,0,0));
628 m_loadBody->setAngularVelocity(btVector3(0,0,0));
634 void ForkLiftDemo::specialKeyboardUp(int key, int x, int y)
642 gBreakingForce = defaultBreakingForce;
649 gBreakingForce = defaultBreakingForce;
659 DemoApplication::specialKeyboardUp(key,x,y);
665 void ForkLiftDemo::specialKeyboard(int key, int x, int y)
668 if (key==GLUT_KEY_END)
671 // printf("key = %i x=%i y=%i\n",key,x,y);
674 state=glutGetModifiers();
675 if (state & GLUT_ACTIVE_SHIFT)
682 m_liftHinge->setLimit(-M_PI/16.0f, M_PI/8.0f);
683 m_liftHinge->enableAngularMotor(true, -0.1, 10.0);
686 case GLUT_KEY_RIGHT :
689 m_liftHinge->setLimit(-M_PI/16.0f, M_PI/8.0f);
690 m_liftHinge->enableAngularMotor(true, 0.1, 10.0);
695 m_forkSlider->setLowerLinLimit(0.1f);
696 m_forkSlider->setUpperLinLimit(3.9f);
697 m_forkSlider->setPoweredLinMotor(true);
698 m_forkSlider->setMaxLinMotorForce(10.0);
699 m_forkSlider->setTargetLinMotorVelocity(1.0);
704 m_forkSlider->setLowerLinLimit(0.1f);
705 m_forkSlider->setUpperLinLimit(3.9f);
706 m_forkSlider->setPoweredLinMotor(true);
707 m_forkSlider->setMaxLinMotorForce(10.0);
708 m_forkSlider->setTargetLinMotorVelocity(-1.0);
713 DemoApplication::specialKeyboard(key,x,y);
723 gVehicleSteering += steeringIncrement;
724 if ( gVehicleSteering > steeringClamp)
725 gVehicleSteering = steeringClamp;
729 case GLUT_KEY_RIGHT :
731 gVehicleSteering -= steeringIncrement;
732 if ( gVehicleSteering < -steeringClamp)
733 gVehicleSteering = -steeringClamp;
739 gEngineForce = maxEngineForce;
740 gBreakingForce = 0.f;
745 gEngineForce = -maxEngineForce;
746 gBreakingForce = 0.f;
751 m_useDefaultCamera = !m_useDefaultCamera;
754 DemoApplication::specialKeyboard(key,x,y);
759 // glutPostRedisplay();
764 void ForkLiftDemo::updateCamera()
767 //#define DISABLE_CAMERA 1
768 if(m_useDefaultCamera)
770 DemoApplication::updateCamera();
774 glMatrixMode(GL_PROJECTION);
777 btTransform chassisWorldTrans;
779 //look at the vehicle
780 m_carChassis->getMotionState()->getWorldTransform(chassisWorldTrans);
781 m_cameraTargetPosition = chassisWorldTrans.getOrigin();
783 //interpolate the camera height
784 #ifdef FORCE_ZAXIS_UP
785 m_cameraPosition[2] = (15.0*m_cameraPosition[2] + m_cameraTargetPosition[2] + m_cameraHeight)/16.0;
787 m_cameraPosition[1] = (15.0*m_cameraPosition[1] + m_cameraTargetPosition[1] + m_cameraHeight)/16.0;
790 btVector3 camToObject = m_cameraTargetPosition - m_cameraPosition;
792 //keep distance between min and max distance
793 float cameraDistance = camToObject.length();
794 float correctionFactor = 0.f;
795 if (cameraDistance < m_minCameraDistance)
797 correctionFactor = 0.15*(m_minCameraDistance-cameraDistance)/cameraDistance;
799 if (cameraDistance > m_maxCameraDistance)
801 correctionFactor = 0.15*(m_maxCameraDistance-cameraDistance)/cameraDistance;
803 m_cameraPosition -= correctionFactor*camToObject;
805 //update OpenGL camera settings
806 btScalar aspect = m_glutScreenWidth / (btScalar)m_glutScreenHeight;
807 glFrustum (-aspect, aspect, -1.0, 1.0, 1.0, 10000.0);
809 glMatrixMode(GL_MODELVIEW);
812 gluLookAt(m_cameraPosition[0],m_cameraPosition[1],m_cameraPosition[2],
813 m_cameraTargetPosition[0],m_cameraTargetPosition[1], m_cameraTargetPosition[2],
814 m_cameraUp.getX(),m_cameraUp.getY(),m_cameraUp.getZ());
820 void ForkLiftDemo::lockLiftHinge(void)
822 btScalar hingeAngle = m_liftHinge->getHingeAngle();
823 btScalar lowLim = m_liftHinge->getLowerLimit();
824 btScalar hiLim = m_liftHinge->getUpperLimit();
825 m_liftHinge->enableAngularMotor(false, 0, 0);
826 if(hingeAngle < lowLim)
828 // m_liftHinge->setLimit(lowLim, lowLim + LIFT_EPS);
829 m_liftHinge->setLimit(lowLim, lowLim);
831 else if(hingeAngle > hiLim)
833 // m_liftHinge->setLimit(hiLim - LIFT_EPS, hiLim);
834 m_liftHinge->setLimit(hiLim, hiLim);
838 // m_liftHinge->setLimit(hingeAngle - LIFT_EPS, hingeAngle + LIFT_EPS);
839 m_liftHinge->setLimit(hingeAngle, hingeAngle);
842 } // ForkLiftDemo::lockLiftHinge()
844 void ForkLiftDemo::lockForkSlider(void)
846 btScalar linDepth = m_forkSlider->getLinearPos();
847 btScalar lowLim = m_forkSlider->getLowerLinLimit();
848 btScalar hiLim = m_forkSlider->getUpperLinLimit();
849 m_forkSlider->setPoweredLinMotor(false);
850 if(linDepth <= lowLim)
852 m_forkSlider->setLowerLinLimit(lowLim);
853 m_forkSlider->setUpperLinLimit(lowLim);
855 else if(linDepth > hiLim)
857 m_forkSlider->setLowerLinLimit(hiLim);
858 m_forkSlider->setUpperLinLimit(hiLim);
862 m_forkSlider->setLowerLinLimit(linDepth);
863 m_forkSlider->setUpperLinLimit(linDepth);
866 } // ForkLiftDemo::lockForkSlider()