Hello all, so I'm working on a Car implementation for my Game, and so far going forward and turning, all is well and the vehicle can go in circles, however when it comes to backing up and turning, the Vehicle Un-naturally just flips over… I've tried to tighten the suspension stiffness, mess with the size of the body and size of wheels, and positioning of wheels on the car, but I can't mitigate this unwanted behavior!
The code below is what's driving the Raycast Vehicle Physics, One thing to note, I apply Steer to my front wheels, and I apply engine for to my back wheels. I've tried applying engine force on front wheels aswell, but the same issue occurs, and it just results in more aggressive steering,
Also note that the vehicle is driving on a flat test plane, with a small Pyramid to step over (Static Rigid Bodys)
#include "VehiclePhysics.h"
#include "engine_core/singletons/PhysicsWorldSingleton.h"
VehiclePhysics::VehiclePhysics()
{
PhysicsWorldSingleton *physicsWorld = PhysicsWorldSingleton::getInstance();
// Vehicle tuning:
tuning.m_suspensionStiffness = 90.0f;
tuning.m_suspensionCompression = 0.83f;
tuning.m_suspensionDamping = 0.88f;
tuning.m_maxSuspensionTravelCm = 100.0f;
tuning.m_frictionSlip = 10.5f;
tuning.m_maxSuspensionForce = 6000.0f;
// Vehicle setup
btBoxShape *vehicleChassisShape = new btBoxShape(btVector3(0.8f, 0.25f, 1.5f));
btDefaultMotionState *vehicleMotionState = new btDefaultMotionState();
btTransform localTransform;
localTransform.setIdentity();
localTransform.setOrigin(btVector3(0, 1, -10));
vehicleMotionState->setWorldTransform(localTransform);
//* VEHICLE MASS !
btScalar vehicleMass = 1000;
btVector3 vehicleInertia(0, 0, 0);
vehicleChassisShape->calculateLocalInertia(vehicleMass, vehicleInertia);
btRigidBody::btRigidBodyConstructionInfo vehicleRigidBodyCI(vehicleMass, vehicleMotionState, vehicleChassisShape, vehicleInertia);
vehicleRigidBody = new btRigidBody(vehicleRigidBodyCI);
physicsWorld->dynamicsWorld->addRigidBody(vehicleRigidBody);
// vehicleRigidBody->getWorldTransform
// ^ use for rotation camera thingy
//*
// Raycaster and the actual vehicle
vehicleRayCaster = new btDefaultVehicleRaycaster(physicsWorld->dynamicsWorld);
vehicle = new btRaycastVehicle(tuning, vehicleRigidBody, vehicleRayCaster);
btVector3 wheelDirection = btVector3(0, -1, 0);
btVector3 wheelAxle = btVector3(-0.75, 0, 0); //used to be -1
btScalar suspensionRestLength = 0.6;
btScalar wheelRadius = 0.35;
btScalar wheelWidth = 0.3;
btScalar suspensionStiffness = 40.0;
btScalar dampingRelaxation = 4.3;
btScalar dampingCompression = 2.4;
btScalar frictionSlip = 10;
btScalar rollInfluence = 0.2;
//* Adding WHEELS to vehicle physics model !
auto halfExtents = vehicleChassisShape->getHalfExtentsWithoutMargin();
btScalar connectionHeight(5);
btVector3 wheelConnectionPoint(halfExtents.x() - wheelRadius, connectionHeight, halfExtents.z() - wheelWidth);
// Adds the front wheels
vehicle->addWheel(wheelConnectionPoint * btVector3(2, 0, 1), wheelDirection, wheelAxle, suspensionRestLength, wheelRadius, tuning, true);
vehicle->addWheel(wheelConnectionPoint * btVector3(-2, 0, 1), wheelDirection, wheelAxle, suspensionRestLength, wheelRadius, tuning, true);
// Adds the rear wheels
vehicle->addWheel(wheelConnectionPoint * btVector3(2, 0, -1), wheelDirection, wheelAxle, suspensionRestLength, wheelRadius, tuning, false);
vehicle->addWheel(wheelConnectionPoint * btVector3(-2, 0, -1), wheelDirection, wheelAxle, suspensionRestLength, wheelRadius, tuning, false);
for (int i = 0; i < vehicle->getNumWheels(); i++)
{
btWheelInfo &wheel = vehicle->getWheelInfo(i);
// Larger
//wheel.m_chassisConnectionPointCS = wheelConnectionPoint;
wheel.m_suspensionStiffness = suspensionStiffness;
wheel.m_wheelsDampingRelaxation = dampingRelaxation;
wheel.m_wheelsDampingCompression = dampingCompression;
wheel.m_wheelsDampingCompression = btScalar(0.3) * 2 * btSqrt(wheel.m_suspensionStiffness); // btScalar(0.8);
wheel.m_wheelsDampingRelaxation = btScalar(0.5) * 2 * btSqrt(wheel.m_suspensionStiffness); // 1;
// Larger friction slips will result in better handling
wheel.m_frictionSlip = frictionSlip;
wheel.m_rollInfluence = rollInfluence;
}
vehicleRigidBody->setActivationState(DISABLE_DEACTIVATION);
//! Experimental
// vehicleRigidBody->setLinearVelocity(btVector3(0, 0, 0));
// vehicleRigidBody->setAngularVelocity(btVector3(0, 0, 0));
physicsWorld->dynamicsWorld->addVehicle(vehicle);
// Vehicle setup:
engineForce = 0.0;
vehicleSteering = 0.0;
steeringIncrement = 0.04;
steeringClamp = 0.45;
brakeForce = 0.0;
}
void VehiclePhysics::ApplyEngineForce(float force)
{
engineForce = force;
// Rear Wheel Drive
vehicle->applyEngineForce(engineForce, 2);
vehicle->applyEngineForce(engineForce, 3);
// TODO: Add any Bullet physics code here that applies this force
}
void VehiclePhysics::ApplySteer(float steerIncr)
{
if (steerIncr != 0)
{
// Increment or decrement steering based on steerIncr
vehicleSteering += steerIncr;
// Clamp the steering value to make sure it's within [-steeringClamp, steeringClamp]
if (vehicleSteering > steeringClamp) {
vehicleSteering = steeringClamp;
} else if (vehicleSteering < -steeringClamp) {
vehicleSteering = -steeringClamp;
}
}
else
{
// Tend the steering value back to zero if steerIncr is 0
if (vehicleSteering > steeringIncrement) {
vehicleSteering -= steeringIncrement;
} else if (vehicleSteering < -steeringIncrement) {
vehicleSteering += steeringIncrement;
} else {
vehicleSteering = 0; // Close enough to zero we can set it directly
}
}
// Apply the steering value to the front wheels
vehicle->setSteeringValue(vehicleSteering, 0);
vehicle->setSteeringValue(vehicleSteering, 1);
}
void VehiclePhysics::Brake(float force)
{
brakeForce = force;
vehicle->setBrake(brakeForce, 2);
vehicle->setBrake(brakeForce, 3);
// TODO: Add Bullet code here to apply brake
}
void VehiclePhysics::Update()
{
// TODO: Code to update vehicle's state
}
btTransform VehiclePhysics::GetTransform() const
{
// Returns the current transform (position & rotation) of the vehicle
return vehicleRigidBody->getWorldTransform();
}
void VehiclePhysics::printState()
{
btVector3 velocity = vehicleRigidBody->getLinearVelocity();
btVector3 position = vehicleRigidBody->getWorldTransform().getOrigin();
printf("Vehicle Velocity (XYZ): %.2f, %.2f, %.2f | Position (XYZ): %.2f, %.2f, %.2f | Steer: %.2f \n",
velocity.getX(), velocity.getY(), velocity.getZ(),
position.getX(), position.getY(), position.getZ(), vehicle->getSteeringValue(0));
}