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

时间:2019-02-08 19:08:31

标签: three.js mesh init skin inverse-kinematics

我使用OpenCV处理任何给定的图像(段,凸包,腔)。然后,我使用Three.js将这些坐标用作骨骼。为了创建SkinnedMesh,我从this cylinder example开始,它是1线性的。由于我的目标是支撑胳膊/腿,所以我决定从顶点到最近的骨骼保持距离,这导致了很多失败。

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;
});

1 个答案:

答案 0 :(得分:0)

已解决:修复程序:

  • var vertex = new THREE.Vector3();
  • vertex.fromBufferAttribute(position,i);
  • skinIndices数组应该增加新的唯一骨骼ID,而不是预先存在的引用。
  • 请勿在纹理内混合使用SkinnedMesh和Mesh,否则将不会出现眼泪/消失/不同步的阴影