diff --git a/apps/openmw/mwbase/rotationflags.hpp b/apps/openmw/mwbase/rotationflags.hpp new file mode 100644 index 000000000..567192ed2 --- /dev/null +++ b/apps/openmw/mwbase/rotationflags.hpp @@ -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 diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 07e4edc5b..a2e36d3d0 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -1,6 +1,8 @@ #ifndef GAME_MWBASE_WORLD_H #define GAME_MWBASE_WORLD_H +#include "rotationflags.hpp" + #include #include #include @@ -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. diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index ddca61148..c558dd4d2 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -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) diff --git a/apps/openmw/mwworld/scene.hpp b/apps/openmw/mwworld/scene.hpp index 0f1ae7298..056c3acb2 100644 --- a/apps/openmw/mwworld/scene.hpp +++ b/apps/openmw/mwworld/scene.hpp @@ -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); diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 284185261..704ffe6f9 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -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(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()); diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 2a9bd839f..6090e2ce4 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -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.