Restore ranged weapon aiming

c++11
scrawl 10 years ago
parent 71bafcb52b
commit ed4863ad7d

@ -20,7 +20,7 @@ set(GAME_HEADER
source_group(game FILES ${GAME} ${GAME_HEADER})
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
bulletdebugdraw globalmap characterpreview camera localmap
# occlusionquery water shadows

@ -171,14 +171,16 @@ Resource::ResourceSystem *CreatureWeaponAnimation::getResourceSystem()
return mResourceSystem;
}
void CreatureWeaponAnimation::addControllers()
{
WeaponAnimation::addControllers(mNodeMap, mActiveControllers, mObjectRoot.get());
}
osg::Vec3f CreatureWeaponAnimation::runAnimation(float duration)
{
osg::Vec3f ret = Animation::runAnimation(duration);
/*
if (mSkelBase)
pitchSkeleton(mPtr.getRefData().getPosition().rot[0], mSkelBase->getSkeleton());
*/
WeaponAnimation::configureControllers(mPtr.getRefData().getPosition().rot[0]);
return ret;
}

@ -46,11 +46,13 @@ namespace MWRender
virtual void showWeapon(bool show) { showWeapons(show); }
virtual void setWeaponGroup(const std::string& group) { mWeaponAnimationTime->setGroup(group); }
virtual void addControllers();
virtual osg::Vec3f runAnimation(float duration);
/// 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 setPitchFactor(float factor) { mPitchFactor = factor; }
private:

@ -26,6 +26,7 @@
#include "../mwbase/soundmanager.hpp"
#include "camera.hpp"
#include "rotatecontroller.hpp"
namespace
{
@ -72,64 +73,6 @@ std::string getVampireHead(const std::string& race, bool female)
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.
/// @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.
@ -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)));
}
/*
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);
}
}
*/
WeaponAnimation::configureControllers(mPtr.getRefData().getPosition().rot[0]);
return ret;
}
@ -906,6 +839,8 @@ void NpcAnimation::addControllers()
{
mFirstPersonNeckController = NULL;
mHeadController = NULL;
WeaponAnimation::deleteControllers();
if (mViewMode == VM_FirstPerson)
{
NodeMap::iterator found = mNodeMap.find("bip01 neck");
@ -927,6 +862,8 @@ void NpcAnimation::addControllers()
node->addUpdateCallback(mHeadController);
mActiveControllers.insert(std::make_pair(node, mHeadController));
}
WeaponAnimation::addControllers(mNodeMap, mActiveControllers, mObjectRoot.get());
}
}

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

@ -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 <osg/MatrixTransform>
#include <components/resource/resourcesystem.hpp>
#include <components/resource/scenemanager.hpp>
@ -15,6 +17,7 @@
#include "../mwmechanics/combat.hpp"
#include "animation.hpp"
#include "rotatecontroller.hpp"
namespace MWRender
{
@ -46,6 +49,11 @@ WeaponAnimation::WeaponAnimation()
{
}
WeaponAnimation::~WeaponAnimation()
{
}
void WeaponAnimation::attachArrow(MWWorld::Ptr actor)
{
MWWorld::InventoryStore& inv = actor.getClass().getInventoryStore(actor);
@ -149,28 +157,49 @@ void WeaponAnimation::releaseArrow(MWWorld::Ptr actor)
}
}
/*
void WeaponAnimation::pitchSkeleton(float xrot, Ogre::SkeletonInstance* skel)
void WeaponAnimation::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)
{
if (mPitchFactor == 0)
return;
for (int i=0; i<2; ++i)
{
mSpineControllers[i] = NULL;
float pitch = xrot * mPitchFactor;
Ogre::Node *node;
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]));
}
}
}
// In spherearcher.nif, we have spine, not Spine. Not sure if all bone names should be case insensitive?
if (skel->hasBone("Bip01 spine2"))
node = skel->getBone("Bip01 spine2");
else
node = skel->getBone("Bip01 Spine2");
node->pitch(Ogre::Radian(-pitch/2), Ogre::Node::TS_WORLD);
void WeaponAnimation::deleteControllers()
{
for (int i=0; i<2; ++i)
mSpineControllers[i] = NULL;
}
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);
void WeaponAnimation::configureControllers(float characterPitchRadians)
{
if (!mSpineControllers[0])
return;
if (mPitchFactor == 0.f || characterPitchRadians == 0.f)
{
for (int i=0; i<2; ++i)
mSpineControllers[i]->setEnabled(false);
return;
}
float pitch = characterPitchRadians * mPitchFactor;
osg::Quat rotate (pitch/2, osg::Vec3f(-1,0,0));
for (int i=0; i<2; ++i)
{
mSpineControllers[i]->setRotate(rotate);
mSpineControllers[i]->setEnabled(true);
}
}
*/
}

@ -9,6 +9,8 @@
namespace MWRender
{
class RotateController;
class WeaponAnimationTime : public SceneUtil::ControllerSource
{
private:
@ -28,7 +30,7 @@ namespace MWRender
{
public:
WeaponAnimation();
virtual ~WeaponAnimation() {}
virtual ~WeaponAnimation();
/// @note If no weapon (or an invalid weapon) is equipped, this function is a no-op.
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.
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:
PartHolderPtr mAmmunition;
osg::ref_ptr<RotateController> mSpineControllers[2];
virtual osg::Group* getArrowBone() = 0;
virtual osg::Node* getWeaponNode() = 0;
virtual Resource::ResourceSystem* getResourceSystem() = 0;

Loading…
Cancel
Save