Three.js прикрепление объекта к кости

Есть ли способ прикрепить сетку к кости? Например, я загружаю анимированный персонаж.js и хочу прикрепить оружие к его руке.

3 ответа

Решение

Это возможно с помощью нескольких простых хаков на прототипе Bone и Object3D. Поскольку кости наследуются от Object3D, они могут иметь детей, поэтому мы можем легко.add () создать меш для любой кости.

Однако SkinnedMesh будет вызывать updateMatrixWorld() только для дочерних элементов, отличных от Bone, и update() для дочерних элементов Bone. Кроме того, кости вызывают update() для каждого из его дочерних элементов (независимо от того, кость это или нет). Следующие фрагменты изменяют это поведение:

// modify bone update function to also update its world matrix
// possibly do this only to skeletons you need it for, not for all bones
var update = THREE.Bone.prototype.update;
THREE.Bone.prototype.update = function(parentSkinMatrix, forceUpdate) {
    update.call(this, parentSkinMatrix, forceUpdate);
    this.updateMatrixWorld( true );
};

// add noop update function to Object3D prototype
// so any Object3D may be a child of a Bone
THREE.Object3D.prototype.update = function() {};

// create buffalo ...

// create a mesh and add it to some bone
var mesh = new THREE.Mesh( new THREE.SphereGeometry(20), new THREE.MeshNormalMaterial() );

var bone = buffalo.bones[5];
bone.add(mesh);

Three.js Version 68 обрабатывает это из коробки, но немного по-другому. Никаких изменений внутренних функций не требуется.

Теперь это работает так:

иерархия костей теперь находится в потомках SkinnedMesh.

Найдите кость в списке детей и просто прикрепите к ней объект:

player.children[0].add(testObj);

Примечание. Если у вас есть иерархия костей (например, в вашей экспортированной модели блендера), то она также представлена ​​в файле three.js. Если у вашей целевой кости есть родительская кость, она будет выглядеть так:

player.children[0].children[1].add(testObj);
              const modelWithSkeleton = scene.getObjectByName("modelWithSkeleton")   
        loader.load("ModeltoAttachToBone", (object) => {
        object.name = "modelAttachedToBone"   
    
 modelWithSkeleton.children[x].skeleton.getBoneByName("boneToAttachObject").add(object)
        })

работает на меня

Другие вопросы по тегам