A 帧在相机方向向前移动 [英] A-frame move forward in camera direction

查看:17
本文介绍了A 帧在相机方向向前移动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

<script src="https://aframe.io/releases/1.2.0/aframe.min.js"><<;/脚本><脚本>//与 2D 相同的组件 - 只是不同的计算AFRAME.registerComponent("foo", {初始化:函数(){var player = document.querySelector("a-camera")window.addEventListener("keydown", (e) => {if (e.code === "KeyR") {//获取玩家旋转var angle = player.getAttribute("旋转")//计算角度//相机的 theta == 0 实际上是剪辑空间中的 90'让 theta = (angle.x * Math.PI/180) + Math.PI/2让 fi = 角度.y * Math.PI/180让 r = 0.1//计算位置偏移让 z = Math.sin(theta) * Math.cos(fi) * r让 x = Math.sin(theta) * Math.sin(fi) * r让 y = Math.cos(theta) * r//更新位置var pos = player.getAttribute("位置")pos.x -= x;pos.y -= y;pos.z -= z;player.setAttribute("位置", pos);}})}})<场景><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-圆筒位置="1 0.75 -3" radius="0.5" height="1.5" color="#FFC65D"></a-圆筒><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-相机></a-相机></a-scene>

I'm trying to make a component in A-frame that will move the player/camera in the direction the camera is facing. It should not move anywhere on the y plane, only in the x/y plane. The current setup in the dom is:

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

I want to move the entity element position to x units in the current camera direction but it should not move anything on the y-plane. I have tried various solutions but they seem to introduce some weird shift in the camera.

解决方案

You could handle this in multiple ways.

0) Vectors

Simple and available in most 3D engines:

  • Grab the camera's forward vector / world direction
  • multiply it by the distance you want to move
  • add it to your position vector

The above steps within an a-frame component could look like this:

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

However you may want to do this a bit more "math-ish" way:

1) 2D - Polar Coordinates

Mapping angles to 2D space is a job for the polar coordinate system !

We want to calculate x/y coordinates based on the camera rotation. The coordinate conversion looks like this:

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

where "r" is the step, the "a" is the angle.


Theory is boring, so lets get to practice:

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

It's quite simple - get the angle, calculate the shift, and set the new position.

We can modify the earlier example:

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

After all, this is a 3D space we're talking about.
The concept is the same - converting the camera angles into the x/y/z coordinates. The nifty trick here are the conversions from the spherical coordinate system.Three dimensions make it a bit more difficult, but the most confusing thing - the axis are different in the spherical system, than in the clipspace(used by a-frame):

Keeping that in mind the calculations should look like in this snippet:

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

这篇关于A 帧在相机方向向前移动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