From 6810e6c8947cf0a8036107e8d5a47c52f04522b0 Mon Sep 17 00:00:00 2001 From: dnandha Date: Thu, 20 Jun 2019 22:32:17 +0200 Subject: [PATCH] ovis: add methods (+ sample) for setting entity animations ovis: add methods (+sample) to play/stop animations ovis: add entity property and according function override ovis: fix overloaded method wrap aliases ovis, samples: add animation to ovis demo ovis: consolidate setting entity property --- modules/ovis/include/opencv2/ovis.hpp | 29 ++++++++++- modules/ovis/samples/ovis_demo.cpp | 12 +++-- modules/ovis/samples/ovis_demo.py | 9 +++- modules/ovis/src/ovis.cpp | 70 +++++++++++++++++++++++++-- 4 files changed, 109 insertions(+), 11 deletions(-) diff --git a/modules/ovis/include/opencv2/ovis.hpp b/modules/ovis/include/opencv2/ovis.hpp index 473946fa0..9b39b1936 100644 --- a/modules/ovis/include/opencv2/ovis.hpp +++ b/modules/ovis/include/opencv2/ovis.hpp @@ -45,7 +45,8 @@ enum EntityProperty { ENTITY_MATERIAL, ENTITY_SCALE, - ENTITY_AABB_WORLD + ENTITY_AABB_WORLD, + ENTITY_ANIMBLEND_MODE }; /** @@ -77,7 +78,7 @@ public: CV_WRAP virtual void setCompositors(const std::vector& names) = 0; /** - * place an entity of an mesh in the scene + * place an entity of a mesh in the scene * * the mesh needs to be created beforehand. Either programmatically * by e.g. @ref createPointCloudMesh or by placing an Ogre .mesh file in a resource location. @@ -164,6 +165,30 @@ public: CV_WRAP virtual void setEntityPose(const String& name, InputArray tvec = noArray(), InputArray rot = noArray(), bool invert = false) = 0; + /** + * get a list of available entity animations + * @param name entity name + * @param out the animation names + */ + CV_WRAP virtual void getEntityAnimations(const String& name, std::vector& out) = 0; + + /** + * play entity animation + * @param name entity name + * @param animname animation name + * @param loop enable or disable animation loop + * @see getEntityAnimations + */ + CV_WRAP virtual void playEntityAnimation(const String& name, const String& animname, + bool loop = true) = 0; + + /** + * stop entity animation + * @param name enitity name + * @param animname animation name + */ + CV_WRAP virtual void stopEntityAnimation(const String& name, const String& animname) = 0; + /** * read back the image generated by the last call to @ref waitKey */ diff --git a/modules/ovis/samples/ovis_demo.cpp b/modules/ovis/samples/ovis_demo.cpp index 1eafa2c8f..03c8e2b8a 100644 --- a/modules/ovis/samples/ovis_demo.cpp +++ b/modules/ovis/samples/ovis_demo.cpp @@ -2,7 +2,6 @@ #include #include -#include #include @@ -35,12 +34,17 @@ int main() ovis::createGridMesh("ground", Size2i(10, 10), Size2i(10, 10)); owin->createEntity("ground", "ground", Vec3f(1.57, 0, 0)); owin->createCameraEntity("cam", K, imsize, 5); - owin->createEntity("figure", "Sinbad.mesh", Vec3i(0, 0, 5), Vec3f(CV_PI/2.0, 0.0, 0.0)); // externally defined mesh + owin->createEntity("sinbad", "Sinbad.mesh", Vec3i(0, 0, 5), Vec3f(CV_PI/2.0, 0.0, 0.0)); // externally defined mesh owin->createLightEntity("sun", Vec3i(0, 0, -100)); + // setup and play idle animation + owin->setEntityProperty("sinbad", ovis::EntityProperty::ENTITY_ANIMBLEND_MODE, Scalar(1)); // 1 = cumulative + owin->playEntityAnimation("sinbad", "IdleBase"); + owin->playEntityAnimation("sinbad", "IdleTop"); + //interaction scene Ptr iwin = ovis::createWindow(String("AR"), imsize, ovis::SCENE_SEPERATE | ovis::SCENE_INTERACTIVE); - iwin->createEntity("figure", "Sinbad.mesh", Vec3i(0, -5, 0), Vec3f(CV_PI, 0.0, 0.0)); + iwin->createEntity("sinbad", "Sinbad.mesh", Vec3i(0, -5, 0), Vec3f(CV_PI, 0.0, 0.0)); iwin->createLightEntity("sun", Vec3i(0, 0, -100)); iwin->setCameraIntrinsics(K, imsize); @@ -50,5 +54,5 @@ int main() owin->setEntityPose("cam", t, R); } - return 0; + return 1; } diff --git a/modules/ovis/samples/ovis_demo.py b/modules/ovis/samples/ovis_demo.py index 819dea38f..b607d180b 100644 --- a/modules/ovis/samples/ovis_demo.py +++ b/modules/ovis/samples/ovis_demo.py @@ -14,12 +14,17 @@ owin = cv.ovis.createWindow("VR", imsize) cv.ovis.createGridMesh("ground", (10, 10), (10, 10)) owin.createEntity("ground", "ground", rot=(1.57, 0, 0)) owin.createCameraEntity("cam", K, imsize, 5) -owin.createEntity("figure", "Sinbad.mesh", tvec=(0, -5, 0), rot=(np.pi, 0, 0)) # externally defined mesh +owin.createEntity("sinbad", "Sinbad.mesh", tvec=(0, -5, 0), rot=(np.pi, 0, 0)) # externally defined mesh owin.createLightEntity("sun", (0, 0, -100)) +# setup and play idle animation +owin.setEntityProperty("sinbad", cv.ovis.ENTITY_ANIMBLEND_MODE, 1) # 1 = cumulative +owin.playEntityAnimation("sinbad", "IdleBase") +owin.playEntityAnimation("sinbad", "IdleTop") + # interaction scene iwin = cv.ovis.createWindow("AR", imsize, cv.ovis.SCENE_SEPERATE | cv.ovis.SCENE_INTERACTIVE) -iwin.createEntity("figure", "Sinbad.mesh", tvec=(0, -5, 0), rot=(np.pi, 0, 0)) +iwin.createEntity("sinbad", "Sinbad.mesh", tvec=(0, -5, 0), rot=(np.pi, 0, 0)) iwin.createLightEntity("sun", (0, 0, -100)) iwin.setCameraIntrinsics(K, imsize) diff --git a/modules/ovis/src/ovis.cpp b/modules/ovis/src/ovis.cpp index 65a4a19b9..eb194f059 100644 --- a/modules/ovis/src/ovis.cpp +++ b/modules/ovis/src/ovis.cpp @@ -277,6 +277,7 @@ class WindowSceneImpl : public WindowScene RenderWindow* rWin; Ptr camman; Ptr bgplane; + std::unordered_map*> frameCtrlrs; Ogre::RenderTarget* depthRTT; int flags; @@ -495,7 +496,8 @@ public: node->attachObject(ent); } - void removeEntity(const String& name) CV_OVERRIDE { + void removeEntity(const String& name) CV_OVERRIDE + { SceneNode& node = _getSceneNode(sceneMgr, name); node.getAttachedObject(name)->detachFromParent(); @@ -576,6 +578,52 @@ public: node.setPosition(t); } + void getEntityAnimations(const String& name, std::vector& out) CV_OVERRIDE + { + SceneNode& node = _getSceneNode(sceneMgr, name); + Entity* ent = dynamic_cast(node.getAttachedObject(name)); + CV_Assert(ent && "invalid entity"); + for (auto const& anim : ent->getAllAnimationStates()->getAnimationStates()) + { + out.push_back(anim.first); + } + } + + void playEntityAnimation(const String& name, const String& animname, bool loop = true) CV_OVERRIDE + { + SceneNode& node = _getSceneNode(sceneMgr, name); + Entity* ent = dynamic_cast(node.getAttachedObject(name)); + CV_Assert(ent && "invalid entity"); + AnimationState* animstate = ent->getAnimationState(animname); + + animstate->setTimePosition(0); + animstate->setEnabled(true); + animstate->setLoop(loop); + + if (frameCtrlrs.find(animname) != frameCtrlrs.end()) return; + frameCtrlrs.insert({ + animname, + Ogre::ControllerManager::getSingleton().createFrameTimePassthroughController( + Ogre::AnimationStateControllerValue::create(animstate, true) + ) + }); + } + + void stopEntityAnimation(const String& name, const String& animname) CV_OVERRIDE + { + SceneNode& node = _getSceneNode(sceneMgr, name); + Entity* ent = dynamic_cast(node.getAttachedObject(name)); + CV_Assert(ent && "invalid entity"); + AnimationState* animstate = ent->getAnimationState(animname); + + if (!animstate->getEnabled()) return; + + animstate->setEnabled(false); + animstate->setTimePosition(0); + Ogre::ControllerManager::getSingleton().destroyController(frameCtrlrs[animname]); + frameCtrlrs.erase(animname); + } + void setEntityProperty(const String& name, int prop, const String& value) CV_OVERRIDE { CV_Assert(prop == ENTITY_MATERIAL); @@ -598,9 +646,25 @@ public: void setEntityProperty(const String& name, int prop, const Scalar& value) CV_OVERRIDE { - CV_Assert(prop == ENTITY_SCALE); SceneNode& node = _getSceneNode(sceneMgr, name); - node.setScale(value[0], value[1], value[2]); + switch(prop) + { + case ENTITY_SCALE: + { + node.setScale(value[0], value[1], value[2]); + break; + } + case ENTITY_ANIMBLEND_MODE: + { + Entity* ent = dynamic_cast(node.getAttachedObject(name)); + CV_Assert(ent && "invalid entity"); + + ent->getSkeleton()->setBlendMode(static_cast(value[0])); + break; + } + default: + CV_Error(Error::StsBadArg, "unsupported property"); + } } void getEntityProperty(const String& name, int prop, OutputArray value) CV_OVERRIDE