一个模型(Model / ModelInstance) 包含了一个或多个动画。每个动画都有一个标识符id,标识符id在一个模型中是唯一的。
通过对一个或多个节点的变换,可以利用蒙皮对模型(网格)进行变形。这通常与动画结合使用。该页还介绍了如何在应用程序中使用皮肤。
当我们使用 fbx-conv 把 fbx 转换为 G3DB/G3DJ 时,fbx里面的动画也就自动转换到了animations 节点上了,
libGDX 不支持关键帧之间的自定义插值。如果你使用非线性插值,fbx-conv 将产生额外的关键帧来实现这一点。这种实现是根据目标 FPS 来完成的。虽然目标 FPS 在 FBX 中是可定制的,但并非所有建模软件都允许您更改这个值(默认值为30 FPS)。为了避免文件膨胀与额外的关键帧,请确保尽可能使用线性插值。
当使用 G3dModelLoader 或 AssetManager 在游戏中加载 G3DB/G3DJ 文件时,动画也就自动加载了。当您从 Model 创建一个 ModelInstance 时,动画也会被复制到 ModelInstance。如果在创建 ModelInstance 时指定特定的节点,则只将应用于这些节点(和子节点)的动画复制到新的 ModelInstance。
在 libGDX 中使用 AnimationController 来播放 ModelInstalce 中的动画,AnimationController 播放动画的示例如下:
ModelInstance instance;
AnimationController controller;
public void create() {
...
instance = new ModelInstance(model);
controller = new AnimationController(instance);
controller.setAnimation("walk");
}
public void render() {
...
controller.update(Gdx.graphics.getDeltaTime());
...
}
setAnimation设置需要播放的动画,之后通过 update(delta) 播放动画。
在 setAnimation 时可以传loopCount播放次数参数:setAnimation(String id, int loopCount),loopCount播放的次数,默认为1,当为-1时一直循环播放,不能为0.
当调用 setAnimation 方法时会返回一个 AnimationDesc 实例,该实例在动画播放或排队播放时有效。包含了有关动画的所有信息,比如当前动画的时间、该动画的剩余循环次数等等,可以在动画执行期间通过修改这些参数来控制动画,得当动画结束时,需要接触 AnimationDesc 的所有引用,因为它可能被销毁、重用或用于下一个动画。
AnimationListener 是动画监听器,可以通过setAnimation (String id,int loopCount,AnimationListener listener)或者AnimationDesc进行设置。改监听器可以监听动画的行为,比如动画循环或结束通知。
当直接调用setAnimation方法切换动画时,前面的动画会突然停止,然后播放新的动画,若想要动画平稳过度,可以使用 AnimationController 中的animate方法:animController.animate(String id, float transitionTime),transitionTime参数为新的动画在此期间将线性插入到旧的动画之上,然后实现平滑过度,若之前没有动画,则新的动画立即播放。
队列动画使用 AnimationController 中的queue方法实现: animController.queue(...); 当此时播放的动画播放完成时,执行队列动画,如果此时播放的动画是连续循环的,则在播放的动画当前循环完成时播放队列动画,然后在继续下一次循环。如果当前没有动画播放,那队列动画立即播放,如果指定的转换时间大于0,则混合队列动画。
animController.action(...) 在当前动画基础上执行动画,实际上,调用animate(...)与action(...)和queue(...)效果是相同的。
例如setAnimation、animate、queue和action方法允许设置动画的播放速度,速度为1则动画正常速度播放,如果为负数,则动画方向播放。
也可以通过更改 AnimationController 的 delta 值来控制每个动画的总体速度 :update (float delta)。例如,当调用 animController.update (0.5f * gdx.graphics.getdeltatiana ()) ; 整体速度将是原来速度的一半。
在执行动画时,所有受影响的节点都将 isAnimated 成员设置为 true。这将导致无法使用 Node 的平移、旋转和缩放值。因此,在动画的时候,不能变换受影响的节点。
皮肤是用来根据一个或多个节点(也成为骨骼或者关节)的变换对模型进行变换。在使用皮肤时,最常用的是使用不可见节点(没有节点附加到该节点)来使模型变形。这些节点(通常形成一个层次结构)也被成为骨架或衔铁。所以在实践中,当使用皮肤时,模型有一个不可见的骨架部分(一个或多个节点)和一个可见的部分(一个或多个节点)。当可见节点本身保持不变形时,骨架就会变形(例如通过动画) ,从而影响可见网格顶点的位置。这是通过使用混合权重(也称为骨权重)来实现的,这是可见节点的顶点属性。每个混合权重都有一个(特定骨骼/节点的)索引和一个权重(受该骨骼/节点影响的程度)。每个可见节点(NodePart)都有对其骨架(骨架节点)的引用。
libGDX 只支持着色器皮肤,这至少需要 Open GL ES 2.0。如果您使用建模软件创建模型,将其导出到 FBX 并将其转换为 G3DB/G3DJ,那么皮肤应该能够在 libGDX中无缝使用。注意,需要导出可见和不可见(骨架)节点以及动画本身。
皮肤可能需要一些调整,以获得最佳和最佳的结果。默认情况下 fbx-conv 将包括每个顶点4骨权重(每个顶点最多可以受到四个节点的影响)。同样默认情况下,fbx-conv 将分组顶点,当骨骼影响的总数量超过12,则共享相同的骨骼和分裂成多个部分的网格。分割网格是完成的,因为着色器的数量是有限的变量,它可以使用。但是,这将导致多个呈现调用,这可能会影响性能。您可以使用命令行选项 -w 和 -b 更改 fbx-conv 的默认值。W 命令允许您指定可以影响一个顶点的骨骼数量。必须在1到8之间(默认着色器不支持超过8个骨量)。例如:
fbx-conv -w 3 inputfile.fbx
-b 命令允许您指定 fbx-conv 开始分割网格之前允许的骨骼总数。此值必须大于零并且没有硬限制。通常不应该将其设置为 -w 命令指定数量的三倍以下。你可以增加这个值来避免分割网格,但代价是 uniform 着色器。
fbx-conv -b 16 inputfile.fbx
如果您使用 -b 命令行选项来更改最大骨骼数,那么您还应该更改着色器以使用相同数量的骨骼。这可以在为 ModelBatch 创建 ShaderProvider 时使用 Config # numbones 成员来完成。例如:
DefaultShader.Config config = new DefaultShader.Config();
config.numBones = 16;
modelBatch = new ModelBatch(new DefaultShaderProvider(config));