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

Improve vehicle door dynamics

+ Vehicle doors should move in the right direction now
+ Fix debugging draw class for bullet
This commit is contained in:
Daniel Evans 2015-01-22 20:16:28 +00:00
parent 3f40ba0e18
commit 4ea6e14299
8 changed files with 150 additions and 90 deletions

View File

@ -40,6 +40,8 @@ public:
btHingeConstraint* constraint; btHingeConstraint* constraint;
bool holdAngle; bool holdAngle;
float targetAngle; float targetAngle;
float openAngle;
float closedAngle;
}; };
std::map<std::string, Part> dynamicParts; std::map<std::string, Part> dynamicParts;

View File

@ -1,11 +1,8 @@
#pragma once #pragma once
#include <LinearMath/btIDebugDraw.h> #include <LinearMath/btIDebugDraw.h>
#include <render/GameRenderer.hpp>
#define GLEW_STATIC #include "Model.hpp"
#include <GL/glew.h>
#include <vector>
#include <glm/glm.hpp>
class DebugDraw : public btIDebugDraw class DebugDraw : public btIDebugDraw
{ {
@ -21,21 +18,21 @@ public:
void setDebugMode(int debugMode); void setDebugMode(int debugMode);
int getDebugMode() const; int getDebugMode() const;
void drawAllLines(); void flush(GameRenderer* renderer);
void setShaderProgram(GLuint shaderProgram) { void setShaderProgram(Renderer::ShaderProgram* shaderProgram) {
this->shaderProgram = shaderProgram; this->shaderProgram = shaderProgram;
} }
protected: protected:
int debugMode; int debugMode;
std::vector<glm::vec3> lines; std::vector<Model::GeometryVertex> lines;
size_t maxlines; size_t maxlines;
GeometryBuffer* lineBuff;
DrawBuffer* dbuff;
btVector3 color; Renderer::ShaderProgram* shaderProgram;
GLuint shaderProgram; GLuint texture;
GLuint vbo, vao, texture;
}; };

View File

