1
0
mirror of https://github.com/rwengine/openrw.git synced 2024-09-18 16:32:32 +02:00

Intial vehicle physics

This commit is contained in:
Daniel Evans 2013-09-15 01:42:35 +00:00
parent 22cb749073
commit d4064480d1
10 changed files with 259 additions and 41 deletions

View File

@ -6,25 +6,27 @@
GTACharacter::GTACharacter(GTAEngine* engine, const glm::vec3& pos, const glm::quat& rot, Model* model, std::shared_ptr<LoaderIDE::PEDS_t> ped)
: GTAObject(engine, pos, rot, model), ped(ped), currentActivity(None), controller(nullptr)
{
animator = new Animator();
animator->setModel(model);
// Don't create anything without a valid model.
if(model) {
animator = new Animator();
animator->setModel(model);
btTransform tf;
tf.setIdentity();
tf.setOrigin(btVector3(pos.x, pos.y, pos.z));
btTransform tf;
tf.setIdentity();
tf.setOrigin(btVector3(pos.x, pos.y, pos.z));
physObject = new btPairCachingGhostObject;
physObject->setWorldTransform(tf);
physShape = new btBoxShape(btVector3(0.25f, 0.25f, 1.f));
physObject->setCollisionShape(physShape);
physObject->setCollisionFlags(btCollisionObject::CF_CHARACTER_OBJECT);
physCharacter = new btKinematicCharacterController(physObject, physShape, 0.65f, 2);
physObject = new btPairCachingGhostObject;
physObject->setWorldTransform(tf);
physShape = new btBoxShape(btVector3(0.25f, 0.25f, 1.f));
physObject->setCollisionShape(physShape);
physObject->setCollisionFlags(btCollisionObject::CF_CHARACTER_OBJECT);
physCharacter = new btKinematicCharacterController(physObject, physShape, 0.65f, 2);
engine->dynamicsWorld->addCollisionObject(physObject, btBroadphaseProxy::CharacterFilter, btBroadphaseProxy::StaticFilter|btBroadphaseProxy::DefaultFilter);
engine->dynamicsWorld->addAction(physCharacter);
changeAction(Idle);
engine->dynamicsWorld->addCollisionObject(physObject, btBroadphaseProxy::CharacterFilter, btBroadphaseProxy::StaticFilter|btBroadphaseProxy::DefaultFilter);
engine->dynamicsWorld->addAction(physCharacter);
changeAction(Idle);
}
}
void GTACharacter::changeAction(Activity newAction)

View File

