javascript - A 帧沿相机方向向前移动

标签 javascript three.js aframe

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

<a-entity>
    <a-camera></a-camera>
</a-entity>

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

最佳答案

您可以通过多种方式处理此问题。
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>

    但是,您可能希望以更“数学”的方式执行此操作:
    1) 2D - 极坐标
    将 Angular 映射到 2D 空间是 polar coordinate system 的工作。 !
    我们想根据相机旋转计算 x/y 坐标。坐标转换如下所示:
    x = r * cos(a)
    y = r * sin(a)
    其中“r”是步长,“a”是 Angular 。

    理论很无聊,让我们开始实践吧:
    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);
    
    这很简单——获取 Angular ,计算位移,然后设置新位置。
    我们可以修改前面的例子:

    <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>

    2) 3D - 球坐标
    毕竟,这是我们正在谈论的 3D 空间。
    概念是相同的 - 将摄像机 Angular 转换为 x/y/z 坐标。这里的绝妙技巧是来自 spherical coordinate system 的转换。 .三维使它有点困难,但最令人困惑的是-球面系统中的轴与clipspace中的轴不同。 (由 a-frame 使用):
    enter image description here
    请记住,计算应如下所示:

    <script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script>
    <script>
      // same component as 2D - just different calculations
      AFRAME.registerComponent("foo", {
        init: function() {
          var player = document.querySelector("a-camera")
          window.addEventListener("keydown", (e) => {
            if (e.code === "KeyR") {
              // get the player rotation
              var angle = player.getAttribute("rotation")
              // calculate the angles
              // the camera's theta == 0 is actually 90' in the clipspace
              let theta = (angle.x * Math.PI / 180) + Math.PI / 2 
              let fi = angle.y * Math.PI / 180
              let r = 0.1
              // calculate the position shifts
              let z = Math.sin(theta) * Math.cos(fi) * r
              let x = Math.sin(theta) * Math.sin(fi) * r
              let y = Math.cos(theta) * r
    
              // update the position
              var pos = player.getAttribute("position")
              pos.x -= x;
              pos.y -= y;
              pos.z -= z;
              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>

    关于javascript - A 帧沿相机方向向前移动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48726018/

    相关文章:

    javascript - Three.js:逐步增加纹理分辨率的策略

    javascript - 从新对象中运行 requestAnimationFrame

    Aframe 直接实时更新 aframe-article-system-component 的属性,无需 setAttribute()

    aframe - 如何在 A-Frame 中监听相机的世界位置?

    javascript - tinyMCE - 获取光标位置的内容

    javascript - 如何包裹兄弟元素?

    javascript - 使用 GSAP 将副本 SVG 元素插入到 DOM 中

    javascript - 未捕获的类型错误 : object is not a function onclick

    javascript - THREE.js 旋转加载文件

    aframe - 如何加载obj的纹理?