1

我正在 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 可视化的骨架。

骨骼非常糟糕的机器人

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

提前致谢!

4

2 回答 2

0

child.getWorldPosition(p);

恐怕将世界空间中的位置应用到Bone.position代表本地空间中的位置是不正确的。

骨父=骨;

这条线看起来也有问题。一个骨骼可以有多个子元素。在我看来,您的代码没有考虑这个用例。

于 2020-12-14T11:58:52.863 回答
0

经过一番摆弄,我找到了解决方案:

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()省去了很多矩阵麻烦:)

于 2021-05-27T08:48:14.917 回答