Three.js SkinnedMesh - 将顶点绑定到骨骼

问题描述 投票:0回答:1

我使用OpenCV来处理任何给定的图像(段,凸壳,腔)。然后我使用Three.js将这些坐标用作骨骼。为了创建SkinnedMesh,我开始使用this cylinder example,它是1-linear。由于我的目标是支撑手臂/腿,我决定从顶点到最近骨骼的距离,这导致许多失败。

skinIndex的顶点不响应。阴影随动画移动,但不随模型移动。两侧移动,但不是前/后。这似乎是一个计时问题,可能需要一个promise / async(?)我试过调用needsUpdate,分配一个计数,设置dynamic为true等。

我意识到这是未完成的作业,但是从根本上说是错误的吗?

https://codepen.io/kpachinger/pen/ZVgejg

var skinIndices = [];
var skinWeights = [];

function distance(x1, y1, x2, y2) {
  let a = x1 - x2;
  let b = y1 - y2;
  let c = 1 - Math.sqrt(a * a + b * b);
  c = Math.abs(c);

  return c;
}

let pos = geometry.attributes.position;
var promise = new Promise(function(resolve, reject) {

  let root = sto.skind[0].id;
  let skin = [];

  for (let i = 0; i < pos.count; i++) {
    x1 = pos.array[i * 2];
    y1 = pos.array[i * 3];

    skin[i] = [];

    for (let j = 0; j < bones.length; j++) {
      x2 = bones[j].positionGlobal.x / sto.width;
      y2 = bones[j].positionGlobal.y / sto.height;

      if (bones[j].name != 'Root' && bones[j].name != 'Bone_0') {
        skin[i].push(distance(x1, y1, x2, y2) + '|' + bones[j].id);
      }
    }

    skin[i].sort();

    let closest = skin[i][0];
    closest = closest.split('|');
    closest = {
      'dist': closest[0],
      'id': closest[1] * 1
    };

    const halfHeight = area / (sto.width + sto.height) / 4;
    const segmentHeight = halfHeight / 3;

    const y = Math.abs(y1);
    var skinIndexY = Math.floor(y / segmentHeight / 2);
    var skinWeightY = ((y / segmentHeight) * (halfHeight / 2)) / 2;

    skinIndices.push(
      skinIndexY,
      closest.id,
      closest.id,
      root);

    //all add up to 1
    skinWeights.push(
      0.5 - (skinWeightY*0.50),
      (skinWeightY*0.50),
      0.25,
      0.25);

  }

  resolve('Vertices => SkinnedMesh');
});


promise.then(function(value) {
  console.log(value);

  geometry.addAttribute('skinIndex', new THREE.Uint16BufferAttribute(skinIndices, 4));
  geometry.addAttribute('skinWeight', new THREE.Float32BufferAttribute(skinWeights, 4));

  mesh = new THREE.SkinnedMesh(geometry, [material, materialSides]);
  let skeleton = new THREE.Skeleton(bones);

  mesh.add(bones[0]);
  mesh.bind(skeleton);

  let skeletonHelper = new THREE.SkeletonHelper(mesh);
  skeletonHelper.material.linewidth = 2;

  group.add(mesh, skeletonHelper);

  return mesh;
});
three.js mesh init skin inverse-kinematics
1个回答
1
投票

已解决:修复:

  • var vertex = new THREE.Vector3();
  • vertex.form BufferAttribute(position,i);
  • skinIndices数组应该增加新的,唯一的骨骼ID,而不是参考预先存在的。
  • 不要在纹理中混合SkinnedMesh和Mesh,否则撕裂/消失/取消同步阴影
© www.soinside.com 2019 - 2024. All rights reserved.