【问题标题】:How to move a glTF model in the direction it is facing in A-frame?如何将 glTF 模型沿其在 A 帧中所面对的方向移动?
【发布时间】:2022-02-11 18:24:02
【问题描述】:

我在 A-frame 场景版本 1.0.4 中加载了我的机器人的 gltf 模型。到目前为止,我可以围绕它的 x、y、z 轴转动机器人,但是当我尝试将其向前移动时,它仍会沿其初始方向移动,而不是它所面对的方向。我希望能够在不使用任何外部库的情况下用我的键盘控制它的动作。我相信我必须使用四元数,但我还没有弄清楚如何使用它们。到目前为止,这是我的 A 帧代码。

<a-scene id="myScene">
  <a-entity environment="preset:forest;"></a-entity>

 <a-entity gltf-model="#humanoid" id="robot" position="0 20 0" rotation="0 0          0" 
   scale="0.0001 0.0001 0.0001" static-body>
 </a-entity>
</a-scene>

这是我的脚本

const robot = document.getElementById('robot');

const update = () => {
   if (keys.forward) {
       let {x,y,z} = robot.object3D.position;
       let ry = robot.object3D.rotation.y;
       z += Math.cos(ry * Math.PI/180)/12;
       x += Math.sin(ry * Math.PI/180)/12;
       robot.object3D.position.set(x, y, z); 
}
   else if (keys.backwards) {
       let {x, y, z} = robot.object3D.position;
       let ry = robot.object3D.rotation.y;
       z -= Math.cos(ry * Math.PI/180)/10;
       x -= Math.sin(ry * Math.PI/180)/10;
       robot.object3D.position.set(x, y, z);   
}
 if (keys.turnLeft) {
       let {x, y, z} = robot.getAttribute('rotation');
       y += 0.25;
       robot.setAttribute('rotation',{x,y,z});
}
    else if (keys.turnRight) {
        let {x, y, z} = robot.getAttribute('rotation');
        y -= 0.25;
        robot.setAttribute('rotation',{x,y,z});
}
}

【问题讨论】:

  • 听起来this线程很相似
  • 这对相机按预期工作,我可以在相机面对的方向移动机器人,但不能在它面对的方向移动它。它显示错误“无法读取未定义的属性(读取'getWorldDirection')”。
  • @jacob1 用你的方法和 getWorldDirection 做了一个 anwser

标签: javascript html aframe


【解决方案1】:
let ry = robot.object3D.rotation.y;
z += Math.cos(ry * Math.PI/180)/12;

虽然a-frame使用度数进行旋转,threejs使用弧度,所以不需要再次转换:

const robot = document.querySelector("a-box")
document.body.addEventListener("keydown", (evt) => {
   if (evt.key === 's') {
       let {x,y,z} = robot.object3D.position;
       let ry = robot.object3D.rotation.y;
       z += Math.cos(ry)/12;
       x += Math.sin(ry)/12;
       robot.object3D.position.set(x, y, z); 
    } else if (evt.key === 'w') {
       let {x, y, z} = robot.object3D.position;
       let ry = robot.object3D.rotation.y;
       console.log(ry)
       z -= Math.cos(ry)/10;
       x -= Math.sin(ry)/10;
       robot.object3D.position.set(x, y, z);   
     }
     if (evt.key === 'a') {
       let {x, y, z} = robot.getAttribute('rotation');
       y += 1;
       robot.setAttribute('rotation',{x,y,z});
     } else if (evt.key === 'd') {
       let {x, y, z} = robot.getAttribute('rotation');
       y -= 1;
       robot.setAttribute('rotation',{x: x,y: y,z: z});
     }
})
<script src="https://aframe.io/releases/1.3.0/aframe.min.js"></script>
<a-scene>
  <a-box position="-1 0.5 -3" rotation="0 0 0" color="#4CC3D9">
    <a-sphere radius="0.5" position="0 0 -1"></a-sphere>
  </a-box>
  <a-entity camera position="0 1.6 0"></a-entity>
</a-scene>

getWorldDirection相同:

const robot = document.querySelector("a-box")
const direction = new THREE.Vector3();
document.body.addEventListener("keydown", (evt) => {
   if (evt.key === 's') {
     // get robot direction
     robot.object3D.getWorldDirection(direction);
     // add a "speed" value
     direction.multiplyScalar(0.1)
     // add the new vector to the actual position
     robot.object3D.position.add(direction)
    } else if (evt.key === 'w') {
     robot.object3D.getWorldDirection(direction);
     direction.multiplyScalar(-0.1)
     robot.object3D.position.add(direction) 
    }
    if (evt.key === 'a') {
     let {x, y, z} = robot.getAttribute('rotation');
     y=y+1
     robot.setAttribute('rotation',{x,y,z});
    } else if (evt.key === 'd') {
     let {x, y, z} = robot.getAttribute('rotation');
     y=y-1
     robot.setAttribute('rotation',{x: x,y: y,z: z});
    }
})
<script src="https://aframe.io/releases/1.3.0/aframe.min.js"></script>
<a-scene>
  <a-box position="-1 0.5 -3" rotation="0 0 0" color="#4CC3D9">
    <a-sphere radius="0.5" position="0 0 -1"></a-sphere>
  </a-box>
  <a-entity camera position="0 1.6 0"></a-entity>
</a-scene>

【讨论】:

  • 同意 Diarmid 所说的所有内容(+1),只是想让您知道为什么您的脚本不起作用
  • 谢谢,getWorldDirection 方法在所有可能的旋转角度都可以正常工作。但是控制有点滞后。无论如何,谢谢。
【解决方案2】:

是的,使用四元数是解决这个问题的好方法。

您可以简单地将机器人的当前四元数应用于表示您希望在机器人原始旋转中进行的运动的向量3,并将其应用于机器人的位置。

类似这样的:

fowardVector = new Vector3(0, 0, -0.1)
rotatedForwardVector = new Vector3();

rotatedForwardVector.copy(forwardVector);
rotatedForwardVector.applyQuaternion(robot.object3D.quaternion);
robot.object3D.position.add(rotatedForwardVector);

请注意,您只想创建一次 Vector3,然后重复使用它们以避免不必要的垃圾收集,而不是为每个动作创建它们。

例如使用 here 解释的闭包

【讨论】:

    【解决方案3】:

    您可以使用四元数和许多其他方式,但 Object3D 有一些有用且更简单的替代方法可以在局部坐标中移动对象:

    我觉得最简单的就是用https://threejs.org/docs/#api/en/core/Object3D.translateZ

    robot.object3D.translateZ(amountToMoveForward);
    

    还可以使用https://threejs.org/docs/#api/en/core/Object3D.localToWorld 来转换向量。

    【讨论】:

      猜你喜欢
      • 2018-07-21
      • 1970-01-01
      • 2019-09-10
      • 2023-04-05
      • 1970-01-01
      • 2021-08-30
      • 2013-01-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多