Skip to content

Commit f0d30f2

Browse files
committed
Merge pull request #2160 from dnandha:ovis-add-animation
2 parents 8acc8aa + 6810e6c commit f0d30f2

File tree

4 files changed

+109
-11
lines changed

4 files changed

+109
-11
lines changed

modules/ovis/include/opencv2/ovis.hpp

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ enum EntityProperty
4545
{
4646
ENTITY_MATERIAL,
4747
ENTITY_SCALE,
48-
ENTITY_AABB_WORLD
48+
ENTITY_AABB_WORLD,
49+
ENTITY_ANIMBLEND_MODE
4950
};
5051

5152
/**
@@ -77,7 +78,7 @@ class CV_EXPORTS_W WindowScene {
7778
CV_WRAP virtual void setCompositors(const std::vector<String>& names) = 0;
7879

7980
/**
80-
* place an entity of an mesh in the scene
81+
* place an entity of a mesh in the scene
8182
*
8283
* the mesh needs to be created beforehand. Either programmatically
8384
* by e.g. @ref createPointCloudMesh or by placing an Ogre .mesh file in a resource location.
@@ -164,6 +165,30 @@ class CV_EXPORTS_W WindowScene {
164165
CV_WRAP virtual void setEntityPose(const String& name, InputArray tvec = noArray(),
165166
InputArray rot = noArray(), bool invert = false) = 0;
166167

168+
/**
169+
* get a list of available entity animations
170+
* @param name entity name
171+
* @param out the animation names
172+
*/
173+
CV_WRAP virtual void getEntityAnimations(const String& name, std::vector<String>& out) = 0;
174+
175+
/**
176+
* play entity animation
177+
* @param name entity name
178+
* @param animname animation name
179+
* @param loop enable or disable animation loop
180+
* @see getEntityAnimations
181+
*/
182+
CV_WRAP virtual void playEntityAnimation(const String& name, const String& animname,
183+
bool loop = true) = 0;
184+
185+
/**
186+
* stop entity animation
187+
* @param name enitity name
188+
* @param animname animation name
189+
*/
190+
CV_WRAP virtual void stopEntityAnimation(const String& name, const String& animname) = 0;
191+
167192
/**
168193
* read back the image generated by the last call to @ref waitKey
169194
*/

modules/ovis/samples/ovis_demo.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
#include <opencv2/videoio.hpp>
33

44
#include <opencv2/ovis.hpp>
5-
#include <opencv2/aruco.hpp>
65

76
#include <iostream>
87

@@ -35,12 +34,17 @@ int main()
3534
ovis::createGridMesh("ground", Size2i(10, 10), Size2i(10, 10));
3635
owin->createEntity("ground", "ground", Vec3f(1.57, 0, 0));
3736
owin->createCameraEntity("cam", K, imsize, 5);
38-
owin->createEntity("figure", "Sinbad.mesh", Vec3i(0, 0, 5), Vec3f(CV_PI/2.0, 0.0, 0.0)); // externally defined mesh
37+
owin->createEntity("sinbad", "Sinbad.mesh", Vec3i(0, 0, 5), Vec3f(CV_PI/2.0, 0.0, 0.0)); // externally defined mesh
3938
owin->createLightEntity("sun", Vec3i(0, 0, -100));
4039

40+
// setup and play idle animation
41+
owin->setEntityProperty("sinbad", ovis::EntityProperty::ENTITY_ANIMBLEND_MODE, Scalar(1)); // 1 = cumulative
42+
owin->playEntityAnimation("sinbad", "IdleBase");
43+
owin->playEntityAnimation("sinbad", "IdleTop");
44+
4145
//interaction scene
4246
Ptr<ovis::WindowScene> iwin = ovis::createWindow(String("AR"), imsize, ovis::SCENE_SEPERATE | ovis::SCENE_INTERACTIVE);
43-
iwin->createEntity("figure", "Sinbad.mesh", Vec3i(0, -5, 0), Vec3f(CV_PI, 0.0, 0.0));
47+
iwin->createEntity("sinbad", "Sinbad.mesh", Vec3i(0, -5, 0), Vec3f(CV_PI, 0.0, 0.0));
4448
iwin->createLightEntity("sun", Vec3i(0, 0, -100));
4549
iwin->setCameraIntrinsics(K, imsize);
4650

@@ -50,5 +54,5 @@ int main()
5054
owin->setEntityPose("cam", t, R);
5155
}
5256

53-
return 0;
57+
return 1;
5458
}

modules/ovis/samples/ovis_demo.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,17 @@
1414
cv.ovis.createGridMesh("ground", (10, 10), (10, 10))
1515
owin.createEntity("ground", "ground", rot=(1.57, 0, 0))
1616
owin.createCameraEntity("cam", K, imsize, 5)
17-
owin.createEntity("figure", "Sinbad.mesh", tvec=(0, -5, 0), rot=(np.pi, 0, 0)) # externally defined mesh
17+
owin.createEntity("sinbad", "Sinbad.mesh", tvec=(0, -5, 0), rot=(np.pi, 0, 0)) # externally defined mesh
1818
owin.createLightEntity("sun", (0, 0, -100))
1919

