将刚体模拟保存为动画
Saving a rigid-body simulation as an animation
我在自主机器人领域工作。我经常会在没有可视化的情况下模拟机器人,将位置和旋转数据以 ~30 fps 的速度导出到一个文件,然后稍后播放该文件。目前,我将动画数据保存在自定义格式 JSON 文件中,并使用 three.js.
制作动画。
我想知道是否有更好的方法导出这些数据?
我不太精通动画,但我怀疑我可以导出到 COLLADA 或 glTF 之类的东西并获得使用许多系统已经使用的格式的好处设置导入。
我有几个问题(有些具体,有些一般):
动画通常如何以这些格式导出?似乎它们中的大多数都与骨架或变形有关,但这两个概念似乎都不适用于我的情况。 (我能得到一个指向一般动画概念概述的指针吗?)
我真的不需要关键帧。使用 30 到 60 fps 的关键帧而不需要插值是否合理?
是否有任何标准动画格式以不采用某种形式的插值的格式保存数据?
我是不是漏掉了什么?我确信我在该领域缺乏知识隐藏了一些对动画师来说显而易见的东西。
您描述的动画类型通常称为 "baked" 动画,其中一些计算已被采样,可能在 30 ~ 60 fps,关键帧以高采样率保存。对于此类动画,通常应用线性插值。例如,在 Blender 中,有一种方法可以 运行 Blender 游戏引擎并将物理模拟记录到(密集)关键帧。
关于插值,这里有一个思想实验:考虑一下基于多边形的渲染引擎想要渲染一个圆,但必须只使用直线。围绕圆的边缘计算一些有限数量的点,几十或数百个小线段填充点之间的空隙。如果密度足够大,或者相机足够靠后,它看起来是圆的,但线段确保在可能的圆中没有泄漏或间隙。相同的概念(在时间上而不是在 space 中)适用于烘焙的关键帧。样本密度很高,直线(线性插值)填补了空白。如果您以超慢动作播放它,您可能能够在到达新的关键帧时检测到速度的细微变化。但是在正常速度下,它看起来很正常,帧率不需要一直锁定在采样率上。
有一个 section on animations for glTF 2.0 我会推荐阅读这里(免责声明,我是 glTF 贡献者和工作组成员)。尤其是,查看带有线性插值的基于节点的动画的描述。
对于机器人技术,您需要避开皮肤和基于骨架的动画。无论如何,这些东西并不总是与基于节点的动画兼容(我们最近 运行 遇到了问题)。基于节点的动画更适用于具有铰接关节等的非变形机器人。
您特别提到了自主机器人,特别是位置和旋转。所以我假设 机器人本身 是应该存储在这里的粒度级别。 (只是为了将其与 铰接式 机器人区分开来——基本上是一个机械手 ("arm"),具有多个可能具有不同角度的旋转或平移关节)
对于这种情况,关于如何将其存储在 glTF(*) 中的 非常 简短的高级描述:
您可以将机器人(或每个机器人)存储为 glTF 资产的一个 node
。每个节点都可以包含 translation
和 rotation
属性(以 3D 向量和四元数给出)。然后,这些节点将简单地描述机器人的位置和方向。您可以想象机器人正在 "attached" 这些节点。 (事实上 ,你可以在glTF中为这些节点附加一个mesh
,然后它可以成为机器人的视觉表示)。
动画数据本身将是关于这些属性(平移和旋转)如何随时间变化的描述。可以将此信息的存储方式想象为 table,其中将平移和旋转与每个时间戳相关联:
time (s) 0.1 0.2 ... 1.0
translation x 1.2 1.3 ... 2.3
translation y 3.4 3.4 ... 4.3
translation z 4.5 4.6 ... 4.9
rotation x 0.12 0.13 ... 0.42
rotation y 0.32 0.43 ... 0.53
rotation z 0.14 0.13 ... 0.34
rotation w 0.53 0.46 ... 0.45
此信息随后以二进制形式存储,并由所谓的 accessor
对象提供。
glTF asset 的 animation
然后基本上建立了这个二进制动画数据之间的连接,以及受其影响的节点中的属性:每个 animation
指的是这样一个 "data table",以及node
,随着时间的推移,其属性将填充新的平移和旋转值。
关于插值:
在你的例子中,输出是从模拟中以高速率采样的,基本上每个帧 是 一个 "key frame",并且没有关于关键帧的明确信息否则必须存储插值方案。对于这个用例,只需声明动画插值应该是 LINEAR
或 STEP
类型就足够了。
(将其声明为 LINEAR
插值的选项将主要与播放相关。假设您在 0.15 秒后恰好停止播放:它是否应该显示机器人在时间戳时的状态0.1 或时间戳 0.2 处的状态,或线性插值的状态?然而,这主要适用于标准查看器,不一定适用于自定义播放)
(*) 附注:在 概念 层面上,信息在 glTF 和 COLLADA 中的表示方式是相似的。粗略地说,COLLADA 是一种用于编写应用程序的 interchange 格式,而 glTF 是一种可以高效传输和呈现的 transmission 格式。因此,尽管到目前为止的答案都涉及 glTF,但您也应该考虑 COLLADA,具体取决于您的优先级、用例或您提到的 "playback" 应该如何实施。
免责声明:我也是 glTF 贡献者。我还创建了 glTF tutorial section showing a simple animation and the one that explains some concepts of animations in glTF。您可能会发现它们很有用,但它们显然建立在前面几节中解释的一些概念之上。
我在自主机器人领域工作。我经常会在没有可视化的情况下模拟机器人,将位置和旋转数据以 ~30 fps 的速度导出到一个文件,然后稍后播放该文件。目前,我将动画数据保存在自定义格式 JSON 文件中,并使用 three.js.
制作动画。我想知道是否有更好的方法导出这些数据?
我不太精通动画,但我怀疑我可以导出到 COLLADA 或 glTF 之类的东西并获得使用许多系统已经使用的格式的好处设置导入。
我有几个问题(有些具体,有些一般):
动画通常如何以这些格式导出?似乎它们中的大多数都与骨架或变形有关,但这两个概念似乎都不适用于我的情况。 (我能得到一个指向一般动画概念概述的指针吗?)
我真的不需要关键帧。使用 30 到 60 fps 的关键帧而不需要插值是否合理?
是否有任何标准动画格式以不采用某种形式的插值的格式保存数据?
我是不是漏掉了什么?我确信我在该领域缺乏知识隐藏了一些对动画师来说显而易见的东西。
您描述的动画类型通常称为 "baked" 动画,其中一些计算已被采样,可能在 30 ~ 60 fps,关键帧以高采样率保存。对于此类动画,通常应用线性插值。例如,在 Blender 中,有一种方法可以 运行 Blender 游戏引擎并将物理模拟记录到(密集)关键帧。
关于插值,这里有一个思想实验:考虑一下基于多边形的渲染引擎想要渲染一个圆,但必须只使用直线。围绕圆的边缘计算一些有限数量的点,几十或数百个小线段填充点之间的空隙。如果密度足够大,或者相机足够靠后,它看起来是圆的,但线段确保在可能的圆中没有泄漏或间隙。相同的概念(在时间上而不是在 space 中)适用于烘焙的关键帧。样本密度很高,直线(线性插值)填补了空白。如果您以超慢动作播放它,您可能能够在到达新的关键帧时检测到速度的细微变化。但是在正常速度下,它看起来很正常,帧率不需要一直锁定在采样率上。
有一个 section on animations for glTF 2.0 我会推荐阅读这里(免责声明,我是 glTF 贡献者和工作组成员)。尤其是,查看带有线性插值的基于节点的动画的描述。
对于机器人技术,您需要避开皮肤和基于骨架的动画。无论如何,这些东西并不总是与基于节点的动画兼容(我们最近 运行 遇到了问题)。基于节点的动画更适用于具有铰接关节等的非变形机器人。
您特别提到了自主机器人,特别是位置和旋转。所以我假设 机器人本身 是应该存储在这里的粒度级别。 (只是为了将其与 铰接式 机器人区分开来——基本上是一个机械手 ("arm"),具有多个可能具有不同角度的旋转或平移关节)
对于这种情况,关于如何将其存储在 glTF(*) 中的 非常 简短的高级描述:
您可以将机器人(或每个机器人)存储为 glTF 资产的一个 node
。每个节点都可以包含 translation
和 rotation
属性(以 3D 向量和四元数给出)。然后,这些节点将简单地描述机器人的位置和方向。您可以想象机器人正在 "attached" 这些节点。 (事实上 ,你可以在glTF中为这些节点附加一个mesh
,然后它可以成为机器人的视觉表示)。
动画数据本身将是关于这些属性(平移和旋转)如何随时间变化的描述。可以将此信息的存储方式想象为 table,其中将平移和旋转与每个时间戳相关联:
time (s) 0.1 0.2 ... 1.0
translation x 1.2 1.3 ... 2.3
translation y 3.4 3.4 ... 4.3
translation z 4.5 4.6 ... 4.9
rotation x 0.12 0.13 ... 0.42
rotation y 0.32 0.43 ... 0.53
rotation z 0.14 0.13 ... 0.34
rotation w 0.53 0.46 ... 0.45
此信息随后以二进制形式存储,并由所谓的 accessor
对象提供。
glTF asset 的 animation
然后基本上建立了这个二进制动画数据之间的连接,以及受其影响的节点中的属性:每个 animation
指的是这样一个 "data table",以及node
,随着时间的推移,其属性将填充新的平移和旋转值。
关于插值:
在你的例子中,输出是从模拟中以高速率采样的,基本上每个帧 是 一个 "key frame",并且没有关于关键帧的明确信息否则必须存储插值方案。对于这个用例,只需声明动画插值应该是 LINEAR
或 STEP
类型就足够了。
(将其声明为 LINEAR
插值的选项将主要与播放相关。假设您在 0.15 秒后恰好停止播放:它是否应该显示机器人在时间戳时的状态0.1 或时间戳 0.2 处的状态,或线性插值的状态?然而,这主要适用于标准查看器,不一定适用于自定义播放)
(*) 附注:在 概念 层面上,信息在 glTF 和 COLLADA 中的表示方式是相似的。粗略地说,COLLADA 是一种用于编写应用程序的 interchange 格式,而 glTF 是一种可以高效传输和呈现的 transmission 格式。因此,尽管到目前为止的答案都涉及 glTF,但您也应该考虑 COLLADA,具体取决于您的优先级、用例或您提到的 "playback" 应该如何实施。
免责声明:我也是 glTF 贡献者。我还创建了 glTF tutorial section showing a simple animation and the one that explains some concepts of animations in glTF。您可能会发现它们很有用,但它们显然建立在前面几节中解释的一些概念之上。