@ -88,6 +88,7 @@ void GTAData::load()
loadCarcols(datpath+"/data/carcols.dat");
loadWeather(datpath+"/data/timecyc.dat");
loadHandling(datpath+"/data/handling.cfg");
loadWaterpro(datpath+"/data/waterpro.dat");
loadWater(datpath+"/data/water.dat");
@ -279,6 +280,60 @@ void GTAData::loadWeather(const std::string &path)
weatherLoader.load(path);
}
void GTAData::loadHandling(const std::string& path)
{
std::ifstream hndFile(path.c_str());
if(! hndFile.is_open()) {
std::cerr << "Error loadind handling data " << path << std::endl;
return;
}
std::string lineBuff;
while(std::getline(hndFile, lineBuff)) {
if(lineBuff.at(0) == ';') continue;
std::stringstream ss(lineBuff);
VehicleHandlingInfo info;
ss >> info.ID;
ss >> info.mass;
ss >> info.dimensions.x;
ss >> info.dimensions.y;
ss >> info.dimensions.z;
ss >> info.centerOfMass.x;
ss >> info.centerOfMass.y;
ss >> info.centerOfMass.z;
ss >> info.percentSubmerged;
ss >> info.tractionMulti;
ss >> info.tractionLoss;
ss >> info.tractionBias;
ss >> info.numGears;
ss >> info.maxVelocity;
ss >> info.acceleration;
char dt, et;
ss >> dt; ss >> et;
info.driveType = (VehicleHandlingInfo::DriveType)dt;
info.engineType = (VehicleHandlingInfo::EngineType)et;
ss >> info.brakeDeceleration;
ss >> info.brakeBias;
ss >> info.ABS;
ss >> info.steeringLock;
ss >> info.suspensionForce;
ss >> info.suspensionDamping;
ss >> info.seatOffset;
ss >> info.damageMulti;
ss >> info.value;
ss >> info.suspensionUpperLimit;
ss >> info.suspensionLowerLimit;
ss >> info.suspensionBias;
ss >> std::hex >> info.flags;
vehicleInfo.insert({info.ID, {info}});
}
}
void GTAData::loadWaterpro(const std::string& path)
{
std::ifstream ifstr(path.c_str());

View File

@ -247,21 +247,23 @@ void GTAEngine::createVehicle(const uint16_t id, const glm::vec3& pos, const glm
}
}
Model* model = gameData.models[vti->second->modelName];
if(model) {
if( vti->second->wheelPositions.size() == 0 ) {
Model* model = gameData.models[vti->second->modelName];
auto info = gameData.vehicleInfo.find(vti->second->handlingID);
if(model && info != gameData.vehicleInfo.end()) {
if( info->second.wheels.size() == 0 ) {
for( size_t f = 0; f < model->frames.size(); ++f) {
if( model->frameNames.size() > f) {
std::string& name = model->frameNames[f];
if( name.substr(0, 5) == "wheel" ) {
vti->second->wheelPositions.push_back(model->frames[f].defaultTranslation);
auto frameTrans = model->getFrameMatrix(f);
info->second.wheels.push_back({glm::vec3(frameTrans[3])});
}
}
}
}
}
vehicleInstances.push_back(new GTAVehicle{ this, pos, rot, model, vti->second, prim, sec });
vehicleInstances.push_back(new GTAVehicle{ this, pos, rot, model, vti->second, info->second, prim, sec });
}
}
@ -283,10 +285,12 @@ GTACharacter* GTAEngine::createPedestrian(const uint16_t id, const glm::vec3 &po
Model* model = gameData.models[pt->modelName];
auto ped = new GTACharacter( this, pos, rot, model, pt );
pedestrians.push_back(ped);
new GTADefaultAIController(ped);
return ped;
if(model != nullptr) {
auto ped = new GTACharacter( this, pos, rot, model, pt );
pedestrians.push_back(ped);
new GTADefaultAIController(ped);
return ped;
}
}
return nullptr;
}

View File

