A 帧沿相机方向向前移动
Posted
技术标签:
【中文标题】A 帧沿相机方向向前移动【英文标题】:A-frame move forward in camera direction 【发布时间】:2018-07-21 09:58:20 【问题描述】:我正在尝试在 A 帧中制作一个组件,该组件将使播放器/相机沿相机朝向的方向移动。它不应在 y 平面上的任何位置移动,只能在 x/y 平面上移动。 dom 中的当前设置是:
<a-entity>
<a-camera></a-camera>
</a-entity>
我想将实体元素位置移动到当前相机方向上的 x 个单位,但它不应该在 y 平面上移动任何东西。我尝试了各种解决方案,但它们似乎在相机中引入了一些奇怪的变化。
【问题讨论】:
作为一个刚接触 VR 的人——WASD 控件已经在框架中执行此操作,我想重点是您希望独立于用户交互来执行此操作...? @KyleBaker WASD 控件不会将您移向相机方向 - 如果仅启用“w”,它们可以:) 【参考方案1】:您可以通过多种方式处理此问题。
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" color="#FFC65D"></a-cylinder>
<a-plane position="0 0 -4" rotation="-90 0 0" color="#7BC8A4"></a-plane>
<a-sky color="#ECECEC"></a-sky>
<a-camera></a-camera>
</a-scene>
但是,您可能希望以更“数学式”的方式执行此操作:
1) 2D - 极坐标
将角度映射到 2D 空间是 polar coordinate system 的工作!
我们想根据相机旋转计算 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);
这很简单 - 获取角度,计算偏移,然后设置新位置。
我们可以修改前面的例子:
<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" color="#FFC65D"></a-cylinder>
<a-plane position="0 0 -4" rotation="-90 0 0" color="#7BC8A4"></a-plane>
<a-sky color="#ECECEC"></a-sky>
<a-camera></a-camera>
</a-scene>
2) 3D - 球坐标
毕竟,这是我们所说的 3D 空间。 概念是相同的 - 将摄像机角度转换为 x/y/z 坐标。这里的绝妙技巧是从spherical coordinate system 转换。三个维度使它有点困难,但最令人困惑的是——球面系统中的轴与clipspace 中的轴不同(由a-frame 使用) :
请记住,计算应类似于此 sn-p:
<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" color="#FFC65D"></a-cylinder>
<a-plane position="0 0 -4" rotation="-90 0 0" color="#7BC8A4"></a-plane>
<a-sky color="#ECECEC"></a-sky>
<a-camera></a-camera>
</a-scene>
【讨论】:
@Kristofer 很高兴我能帮上忙,我在制造车辆时经常使用这些——比如机械师。 那你如何在 Y 轴上移动? (我知道 OP 没有要求它,但它可能会帮助很多人) @nook 让我知道它是否可以理解 哇,谢谢。我认为这是现在互联网上非常有价值的资源。 @nook 开始想多了,添加了一个更简单的选项以上是关于A 帧沿相机方向向前移动的主要内容,如果未能解决你的问题,请参考以下文章