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:
parent
3f40ba0e18
commit
4ea6e14299
@ -40,6 +40,8 @@ public:
|
||||
btHingeConstraint* constraint;
|
||||
bool holdAngle;
|
||||
float targetAngle;
|
||||
float openAngle;
|
||||
float closedAngle;
|
||||
};
|
||||
|
||||
std::map<std::string, Part> dynamicParts;
|
||||
|
@ -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;
|
||||
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;
|
||||
};
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
@ -605,16 +610,25 @@ void VehicleObject::createObjectHinge(btTransform& local, Part *part)
|
||||
|
||||
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);
|
||||
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->constraint = hinge;
|
||||
|
@ -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,46 +95,33 @@ void DebugDraw::drawContactPoint(const btVector3 &pointOnB, const btVector3 &nor
|
||||
|
||||
}
|
||||
|
||||
void DebugDraw::drawAllLines()
|
||||
void DebugDraw::flush(GameRenderer* renderer)
|
||||
{
|
||||
if(lines.size() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
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->getRenderer()->useProgram(shaderProgram);
|
||||
|
||||
GLint posAttrib = glGetAttribLocation(shaderProgram, "position");
|
||||
GLint uniModel = glGetUniformLocation(shaderProgram, "model");
|
||||
lineBuff->uploadVertices(lines);
|
||||
dbuff->addGeometry(lineBuff);
|
||||
|
||||
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());
|
||||
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;
|
||||
|
||||
glEnableVertexAttribArray(posAttrib);
|
||||
glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 0, 0);
|
||||
renderer->getRenderer()->drawArrays(glm::mat4(1.f), dbuff, dp);
|
||||
|
||||
glm::mat4 model;
|
||||
glUniformMatrix4fv(uniModel, 1, GL_FALSE, glm::value_ptr(model));
|
||||
renderer->getRenderer()->invalidate();
|
||||
|
||||
glDrawArrays(GL_LINES, 0, lines.size());
|
||||
glUseProgram(0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
glBindVertexArray( 0 );
|
||||
|
||||
lines.clear();
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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");
|
||||
|
||||
@ -213,6 +221,24 @@ void RWGame::render(float 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();
|
||||
|
||||
std::stringstream ss;
|
||||
|
Loading…
Reference in New Issue
Block a user