From a07eaa0c0ddd237529b357acfd59e2bc85d4e23a Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 4 Feb 2014 04:00:52 +0100 Subject: [PATCH] Feature #50: Allow body pitch in third person for ranged weapon aiming --- apps/openmw/mwmechanics/character.cpp | 44 +++++++++++++++++++++++++++ apps/openmw/mwrender/animation.cpp | 1 - apps/openmw/mwrender/animation.hpp | 8 ++--- apps/openmw/mwrender/camera.cpp | 2 -- apps/openmw/mwrender/npcanimation.cpp | 18 ++++++++--- apps/openmw/mwrender/npcanimation.hpp | 5 +++ 6 files changed, 67 insertions(+), 11 deletions(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 9ea159e03..df6e7938f 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -773,6 +773,50 @@ bool CharacterController::updateWeaponState() } } + mAnimation->setPitchFactor(0.f); + if (mWeaponType == WeapType_BowAndArrow || mWeaponType == WeapType_Thrown) + { + switch (mUpperBodyState) + { + case UpperCharState_StartToMinAttack: + mAnimation->setPitchFactor(complete); + break; + case UpperCharState_MinAttackToMaxAttack: + case UpperCharState_MaxAttackToMinHit: + case UpperCharState_MinHitToHit: + mAnimation->setPitchFactor(1.f); + break; + case UpperCharState_FollowStartToFollowStop: + if (animPlaying) + mAnimation->setPitchFactor(1.f-complete); + break; + default: + break; + } + } + else if (mWeaponType == WeapType_Crossbow) + { + switch (mUpperBodyState) + { + case UpperCharState_EquipingWeap: + mAnimation->setPitchFactor(complete); + break; + case UpperCharState_UnEquipingWeap: + mAnimation->setPitchFactor(1.f-complete); + break; + case UpperCharState_WeapEquiped: + case UpperCharState_StartToMinAttack: + case UpperCharState_MinAttackToMaxAttack: + case UpperCharState_MaxAttackToMinHit: + case UpperCharState_MinHitToHit: + case UpperCharState_FollowStartToFollowStop: + mAnimation->setPitchFactor(1.f); + break; + default: + break; + } + } + if(!animPlaying) { if(mUpperBodyState == UpperCharState_EquipingWeap || diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 5417f1820..66153a7e0 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -53,7 +53,6 @@ void Animation::EffectAnimationTime::setValue(Ogre::Real) Animation::Animation(const MWWorld::Ptr &ptr, Ogre::SceneNode *node) : mPtr(ptr) - , mCamera(NULL) , mInsert(node) , mSkelBase(NULL) , mAccumRoot(NULL) diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index 27778d373..ed7ed819f 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -121,7 +121,6 @@ protected: std::vector mEffects; MWWorld::Ptr mPtr; - Camera *mCamera; Ogre::SceneNode *mInsert; Ogre::Entity *mSkelBase; @@ -288,6 +287,10 @@ public: /** Retrieves the velocity (in units per second) that the animation will move. */ float getVelocity(const std::string &groupname) const; + /// A relative factor (0-1) that decides if and how much the skeleton should be pitched + /// to indicate the facing orientation of the character. + virtual void setPitchFactor(float factor) {} + virtual Ogre::Vector3 runAnimation(float duration); virtual void showWeapons(bool showWeapon); @@ -297,9 +300,6 @@ public: Ogre::AxisAlignedBox getWorldBounds(); - void setCamera(Camera *cam) - { mCamera = cam; } - Ogre::Node *getNode(const std::string &name); // Attaches the given object to a bone on this object's base skeleton. If the bone doesn't diff --git a/apps/openmw/mwrender/camera.cpp b/apps/openmw/mwrender/camera.cpp index 9c8387b83..9ae9c5878 100644 --- a/apps/openmw/mwrender/camera.cpp +++ b/apps/openmw/mwrender/camera.cpp @@ -338,11 +338,9 @@ namespace MWRender if(mAnimation && mAnimation != anim) { mAnimation->setViewMode(NpcAnimation::VM_Normal); - mAnimation->setCamera(NULL); mAnimation->detachObjectFromBone(mCamera); } mAnimation = anim; - mAnimation->setCamera(this); processViewChange(); } diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 531d90162..d051bde52 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -142,7 +142,8 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, int v mShowCarriedLeft(true), mFirstPersonOffset(0.f, 0.f, 0.f), mAlpha(1.f), - mNpcType(Type_Normal) + mNpcType(Type_Normal), + mPitchFactor(0) { mNpc = mPtr.get()->mBase; @@ -522,16 +523,25 @@ Ogre::Vector3 NpcAnimation::runAnimation(float timepassed) Ogre::Vector3 ret = Animation::runAnimation(timepassed); Ogre::SkeletonInstance *baseinst = mSkelBase->getSkeleton(); - if(mViewMode == VM_FirstPerson && mCamera) + if(mViewMode == VM_FirstPerson) { - float pitch = mCamera->getPitch(); + float pitch = mPtr.getRefData().getPosition().rot[0]; Ogre::Node *node = baseinst->getBone("Bip01 Neck"); - node->pitch(Ogre::Radian(pitch*0.75f), Ogre::Node::TS_WORLD); + node->pitch(Ogre::Radian(pitch), Ogre::Node::TS_WORLD); // This has to be done before this function ends; // updateSkeletonInstance, below, touches the hands. node->translate(mFirstPersonOffset, Ogre::Node::TS_WORLD); } + else if (mPitchFactor > 0) + { + // In third person mode we may still need pitch for ranged weapon targeting + float pitch = mPtr.getRefData().getPosition().rot[0] * mPitchFactor; + Ogre::Node *node = baseinst->getBone("Bip01 Spine2"); + node->pitch(Ogre::Radian(pitch/2), Ogre::Node::TS_WORLD); + node = baseinst->getBone("Bip01 Spine1"); + node->pitch(Ogre::Radian(pitch/2), Ogre::Node::TS_WORLD); + } mFirstPersonOffset = 0.f; // reset the X, Y, Z offset for the next frame. for(size_t i = 0;i < ESM::PRT_Count;i++) diff --git a/apps/openmw/mwrender/npcanimation.hpp b/apps/openmw/mwrender/npcanimation.hpp index 1dd0b41e6..9baf975f1 100644 --- a/apps/openmw/mwrender/npcanimation.hpp +++ b/apps/openmw/mwrender/npcanimation.hpp @@ -91,6 +91,7 @@ private: Ogre::SharedPtr mWeaponAnimationTime; float mAlpha; + float mPitchFactor; void updateNpcBase(); @@ -127,6 +128,10 @@ public: virtual Ogre::Vector3 runAnimation(float timepassed); + /// A relative factor (0-1) that decides if and how much the skeleton should be pitched + /// to indicate the facing orientation of the character. + virtual void setPitchFactor(float factor) { mPitchFactor = factor; } + virtual void showWeapons(bool showWeapon); virtual void showCarriedLeft(bool showa);