1
0
mirror of https://github.com/rwengine/openrw.git synced 2024-09-03 17:19:46 +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;
bool holdAngle;
float targetAngle;
float openAngle;
float closedAngle;
};
std::map<std::string, Part> dynamicParts;

View File

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

View File

@ -1,8 +1,11 @@
#include <ai/CharacterController.hpp>
#include <objects/CharacterObject.hpp>
#include <objects/VehicleObject.hpp>
#include <render/Model.hpp>
#include <engine/Animator.hpp>
#include <items/WeaponItem.hpp>
#include <boost/concept_check.hpp>
bool CharacterController::updateActivity()
{
@ -69,6 +72,22 @@ void CharacterController::update(float dt)
if( _currentActivity == nullptr ) {
/// @todo play _low variant if car has low flag.
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 {
@ -242,7 +261,7 @@ bool Activities::EnterVehicle::update(CharacterObject *character, CharacterContr
}
else if( entryDoor && character->animator->getAnimationTime() >= 0.5f )
{
vehicle->setPartTarget(entryDoor, true, 1.f);
vehicle->setPartTarget(entryDoor, true, entryDoor->openAngle);
}
else {
//character->setPosition(vehicle->getSeatEntryPosition(seat));
@ -251,11 +270,6 @@ bool Activities::EnterVehicle::update(CharacterObject *character, CharacterContr
}
else if( character->animator->getAnimation() == anm_enter ) {
if( character->animator->isCompleted() ) {
if( entryDoor )
{
vehicle->setPartTarget(entryDoor, true, 0.f);
}
// VehicleGetIn is over, finish activity
return true;
}
@ -275,7 +289,7 @@ bool Activities::EnterVehicle::update(CharacterObject *character, CharacterContr
character->rotation = vehicle->getRotation();
// 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->enterVehicle(vehicle, seat);
@ -329,7 +343,7 @@ bool Activities::ExitVehicle::update(CharacterObject *character, CharacterContro
auto door = vehicle->getSeatEntryDoor(character->getCurrentSeat());
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;
}
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);
GLenum texwrap = GL_REPEAT;

View File

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

View File

@ -10,25 +10,48 @@
#include <iostream>
DebugDraw::DebugDraw()
: shaderProgram(nullptr)
{
glGenBuffers(1, &vbo);
glGenVertexArrays(1, &vao);
lineBuff = new GeometryBuffer;
dbuff = new DrawBuffer;
dbuff->setFaceType(GL_LINES);
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;
}
DebugDraw::~DebugDraw()
{
glDeleteBuffers(1, &vbo);
glDeleteVertexArrays(1, &vbo);
glDeleteTextures(1, &texture);
delete dbuff;
delete lineBuff;
}
void DebugDraw::drawLine(const btVector3 &from, const btVector3 &to, const btVector3 &color)
{
lines.push_back(glm::vec3(from.getX(), from.getY(), from.getZ()));
lines.push_back(glm::vec3(to.getX(), to.getY(), to.getZ()));
this->color = color;
btVector3 c = color * 255;
lines.push_back({
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)
@ -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) {
return;
}
if(lines.size() == 0) {
return;
}
renderer->getRenderer()->useProgram(shaderProgram);
lineBuff->uploadVertices(lines);
dbuff->addGeometry(lineBuff);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
float img[] = {color.getX(), color.getY(), color.getZ()};
glTexImage2D(
GL_TEXTURE_2D, 0, GL_RGB, 1, 1,
0, GL_RGB, GL_FLOAT, img
);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
Renderer::DrawParameters dp;
dp.texture = texture;
dp.ambient = 1.f;
dp.colour = glm::u8vec4(255, 255, 255, 255);
dp.start = 0;
dp.count = lines.size();
dp.diffuse = 1.f;
renderer->getRenderer()->drawArrays(glm::mat4(1.f), dbuff, dp);
renderer->getRenderer()->invalidate();
glUseProgram(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray( 0 );
GLint posAttrib = glGetAttribLocation(shaderProgram, "position");
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();
lines.clear();
}
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)
{
useDrawBuffer(draw);
useTexture(p.texture);

View File

@ -5,10 +5,15 @@
#include <engine/GameObject.hpp>
#include <engine/GameState.hpp>
#include <render/GameRenderer.hpp>
#include <render/DebugDraw.hpp>
#include <script/ScriptMachine.hpp>
#include <data/CutsceneData.hpp>
#include <ai/PlayerController.hpp>
#include <objects/CharacterObject.hpp>
#include <objects/VehicleObject.hpp>
DebugDraw* debug;
RWGame::RWGame(const std::string& gamepath)
: engine(nullptr), inFocus(true),
@ -38,6 +43,9 @@ RWGame::RWGame(const std::string& gamepath)
/// @TODO expand this here.
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");
@ -212,7 +220,25 @@ void RWGame::render(float alpha)
glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);
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();
std::stringstream ss;