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

Improve vehicle dynamics

This commit is contained in:
Daniel Evans 2014-06-07 04:11:20 +01:00
parent 891b12272c
commit b2e1c0fad2
4 changed files with 95 additions and 18 deletions

View File

@ -105,4 +105,19 @@ public:
virtual bool isFrameVisible(ModelFrame *frame) const;
};
/**
* Implements vehicle ray casting behaviour.
* i.e. ignore the god damn vehicle body when casting rays.
*/
class VehicleRaycaster : public btVehicleRaycaster
{
btDynamicsWorld* _world;
VehicleObject* _vehicle;
public:
VehicleRaycaster(VehicleObject* vehicle, btDynamicsWorld* world)
: _world(world), _vehicle(vehicle) {}
void* castRay(const btVector3 &from, const btVector3 &to, btVehicleRaycasterResult &result);
};
#endif

View File

@ -37,7 +37,7 @@ VehicleObject::VehicleObject(GameWorld* engine, const glm::vec3& pos, const glm:
auto mid = (box.min + box.max) / 2.f;
btCollisionShape* bshape = new btBoxShape( btVector3(size.x, size.y, size.z) );
btTransform t; t.setIdentity();
t.setOrigin(btVector3(mid.x, mid.y, mid.z) + com);
t.setOrigin(btVector3(mid.x, mid.y, mid.z));
cmpShape->addChildShape(t, bshape);
}
@ -46,11 +46,11 @@ VehicleObject::VehicleObject(GameWorld* engine, const glm::vec3& pos, const glm:
auto& sphere = physInst.spheres[i];
btCollisionShape* sshape = new btSphereShape(sphere.radius);
btTransform t; t.setIdentity();
t.setOrigin(btVector3(sphere.center.x, sphere.center.y, sphere.center.z) + com);
t.setOrigin(btVector3(sphere.center.x, sphere.center.y, sphere.center.z));
cmpShape->addChildShape(t, sshape);
}
if( physInst.vertices.size() > 0 && physInst.indices.size() >= 3 ) {
if( false && physInst.vertices.size() > 0 && physInst.indices.size() >= 3 ) {
btTriangleIndexVertexArray* vertarray = new btTriangleIndexVertexArray(
physInst.indices.size()/3,
(int*) physInst.indices.data(),
@ -59,7 +59,8 @@ VehicleObject::VehicleObject(GameWorld* engine, const glm::vec3& pos, const glm:
&(physInst.vertices[0].x),
sizeof(glm::vec3));
btBvhTriangleMeshShape* trishape = new btBvhTriangleMeshShape(vertarray, false);
btTransform t; t.setIdentity();
btTransform t;
t.setOrigin(com);
cmpShape->addChildShape(t,trishape);
}
@ -72,10 +73,10 @@ VehicleObject::VehicleObject(GameWorld* engine, const glm::vec3& pos, const glm:
physBody->setUserPointer(this);
engine->dynamicsWorld->addRigidBody(physBody);
physRaycaster = new btDefaultVehicleRaycaster(engine->dynamicsWorld);
physRaycaster = new VehicleRaycaster(this, engine->dynamicsWorld);
btRaycastVehicle::btVehicleTuning tuning;
float travel = info->handling.suspensionUpperLimit - info->handling.suspensionLowerLimit;
float travel = fabs(info->handling.suspensionUpperLimit - info->handling.suspensionLowerLimit);
tuning.m_frictionSlip = 1.8f;
tuning.m_maxSuspensionTravelCm = travel * 100.f;
@ -88,13 +89,25 @@ VehicleObject::VehicleObject(GameWorld* engine, const glm::vec3& pos, const glm:
float kR = 0.6f;
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 - info->handling.suspensionLowerLimit);
auto restLength = travel;
auto heightOffset = info->handling.suspensionUpperLimit;
btVector3 connection(
info->wheels[w].position.x,
info->wheels[w].position.y,
info->wheels[w].position.z + heightOffset );
bool front = connection.y() > 0;
btWheelInfo& wi = physVehicle->addWheel(connection + com, btVector3(0.f, 0.f, -1.f), btVector3(1.f, 0.f, 0.f), travel, data->wheelScale / 2.f, tuning, front);
wi.m_suspensionStiffness = info->handling.suspensionForce * 10.f;
btWheelInfo& wi = physVehicle->addWheel(connection, btVector3(0.f, 0.f, -1.f), btVector3(1.f, 0.f, 0.f), restLength, data->wheelScale / 2.f, tuning, front);
wi.m_suspensionRestLength1 = restLength;
wi.m_maxSuspensionForce = 100000.f;
wi.m_suspensionStiffness = (info->handling.suspensionForce * 10.f);
//float dampEffect = (info->handling.suspensionDamping) / travel;
//wi.m_wheelsDampingCompression = wi.m_wheelsDampingRelaxation = dampEffect;
wi.m_wheelsDampingCompression = kC * 2.f * btSqrt(wi.m_suspensionStiffness);
wi.m_wheelsDampingRelaxation = kR * 2.f * btSqrt(wi.m_suspensionStiffness);
wi.m_rollInfluence = 0.2f;
wi.m_rollInfluence = 0.0f;
wi.m_frictionSlip = tuning.m_frictionSlip * (front ? info->handling.tractionBias : 1.f - info->handling.tractionBias);
}
@ -125,22 +138,24 @@ void VehicleObject::setPosition(const glm::vec3& pos)
glm::vec3 VehicleObject::getPosition() const
{
if(physBody) {
btVector3 Pos = physBody->getWorldTransform().getOrigin();
return glm::vec3(Pos.x(), Pos.y(), Pos.z()) + info->handling.centerOfMass;
if(physVehicle) {
btVector3 Pos = physVehicle->getChassisWorldTransform().getOrigin();
return glm::vec3(Pos.x(), Pos.y(), Pos.z());
}
return position;
}
glm::quat VehicleObject::getRotation() const
{
if(physBody) {
btQuaternion rot = physBody->getWorldTransform().getRotation();
if(physVehicle) {
btQuaternion rot = physVehicle->getChassisWorldTransform().getRotation();
return glm::quat(rot.w(), rot.x(), rot.y(), rot.z());
}
return rotation;
}
#include <glm/gtc/type_ptr.hpp>
void VehicleObject::tick(float dt)
{
if(physVehicle) {
@ -298,3 +313,42 @@ bool VehicleObject::isFrameVisible(ModelFrame *frame) const
return true;
}
// Dammnit Bullet
class ClosestNotMeRayResultCallback : public btCollisionWorld::ClosestRayResultCallback
{
btCollisionObject* _self;
public:
ClosestNotMeRayResultCallback( btCollisionObject* self, const btVector3& from, const btVector3& to )
: ClosestRayResultCallback( from, to ), _self( self ) {}
virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult &rayResult, bool normalInWorldSpace)
{
if( rayResult.m_collisionObject == _self ) {
return 1.0;
}
return ClosestRayResultCallback::addSingleResult( rayResult, normalInWorldSpace );
}
};
void *VehicleRaycaster::castRay(const btVector3 &from, const btVector3 &to, btVehicleRaycaster::btVehicleRaycasterResult &result)
{
ClosestNotMeRayResultCallback rayCallback( _vehicle->physBody, from, to );
_world->rayTest(from, to, rayCallback);
if( rayCallback.hasHit() ) {
const btRigidBody* body = btRigidBody::upcast( rayCallback.m_collisionObject );
if( body && body->hasContactResponse() ) {
result.m_hitPointInWorld = rayCallback.m_hitPointWorld;
result.m_hitNormalInWorld = rayCallback.m_hitNormalWorld;
result.m_hitNormalInWorld.normalize();
result.m_distFraction = rayCallback.m_closestHitFraction;
return (void*) body;
}
}
return 0;
}

View File

@ -340,7 +340,7 @@ void GameRenderer::renderWorld(float alpha)
auto woi = engine->objectTypes.find(inst->vehicle->wheelModelID);
if(woi != engine->objectTypes.end()) {
Model* wheelModel = engine->gameData.models["wheels"]->model;
if( wheelModel) {
if( wheelModel ) {
// Tell bullet to update the matrix for this wheel.
inst->physVehicle->updateWheelTransform(w, false);
glm::mat4 wheel_tf;
@ -349,7 +349,7 @@ void GameRenderer::renderWorld(float alpha)
if(inst->physVehicle->getWheelInfo(w).m_chassisConnectionPointCS.x() < 0.f) {
wheel_tf = glm::scale(wheel_tf, glm::vec3(-1.f, 1.f, 1.f));
}
renderWheel(wheelModel, /*matrixVehicle **/ wheel_tf, woi->second->modelName);
renderWheel(wheelModel, wheel_tf, woi->second->modelName);
}
else {
std::cout << "Wheel model " << woi->second->modelName << " not loaded" << std::endl;

View File

@ -9,10 +9,18 @@
IngameState::IngameState()
: _player(nullptr), _playerCharacter(nullptr)
{
_playerCharacter = getWorld()->createPedestrian(1, {100.f, 100.f, 25.f});
_playerCharacter = getWorld()->createPedestrian(1, {-1240.f, -875.f, 13.f});
_player = new PlayerController(_playerCharacter);
setPlayerCharacter( _playerCharacter );
float j = 0;
auto spawnPos = glm::vec3( -1200.f, -885.f, 14.f );
for( auto& vi : getWorld()->vehicleTypes ) {
auto v = getWorld()->createVehicle(vi.first, spawnPos, glm::quat());
spawnPos -= glm::vec3( 2.f + v->info->handling.dimensions.x, 0.f, 0.f);
if( ++j > 33 ) break;
}
}
void IngameState::spawnPlayerVehicle()