1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-03-17 10:21:11 +00:00

Merge pull request #2620 from elsid/fix_cage_door_rotation

Rotate door object using direct rotation order once
This commit is contained in:
Andrei Kortunov 2019-12-01 09:54:38 +04:00 committed by GitHub
commit 058bbf4b0f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 49 additions and 21 deletions

View File

@ -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

View File

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

View File

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

View File

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

View File

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

View File

@ -126,7 +126,7 @@ namespace MWWorld
void updateWeather(float duration, bool paused = false); void updateWeather(float duration, bool paused = false);
int getDaysPerMonth (int month) const; 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); 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 ///< @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 /// @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. /// could be considered a bug, but is needed for MW compatibility.
/// \param adjust indicates rotation should be set or adjusted /// \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; MWWorld::Ptr placeObject(const MWWorld::ConstPtr& ptr, MWWorld::CellStore* cell, ESM::Position pos) override;
///< Place an object. Makes a copy of the Ptr. ///< Place an object. Makes a copy of the Ptr.