Three.js - 骨骼蒙皮网格实例、动画和混合

25

我正在开发一个小型的多人游戏,其中有一个带有单个皮肤的播放器模型,许多玩家都在使用它。 一些背景信息: 我尝试了通过maya和blender导出collada格式加载模型。两者似乎都引用了某种形式的动画数据,但我无法让它们正常工作。我尝试了maya JSON导出器,但它只生成了非常小的1k文件,只包含材质行。最后,blender JSON导出器起到了作用。对于那些也在尝试加载蒙皮网格的人,我发现这个链接非常有用:Model with bones animation (blender export) animating incorrectly in three.js

现在我有了从JSON加载器中得到的geometry对象和materials数组。

我可以在材料上设置skinning=true,创建一个THREE.SkinnedMesh,将其添加到场景中,通过THREE.AnimationHandler.add添加动画(我对AnimationHandler实际上是做什么的还不太清楚),创建一个THREE.Animation,调用play()update(dt)。最终,在我的场景中有一个单个的网格和一个正在播放的动画。

现在我想要的是这些...

  1. 许多实例 - 我希望我的场景中有多个运行的播放器模型。

    • 我不想加载多次相同的网格和动画数据。
    • 动画时间应该是每个实例独立的(所以它们不会全部同步播放)。

    我应该为同一个模型创建多个THREE.SkinnedMeshTHREE.Animation吗?THREE.AnimationHandler是用来做什么的?

  2. 许多动画 - 我想要分别播放空闲/奔跑循环的能力。

    据我所知,动画关键帧只有一个时间轴。Three.js如何为我分配它,还是我必须手动完成?

  3. 动画混合 - 当角色停止奔跑并静止不动时,我不想从一个动画立即切换到另一个。我想暂停奔跑动画并将该状态混合回空闲动画。

    目前在蒙皮网格(而不是变形目标)中是否可以实现此功能?是否有相关的示例或文档?

任何信息都将不胜感激,即使只是指出正确的方向。我不需要完整的教程,我想要一些关于这些功能的高级信息。

我很乐意实现23,但我想了解一些关于threejs皮肤和动画框架的信息/描述性文档以帮助我入门。例如,这个没有太多参考价值。

[编辑]
谢谢@NishchitDhanani,这个页面非常好,但没有提到多个动画或混合骨骼动画:http://chimera.labs.oreilly.com/books/1234000000802/ch05.html#animating_characters_with_skinning

这个页面说多个动画仍然是一个当前的问题,但没有更多的信息(在评论中简要讨论): http://devmatrix.wordpress.com/2013/02/27/creating-skeletal-animation-in-blender-and-exporting-it-to-three-js/

目前的答案是...

  1. 使用许多THREE.SkinnedMesh,但仍不确定如何使用THREE.AnimationHandler
  2. 不知道。也许有一种方法可以在THREE.Animation中手动修改起始/结束关键帧。
  3. 据我所知尚未实现。我可能会尝试创建一个自定义着色器,可以接受两个THREE.Animation并在它们之间进行插值。

有没有人能给那些必须从MAYA 2013导出场景的人提供一些建议?除了将其导入不同的程序之外,没有其他选择。 - Ryan Blevins
@RyanBlevins 我正在使用Collada导入我的关卡模型和灯光等。只是我无法让骨骼动画正常工作。Collada加载器会为你提供一个带有.scene的对象。你可以添加整个场景或从其子元素中进行选择。 - jozxyqk
它必须具备皮肤骨骼动画。 - Ryan Blevins
3个回答

13

从2014年4月版本的发布67开始,支持骨骼动画混合和多个动画。你仍需要为每个模型创建一个 SkinnedMeshAnimationHandler 负责每帧更新(轮询)动画,因此您应该在其上调用update而不是手动调用每个Animation

查看新增的示例:webgl_animation_skinning_blending.html 或者参考我自己的这几个示例:

基本角色控制器(带时间扭曲速度混合)

