mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-04-02 03:06:43 +00:00
Merge branch 'osgAnimation_basics' into 'master'
Collada animation support See merge request OpenMW/openmw!421
This commit is contained in:
commit
dc1bd8ec29
23 changed files with 622 additions and 116 deletions
|
@ -259,7 +259,7 @@ if(NOT HAVE_STDINT_H)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
find_package(OpenSceneGraph 3.3.4 REQUIRED osgDB osgViewer osgText osgGA osgParticle osgUtil osgFX osgShadow)
|
find_package(OpenSceneGraph 3.3.4 REQUIRED osgDB osgViewer osgText osgGA osgParticle osgUtil osgFX osgShadow osgAnimation)
|
||||||
include_directories(SYSTEM ${OPENSCENEGRAPH_INCLUDE_DIRS})
|
include_directories(SYSTEM ${OPENSCENEGRAPH_INCLUDE_DIRS})
|
||||||
|
|
||||||
set(USED_OSG_PLUGINS
|
set(USED_OSG_PLUGINS
|
||||||
|
|
|
@ -936,7 +936,7 @@ void split(const std::string &s, char delim, std::vector<std::string> &elems) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CharacterController::handleTextKey(const std::string &groupname, NifOsg::TextKeyMap::ConstIterator key, const NifOsg::TextKeyMap& map)
|
void CharacterController::handleTextKey(const std::string &groupname, SceneUtil::TextKeyMap::ConstIterator key, const SceneUtil::TextKeyMap& map)
|
||||||
{
|
{
|
||||||
const std::string &evt = key->second;
|
const std::string &evt = key->second;
|
||||||
|
|
||||||
|
|
|
@ -241,7 +241,7 @@ public:
|
||||||
CharacterController(const MWWorld::Ptr &ptr, MWRender::Animation *anim);
|
CharacterController(const MWWorld::Ptr &ptr, MWRender::Animation *anim);
|
||||||
virtual ~CharacterController();
|
virtual ~CharacterController();
|
||||||
|
|
||||||
void handleTextKey(const std::string &groupname, NifOsg::TextKeyMap::ConstIterator key, const NifOsg::TextKeyMap& map) override;
|
void handleTextKey(const std::string &groupname, SceneUtil::TextKeyMap::ConstIterator key, const SceneUtil::TextKeyMap& map) override;
|
||||||
|
|
||||||
// Be careful when to call this, see comment in Actors
|
// Be careful when to call this, see comment in Actors
|
||||||
void updateContinuousVfx();
|
void updateContinuousVfx();
|
||||||
|
|
|
@ -20,8 +20,7 @@
|
||||||
#include <components/misc/constants.hpp>
|
#include <components/misc/constants.hpp>
|
||||||
#include <components/misc/resourcehelpers.hpp>
|
#include <components/misc/resourcehelpers.hpp>
|
||||||
|
|
||||||
#include <components/nifosg/nifloader.hpp> // KeyframeHolder
|
#include <components/sceneutil/keyframe.hpp>
|
||||||
#include <components/nifosg/controller.hpp>
|
|
||||||
|
|
||||||
#include <components/vfs/manager.hpp>
|
#include <components/vfs/manager.hpp>
|
||||||
|
|
||||||
|
@ -148,7 +147,7 @@ namespace
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
float calcAnimVelocity(const NifOsg::TextKeyMap& keys, NifOsg::KeyframeController *nonaccumctrl,
|
float calcAnimVelocity(const SceneUtil::TextKeyMap& keys, SceneUtil::KeyframeController *nonaccumctrl,
|
||||||
const osg::Vec3f& accum, const std::string &groupname)
|
const osg::Vec3f& accum, const std::string &groupname)
|
||||||
{
|
{
|
||||||
const std::string start = groupname+": start";
|
const std::string start = groupname+": start";
|
||||||
|
@ -530,13 +529,13 @@ namespace MWRender
|
||||||
|
|
||||||
struct Animation::AnimSource
|
struct Animation::AnimSource
|
||||||
{
|
{
|
||||||
osg::ref_ptr<const NifOsg::KeyframeHolder> mKeyframes;
|
osg::ref_ptr<const SceneUtil::KeyframeHolder> mKeyframes;
|
||||||
|
|
||||||
typedef std::map<std::string, osg::ref_ptr<NifOsg::KeyframeController> > ControllerMap;
|
typedef std::map<std::string, osg::ref_ptr<SceneUtil::KeyframeController> > ControllerMap;
|
||||||
|
|
||||||
ControllerMap mControllerMap[Animation::sNumBlendMasks];
|
ControllerMap mControllerMap[Animation::sNumBlendMasks];
|
||||||
|
|
||||||
const NifOsg::TextKeyMap& getTextKeys() const;
|
const SceneUtil::TextKeyMap& getTextKeys() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
void UpdateVfxCallback::operator()(osg::Node* node, osg::NodeVisitor* nv)
|
void UpdateVfxCallback::operator()(osg::Node* node, osg::NodeVisitor* nv)
|
||||||
|
@ -688,7 +687,7 @@ namespace MWRender
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const NifOsg::TextKeyMap &Animation::AnimSource::getTextKeys() const
|
const SceneUtil::TextKeyMap &Animation::AnimSource::getTextKeys() const
|
||||||
{
|
{
|
||||||
return mKeyframes->mTextKeys;
|
return mKeyframes->mTextKeys;
|
||||||
}
|
}
|
||||||
|
@ -729,8 +728,6 @@ namespace MWRender
|
||||||
|
|
||||||
if(kfname.size() > 4 && kfname.compare(kfname.size()-4, 4, ".nif") == 0)
|
if(kfname.size() > 4 && kfname.compare(kfname.size()-4, 4, ".nif") == 0)
|
||||||
kfname.replace(kfname.size()-4, 4, ".kf");
|
kfname.replace(kfname.size()-4, 4, ".kf");
|
||||||
else
|
|
||||||
return;
|
|
||||||
|
|
||||||
addSingleAnimSource(kfname, baseModel);
|
addSingleAnimSource(kfname, baseModel);
|
||||||
|
|
||||||
|
@ -753,7 +750,7 @@ namespace MWRender
|
||||||
|
|
||||||
const NodeMap& nodeMap = getNodeMap();
|
const NodeMap& nodeMap = getNodeMap();
|
||||||
|
|
||||||
for (NifOsg::KeyframeHolder::KeyframeControllerMap::const_iterator it = animsrc->mKeyframes->mKeyframeControllers.begin();
|
for (SceneUtil::KeyframeHolder::KeyframeControllerMap::const_iterator it = animsrc->mKeyframes->mKeyframeControllers.begin();
|
||||||
it != animsrc->mKeyframes->mKeyframeControllers.end(); ++it)
|
it != animsrc->mKeyframes->mKeyframeControllers.end(); ++it)
|
||||||
{
|
{
|
||||||
std::string bonename = Misc::StringUtils::lowerCase(it->first);
|
std::string bonename = Misc::StringUtils::lowerCase(it->first);
|
||||||
|
@ -769,7 +766,7 @@ namespace MWRender
|
||||||
size_t blendMask = detectBlendMask(node);
|
size_t blendMask = detectBlendMask(node);
|
||||||
|
|
||||||
// clone the controller, because each Animation needs its own ControllerSource
|
// clone the controller, because each Animation needs its own ControllerSource
|
||||||
osg::ref_ptr<NifOsg::KeyframeController> cloned = new NifOsg::KeyframeController(*it->second, osg::CopyOp::SHALLOW_COPY);
|
osg::ref_ptr<SceneUtil::KeyframeController> cloned = osg::clone(it->second.get(), osg::CopyOp::SHALLOW_COPY);
|
||||||
cloned->setSource(mAnimationTimePtr[blendMask]);
|
cloned->setSource(mAnimationTimePtr[blendMask]);
|
||||||
|
|
||||||
animsrc->mControllerMap[blendMask].insert(std::make_pair(bonename, cloned));
|
animsrc->mControllerMap[blendMask].insert(std::make_pair(bonename, cloned));
|
||||||
|
@ -785,6 +782,8 @@ namespace MWRender
|
||||||
NodeMap::const_iterator found = nodeMap.find("bip01");
|
NodeMap::const_iterator found = nodeMap.find("bip01");
|
||||||
if (found == nodeMap.end())
|
if (found == nodeMap.end())
|
||||||
found = nodeMap.find("root bone");
|
found = nodeMap.find("root bone");
|
||||||
|
if (found == nodeMap.end())
|
||||||
|
found = nodeMap.find("root");
|
||||||
|
|
||||||
if (found != nodeMap.end())
|
if (found != nodeMap.end())
|
||||||
mAccumRoot = found->second;
|
mAccumRoot = found->second;
|
||||||
|
@ -810,7 +809,7 @@ namespace MWRender
|
||||||
AnimSourceList::const_iterator iter(mAnimSources.begin());
|
AnimSourceList::const_iterator iter(mAnimSources.begin());
|
||||||
for(;iter != mAnimSources.end();++iter)
|
for(;iter != mAnimSources.end();++iter)
|
||||||
{
|
{
|
||||||
const NifOsg::TextKeyMap &keys = (*iter)->getTextKeys();
|
const SceneUtil::TextKeyMap &keys = (*iter)->getTextKeys();
|
||||||
if (keys.hasGroupStart(anim))
|
if (keys.hasGroupStart(anim))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -822,7 +821,7 @@ namespace MWRender
|
||||||
{
|
{
|
||||||
for(AnimSourceList::const_reverse_iterator iter(mAnimSources.rbegin()); iter != mAnimSources.rend(); ++iter)
|
for(AnimSourceList::const_reverse_iterator iter(mAnimSources.rbegin()); iter != mAnimSources.rend(); ++iter)
|
||||||
{
|
{
|
||||||
const NifOsg::TextKeyMap &keys = (*iter)->getTextKeys();
|
const SceneUtil::TextKeyMap &keys = (*iter)->getTextKeys();
|
||||||
|
|
||||||
const auto found = keys.findGroupStart(groupname);
|
const auto found = keys.findGroupStart(groupname);
|
||||||
if(found != keys.end())
|
if(found != keys.end())
|
||||||
|
@ -835,7 +834,7 @@ namespace MWRender
|
||||||
{
|
{
|
||||||
for(AnimSourceList::const_reverse_iterator iter(mAnimSources.rbegin()); iter != mAnimSources.rend(); ++iter)
|
for(AnimSourceList::const_reverse_iterator iter(mAnimSources.rbegin()); iter != mAnimSources.rend(); ++iter)
|
||||||
{
|
{
|
||||||
const NifOsg::TextKeyMap &keys = (*iter)->getTextKeys();
|
const SceneUtil::TextKeyMap &keys = (*iter)->getTextKeys();
|
||||||
|
|
||||||
for(auto iterKey = keys.begin(); iterKey != keys.end(); ++iterKey)
|
for(auto iterKey = keys.begin(); iterKey != keys.end(); ++iterKey)
|
||||||
{
|
{
|
||||||
|
@ -847,8 +846,8 @@ namespace MWRender
|
||||||
return -1.f;
|
return -1.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Animation::handleTextKey(AnimState &state, const std::string &groupname, NifOsg::TextKeyMap::ConstIterator key,
|
void Animation::handleTextKey(AnimState &state, const std::string &groupname, SceneUtil::TextKeyMap::ConstIterator key,
|
||||||
const NifOsg::TextKeyMap& map)
|
const SceneUtil::TextKeyMap& map)
|
||||||
{
|
{
|
||||||
const std::string &evt = key->second;
|
const std::string &evt = key->second;
|
||||||
|
|
||||||
|
@ -911,7 +910,7 @@ namespace MWRender
|
||||||
AnimSourceList::reverse_iterator iter(mAnimSources.rbegin());
|
AnimSourceList::reverse_iterator iter(mAnimSources.rbegin());
|
||||||
for(;iter != mAnimSources.rend();++iter)
|
for(;iter != mAnimSources.rend();++iter)
|
||||||
{
|
{
|
||||||
const NifOsg::TextKeyMap &textkeys = (*iter)->getTextKeys();
|
const SceneUtil::TextKeyMap &textkeys = (*iter)->getTextKeys();
|
||||||
if(reset(state, textkeys, groupname, start, stop, startpoint, loopfallback))
|
if(reset(state, textkeys, groupname, start, stop, startpoint, loopfallback))
|
||||||
{
|
{
|
||||||
state.mSource = *iter;
|
state.mSource = *iter;
|
||||||
|
@ -956,7 +955,7 @@ namespace MWRender
|
||||||
resetActiveGroups();
|
resetActiveGroups();
|
||||||
}
|
}
|
||||||
|
|
||||||
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 SceneUtil::TextKeyMap &keys, const std::string &groupname, const std::string &start, const std::string &stop, float startpoint, bool loopfallback)
|
||||||
{
|
{
|
||||||
// Look for text keys in reverse. This normally wouldn't matter, but for some reason undeadwolf_2.nif has two
|
// Look for text keys in reverse. This normally wouldn't matter, but for some reason undeadwolf_2.nif has two
|
||||||
// separate walkforward keys, and the last one is supposed to be used.
|
// separate walkforward keys, and the last one is supposed to be used.
|
||||||
|
@ -1186,7 +1185,7 @@ namespace MWRender
|
||||||
AnimSourceList::const_reverse_iterator animsrc(mAnimSources.rbegin());
|
AnimSourceList::const_reverse_iterator animsrc(mAnimSources.rbegin());
|
||||||
for(;animsrc != mAnimSources.rend();++animsrc)
|
for(;animsrc != mAnimSources.rend();++animsrc)
|
||||||
{
|
{
|
||||||
const NifOsg::TextKeyMap &keys = (*animsrc)->getTextKeys();
|
const SceneUtil::TextKeyMap &keys = (*animsrc)->getTextKeys();
|
||||||
if (keys.hasGroupStart(groupname))
|
if (keys.hasGroupStart(groupname))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1194,7 +1193,7 @@ namespace MWRender
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
|
|
||||||
float velocity = 0.0f;
|
float velocity = 0.0f;
|
||||||
const NifOsg::TextKeyMap &keys = (*animsrc)->getTextKeys();
|
const SceneUtil::TextKeyMap &keys = (*animsrc)->getTextKeys();
|
||||||
|
|
||||||
const AnimSource::ControllerMap& ctrls = (*animsrc)->mControllerMap[0];
|
const AnimSource::ControllerMap& ctrls = (*animsrc)->mControllerMap[0];
|
||||||
for (AnimSource::ControllerMap::const_iterator it = ctrls.begin(); it != ctrls.end(); ++it)
|
for (AnimSource::ControllerMap::const_iterator it = ctrls.begin(); it != ctrls.end(); ++it)
|
||||||
|
@ -1215,7 +1214,7 @@ namespace MWRender
|
||||||
|
|
||||||
while(!(velocity > 1.0f) && ++animiter != mAnimSources.rend())
|
while(!(velocity > 1.0f) && ++animiter != mAnimSources.rend())
|
||||||
{
|
{
|
||||||
const NifOsg::TextKeyMap &keys2 = (*animiter)->getTextKeys();
|
const SceneUtil::TextKeyMap &keys2 = (*animiter)->getTextKeys();
|
||||||
|
|
||||||
const AnimSource::ControllerMap& ctrls2 = (*animiter)->mControllerMap[0];
|
const AnimSource::ControllerMap& ctrls2 = (*animiter)->mControllerMap[0];
|
||||||
for (AnimSource::ControllerMap::const_iterator it = ctrls2.begin(); it != ctrls2.end(); ++it)
|
for (AnimSource::ControllerMap::const_iterator it = ctrls2.begin(); it != ctrls2.end(); ++it)
|
||||||
|
@ -1265,7 +1264,7 @@ namespace MWRender
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const NifOsg::TextKeyMap &textkeys = state.mSource->getTextKeys();
|
const SceneUtil::TextKeyMap &textkeys = state.mSource->getTextKeys();
|
||||||
auto textkey = textkeys.upperBound(state.getTime());
|
auto textkey = textkeys.upperBound(state.getTime());
|
||||||
|
|
||||||
float timepassed = duration * state.mSpeedMult;
|
float timepassed = duration * state.mSpeedMult;
|
||||||
|
@ -1839,7 +1838,7 @@ namespace MWRender
|
||||||
osg::Callback* cb = node->getUpdateCallback();
|
osg::Callback* cb = node->getUpdateCallback();
|
||||||
while (cb)
|
while (cb)
|
||||||
{
|
{
|
||||||
if (dynamic_cast<NifOsg::KeyframeController*>(cb))
|
if (dynamic_cast<SceneUtil::KeyframeController*>(cb))
|
||||||
{
|
{
|
||||||
foundKeyframeCtrl = true;
|
foundKeyframeCtrl = true;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
|
|
||||||
#include <components/sceneutil/controller.hpp>
|
#include <components/sceneutil/controller.hpp>
|
||||||
|
#include <components/sceneutil/textkeymap.hpp>
|
||||||
#include <components/sceneutil/util.hpp>
|
#include <components/sceneutil/util.hpp>
|
||||||
#include <components/nifosg/textkeymap.hpp>
|
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
@ -20,14 +20,10 @@ namespace Resource
|
||||||
class ResourceSystem;
|
class ResourceSystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace NifOsg
|
namespace SceneUtil
|
||||||
{
|
{
|
||||||
class KeyframeHolder;
|
class KeyframeHolder;
|
||||||
class KeyframeController;
|
class KeyframeController;
|
||||||
}
|
|
||||||
|
|
||||||
namespace SceneUtil
|
|
||||||
{
|
|
||||||
class LightSource;
|
class LightSource;
|
||||||
class LightListCallback;
|
class LightListCallback;
|
||||||
class Skeleton;
|
class Skeleton;
|
||||||
|
@ -150,8 +146,8 @@ public:
|
||||||
class TextKeyListener
|
class TextKeyListener
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void handleTextKey(const std::string &groupname, NifOsg::TextKeyMap::ConstIterator key,
|
virtual void handleTextKey(const std::string &groupname, SceneUtil::TextKeyMap::ConstIterator key,
|
||||||
const NifOsg::TextKeyMap& map) = 0;
|
const SceneUtil::TextKeyMap& map) = 0;
|
||||||
|
|
||||||
virtual ~TextKeyListener() = default;
|
virtual ~TextKeyListener() = default;
|
||||||
};
|
};
|
||||||
|
@ -242,7 +238,7 @@ protected:
|
||||||
osg::ref_ptr<osg::Node> mAccumRoot;
|
osg::ref_ptr<osg::Node> mAccumRoot;
|
||||||
|
|
||||||
// The controller animating that node.
|
// The controller animating that node.
|
||||||
osg::ref_ptr<NifOsg::KeyframeController> mAccumCtrl;
|
osg::ref_ptr<SceneUtil::KeyframeController> mAccumCtrl;
|
||||||
|
|
||||||
// Used to reset the position of the accumulation root every frame - the movement should be applied to the physics system
|
// 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;
|
osg::ref_ptr<ResetAccumRootCallback> mResetAccumRootCallback;
|
||||||
|
@ -306,12 +302,12 @@ protected:
|
||||||
* the marker is not found, or if the markers are the same, it returns
|
* the marker is not found, or if the markers are the same, it returns
|
||||||
* false.
|
* false.
|
||||||
*/
|
*/
|
||||||
bool reset(AnimState &state, const NifOsg::TextKeyMap &keys,
|
bool reset(AnimState &state, const SceneUtil::TextKeyMap &keys,
|
||||||
const std::string &groupname, const std::string &start, const std::string &stop,
|
const std::string &groupname, const std::string &start, const std::string &stop,
|
||||||
float startpoint, bool loopfallback);
|
float startpoint, bool loopfallback);
|
||||||
|
|
||||||
void handleTextKey(AnimState &state, const std::string &groupname, NifOsg::TextKeyMap::ConstIterator key,
|
void handleTextKey(AnimState &state, const std::string &groupname, SceneUtil::TextKeyMap::ConstIterator key,
|
||||||
const NifOsg::TextKeyMap& map);
|
const SceneUtil::TextKeyMap& map);
|
||||||
|
|
||||||
/** Sets the root model of the object.
|
/** Sets the root model of the object.
|
||||||
*
|
*
|
||||||
|
|
|
@ -19,11 +19,10 @@
|
||||||
#include <components/sceneutil/attach.hpp>
|
#include <components/sceneutil/attach.hpp>
|
||||||
#include <components/sceneutil/visitor.hpp>
|
#include <components/sceneutil/visitor.hpp>
|
||||||
#include <components/sceneutil/skeleton.hpp>
|
#include <components/sceneutil/skeleton.hpp>
|
||||||
|
#include <components/sceneutil/keyframe.hpp>
|
||||||
|
|
||||||
#include <components/settings/settings.hpp>
|
#include <components/settings/settings.hpp>
|
||||||
|
|
||||||
#include <components/nifosg/nifloader.hpp> // TextKeyMapHolder
|
|
||||||
|
|
||||||
#include <components/vfs/manager.hpp>
|
#include <components/vfs/manager.hpp>
|
||||||
|
|
||||||
#include "../mwworld/esmstore.hpp"
|
#include "../mwworld/esmstore.hpp"
|
||||||
|
@ -864,7 +863,7 @@ bool NpcAnimation::addOrReplaceIndividualPart(ESM::PartReferenceType type, int g
|
||||||
for (unsigned int i=0; i<node->getUserDataContainer()->getNumUserObjects(); ++i)
|
for (unsigned int i=0; i<node->getUserDataContainer()->getNumUserObjects(); ++i)
|
||||||
{
|
{
|
||||||
osg::Object* obj = node->getUserDataContainer()->getUserObject(i);
|
osg::Object* obj = node->getUserDataContainer()->getUserObject(i);
|
||||||
if (NifOsg::TextKeyMapHolder* keys = dynamic_cast<NifOsg::TextKeyMapHolder*>(obj))
|
if (SceneUtil::TextKeyMapHolder* keys = dynamic_cast<SceneUtil::TextKeyMapHolder*>(obj))
|
||||||
{
|
{
|
||||||
for (const auto &key : keys->mTextKeys)
|
for (const auto &key : keys->mTextKeys)
|
||||||
{
|
{
|
||||||
|
|
|
@ -41,7 +41,8 @@ add_component_dir (vfs
|
||||||
)
|
)
|
||||||
|
|
||||||
add_component_dir (resource
|
add_component_dir (resource
|
||||||
scenemanager keyframemanager imagemanager bulletshapemanager bulletshape niffilemanager objectcache multiobjectcache resourcesystem resourcemanager stats
|
scenemanager keyframemanager imagemanager bulletshapemanager bulletshape niffilemanager objectcache multiobjectcache resourcesystem
|
||||||
|
resourcemanager stats animation
|
||||||
)
|
)
|
||||||
|
|
||||||
add_component_dir (shader
|
add_component_dir (shader
|
||||||
|
@ -51,7 +52,7 @@ add_component_dir (shader
|
||||||
add_component_dir (sceneutil
|
add_component_dir (sceneutil
|
||||||
clone attach visitor util statesetupdater controller skeleton riggeometry morphgeometry lightcontroller
|
clone attach visitor util statesetupdater controller skeleton riggeometry morphgeometry lightcontroller
|
||||||
lightmanager lightutil positionattitudetransform workqueue unrefqueue pathgridutil waterutil writescene serialize optimizer
|
lightmanager lightutil positionattitudetransform workqueue unrefqueue pathgridutil waterutil writescene serialize optimizer
|
||||||
actorutil detourdebugdraw navmesh agentpath shadow mwshadowtechnique recastmesh shadowsbin
|
actorutil detourdebugdraw navmesh agentpath shadow mwshadowtechnique recastmesh shadowsbin osgacontroller
|
||||||
)
|
)
|
||||||
|
|
||||||
add_component_dir (nif
|
add_component_dir (nif
|
||||||
|
|
|
@ -71,8 +71,7 @@ KeyframeController::KeyframeController()
|
||||||
}
|
}
|
||||||
|
|
||||||
KeyframeController::KeyframeController(const KeyframeController ©, const osg::CopyOp ©op)
|
KeyframeController::KeyframeController(const KeyframeController ©, const osg::CopyOp ©op)
|
||||||
: osg::NodeCallback(copy, copyop)
|
: SceneUtil::KeyframeController(copy, copyop)
|
||||||
, Controller(copy)
|
|
||||||
, mRotations(copy.mRotations)
|
, mRotations(copy.mRotations)
|
||||||
, mXRotations(copy.mXRotations)
|
, mXRotations(copy.mXRotations)
|
||||||
, mYRotations(copy.mYRotations)
|
, mYRotations(copy.mYRotations)
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
#include <components/nif/controller.hpp>
|
#include <components/nif/controller.hpp>
|
||||||
#include <components/nif/data.hpp>
|
#include <components/nif/data.hpp>
|
||||||
|
|
||||||
#include <components/sceneutil/controller.hpp>
|
#include <components/sceneutil/keyframe.hpp>
|
||||||
#include <components/sceneutil/statesetupdater.hpp>
|
#include <components/sceneutil/statesetupdater.hpp>
|
||||||
|
|
||||||
#include <set>
|
#include <set>
|
||||||
|
@ -226,7 +226,7 @@ namespace NifOsg
|
||||||
std::vector<FloatInterpolator> mKeyFrames;
|
std::vector<FloatInterpolator> mKeyFrames;
|
||||||
};
|
};
|
||||||
|
|
||||||
class KeyframeController : public osg::NodeCallback, public SceneUtil::Controller
|
class KeyframeController : public SceneUtil::KeyframeController
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// This is used if there's no interpolator but there is data (Morrowind meshes).
|
// This is used if there's no interpolator but there is data (Morrowind meshes).
|
||||||
|
@ -242,7 +242,7 @@ namespace NifOsg
|
||||||
|
|
||||||
META_Object(NifOsg, KeyframeController)
|
META_Object(NifOsg, KeyframeController)
|
||||||
|
|
||||||
virtual osg::Vec3f getTranslation(float time) const;
|
osg::Vec3f getTranslation(float time) const override;
|
||||||
|
|
||||||
void operator() (osg::Node*, osg::NodeVisitor*) override;
|
void operator() (osg::Node*, osg::NodeVisitor*) override;
|
||||||
|
|
||||||
|
|
|
@ -139,7 +139,7 @@ namespace
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void extractTextKeys(const Nif::NiTextKeyExtraData *tk, NifOsg::TextKeyMap &textkeys)
|
void extractTextKeys(const Nif::NiTextKeyExtraData *tk, SceneUtil::TextKeyMap &textkeys)
|
||||||
{
|
{
|
||||||
for(size_t i = 0;i < tk->list.size();i++)
|
for(size_t i = 0;i < tk->list.size();i++)
|
||||||
{
|
{
|
||||||
|
@ -234,7 +234,7 @@ namespace NifOsg
|
||||||
// This is used to queue emitters that weren't attached to their node yet.
|
// This is used to queue emitters that weren't attached to their node yet.
|
||||||
std::vector<std::pair<size_t, osg::ref_ptr<Emitter>>> mEmitterQueue;
|
std::vector<std::pair<size_t, osg::ref_ptr<Emitter>>> mEmitterQueue;
|
||||||
|
|
||||||
static void loadKf(Nif::NIFFilePtr nif, KeyframeHolder& target)
|
static void loadKf(Nif::NIFFilePtr nif, SceneUtil::KeyframeHolder& target)
|
||||||
{
|
{
|
||||||
const Nif::NiSequenceStreamHelper *seq = nullptr;
|
const Nif::NiSequenceStreamHelper *seq = nullptr;
|
||||||
const size_t numRoots = nif->numRoots();
|
const size_t numRoots = nif->numRoots();
|
||||||
|
@ -284,7 +284,7 @@ namespace NifOsg
|
||||||
if (key->data.empty() && key->interpolator.empty())
|
if (key->data.empty() && key->interpolator.empty())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
osg::ref_ptr<NifOsg::KeyframeController> callback(handleKeyframeController(key));
|
osg::ref_ptr<SceneUtil::KeyframeController> callback(handleKeyframeController(key));
|
||||||
callback->setFunction(std::shared_ptr<NifOsg::ControllerFunction>(new NifOsg::ControllerFunction(key)));
|
callback->setFunction(std::shared_ptr<NifOsg::ControllerFunction>(new NifOsg::ControllerFunction(key)));
|
||||||
|
|
||||||
if (!target.mKeyframeControllers.emplace(strdata->string, callback).second)
|
if (!target.mKeyframeControllers.emplace(strdata->string, callback).second)
|
||||||
|
@ -305,7 +305,7 @@ namespace NifOsg
|
||||||
if (!nifNode)
|
if (!nifNode)
|
||||||
nif->fail("Found no root nodes");
|
nif->fail("Found no root nodes");
|
||||||
|
|
||||||
osg::ref_ptr<TextKeyMapHolder> textkeys (new TextKeyMapHolder);
|
osg::ref_ptr<SceneUtil::TextKeyMapHolder> textkeys (new SceneUtil::TextKeyMapHolder);
|
||||||
|
|
||||||
osg::ref_ptr<osg::Node> created = handleNode(nifNode, nullptr, imageManager, std::vector<unsigned int>(), 0, false, false, false, &textkeys->mTextKeys);
|
osg::ref_ptr<osg::Node> created = handleNode(nifNode, nullptr, imageManager, std::vector<unsigned int>(), 0, false, false, false, &textkeys->mTextKeys);
|
||||||
|
|
||||||
|
@ -353,10 +353,10 @@ namespace NifOsg
|
||||||
else if (props[i].getPtr()->recType == Nif::RC_NiTexturingProperty)
|
else if (props[i].getPtr()->recType == Nif::RC_NiTexturingProperty)
|
||||||
{
|
{
|
||||||
if (props[i].getPtr()->recIndex == mFirstRootTextureIndex)
|
if (props[i].getPtr()->recIndex == mFirstRootTextureIndex)
|
||||||
applyTo->setUserValue("overrideFx", 1);
|
applyTo->setUserValue("overrideFx", 1);
|
||||||
}
|
}
|
||||||
handleProperty(props[i].getPtr(), applyTo, composite, imageManager, boundTextures, animflags);
|
handleProperty(props[i].getPtr(), applyTo, composite, imageManager, boundTextures, animflags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -514,7 +514,7 @@ namespace NifOsg
|
||||||
}
|
}
|
||||||
|
|
||||||
osg::ref_ptr<osg::Node> handleNode(const Nif::Node* nifNode, osg::Group* parentNode, Resource::ImageManager* imageManager,
|
osg::ref_ptr<osg::Node> handleNode(const Nif::Node* nifNode, osg::Group* parentNode, Resource::ImageManager* imageManager,
|
||||||
std::vector<unsigned int> boundTextures, int animflags, bool skipMeshes, bool hasMarkers, bool hasAnimatedParents, TextKeyMap* textKeys, osg::Node* rootNode=nullptr)
|
std::vector<unsigned int> boundTextures, int animflags, bool skipMeshes, bool hasMarkers, bool hasAnimatedParents, SceneUtil::TextKeyMap* textKeys, osg::Node* rootNode=nullptr)
|
||||||
{
|
{
|
||||||
if (rootNode != nullptr && Misc::StringUtils::ciEqual(nifNode->name, "Bounding Box"))
|
if (rootNode != nullptr && Misc::StringUtils::ciEqual(nifNode->name, "Bounding Box"))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -1197,7 +1197,7 @@ namespace NifOsg
|
||||||
for (const auto& strip : data->strips)
|
for (const auto& strip : data->strips)
|
||||||
{
|
{
|
||||||
if (strip.size() >= 3)
|
if (strip.size() >= 3)
|
||||||
geometry->addPrimitiveSet(new osg::DrawElementsUShort(osg::PrimitiveSet::TRIANGLE_STRIP, strip.size(),
|
geometry->addPrimitiveSet(new osg::DrawElementsUShort(osg::PrimitiveSet::TRIANGLE_STRIP, strip.size(),
|
||||||
(unsigned short*)strip.data()));
|
(unsigned short*)strip.data()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1929,7 +1929,7 @@ namespace NifOsg
|
||||||
return impl.load(file, imageManager);
|
return impl.load(file, imageManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Loader::loadKf(Nif::NIFFilePtr kf, KeyframeHolder& target)
|
void Loader::loadKf(Nif::NIFFilePtr kf, SceneUtil::KeyframeHolder& target)
|
||||||
{
|
{
|
||||||
LoaderImpl impl(kf->getFilename(), kf->getVersion(), kf->getUserVersion(), kf->getBethVersion());
|
LoaderImpl impl(kf->getFilename(), kf->getVersion(), kf->getUserVersion(), kf->getBethVersion());
|
||||||
impl.loadKf(kf, target);
|
impl.loadKf(kf, target);
|
||||||
|
|
|
@ -2,12 +2,13 @@
|
||||||
#define OPENMW_COMPONENTS_NIFOSG_LOADER
|
#define OPENMW_COMPONENTS_NIFOSG_LOADER
|
||||||
|
|
||||||
#include <components/nif/niffile.hpp>
|
#include <components/nif/niffile.hpp>
|
||||||
|
#include <components/sceneutil/keyframe.hpp>
|
||||||
|
#include <components/sceneutil/textkeymap.hpp>
|
||||||
|
|
||||||
#include <osg/ref_ptr>
|
#include <osg/ref_ptr>
|
||||||
#include <osg/Referenced>
|
#include <osg/Referenced>
|
||||||
|
|
||||||
#include "controller.hpp"
|
#include "controller.hpp"
|
||||||
#include "textkeymap.hpp"
|
|
||||||
|
|
||||||
namespace osg
|
namespace osg
|
||||||
{
|
{
|
||||||
|
@ -21,39 +22,6 @@ namespace Resource
|
||||||
|
|
||||||
namespace NifOsg
|
namespace NifOsg
|
||||||
{
|
{
|
||||||
struct TextKeyMapHolder : public osg::Object
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TextKeyMapHolder() {}
|
|
||||||
TextKeyMapHolder(const TextKeyMapHolder& copy, const osg::CopyOp& copyop)
|
|
||||||
: osg::Object(copy, copyop)
|
|
||||||
, mTextKeys(copy.mTextKeys)
|
|
||||||
{}
|
|
||||||
|
|
||||||
TextKeyMap mTextKeys;
|
|
||||||
|
|
||||||
META_Object(NifOsg, TextKeyMapHolder)
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
class KeyframeHolder : public osg::Object
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
KeyframeHolder() {}
|
|
||||||
KeyframeHolder(const KeyframeHolder& copy, const osg::CopyOp& copyop)
|
|
||||||
: mTextKeys(copy.mTextKeys)
|
|
||||||
, mKeyframeControllers(copy.mKeyframeControllers)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
TextKeyMap mTextKeys;
|
|
||||||
|
|
||||||
META_Object(OpenMW, KeyframeHolder)
|
|
||||||
|
|
||||||
typedef std::map<std::string, osg::ref_ptr<const KeyframeController> > KeyframeControllerMap;
|
|
||||||
KeyframeControllerMap mKeyframeControllers;
|
|
||||||
};
|
|
||||||
|
|
||||||
/// The main class responsible for loading NIF files into an OSG-Scenegraph.
|
/// The main class responsible for loading NIF files into an OSG-Scenegraph.
|
||||||
/// @par This scene graph is self-contained and can be cloned using osg::clone if desired. Particle emitters
|
/// @par This scene graph is self-contained and can be cloned using osg::clone if desired. Particle emitters
|
||||||
/// and programs hold a pointer to their ParticleSystem, which would need to be manually updated when cloning.
|
/// and programs hold a pointer to their ParticleSystem, which would need to be manually updated when cloning.
|
||||||
|
@ -64,7 +32,7 @@ namespace NifOsg
|
||||||
static osg::ref_ptr<osg::Node> load(Nif::NIFFilePtr file, Resource::ImageManager* imageManager);
|
static osg::ref_ptr<osg::Node> load(Nif::NIFFilePtr file, Resource::ImageManager* imageManager);
|
||||||
|
|
||||||
/// Load keyframe controllers from the given kf file.
|
/// Load keyframe controllers from the given kf file.
|
||||||
static void loadKf(Nif::NIFFilePtr kf, KeyframeHolder& target);
|
static void loadKf(Nif::NIFFilePtr kf, SceneUtil::KeyframeHolder& target);
|
||||||
|
|
||||||
/// Set whether or not nodes marked as "MRK" should be shown.
|
/// Set whether or not nodes marked as "MRK" should be shown.
|
||||||
/// These should be hidden ingame, but visible in the editor.
|
/// These should be hidden ingame, but visible in the editor.
|
||||||
|
|
40
components/resource/animation.cpp
Normal file
40
components/resource/animation.cpp
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
#include <components/resource/animation.hpp>
|
||||||
|
|
||||||
|
#include <osg/ref_ptr>
|
||||||
|
#include <osgAnimation/Channel>
|
||||||
|
|
||||||
|
namespace Resource
|
||||||
|
{
|
||||||
|
Animation::Animation(const Animation& anim, const osg::CopyOp& copyop): osg::Object(anim, copyop),
|
||||||
|
mDuration(0.0f),
|
||||||
|
mStartTime(0.0f)
|
||||||
|
{
|
||||||
|
const osgAnimation::ChannelList& channels = anim.getChannels();
|
||||||
|
for (const osg::ref_ptr<osgAnimation::Channel> channel: channels)
|
||||||
|
addChannel(channel.get()->clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Animation::addChannel(osg::ref_ptr<osgAnimation::Channel> pChannel)
|
||||||
|
{
|
||||||
|
mChannels.push_back(pChannel);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<osg::ref_ptr<osgAnimation::Channel>>& Animation::getChannels()
|
||||||
|
{
|
||||||
|
return mChannels;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<osg::ref_ptr<osgAnimation::Channel>>& Animation::getChannels() const
|
||||||
|
{
|
||||||
|
return mChannels;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Animation::update (double time)
|
||||||
|
{
|
||||||
|
for (const osg::ref_ptr<osgAnimation::Channel> channel: mChannels)
|
||||||
|
{
|
||||||
|
channel->update(time, 1.0f, 0);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
39
components/resource/animation.hpp
Normal file
39
components/resource/animation.hpp
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
#ifndef OPENMW_COMPONENTS_RESOURCE_ANIMATION_HPP
|
||||||
|
#define OPENMW_COMPONENTS_RESOURCE_ANIMATION_HPP
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <osg/Node>
|
||||||
|
#include <osg/Object>
|
||||||
|
#include <osgAnimation/Channel>
|
||||||
|
|
||||||
|
namespace Resource
|
||||||
|
{
|
||||||
|
/// Stripped down class of osgAnimation::Animation, only needed for OSG's plugin formats like dae
|
||||||
|
class Animation : public osg::Object
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
META_Object(Resource, Animation)
|
||||||
|
|
||||||
|
Animation() :
|
||||||
|
mDuration(0.0), mStartTime(0) {}
|
||||||
|
|
||||||
|
Animation(const Animation&, const osg::CopyOp&);
|
||||||
|
~Animation() {}
|
||||||
|
|
||||||
|
void addChannel (osg::ref_ptr<osgAnimation::Channel> pChannel);
|
||||||
|
|
||||||
|
std::vector<osg::ref_ptr<osgAnimation::Channel>>& getChannels();
|
||||||
|
|
||||||
|
const std::vector<osg::ref_ptr<osgAnimation::Channel>>& getChannels() const;
|
||||||
|
|
||||||
|
bool update (double time);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
double mDuration;
|
||||||
|
double mStartTime;
|
||||||
|
std::vector<osg::ref_ptr<osgAnimation::Channel>> mChannels;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -2,13 +2,88 @@
|
||||||
|
|
||||||
#include <components/vfs/manager.hpp>
|
#include <components/vfs/manager.hpp>
|
||||||
|
|
||||||
|
#include <osgAnimation/Animation>
|
||||||
|
#include <osgAnimation/BasicAnimationManager>
|
||||||
|
#include <osgAnimation/Channel>
|
||||||
|
|
||||||
|
#include <components/nifosg/nifloader.hpp>
|
||||||
|
#include <components/sceneutil/keyframe.hpp>
|
||||||
|
#include <components/sceneutil/osgacontroller.hpp>
|
||||||
|
|
||||||
|
#include "animation.hpp"
|
||||||
#include "objectcache.hpp"
|
#include "objectcache.hpp"
|
||||||
|
#include "scenemanager.hpp"
|
||||||
|
|
||||||
namespace Resource
|
namespace Resource
|
||||||
{
|
{
|
||||||
|
|
||||||
KeyframeManager::KeyframeManager(const VFS::Manager* vfs)
|
RetrieveAnimationsVisitor::RetrieveAnimationsVisitor(SceneUtil::KeyframeHolder& target, osg::ref_ptr<osgAnimation::BasicAnimationManager> animationManager) : osg::NodeVisitor(TRAVERSE_ALL_CHILDREN), mTarget(target), mAnimationManager(animationManager) {}
|
||||||
|
|
||||||
|
void RetrieveAnimationsVisitor::apply(osg::Node& node)
|
||||||
|
{
|
||||||
|
if (node.libraryName() == std::string("osgAnimation") && node.className() == std::string("Bone") && node.getName() == std::string("root"))
|
||||||
|
{
|
||||||
|
osg::ref_ptr<SceneUtil::OsgAnimationController> callback = new SceneUtil::OsgAnimationController();
|
||||||
|
|
||||||
|
std::vector<SceneUtil::EmulatedAnimation> emulatedAnimations;
|
||||||
|
|
||||||
|
for (auto animation : mAnimationManager->getAnimationList())
|
||||||
|
{
|
||||||
|
if (animation)
|
||||||
|
{
|
||||||
|
if (animation->getName() == "Default") //"Default" is osg dae plugin's default naming scheme for unnamed animations
|
||||||
|
{
|
||||||
|
animation->setName(std::string("idle")); // animation naming scheme "idle: start" and "idle: stop" is the default idle animation that OpenMW seems to want to play
|
||||||
|
}
|
||||||
|
|
||||||
|
osg::ref_ptr<Resource::Animation> mergedAnimationTrack = new Resource::Animation;
|
||||||
|
std::string animationName = animation->getName();
|
||||||
|
std::string start = animationName + std::string(": start");
|
||||||
|
std::string stop = animationName + std::string(": stop");
|
||||||
|
std::string loopstart = animationName + std::string(": loop start");
|
||||||
|
std::string loopstop = animationName + std::string(": loop stop");
|
||||||
|
|
||||||
|
const osgAnimation::ChannelList& channels = animation->getChannels();
|
||||||
|
for (const osg::ref_ptr<osgAnimation::Channel> channel: channels)
|
||||||
|
{
|
||||||
|
mergedAnimationTrack->addChannel(channel.get()->clone()); // is ->clone needed?
|
||||||
|
}
|
||||||
|
mergedAnimationTrack->setName(animation->getName());
|
||||||
|
callback->addMergedAnimationTrack(mergedAnimationTrack);
|
||||||
|
|
||||||
|
float startTime = animation->getStartTime();
|
||||||
|
float stopTime = startTime + animation->getDuration();
|
||||||
|
|
||||||
|
// mTextKeys is a nif-thing, used by OpenMW's animation system
|
||||||
|
// Format is likely "AnimationName: [Keyword_optional] [Start OR Stop]"
|
||||||
|
// AnimationNames are keywords like idle2, idle3... AiPackages and various mechanics control which animations are played
|
||||||
|
// Keywords can be stuff like Loop, Equip, Unequip, Block, InventoryHandtoHand, InventoryWeaponOneHand, PickProbe, Slash, Thrust, Chop... even "Slash Small Follow"
|
||||||
|
mTarget.mTextKeys.emplace(startTime, std::move(start));
|
||||||
|
mTarget.mTextKeys.emplace(stopTime, std::move(stop));
|
||||||
|
mTarget.mTextKeys.emplace(startTime, std::move(loopstart));
|
||||||
|
mTarget.mTextKeys.emplace(stopTime, std::move(loopstop));
|
||||||
|
|
||||||
|
SceneUtil::EmulatedAnimation emulatedAnimation;
|
||||||
|
emulatedAnimation.mStartTime = startTime;
|
||||||
|
emulatedAnimation.mStopTime = stopTime;
|
||||||
|
emulatedAnimation.mName = animationName;
|
||||||
|
emulatedAnimations.emplace_back(emulatedAnimation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
callback->setEmulatedAnimations(emulatedAnimations);
|
||||||
|
mTarget.mKeyframeControllers.emplace(node.getName(), callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
traverse(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Resource
|
||||||
|
{
|
||||||
|
|
||||||
|
KeyframeManager::KeyframeManager(const VFS::Manager* vfs, SceneManager* sceneManager)
|
||||||
: ResourceManager(vfs)
|
: ResourceManager(vfs)
|
||||||
|
, mSceneManager(sceneManager)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,19 +91,32 @@ namespace Resource
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
osg::ref_ptr<const NifOsg::KeyframeHolder> KeyframeManager::get(const std::string &name)
|
osg::ref_ptr<const SceneUtil::KeyframeHolder> KeyframeManager::get(const std::string &name)
|
||||||
{
|
{
|
||||||
std::string normalized = name;
|
std::string normalized = name;
|
||||||
mVFS->normalizeFilename(normalized);
|
mVFS->normalizeFilename(normalized);
|
||||||
|
|
||||||
osg::ref_ptr<osg::Object> obj = mCache->getRefFromObjectCache(normalized);
|
osg::ref_ptr<osg::Object> obj = mCache->getRefFromObjectCache(normalized);
|
||||||
if (obj)
|
if (obj)
|
||||||
return osg::ref_ptr<const NifOsg::KeyframeHolder>(static_cast<NifOsg::KeyframeHolder*>(obj.get()));
|
return osg::ref_ptr<const SceneUtil::KeyframeHolder>(static_cast<SceneUtil::KeyframeHolder*>(obj.get()));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
osg::ref_ptr<NifOsg::KeyframeHolder> loaded (new NifOsg::KeyframeHolder);
|
osg::ref_ptr<SceneUtil::KeyframeHolder> loaded (new SceneUtil::KeyframeHolder);
|
||||||
NifOsg::Loader::loadKf(Nif::NIFFilePtr(new Nif::NIFFile(mVFS->getNormalized(normalized), normalized)), *loaded.get());
|
std::string ext = Resource::getFileExtension(normalized);
|
||||||
|
if (ext == "kf")
|
||||||
|
{
|
||||||
|
NifOsg::Loader::loadKf(Nif::NIFFilePtr(new Nif::NIFFile(mVFS->getNormalized(normalized), normalized)), *loaded.get());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
osg::ref_ptr<osg::Node> scene = const_cast<osg::Node*> ( mSceneManager->getTemplate(normalized).get() );
|
||||||
|
osg::ref_ptr<osgAnimation::BasicAnimationManager> bam = dynamic_cast<osgAnimation::BasicAnimationManager*> (scene->getUpdateCallback());
|
||||||
|
if (bam)
|
||||||
|
{
|
||||||
|
Resource::RetrieveAnimationsVisitor rav(*loaded.get(), bam);
|
||||||
|
scene->accept(rav);
|
||||||
|
}
|
||||||
|
}
|
||||||
mCache->addEntryToObjectCache(normalized, loaded);
|
mCache->addEntryToObjectCache(normalized, loaded);
|
||||||
return loaded;
|
return loaded;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,28 +2,50 @@
|
||||||
#define OPENMW_COMPONENTS_KEYFRAMEMANAGER_H
|
#define OPENMW_COMPONENTS_KEYFRAMEMANAGER_H
|
||||||
|
|
||||||
#include <osg/ref_ptr>
|
#include <osg/ref_ptr>
|
||||||
|
#include <osgAnimation/BasicAnimationManager>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include <components/nifosg/nifloader.hpp>
|
#include <components/sceneutil/keyframe.hpp>
|
||||||
|
|
||||||
#include "resourcemanager.hpp"
|
#include "resourcemanager.hpp"
|
||||||
|
|
||||||
namespace Resource
|
namespace Resource
|
||||||
{
|
{
|
||||||
|
/// @brief extract animations to OpenMW's animation system
|
||||||
|
class RetrieveAnimationsVisitor : public osg::NodeVisitor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RetrieveAnimationsVisitor(SceneUtil::KeyframeHolder& target, osg::ref_ptr<osgAnimation::BasicAnimationManager> animationManager);
|
||||||
|
|
||||||
|
virtual void apply(osg::Node& node) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
SceneUtil::KeyframeHolder& mTarget;
|
||||||
|
osg::ref_ptr<osgAnimation::BasicAnimationManager> mAnimationManager;
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Resource
|
||||||
|
{
|
||||||
|
|
||||||
|
class SceneManager;
|
||||||
|
|
||||||
/// @brief Managing of keyframe resources
|
/// @brief Managing of keyframe resources
|
||||||
/// @note May be used from any thread.
|
/// @note May be used from any thread.
|
||||||
class KeyframeManager : public ResourceManager
|
class KeyframeManager : public ResourceManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
KeyframeManager(const VFS::Manager* vfs);
|
KeyframeManager(const VFS::Manager* vfs, SceneManager* sceneManager);
|
||||||
~KeyframeManager();
|
~KeyframeManager();
|
||||||
|
|
||||||
/// Retrieve a read-only keyframe resource by name (case-insensitive).
|
/// Retrieve a read-only keyframe resource by name (case-insensitive).
|
||||||
/// @note Throws an exception if the resource is not found.
|
/// @note Throws an exception if the resource is not found.
|
||||||
osg::ref_ptr<const NifOsg::KeyframeHolder> get(const std::string& name);
|
osg::ref_ptr<const SceneUtil::KeyframeHolder> get(const std::string& name);
|
||||||
|
|
||||||
void reportStats(unsigned int frameNumber, osg::Stats* stats) const override;
|
void reportStats(unsigned int frameNumber, osg::Stats* stats) const override;
|
||||||
|
private:
|
||||||
|
SceneManager* mSceneManager;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,9 +14,9 @@ namespace Resource
|
||||||
: mVFS(vfs)
|
: mVFS(vfs)
|
||||||
{
|
{
|
||||||
mNifFileManager.reset(new NifFileManager(vfs));
|
mNifFileManager.reset(new NifFileManager(vfs));
|
||||||
mKeyframeManager.reset(new KeyframeManager(vfs));
|
|
||||||
mImageManager.reset(new ImageManager(vfs));
|
mImageManager.reset(new ImageManager(vfs));
|
||||||
mSceneManager.reset(new SceneManager(vfs, mImageManager.get(), mNifFileManager.get()));
|
mSceneManager.reset(new SceneManager(vfs, mImageManager.get(), mNifFileManager.get()));
|
||||||
|
mKeyframeManager.reset(new KeyframeManager(vfs, mSceneManager.get()));
|
||||||
|
|
||||||
addResourceManager(mNifFileManager.get());
|
addResourceManager(mNifFileManager.get());
|
||||||
addResourceManager(mKeyframeManager.get());
|
addResourceManager(mKeyframeManager.get());
|
||||||
|
|
|
@ -338,17 +338,9 @@ namespace Resource
|
||||||
Resource::ImageManager* mImageManager;
|
Resource::ImageManager* mImageManager;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string getFileExtension(const std::string& file)
|
|
||||||
{
|
|
||||||
size_t extPos = file.find_last_of('.');
|
|
||||||
if (extPos != std::string::npos && extPos+1 < file.size())
|
|
||||||
return file.substr(extPos+1);
|
|
||||||
return std::string();
|
|
||||||
}
|
|
||||||
|
|
||||||
osg::ref_ptr<osg::Node> load (Files::IStreamPtr file, const std::string& normalizedFilename, Resource::ImageManager* imageManager, Resource::NifFileManager* nifFileManager)
|
osg::ref_ptr<osg::Node> load (Files::IStreamPtr file, const std::string& normalizedFilename, Resource::ImageManager* imageManager, Resource::NifFileManager* nifFileManager)
|
||||||
{
|
{
|
||||||
std::string ext = getFileExtension(normalizedFilename);
|
std::string ext = Resource::getFileExtension(normalizedFilename);
|
||||||
if (ext == "nif")
|
if (ext == "nif")
|
||||||
return NifOsg::Loader::load(nifFileManager->get(normalizedFilename), imageManager);
|
return NifOsg::Loader::load(nifFileManager->get(normalizedFilename), imageManager);
|
||||||
else
|
else
|
||||||
|
@ -492,7 +484,7 @@ namespace Resource
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
{
|
{
|
||||||
static const char * const sMeshTypes[] = { "nif", "osg", "osgt", "osgb", "osgx", "osg2" };
|
static const char * const sMeshTypes[] = { "nif", "osg", "osgt", "osgb", "osgx", "osg2", "dae" };
|
||||||
|
|
||||||
for (unsigned int i=0; i<sizeof(sMeshTypes)/sizeof(sMeshTypes[0]); ++i)
|
for (unsigned int i=0; i<sizeof(sMeshTypes)/sizeof(sMeshTypes[0]); ++i)
|
||||||
{
|
{
|
||||||
|
@ -780,4 +772,11 @@ namespace Resource
|
||||||
return shaderVisitor;
|
return shaderVisitor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string getFileExtension(const std::string& file)
|
||||||
|
{
|
||||||
|
size_t extPos = file.find_last_of('.');
|
||||||
|
if (extPos != std::string::npos && extPos+1 < file.size())
|
||||||
|
return file.substr(extPos+1);
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -181,6 +181,7 @@ namespace Resource
|
||||||
void operator = (const SceneManager&);
|
void operator = (const SceneManager&);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::string getFileExtension(const std::string& file);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -2,6 +2,11 @@
|
||||||
|
|
||||||
#include <osg/StateSet>
|
#include <osg/StateSet>
|
||||||
|
|
||||||
|
#include <osgAnimation/Bone>
|
||||||
|
#include <osgAnimation/Skeleton>
|
||||||
|
#include <osgAnimation/MorphGeometry>
|
||||||
|
#include <osgAnimation/RigGeometry>
|
||||||
|
|
||||||
#include <osgParticle/ParticleProcessor>
|
#include <osgParticle/ParticleProcessor>
|
||||||
#include <osgParticle/ParticleSystemUpdater>
|
#include <osgParticle/ParticleSystemUpdater>
|
||||||
#include <osgParticle/Emitter>
|
#include <osgParticle/Emitter>
|
||||||
|
@ -30,6 +35,11 @@ namespace SceneUtil
|
||||||
mUpdaterToOldPs[cloned] = updater->getParticleSystem(0);
|
mUpdaterToOldPs[cloned] = updater->getParticleSystem(0);
|
||||||
return cloned;
|
return cloned;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dynamic_cast<const osgAnimation::Bone*>(node) || dynamic_cast<const osgAnimation::Skeleton*>(node))
|
||||||
|
{
|
||||||
|
return osg::clone(node, *this);
|
||||||
|
}
|
||||||
return osg::CopyOp::operator()(node);
|
return osg::CopyOp::operator()(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,7 +48,7 @@ namespace SceneUtil
|
||||||
if (const osgParticle::ParticleSystem* partsys = dynamic_cast<const osgParticle::ParticleSystem*>(drawable))
|
if (const osgParticle::ParticleSystem* partsys = dynamic_cast<const osgParticle::ParticleSystem*>(drawable))
|
||||||
return operator()(partsys);
|
return operator()(partsys);
|
||||||
|
|
||||||
if (dynamic_cast<const SceneUtil::RigGeometry*>(drawable) || dynamic_cast<const SceneUtil::MorphGeometry*>(drawable))
|
if (dynamic_cast<const SceneUtil::RigGeometry*>(drawable) || dynamic_cast<const SceneUtil::MorphGeometry*>(drawable) || dynamic_cast<const osgAnimation::RigGeometry*>(drawable) || dynamic_cast<const osgAnimation::MorphGeometry*>(drawable))
|
||||||
{
|
{
|
||||||
return static_cast<osg::Drawable*>(drawable->clone(*this));
|
return static_cast<osg::Drawable*>(drawable->clone(*this));
|
||||||
}
|
}
|
||||||
|
|
68
components/sceneutil/keyframe.hpp
Normal file
68
components/sceneutil/keyframe.hpp
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
#ifndef OPENMW_COMPONENTS_SCENEUTIL_KEYFRAME_HPP
|
||||||
|
#define OPENMW_COMPONENTS_SCENEUTIL_KEYFRAME_HPP
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include <osg/Node>
|
||||||
|
|
||||||
|
#include <components/sceneutil/controller.hpp>
|
||||||
|
#include <components/sceneutil/textkeymap.hpp>
|
||||||
|
#include <components/resource/animation.hpp>
|
||||||
|
|
||||||
|
namespace SceneUtil
|
||||||
|
{
|
||||||
|
class KeyframeController : public osg::NodeCallback, public SceneUtil::Controller
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
KeyframeController() {}
|
||||||
|
|
||||||
|
KeyframeController(const KeyframeController& copy, const osg::CopyOp& copyop)
|
||||||
|
: osg::NodeCallback(copy, copyop)
|
||||||
|
, SceneUtil::Controller(copy)
|
||||||
|
{}
|
||||||
|
META_Object(SceneUtil, KeyframeController)
|
||||||
|
|
||||||
|
virtual osg::Vec3f getTranslation(float time) const { return osg::Vec3f(); }
|
||||||
|
|
||||||
|
virtual void operator() (osg::Node* node, osg::NodeVisitor* nodeVisitor) override { traverse(node, nodeVisitor); }
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Wrapper object containing an animation track as a ref-countable osg::Object.
|
||||||
|
struct TextKeyMapHolder : public osg::Object
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TextKeyMapHolder() {}
|
||||||
|
TextKeyMapHolder(const TextKeyMapHolder& copy, const osg::CopyOp& copyop)
|
||||||
|
: osg::Object(copy, copyop)
|
||||||
|
, mTextKeys(copy.mTextKeys)
|
||||||
|
{}
|
||||||
|
|
||||||
|
TextKeyMap mTextKeys;
|
||||||
|
|
||||||
|
META_Object(SceneUtil, TextKeyMapHolder)
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Wrapper object containing the animation track and its KeyframeControllers.
|
||||||
|
class KeyframeHolder : public osg::Object
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
KeyframeHolder() {}
|
||||||
|
KeyframeHolder(const KeyframeHolder& copy, const osg::CopyOp& copyop)
|
||||||
|
: mTextKeys(copy.mTextKeys)
|
||||||
|
, mKeyframeControllers(copy.mKeyframeControllers)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
TextKeyMap mTextKeys;
|
||||||
|
|
||||||
|
META_Object(SceneUtil, KeyframeHolder)
|
||||||
|
|
||||||
|
/// Controllers mapped to node name.
|
||||||
|
typedef std::map<std::string, osg::ref_ptr<const KeyframeController> > KeyframeControllerMap;
|
||||||
|
KeyframeControllerMap mKeyframeControllers;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
197
components/sceneutil/osgacontroller.cpp
Normal file
197
components/sceneutil/osgacontroller.cpp
Normal file
|
@ -0,0 +1,197 @@
|
||||||
|
#include <components/sceneutil/osgacontroller.hpp>
|
||||||
|
|
||||||
|
#include <osg/Geode>
|
||||||
|
#include <osg/Node>
|
||||||
|
#include <osg/NodeVisitor>
|
||||||
|
#include <osg/ref_ptr>
|
||||||
|
#include <osg/StateSet>
|
||||||
|
|
||||||
|
#include <osgAnimation/Animation>
|
||||||
|
#include <osgAnimation/AnimationUpdateCallback>
|
||||||
|
#include <osgAnimation/Channel>
|
||||||
|
#include <osgAnimation/BasicAnimationManager>
|
||||||
|
#include <osgAnimation/Bone>
|
||||||
|
#include <osgAnimation/Sampler>
|
||||||
|
#include <osgAnimation/Skeleton>
|
||||||
|
#include <osgAnimation/RigGeometry>
|
||||||
|
#include <osgAnimation/UpdateMatrixTransform>
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
|
#include <components/resource/animation.hpp>
|
||||||
|
#include <components/sceneutil/controller.hpp>
|
||||||
|
#include <components/sceneutil/keyframe.hpp>
|
||||||
|
|
||||||
|
namespace SceneUtil
|
||||||
|
{
|
||||||
|
LinkVisitor::LinkVisitor() : osg::NodeVisitor( TRAVERSE_ALL_CHILDREN )
|
||||||
|
{
|
||||||
|
mAnimation = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LinkVisitor::link(osgAnimation::UpdateMatrixTransform* umt)
|
||||||
|
{
|
||||||
|
const osgAnimation::ChannelList& channels = mAnimation->getChannels();
|
||||||
|
for (const osg::ref_ptr<osgAnimation::Channel> channel: channels)
|
||||||
|
{
|
||||||
|
const std::string& channelName = channel->getName();
|
||||||
|
const std::string& channelTargetName = channel->getTargetName();
|
||||||
|
|
||||||
|
if (channelTargetName != umt->getName()) continue;
|
||||||
|
|
||||||
|
// check if we can link a StackedTransformElement to the current Channel
|
||||||
|
for (auto stackedTransform : umt->getStackedTransforms())
|
||||||
|
{
|
||||||
|
osgAnimation::StackedTransformElement* element = stackedTransform.get();
|
||||||
|
if (element && !element->getName().empty() && channelName == element->getName())
|
||||||
|
{
|
||||||
|
osgAnimation::Target* target = element->getOrCreateTarget();
|
||||||
|
if (target)
|
||||||
|
{
|
||||||
|
channel->setTarget(target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LinkVisitor::handle_stateset(osg::StateSet* stateset)
|
||||||
|
{
|
||||||
|
if (!stateset)
|
||||||
|
return;
|
||||||
|
const osg::StateSet::AttributeList& attributeList = stateset->getAttributeList();
|
||||||
|
for (auto attribute : attributeList)
|
||||||
|
{
|
||||||
|
osg::StateAttribute* sattr = attribute.second.first.get();
|
||||||
|
osgAnimation::UpdateMatrixTransform* umt = dynamic_cast<osgAnimation::UpdateMatrixTransform*>(sattr->getUpdateCallback()); //Can this even be in sa?
|
||||||
|
if (umt) link(umt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LinkVisitor::setAnimation(Resource::Animation* animation)
|
||||||
|
{
|
||||||
|
mAnimation = animation;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LinkVisitor::apply(osg::Node& node)
|
||||||
|
{
|
||||||
|
osg::StateSet* st = node.getStateSet();
|
||||||
|
if (st)
|
||||||
|
handle_stateset(st);
|
||||||
|
|
||||||
|
osg::Callback* cb = node.getUpdateCallback();
|
||||||
|
while (cb)
|
||||||
|
{
|
||||||
|
osgAnimation::UpdateMatrixTransform* umt = dynamic_cast<osgAnimation::UpdateMatrixTransform*>(cb);
|
||||||
|
if (umt)
|
||||||
|
if (node.getName() != "root") link(umt);
|
||||||
|
cb = cb->getNestedCallback();
|
||||||
|
}
|
||||||
|
|
||||||
|
traverse( node );
|
||||||
|
}
|
||||||
|
|
||||||
|
void LinkVisitor::apply(osg::Geode& node)
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < node.getNumDrawables(); i++)
|
||||||
|
{
|
||||||
|
osg::Drawable* drawable = node.getDrawable(i);
|
||||||
|
if (drawable && drawable->getStateSet())
|
||||||
|
handle_stateset(drawable->getStateSet());
|
||||||
|
}
|
||||||
|
apply(static_cast<osg::Node&>(node));
|
||||||
|
}
|
||||||
|
|
||||||
|
OsgAnimationController::OsgAnimationController(const OsgAnimationController ©, const osg::CopyOp ©op) : SceneUtil::KeyframeController(copy, copyop)
|
||||||
|
, mMergedAnimationTracks(copy.mMergedAnimationTracks)
|
||||||
|
, mEmulatedAnimations(copy.mEmulatedAnimations)
|
||||||
|
{
|
||||||
|
mLinker = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
osg::Vec3f OsgAnimationController::getTranslation(float time) const
|
||||||
|
{
|
||||||
|
osg::Vec3f translationValue;
|
||||||
|
std::string animationName;
|
||||||
|
float newTime = time;
|
||||||
|
|
||||||
|
//Find the correct animation based on time
|
||||||
|
for (const EmulatedAnimation& emulatedAnimation : mEmulatedAnimations)
|
||||||
|
{
|
||||||
|
if (time > emulatedAnimation.mStartTime && time < emulatedAnimation.mStopTime)
|
||||||
|
{
|
||||||
|
newTime = time - emulatedAnimation.mStartTime;
|
||||||
|
animationName = emulatedAnimation.mName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Find the root transform track in animation
|
||||||
|
for (const osg::ref_ptr<Resource::Animation> mergedAnimationTrack : mMergedAnimationTracks)
|
||||||
|
{
|
||||||
|
if (mergedAnimationTrack->getName() != animationName) continue;
|
||||||
|
|
||||||
|
const osgAnimation::ChannelList& channels = mergedAnimationTrack->getChannels();
|
||||||
|
|
||||||
|
for (const osg::ref_ptr<osgAnimation::Channel> channel: channels)
|
||||||
|
{
|
||||||
|
if (channel->getTargetName() != "root" || channel->getName() != "transform") continue;
|
||||||
|
|
||||||
|
if ( osgAnimation::MatrixLinearSampler* templateSampler = dynamic_cast<osgAnimation::MatrixLinearSampler*> (channel->getSampler()) )
|
||||||
|
{
|
||||||
|
osg::Matrixf matrix;
|
||||||
|
templateSampler->getValueAt(newTime, matrix);
|
||||||
|
translationValue = matrix.getTrans();
|
||||||
|
return osg::Vec3f(translationValue[0], translationValue[1], translationValue[2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return osg::Vec3f();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OsgAnimationController::update(float time, std::string animationName)
|
||||||
|
{
|
||||||
|
for (const osg::ref_ptr<Resource::Animation> mergedAnimationTrack : mMergedAnimationTracks)
|
||||||
|
{
|
||||||
|
if (mergedAnimationTrack->getName() == animationName) mergedAnimationTrack->update(time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OsgAnimationController::operator() (osg::Node* node, osg::NodeVisitor* nv)
|
||||||
|
{
|
||||||
|
if (hasInput())
|
||||||
|
{
|
||||||
|
if (mNeedToLink)
|
||||||
|
{
|
||||||
|
for (const osg::ref_ptr<Resource::Animation> mergedAnimationTrack : mMergedAnimationTracks)
|
||||||
|
{
|
||||||
|
if (!mLinker.valid()) mLinker = new LinkVisitor();
|
||||||
|
mLinker->setAnimation(mergedAnimationTrack);
|
||||||
|
node->accept(*mLinker);
|
||||||
|
}
|
||||||
|
mNeedToLink = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
float time = getInputValue(nv);
|
||||||
|
|
||||||
|
for (const EmulatedAnimation& emulatedAnimation : mEmulatedAnimations)
|
||||||
|
{
|
||||||
|
if (time > emulatedAnimation.mStartTime && time < emulatedAnimation.mStopTime)
|
||||||
|
{
|
||||||
|
update(time - emulatedAnimation.mStartTime, emulatedAnimation.mName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
traverse(node, nv);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OsgAnimationController::setEmulatedAnimations(std::vector<EmulatedAnimation> emulatedAnimations)
|
||||||
|
{
|
||||||
|
mEmulatedAnimations = emulatedAnimations;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OsgAnimationController::addMergedAnimationTrack(osg::ref_ptr<Resource::Animation> animationTrack)
|
||||||
|
{
|
||||||
|
mMergedAnimationTracks.emplace_back(animationTrack);
|
||||||
|
}
|
||||||
|
}
|
80
components/sceneutil/osgacontroller.hpp
Normal file
80
components/sceneutil/osgacontroller.hpp
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
#ifndef OPENMW_COMPONENTS_SCENEUTIL_OSGACONTROLLER_HPP
|
||||||
|
#define OPENMW_COMPONENTS_SCENEUTIL_OSGACONTROLLER_HPP
|
||||||
|
|
||||||
|
#include <osg/Node>
|
||||||
|
#include <osg/NodeVisitor>
|
||||||
|
#include <osg/StateSet>
|
||||||
|
#include <osg/ref_ptr>
|
||||||
|
#include <osgAnimation/Animation>
|
||||||
|
#include <osgAnimation/AnimationUpdateCallback>
|
||||||
|
#include <osgAnimation/Channel>
|
||||||
|
#include <osgAnimation/BasicAnimationManager>
|
||||||
|
#include <osgAnimation/StackedTransform>
|
||||||
|
#include <osgAnimation/UpdateMatrixTransform>
|
||||||
|
|
||||||
|
#include <components/sceneutil/controller.hpp>
|
||||||
|
#include <components/sceneutil/keyframe.hpp>
|
||||||
|
#include <components/resource/animation.hpp>
|
||||||
|
|
||||||
|
namespace SceneUtil
|
||||||
|
{
|
||||||
|
struct EmulatedAnimation
|
||||||
|
{
|
||||||
|
float mStartTime;
|
||||||
|
float mStopTime;
|
||||||
|
std::string mName;
|
||||||
|
};
|
||||||
|
|
||||||
|
class LinkVisitor : public osg::NodeVisitor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LinkVisitor();
|
||||||
|
|
||||||
|
virtual void link(osgAnimation::UpdateMatrixTransform* umt);
|
||||||
|
|
||||||
|
virtual void handle_stateset(osg::StateSet* stateset);
|
||||||
|
|
||||||
|
virtual void setAnimation(Resource::Animation* animation);
|
||||||
|
|
||||||
|
virtual void apply(osg::Node& node) override;
|
||||||
|
|
||||||
|
virtual void apply(osg::Geode& node) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Resource::Animation* mAnimation;
|
||||||
|
};
|
||||||
|
|
||||||
|
class OsgAnimationController : public SceneUtil::KeyframeController
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// @brief Handles the animation for osgAnimation formats
|
||||||
|
OsgAnimationController() {};
|
||||||
|
|
||||||
|
OsgAnimationController(const OsgAnimationController& copy, const osg::CopyOp& copyop);
|
||||||
|
|
||||||
|
META_Object(SceneUtil, OsgAnimationController)
|
||||||
|
|
||||||
|
/// @brief Handles the location of the instance
|
||||||
|
osg::Vec3f getTranslation(float time) const override;
|
||||||
|
|
||||||
|
/// @brief Calls animation track update()
|
||||||
|
void update(float time, std::string animationName);
|
||||||
|
|
||||||
|
/// @brief Called every frame for osgAnimation
|
||||||
|
void operator() (osg::Node*, osg::NodeVisitor*) override;
|
||||||
|
|
||||||
|
/// @brief Sets details of the animations
|
||||||
|
void setEmulatedAnimations(std::vector<EmulatedAnimation> emulatedAnimations);
|
||||||
|
|
||||||
|
/// @brief Adds an animation track to a model
|
||||||
|
void addMergedAnimationTrack(osg::ref_ptr<Resource::Animation> animationTrack);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool mNeedToLink = true;
|
||||||
|
osg::ref_ptr<LinkVisitor> mLinker;
|
||||||
|
std::vector<osg::ref_ptr<Resource::Animation>> mMergedAnimationTracks; // Used only by osgAnimation-based formats (e.g. dae)
|
||||||
|
std::vector<EmulatedAnimation> mEmulatedAnimations;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,12 +1,12 @@
|
||||||
#ifndef OPENMW_COMPONENTS_NIFOSG_TEXTKEYMAP
|
#ifndef OPENMW_COMPONENTS_SCENEUTIL_TEXTKEYMAP
|
||||||
#define OPENMW_COMPONENTS_NIFOSG_TEXTKEYMAP
|
#define OPENMW_COMPONENTS_SCENEUTIL_TEXTKEYMAP
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace NifOsg
|
namespace SceneUtil
|
||||||
{
|
{
|
||||||
class TextKeyMap
|
class TextKeyMap
|
||||||
{
|
{
|
Loading…
Reference in a new issue