mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-03-29 19:36:43 +00:00
Restore ranged weapon aiming
This commit is contained in:
parent
71bafcb52b
commit
ed4863ad7d
8 changed files with 170 additions and 94 deletions
|
@ -20,7 +20,7 @@ set(GAME_HEADER
|
||||||
source_group(game FILES ${GAME} ${GAME_HEADER})
|
source_group(game FILES ${GAME} ${GAME_HEADER})
|
||||||
|
|
||||||
add_openmw_dir (mwrender
|
add_openmw_dir (mwrender
|
||||||
actors objects renderingmanager animation sky npcanimation vismask
|
actors objects renderingmanager animation rotatecontroller sky npcanimation vismask
|
||||||
creatureanimation effectmanager util renderinginterface pathgrid rendermode weaponanimation
|
creatureanimation effectmanager util renderinginterface pathgrid rendermode weaponanimation
|
||||||
bulletdebugdraw globalmap characterpreview camera localmap
|
bulletdebugdraw globalmap characterpreview camera localmap
|
||||||
# occlusionquery water shadows
|
# occlusionquery water shadows
|
||||||
|
|
|
@ -171,14 +171,16 @@ Resource::ResourceSystem *CreatureWeaponAnimation::getResourceSystem()
|
||||||
return mResourceSystem;
|
return mResourceSystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CreatureWeaponAnimation::addControllers()
|
||||||
|
{
|
||||||
|
WeaponAnimation::addControllers(mNodeMap, mActiveControllers, mObjectRoot.get());
|
||||||
|
}
|
||||||
|
|
||||||
osg::Vec3f CreatureWeaponAnimation::runAnimation(float duration)
|
osg::Vec3f CreatureWeaponAnimation::runAnimation(float duration)
|
||||||
{
|
{
|
||||||
osg::Vec3f ret = Animation::runAnimation(duration);
|
osg::Vec3f ret = Animation::runAnimation(duration);
|
||||||
|
|
||||||
/*
|
WeaponAnimation::configureControllers(mPtr.getRefData().getPosition().rot[0]);
|
||||||
if (mSkelBase)
|
|
||||||
pitchSkeleton(mPtr.getRefData().getPosition().rot[0], mSkelBase->getSkeleton());
|
|
||||||
*/
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,11 +46,13 @@ namespace MWRender
|
||||||
virtual void showWeapon(bool show) { showWeapons(show); }
|
virtual void showWeapon(bool show) { showWeapons(show); }
|
||||||
virtual void setWeaponGroup(const std::string& group) { mWeaponAnimationTime->setGroup(group); }
|
virtual void setWeaponGroup(const std::string& group) { mWeaponAnimationTime->setGroup(group); }
|
||||||
|
|
||||||
|
virtual void addControllers();
|
||||||
|
|
||||||
virtual osg::Vec3f runAnimation(float duration);
|
virtual osg::Vec3f runAnimation(float duration);
|
||||||
|
|
||||||
/// A relative factor (0-1) that decides if and how much the skeleton should be pitched
|
/// A relative factor (0-1) that decides if and how much the skeleton should be pitched
|
||||||
/// to indicate the facing orientation of the character.
|
/// to indicate the facing orientation of the character.
|
||||||
//virtual void setPitchFactor(float factor) { mPitchFactor = factor; }
|
virtual void setPitchFactor(float factor) { mPitchFactor = factor; }
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "../mwbase/soundmanager.hpp"
|
#include "../mwbase/soundmanager.hpp"
|
||||||
|
|
||||||
#include "camera.hpp"
|
#include "camera.hpp"
|
||||||
|
#include "rotatecontroller.hpp"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
@ -72,64 +73,6 @@ std::string getVampireHead(const std::string& race, bool female)
|
||||||
namespace MWRender
|
namespace MWRender
|
||||||
{
|
{
|
||||||
|
|
||||||
/// @note Assumes that the node being rotated has its "original" orientation set every frame by a different controller.
|
|
||||||
/// The rotation is then applied on top of that orientation.
|
|
||||||
/// @note Must be set on a MatrixTransform.
|
|
||||||
class RotateController : public osg::NodeCallback
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
RotateController(osg::Node* relativeTo)
|
|
||||||
: mEnabled(true)
|
|
||||||
, mRelativeTo(relativeTo)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void setEnabled(bool enabled)
|
|
||||||
{
|
|
||||||
mEnabled = enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setRotate(const osg::Quat& rotate)
|
|
||||||
{
|
|
||||||
mRotate = rotate;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
|
|
||||||
{
|
|
||||||
if (!mEnabled)
|
|
||||||
return;
|
|
||||||
osg::MatrixTransform* transform = static_cast<osg::MatrixTransform*>(node);
|
|
||||||
osg::Matrix matrix = transform->getMatrix();
|
|
||||||
osg::Quat worldOrient = getWorldOrientation(node);
|
|
||||||
|
|
||||||
osg::Quat orient = worldOrient * mRotate * worldOrient.inverse() * matrix.getRotate();
|
|
||||||
matrix.setRotate(orient);
|
|
||||||
|
|
||||||
transform->setMatrix(matrix);
|
|
||||||
|
|
||||||
traverse(node,nv);
|
|
||||||
}
|
|
||||||
|
|
||||||
osg::Quat getWorldOrientation(osg::Node* node)
|
|
||||||
{
|
|
||||||
// this could be optimized later, we just need the world orientation, not the full matrix
|
|
||||||
osg::MatrixList worldMats = node->getWorldMatrices(mRelativeTo);
|
|
||||||
osg::Quat worldOrient;
|
|
||||||
if (!worldMats.empty())
|
|
||||||
{
|
|
||||||
osg::Matrixf worldMat = worldMats[0];
|
|
||||||
worldOrient = worldMat.getRotate();
|
|
||||||
}
|
|
||||||
return worldOrient;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
bool mEnabled;
|
|
||||||
osg::Quat mRotate;
|
|
||||||
osg::ref_ptr<osg::Node> mRelativeTo;
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Subclass RotateController to add a Z-offset for sneaking in first person mode.
|
/// Subclass RotateController to add a Z-offset for sneaking in first person mode.
|
||||||
/// @note We use inheritance instead of adding another controller, so that we do not have to compute the worldOrient twice.
|
/// @note We use inheritance instead of adding another controller, so that we do not have to compute the worldOrient twice.
|
||||||
/// @note Must be set on a MatrixTransform.
|
/// @note Must be set on a MatrixTransform.
|
||||||
|
@ -710,17 +653,7 @@ osg::Vec3f NpcAnimation::runAnimation(float timepassed)
|
||||||
mHeadController->setRotate(osg::Quat(mHeadPitchRadians, osg::Vec3f(1,0,0)) * osg::Quat(mHeadYawRadians, osg::Vec3f(0,0,1)));
|
mHeadController->setRotate(osg::Quat(mHeadPitchRadians, osg::Vec3f(1,0,0)) * osg::Quat(mHeadYawRadians, osg::Vec3f(0,0,1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
WeaponAnimation::configureControllers(mPtr.getRefData().getPosition().rot[0]);
|
||||||
if (mSkelBase)
|
|
||||||
{
|
|
||||||
Ogre::SkeletonInstance *baseinst = mSkelBase->getSkeleton();
|
|
||||||
if(mViewMode != VM_FirstPerson)
|
|
||||||
{
|
|
||||||
// In third person mode we may still need pitch for ranged weapon targeting
|
|
||||||
pitchSkeleton(mPtr.getRefData().getPosition().rot[0], baseinst);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -906,6 +839,8 @@ void NpcAnimation::addControllers()
|
||||||
{
|
{
|
||||||
mFirstPersonNeckController = NULL;
|
mFirstPersonNeckController = NULL;
|
||||||
mHeadController = NULL;
|
mHeadController = NULL;
|
||||||
|
WeaponAnimation::deleteControllers();
|
||||||
|
|
||||||
if (mViewMode == VM_FirstPerson)
|
if (mViewMode == VM_FirstPerson)
|
||||||
{
|
{
|
||||||
NodeMap::iterator found = mNodeMap.find("bip01 neck");
|
NodeMap::iterator found = mNodeMap.find("bip01 neck");
|
||||||
|
@ -927,6 +862,8 @@ void NpcAnimation::addControllers()
|
||||||
node->addUpdateCallback(mHeadController);
|
node->addUpdateCallback(mHeadController);
|
||||||
mActiveControllers.insert(std::make_pair(node, mHeadController));
|
mActiveControllers.insert(std::make_pair(node, mHeadController));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WeaponAnimation::addControllers(mNodeMap, mActiveControllers, mObjectRoot.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
57
apps/openmw/mwrender/rotatecontroller.cpp
Normal file
57
apps/openmw/mwrender/rotatecontroller.cpp
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
#include "rotatecontroller.hpp"
|
||||||
|
|
||||||
|
#include <osg/MatrixTransform>
|
||||||
|
|
||||||
|
namespace MWRender
|
||||||
|
{
|
||||||
|
|
||||||
|
RotateController::RotateController(osg::Node *relativeTo)
|
||||||
|
: mEnabled(true)
|
||||||
|
, mRelativeTo(relativeTo)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void RotateController::setEnabled(bool enabled)
|
||||||
|
{
|
||||||
|
mEnabled = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RotateController::setRotate(const osg::Quat &rotate)
|
||||||
|
{
|
||||||
|
mRotate = rotate;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RotateController::operator()(osg::Node *node, osg::NodeVisitor *nv)
|
||||||
|
{
|
||||||
|
if (!mEnabled)
|
||||||
|
{
|
||||||
|
traverse(node, nv);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
osg::MatrixTransform* transform = static_cast<osg::MatrixTransform*>(node);
|
||||||
|
osg::Matrix matrix = transform->getMatrix();
|
||||||
|
osg::Quat worldOrient = getWorldOrientation(node);
|
||||||
|
|
||||||
|
osg::Quat orient = worldOrient * mRotate * worldOrient.inverse() * matrix.getRotate();
|
||||||
|
matrix.setRotate(orient);
|
||||||
|
|
||||||
|
transform->setMatrix(matrix);
|
||||||
|
|
||||||
|
traverse(node,nv);
|
||||||
|
}
|
||||||
|
|
||||||
|
osg::Quat RotateController::getWorldOrientation(osg::Node *node)
|
||||||
|
{
|
||||||
|
// this could be optimized later, we just need the world orientation, not the full matrix
|
||||||
|
osg::MatrixList worldMats = node->getWorldMatrices(mRelativeTo);
|
||||||
|
osg::Quat worldOrient;
|
||||||
|
if (!worldMats.empty())
|
||||||
|
{
|
||||||
|
osg::Matrixf worldMat = worldMats[0];
|
||||||
|
worldOrient = worldMat.getRotate();
|
||||||
|
}
|
||||||
|
return worldOrient;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
36
apps/openmw/mwrender/rotatecontroller.hpp
Normal file
36
apps/openmw/mwrender/rotatecontroller.hpp
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
#ifndef OPENMW_MWRENDER_ROTATECONTROLLER_H
|
||||||
|
#define OPENMW_MWRENDER_ROTATECONTROLLER_H
|
||||||
|
|
||||||
|
#include <osg/NodeCallback>
|
||||||
|
#include <osg/Quat>
|
||||||
|
|
||||||
|
namespace MWRender
|
||||||
|
{
|
||||||
|
|
||||||
|
/// Applies a rotation in \a relativeTo's space.
|
||||||
|
/// @note Assumes that the node being rotated has its "original" orientation set every frame by a different controller.
|
||||||
|
/// The rotation is then applied on top of that orientation.
|
||||||
|
/// @note Must be set on a MatrixTransform.
|
||||||
|
class RotateController : public osg::NodeCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RotateController(osg::Node* relativeTo);
|
||||||
|
|
||||||
|
void setEnabled(bool enabled);
|
||||||
|
|
||||||
|
void setRotate(const osg::Quat& rotate);
|
||||||
|
|
||||||
|
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
osg::Quat getWorldOrientation(osg::Node* node);
|
||||||
|
|
||||||
|
bool mEnabled;
|
||||||
|
osg::Quat mRotate;
|
||||||
|
osg::ref_ptr<osg::Node> mRelativeTo;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,5 +1,7 @@
|
||||||
#include "weaponanimation.hpp"
|
#include "weaponanimation.hpp"
|
||||||
|
|
||||||
|
#include <osg/MatrixTransform>
|
||||||
|
|
||||||
#include <components/resource/resourcesystem.hpp>
|
#include <components/resource/resourcesystem.hpp>
|
||||||
#include <components/resource/scenemanager.hpp>
|
#include <components/resource/scenemanager.hpp>
|
||||||
|
|
||||||
|
@ -15,6 +17,7 @@
|
||||||
#include "../mwmechanics/combat.hpp"
|
#include "../mwmechanics/combat.hpp"
|
||||||
|
|
||||||
#include "animation.hpp"
|
#include "animation.hpp"
|
||||||
|
#include "rotatecontroller.hpp"
|
||||||
|
|
||||||
namespace MWRender
|
namespace MWRender
|
||||||
{
|
{
|
||||||
|
@ -46,6 +49,11 @@ WeaponAnimation::WeaponAnimation()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WeaponAnimation::~WeaponAnimation()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void WeaponAnimation::attachArrow(MWWorld::Ptr actor)
|
void WeaponAnimation::attachArrow(MWWorld::Ptr actor)
|
||||||
{
|
{
|
||||||
MWWorld::InventoryStore& inv = actor.getClass().getInventoryStore(actor);
|
MWWorld::InventoryStore& inv = actor.getClass().getInventoryStore(actor);
|
||||||
|
@ -149,28 +157,49 @@ void WeaponAnimation::releaseArrow(MWWorld::Ptr actor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
void WeaponAnimation::addControllers(const std::map<std::string, osg::ref_ptr<osg::MatrixTransform> >& nodes,
|
||||||
void WeaponAnimation::pitchSkeleton(float xrot, Ogre::SkeletonInstance* skel)
|
std::multimap<osg::ref_ptr<osg::Node>, osg::ref_ptr<osg::NodeCallback> > &map, osg::Node* objectRoot)
|
||||||
{
|
{
|
||||||
if (mPitchFactor == 0)
|
for (int i=0; i<2; ++i)
|
||||||
|
{
|
||||||
|
mSpineControllers[i] = NULL;
|
||||||
|
|
||||||
|
std::map<std::string, osg::ref_ptr<osg::MatrixTransform> >::const_iterator found = nodes.find(i == 0 ? "bip01 spine1" : "bip01 spine2");
|
||||||
|
if (found != nodes.end())
|
||||||
|
{
|
||||||
|
osg::Node* node = found->second;
|
||||||
|
mSpineControllers[i] = new RotateController(objectRoot);
|
||||||
|
node->addUpdateCallback(mSpineControllers[i]);
|
||||||
|
map.insert(std::make_pair(node, mSpineControllers[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WeaponAnimation::deleteControllers()
|
||||||
|
{
|
||||||
|
for (int i=0; i<2; ++i)
|
||||||
|
mSpineControllers[i] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WeaponAnimation::configureControllers(float characterPitchRadians)
|
||||||
|
{
|
||||||
|
if (!mSpineControllers[0])
|
||||||
return;
|
return;
|
||||||
|
|
||||||
float pitch = xrot * mPitchFactor;
|
if (mPitchFactor == 0.f || characterPitchRadians == 0.f)
|
||||||
Ogre::Node *node;
|
{
|
||||||
|
for (int i=0; i<2; ++i)
|
||||||
|
mSpineControllers[i]->setEnabled(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// In spherearcher.nif, we have spine, not Spine. Not sure if all bone names should be case insensitive?
|
float pitch = characterPitchRadians * mPitchFactor;
|
||||||
if (skel->hasBone("Bip01 spine2"))
|
osg::Quat rotate (pitch/2, osg::Vec3f(-1,0,0));
|
||||||
node = skel->getBone("Bip01 spine2");
|
for (int i=0; i<2; ++i)
|
||||||
else
|
{
|
||||||
node = skel->getBone("Bip01 Spine2");
|
mSpineControllers[i]->setRotate(rotate);
|
||||||
node->pitch(Ogre::Radian(-pitch/2), Ogre::Node::TS_WORLD);
|
mSpineControllers[i]->setEnabled(true);
|
||||||
|
}
|
||||||
if (skel->hasBone("Bip01 spine1")) // in spherearcher.nif
|
|
||||||
node = skel->getBone("Bip01 spine1");
|
|
||||||
else
|
|
||||||
node = skel->getBone("Bip01 Spine1");
|
|
||||||
node->pitch(Ogre::Radian(-pitch/2), Ogre::Node::TS_WORLD);
|
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
namespace MWRender
|
namespace MWRender
|
||||||
{
|
{
|
||||||
|
|
||||||
|
class RotateController;
|
||||||
|
|
||||||
class WeaponAnimationTime : public SceneUtil::ControllerSource
|
class WeaponAnimationTime : public SceneUtil::ControllerSource
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
@ -28,7 +30,7 @@ namespace MWRender
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
WeaponAnimation();
|
WeaponAnimation();
|
||||||
virtual ~WeaponAnimation() {}
|
virtual ~WeaponAnimation();
|
||||||
|
|
||||||
/// @note If no weapon (or an invalid weapon) is equipped, this function is a no-op.
|
/// @note If no weapon (or an invalid weapon) is equipped, this function is a no-op.
|
||||||
void attachArrow(MWWorld::Ptr actor);
|
void attachArrow(MWWorld::Ptr actor);
|
||||||
|
@ -36,9 +38,20 @@ namespace MWRender
|
||||||
/// @note If no weapon (or an invalid weapon) is equipped, this function is a no-op.
|
/// @note If no weapon (or an invalid weapon) is equipped, this function is a no-op.
|
||||||
void releaseArrow(MWWorld::Ptr actor);
|
void releaseArrow(MWWorld::Ptr actor);
|
||||||
|
|
||||||
|
/// Add WeaponAnimation-related controllers to \a nodes and store the added controllers in \a map.
|
||||||
|
void addControllers(const std::map<std::string, osg::ref_ptr<osg::MatrixTransform> >& nodes,
|
||||||
|
std::multimap<osg::ref_ptr<osg::Node>, osg::ref_ptr<osg::NodeCallback> >& map, osg::Node* objectRoot);
|
||||||
|
|
||||||
|
void deleteControllers();
|
||||||
|
|
||||||
|
/// Configure controllers, should be called every animation frame.
|
||||||
|
void configureControllers(float characterPitchRadians);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
PartHolderPtr mAmmunition;
|
PartHolderPtr mAmmunition;
|
||||||
|
|
||||||
|
osg::ref_ptr<RotateController> mSpineControllers[2];
|
||||||
|
|
||||||
virtual osg::Group* getArrowBone() = 0;
|
virtual osg::Group* getArrowBone() = 0;
|
||||||
virtual osg::Node* getWeaponNode() = 0;
|
virtual osg::Node* getWeaponNode() = 0;
|
||||||
virtual Resource::ResourceSystem* getResourceSystem() = 0;
|
virtual Resource::ResourceSystem* getResourceSystem() = 0;
|
||||||
|
|
Loading…
Reference in a new issue