时间扭曲速度混合


在网站上没有看到WebGL动画蒙皮混合示例,同时,使用Blender导出具有多个动画的模型并在Three.js版本66中加载它会抛出错误“Uncaught TypeError:Cannot read property 'name' of undefined”,有什么想法吗? - Jason Welch
2
没错,它在当前的“dev”分支上,还没有进入版本发布。https://github.com/mrdoob/three.js/tree/dev - insominx
啊,好的!我应该意识到这点的 :p 谢谢。 - Jason Welch

0

我已经成功地同时部署了四个不同的动画模型,这些模型是使用Blender创建并导出为JSON文件的。我通过为每个模型创建单独的蒙皮网格,并使用针对每个模型量身定制的函数与JSON加载器一起使用,实现了这一目标。我的四个模型都具有不同的网格、动画、纹理和关键帧数量。

var loader = new THREE.JSONLoader(); 
loader.load("model_1.js", createSkinnedMeshforModel_1);
loader.load("model_2.js", createSkinnedMeshforModel_2);
loader.load("model_3.js", createSkinnedMeshforModel_3);

...

var animations = [];

function createSkinnedMeshforModel_1( geometry, materials )
{
  var myModel1, animation;
  THREE.AnimationHandler.add( geometry.animation );
  myModel1 = new THREE.SkinnedMesh(geometry, new THREE.MeshFaceMaterial(materials));
  enableSkinning( myModel1 );
  scene.add( myModel1 );
  animation = new THREE.Animation(myModel1, Model1_Animation_title, THREE.AnimationHandler.CATMULLROM);
  animations.push( animation );
  for( var i = 0; i < animations.length; i ++ )
  {
    animations[ i ].play();
  }
}


function createSkinnedMeshforModel_2( geometry, materials )
{
  var myModel2, animation;
  THREE.AnimationHandler.add( geometry.animation );
  myModel2 = new THREE.SkinnedMesh(geometry, new THREE.MeshFaceMaterial(materials));
  enableSkinning( myModel2 );
  scene.add( myModel2 );
  animation = new THREE.Animation(myModel2, Model2_Animation_title, THREE.AnimationHandler.CATMULLROM);
  animations.push( animation );
  for( var i = 0; i < animations.length; i ++ )
  {
    animations[ i ].play();
  }
}

function createSkinnedMeshforModel_3( geometry, materials )
{
  var myModel3, animation;
  THREE.AnimationHandler.add( geometry.animation );
  myModel3 = new THREE.SkinnedMesh(geometry, new THREE.MeshFaceMaterial(materials));
  enableSkinning( myModel3 );
  scene.add( myModel3 );
  animation = new THREE.Animation(myModel3, Model3_Animation_title, THREE.AnimationHandler.CATMULLROM);
  animations.push( animation );
  for( var i = 0; i < animations.length; i ++ )
  {
    animations[ i ].play();
  }
}

enableSkinning()函数与DEVMATRIX非常有帮助的教程中提供的相同。

"Modelx_Animation_title"变量是在Blender中定义并由Three.js Blender导出器复制到模型导出的JSON文件中的动画标题名称。

当我加载给定模型的多个副本时,它们最初会同步播放动画。但是,我已经能够通过短暂随机暂停每个模型后再开始播放来使它们异步播放动画。每个单独模型的动画将从暂停的帧恢复播放。

animations[ i ].pause();
... (random delay) ...
animations[ i ].play();

也许这种方法可以在某种程度上解决问题1,可能也可以解决问题2。

关于问题2,Three.js发布的r62版本更新了Blender导出器,允许“导出多个动作”。虽然我没有尝试过,但也许这可以在加载给定模型的两个或更多副本时指定不同动画标题。然后,在需要不同动作时,可能可以将模型从视图中切换进出。

如果这样行得通,那么问题3的一个可能解决方案是在Blender中创建一个额外的动画动作,将模型从活动状态混合到其空闲状态。


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接