20+
# setup and play idle animation
21+
owin.setEntityProperty("sinbad", cv.ovis.ENTITY_ANIMBLEND_MODE, 1) # 1 = cumulative
22+
owin.playEntityAnimation("sinbad", "IdleBase")
23+
owin.playEntityAnimation("sinbad", "IdleTop")
24+
2025
# interaction scene
2126
iwin = cv.ovis.createWindow("AR", imsize, cv.ovis.SCENE_SEPERATE | cv.ovis.SCENE_INTERACTIVE)
22-
iwin.createEntity("figure", "Sinbad.mesh", tvec=(0, -5, 0), rot=(np.pi, 0, 0))
27+
iwin.createEntity("sinbad", "Sinbad.mesh", tvec=(0, -5, 0), rot=(np.pi, 0, 0))
2328
iwin.createLightEntity("sun", (0, 0, -100))
2429
iwin.setCameraIntrinsics(K, imsize)
2530

modules/ovis/src/ovis.cpp

Lines changed: 67 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,7 @@ class WindowSceneImpl : public WindowScene
277277
RenderWindow* rWin;
278278
Ptr<OgreBites::CameraMan> camman;
279279
Ptr<Rectangle2D> bgplane;
280+
std::unordered_map<String, Controller<Real>*> frameCtrlrs;
280281

281282
Ogre::RenderTarget* depthRTT;
282283
int flags;
@@ -495,7 +496,8 @@ class WindowSceneImpl : public WindowScene
495496
node->attachObject(ent);
496497
}
497498

498-
void removeEntity(const String& name) CV_OVERRIDE {
499+
void removeEntity(const String& name) CV_OVERRIDE
500+
{
499501
SceneNode& node = _getSceneNode(sceneMgr, name);
500502
node.getAttachedObject(name)->detachFromParent();
501503

@@ -576,6 +578,52 @@ class WindowSceneImpl : public WindowScene
576578
node.setPosition(t);
577579
}
578580

581+
void getEntityAnimations(const String& name, std::vector<String>& out) CV_OVERRIDE
582+
{
583+
SceneNode& node = _getSceneNode(sceneMgr, name);
584+
Entity* ent = dynamic_cast<Entity*>(node.getAttachedObject(name));
585+
CV_Assert(ent && "invalid entity");
586+
for (auto const& anim : ent->getAllAnimationStates()->getAnimationStates())
587+
{
588+
out.push_back(anim.first);
589+
}
590+
}
591+
592+
void playEntityAnimation(const String& name, const String& animname, bool loop = true) CV_OVERRIDE
593+
{
594+
SceneNode& node = _getSceneNode(sceneMgr, name);
595+
Entity* ent = dynamic_cast<Entity*>(node.getAttachedObject(name));
596+
CV_Assert(ent && "invalid entity");
597+
AnimationState* animstate = ent->getAnimationState(animname);
598+
599+
animstate->setTimePosition(0);
600+
animstate->setEnabled(true);
601+
animstate->setLoop(loop);
602+
603+
if (frameCtrlrs.find(animname) != frameCtrlrs.end()) return;
604+
frameCtrlrs.insert({
605+
animname,
606+
Ogre::ControllerManager::getSingleton().createFrameTimePassthroughController(
607+
Ogre::AnimationStateControllerValue::create(animstate, true)
608+
)
609+
});
610+
}
611+
612+
void stopEntityAnimation(const String& name, const String& animname) CV_OVERRIDE
613+
{
614+
SceneNode& node = _getSceneNode(sceneMgr, name);
615+
Entity* ent = dynamic_cast<Entity*>(node.getAttachedObject(name));
616+
CV_Assert(ent && "invalid entity");
617+
AnimationState* animstate = ent->getAnimationState(animname);
618+
619+
if (!animstate->getEnabled()) return;
620+
621+
animstate->setEnabled(false);
622+
animstate->setTimePosition(0);
623+
Ogre::ControllerManager::getSingleton().destroyController(frameCtrlrs[animname]);
624+
frameCtrlrs.erase(animname);
625+
}
626+
579627
void setEntityProperty(const String& name, int prop, const String& value) CV_OVERRIDE
580628
{
581629
CV_Assert(prop == ENTITY_MATERIAL);
@@ -598,9 +646,25 @@ class WindowSceneImpl : public WindowScene
598646

599647
void setEntityProperty(const String& name, int prop, const Scalar& value) CV_OVERRIDE
600648
{
601-
CV_Assert(prop == ENTITY_SCALE);
602649
SceneNode& node = _getSceneNode(sceneMgr, name);
603-
node.setScale(value[0], value[1], value[2]);
650+
switch(prop)
651+
{
652+
case ENTITY_SCALE:
653+
{
654+
node.setScale(value[0], value[1], value[2]);
655+
break;
656+
}
657+
case ENTITY_ANIMBLEND_MODE:
658+
{
659+
Entity* ent = dynamic_cast<Entity*>(node.getAttachedObject(name));
660+
CV_Assert(ent && "invalid entity");
661+
662+
ent->getSkeleton()->setBlendMode(static_cast<Ogre::SkeletonAnimationBlendMode>(value[0]));
663+
break;
664+
}
665+
default:
666+
CV_Error(Error::StsBadArg, "unsupported property");
667+
}
604668
}
605669

606670
void getEntityProperty(const String& name, int prop, OutputArray value) CV_OVERRIDE

0 commit comments

Comments
 (0)