Rotate door object using direct rotation order once

Instead of rotating using inverse and then applying the direct rotation.
To properly update object in navigator.
pull/556/head
elsid 5 years ago
parent eec5d80566
commit 3cfd5fca4e
No known key found for this signature in database
GPG Key ID: B845CB9FEE18AB40

@ -0,0 +1,16 @@
#ifndef GAME_MWBASE_ROTATIONFLAGS_H
#define GAME_MWBASE_ROTATIONFLAGS_H
namespace MWBase
{
using RotationFlags = unsigned short;
enum RotationFlag : RotationFlags
{
RotationFlag_none = 0,
RotationFlag_adjust = 1,
RotationFlag_inverseOrder = 1 << 1,
};
}
#endif

@ -1,6 +1,8 @@
#ifndef GAME_MWBASE_WORLD_H
#define GAME_MWBASE_WORLD_H
#include "rotationflags.hpp"
#include <vector>
#include <map>
#include <set>
@ -280,7 +282,8 @@ namespace MWBase
virtual void scaleObject (const MWWorld::Ptr& ptr, float scale) = 0;
virtual void rotateObject(const MWWorld::Ptr& ptr,float x,float y,float z, bool adjust = false) = 0;
virtual void rotateObject(const MWWorld::Ptr& ptr, float x, float y, float z,
RotationFlags flags = RotationFlag_inverseOrder) = 0;
virtual MWWorld::Ptr placeObject(const MWWorld::ConstPtr& ptr, MWWorld::CellStore* cell, ESM::Position pos) = 0;
///< Place an object. Makes a copy of the Ptr.

