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

时间:2013-12-09 07:22:49

标签: javascript animation opengl-es three.js skeletal-mesh

我正在开发一款小型多人游戏,它有一个单一的皮肤玩家网格,很多玩家使用它。 一些背景:我尝试通过maya和blender collada export加载。两者似乎都参考了某种形式的动画数据,但我无法让它发挥作用。我已经尝试过maya JSON导出器,它只用一条物质线吐出很小的1k文件。最后,搅拌机JSON导出器工作。对于那些也试图加载蒙皮网格的人,我发现这非常有用:Model with bones animation (blender export) animating incorrectly in three.js

所以现在我有了一个geometry对象和一个来自JSON加载器的materials数组。

我可以在素材上设置skinning=true,创建THREE.SkinnedMesh,将其添加到场景中,通过THREE.AnimationHandler.add添加动画(我很不清楚{ {1}}实际上),创建AnimationHandler,致电THREE.Animationplay()。最后我在我的场景中播放了一个网格和一个动画。

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

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

    • 我不希望多次加载相同的网格和动画数据。
    • 动画时间应该是每个实例(因此它们不能全部同步动画)。

    我应该为同一型号创建多个update(dt)THREE.SkinnedMesh吗? THREE.Animation在哪里?

  2. 许多动画 - 我希望能够单独播放空闲/运行周期。

    AFAIK只有一个动画关键帧的时间轴。 Three.js如何为我分区,或者我必须手动分区吗?

  3. 动画混合 - 当角色停止运行并使用空闲动画静止不动时,我不希望从一个角色到另一个角色立即拍摄。我想暂停运行动画并将该状态重新混合到空闲动画中。

    目前是否可以使用蒙皮网格(不是变形目标)?是否有关于此的示例或文档?

  4. 任何信息都会受到高度赞赏,即使只是朝着正确的方向推进。 我不是在完整的教程之后,我想了解一些关于这些功能的更高级别的信息。

    我很乐意实现 2 3 ,但我想了解一些关于threejs皮肤和动画框架的信息/描述文档,以帮助我入门。例如,this并不多。

    [修改]
    谢谢@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.AnimationHandler但仍然不确定THREE.SkinnedMesh
    2. 不知道。也许有一种方法可以在THREE.AnimationHandler
    3. 中手动修改开始/结束关键帧
    4. 未实施AFAIK。我可能会尝试创建一个自定义着色器,它可以使用两个THREE.Animation并在它们之间进行插值。

3 个答案:

答案 0 :(得分:13)

自版本67(2014年4月)起,支持骨架动画混合和多个动画。您仍然需要为每个模型创建SkinnedMeshAnimationHandler负责每帧更新(勾选)动画,因此您应该在其上调用更新,而不是在每个Animation上手动调用。

请参阅新添加的示例: webgl_animation_skinning_blending.html 或在此处查看我自己的几个:

Basic Character Controller (with time warped speed blend)

Time Warped Speed Blend

答案 1 :(得分: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's really helpful tutorial

中提供的函数相同

“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中创建一个额外的动画动作,将模型从活动状态混合到它的空闲状态。

答案 2 :(得分:0)

@Xealgo:Maya的新出口商也做骨骼和动画。在我被迫使用Blender工作流程之前,我很想在几个月前拥有它。 :)

这是一个链接:https://github.com/mrdoob/three.js/tree/dev/utils/exporters/maya