I have created a bullet vehicle with a attached turret at the top like this:
gEngineForce = 0.f;
gBreakingFrontForce = 0.f;
gBreakingBackForce = 0.f;
maxEngineForce = 20000.f;
minEngineForce = -2000.f;
maxBreakingFrontForce = 4000.f;
maxBreakingBackForce = 600.f;
gVehicleSteering = 0.f;
steeringIncrement = 0.002f;
steeringClamp = 0.6f;
wheelRadius = 0.5f;
wheelWidth = 0.4f;
wheelFriction = 50;
suspensionStiffness = 10.f;
suspensionDamping = 1.3f;
suspensionCompression = 4.4f;
rollInfluence = 0.1f;//1.0f
btScalar suspensionRestLength(0.6);
btVector3 wheelDirectionCS0(0, -1, 0);
btVector3 wheelAxleCS(-1, 0, 0);
btTransform tr;
tr.setIdentity();
chassisShape = new btBoxShape(btVector3(1.f, 0.5f, 2.f));
bulletCollisionShapes.push_back(chassisShape);
compound = new btCompoundShape();
bulletCollisionShapes.push_back(compound);
btTransform chassisTrans;
chassisTrans.setIdentity();
//localTrans effectively shifts the center of mass with respect to the chassis
chassisTrans.setOrigin(btVector3(0, 1.3, 0));
compound->addChildShape(chassisTrans, chassisShape);
tr.setOrigin(btVector3(0, 0.f, 0));
//m_carChassis = CreateRigidBody(2000, tr, compound);
//m_carChassis->setDamping(0.2,0.2);
m_wheelShape = new btCylinderShapeX(btVector3(wheelWidth, wheelRadius, wheelRadius));
m_carChassis = CreateRigidBody(2000, tr, compound);
// create turret
turretShape = new btBoxShape(btVector3(0.4f, 0.2f, 0.8f));
bulletCollisionShapes.push_back(turretShape);
btTransform turretTrans;
turretTrans.setIdentity();
turretTrans.setOrigin(btVector3(0.0f, 0.7f, 0.0f));
turretBody = CreateRigidBody(1, turretTrans, turretShape);
// add some data to build constraint frames
btVector3 axisA(0.f, 1.f, 0.f);
btVector3 axisB(0.f, 0.f, 0.f);
btVector3 pivotA(0.f, 1.f, 0.f);
btVector3 pivotB(0.f, 0.f, 0.f);
hinge = new btHingeConstraint(*m_carChassis, *turretBody, pivotA, pivotB, axisA, axisB);
//hinge->setLimit(-SIMD_HALF_PI * 0.5f, SIMD_HALF_PI * 0.5f);
hinge->enableAngularMotor(true, 0, 1);
// add constraint to world
bt_dynamicsWorld->addConstraint(hinge, true);
{
btTransform something;
something.setIdentity();
something.setOrigin(btVector3(0, 10, 0));
m_carChassis->setWorldTransform(something);
m_vehicleRayCaster = new btDefaultVehicleRaycaster(bt_dynamicsWorld);
m_vehicle = new btRaycastVehicle(m_tuning, m_carChassis, m_vehicleRayCaster);
m_carChassis->setActivationState(DISABLE_DEACTIVATION);
bt_dynamicsWorld->addVehicle(m_vehicle);
float connectionHeight = 1.2f;
//choose coordinate system
m_vehicle->setCoordinateSystem(rightIndex, upIndex, forwardIndex);
bool isFrontWheel = true;
btVector3 connectionPointCS0(1 - (-0.8*wheelWidth), connectionHeight, 3 * 1 - wheelRadius);
m_vehicle->addWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, suspensionRestLength, wheelRadius, m_tuning, isFrontWheel);
connectionPointCS0 = btVector3(-1 + (-0.8*wheelWidth), connectionHeight, 3 * 1 - wheelRadius);
m_vehicle->addWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, suspensionRestLength, wheelRadius, m_tuning, isFrontWheel);
isFrontWheel = false;
connectionPointCS0 = btVector3(-1 + (-0.8*wheelWidth), connectionHeight, -3 * 1 + wheelRadius);
m_vehicle->addWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, suspensionRestLength, wheelRadius, m_tuning, isFrontWheel);
connectionPointCS0 = btVector3(1 - (-0.8*wheelWidth), connectionHeight, -3 * 1 + wheelRadius);
m_vehicle->addWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, suspensionRestLength, wheelRadius, m_tuning, isFrontWheel);
for (int i = 0; i < m_vehicle->getNumWheels(); i++)
{
btWheelInfo& wheel = m_vehicle->getWheelInfo(i);
wheel.m_suspensionStiffness = suspensionStiffness;
wheel.m_wheelsDampingRelaxation = suspensionDamping;
wheel.m_wheelsDampingCompression = suspensionCompression;
wheel.m_frictionSlip = wheelFriction;
wheel.m_rollInfluence = rollInfluence;
}
}
int wheelIndex = 2;
m_vehicle->applyEngineForce(gEngineForce, wheelIndex);
m_vehicle->setBrake(gBreakingBackForce, wheelIndex);
wheelIndex = 3;
m_vehicle->applyEngineForce(gEngineForce, wheelIndex);
m_vehicle->setBrake(gBreakingBackForce, wheelIndex);
wheelIndex = 0;
m_vehicle->setSteeringValue(gVehicleSteering, wheelIndex);
m_vehicle->setBrake(gBreakingFrontForce, wheelIndex);
wheelIndex = 1;
m_vehicle->setSteeringValue(gVehicleSteering, wheelIndex);
m_vehicle->setBrake(gBreakingFrontForce, wheelIndex);
This is how I render the vehicle:
// render wheels
btScalar mwheel[16];
for (int i = 0; i<m_vehicle->getNumWheels(); i++){
//synchronize the wheels with the (interpolated) chassis worldtransform
m_vehicle->updateWheelTransform(i, true);
//draw wheels
m_vehicle->getWheelInfo(i).m_worldTransform.getOpenGLMatrix(mwheel);
RenderWheel(m_wheelShape, mwheel);
}
// render car chassis
btScalar mchassis[16];
m_vehicle->getChassisWorldTransform().getOpenGLMatrix(mchassis);
RenderBox(chassisShape, mchassis);
// render turret
btScalar mturret[16];
// get chassis and turret transforms
btTransform chassisTransform = m_vehicle->getChassisWorldTransform();
//btTransform turretTransform = compound->getChildTransform(1);
btTransform turretTransform = turretBody->getWorldTransform();
// multiply transforms to get updated turret transform
//turretTransform *= chassisTransform;
turretTransform.getOpenGLMatrix(mturret);
RenderBox(turretShape, mturret);
Using the arrow keys I apply break or acceleration forces like this:
bullet.gEngineForce = bullet.maxEngineForce;
bullet.gBreakingFrontForce = 0.f;
bullet.gBreakingBackForce = 0.f;
etc.
The camera is attached to the turret on top of the car, therefore attached to the car itself.
The issue is that when the car starts moving and as it gain speed, the wheels seem to fall behind and the chassis going forward. I would like make the wheels and the chassis more tight, but playing around with the car suspension settings did not help.
Here is a video demonstrating this behaviour: click
I have also noticed another strange behaviour related to the way the car pitches when moving, breaking and turning.
Increasing the gravity accentuates this behaviour. when I accelerate, the chassis pitches forward and when I brake it goes backwards. This is obviously wrong as it should be the other way around. Same happens when turning left, the car pitches left instead of right, and the other way around.
Here is another video demonstrating this behaviour: click