@ -40,6 +40,8 @@
namespace
{
using MWWorld::RotationOrder;
osg::Quat makeActorOsgQuat(const ESM::Position& position)
{
return osg::Quat(position.rot[2], osg::Vec3(0, 0, -1));
@ -67,7 +69,7 @@ namespace
* osg::Quat(xr, osg::Vec3(-1, 0, 0));
}
void setNodeRotation(const MWWorld::Ptr& ptr, MWRender::RenderingManager& rendering, const bool inverseRotationOrder)
void setNodeRotation(const MWWorld::Ptr& ptr, MWRender::RenderingManager& rendering, RotationOrder order)
{
if (!ptr.getRefData().getBaseNode())
return;
@ -75,7 +77,7 @@ namespace
rendering.rotateObject(ptr,
ptr.getClass().isActor()
? makeActorOsgQuat(ptr.getRefData().getPosition())
: (inverseRotationOrder
: (order == RotationOrder::inverse
? makeInversedOrderObjectOsgQuat(ptr.getRefData().getPosition())
: makeObjectOsgQuat(ptr.getRefData().getPosition()))
);
@ -100,7 +102,7 @@ namespace
model = ""; // marker objects that have a hardcoded function in the game logic, should be hidden from the player
ptr.getClass().insertObjectRendering(ptr, model, rendering);
setNodeRotation(ptr, rendering, false);
setNodeRotation(ptr, rendering, RotationOrder::direct);
ptr.getClass().insertObject (ptr, model, physics);
@ -179,9 +181,9 @@ namespace
}
void updateObjectRotation (const MWWorld::Ptr& ptr, MWPhysics::PhysicsSystem& physics,
MWRender::RenderingManager& rendering, bool inverseRotationOrder)
MWRender::RenderingManager& rendering, RotationOrder order)
{
setNodeRotation(ptr, rendering, inverseRotationOrder);
setNodeRotation(ptr, rendering, order);
physics.updateRotation(ptr);
}
@ -278,9 +280,9 @@ namespace
namespace MWWorld
{
void Scene::updateObjectRotation (const Ptr& ptr, bool inverseRotationOrder)
void Scene::updateObjectRotation(const Ptr& ptr, RotationOrder order)
{
::updateObjectRotation(ptr, *mPhysics, mRendering, inverseRotationOrder);
::updateObjectRotation(ptr, *mPhysics, mRendering, order);
}
void Scene::updateObjectScale(const Ptr &ptr)

@ -51,6 +51,12 @@ namespace MWWorld
class CellStore;
class CellPreloader;
enum class RotationOrder
{
direct,
inverse
};
class Scene
{
public:
@ -137,7 +143,7 @@ namespace MWWorld
void removeObjectFromScene (const Ptr& ptr);
///< Remove an object from the scene, but not from the world model.
void updateObjectRotation (const Ptr& ptr, bool inverseRotationOrder);
void updateObjectRotation(const Ptr& ptr, RotationOrder order);
void updateObjectScale(const Ptr& ptr);
bool isCellActive(const CellStore &cell);

@ -1348,13 +1348,13 @@ namespace MWWorld
mShouldUpdateNavigator = updateNavigatorObject(object) || mShouldUpdateNavigator;
}
void World::rotateObjectImp (const Ptr& ptr, const osg::Vec3f& rot, bool adjust)
void World::rotateObjectImp(const Ptr& ptr, const osg::Vec3f& rot, MWBase::RotationFlags flags)
{
const float pi = static_cast<float>(osg::PI);
ESM::Position pos = ptr.getRefData().getPosition();
float *objRot = pos.rot;
if(adjust)
if (flags & MWBase::RotationFlag_adjust)
{
objRot[0] += rot.x();
objRot[1] += rot.y();
@ -1386,7 +1386,9 @@ namespace MWWorld
if(ptr.getRefData().getBaseNode() != 0)
{
mWorldScene->updateObjectRotation(ptr, true);
const auto order = flags & MWBase::RotationFlag_inverseOrder
? RotationOrder::inverse : RotationOrder::direct;
mWorldScene->updateObjectRotation(ptr, order);
if (const auto object = mPhysics->getObject(ptr))
updateNavigatorObject(object);
@ -1458,9 +1460,9 @@ namespace MWWorld
}
}
void World::rotateObject (const Ptr& ptr,float x,float y,float z, bool adjust)
void World::rotateObject (const Ptr& ptr, float x, float y, float z, MWBase::RotationFlags flags)
{
rotateObjectImp(ptr, osg::Vec3f(x, y, z), adjust);
rotateObjectImp(ptr, osg::Vec3f(x, y, z), flags);
}
void World::rotateWorldObject (const Ptr& ptr, osg::Quat rotate)
@ -1638,7 +1640,7 @@ namespace MWWorld
float diff = duration * osg::DegreesToRadians(90.f);
float targetRot = std::min(std::max(minRot, oldRot + diff * (state == MWWorld::DoorState::Opening ? 1 : -1)), maxRot);
rotateObject(door, objPos.rot[0], objPos.rot[1], targetRot);
rotateObject(door, objPos.rot[0], objPos.rot[1], targetRot, MWBase::RotationFlag_none);
bool reached = (targetRot == maxRot && state != MWWorld::DoorState::Idle) || targetRot == minRot;
@ -1682,11 +1684,9 @@ namespace MWWorld
MWBase::Environment::get().getSoundManager()->stopSound3D(door, closeSound);
}
rotateObject(door, objPos.rot[0], objPos.rot[1], oldRot);
rotateObject(door, objPos.rot[0], objPos.rot[1], oldRot, MWBase::RotationFlag_none);
}
// the rotation order we want to use
mWorldScene->updateObjectRotation(door, false);
return reached;
}
@ -2479,7 +2479,7 @@ namespace MWWorld
player.getClass().getInventoryStore(player).setContListener(anim);
scaleObject(player, player.getCellRef().getScale()); // apply race height
rotateObject(player, 0.f, 0.f, 0.f, true);
rotateObject(player, 0.f, 0.f, 0.f, MWBase::RotationFlag_inverseOrder | MWBase::RotationFlag_adjust);
MWBase::Environment::get().getMechanicsManager()->add(getPlayerPtr());
MWBase::Environment::get().getMechanicsManager()->watchActor(getPlayerPtr());

@ -126,7 +126,7 @@ namespace MWWorld
void updateWeather(float duration, bool paused = false);
int getDaysPerMonth (int month) const;
void rotateObjectImp (const Ptr& ptr, const osg::Vec3f& rot, bool adjust);
void rotateObjectImp (const Ptr& ptr, const osg::Vec3f& rot, MWBase::RotationFlags flags);
Ptr moveObjectImp (const Ptr& ptr, float x, float y, float z, bool movePhysics=true, bool moveToActive=false);
///< @return an updated Ptr in case the Ptr's cell changes
@ -393,7 +393,8 @@ namespace MWWorld
/// @note Rotations via this method use a different rotation order than the initial rotations in the CS. This
/// could be considered a bug, but is needed for MW compatibility.
/// \param adjust indicates rotation should be set or adjusted
void rotateObject (const Ptr& ptr,float x,float y,float z, bool adjust = false) override;
void rotateObject (const Ptr& ptr, float x, float y, float z,
MWBase::RotationFlags flags = MWBase::RotationFlag_inverseOrder) override;
MWWorld::Ptr placeObject(const MWWorld::ConstPtr& ptr, MWWorld::CellStore* cell, ESM::Position pos) override;
///< Place an object. Makes a copy of the Ptr.

Loading…
Cancel
Save