@ -362,19 +362,21 @@ void GTARenderer::renderWorld()
matrixModel = glm::translate(matrixModel, inst->getPosition());
matrixModel = matrixModel * glm::mat4_cast(inst->getRotation());
glm::mat4 matrixVehicle = matrixModel;
renderModel(inst->model, matrixModel, inst);
// Draw wheels n' stuff
for( size_t w = 0; w < inst->vehicle->wheelPositions.size(); ++w) {
for( size_t w = 0; w < inst->info.wheels.size(); ++w) {
auto woi = engine->objectTypes.find(inst->vehicle->wheelModelID);
if(woi != engine->objectTypes.end()) {
Model* wheelModel = engine->gameData.models["wheels"];
if( wheelModel) {
glm::mat4 wheelMatrix = glm::translate(glm::mat4(), inst->vehicle->wheelPositions[w]);
wheelMatrix = glm::scale(wheelMatrix, glm::vec3(1.f, inst->vehicle->wheelScale, inst->vehicle->wheelScale));
renderNamedFrame(wheelModel, matrixVehicle * wheelMatrix, woi->second->modelName);
// Tell bullet to update the matrix for this wheel.
inst->physVehicle->updateWheelTransform(w, false);
glm::mat4 wheel_tf;
inst->physVehicle->getWheelTransformWS(w).getOpenGLMatrix(glm::value_ptr(wheel_tf));
wheel_tf = glm::scale(wheel_tf, glm::vec3(inst->vehicle->wheelScale));
wheel_tf = glm::rotate(wheel_tf, inst->physVehicle->getWheelInfo(w).m_rotation, glm::vec3(1.f, 0.f, 0.f));
renderNamedFrame(wheelModel, /*matrixVehicle **/ wheel_tf, woi->second->modelName);
}
else {
std::cout << "Wheel model " << woi->second->modelName << " not loaded" << std::endl;

View File

@ -1,8 +1,9 @@
#include <renderwure/objects/GTAVehicle.hpp>
#include <renderwure/engine/GTAEngine.hpp>
#include <BulletDynamics/Vehicle/btRaycastVehicle.h>
GTAVehicle::GTAVehicle(GTAEngine* engine, const glm::vec3& pos, const glm::quat& rot, Model* model, std::shared_ptr<LoaderIDE::CARS_t> veh, const glm::vec3& prim, const glm::vec3& sec)
: GTAObject(engine, pos, rot, model), vehicle(veh), colourPrimary(prim), colourSecondary(sec), physBody(nullptr)
GTAVehicle::GTAVehicle(GTAEngine* engine, const glm::vec3& pos, const glm::quat& rot, Model* model, std::shared_ptr<LoaderIDE::CARS_t> veh, const VehicleInfo& info, const glm::vec3& prim, const glm::vec3& sec)
: GTAObject(engine, pos, rot, model), vehicle(veh), info(info), colourPrimary(prim), colourSecondary(sec), physBody(nullptr), physVehicle(nullptr)
{
if(! veh->modelName.empty()) {
auto phyit = engine->gameData.collisions.find(veh->modelName);
@ -19,6 +20,8 @@ GTAVehicle::GTAVehicle(GTAEngine* engine, const glm::vec3& pos, const glm::quat&
));
CollisionInstance& physInst = *phyit->second.get();
btVector3 com(info.handling.centerOfMass.x, info.handling.centerOfMass.y, info.handling.centerOfMass.z);
// Boxes
for( size_t i = 0; i < physInst.boxes.size(); ++i ) {
CollTBox& box = physInst.boxes[i];
@ -54,12 +57,36 @@ GTAVehicle::GTAVehicle(GTAEngine* engine, const glm::vec3& pos, const glm::quat&
}
btVector3 inertia(0,0,0);
cmpShape->calculateLocalInertia(1000.f, inertia);
cmpShape->calculateLocalInertia(info.handling.mass, inertia);
btRigidBody::btRigidBodyConstructionInfo info(1000.f, msta, cmpShape, inertia);
btRigidBody::btRigidBodyConstructionInfo rginfo(info.handling.mass, msta, cmpShape, inertia);
physBody = new btRigidBody(info);
physBody = new btRigidBody(rginfo);
engine->dynamicsWorld->addRigidBody(physBody);
physRaycaster = new btDefaultVehicleRaycaster(engine->dynamicsWorld);
btRaycastVehicle::btVehicleTuning tuning;
float travel = info.handling.suspensionUpperLimit - info.handling.suspensionLowerLimit;
tuning.m_maxSuspensionTravelCm = (travel)*100.f;
tuning.m_frictionSlip = info.handling.tractionMulti * 10.f;
physVehicle = new btRaycastVehicle(tuning, physBody, physRaycaster);
physVehicle->setCoordinateSystem(0, 2, 1);
physBody->setActivationState(DISABLE_DEACTIVATION);
engine->dynamicsWorld->addVehicle(physVehicle);
for(size_t w = 0; w < info.wheels.size(); ++w) {
btVector3 connection(info.wheels[w].position.x, info.wheels[w].position.y, info.wheels[w].position.z);
bool front = connection.y() > 0;
btWheelInfo& wi = physVehicle->addWheel(connection, btVector3(0.f, 0.f, -1.f), btVector3(1.f, 0.f, 0.f), travel*0.45f, veh->wheelScale / 2.f, tuning, front);
wi.m_wheelsSuspensionForce = info.handling.mass * 1.5f;
wi.m_suspensionStiffness = 20.f;
wi.m_wheelsDampingRelaxation = 2.3;
wi.m_wheelsDampingCompression = 4.4f;
wi.m_frictionSlip = tuning.m_frictionSlip * (front ? info.handling.tractionBias : 1.f - info.handling.tractionBias);
}
}
}
}
@ -81,3 +108,22 @@ glm::quat GTAVehicle::getRotation() const
}
return rotation;
}
void GTAVehicle::tick(float dt)
{
if(physVehicle) {
for(size_t w = 0; w < physVehicle->getNumWheels(); ++w) {
btWheelInfo& wi = physVehicle->getWheelInfo(w);
if( info.handling.driveType == VehicleHandlingInfo::All ||
(info.handling.driveType == VehicleHandlingInfo::Forward && wi.m_bIsFrontWheel) ||
(info.handling.driveType == VehicleHandlingInfo::Rear && !wi.m_bIsFrontWheel))
{
physVehicle->applyEngineForce(info.handling.acceleration * info.handling.mass * 0.1f, w);
}
/*if(wi.m_bIsFrontWheel) {
physVehicle->setSteeringValue(info.handling.steeringLock*(3.141/180.f), w);
}*/
}
}
}

View File

@ -10,6 +10,7 @@
#include <renderwure/loaders/LoaderIFP.hpp>
#include <renderwure/loaders/WeatherLoader.hpp>
#include <renderwure/loaders/LoaderCOL.hpp>
#include <renderwure/objects/VehicleInfo.hpp>
#include <memory>
@ -94,6 +95,8 @@ public:
void loadCarcols(const std::string& path);
void loadWeather(const std::string& path);
void loadHandling(const std::string& path);
/**
* Loads water level data
@ -168,6 +171,11 @@ public:
* The vehicle colours for each vehicle type
*/
std::map<std::string, std::vector<std::pair<size_t,size_t>>> vehiclePalettes;
/**
* Vehicle information
*/
std::map<std::string, VehicleInfo> vehicleInfo;
/**
* Texture Loader

View File

@ -91,7 +91,6 @@ public:
int16_t modelLOD; // used only when type == PLANE
};
float wheelScale; // used only when type == CAR
std::vector<glm::vec3> wheelPositions;
};
struct PEDS_t

View File

@ -3,6 +3,7 @@
#define _GTAVEHICLE_HPP_
#include <renderwure/engine/GTAObject.hpp>
#include <bullet/btBulletDynamicsCommon.h>
#include <renderwure/objects/VehicleInfo.hpp>
/**
* @class GTAVehicle
@ -11,18 +12,30 @@
struct GTAVehicle : public GTAObject
{
std::shared_ptr<LoaderIDE::CARS_t> vehicle; /// Vehicle type
VehicleInfo info;
glm::vec3 colourPrimary;
glm::vec3 colourSecondary;
btRigidBody* physBody;
btVehicleRaycaster* physRaycaster;
btRaycastVehicle* physVehicle;
GTAVehicle(GTAEngine* engine, const glm::vec3& pos, const glm::quat& rot, Model* model, std::shared_ptr<LoaderIDE::CARS_t> veh, const glm::vec3& prim, const glm::vec3& sec);
GTAVehicle(GTAEngine* engine,
const glm::vec3& pos,
const glm::quat& rot,
Model* model,
std::shared_ptr<LoaderIDE::CARS_t> veh,
const VehicleInfo& info,
const glm::vec3& prim,
const glm::vec3& sec);
glm::vec3 getPosition() const;
glm::quat getRotation() const;
Type type() { return Vehicle; }
void tick(float dt);
};
#endif

View File

@ -0,0 +1,83 @@
#pragma once
#ifndef _VEHICLE_INFO_HPP_
#define _VEHICLE_INFO_HPP_
#include <string>
#include <vector>
#include <glm/glm.hpp>
struct VehicleHandlingInfo
{
enum EngineType
{
Diesel = 'D',
Petrol = 'P',
Electric = 'E'
};
enum DriveType
{
Forward = 'F',
Rear = 'R',
All = '4'
};
std::string ID;
float mass;
glm::vec3 dimensions;
glm::vec3 centerOfMass;
float percentSubmerged;
float tractionMulti;
float tractionLoss;
float tractionBias;
size_t numGears;
float maxVelocity;
float acceleration;
DriveType driveType;
EngineType engineType;
float brakeDeceleration;
float brakeBias;
bool ABS;
float steeringLock;
float suspensionForce;
float suspensionDamping;
float seatOffset;
float damageMulti;
size_t value;
float suspensionUpperLimit;
float suspensionLowerLimit;
float suspensionBias;
uint32_t flags;
enum /*VehicleFlags*/ {
VF_1G_BOOST = 1 << 0,
VF_2G_BOOST = 2 << 0,
VF_REV_BONNET = 4 << 0,
VF_HANGING_BOOT = 8 << 0,
VF_NO_DOORS = 1 << 8,
VF_IS_VAN = 2 << 8,
VF_IS_BUS = 4 << 8,
VF_IS_LOW = 8 << 8,
VF_DBL_EXHAUST = 1 << 16,
VF_TAILGATE_BOOT= 2 << 16,
VF_NOSWING_BOOT = 4 << 16,
VF_NONPLAYER_STABILIZER = 8 << 16,
VF_NEUTRALHANDLING = 1 << 16,
VF_HAS_NO_ROOF = 2 << 16,
VF_IS_BIG = 4 << 16,
VF_HALOGEN_LIGHTS = 8 << 16
};
};
struct WheelInfo
{
glm::vec3 position;
};
struct VehicleInfo
{
VehicleHandlingInfo handling;
std::vector<WheelInfo> wheels;
};
#endif

