首页 > 解决方案 > Three.js - 如何使用来自姿态估计的数据为 3D 模型制作动画

问题描述

我正在尝试使用姿势估计坐标来为 Three.js 中的装配模型设置动画我正在使用的姿势估计技术提供来自视频源中的人的实时 x、y、z 坐标,我正在尝试使用这些相应地移动 3D 模型。我使用下面的代码(其中一些是我在相关问题的答案中找到的)作为起点......

let camera, scene, renderer, clock, rightArm;

init();
animate();

function init() {

  camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.01, 10);
  camera.position.set(2, 2, -2);

  clock = new THREE.Clock();

  scene = new THREE.Scene();
  scene.background = new THREE.Color(0xffffff);

  const light = new THREE.HemisphereLight(0xbbbbff, 0x444422);
  light.position.set(0, 1, 0);
  scene.add(light);

  // model
  const loader = new THREE.GLTFLoader();
  loader.load('https://threejs.org/examples/models/gltf/Soldier.glb', function(gltf) {

    const model = gltf.scene;

    rightArm = model.getObjectByName('mixamorigRightArm');

    scene.add(model);

  });

  renderer = new THREE.WebGLRenderer({
    antialias: true
  });
  renderer.setPixelRatio(window.devicePixelRatio);
  renderer.setSize(window.innerWidth, window.innerHeight);
  renderer.outputEncoding = THREE.sRGBEncoding;
  document.body.appendChild(renderer.domElement);

  window.addEventListener('resize', onWindowResize, false);

  const controls = new THREE.OrbitControls(camera, renderer.domElement);
  controls.target.set(0, 1, 0);
  controls.update();

}

function onWindowResize() {

  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();

  renderer.setSize(window.innerWidth, window.innerHeight);

}

//This was my attempt at deriving the rotation from two vector3's and applying it to the model
//storedresults is simply an array where I store the pose estimation data for a given position
//getPosition is just a helper function for getting the vector three for a specific position
function setRightArmRotation() {
  if (rightArm) {
    if (storedresults === undefined || storedresults.length == 0) {
      return;
    } else {
      if (vectorarray.length < 2) {
        vectorarray.push(getPosition(12));
      } else {
        vectorarray.pop();
        vectorarray.push(getPosition(12));
        var quaternion = new THREE.Quaternion();
        quaternion.setFromUnitVectors(vectorarray[0], vectorarray[1]);
        var matrix = new THREE.Matrix4();
        matrix.makeRotationFromQuaternion(quaternion);
        rightArm.applyMatrix4(matrix);
      }
    }
  }
}

function animate() {

  requestAnimationFrame(animate);

  const t = clock.getElapsedTime();

  if (rightArm) {

    rightArm.rotation.z += Math.sin(t) * 0.005;
    //setRightArmRotation()

  }

  renderer.render(scene, camera);

}
<script src="https://cdn.jsdelivr.net/npm/three@0.125.2/build/three.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.125.2/examples/js/loaders/GLTFLoader.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.125.2/examples/js/controls/OrbitControls.js"></script>

我还提到了这个关于从两个向量中查找旋转的答案,但我没有成功实现它以达到预期的结果...... 如何找到两个向量之间的旋转矩阵

我可以轻松地从姿势估计技术中获得 Vector3,并且我了解 jsfiddle 中的大部分内容是如何工作的,但我似乎无法将它们全部放在一起以获得让我的 3D 模型“镜像”运动的预期结果我的视频中使用姿势估计坐标的内容。我几乎可以让模型“四处乱窜”。

据我了解,我需要操纵骨骼的旋转以达到所需的结果,为此我需要使用两个向量来计算这些旋转,但经过大量研究和反复试验,我似乎无法提出这一切都在一起。任何帮助,将不胜感激。

标签: javascriptanimationthree.jsrotationmediapipe

解决方案


推荐阅读