You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ThreeJS技术问询:如何在绑定骨骼的网格(Rigged Mesh)上标记点位?

基于ThreeJS实现骨骼形变网格的标记点同步方案

最优方案:复用骨骼权重与矩阵实时计算位置

这是最直接高效的实现方式,无需额外骨骼或纹理,核心逻辑复用ThreeJS自身的蒙皮计算机制:

  • 点击拾取关键数据:用Raycaster检测点击,获取目标网格、点击交点,以及交点对应的网格顶点索引(或直接取交点的局部空间坐标)。
  • 提取顶点绑定信息:从网格的skinIndex和skinWeight属性中,拿到该顶点绑定的骨骼索引及对应权重值(ThreeJS默认每个顶点最多绑定4根骨骼)。
  • 实时更新标记点坐标:每帧动画更新后,遍历顶点绑定的骨骼,用骨骼的worldMatrix变换顶点局部位置,再按权重加权求和,将结果赋值给标记点的position。

对你现有思路的分析

  • 新增骨骼方案:可行但冗余。可以通过权重占比最高的骨骼作为父级,但需要手动创建骨骼、设置父子关系、分配权重,步骤繁琐,远不如直接计算位置高效。
  • 绑定特定顶点:这正是最优方案的核心——不需要把顶点“赋值给变量”,而是直接利用顶点自带的骨骼绑定数据,复现蒙皮形变后的位置,完全符合需求。
  • 纹理实现方案:完全没必要,会无端增加渲染开销,不符合你的轻量化需求。

关键代码示例

// 假设已通过Raycaster获取:目标网格skinnedMesh、点击顶点索引vertexIndex、标记点marker
const geometry = skinnedMesh.geometry;
const skinIndex = geometry.attributes.skinIndex;
const skinWeight = geometry.attributes.skinWeight;
const skeleton = skinnedMesh.skeleton;

// 获取顶点的局部初始位置
const localVertexPos = new THREE.Vector3();
localVertexPos.fromBufferAttribute(geometry.attributes.position, vertexIndex);

// 每帧更新标记点位置的函数
function updateMarker() {
  const finalPos = new THREE.Vector3(0, 0, 0);
  // 遍历顶点绑定的4根骨骼(ThreeJS默认上限)
  for (let i = 0; i < 4; i++) {
    const boneIdx = skinIndex.getX(vertexIndex, i);
    const weight = skinWeight.getX(vertexIndex, i);
    if (weight === 0) continue;
    
    const bone = skeleton.bones[boneIdx];
    const transformedPos = localVertexPos.clone().applyMatrix4(bone.matrixWorld);
    finalPos.add(transformedPos.multiplyScalar(weight));
  }
  marker.position.copy(finalPos);
}

// 在动画循环中调用更新函数
function animate() {
  requestAnimationFrame(animate);
  updateMarker();
  renderer.render(scene, camera);
}

内容的提问来源于stack exchange,提问作者Anson Kao

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 18:45:13