@ -1,8 +1,11 @@
#include <ai/CharacterController.hpp> #include <ai/CharacterController.hpp>
#include <objects/CharacterObject.hpp> #include <objects/CharacterObject.hpp>
#include <objects/VehicleObject.hpp> #include <objects/VehicleObject.hpp>
#include <render/Model.hpp>
#include <engine/Animator.hpp> #include <engine/Animator.hpp>
#include <items/WeaponItem.hpp> #include <items/WeaponItem.hpp>
#include <boost/concept_check.hpp>
bool CharacterController::updateActivity() bool CharacterController::updateActivity()
{ {
@ -69,6 +72,22 @@ void CharacterController::update(float dt)
if( _currentActivity == nullptr ) { if( _currentActivity == nullptr ) {
/// @todo play _low variant if car has low flag. /// @todo play _low variant if car has low flag.
character->playAnimation(character->animations.car_sit, true); character->playAnimation(character->animations.car_sit, true);
// If character is idle in vehicle, close door.
if( glm::length( d ) <= 0.1f )
{
auto entryDoor = character->getCurrentVehicle()->getSeatEntryDoor(character->getCurrentSeat());
if( entryDoor && entryDoor->constraint )
{
character->getCurrentVehicle()->setPartTarget(entryDoor, true, entryDoor->closedAngle);
}
}
else
{
auto entryDoor = character->getCurrentVehicle()->getSeatEntryDoor(character->getCurrentSeat());
entryDoor->holdAngle = false;
}
} }
} }
else { else {
@ -242,7 +261,7 @@ bool Activities::EnterVehicle::update(CharacterObject *character, CharacterContr
} }
else if( entryDoor && character->animator->getAnimationTime() >= 0.5f ) else if( entryDoor && character->animator->getAnimationTime() >= 0.5f )
{ {
vehicle->setPartTarget(entryDoor, true, 1.f); vehicle->setPartTarget(entryDoor, true, entryDoor->openAngle);
} }
else { else {
//character->setPosition(vehicle->getSeatEntryPosition(seat)); //character->setPosition(vehicle->getSeatEntryPosition(seat));
@ -251,11 +270,6 @@ bool Activities::EnterVehicle::update(CharacterObject *character, CharacterContr
} }
else if( character->animator->getAnimation() == anm_enter ) { else if( character->animator->getAnimation() == anm_enter ) {
if( character->animator->isCompleted() ) { if( character->animator->isCompleted() ) {
if( entryDoor )
{
vehicle->setPartTarget(entryDoor, true, 0.f);
}
// VehicleGetIn is over, finish activity // VehicleGetIn is over, finish activity
return true; return true;
} }
@ -275,7 +289,7 @@ bool Activities::EnterVehicle::update(CharacterObject *character, CharacterContr
character->rotation = vehicle->getRotation(); character->rotation = vehicle->getRotation();
// Determine if the door open animation should be skipped. // Determine if the door open animation should be skipped.
if( entryDoor == nullptr || (entryDoor->constraint != nullptr && entryDoor->constraint->getHingeAngle() >= 0.6f ) ) if( entryDoor == nullptr || (entryDoor->constraint != nullptr && glm::abs(entryDoor->constraint->getHingeAngle()) >= 0.6f ) )
{ {
character->playAnimation(anm_enter, false); character->playAnimation(anm_enter, false);
character->enterVehicle(vehicle, seat); character->enterVehicle(vehicle, seat);
@ -329,7 +343,7 @@ bool Activities::ExitVehicle::update(CharacterObject *character, CharacterContro
auto door = vehicle->getSeatEntryDoor(character->getCurrentSeat()); auto door = vehicle->getSeatEntryDoor(character->getCurrentSeat());
if( door ) if( door )
{ {
vehicle->setPartTarget(door, true, 1.f); vehicle->setPartTarget(door, true, door->openAngle);
} }
} }

View File

@ -159,7 +159,7 @@ GLuint createTexture(RW::BSTextureNative& texNative, RW::BinaryStreamSection& ro
break; break;
} }
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, texFilter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, texFilter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, texFilter);
GLenum texwrap = GL_REPEAT; GLenum texwrap = GL_REPEAT;

View File

@ -8,7 +8,7 @@
#include <render/Model.hpp> #include <render/Model.hpp>
#include <engine/Animator.hpp> #include <engine/Animator.hpp>
#define PART_CLOSE_VELOCITY 0.5f #define PART_CLOSE_VELOCITY 0.25f
VehicleObject::VehicleObject(GameWorld* engine, const glm::vec3& pos, const glm::quat& rot, ModelHandle* model, VehicleDataHandle data, VehicleInfoHandle info, const glm::u8vec3& prim, const glm::u8vec3& sec) VehicleObject::VehicleObject(GameWorld* engine, const glm::vec3& pos, const glm::quat& rot, ModelHandle* model, VehicleDataHandle data, VehicleInfoHandle info, const glm::u8vec3& prim, const glm::u8vec3& sec)
: GameObject(engine, pos, rot, model), : GameObject(engine, pos, rot, model),
@ -297,25 +297,30 @@ void VehicleObject::tickPhysics(float dt)
if(it.second.body == nullptr) continue; if(it.second.body == nullptr) continue;
auto inv = glm::inverse(getRotation()); auto inv = glm::inverse(getRotation());
auto rot = it.second.body->getWorldTransform().getRotation(); auto rot = it.second.body->getWorldTransform().getRotation();
auto pos = it.second.body->getWorldTransform().getOrigin();
auto r2 = inv * glm::quat(rot.w(), rot.x(), rot.y(), rot.z()); auto r2 = inv * glm::quat(rot.w(), rot.x(), rot.y(), rot.z());
//auto p2 = inv * (glm::vec3(pos.x(), pos.y(), pos.z()) - getPosition());
auto& prev = skeleton->getData(it.second.dummy->getIndex()).a; auto& prev = skeleton->getData(it.second.dummy->getIndex()).a;
auto next = prev; auto next = prev;
next.rotation = r2; next.rotation = r2;
//next.translation = p2;
skeleton->setData(it.second.dummy->getIndex(), { next, prev, true } ); skeleton->setData(it.second.dummy->getIndex(), { next, prev, true } );
if( it.second.holdAngle ) if( it.second.holdAngle )
{ {
it.second.constraint->setMotorTarget(it.second.targetAngle, 0.1f); it.second.constraint->setMotorTarget(it.second.targetAngle, 0.1f);
} }
it.second.constraint->enableMotor( it.second.holdAngle );
// If the part is moving quite fast and near the limit, lock it. // If the part is moving quite fast and near the limit, lock it.
/// @TODO not all parts rotate in the z axis. /// @TODO not all parts rotate in the z axis.
if(it.second.body->getAngularVelocity().getZ() >= PART_CLOSE_VELOCITY) if(it.second.body->getAngularVelocity().getZ() >= PART_CLOSE_VELOCITY)
{ {
auto d = it.second.constraint->getHingeAngle() - it.second.constraint->getLowerLimit(); auto d = it.second.constraint->getHingeAngle() - it.second.closedAngle;
if( std::abs(d) < 0.01f ) if( std::abs(d) < 0.05f )
{ {
it.second.holdAngle = false;
setPartLocked(&(it.second), true); setPartLocked(&(it.second), true);
} }
} }
@ -602,19 +607,28 @@ void VehicleObject::createObjectHinge(btTransform& local, Part *part)
auto& geom = model->model->geometries[okframe->getGeometries()[0]]; auto& geom = model->model->geometries[okframe->getGeometries()[0]];
auto gbounds = geom->geometryBounds; auto gbounds = geom->geometryBounds;
if( fn.find("door") != fn.npos ) { if( fn.find("door") != fn.npos ) {
hingeAxis = {0.f, 0.f, 1.f}; hingeAxis = {0.f, 0.f, 1.f};
hingePosition = {0.f, 0.2f, 0.f}; //hingePosition = {0.f, 0.2f, 0.f};
boxSize = {0.1f, 0.4f, gbounds.radius/2.f}; boxSize = {0.15f, 0.5f, 0.6f};
boxOffset = {0.f,-0.2f, gbounds.center.z/2.f}; //boxOffset = {0.f,-0.2f, gbounds.center.z/2.f};
if( sign > 0.f ) { auto tf = gbounds.center;
hingeMin = -glm::quarter_pi<float>() * 1.5f; boxOffset = btVector3(tf.x, tf.y, tf.z);
hingeMax = 0.f; hingePosition = -boxOffset;
}
else { if( sign < 0.f ) {
hingeMax = glm::quarter_pi<float>() * 1.5f; hingeMax = glm::quarter_pi<float>() * 1.5f;
hingeMin = 0.f; hingeMin = 0.f;
part->openAngle = hingeMax;
part->closedAngle = hingeMin;
}
else
{
hingeMin = glm::quarter_pi<float>() * -1.5f;
hingeMax = 0.f;
part->openAngle = hingeMin;
part->closedAngle = hingeMax;
} }
} }
else if( fn.find("bonnet") != fn.npos ) { else if( fn.find("bonnet") != fn.npos ) {
@ -637,14 +651,11 @@ void VehicleObject::createObjectHinge(btTransform& local, Part *part)
auto o = glm::toQuat(part->dummy->getDefaultRotation()); auto o = glm::toQuat(part->dummy->getDefaultRotation());
tr.setOrigin(btVector3(p.x, p.y, p.z)); tr.setOrigin(btVector3(p.x, p.y, p.z));
tr.setRotation(btQuaternion(o.x, o.y, o.z, o.w)); tr.setRotation(btQuaternion(o.x, o.y, o.z, o.w));
dms->setWorldTransform(local * tr); dms->setWorldTransform(local * tr);
btCompoundShape* cs = new btCompoundShape; btCollisionShape* cs = new btBoxShape( boxSize );
btCollisionShape* bshape = new btBoxShape( boxSize );
btTransform t; t.setIdentity(); btTransform t; t.setIdentity();
t.setOrigin(boxOffset); t.setOrigin(boxOffset);
cs->addChildShape(t, bshape);
btVector3 inertia; btVector3 inertia;
cs->calculateLocalInertia(10.f, inertia); cs->calculateLocalInertia(10.f, inertia);
@ -659,9 +670,10 @@ void VehicleObject::createObjectHinge(btTransform& local, Part *part)
tr.getOrigin(), hingePosition, tr.getOrigin(), hingePosition,
hingeAxis, hingeAxis); hingeAxis, hingeAxis);
hinge->setLimit(hingeMin, hingeMax); hinge->setLimit(hingeMin, hingeMax);
hinge->setBreakingImpulseThreshold(250.f);
//engine->dynamicsWorld->addRigidBody(subObject);
//engine->dynamicsWorld->addConstraint(hinge, true); engine->dynamicsWorld->addRigidBody(subObject);
engine->dynamicsWorld->addConstraint(hinge, true);
part->body = subObject; part->body = subObject;
part->constraint = hinge; part->constraint = hinge;

View File

@ -10,25 +10,48 @@
#include <iostream> #include <iostream>
DebugDraw::DebugDraw() DebugDraw::DebugDraw()
: shaderProgram(nullptr)
{ {
glGenBuffers(1, &vbo); lineBuff = new GeometryBuffer;
glGenVertexArrays(1, &vao); dbuff = new DrawBuffer;
dbuff->setFaceType(GL_LINES);
glGenTextures(1, &texture); glGenTextures(1, &texture);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
int img = 0xFFFFFFFF;
glTexImage2D(
GL_TEXTURE_2D, 0, GL_RGBA, 1, 1,
0, GL_RGBA, GL_UNSIGNED_BYTE, &img
);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
maxlines = 0; maxlines = 0;
} }
DebugDraw::~DebugDraw() DebugDraw::~DebugDraw()
{ {
glDeleteBuffers(1, &vbo); delete dbuff;
glDeleteVertexArrays(1, &vbo); delete lineBuff;
glDeleteTextures(1, &texture);
} }
void DebugDraw::drawLine(const btVector3 &from, const btVector3 &to, const btVector3 &color) void DebugDraw::drawLine(const btVector3 &from, const btVector3 &to, const btVector3 &color)
{ {
lines.push_back(glm::vec3(from.getX(), from.getY(), from.getZ())); btVector3 c = color * 255;
lines.push_back(glm::vec3(to.getX(), to.getY(), to.getZ())); lines.push_back({
this->color = color; glm::vec3(from.getX(), from.getY(), from.getZ()),
glm::vec3(0.f),
glm::vec2(0.f),
glm::u8vec4(c.getX(), c.getY(), c.getZ(), 255)
});
lines.push_back({
glm::vec3(to.getX(), to.getY(), to.getZ()),
glm::vec3(0.f),
glm::vec2(0.f),
glm::u8vec4(c.getX(), c.getY(), c.getZ(), 255)
});
} }
void DebugDraw::drawTriangle(const btVector3 &a, const btVector3 &b, const btVector3 &c, const btVector3 &color, btScalar alpha) void DebugDraw::drawTriangle(const btVector3 &a, const btVector3 &b, const btVector3 &c, const btVector3 &color, btScalar alpha)
@ -72,48 +95,35 @@ void DebugDraw::drawContactPoint(const btVector3 &pointOnB, const btVector3 &nor
} }
void DebugDraw::drawAllLines() void DebugDraw::flush(GameRenderer* renderer)
{ {
if(lines.size() == 0) { if(lines.size() == 0) {
return; return;
} }
renderer->getRenderer()->useProgram(shaderProgram);
lineBuff->uploadVertices(lines);
dbuff->addGeometry(lineBuff);
glActiveTexture(GL_TEXTURE0); Renderer::DrawParameters dp;
glBindTexture(GL_TEXTURE_2D, texture); dp.texture = texture;
glActiveTexture(GL_TEXTURE0); dp.ambient = 1.f;
glBindTexture(GL_TEXTURE_2D, texture); dp.colour = glm::u8vec4(255, 255, 255, 255);
float img[] = {color.getX(), color.getY(), color.getZ()}; dp.start = 0;
glTexImage2D( dp.count = lines.size();
GL_TEXTURE_2D, 0, GL_RGB, 1, 1, dp.diffuse = 1.f;
0, GL_RGB, GL_FLOAT, img
); renderer->getRenderer()->drawArrays(glm::mat4(1.f), dbuff, dp);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); renderer->getRenderer()->invalidate();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glUseProgram(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray( 0 );
GLint posAttrib = glGetAttribLocation(shaderProgram, "position"); lines.clear();
GLint uniModel = glGetUniformLocation(shaderProgram, "model");
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
if( lines.size() > maxlines ) {
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * lines.size(), &lines[0].x, GL_STREAM_DRAW);
}
else {
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(glm::vec3) * lines.size(), &lines[0].x);
}
maxlines = std::max(maxlines, lines.size());
glEnableVertexAttribArray(posAttrib);
glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 0, 0);
glm::mat4 model;
glUniformMatrix4fv(uniModel, 1, GL_FALSE, glm::value_ptr(model));
glDrawArrays(GL_LINES, 0, lines.size());
lines.clear();
} }
void DebugDraw::reportErrorWarning(const char *warningString) void DebugDraw::reportErrorWarning(const char *warningString)

