1.Introduction

OpenCASCADE提供了类AIS_Animation等来实现简单的动画功能。

OpenCV视频中画圆_OpenCV视频中画圆

 

从其类图可以看出,动画功能有两种:一种是相机的动画AnimationCamera,一种是模型的动画AnimationObject。因为OpenCASCADE不像OpenSceneGraph那样是专门做仿真动画的,内置多线程,OpenCASCADE中的动画可以理解为一个while(true) {update();},即在动画时间内对相机或模型的起始位置和终止位置进行插值并更新来实现动画。对于简单的动画效果,这种方式是够用了。

 

2. Examples

在OpenCASCADE的源码文件夹中提供了动画用法的示例,分别演示了模型变换、视图变换及将动画保存成视频文件,当然这个功能需要引入第三方库FFmpeg:

OpenCV视频中画圆_sed_02

OpenCASCADE中动画中间位置的生成采用了类gp_TrsfNLerp进行插值。

OpenCV视频中画圆_插值_03

 根据其注释是对一个变换的三个部分分别进行线性插值,旋转部分采用四元数类进行插值。这种插值方式不可能满足复杂动画的要求,不过可以把这个类当成一个插值的例子。

在Draw Test Harness中输入以下命令:

source tests/v3d/anim/propeller

vanim anim -play -playSpeed 0.1

即可以让一个螺旋桨动起来了:

OpenCV视频中画圆_3d_04

其实这个螺旋桨动画是个复杂的例子,包含了视图动画和模型动画。对于简单的示例,可以参考另外几个文件,里面的例子是相对简单的。

OpenCV视频中画圆_插值_05

 

3. Conclusion

OpenCASCADE7.3版本中引入了简单动画的功能,结合其测试案例,找到其实现源码,可以方便地在程序中实现简单的动画功能。其中动画支持两种方式:一种是视图支画,一种是模型动画。视图动画一般用于两个视图之间的动画过渡,如从主视图切换到仰视图中间加一个动画过渡;模型动画可用于简单的动画仿真。

 

其他

一. 实现动画的两种方式

1.使用AIS_Animation类(https://www.opencascade.com/doc/occt-7.3.0/refman/html/class_a_i_s ___ ani ...)。 目前还不清楚如何使用它,没有例子如何使用它!

2.在线程中简单使用转换,如下所述:https://www.opencascade.com/content/rotating-and-translating-cylinder-3d ...

AIS_Animation是一个集中的工具,用于以可靠的方式处理简单和复杂(嵌套)动画,
介绍演示时间戳,高分辨率计时器,动画速度,插值例程等概念。
如果将局部转换应用于对象,则AIS_AnimationObject将在内部执行与帖子中引用链接相同的内容。
MFC动画示例尚未使用AIS_Animation进行更新。

AIS_Animation不会“自动”为你做任何事情 - 它应该在应用程序级别正确初始化(定义动画序列 - 关键帧)并使用(以适当的间隔重绘查看器)。
另请参见tests \ v3d \ anim \ Draw Harness测试,演示了vanimation命令的用法。

 

OCCT中的测试使用test和testgrid命令执行,例如:

> test v3d anim propeller 1
> vanimation anim -play

> AIS_Animation wouldn't do everything for you "automatically" - it should be properly initialized (defining animation sequence(s) - key frames)
> and used (to redraw viewer at proper intervals) at application level.

AIS_Animation::StartTimer() starts its internal timer returning elapsed time, the actual update of current frame is done by AIS_Animation::UpdateTimer(), which should be called before redrawing new frame in 3D Viewer.
Redrawing the viewer should be done by application itself, and will depend on used GUI framework and application design.

You don't need re-implementing AIS_Animation::UpdateTimer(), standard implementation should be enough in most cases.
General idea is:
- Define single AIS_Animation instance at application level as a container for active animation(s) and main playback controller.
- Define animation atoms like AIS_AnimationObject/AIS_AnimationCamera and insert them into AIS_Animation container (AIS_Animation::Add()). Each item should define its own duration (should not be 0) and start presentation timestamp (PTS, 0 by default), so that AIS_Animation container will automatically calculate the complete animation duration as summary of its children. Nested AIS_Animation containers are also possible.
- Start AIS_Animation playback AIS_Animation::StartTimer(), and call AIS_Animation::UpdateTimer() within each Viewer redraw (for example, on multimedia timer triggering update at desired time intervals, as provided by GUI framework) until animation is not finished (AIS_Animation::IsStopped()). AIS_Animation controller will automatically execute (update) children, so that only one root AIS_Animation instance (controller) should be managed with StartTimer()/UpdateTimer()/IsStopped() calls.
- Custom animation items (similar to AIS_AnimationObject/AIS_AnimationCamera) should inherit AIS_Animation and override AIS_Animation::update() method. Existing implementation can be used as a reference. The main input for ::update() is a current presentation timestamp (PTS) and normalized (0..1) progress inside this specific item (based on own duration), which should be used for updating scene (for instance, by applying linear interpolation between two key frames), see also AIS_AnimationProgress definition.

TopoDS_Shape obj1 = BRepPrimAPI_MakeBox(100, 500, 20);
Handle(AIS_Shape) ais_obj1 = new AIS_Shape(obj1);
g_pDoc->myAISContext->Display(ais_obj1, true);

gp_Trsf start_pnt, end_pnt;
	
start_pnt.SetValues(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0);
end_pnt.SetValues(1, 0, 0, 100, 0, 1, 0, 100, 0, 0, 1, 100);
	
Handle(AIS_Animation) ais_animation = new AIS_Animation("obj1");
Handle(AIS_AnimationObject) ais_ao = new AIS_AnimationObject("obj1", g_pDoc->myAISContext, ais_obj1, start_pnt, end_pnt);
ais_ao->SetOwnDuration(10);
ais_ao->SetStartPts(0);
	
ais_animation->Add(ais_ao);

double duration = ais_animation->Duration();

ais_animation->StartTimer(0, 1.0, true);

while (!ais_animation->IsStopped())
{
	ais_animation->UpdateTimer();
		
	g_pDoc->myAISContext->UpdateCurrentViewer();
}

参考OCCT开发者论坛:https://www.opencascade.com/content/proper-way-make-animation-aisshape-scene