在 Three.js 中以编程方式创建骨架

我正在 Three.js 中加载机构模型(例如机器人手臂)。遗憾的是,我使用的模型没有骨架,但我有关节的位置、轴等。为了使用诸如 Three-IK 之类的逆运动解算器,我想根据这些参数创建一个骨架。由于我想使用许多不同的模型,因此我宁愿不手动创建骨架,而是用代码创建骨架。


我已经尝试了一个多星期,根据这些反映模型的值创建有效的骨骼结构,但没有成功。例如,如果我使用关节的位置创建骨骼链,我会得到一个非常长的骨架,它与我使用的位置完全不匹配。


let boneParent;

let bonepos = [];

let bones = [];

model.traverse(child => {

    switch(child.type) {

        case "joint":

            let p = new Vector3();

            child.getWorldPosition(p);

            bonepos.push(p);


            let bone = new Bone();

            boneParent && boneParent.add(p);

            bone.worldToLocal(p.clone());

            bone.position.copy(p);

            bone.rotation.copy(child.rotation);

            bone.scale.copy(child.scale);


            boneParent = bone;

            bones.push(bone);

            break;

    }

});

showPoints(scene, bonepos, 0xff0000);


const skeletonHelper = new SkeletonHelper(bones[0]);

skeletonHelper.visible = true;

scene.add(skeletonHelper);

上面的代码产生下面的屏幕截图。红色标记是我从机器人关节获得的位置,蜿蜒延伸到远处的线是 SkeletonHelper 可视化的骨架。

https://img1.sycdn.imooc.com/65507d550001411f04090428.jpg

所以我的问题是:我似乎不太了解 Three.js 中如何处理骨骼。如何创建一个从关节位置和方向反映现有模型的骨架?

提前致谢!

对于未来的访客: Rocksi 是开源的!


饮歌长啸
浏览 256回答 2
2回答

森林海

经过一番摆弄,我找到了解决方案:let root = new Bone();let parent = root;let pos = new Vector3();for (let joint of robot.arm.movable) {    let link = robot.getLinkForJoint(joint);    link.getWorldPosition(pos);        let bone = new Bone();    parent.add(bone);    parent.lookAt(pos);    parent.updateMatrixWorld();  // crucial for worldToLocal!    bone.position.copy(bone.worldToLocal(pos));            parent = bone;}重要的部分是在lookAt()之后调用updateMatrixWOrld(),以便bone.worldToLocal()正常工作。还lookAt()省去了很多矩阵麻烦:)

RISEBY

child.getWorldPosition(p);恐怕将世界空间中的位置应用于代表本地Bone.position空间中的位置是不正确的。骨骼父 = 骨骼;这条线看起来也有问题。一根骨头可以有多个子元素。在我看来,您的代码没有考虑这个用例。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript