mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-05 10:45:35 +00:00
Movement accumulation works
This commit is contained in:
parent
09742d5b95
commit
86b4a610cb
3 changed files with 74 additions and 32 deletions
|
@ -8,6 +8,7 @@
|
||||||
#include <osg/TexEnvCombine>
|
#include <osg/TexEnvCombine>
|
||||||
#include <osg/ComputeBoundsVisitor>
|
#include <osg/ComputeBoundsVisitor>
|
||||||
#include <osg/MatrixTransform>
|
#include <osg/MatrixTransform>
|
||||||
|
#include <osg/io_utils>
|
||||||
|
|
||||||
#include <components/nifosg/nifloader.hpp>
|
#include <components/nifosg/nifloader.hpp>
|
||||||
|
|
||||||
|
@ -168,10 +169,39 @@ namespace
|
||||||
namespace MWRender
|
namespace MWRender
|
||||||
{
|
{
|
||||||
|
|
||||||
|
class ResetAccumRootCallback : public osg::NodeCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
|
||||||
|
{
|
||||||
|
osg::MatrixTransform* transform = static_cast<osg::MatrixTransform*>(node);
|
||||||
|
|
||||||
|
osg::Matrix mat = transform->getMatrix();
|
||||||
|
osg::Vec3f position = mat.getTrans();
|
||||||
|
position = osg::componentMultiply(mResetAxes, position);
|
||||||
|
mat.setTrans(position);
|
||||||
|
transform->setMatrix(mat);
|
||||||
|
|
||||||
|
traverse(node, nv);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setAccumulate(const osg::Vec3f& accumulate)
|
||||||
|
{
|
||||||
|
// anything that accumulates (1.f) should be reset in the callback to (0.f)
|
||||||
|
mResetAxes.x() = accumulate.x() != 0.f ? 0.f : 1.f;
|
||||||
|
mResetAxes.y() = accumulate.y() != 0.f ? 0.f : 1.f;
|
||||||
|
mResetAxes.z() = accumulate.z() != 0.f ? 0.f : 1.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
osg::Vec3f mResetAxes;
|
||||||
|
};
|
||||||
|
|
||||||
Animation::Animation(const MWWorld::Ptr &ptr, osg::ref_ptr<osg::Group> parentNode, Resource::ResourceSystem* resourceSystem)
|
Animation::Animation(const MWWorld::Ptr &ptr, osg::ref_ptr<osg::Group> parentNode, Resource::ResourceSystem* resourceSystem)
|
||||||
: mPtr(ptr)
|
: mPtr(ptr)
|
||||||
, mInsert(parentNode)
|
, mInsert(parentNode)
|
||||||
, mResourceSystem(resourceSystem)
|
, mResourceSystem(resourceSystem)
|
||||||
|
, mAccumulate(1.f, 1.f, 0.f)
|
||||||
{
|
{
|
||||||
for(size_t i = 0;i < sNumGroups;i++)
|
for(size_t i = 0;i < sNumGroups;i++)
|
||||||
mAnimationTimePtr[i].reset(new AnimationTime(this));
|
mAnimationTimePtr[i].reset(new AnimationTime(this));
|
||||||
|
@ -191,6 +221,9 @@ namespace MWRender
|
||||||
void Animation::setAccumulation(const osg::Vec3f& accum)
|
void Animation::setAccumulation(const osg::Vec3f& accum)
|
||||||
{
|
{
|
||||||
mAccumulate = accum;
|
mAccumulate = accum;
|
||||||
|
|
||||||
|
if (mResetAccumRootCallback)
|
||||||
|
mResetAccumRootCallback->setAccumulate(mAccumulate);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Animation::detectAnimGroup(osg::Node* node)
|
size_t Animation::detectAnimGroup(osg::Node* node)
|
||||||
|
@ -322,6 +355,16 @@ namespace MWRender
|
||||||
void Animation::handleTextKey(AnimState &state, const std::string &groupname, const std::multimap<float, std::string>::const_iterator &key,
|
void Animation::handleTextKey(AnimState &state, const std::string &groupname, const std::multimap<float, std::string>::const_iterator &key,
|
||||||
const std::multimap<float, std::string>& map)
|
const std::multimap<float, std::string>& map)
|
||||||
{
|
{
|
||||||
|
const std::string &evt = key->second;
|
||||||
|
|
||||||
|
size_t off = groupname.size()+2;
|
||||||
|
size_t len = evt.size() - off;
|
||||||
|
|
||||||
|
if(evt.compare(off, len, "loop start") == 0)
|
||||||
|
state.mLoopStartTime = key->first;
|
||||||
|
else if(evt.compare(off, len, "loop stop") == 0)
|
||||||
|
state.mLoopStopTime = key->first;
|
||||||
|
|
||||||
// TODO: forward to listener?
|
// TODO: forward to listener?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -406,16 +449,6 @@ namespace MWRender
|
||||||
std::cerr<< "Failed to find animation "<<groupname<<" for "<<mPtr.getCellRef().getRefId() <<std::endl;
|
std::cerr<< "Failed to find animation "<<groupname<<" for "<<mPtr.getCellRef().getRefId() <<std::endl;
|
||||||
|
|
||||||
resetActiveGroups();
|
resetActiveGroups();
|
||||||
|
|
||||||
// This shouldn't be needed, same is already done in resetActiveGroups()
|
|
||||||
/*
|
|
||||||
if (!state.mPlaying && mNonAccumCtrl)
|
|
||||||
{
|
|
||||||
// If the animation state is not playing, we need to manually apply the accumulation
|
|
||||||
// (see updatePosition, which would be called if the animation was playing)
|
|
||||||
mAccumRoot->setPosition(-mNonAccumCtrl->getTranslation(state.mTime)*mAccumulate);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Animation::reset(AnimState &state, const NifOsg::TextKeyMap &keys, const std::string &groupname, const std::string &start, const std::string &stop, float startpoint, bool loopfallback)
|
bool Animation::reset(AnimState &state, const NifOsg::TextKeyMap &keys, const std::string &groupname, const std::string &start, const std::string &stop, float startpoint, bool loopfallback)
|
||||||
|
@ -504,6 +537,8 @@ namespace MWRender
|
||||||
osg::Node* node = it->first;
|
osg::Node* node = it->first;
|
||||||
node->removeUpdateCallback(it->second);
|
node->removeUpdateCallback(it->second);
|
||||||
}
|
}
|
||||||
|
if (mResetAccumRootCallback && mAccumRoot)
|
||||||
|
mAccumRoot->removeUpdateCallback(mResetAccumRootCallback);
|
||||||
mAnimSourceControllers.clear();
|
mAnimSourceControllers.clear();
|
||||||
|
|
||||||
mAccumCtrl = NULL;
|
mAccumCtrl = NULL;
|
||||||
|
@ -538,26 +573,19 @@ namespace MWRender
|
||||||
mAnimSourceControllers[node] = it->second;
|
mAnimSourceControllers[node] = it->second;
|
||||||
|
|
||||||
if (grp == 0 && node == mAccumRoot)
|
if (grp == 0 && node == mAccumRoot)
|
||||||
|
{
|
||||||
mAccumCtrl = it->second;
|
mAccumCtrl = it->second;
|
||||||
|
|
||||||
|
if (!mResetAccumRootCallback)
|
||||||
|
{
|
||||||
|
mResetAccumRootCallback = new ResetAccumRootCallback;
|
||||||
|
mResetAccumRootCallback->setAccumulate(mAccumulate);
|
||||||
|
}
|
||||||
|
mAccumRoot->addUpdateCallback(mResetAccumRootCallback);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//if(!mNonAccumRoot || mAccumulate == Ogre::Vector3(0.0f))
|
|
||||||
// return;
|
|
||||||
|
|
||||||
/*
|
|
||||||
AnimStateMap::const_iterator state = mStates.find(mAnimationTimePtr[0]->getAnimName());
|
|
||||||
if(state == mStates.end())
|
|
||||||
{
|
|
||||||
//if (mAccumRoot && mNonAccumRoot)
|
|
||||||
// mAccumRoot->setPosition(-mNonAccumRoot->getPosition()*mAccumulate);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
//if (mAccumRoot && mNonAccumCtrl)
|
|
||||||
// mAccumRoot->setPosition(-mNonAccumCtrl->getTranslation(state->second.mTime)*mAccumulate);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Animation::changeGroups(const std::string &groupname, int groups)
|
void Animation::changeGroups(const std::string &groupname, int groups)
|
||||||
|
@ -695,6 +723,13 @@ namespace MWRender
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Animation::updatePosition(float oldtime, float newtime, osg::Vec3f& position)
|
||||||
|
{
|
||||||
|
// Get the difference from the last update, and move the position
|
||||||
|
osg::Vec3f off = osg::componentMultiply(mAccumCtrl->getTranslation(newtime), mAccumulate);
|
||||||
|
position += off - osg::componentMultiply(mAccumCtrl->getTranslation(oldtime), mAccumulate);
|
||||||
|
}
|
||||||
|
|
||||||
osg::Vec3f Animation::runAnimation(float duration)
|
osg::Vec3f Animation::runAnimation(float duration)
|
||||||
{
|
{
|
||||||
osg::Vec3f movement(0.f, 0.f, 0.f);
|
osg::Vec3f movement(0.f, 0.f, 0.f);
|
||||||
|
@ -716,14 +751,14 @@ namespace MWRender
|
||||||
targetTime = state.mTime + timepassed;
|
targetTime = state.mTime + timepassed;
|
||||||
if(textkey == textkeys.end() || textkey->first > targetTime)
|
if(textkey == textkeys.end() || textkey->first > targetTime)
|
||||||
{
|
{
|
||||||
//if(mNonAccumCtrl && stateiter->first == mAnimationTimePtr[0]->getAnimName())
|
if(mAccumCtrl && stateiter->first == mAnimationTimePtr[0]->getAnimName())
|
||||||
// updatePosition(state.mTime, targetTime, movement);
|
updatePosition(state.mTime, targetTime, movement);
|
||||||
state.mTime = std::min(targetTime, state.mStopTime);
|
state.mTime = std::min(targetTime, state.mStopTime);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//if(mNonAccumCtrl && stateiter->first == mAnimationTimePtr[0]->getAnimName())
|
if(mAccumCtrl && stateiter->first == mAnimationTimePtr[0]->getAnimName())
|
||||||
// updatePosition(state.mTime, textkey->first, movement);
|
updatePosition(state.mTime, textkey->first, movement);
|
||||||
state.mTime = textkey->first;
|
state.mTime = textkey->first;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -779,9 +814,12 @@ namespace MWRender
|
||||||
{
|
{
|
||||||
mObjectRoot->getParent(0)->removeChild(mObjectRoot);
|
mObjectRoot->getParent(0)->removeChild(mObjectRoot);
|
||||||
}
|
}
|
||||||
|
mObjectRoot = NULL;
|
||||||
|
|
||||||
mNodeMap.clear();
|
mNodeMap.clear();
|
||||||
mAnimSourceControllers.clear();
|
mAnimSourceControllers.clear();
|
||||||
|
mAccumRoot = NULL;
|
||||||
|
mAccumCtrl = NULL;
|
||||||
|
|
||||||
mObjectRoot = mResourceSystem->getSceneManager()->createInstance(model, mInsert);
|
mObjectRoot = mResourceSystem->getSceneManager()->createInstance(model, mInsert);
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,8 @@ namespace NifOsg
|
||||||
namespace MWRender
|
namespace MWRender
|
||||||
{
|
{
|
||||||
|
|
||||||
|
class ResetAccumRootCallback;
|
||||||
|
|
||||||
class EffectAnimationTime : public SceneUtil::ControllerSource
|
class EffectAnimationTime : public SceneUtil::ControllerSource
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
@ -133,6 +135,9 @@ protected:
|
||||||
// The controller animating that node.
|
// The controller animating that node.
|
||||||
osg::ref_ptr<NifOsg::KeyframeController> mAccumCtrl;
|
osg::ref_ptr<NifOsg::KeyframeController> mAccumCtrl;
|
||||||
|
|
||||||
|
// Used to reset the position of the accumulation root every frame - the movement should be applied to the physics system
|
||||||
|
osg::ref_ptr<ResetAccumRootCallback> mResetAccumRootCallback;
|
||||||
|
|
||||||
// Keep track of keyframe controllers from external files that we added to our scene graph.
|
// Keep track of keyframe controllers from external files that we added to our scene graph.
|
||||||
// We may need to rebuild these controllers when the active animation groups / sources change.
|
// We may need to rebuild these controllers when the active animation groups / sources change.
|
||||||
typedef std::map<osg::ref_ptr<osg::Node>, osg::ref_ptr<NifOsg::KeyframeController> > AnimSourceControllerMap;
|
typedef std::map<osg::ref_ptr<osg::Node>, osg::ref_ptr<NifOsg::KeyframeController> > AnimSourceControllerMap;
|
||||||
|
@ -196,7 +201,7 @@ protected:
|
||||||
|
|
||||||
/* Updates the position of the accum root node for the given time, and
|
/* Updates the position of the accum root node for the given time, and
|
||||||
* returns the wanted movement vector from the previous time. */
|
* returns the wanted movement vector from the previous time. */
|
||||||
//void updatePosition(float oldtime, float newtime, Ogre::Vector3 &position);
|
void updatePosition(float oldtime, float newtime, osg::Vec3f& position);
|
||||||
|
|
||||||
/* Resets the animation to the time of the specified start marker, without
|
/* Resets the animation to the time of the specified start marker, without
|
||||||
* moving anything, and set the end time to the specified stop marker. If
|
* moving anything, and set the end time to the specified stop marker. If
|
||||||
|
|
|
@ -167,7 +167,6 @@ void Objects::insertNPC(const MWWorld::Ptr &ptr)
|
||||||
insertBegin(ptr);
|
insertBegin(ptr);
|
||||||
|
|
||||||
std::auto_ptr<NpcAnimation> anim (new NpcAnimation(ptr, osg::ref_ptr<osg::Group>(ptr.getRefData().getBaseNode()), mResourceSystem, 0));
|
std::auto_ptr<NpcAnimation> anim (new NpcAnimation(ptr, osg::ref_ptr<osg::Group>(ptr.getRefData().getBaseNode()), mResourceSystem, 0));
|
||||||
anim->play("idle2", 0, Animation::Group_All, false, 1.f, "loop start", "loop stop", 0.f, 50); //testing
|
|
||||||
|
|
||||||
if (anim->getObjectRoot())
|
if (anim->getObjectRoot())
|
||||||
anim->getObjectRoot()->addCullCallback(new SceneUtil::LightListCallback);
|
anim->getObjectRoot()->addCullCallback(new SceneUtil::LightListCallback);
|
||||||
|
|
Loading…
Reference in a new issue