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

Overhaul object transformation handling

Objects must now write back to their position and rotations using
updateTransform(position, rotation) to updae their transform. This
allows the getPosition and getRotation methods to become non virtual
This commit is contained in:
Daniel Evans 2016-05-27 19:45:50 +01:00 committed by Daniel Evans
parent b3fe87c2ea
commit f860e4c9a7
12 changed files with 101 additions and 97 deletions

View File

@ -158,15 +158,13 @@ public:
virtual void setPosition(const glm::vec3& pos);
virtual glm::vec3 getPosition() const;
virtual glm::quat getRotation() const;
bool isAlive() const;
bool takeDamage(const DamageInfo& damage) override;
bool enterVehicle(VehicleObject* vehicle, size_t seat);
bool isEnteringOrExitingVehicle() const;
/**
* @brief isStopped
* @return True if the character isn't moving

View File

@ -98,10 +98,10 @@ public:
virtual void setPosition(const glm::vec3& pos);
virtual glm::vec3 getPosition() const { return position; }
const glm::vec3& getPosition() const { return position; }
const glm::vec3& getLastPosition() const { return _lastPosition; }
virtual glm::quat getRotation() const;
const glm::quat& getRotation() const { return rotation; }
virtual void setRotation(const glm::quat &orientation);
float getHeading() const;
@ -185,7 +185,15 @@ public:
void setLifetime(ObjectLifetime ol) { lifetime = ol; }
ObjectLifetime getLifetime() const { return lifetime; }
void updateTransform(const glm::vec3& pos, const glm::quat& rot)
{
_lastPosition = position;
_lastRotation = rotation;
position = pos;
rotation = rot;
}
private:
ObjectLifetime lifetime;
};

View File

@ -31,9 +31,6 @@ public:
void changeModel(std::shared_ptr<ObjectData> incoming);
glm::vec3 getPosition() const override;
glm::quat getRotation() const override;
virtual void setRotation(const glm::quat& r);
virtual bool takeDamage(const DamageInfo& damage);

View File

@ -57,12 +57,8 @@ public:
void setPosition(const glm::vec3& pos);
glm::vec3 getPosition() const;
void setRotation(const glm::quat &orientation);
glm::quat getRotation() const;
Type type() { return Vehicle; }
void setSteeringAngle(float);
@ -111,7 +107,10 @@ public:
glm::vec3 getSeatEntryPosition(size_t seat) const {
auto pos = info->seats[seat].offset;
pos -= glm::vec3(glm::sign(pos.x) * -0.81756252f, 0.34800607f, -0.486281008f);
return getPosition() + getRotation() * pos;
return pos;
}
glm::vec3 getSeatEntryPositionWorld(size_t seat) const {
return getPosition() + getRotation() * getSeatEntryPosition(seat);
}
Part* getSeatEntryDoor(size_t seat);

View File

@ -207,7 +207,7 @@ bool Activities::EnterVehicle::update(CharacterObject *character, CharacterContr
float nearest = std::numeric_limits<float>::max();
for(unsigned int s = 1; s < vehicle->info->seats.size(); ++s)
{
auto entry = vehicle->getSeatEntryPosition(s);
auto entry = vehicle->getSeatEntryPositionWorld(s);
float dist = glm::distance(entry, character->getPosition());
if( dist < nearest )
{
@ -218,6 +218,7 @@ bool Activities::EnterVehicle::update(CharacterObject *character, CharacterContr
}
auto entryDoor = vehicle->getSeatEntryDoor(seat);
auto entryPos = vehicle->getSeatEntryPositionWorld(seat);
auto anm_open = character->animations.car_open_lhs;
auto anm_enter = character->animations.car_getin_lhs;
@ -262,8 +263,7 @@ bool Activities::EnterVehicle::update(CharacterObject *character, CharacterContr
}
}
else {
glm::vec3 target = vehicle->getSeatEntryPosition(seat);
glm::vec3 targetDirection = target - character->getPosition();
glm::vec3 targetDirection = entryPos - character->getPosition();
targetDirection.z = 0.f;
float targetDistance = glm::length(targetDirection);
@ -387,7 +387,7 @@ bool Activities::ExitVehicle::update(CharacterObject *character, CharacterContro
if( character->animator->getAnimation(AnimIndexAction) == anm_exit ) {
if( character->animator->isCompleted(AnimIndexAction) ) {
auto exitpos = vehicle->getSeatEntryPosition(seat);
auto exitpos = vehicle->getSeatEntryPositionWorld(seat);
character->enterVehicle(nullptr, seat);
character->setPosition(exitpos);

View File

@ -4,6 +4,34 @@
#include <engine/GameWorld.hpp>
#include <engine/GameData.hpp>
class GameObjectMotionState : public btMotionState
{
public:
GameObjectMotionState(GameObject *object)
: m_object(object)
{ }
virtual void getWorldTransform(btTransform& tform) const
{
auto& position = m_object->getPosition();
auto& rotation = m_object->getRotation();
tform.setOrigin(btVector3(position.x, position.y, position.z));
tform.setRotation(btQuaternion(rotation.x, rotation.y, rotation.z, rotation.w));
}
virtual void setWorldTransform(const btTransform& tform)
{
auto& o = tform.getOrigin();
auto r = tform.getRotation();
glm::vec3 position(o.x(), o.y(), o.z());
glm::quat rotation(r.w(), r.x(), r.y(), r.z());
m_object->updateTransform(position, rotation);
}
private:
GameObject *m_object;
};
CollisionInstance::~CollisionInstance()
{
if( m_body ) {
@ -32,14 +60,7 @@ bool CollisionInstance::createPhysicsBody(GameObject *object, const std::string&
if( phyit != object->engine->data->collisions.end()) {
btCompoundShape* cmpShape = new btCompoundShape;
auto p = object->getPosition();
auto r = object->getRotation();
m_motionState = new btDefaultMotionState;
m_motionState->setWorldTransform(btTransform(
btQuaternion(r.x, r.y, r.z, -r.w).inverse(),
btVector3(p.x, p.y, p.z)
));
m_motionState = new GameObjectMotionState(object);
m_shapes.push_back(cmpShape);
btRigidBody::btRigidBodyConstructionInfo info(0.f, m_motionState, cmpShape);

View File

@ -316,8 +316,6 @@ void CharacterObject::updateCharacter(float dt)
if(physCharacter) {
glm::vec3 walkDir = updateMovementAnimation(dt);
position = getPosition();
if (canTurn()) {
rotation = glm::angleAxis(m_look.x, glm::vec3{0.f, 0.f, 1.f});
}
@ -399,39 +397,6 @@ void CharacterObject::setPosition(const glm::vec3& pos)
position = pos;
}
glm::vec3 CharacterObject::getPosition() const
{
if(physCharacter) {
btVector3 Pos = physCharacter->getGhostObject()->getWorldTransform().getOrigin();
return glm::vec3(Pos.x(), Pos.y(), Pos.z());
}
if(currentVehicle) {
/// @todo this is hacky.
if( animator->getAnimation(AnimIndexAction) == animations.car_getout_lhs ) {
return currentVehicle->getSeatEntryPosition(currentSeat);
}
auto v = getCurrentVehicle();
auto R = glm::mat3_cast(v->getRotation());
glm::vec3 offset;
auto o = (animator->getAnimation(AnimIndexAction) == animations.car_getin_lhs) ? enter_offset : glm::vec3();
if(getCurrentSeat() < v->info->seats.size()) {
offset = R * (v->info->seats[getCurrentSeat()].offset -
o);
}
return currentVehicle->getPosition() + offset;
}
return position;
}
glm::quat CharacterObject::getRotation() const
{
if(currentVehicle) {
return currentVehicle->getRotation();
}
return GameObject::getRotation();
}
bool CharacterObject::isAlive() const
{
return currentState.health > 0.f;
@ -465,6 +430,12 @@ bool CharacterObject::enterVehicle(VehicleObject* vehicle, size_t seat)
return false;
}
bool CharacterObject::isEnteringOrExitingVehicle() const
{
return animator->getAnimation(AnimIndexAction) == animations.car_getout_lhs ||
animator->getAnimation(AnimIndexAction) == animations.car_getin_lhs;
}
bool CharacterObject::isStopped() const
{
if (currentVehicle != nullptr) {

View File

@ -23,11 +23,6 @@ void GameObject::setPosition(const glm::vec3& pos)
_lastPosition = position = pos;
}
glm::quat GameObject::getRotation() const
{
return rotation;
}
void GameObject::setRotation(const glm::quat& orientation)
{
rotation = orientation;

View File

@ -49,12 +49,8 @@ void InstanceObject::tick(float dt)
body->changeMass(dynamics->mass);
}
}
_updateLastTransform();
/// @todo replace with position from motionstate
auto _bws = body->getBulletBody()->getWorldTransform().getOrigin();
glm::vec3 ws(_bws.x(), _bws.y(), _bws.z());
const glm::vec3& ws = getPosition();
auto wX = (int) ((ws.x + WATER_WORLD_SIZE/2.f) / (WATER_WORLD_SIZE/WATER_HQ_DATA_SIZE));
auto wY = (int) ((ws.y + WATER_WORLD_SIZE/2.f) / (WATER_WORLD_SIZE/WATER_HQ_DATA_SIZE));
float vH = ws.z;// - _collisionHeight/2.f;
@ -136,16 +132,6 @@ void InstanceObject::changeModel(std::shared_ptr<ObjectData> incoming)
}
}
glm::vec3 InstanceObject::getPosition() const
{
return position;
}
glm::quat InstanceObject::getRotation() const
{
return rotation;
}
void InstanceObject::setRotation(const glm::quat &r)
{
if( body ) {

View File

@ -163,12 +163,6 @@ void VehicleObject::setPosition(const glm::vec3& pos)
}
}
glm::vec3 VehicleObject::getPosition() const
{
/// @todo update our position from the motion state
return position;
}
void VehicleObject::setRotation(const glm::quat &orientation)
{
if( collision->getBulletBody() ) {
@ -179,11 +173,6 @@ void VehicleObject::setRotation(const glm::quat &orientation)
GameObject::setRotation(orientation);
}
glm::quat VehicleObject::getRotation() const
{
/// @todo update our rotation from the motion state
return rotation;
}
#include <glm/gtc/type_ptr.hpp>
@ -232,11 +221,30 @@ void VehicleObject::tickPhysics(float dt)
}
}
// Update passenger positions
for (auto& seat : seatOccupants)
{
auto character = static_cast<CharacterObject*>(seat.second);
glm::vec3 passPosition;
if (character->isEnteringOrExitingVehicle())
{
passPosition = getSeatEntryPositionWorld(seat.first);
}
else
{
passPosition = getPosition();
if (seat.first < info->seats.size()) {
passPosition += getRotation() * (info->seats[seat.first].offset);
}
}
seat.second->updateTransform(passPosition, getRotation());
}
if( vehicle->type == VehicleData::BOAT ) {
if( isInWater() ) {
float sign = std::signbit(steerAngle) ? -1.f : 1.f;
float steer = std::min(info->handling.steeringLock*(3.141f/180.f), std::abs(steerAngle)) * sign;
/// @todo get orientation from motion state
auto orient = collision->getBulletBody()->getOrientation();
// Find the local-space velocity
@ -265,7 +273,7 @@ void VehicleObject::tickPhysics(float dt)
}
}
auto ws = getPosition();
const auto& ws = getPosition();
auto wX = (int) ((ws.x + WATER_WORLD_SIZE/2.f) / (WATER_WORLD_SIZE/WATER_HQ_DATA_SIZE));
auto wY = (int) ((ws.y + WATER_WORLD_SIZE/2.f) / (WATER_WORLD_SIZE/WATER_HQ_DATA_SIZE));
btVector3 bbmin, bbmax;

View File

@ -298,7 +298,28 @@ void ObjectRenderer::renderInstance(InstanceObject *instance,
void ObjectRenderer::renderCharacter(CharacterObject *pedestrian,
RenderList& outList)
{
glm::mat4 matrixModel = pedestrian->getTimeAdjustedTransform( m_renderAlpha );
glm::mat4 matrixModel;
if (pedestrian->getCurrentVehicle())
{
auto vehicle = pedestrian->getCurrentVehicle();
auto seat = pedestrian->getCurrentSeat();
matrixModel = vehicle->getTimeAdjustedTransform( m_renderAlpha );
if (pedestrian->isEnteringOrExitingVehicle())
{
matrixModel = glm::translate(matrixModel, vehicle->getSeatEntryPosition(seat));
}
else
{
if (seat < vehicle->info->seats.size()) {
matrixModel = glm::translate(matrixModel, vehicle->info->seats[seat].offset);
}
}
}
else
{
matrixModel = pedestrian->getTimeAdjustedTransform( m_renderAlpha );
}
if(!pedestrian->model->resource) return;

View File

@ -78,7 +78,7 @@ BOOST_AUTO_TEST_CASE(test_door_position)
BOOST_REQUIRE(vehicle->info != nullptr);
BOOST_REQUIRE(vehicle->vehicle != nullptr);
BOOST_CHECK( vehicle->getSeatEntryPosition(0).x > 5.f );
BOOST_CHECK( vehicle->getSeatEntryPositionWorld(0).x > 5.f );
Global::get().e->destroyObject(vehicle);