Three.js: 重新连接骨骼后如何rebind/reconnect网格化骨架?

Three.js: How to rebind/reconnect mesh skeleton after reconnecting bone?

基本上,我试图在全局轴上独立地旋转我装配的手部网格上的骨骼,并使用我用来计算它们方向的方向向量。我想出了这个代码来做到这一点:

function boneLookAtLocal(bone, position) {
    bone.updateMatrixWorld()
    let direction = position.clone().normalize()
    let pitch = Math.asin(-direction.y)
    let yaw = Math.atan2(direction.x, direction.z); 
    let roll = Math.PI;
    bone.rotation.set(roll, yaw, pitch);
}

function boneLookAtWorld(bone, v) {
    scene.attach(bone)
    boneLookAtLocal(bone, v)
    bone.parent.attach(bone) 
}

在手腕和食指上调用此代码会产生我 want/would 期望的手指姿势:

// hand.wrist and hand.index[0:3] are bones
boneLookAtWorld(hand.wrist, new THREE.Vector3(1, 1, 1))
boneLookAtWorld(hand.index[0], new THREE.Vector3(1, 1, 1))
boneLookAtWorld(hand.index[1], new THREE.Vector3(1, 0, 1))
boneLookAtWorld(hand.index[2], new THREE.Vector3(0, -1, 0))

问题是,每次我在骨骼上调用 boneLookAtWorld() 后,它都会断开与网格的连接,正如您从骨架助手中看到的那样,blue/green 骨架线不再连接我在其上调用 boneLookAtWorld() 的腕骨和食指骨。

因此,此解决方案一直有效,直到我想更改已调用 boneLookAtWorld() 的骨骼的方向。因此,如果我在之前的调用之后再次调用手腕上的 boneLookAtWorld():

// hand.wrist and hand.index[0:3] are bones
boneLookAtWorld(hand.wrist, new THREE.Vector3(1, 1, 1))
boneLookAtWorld(hand.index[0], new THREE.Vector3(1, 1, 1))
boneLookAtWorld(hand.index[1], new THREE.Vector3(1, 0, 1))
boneLookAtWorld(hand.index[2], new THREE.Vector3(0, -1, 0)) 
...
boneLookAtWorld(hand.wrist, new THREE.Vector3(0, 0, 1))

这会旋转手腕,但会留下其余的手指:


有谁知道我如何在我的函数 boneLookAtWorld() 中将骨骼重新连接到其父级后如何将骨骼重新绑定到 mesh/skeleton 来解决这个问题?

如果这对任何人都有帮助,则无需执行任何类型的重新网格划分。

发生这种情况的原因是因为:

function boneLookAtWorld(bone, v) {
    scene.attach(bone)
    boneLookAtLocal(bone, v)
    bone.parent.attach(bone)
}

当我们将骨骼附加到场景时,场景成为骨骼的新父级。因此,在我们通过 boneLookAtLocal() 执行旋转并重新附加骨骼之后,我们并没有将骨骼重新附加到原始父级!骨骼刚刚重新附加到它已经附加到的场景。

这可以通过将 boneLookAtWorld() 更改为:

来解决
function boneLookAtWorld(bone, v) {
    const parent = bone.parent;
    scene.attach(bone)
    boneLookAtLocal(bone, v)
    parent.attach(bone)
}