opencscade AIS_Animation 源码学习 动画 原创
类 AIS_Animation
翻译:
• 动画实现者
子类应该重写 AIS_Animation::update() 方法来执行特定的动画。
AIS 包提供了有限数量的动画原子类 - AIS_AnimationObject 和 AIS_AnimationCamera,这些可能足够定义简单的动画。在一般情况下,应用程序应该定义自己的 AIS_Animation 子类,实现特定于应用程序的动画逻辑(例如,另一种插值或其他类型的变换,如颜色过渡等)。AIS_Animation::update() 的基本概念是定义当前呈现时间戳的精确场景状态,提供在任何时间步长和任何方向上都定义良好的平滑且连续的动画。因此,两个连续绘制的查看器帧之间的时间差异可以逐帧变化而不会产生视觉伪影,增加渲染帧率不会导致动画执行过快,而在慢速硬件上的低帧率也不会导致动画播放时间超过定义的持续时间。因此,实现应避免使用增量步长逻辑,或者应非常谨慎地使用它。
• 动画容器
AIS_Animation(无子类化)可用于聚合一系列动画项(子项)。每个子项都应该具有自己的持续时间和开始时间(呈现时间戳)。可以定义嵌套的 AIS_Animation 项集合,以便在每个容器级别中,子项定义相对于其持有者的开始播放时间。
• 动画播放控制器
建议应用程序定义一个单一的 AIS_Animation 实例(可选的子类化)来控制整个动画的播放。这样的控制器应该由其他 AIS_Animation 作为子对象填充,并通过调用 StartTimer()、UpdateTimer() 和 IsStopped() 方法由应用程序管理
请注意,AIS_Animation::StartTimer() 定义了一个计算经过时间的计时器,而不是一个多媒体计时器,后者会在特定间隔内执行查看器的更新!应用程序应避免使用隐式和即时的查看器更新,以确保在每次重新绘制查看器内容之前都调用 AIS_Animation::UpdateTimer()。重新绘制的逻辑也应在应用程序级别进行管理,以确保动画的平滑运行(通过定义由使用的GUI框架提供的多媒体计时器,以期望的帧率执行更新,或者在循环中进行连续的重新绘制)。
动画的动画开始、暂停、停止
方法: Add
用法:将单个动画添加到时间线
方法 :Children
用法:返回子动画序列
方法 :Clear
用法:清楚所有动画
方法:CopyFrom
用法:清除自身的子动画,然后从另一个对象复制子动画。同时复制开始时间和持续时间值。
方法:Duration
用法:时间线中动画的持续时间
方法:ElapsedTime
用法:返回已用时间
方法:Find
用法:输入子动画名字 返回具有给定名称的子动画。
方法:HasOwnDuration
用法:如果定义了持续时间,则返回 true
方法:IsStopped
用法:检查动画是否应在动画时间线中执行
方法:Name
用法:返回动画的名字
方法:OwnDuration
用法:时间线中动画的自身持续时间
方法:Pause
用法:暂停进程时间线。
方法:Remove
用法:清除子动画
方法:Replace
用法:替换子动画。
方法:SetOwnDuration
用法:设置自身持续时间
方法:SetStartPts
用法:在动画时间线中为动画设置时间限制。
方法:SetTimer
用法:设置播放计时器
方法:Start
用法:开始动画。此方法将动画的状态更改为“已开始”。此状态定义了动画是否应在时间线中执行。
方法:StartPts
用法:时间线中动画的开始时间
方法:StartTimer
用法:使用内部定义的计时器实例开始动画。内部调用 ::Start() 方法。
请注意,此方法初始化一个计算经过时间的计时器(在 AIS_Animation::UpdateTimer() 中的呈现时间戳),而不是一个在特定间隔内执行查看器更新的多媒体计时器!查看器的重绘应在应用程序级别进行管理,以便在每次重新绘制查看器内容之前都调用一次 AIS_Animation::UpdateTimer()。
方法:Stop
用法:停止动画
方法:Timer
用法:返回定时器
方法:update
用法:更新自身动画到指定的位置 - 应由子类重写。
方法:UpdateTimer
用法:更新动画的单帧,并更新计时器的状态。
方法:UpdateTotalDuration
用法:更新时间线的总持续时间,考虑到时间线上的所有动画。
方法:updateWithChildren
用法:根据输入的时间进度处理动画的一步,包括所有子动画。同时调用 ::update() 来更新自身的动画。
示例:
OpenCASCADE 的 AIS_Animation 类用于实现动画效果。以下是使用 AIS_Animation 类进行动画处理的一些基本步骤和概念:
创建动画对象:
首先,你需要创建动画对象。这通常涉及创建一个 AIS_Animation 类的实例,并为其设置相关的属性,如持续时间。
设置动画参数:
使用 SetOwnDuration 方法为动画设置持续时间。这决定了动画从开始到结束所需的时间。
启动定时器:
使用 StartTimer 方法启动动画的定时器。这个方法通常接受几个参数,如开始时间、持续时间和是否立即开始等。
更新动画:
在动画运行过程中,你需要定期调用 UpdateTimer 方法来更新动画的状态。这通常在一个循环中进行,直到动画停止。
更新查看器:
每次更新动画后,你可能还需要更新与之关联的查看器(Viewer),以便在图形界面上显示动画的最新状态。这可以通过调用查看器的更新方法来实现。
处理动画步骤:
动画的每一步都可以根据输入的时间进度进行处理,包括所有子动画。这通常涉及调用 update 方法来更新动画的当前状态。
保存动画(可选):
OpenCASCADE 还提供了将动画保存为视频文件的功能,但这需要引入第三方库(如 FFmpeg)。
示例和测试:
OpenCASCADE 的源码文件夹中提供了动画用法的示例,你可以参考这些示例来理解如何在实际项目中使用 AIS_Animation 类。
#include <AIS_Animation.hxx>
#include <AIS_InteractiveContext.hxx>
#include <AIS_Shape.hxx>
#include <Standard_Transient.hxx>
#include <gp_Pnt.hxx>
// 假设你已经有了一个 AIS_Shape 实例,并且已经添加到了 AIS_InteractiveContext
AIS_Shape* myShape = ...; // 初始化你的几何体形状
AIS_InteractiveContext* myContext = ...; // 初始化你的 AIS 上下文
// 创建一个动画对象
Handle(AIS_Animation) myAnimation = new AIS_Animation(myShape);
// 设置动画的持续时间(以秒为单位)
myAnimation->SetOwnDuration(5.0); // 5秒
// 假设你想要一个线性插值的移动动画,你需要自定义动画的每一帧
// 在这里,我们仅仅作为一个示例,设置开始和结束位置
gp_Pnt startPos = ...; // 动画开始时的位置
gp_Pnt endPos = ...; // 动画结束时的位置
// 你需要重写 AIS_Animation 的某些方法来定义动画的具体行为
// 例如,可以重写 Update 方法来在每一帧更新位置
class MyCustomAnimation : public AIS_Animation {
public:
MyCustomAnimation(AIS_InteractiveObject* obj) : AIS_Animation(obj) {}
// 重写 Update 方法以自定义动画行为
void Update(const Standard_Real theTime) override {
// 使用 theTime 参数(0到1之间)来计算当前位置
gp_Pnt currentPos = startPos.Interpolated(endPos, theTime);
// 假设你有一个方法来设置 myShape 的位置
// SetPosition(myShape, currentPos); // 这需要你自己实现
// 调用基类的 Update 方法来更新动画状态
AIS_Animation::Update(theTime);
}
};
// 创建自定义动画的实例并启动它
Handle(MyCustomAnimation) myCustomAnim = new MyCustomAnimation(myShape);
myCustomAnim->SetOwnDuration(5.0); // 设置持续时间
myCustomAnim->Start(); // 启动动画
// 确保你的应用程序有一个循环来调用 AIS_InteractiveContext 的 Display 方法
// 这样动画才能被显示出来
while (/* 你的应用程序运行条件 */) {
myContext->Display(Standard_True); // 更新视图
// 在这里添加你的事件处理和其他逻辑
}
// 当你想要停止动画时
myCustomAnim->Stop();
请注意,上面的代码是一个简化的示例,并且包含了一些你需要自己实现的函数(如 SetPosition)。OCCT 本身并没有直接提供设置 AIS_Shape 位置的方法,因为这通常取决于你的几何体和如何表示它。你可能需要访问底层的几何数据,并手动更新位置,然后重新生成和显示 AIS_Shape。
联系:
yzxxty39@163.com