【问题标题】:How to clone a Skinned Mesh?如何克隆蒙皮网格?
【发布时间】:2018-01-05 17:16:49
【问题描述】:

我需要在一个场景中有多个相同的动画模型。如果可能的话,我希望它们有一个共享的几何体和材质,但如果不可能,让它们为每个模型实例化也足够了。

不幸的是,我发现实现这个结果的唯一方法是对每个模型实例都通过 JSONLoader。

SkinnedMesh 确实有一个 clone() 方法,但它似乎还没有完全实现。如果使用并且场景中同时存在原始网格和克隆网格,则只会出现一个,而克隆的网格将没有动画。

我尝试将此示例与共享骨架一起使用: https://github.com/mrdoob/three.js/pull/11666

...确实有效,但我需要能够为每个模型实例播放不同的动画,遗憾的是,让它们都播放相同的动画是不够的。我希望我可以做类似的 hax 并插入我自己的骨架(由 JSON 文件中的骨头制成),但它的行为非常类似于我只使用 SkinnedMesh 中的 clone()。

我正在使用此代码: https://github.com/arturitu/threejs-animation-workflow/blob/master/js/main.js

基本上我想要实现的是

 var onLoad = function (geometry, materials) {
window.geometry = geometry;

character = new THREE.SkinnedMesh(
  geometry,
  new THREE.MeshFaceMaterial(materials)
);

character2 = character.someMagicalClone();

scene.add(character);
scene.add(character2);

(...)

我需要任何线索...在等待帮助的同时,我正忙着解构 SkinnedMesh 和 JSONLoader 的构造函数以获取线索;)

提前致谢!

【问题讨论】:

    标签: animation three.js


    【解决方案1】:

    我在这个拉取请求中找到了一个解决方案: https://github.com/mrdoob/three.js/pull/14494

    简单来说就是增加了两个功能:

    function cloneAnimated( source ) {
    
        var cloneLookup = new Map();
    
        var clone = source.clone();
    
        parallelTraverse( source, clone, function ( sourceNode, clonedNode ) {
    
            cloneLookup.set( sourceNode, clonedNode );
    
        } );
    
        source.traverse( function ( sourceMesh ) {
    
            if ( ! sourceMesh.isSkinnedMesh ) return;
    
            var sourceBones = sourceMesh.skeleton.bones;
            var clonedMesh = cloneLookup.get( sourceMesh );
    
            clonedMesh.skeleton = sourceMesh.skeleton.clone();
    
            clonedMesh.skeleton.bones = sourceBones.map( function ( sourceBone ) {
    
                if ( ! cloneLookup.has( sourceBone ) ) {
    
                    throw new Error( 'THREE.AnimationUtils: Required bones are not descendants of the given object.' );
    
                }
    
                return cloneLookup.get( sourceBone );
    
            } );
    
            clonedMesh.bind( clonedMesh.skeleton, sourceMesh.bindMatrix );
    
        } );
    
        return clone;
    
    }
    
    function parallelTraverse( a, b, callback ) {
    
        callback( a, b );
    
        for ( var i = 0; i < a.children.length; i ++ ) {
    
            parallelTraverse( a.children[ i ], b.children[ i ], callback );
    
        }
    
    }
    

    据我了解,它将克隆的骨架重新绑定到克隆的网格。 所以主题示例可能如下所示:

    var onLoad = function (geometry, materials) {
        window.geometry = geometry;
        character = new THREE.SkinnedMesh(
          geometry,
          new THREE.MeshFaceMaterial(materials)
        );
    
        character2 = cloneAnimated(character); // <-- used that new function
    
        scene.add(character);
        scene.add(character2);
        (...)
    

    【讨论】:

    • 您能否编辑答案并添加更多有关这些功能的作用的信息?
    猜你喜欢
    • 2019-08-23
    • 2018-01-12
    • 2022-11-21
    • 2016-04-30
    • 2013-10-01
    • 2020-10-10
    • 2016-01-24
    • 2018-08-06
    • 2011-12-20
    相关资源
    最近更新 更多