A 帧在相机方向向前移动

Kri*_*fer 4 javascript three.js aframe

我正在尝试在 A 帧中制作一个组件,该组件将在相机面向的方向上移动播放器/相机。它不应该在 y 平面上的任何地方移动,只能在 x/y 平面上移动。dom中的当前设置是:

<a-entity>
    <a-camera></a-camera>
</a-entity>
Run Code Online (Sandbox Code Playgroud)

我想在当前相机方向将实体元素位置移动到 x 单位,但它不应该在 y 平面上移动任何东西。我尝试了各种解决方案,但它们似乎在相机中引入了一些奇怪的转变。

Pio*_*ski 12

您可以通过多种方式处理此问题。

0) 向量

简单且适用于大多数 3D 引擎:

  • 抓取相机的前向矢量/世界方向
  • 乘以你想要移动的距离
  • 将其添加到您的位置向量

a-frame 组件中的上述步骤可能如下所示:

<script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script>
<script>
  // define a custom component
  AFRAME.registerComponent("foo", {
    init: function() {
      // grab the camera
      var player = document.querySelector("a-camera")
      // create a direction vector
      var direction = new THREE.Vector3();

      window.addEventListener("keydown", (e) => {
        if (e.code === "KeyR") {
          // get the cameras world direction
          this.el.sceneEl.camera.getWorldDirection(direction);
          // multiply the direction by a "speed" factor
          direction.multiplyScalar(0.1)
          // get the current position
          var pos = player.getAttribute("position")
          // add the direction vector
          pos.add(direction)
          // set the new position
          player.setAttribute("position", pos);
          // !!! NOTE - it would be more efficient to do the
          // position change on the players THREE.Object:
          // `player.object3D.position.add(direction)`
          // but it would break "getAttribute("position")
        }
      })
    }
  })
</script>
<a-scene>
  <a-box position="-1 0.5 -3" rotation="0 45 0" foo color="#4CC3D9"></a-box>
  <a-sphere position="0 1.25 -5" radius="1.25" color="#EF2D5E"></a-sphere>
  <a-cylinder position="1 0.75 -3" radius="0.5" height="1.5" color="#FFC65D"></a-cylinder>
  <a-plane position="0 0 -4" rotation="-90 0 0" width="4" height="4" color="#7BC8A4"></a-plane>
  <a-sky color="#ECECEC"></a-sky>
  <a-camera></a-camera>
</a-scene>
Run Code Online (Sandbox Code Playgroud)

但是,您可能希望以更“数学化”的方式执行此操作:

1) 2D - 极坐标

将角度映射到 2D 空间是极坐标系的工作

我们想根据相机旋转计算 x/y 坐标。坐标转换如下所示:

x = r * cos(a)
y = r * sin(a)

其中“r”是步长,“a”是角度。


理论很无聊,所以让我们开始实践:
var angle = player.getAttribute("rotation") // grab angle
var x = 1 * Math.cos(angle.y * Math.PI / 180) // calculate shifts
var y = 1 * Math.sin(angle.y * Math.PI / 180)
var pos = player.getAttribute("position") // grab position
pos.x -= y; // update position
pos.z -= x;
player.setAttribute("position", pos);
Run Code Online (Sandbox Code Playgroud)

这很简单 - 获取角度,计算偏移,并设置新位置。

我们可以修改前面的例子:

var angle = player.getAttribute("rotation") // grab angle
var x = 1 * Math.cos(angle.y * Math.PI / 180) // calculate shifts
var y = 1 * Math.sin(angle.y * Math.PI / 180)
var pos = player.getAttribute("position") // grab position
pos.x -= y; // update position
pos.z -= x;
player.setAttribute("position", pos);
Run Code Online (Sandbox Code Playgroud)

2) 3D - 球面坐标

毕竟,这是我们正在谈论的 3D 空间。
概念是相同的 - 将摄像机角度转换为 x/y/z 坐标。这里的绝妙技巧是从球坐标系进行转换。三个维度使它有点困难,但最令人困惑的是 -球坐标系中的轴与剪辑空间中的轴不同(由 a-frame 使用):

在此处输入图片说明

记住这一点,计算应该在这个片段中看起来像:

<script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script>
<script>
  AFRAME.registerComponent("foo", {
    init: function() {
      var player = document.querySelector("a-camera")
      window.addEventListener("keydown", (e) => {
        if (e.code === "KeyR") {
          var angle = player.getAttribute("rotation")
          var x = 0.1 * Math.cos(angle.y * Math.PI / 180)
          var y = 0.1 * Math.sin(angle.y * Math.PI / 180)
          var pos = player.getAttribute("position")
          pos.x -= y;
          pos.z -= x;
          player.setAttribute("position", pos);
        }
      })
    }
  })
</script>
<a-scene>
  <a-box position="-1 0.5 -3" rotation="0 45 0" foo color="#4CC3D9"></a-box>
  <a-sphere position="0 1.25 -5" radius="1.25" color="#EF2D5E"></a-sphere>
  <a-cylinder position="1 0.75 -3" radius="0.5" height="1.5" color="#FFC65D"></a-cylinder>
  <a-plane position="0 0 -4" rotation="-90 0 0" width="4" height="4" color="#7BC8A4"></a-plane>
  <a-sky color="#ECECEC"></a-sky>
  <a-camera></a-camera>
</a-scene>
Run Code Online (Sandbox Code Playgroud)