So I've managed to use this class and the vehicle can be used on it but it sometimes get stuck on terrain's hollows even if the height to climb is really small.
I'm using MLCP constraint solver and tested PGS solver but does not help.
Here is the concerned code :
Vehicle.hpp
Code: Select all
#define USE_MLCP_SOLVER
// I removed other #define because all were just floats
class Vehicle {
public:
// theses bools are set to true when the corresponding key is pressed
bool m_foward = false, m_backward = false, m_leftward = false, m_rightward = false;
bool m_reset = false;
Vehicle(Vao *chassisVao, Vao *wheelVao, const float *heights, uint32_t gridsize, float amplitude);
~Vehicle();
// this function runs the logic of the physics simulation, it gets executed each frame
void stepSimulation(uint32_t frameTime);
// this function instantiate objects to rendered, it gets executed each frame
void prepareRendering(std::vector<const Entity *> &entities);
private:
// members are declared here ---> <---
// create physics world and vehicle
void initPhysics(const float *heights, uint32_t gridsize, float amplitude);
// cleanup things
void exitPhysics(void);
// reset vehicle position, rotation, momentum, etc..
void resetVehicle(void);
// helper function to create rigid body
btRigidBody* localCreateRigidBody(btScalar mass, const btTransform& startTransform, btCollisionShape* shape);
};
Vehicle.cpp
Code: Select all
#include "Vehicle.hpp"
Vehicle::Vehicle(Vao *chassisVao, Vao *wheelVao, const float *heights, uint32_t gridsize, float amplitude) {
initPhysics(heights, gridsize, amplitude);
if (chassisVao) {
m_chassisEntity = new Entity(chassisVao);
}
for (int i = 0; i < 4; ++i) {
m_wheelEntities.push_back(Entity(wheelVao));
}
}
Vehicle::~Vehicle() {
exitPhysics();
if (m_chassisEntity) {
delete m_chassisEntity;
}
m_wheelEntities.clear();
}
void Vehicle::initPhysics(const float *heights, uint32_t gridsize, float amplitude) {
// setup dynamics world
m_collisionConfiguration = new btDefaultCollisionConfiguration();
m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration);
btVector3 worldMin(-1000, -1000, -1000);
btVector3 worldMax(1000, 1000, 1000);
m_overlappingPairCache = new btAxisSweep3(worldMin, worldMax);
#ifdef USE_MLCP_SOLVER
btDantzigSolver* mlcp = new btDantzigSolver();
// btSolveProjectedGaussSeidel* mlcp = new btSolveProjectedGaussSeidel();
btMLCPSolver* sol = new btMLCPSolver(mlcp);
m_solver = sol;
#else
m_solver = new btSequentialImpulseConstraintSolver();
#endif
m_world = new btDiscreteDynamicsWorld(m_dispatcher, m_overlappingPairCache, m_solver, m_collisionConfiguration);
#ifdef USE_MLCP_SOLVER
m_world->getSolverInfo().m_minimumSolverBatchSize = 1;
#else
m_world->getSolverInfo().m_minimumSolverBatchSize = 128;
#endif
m_world->getSolverInfo().m_globalCfm = 0.00001;
// create ground object
// btVector3 groundExtents(100, 3, 100);
// btCollisionShape* groundShape = new btBoxShape(groundExtents);
btCollisionShape* groundShape = new btHeightfieldTerrainShape(gridsize + 1, gridsize + 1, heights, 0.0f, amplitude, 1, false);
m_collisionShapes.push_back(groundShape);
btTransform tr;
tr.setIdentity();
tr.setOrigin(btVector3(gridsize * 0.5f, WHEEL_RADIUS, gridsize * 0.5f));
localCreateRigidBody(0, tr, groundShape);
// create vehicle
// BEGIN - create chassis shape
btVector3 vehicleExtents(1.76f, 1.1f, 4.0f);
btCollisionShape* chassisShape = new btBoxShape(vehicleExtents);
m_collisionShapes.push_back(chassisShape);
btCompoundShape* compound = new btCompoundShape();
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));
compound->addChildShape(localTrans, chassisShape);
tr.setOrigin(btVector3(0, 0, 0));
m_carChassis = localCreateRigidBody(800, tr, compound);
// END - create chassis shape
// BEGIN - create vehicle
m_vehicleRayCaster = new btDefaultVehicleRaycaster(m_world);
m_vehicle = new btRaycastVehicle(m_tuning, m_carChassis, m_vehicleRayCaster);
m_carChassis->setActivationState(DISABLE_DEACTIVATION); // never deactivate the vehicle
m_world->addVehicle(m_vehicle);
// choose coordinate system
m_vehicle->setCoordinateSystem(0, 1, 2);
btVector3 wheelDirection(0, -1, 0);
btVector3 wheelAxis(-1, 0, 0);
btVector3 connectionPoint(0.5f * vehicleExtents.x(), WHEEL_RADIUS, 0.5f * vehicleExtents.z() - WHEEL_RADIUS);
m_vehicle->addWheel(connectionPoint, wheelDirection, wheelAxis, SUSPENSION_REST_LENGTH, WHEEL_RADIUS, m_tuning, true);
connectionPoint = btVector3(-0.5f * vehicleExtents.x(), WHEEL_RADIUS, 0.5f * vehicleExtents.z() - WHEEL_RADIUS);
m_vehicle->addWheel(connectionPoint, wheelDirection, wheelAxis, SUSPENSION_REST_LENGTH, WHEEL_RADIUS, m_tuning, true);
connectionPoint = btVector3(0.5f * vehicleExtents.x(), WHEEL_RADIUS, -0.5f * vehicleExtents.z() + WHEEL_RADIUS);
m_vehicle->addWheel(connectionPoint, wheelDirection, wheelAxis, SUSPENSION_REST_LENGTH, WHEEL_RADIUS, m_tuning, false);
connectionPoint = btVector3(-0.5f * vehicleExtents.x(), WHEEL_RADIUS, -0.5f * vehicleExtents.z() + WHEEL_RADIUS);
m_vehicle->addWheel(connectionPoint, wheelDirection, wheelAxis, SUSPENSION_REST_LENGTH, WHEEL_RADIUS, m_tuning, false);
for (int i = 0; i < m_vehicle->getNumWheels(); i++) {
btWheelInfo& wheel = m_vehicle->getWheelInfo(i);
wheel.m_suspensionStiffness = SUSPENSION_STIFFNESS;
wheel.m_wheelsDampingRelaxation = SUSPENSION_DAMPING;
wheel.m_wheelsDampingCompression = SUSPENSION_COMPRESSION;
wheel.m_frictionSlip = WHEEL_FRICTION;
wheel.m_rollInfluence = ROLL_IN_INFLUENCE;
}
resetVehicle();
}
void Vehicle::stepSimulation(uint32_t frameTime) {
float speed = m_vehicle->getCurrentSpeedKmHour();
m_vehicleEngineForce = 0.0f;
m_vehicleBreakingForce = 0.0f;
/* --->
Processing input sets m_vehicleEngineForce, m_vehicleBreakingForce, m_vehicleSteering
<--- */
m_vehicle->applyEngineForce(m_vehicleEngineForce, 2);
m_vehicle->setBrake(m_vehicleBreakingForce, 2);
m_vehicle->applyEngineForce(m_vehicleEngineForce, 3);
m_vehicle->setBrake(m_vehicleBreakingForce, 3);
m_vehicle->setSteeringValue(m_vehicleSteering, 0);
m_vehicle->setSteeringValue(m_vehicleSteering, 1);
m_world->stepSimulation(frameTime * 0.001f, 2);
btMLCPSolver *solver = (btMLCPSolver *) m_world->getConstraintSolver();
int numFallbacks = solver->getNumFallbacks();
if (numFallbacks) {
std::cerr << "MLCP solver failed " << numFallbacks << " times, falling back to btSequentialImpulseSolver" << std::endl;
}
solver->setNumFallbacks(0);
}
Thank you