From cba140431ed928b72dfeb24fa8f61be1f4dac049 Mon Sep 17 00:00:00 2001 From: erwin coumans Date: Fri, 27 Mar 2015 11:59:22 -0700 Subject: [PATCH] prepare to add ForkLiftDemo in App_AllBullet2Demos rename Ewert/Catto to World/Body for implicit coriolis forces --- Demos/ForkLiftDemo/ForkLiftPhysicsSetup.cpp | 469 ++++++++++++++++++ Demos/ForkLiftDemo/ForkLiftPhysicsSetup.h | 50 ++ Demos/GyroscopicDemo/GyroscopicDemo.cpp | 2 +- Demos/GyroscopicDemo/GyroscopicSetup.cpp | 8 +- Demos3/AllBullet2Demos/BulletDemoEntries.h | 3 + Demos3/AllBullet2Demos/CMakeLists.txt | 2 + Demos3/AllBullet2Demos/premake4.lua | 2 + .../Bullet2RigidBodyDemo.cpp | 3 +- btgui/Bullet3AppSupport/CommonPhysicsSetup.h | 1 + .../btSequentialImpulseConstraintSolver.cpp | 8 +- src/BulletDynamics/Dynamics/btRigidBody.cpp | 6 +- src/BulletDynamics/Dynamics/btRigidBody.h | 11 +- 12 files changed, 548 insertions(+), 17 deletions(-) create mode 100644 Demos/ForkLiftDemo/ForkLiftPhysicsSetup.cpp create mode 100644 Demos/ForkLiftDemo/ForkLiftPhysicsSetup.h diff --git a/Demos/ForkLiftDemo/ForkLiftPhysicsSetup.cpp b/Demos/ForkLiftDemo/ForkLiftPhysicsSetup.cpp new file mode 100644 index 000000000..2a01bebaa --- /dev/null +++ b/Demos/ForkLiftDemo/ForkLiftPhysicsSetup.cpp @@ -0,0 +1,469 @@ +#include "ForkLiftPhysicsSetup.h" +#include "BulletDynamics/MLCPSolvers/btDantzigSolver.h" +#include "BulletDynamics/MLCPSolvers/btSolveProjectedGaussSeidel.h" +#include "BulletDynamics/MLCPSolvers/btMLCPSolver.h" + + +btScalar maxMotorImpulse = 1400.f; +btScalar loadMass = 350.f;// +#ifdef FORCE_ZAXIS_UP + int rightIndex = 0; + int upIndex = 2; + int forwardIndex = 1; + btVector3 wheelDirectionCS0(0,0,-1); + btVector3 wheelAxleCS(1,0,0); +#else + int rightIndex = 0; + int upIndex = 1; + int forwardIndex = 2; + btVector3 wheelDirectionCS0(0,-1,0); + btVector3 wheelAxleCS(-1,0,0); +#endif + +float defaultBreakingForce = 10.f; +float gBreakingForce = 100.f; +float gEngineForce = 0.f; +float gVehicleSteering = 0.f; +float steeringIncrement = 0.04f; +float steeringClamp = 0.3f; +float wheelRadius = 0.5f; +float wheelWidth = 0.4f; +btScalar suspensionRestLength(0.6); +#define CUBE_HALF_EXTENTS 1 +float suspensionStiffness = 20.f; +float suspensionDamping = 2.3f; +float suspensionCompression = 4.4f; +float rollInfluence = 0.1f;//1.0f; +float wheelFriction = 1000;//BT_LARGE_FLOAT; + + +struct ForkLiftInternalData +{ + btRigidBody* m_carChassis; + +//---------------------------- + btRigidBody* m_liftBody; + btVector3 m_liftStartPos; + btHingeConstraint* m_liftHinge; + btRigidBody* m_forkBody; + btVector3 m_forkStartPos; + btSliderConstraint* m_forkSlider; + btRigidBody* m_loadBody; + btVector3 m_loadStartPos; + bool m_useDefaultCamera; + class btTriangleIndexVertexArray* m_indexVertexArrays; + btVector3* m_vertices; + btRaycastVehicle::btVehicleTuning m_tuning; + btVehicleRaycaster* m_vehicleRayCaster; + btRaycastVehicle* m_vehicle; + btCollisionShape* m_wheelShape; + float m_cameraHeight; + float m_minCameraDistance; + float m_maxCameraDistance; + btAlignedObjectArray m_collisionShapes; + class btBroadphaseInterface* m_overlappingPairCache; + class btCollisionDispatcher* m_dispatcher; + class btConstraintSolver* m_constraintSolver; + class btDefaultCollisionConfiguration* m_collisionConfiguration; + class btDiscreteDynamicsWorld* m_dynamicsWorld; + + bool useMCLPSolver; + + ForkLiftInternalData() + :m_carChassis(0), + m_liftBody(0), + m_forkBody(0), + m_loadBody(0), + m_indexVertexArrays(0), + m_vertices(0), + m_cameraHeight(4.f), + m_minCameraDistance(3.f), + m_maxCameraDistance(10.f), + m_overlappingPairCache(0), + m_dispatcher(0), + m_constraintSolver(0), + m_collisionConfiguration(0), + m_dynamicsWorld(0), + useMCLPSolver(false) + { + m_vehicle = 0; + m_wheelShape = 0; + m_useDefaultCamera = false; + } +}; + +ForkLiftPhysicsSetup::ForkLiftPhysicsSetup() +{ + m_data = new ForkLiftInternalData; +} + +ForkLiftPhysicsSetup::~ForkLiftPhysicsSetup() +{ + delete m_data; +} + + +void ForkLiftPhysicsSetup::initPhysics(GraphicsPhysicsBridge& gfxBridge) +{ + + +#ifdef FORCE_ZAXIS_UP + m_cameraUp = btVector3(0,0,1); + m_forwardAxis = 1; +#endif + + btCollisionShape* groundShape = new btBoxShape(btVector3(50,3,50)); + m_data->m_collisionShapes.push_back(groundShape); + m_data->m_collisionConfiguration = new btDefaultCollisionConfiguration(); + m_data->m_dispatcher = new btCollisionDispatcher(m_data->m_collisionConfiguration); + btVector3 worldMin(-1000,-1000,-1000); + btVector3 worldMax(1000,1000,1000); + m_data->m_overlappingPairCache = new btAxisSweep3(worldMin,worldMax); + if (m_data->useMCLPSolver) + { + btDantzigSolver* mlcp = new btDantzigSolver(); + //btSolveProjectedGaussSeidel* mlcp = new btSolveProjectedGaussSeidel; + btMLCPSolver* sol = new btMLCPSolver(mlcp); + m_data->m_constraintSolver = sol; + } else + { + m_data->m_constraintSolver = new btSequentialImpulseConstraintSolver(); + } + m_data->m_dynamicsWorld = new btDiscreteDynamicsWorld(m_data->m_dispatcher,m_data->m_overlappingPairCache,m_data->m_constraintSolver,m_data->m_collisionConfiguration); + if (m_data->useMCLPSolver) + { + m_data->m_dynamicsWorld ->getSolverInfo().m_minimumSolverBatchSize = 1;//for direct solver it is better to have a small A matrix + } else + { + m_data->m_dynamicsWorld ->getSolverInfo().m_minimumSolverBatchSize = 128;//for direct solver, it is better to solve multiple objects together, small batches have high overhead + } +#ifdef FORCE_ZAXIS_UP + m_dynamicsWorld->setGravity(btVector3(0,0,-10)); +#endif + + //m_dynamicsWorld->setGravity(btVector3(0,0,0)); +btTransform tr; +tr.setIdentity(); +tr.setOrigin(btVector3(0,-3,0)); + +//either use heightfield or triangle mesh + + + //create ground object + localCreateRigidBody(0,tr,groundShape); + +#ifdef FORCE_ZAXIS_UP +// indexRightAxis = 0; +// indexUpAxis = 2; +// indexForwardAxis = 1; + btCollisionShape* chassisShape = new btBoxShape(btVector3(1.f,2.f, 0.5f)); + btCompoundShape* compound = new btCompoundShape(); + btTransform localTrans; + localTrans.setIdentity(); + //localTrans effectively shifts the center of mass with respect to the chassis + localTrans.setOrigin(btVector3(0,0,1)); +#else + btCollisionShape* chassisShape = new btBoxShape(btVector3(1.f,0.5f,2.f)); + m_data->m_collisionShapes.push_back(chassisShape); + + btCompoundShape* compound = new btCompoundShape(); + m_data->m_collisionShapes.push_back(compound); + btTransform localTrans; + localTrans.setIdentity(); + //localTrans effectively shifts the center of mass with respect to the chassis + localTrans.setOrigin(btVector3(0,1,0)); +#endif + + compound->addChildShape(localTrans,chassisShape); + + { + btCollisionShape* suppShape = new btBoxShape(btVector3(0.5f,0.1f,0.5f)); + btTransform suppLocalTrans; + suppLocalTrans.setIdentity(); + //localTrans effectively shifts the center of mass with respect to the chassis + suppLocalTrans.setOrigin(btVector3(0,1.0,2.5)); + compound->addChildShape(suppLocalTrans, suppShape); + } + + tr.setOrigin(btVector3(0,0.f,0)); + + m_data->m_carChassis = localCreateRigidBody(800,tr,compound);//chassisShape); + //m_carChassis->setDamping(0.2,0.2); + + m_data->m_wheelShape = new btCylinderShapeX(btVector3(wheelWidth,wheelRadius,wheelRadius)); + + { + btCollisionShape* liftShape = new btBoxShape(btVector3(0.5f,2.0f,0.05f)); + m_data->m_collisionShapes.push_back(liftShape); + btTransform liftTrans; + m_data->m_liftStartPos = btVector3(0.0f, 2.5f, 3.05f); + liftTrans.setIdentity(); + liftTrans.setOrigin(m_data->m_liftStartPos); + m_data->m_liftBody = localCreateRigidBody(10,liftTrans, liftShape); + + btTransform localA, localB; + localA.setIdentity(); + localB.setIdentity(); + localA.getBasis().setEulerZYX(0, SIMD_HALF_PI, 0); + localA.setOrigin(btVector3(0.0, 1.0, 3.05)); + localB.getBasis().setEulerZYX(0, SIMD_HALF_PI, 0); + localB.setOrigin(btVector3(0.0, -1.5, -0.05)); + m_data->m_liftHinge = new btHingeConstraint(*m_data->m_carChassis,*m_data->m_liftBody, localA, localB); +// m_liftHinge->setLimit(-LIFT_EPS, LIFT_EPS); + m_data->m_liftHinge->setLimit(0.0f, 0.0f); + m_data->m_dynamicsWorld->addConstraint(m_data->m_liftHinge, true); + + btCollisionShape* forkShapeA = new btBoxShape(btVector3(1.0f,0.1f,0.1f)); + m_data->m_collisionShapes.push_back(forkShapeA); + btCompoundShape* forkCompound = new btCompoundShape(); + m_data->m_collisionShapes.push_back(forkCompound); + btTransform forkLocalTrans; + forkLocalTrans.setIdentity(); + forkCompound->addChildShape(forkLocalTrans, forkShapeA); + + btCollisionShape* forkShapeB = new btBoxShape(btVector3(0.1f,0.02f,0.6f)); + m_data->m_collisionShapes.push_back(forkShapeB); + forkLocalTrans.setIdentity(); + forkLocalTrans.setOrigin(btVector3(-0.9f, -0.08f, 0.7f)); + forkCompound->addChildShape(forkLocalTrans, forkShapeB); + + btCollisionShape* forkShapeC = new btBoxShape(btVector3(0.1f,0.02f,0.6f)); + m_data->m_collisionShapes.push_back(forkShapeC); + forkLocalTrans.setIdentity(); + forkLocalTrans.setOrigin(btVector3(0.9f, -0.08f, 0.7f)); + forkCompound->addChildShape(forkLocalTrans, forkShapeC); + + btTransform forkTrans; + m_data->m_forkStartPos = btVector3(0.0f, 0.6f, 3.2f); + forkTrans.setIdentity(); + forkTrans.setOrigin(m_data->m_forkStartPos); + m_data->m_forkBody = localCreateRigidBody(5, forkTrans, forkCompound); + + localA.setIdentity(); + localB.setIdentity(); + localA.getBasis().setEulerZYX(0, 0, SIMD_HALF_PI); + localA.setOrigin(btVector3(0.0f, -1.9f, 0.05f)); + localB.getBasis().setEulerZYX(0, 0, SIMD_HALF_PI); + localB.setOrigin(btVector3(0.0, 0.0, -0.1)); + m_data->m_forkSlider = new btSliderConstraint(*m_data->m_liftBody, *m_data->m_forkBody, localA, localB, true); + m_data->m_forkSlider->setLowerLinLimit(0.1f); + m_data->m_forkSlider->setUpperLinLimit(0.1f); +// m_forkSlider->setLowerAngLimit(-LIFT_EPS); +// m_forkSlider->setUpperAngLimit(LIFT_EPS); + m_data->m_forkSlider->setLowerAngLimit(0.0f); + m_data->m_forkSlider->setUpperAngLimit(0.0f); + m_data->m_dynamicsWorld->addConstraint(m_data->m_forkSlider, true); + + + btCompoundShape* loadCompound = new btCompoundShape(); + m_data->m_collisionShapes.push_back(loadCompound); + btCollisionShape* loadShapeA = new btBoxShape(btVector3(2.0f,0.5f,0.5f)); + m_data->m_collisionShapes.push_back(loadShapeA); + btTransform loadTrans; + loadTrans.setIdentity(); + loadCompound->addChildShape(loadTrans, loadShapeA); + btCollisionShape* loadShapeB = new btBoxShape(btVector3(0.1f,1.0f,1.0f)); + m_data->m_collisionShapes.push_back(loadShapeB); + loadTrans.setIdentity(); + loadTrans.setOrigin(btVector3(2.1f, 0.0f, 0.0f)); + loadCompound->addChildShape(loadTrans, loadShapeB); + btCollisionShape* loadShapeC = new btBoxShape(btVector3(0.1f,1.0f,1.0f)); + m_data->m_collisionShapes.push_back(loadShapeC); + loadTrans.setIdentity(); + loadTrans.setOrigin(btVector3(-2.1f, 0.0f, 0.0f)); + loadCompound->addChildShape(loadTrans, loadShapeC); + loadTrans.setIdentity(); + m_data->m_loadStartPos = btVector3(0.0f, 3.5f, 7.0f); + loadTrans.setOrigin(m_data->m_loadStartPos); + m_data->m_loadBody = localCreateRigidBody(loadMass, loadTrans, loadCompound); + } + + + + + + /// create vehicle + { + + m_data->m_vehicleRayCaster = new btDefaultVehicleRaycaster(m_data->m_dynamicsWorld); + m_data->m_vehicle = new btRaycastVehicle(m_data->m_tuning,m_data->m_carChassis,m_data->m_vehicleRayCaster); + + ///never deactivate the vehicle + m_data->m_carChassis->setActivationState(DISABLE_DEACTIVATION); + + m_data->m_dynamicsWorld->addVehicle(m_data->m_vehicle); + + float connectionHeight = 1.2f; + + + bool isFrontWheel=true; + + //choose coordinate system + m_data->m_vehicle->setCoordinateSystem(rightIndex,upIndex,forwardIndex); + +#ifdef FORCE_ZAXIS_UP + btVector3 connectionPointCS0(CUBE_HALF_EXTENTS-(0.3*wheelWidth),2*CUBE_HALF_EXTENTS-wheelRadius, connectionHeight); +#else + btVector3 connectionPointCS0(CUBE_HALF_EXTENTS-(0.3*wheelWidth),connectionHeight,2*CUBE_HALF_EXTENTS-wheelRadius); +#endif + + m_data->m_vehicle->addWheel(connectionPointCS0,wheelDirectionCS0,wheelAxleCS,suspensionRestLength,wheelRadius,m_data->m_tuning,isFrontWheel); +#ifdef FORCE_ZAXIS_UP + connectionPointCS0 = btVector3(-CUBE_HALF_EXTENTS+(0.3*wheelWidth),2*CUBE_HALF_EXTENTS-wheelRadius, connectionHeight); +#else + connectionPointCS0 = btVector3(-CUBE_HALF_EXTENTS+(0.3*wheelWidth),connectionHeight,2*CUBE_HALF_EXTENTS-wheelRadius); +#endif + + m_data->m_vehicle->addWheel(connectionPointCS0,wheelDirectionCS0,wheelAxleCS,suspensionRestLength,wheelRadius,m_data->m_tuning,isFrontWheel); +#ifdef FORCE_ZAXIS_UP + connectionPointCS0 = btVector3(-CUBE_HALF_EXTENTS+(0.3*wheelWidth),-2*CUBE_HALF_EXTENTS+wheelRadius, connectionHeight); +#else + connectionPointCS0 = btVector3(-CUBE_HALF_EXTENTS+(0.3*wheelWidth),connectionHeight,-2*CUBE_HALF_EXTENTS+wheelRadius); +#endif //FORCE_ZAXIS_UP + isFrontWheel = false; + m_data->m_vehicle->addWheel(connectionPointCS0,wheelDirectionCS0,wheelAxleCS,suspensionRestLength,wheelRadius,m_data->m_tuning,isFrontWheel); +#ifdef FORCE_ZAXIS_UP + connectionPointCS0 = btVector3(CUBE_HALF_EXTENTS-(0.3*wheelWidth),-2*CUBE_HALF_EXTENTS+wheelRadius, connectionHeight); +#else + connectionPointCS0 = btVector3(CUBE_HALF_EXTENTS-(0.3*wheelWidth),connectionHeight,-2*CUBE_HALF_EXTENTS+wheelRadius); +#endif + m_data->m_vehicle->addWheel(connectionPointCS0,wheelDirectionCS0,wheelAxleCS,suspensionRestLength,wheelRadius,m_data->m_tuning,isFrontWheel); + + for (int i=0;im_vehicle->getNumWheels();i++) + { + btWheelInfo& wheel = m_data->m_vehicle->getWheelInfo(i); + wheel.m_suspensionStiffness = suspensionStiffness; + wheel.m_wheelsDampingRelaxation = suspensionDamping; + wheel.m_wheelsDampingCompression = suspensionCompression; + wheel.m_frictionSlip = wheelFriction; + wheel.m_rollInfluence = rollInfluence; + } + } + + resetForklift(); + gfxBridge.autogenerateGraphicsObjects(m_data->m_dynamicsWorld); + +// setCameraDistance(26.f); +} + +void ForkLiftPhysicsSetup::resetForklift() +{ + gVehicleSteering = 0.f; + gBreakingForce = defaultBreakingForce; + gEngineForce = 0.f; + + m_data->m_carChassis->setCenterOfMassTransform(btTransform::getIdentity()); + m_data->m_carChassis->setLinearVelocity(btVector3(0,0,0)); + m_data->m_carChassis->setAngularVelocity(btVector3(0,0,0)); + m_data->m_dynamicsWorld->getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(m_data->m_carChassis->getBroadphaseHandle(),m_data->m_dynamicsWorld->getDispatcher()); + if (m_data->m_vehicle) + { + m_data->m_vehicle->resetSuspension(); + for (int i=0;im_vehicle->getNumWheels();i++) + { + //synchronize the wheels with the (interpolated) chassis worldtransform + m_data->m_vehicle->updateWheelTransform(i,true); + } + } + btTransform liftTrans; + liftTrans.setIdentity(); + liftTrans.setOrigin(m_data->m_liftStartPos); + m_data->m_liftBody->activate(); + m_data->m_liftBody->setCenterOfMassTransform(liftTrans); + m_data->m_liftBody->setLinearVelocity(btVector3(0,0,0)); + m_data->m_liftBody->setAngularVelocity(btVector3(0,0,0)); + + btTransform forkTrans; + forkTrans.setIdentity(); + forkTrans.setOrigin(m_data->m_forkStartPos); + m_data->m_forkBody->activate(); + m_data->m_forkBody->setCenterOfMassTransform(forkTrans); + m_data->m_forkBody->setLinearVelocity(btVector3(0,0,0)); + m_data->m_forkBody->setAngularVelocity(btVector3(0,0,0)); + +// m_liftHinge->setLimit(-LIFT_EPS, LIFT_EPS); + m_data->m_liftHinge->setLimit(0.0f, 0.0f); + m_data->m_liftHinge->enableAngularMotor(false, 0, 0); + + + m_data->m_forkSlider->setLowerLinLimit(0.1f); + m_data->m_forkSlider->setUpperLinLimit(0.1f); + m_data->m_forkSlider->setPoweredLinMotor(false); + + btTransform loadTrans; + loadTrans.setIdentity(); + loadTrans.setOrigin(m_data->m_loadStartPos); + m_data->m_loadBody->activate(); + m_data->m_loadBody->setCenterOfMassTransform(loadTrans); + m_data->m_loadBody->setLinearVelocity(btVector3(0,0,0)); + m_data->m_loadBody->setAngularVelocity(btVector3(0,0,0)); + +} + +btRigidBody* ForkLiftPhysicsSetup::localCreateRigidBody(btScalar mass, const btTransform& startTransform, btCollisionShape* shape) +{ + btAssert((!shape || shape->getShapeType() != INVALID_SHAPE_PROXYTYPE)); + + //rigidbody is dynamic if and only if mass is non zero, otherwise static + bool isDynamic = (mass != 0.f); + + btVector3 localInertia(0,0,0); + if (isDynamic) + shape->calculateLocalInertia(mass,localInertia); + + //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects + +//#define USE_MOTIONSTATE 1 +#ifdef USE_MOTIONSTATE + btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform); + + btRigidBody::btRigidBodyConstructionInfo cInfo(mass,myMotionState,shape,localInertia); + + btRigidBody* body = new btRigidBody(cInfo); + body->setContactProcessingThreshold(BT_LARGE_FLOAT);//m_defaultContactProcessingThreshold); + +#else + btRigidBody* body = new btRigidBody(mass,0,shape,localInertia); + body->setWorldTransform(startTransform); +#endif// + + m_data->m_dynamicsWorld->addRigidBody(body); + return body; +} + +void ForkLiftPhysicsSetup::exitPhysics() +{ +} +void ForkLiftPhysicsSetup::stepSimulation(float deltaTime) +{ +} +void ForkLiftPhysicsSetup::debugDraw(int debugDrawFlags) +{ +} +bool ForkLiftPhysicsSetup::pickBody(const btVector3& rayFromWorld, const btVector3& rayToWorld) +{ + return false; +} +bool ForkLiftPhysicsSetup::movePickedBody(const btVector3& rayFromWorld, const btVector3& rayToWorld) +{ + return false; +} +void ForkLiftPhysicsSetup::removePickingConstraint() +{ +} +void ForkLiftPhysicsSetup::syncPhysicsToGraphics(GraphicsPhysicsBridge& gfxBridge) +{ +} + +void ForkLiftPhysicsSetup::renderScene(GraphicsPhysicsBridge& gfxBridge) +{ + +} + +void ForkLiftPhysicsSetup::lockLiftHinge() +{ +} + +void ForkLiftPhysicsSetup::lockForkSlider() +{ +} diff --git a/Demos/ForkLiftDemo/ForkLiftPhysicsSetup.h b/Demos/ForkLiftDemo/ForkLiftPhysicsSetup.h new file mode 100644 index 000000000..89e932668 --- /dev/null +++ b/Demos/ForkLiftDemo/ForkLiftPhysicsSetup.h @@ -0,0 +1,50 @@ +#ifndef FORK_LIFT_PHYSICS_SETUP_H +#define FORK_LIFT_PHYSICS_SETUP_H + +class btRigidBody; +class btCollisionShape; +class btBroadphaseInterface; +class btConstraintSolver; +class btCollisionDispatcher; +class btDefaultCollisionConfiguration; +class btDiscreteDynamicsWorld; +class btTransform; +class btVector3; +class btBoxShape; + +#include "LinearMath/btVector3.h" +#include "LinearMath/btAlignedObjectArray.h" +#include "Bullet3AppSupport/CommonRigidBodySetup.h" + +class ForkLiftPhysicsSetup : public CommonPhysicsSetup +{ + +protected: + + struct ForkLiftInternalData* m_data; + +public: + + ForkLiftPhysicsSetup(); + virtual ~ForkLiftPhysicsSetup(); + + virtual void initPhysics(GraphicsPhysicsBridge& gfxBridge); + + + virtual void exitPhysics(); + virtual void stepSimulation(float deltaTime); + virtual void debugDraw(int debugDrawFlags); + virtual bool pickBody(const btVector3& rayFromWorld, const btVector3& rayToWorld); + virtual bool movePickedBody(const btVector3& rayFromWorld, const btVector3& rayToWorld); + virtual void removePickingConstraint(); + virtual void syncPhysicsToGraphics(GraphicsPhysicsBridge& gfxBridge); + virtual void renderScene(GraphicsPhysicsBridge& gfxBridge); + + void resetForklift(); + void lockLiftHinge(); + void lockForkSlider(); + class btRigidBody* localCreateRigidBody(btScalar mass, const btTransform& startTrans, btCollisionShape* shape); + +}; + +#endif //FORK_LIFT_PHYSICS_SETUP_H diff --git a/Demos/GyroscopicDemo/GyroscopicDemo.cpp b/Demos/GyroscopicDemo/GyroscopicDemo.cpp index 31b399686..cc1a926c5 100644 --- a/Demos/GyroscopicDemo/GyroscopicDemo.cpp +++ b/Demos/GyroscopicDemo/GyroscopicDemo.cpp @@ -107,7 +107,7 @@ void GyroscopicDemo::initPhysics() m_dynamicsWorld->addRigidBody(body); if (gyro[i]) { - body->setFlags(BT_ENABLE_GYROPSCOPIC_FORCE); + body->setFlags(BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_BODY); } else { body->setFlags(0); diff --git a/Demos/GyroscopicDemo/GyroscopicSetup.cpp b/Demos/GyroscopicDemo/GyroscopicSetup.cpp index e2e617705..3b3b497dd 100644 --- a/Demos/GyroscopicDemo/GyroscopicSetup.cpp +++ b/Demos/GyroscopicDemo/GyroscopicSetup.cpp @@ -3,15 +3,15 @@ static int gyroflags[4] = { 0,//none, no gyroscopic term BT_ENABLE_GYROSCOPIC_FORCE_EXPLICIT, - BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_EWERT, - BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_CATTO + BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_WORLD, + BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_BODY }; static const char* gyroNames[4] = { "No Coriolis", "Explicit", - "Implicit", - "Local Implicit" + "Implicit (World)", + "Implicit (Body)" }; diff --git a/Demos3/AllBullet2Demos/BulletDemoEntries.h b/Demos3/AllBullet2Demos/BulletDemoEntries.h index 581c60d42..c7198ae55 100644 --- a/Demos3/AllBullet2Demos/BulletDemoEntries.h +++ b/Demos3/AllBullet2Demos/BulletDemoEntries.h @@ -16,6 +16,7 @@ #include "../bullet2/RagdollDemo/RagdollDemo.h" #include "../bullet2/LuaDemo/LuaPhysicsSetup.h" #include "../bullet2/ChainDemo/ChainDemo.h" +#include "../../Demos/ForkLiftDemo/ForkLiftPhysicsSetup.h" #include "../../Demos/CcdPhysicsDemo/CcdPhysicsSetup.h" #include "../../Demos/GyroscopicDemo/GyroscopicSetup.h" #include "../bullet2/ConstraintDemo/ConstraintPhysicsSetup.h" @@ -57,6 +58,7 @@ MYCREATEFUNC2(LuaDemoCreateFunc,LuaPhysicsSetup); MYCREATEFUNC(Serialize); MYCREATEFUNC(CcdPhysics); MYCREATEFUNC(Gyroscopic); +MYCREATEFUNC(ForkLiftPhysics); MYCREATEFUNC(KinematicObject); MYCREATEFUNC(ConstraintPhysics); MYCREATEFUNC(Dof6Spring2); @@ -96,6 +98,7 @@ static BulletDemoEntry allDemos[]= {0,"API Demos", 0}, {1,"Raytracer",RaytracerPhysicsCreateFunc}, {1,"BasicDemo",BasicDemo::MyCreateFunc}, + {1,"ForkLift",ForkLiftPhysicsCreateFunc}, { 1, "CcdDemo", CcdPhysicsCreateFunc }, { 1, "Gyroscopic", GyroscopicCreateFunc }, { 1, "Kinematic", KinematicObjectCreateFunc }, diff --git a/Demos3/AllBullet2Demos/CMakeLists.txt b/Demos3/AllBullet2Demos/CMakeLists.txt index a846a092e..5e3a7c5b9 100644 --- a/Demos3/AllBullet2Demos/CMakeLists.txt +++ b/Demos3/AllBullet2Demos/CMakeLists.txt @@ -18,6 +18,8 @@ SET(App_AllBullet2Demos_SRCS ../../Demos/Raytracer/RaytracerSetup.h ../../Demos/GyroscopicDemo/GyroscopicSetup.cpp ../../Demos/GyroscopicDemo/GyroscopicSetup.h + ../../Demos/ForkLiftDemo/ForkLiftPhysicsSetup.cpp + ../../Demos/ForkLiftDemo/ForkLiftPhysicsSetup.h ../../Demos/SerializeDemo/SerializeSetup.cpp ../../Extras/Serialize/BulletFileLoader/bChunk.cpp ../../Extras/Serialize/BulletFileLoader/bDNA.cpp diff --git a/Demos3/AllBullet2Demos/premake4.lua b/Demos3/AllBullet2Demos/premake4.lua index 17e17f8ac..4626235b5 100644 --- a/Demos3/AllBullet2Demos/premake4.lua +++ b/Demos3/AllBullet2Demos/premake4.lua @@ -53,6 +53,8 @@ "../FiniteElementMethod/FiniteElementDemo.cpp", "../../Demos/BasicDemo/BasicDemoPhysicsSetup.cpp", "../../Demos/BasicDemo/BasicDemoPhysicsSetup.h", + "../../Demos/ForkLiftDemo/ForkLiftPhysicsSetup.cpp", + "../../Demos/ForkLiftDemo/ForkLiftPhysicsSetup.h", "../../Demos/CcdPhysicsDemo/CcdPhysicsSetup.cpp", "../../Demos/CcdPhysicsDemo/CcdPhysicsSetup.h", "../../Demos/Raytracer/RaytracerSetup.cpp", diff --git a/btgui/Bullet3AppSupport/Bullet2RigidBodyDemo.cpp b/btgui/Bullet3AppSupport/Bullet2RigidBodyDemo.cpp index 13dcc7817..ac0acf95c 100644 --- a/btgui/Bullet3AppSupport/Bullet2RigidBodyDemo.cpp +++ b/btgui/Bullet3AppSupport/Bullet2RigidBodyDemo.cpp @@ -319,9 +319,10 @@ void Bullet2RigidBodyDemo::renderScene() MyGraphicsPhysicsBridge glBridge(m_glApp); m_physicsSetup->syncPhysicsToGraphics(glBridge); - m_glApp->m_renderer->renderScene(); + m_physicsSetup->renderScene(glBridge); + } void Bullet2RigidBodyDemo::physicsDebugDraw(int debugDrawFlags) diff --git a/btgui/Bullet3AppSupport/CommonPhysicsSetup.h b/btgui/Bullet3AppSupport/CommonPhysicsSetup.h index b1146e2a4..ef1838d33 100644 --- a/btgui/Bullet3AppSupport/CommonPhysicsSetup.h +++ b/btgui/Bullet3AppSupport/CommonPhysicsSetup.h @@ -77,6 +77,7 @@ public: virtual void debugDraw(int debugDrawFlags)=0; + virtual void renderScene(GraphicsPhysicsBridge& gfxBridge){}; virtual bool pickBody(const btVector3& rayFromWorld, const btVector3& rayToWorld) = 0; virtual bool movePickedBody(const btVector3& rayFromWorld, const btVector3& rayToWorld)=0; diff --git a/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp b/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp index dba1fcfe2..8da572bf7 100644 --- a/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp +++ b/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp @@ -1274,14 +1274,14 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCol gyroForce = body->computeGyroscopicForceExplicit(infoGlobal.m_maxGyroscopicForce); solverBody.m_externalTorqueImpulse -= gyroForce*body->getInvInertiaTensorWorld()*infoGlobal.m_timeStep; } - if (body->getFlags()&BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_EWERT) + if (body->getFlags()&BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_WORLD) { - gyroForce = body->computeGyroscopicImpulseImplicit_Ewert(infoGlobal.m_timeStep); + gyroForce = body->computeGyroscopicImpulseImplicit_World(infoGlobal.m_timeStep); solverBody.m_externalTorqueImpulse += gyroForce; } - if (body->getFlags()&BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_CATTO) + if (body->getFlags()&BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_BODY) { - gyroForce = body->computeGyroscopicImpulseImplicit_Catto(infoGlobal.m_timeStep); + gyroForce = body->computeGyroscopicImpulseImplicit_Body(infoGlobal.m_timeStep); solverBody.m_externalTorqueImpulse += gyroForce; } diff --git a/src/BulletDynamics/Dynamics/btRigidBody.cpp b/src/BulletDynamics/Dynamics/btRigidBody.cpp index f9feb5cf4..8bc3c1ca5 100644 --- a/src/BulletDynamics/Dynamics/btRigidBody.cpp +++ b/src/BulletDynamics/Dynamics/btRigidBody.cpp @@ -87,7 +87,7 @@ void btRigidBody::setupRigidBody(const btRigidBody::btRigidBodyConstructionInfo& setMassProps(constructionInfo.m_mass, constructionInfo.m_localInertia); updateInertiaTensor(); - m_rigidbodyFlags = BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_EWERT; + m_rigidbodyFlags = BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_BODY; m_deltaLinearVelocity.setZero(); @@ -311,7 +311,7 @@ void btSetCrossMatrixMinus(btMatrix3x3& res, const btVector3& a) +a_1, -a_0, 0); } -btVector3 btRigidBody::computeGyroscopicImpulseImplicit_Catto(btScalar step) const +btVector3 btRigidBody::computeGyroscopicImpulseImplicit_Body(btScalar step) const { btVector3 idl = getLocalInertia(); btVector3 omega1 = getAngularVelocity(); @@ -352,7 +352,7 @@ btVector3 btRigidBody::computeGyroscopicImpulseImplicit_Catto(btScalar step) con -btVector3 btRigidBody::computeGyroscopicImpulseImplicit_Ewert(btScalar step) const +btVector3 btRigidBody::computeGyroscopicImpulseImplicit_World(btScalar step) const { // use full newton-euler equations. common practice to drop the wxIw term. want it for better tumbling behavior. // calculate using implicit euler step so it's stable. diff --git a/src/BulletDynamics/Dynamics/btRigidBody.h b/src/BulletDynamics/Dynamics/btRigidBody.h index b3c77bb94..bed1f9ccb 100644 --- a/src/BulletDynamics/Dynamics/btRigidBody.h +++ b/src/BulletDynamics/Dynamics/btRigidBody.h @@ -44,8 +44,8 @@ enum btRigidBodyFlags ///BT_ENABLE_GYROPSCOPIC_FORCE flags is enabled by default in Bullet 2.83 and onwards. ///See Demos/GyroscopicDemo and computeGyroscopicImpulseImplicit BT_ENABLE_GYROSCOPIC_FORCE_EXPLICIT = 2, - BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_EWERT=4, - BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_CATTO=8, + BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_WORLD=4, + BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_BODY=8, }; @@ -533,8 +533,11 @@ public: - btVector3 computeGyroscopicImpulseImplicit_Ewert(btScalar dt) const; - btVector3 computeGyroscopicImpulseImplicit_Catto(btScalar step) const; + ///perform implicit force computation in world space + btVector3 computeGyroscopicImpulseImplicit_World(btScalar dt) const; + + ///perform implicit force computation in body space (inertial frame) + btVector3 computeGyroscopicImpulseImplicit_Body(btScalar step) const; ///explicit version is best avoided, it gains energy btVector3 computeGyroscopicForceExplicit(btScalar maxGyroscopicForce) const;