Three.js - 获取动画期间的当前骨骼骨骼位置
Three.js - get current skeleton bones position during animation
我有一个正在播放动画的 Three.js 项目,我想在不同时间找到骨骼骨骼的位置。
如果我去:https://modelviewer.dev/examples/animation/index.html
并找到 Three.js 场景:
const modelViewer = document.querySelector("model-viewer");
const scene = modelViewer[Object.getOwnPropertySymbols(modelViewer)[14]];
然后我可以访问例如 LowerArmR
的位置,在这种情况下它是动画的:
scene.children[0].children[0].children[0].children[0].children[1].children[0].skeleton.bones.find(b => b.name == "LowerArmR").position
如果我这样做,在动画的不同点,我总是得到相同的位置:
{x: 1.86264503820865e-10, y: 0.00575238140299916, z: -1.02445485428149e-9}
如何在动画期间访问当前骨骼位置?
如果我在人形化身动画上执行此过程,然后尝试绘制骨骼的位置,我只会得到 T 形姿势,而不是每个给定时间的实际位置:
来自 here 我可以看到:
Skeletal Animations are handled on the GPU so this data is not exactly
accessible in js code at runtime.
Perhaps someone knows some workaround, but as far as I am aware there
is none.
我正在寻找解决方法或规范方法。
骨骼动画(或“蒙皮”)应用于 GPU 上的各个网格顶点1,因为顶点的数量通常比骨骼的数量多得多,并更新它们CPU 上的所有计算量都很大。
然而,骨骼本身的变换 是 在 three.js 中的 CPU 上计算的。此处可能不明显的区别是:
- 骨骼的
.position
属性,继承自THREE.Object3D's .position属性,是一个local位置,相对于其父级的位置及其父级等。
- 大多数骨骼动画通过旋转而不是平移单个骨骼来运行。例如,肩部的旋转将具有平移和旋转该骨骼的后代(即手臂的其余部分)的效果。
将所有这些放在一起,您想要找到的是特定骨骼的世界位置,而不是局部位置。 Object3D parent class 有一个方法可以帮助解决这个问题,object.getWorldPosition:
const position = new THREE.Vector3();
bone.getWorldPosition( position );
请注意,此方法会产生一些性能开销,因为它在计算当前世界位置之前首先更新骨骼的世界矩阵——遍历其祖先。如果您需要许多骨骼的位置,或其他属性,如世界旋转和缩放,最好确保所有全局变换都更新一次(scene.updateMatrixWorld()
,如果需要),然后分解对象的 .matrixWorld
:
const position = new THREE.Vector3();
position.setFromMatrixPosition( bone.matrixWorld );
1 如果您确实需要计算 CPU 上特定顶点的位置,则 three.js SkinnedMesh class为此有一个辅助方法:.boneTransform().
我有一个正在播放动画的 Three.js 项目,我想在不同时间找到骨骼骨骼的位置。
如果我去:https://modelviewer.dev/examples/animation/index.html 并找到 Three.js 场景:
const modelViewer = document.querySelector("model-viewer");
const scene = modelViewer[Object.getOwnPropertySymbols(modelViewer)[14]];
然后我可以访问例如 LowerArmR
的位置,在这种情况下它是动画的:
scene.children[0].children[0].children[0].children[0].children[1].children[0].skeleton.bones.find(b => b.name == "LowerArmR").position
如果我这样做,在动画的不同点,我总是得到相同的位置:
{x: 1.86264503820865e-10, y: 0.00575238140299916, z: -1.02445485428149e-9}
如何在动画期间访问当前骨骼位置?
如果我在人形化身动画上执行此过程,然后尝试绘制骨骼的位置,我只会得到 T 形姿势,而不是每个给定时间的实际位置:
来自 here 我可以看到:
Skeletal Animations are handled on the GPU so this data is not exactly accessible in js code at runtime.
Perhaps someone knows some workaround, but as far as I am aware there is none.
我正在寻找解决方法或规范方法。
骨骼动画(或“蒙皮”)应用于 GPU 上的各个网格顶点1,因为顶点的数量通常比骨骼的数量多得多,并更新它们CPU 上的所有计算量都很大。
然而,骨骼本身的变换 是 在 three.js 中的 CPU 上计算的。此处可能不明显的区别是:
- 骨骼的
.position
属性,继承自THREE.Object3D's .position属性,是一个local位置,相对于其父级的位置及其父级等。 - 大多数骨骼动画通过旋转而不是平移单个骨骼来运行。例如,肩部的旋转将具有平移和旋转该骨骼的后代(即手臂的其余部分)的效果。
将所有这些放在一起,您想要找到的是特定骨骼的世界位置,而不是局部位置。 Object3D parent class 有一个方法可以帮助解决这个问题,object.getWorldPosition:
const position = new THREE.Vector3();
bone.getWorldPosition( position );
请注意,此方法会产生一些性能开销,因为它在计算当前世界位置之前首先更新骨骼的世界矩阵——遍历其祖先。如果您需要许多骨骼的位置,或其他属性,如世界旋转和缩放,最好确保所有全局变换都更新一次(scene.updateMatrixWorld()
,如果需要),然后分解对象的 .matrixWorld
:
const position = new THREE.Vector3();
position.setFromMatrixPosition( bone.matrixWorld );
1 如果您确实需要计算 CPU 上特定顶点的位置,则 three.js SkinnedMesh class为此有一个辅助方法:.boneTransform().