From c3d7e10bc143c449fd89837294bd4ce2ce247339 Mon Sep 17 00:00:00 2001 From: yfw123 Date: Fri, 26 Apr 2024 16:27:27 +0800 Subject: [PATCH 1/2] implement the "non-skeleton animations" with osgAnimation library, at the same time, switch control has been added by "DISABLE_OSGANIMATION" macro. --- readerwriter/CMakeLists.txt | 2 +- readerwriter/LoadSceneGLTF.cpp | 127 ++++++++++++++++++++++++++++++++- 2 files changed, 127 insertions(+), 2 deletions(-) diff --git a/readerwriter/CMakeLists.txt b/readerwriter/CMakeLists.txt index 2d8ab7e..b178b63 100644 --- a/readerwriter/CMakeLists.txt +++ b/readerwriter/CMakeLists.txt @@ -43,7 +43,7 @@ ENDIF(SDL2_FOUND) IF(NOT UNIX) TARGET_LINK_LIBRARIES(${LIB_NAME} osgVerseDependency osgVerseAnimation osgVerseModeling) ENDIF() -LINK_OSG_LIBRARY(${LIB_NAME} OpenThreads osg osgDB osgUtil osgGA osgViewer) +LINK_OSG_LIBRARY(${LIB_NAME} OpenThreads osg osgDB osgUtil osgGA osgViewer osgAnimation) INSTALL(TARGETS ${LIB_NAME} EXPORT ${LIB_NAME} RUNTIME DESTINATION ${INSTALL_BINDIR} COMPONENT libosgverse diff --git a/readerwriter/LoadSceneGLTF.cpp b/readerwriter/LoadSceneGLTF.cpp index 4a71808..05be344 100644 --- a/readerwriter/LoadSceneGLTF.cpp +++ b/readerwriter/LoadSceneGLTF.cpp @@ -8,6 +8,15 @@ #include #include +#define DISABLE_OSGANIMATION 1 +#if !DISABLE_OSGANIMATION +#include +#include +#include +#include +#include +#endif + #include "animation/BlendShapeAnimation.h" #include "pipeline/Utilities.h" #include "LoadTextureKTX.h" @@ -313,6 +322,11 @@ namespace osgVerse #endif } +#if !DISABLE_OSGANIMATION + osgAnimation::BasicAnimationManager* animng = nullptr; + int animatedCount = 0; +#endif + // Configure animations for (size_t i = 0; i < _modelDef.animations.size(); ++i) { @@ -339,6 +353,9 @@ namespace osgVerse } } +#if !DISABLE_OSGANIMATION + osgAnimation::Animation* animation = nullptr; +#endif std::map skeletonAnimMap; for (std::map>::iterator itr = samplers.begin(); itr != samplers.end(); ++itr) @@ -360,9 +377,109 @@ namespace osgVerse osg::Transform* t = g ? g->asTransform() : NULL; if (t) skeletonAnimMap[t] = playerAnim; } - else {} // TODO: non-skeleton animations + else { // non-skeleton animations + +#if !DISABLE_OSGANIMATION + osg::Group* g = (itr->first) ? itr->first->asGroup() : NULL; + osg::Transform* t = g ? g->asTransform() : NULL; + if (!t) continue; + + if (!animation) { animation = new osgAnimation::Animation; animation->setPlayMode(osgAnimation::Animation::LOOP); } + + auto targetName = "AnimatedCallback" + std::to_string(animatedCount++); + // Animation callback for Matrix transforms, name is targetName for Channels + osgAnimation::UpdateMatrixTransform* updatecb = new osgAnimation::UpdateMatrixTransform(targetName); + // connect the UpdateMatrixTransform callback to the MatrixTransform + t->setUpdateCallback(updatecb); + + auto& interpolations = playerAnim._interpolations; + // the order of the pathList is important! it defines the order of the channels in the animation and affect the animation result + for (const auto& path : pathList) + { + auto name = path.first; + auto interp = interpolations.find(name) == interpolations.end() ? "" : interpolations[name]; + if (name.compare("rotation") == 0) { + //continue; + if (interp == "LINEAR") { + if (playerAnim._rotationFrames.size()) { + updatecb->getStackedTransforms().push_back(new osgAnimation::StackedQuaternionElement(name, osg::Quat())); + + // define the channel for interpolation of a Quat value + osgAnimation::QuatSphericalLinearChannel* qsLinearChannel = new osgAnimation::QuatSphericalLinearChannel; + // name of the AnimationUpdateCallback + qsLinearChannel->setTargetName(targetName); + // name of the StackedQuaternionElement for rotation modification + qsLinearChannel->setName(name); + // Create keyframes for (in this case linear) interpolation of a osg::Quat + for (size_t j = 0; j < playerAnim._rotationFrames.size(); ++j) { + const auto& frame = playerAnim._rotationFrames[j]; + qsLinearChannel->getOrCreateSampler()->getOrCreateKeyframeContainer()->push_back(osgAnimation::QuatKeyframe(frame.first, frame.second)); + } + animation->addChannel(qsLinearChannel); + } + } + else {} // TODO: other interp animations + } + else if (name.compare("translation") == 0) { + //continue; + if (interp == "LINEAR") { + if (playerAnim._positionFrames.size()) { + updatecb->getStackedTransforms().push_back(new osgAnimation::StackedTranslateElement(name)); + + // define the channel for interpolation of a Vec3 value + osgAnimation::Vec3LinearChannel* v3LinearChannel = new osgAnimation::Vec3LinearChannel; + // name of the AnimationUpdateCallback + v3LinearChannel->setTargetName(targetName); + // name of the StackedTranslateElement for translation modification + v3LinearChannel->setName(name); + // Create keyframes for (in this case linear) interpolation of a osg::Vec3 + for (size_t j = 0; j < playerAnim._positionFrames.size(); ++j) { + const auto& frame = playerAnim._positionFrames[j]; + v3LinearChannel->getOrCreateSampler()->getOrCreateKeyframeContainer()->push_back(osgAnimation::Vec3Keyframe(frame.first, frame.second)); + } + animation->addChannel(v3LinearChannel); + } + } + else {} // TODO: other interp animations + } + else if (name.compare("scale") == 0) { + //continue; + if (interp == "LINEAR") { + if (playerAnim._scaleFrames.size()) { + updatecb->getStackedTransforms().push_back(new osgAnimation::StackedScaleElement(name)); + + // define the channel for interpolation of a Vec3 value + osgAnimation::Vec3LinearChannel* v3LinearChannel = new osgAnimation::Vec3LinearChannel; + // name of the AnimationUpdateCallback + v3LinearChannel->setTargetName(targetName); + // name of the StackedScaleElement for scale modification + v3LinearChannel->setName(name); + // Create keyframes for (in this case linear) interpolation of a osg::Vec3 + for (size_t j = 0; j < playerAnim._scaleFrames.size(); ++j) { + const auto& frame = playerAnim._scaleFrames[j]; + v3LinearChannel->getOrCreateSampler()->getOrCreateKeyframeContainer()->push_back(osgAnimation::Vec3Keyframe(frame.first, frame.second)); + } + animation->addChannel(v3LinearChannel); + } + } + else {} // TODO: other interp animations + } + else {} // TODO: others case + } +#endif + } } +#if !DISABLE_OSGANIMATION + if (animation) + { + if (!animng) animng = new osgAnimation::BasicAnimationManager(); + // We register the animation inside the scheduler + animng->registerAnimation(animation); + // start the animation + animng->playAnimation(animation); + } +#endif if (belongsToSkeleton >= 0 && !skeletonAnimMap.empty()) { std::vector& boneList = boneListMap[belongsToSkeleton]; @@ -370,6 +487,14 @@ namespace osgVerse animName, boneList, skeletonAnimMap); } } // end of for (animations) + +#if !DISABLE_OSGANIMATION + if (animng) + { + // add the animation manager to the scene graph to get it called during update traversals + _root->setUpdateCallback(animng); + } +#endif } osg::Node* LoaderGLTF::createNode(int id, tinygltf::Node& node) -- Gitee From a6964e5ae951e61a6ef31368e6342573e9e3d278 Mon Sep 17 00:00:00 2001 From: yfw123 Date: Fri, 26 Apr 2024 16:36:50 +0800 Subject: [PATCH 2/2] enable osgAnimation in LoadSceneGLTF.cpp --- readerwriter/LoadSceneGLTF.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readerwriter/LoadSceneGLTF.cpp b/readerwriter/LoadSceneGLTF.cpp index 05be344..6d58037 100644 --- a/readerwriter/LoadSceneGLTF.cpp +++ b/readerwriter/LoadSceneGLTF.cpp @@ -8,7 +8,7 @@ #include #include -#define DISABLE_OSGANIMATION 1 +#define DISABLE_OSGANIMATION 0 #if !DISABLE_OSGANIMATION #include #include -- Gitee