View File

@ -212,7 +212,6 @@ void OpenGLRenderer::draw(const glm::mat4& model, DrawBuffer* draw, const Render
void OpenGLRenderer::drawArrays(const glm::mat4& model, DrawBuffer* draw, const Renderer::DrawParameters& p) void OpenGLRenderer::drawArrays(const glm::mat4& model, DrawBuffer* draw, const Renderer::DrawParameters& p)
{ {
useDrawBuffer(draw); useDrawBuffer(draw);
useTexture(p.texture); useTexture(p.texture);

View File

@ -5,10 +5,15 @@
#include <engine/GameObject.hpp> #include <engine/GameObject.hpp>
#include <engine/GameState.hpp> #include <engine/GameState.hpp>
#include <render/GameRenderer.hpp> #include <render/GameRenderer.hpp>
#include <render/DebugDraw.hpp>
#include <script/ScriptMachine.hpp> #include <script/ScriptMachine.hpp>
#include <data/CutsceneData.hpp> #include <data/CutsceneData.hpp>
#include <ai/PlayerController.hpp> #include <ai/PlayerController.hpp>
#include <objects/CharacterObject.hpp>
#include <objects/VehicleObject.hpp>
DebugDraw* debug;
RWGame::RWGame(const std::string& gamepath) RWGame::RWGame(const std::string& gamepath)
: engine(nullptr), inFocus(true), : engine(nullptr), inFocus(true),
@ -38,6 +43,9 @@ RWGame::RWGame(const std::string& gamepath)
/// @TODO expand this here. /// @TODO expand this here.
engine->load(); engine->load();
debug = new DebugDraw;
debug->setDebugMode(btIDebugDraw::DBG_DrawWireframe | btIDebugDraw::DBG_DrawConstraints | btIDebugDraw::DBG_DrawConstraintLimits);
engine->dynamicsWorld->setDebugDrawer(debug);
engine->gameData.loadDynamicObjects(gamepath + "/data/object.dat"); engine->gameData.loadDynamicObjects(gamepath + "/data/object.dat");
@ -212,7 +220,25 @@ void RWGame::render(float alpha)
glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT); glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);
engine->renderer.renderWorld(viewCam, alpha); engine->renderer.renderWorld(viewCam, alpha);
debug->setShaderProgram(engine->renderer.worldProg);
if( engine->state.player )
{
if( engine->state.player->getCharacter()->getCurrentVehicle() )
{
auto v = engine->state.player->getCharacter()->getCurrentVehicle();
for( auto& p : v->dynamicParts )
{
if( p.second.body )
{
engine->dynamicsWorld->debugDrawObject(p.second.body->getWorldTransform(), p.second.body->getCollisionShape(), btVector3(1.f, 0.f, 0.f));
engine->dynamicsWorld->debugDrawConstraint(p.second.constraint);
}
}
}
}
debug->flush(&engine->renderer);
window.resetGLStates(); window.resetGLStates();
std::stringstream ss; std::stringstream ss;