View File

@ -7,6 +7,7 @@
#include <renderwure/ai/GTAAIController.hpp>
#include <renderwure/ai/GTAPlayerAIController.hpp>
#include <renderwure/objects/GTACharacter.hpp>
#include <renderwure/objects/GTAVehicle.hpp>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
@ -97,17 +98,18 @@ void init(std::string gtapath)
plyPos = gta->itemCentroid / (float) gta->itemCount + glm::vec3(0, 0, 2);
glm::vec3 spawnPos = plyPos + glm::vec3(-5, -20, 0);
glm::vec3 spawnPos = plyPos + glm::vec3(-5, -20, 0.0);
size_t k = 1;
// Spawn every vehicle, cause why not.
for(std::map<uint16_t, std::shared_ptr<LoaderIDE::CARS_t>>::iterator it = gta->vehicleTypes.begin();
it != gta->vehicleTypes.end(); ++it) {
if(it->first == 140) continue; // get this plane out of here.
gta->createVehicle(it->first, spawnPos);
spawnPos += glm::vec3(5, 0, 0);
if((k++ % 4) == 0) { spawnPos += glm::vec3(-20, -15, 0); }
}
spawnPos = plyPos + glm::vec3(-5, 20 + (2.5 * gta->pedestrianTypes.size()/4), 0);
spawnPos = plyPos + glm::vec3(-5, 20 + (2.5 * gta->pedestrianTypes.size()/4), 0);
k = 1;
// Spawn every pedestrian.
for(auto it = gta->pedestrianTypes.begin();
@ -193,10 +195,14 @@ void update(float dt)
gta->renderer.camera.worldPos = plyPos;
gta->renderer.camera.frustum.view = view;
// TODO: move this inside the engine
for( size_t p = 0; p < gta->pedestrians.size(); ++p ) {
gta->pedestrians[p]->tick(dt);
}
for( size_t v = 0; v < gta->vehicleInstances.size(); ++v ) {
gta->vehicleInstances[v]->tick(dt);
}
gta->dynamicsWorld->stepSimulation(dt);
}
}
@ -327,7 +333,7 @@ int main(int argc, char *argv[])
while (window.pollEvent(event)) {
handleEvent(event);
}
accum += clock.restart().asSeconds();
while ( accum >= ts ) {