有没有办法在现代 OpenGL 中创建简单的动画 "on the fly"?

Is there a way to create simple animations "on the fly" in modern OpenGL?

我认为这需要一些背景信息: 我修改 Minecraft 有一段时间了,但我一直想制作自己的游戏,所以我开始深入研究新发布的 LWJGL3 以真正完成任务。是的,我知道它的水平有点低,我应该使用引擎和其他东西……事实上,我已经尝试了一些引擎,但它们与我想做的事情完全不匹配,所以我决定从根本上解决这个问题. 到目前为止,我有点了解如何渲染网格、移动 "camera" 等,我愿意接受学习曲线。

但问题是,在某些时候所有的教程都开始解释如何加载模型和创建骨骼动画等等......但我想我真的不想那样做。使用 Minecraft 代码的很多事情都很糟糕,但我喜欢如何从 Java 代码创建模型和动画。当然,它看起来并不超逼真,但由于我对 Blender 也不是很好,我怀疑拥有 "classic" 个模型和动画是否会有帮助。无论如何,在那个代码中,我可以旋转一个盒子来让一个生物看着玩家,我可以使用正弦函数来移动腿和手臂(或翅膀,在我的例子中)并且这是有效的,因为 Minecraft 使用即时模式并且Java可以直接告诉显卡在哪里绘制每个顶点。

所以,实际问题:在现代 (3.3+) OpenGL 中有什么制作动态动画的好方法吗?我的模型基本上是形状的层次结构(盒子或其他),我希望能够动态旋转它们。但我不确定如何组织。我会为每个子形状存储所有 translation/rotation-matrices 吗?这会对模型可以拥有的子形状数量施加硬性限制吗?有人试过类似的东西吗?

编辑:为了澄清,我所做的看起来像这样:

创建模型:https://github.com/TheOnlySilverClaw/Birdmod/blob/master/src/main/java/silverclaw/birds/client/model/ModelOstrich.java 该模型在构造函数中创建为一堆框,render 和 setRotationAngles 方法设置比例和旋转。

是也不是。

您可以拥有形状层次结构并为每个形状存储一个相对变换。 例如 "player" 应该翻译成 100,100, 10(玩家所在的位置),然后 "head" 子组件会有额外的翻译 0,0,5(在z 轴)。

您可以将它们存储为矩阵(它们可以对平移、旋转和缩放进行编码)并使用 glPushMatrix 和 glPop 矩阵向 openGL 维护的堆栈添加和删除矩阵。

draw() 函数(或者随便你怎么称呼它)应该类似于:

glPushMatrix();
glMultMatrix(my_transform);  // You can also just have glTranslate, glRotate or anything else.
// Draw my mesh
for (child : children) { child.draw(); }
glPopMatrix();

这为您提供了分层设置,以便对象与其父对象一起移动。或者,您可以在主内存中有一个堆栈并自己进行乘法运算(使用库)。我认为 openGL 堆栈可能有一个限制(取决于实现),但如果你自己处理它,唯一的限制是你可以使用的 ram 数量。一旦所有矩阵相乘,渲染就会在相同的时间内完成,也就是说,网格在层次结构中的深度对性能来说并不重要。

对于实际的动画,您需要计算中间变换。例如,对于蹲伏动画,您可能希望中间有几帧,这样摄像机就不会跳到低位。您可以在开始位置和结束位置之间使用基于时间的线性插值来做到这一点,但这只涵盖简单的动画,您仍然必须自己实现它。

您需要自己实现任何更复杂的(即根据骨骼链接修改网格)。

您正在寻找的正是骨骼动画,唯一的区别是您不想为骨骼加载动画,而是想动态计算/生成变换。

你基本上有一个骨骼层次结构,以及附加到它的几何体。看起来你想操纵这个几何体 "rigidly",所以在将你的网格/变换发送到 GPU(经典方式)之前,你想开始计算模型或世界中的新变换 space,然后发送那些新计算的矩阵以标准方式在 gpu 上绘制你的几何图形。

正如 Sorin 所说,要计算每个变换,您只需遍历层次结构并在给定父骨骼变换和本地变换 w.r.t 父骨骼的情况下累积变换。

您应该学习一个 opengl 教程以了解基础知识。

让我建议 "Learning Modern 3D Graphics Programming", and especially this chapter,您可以在其中移动具有多个关节的机器人手臂。

我在 java 中使用 jogl here 进行了移植,但您可以通过 lwjgl 轻松移植它。