相机旋转时 2d 屏幕速度到 3d 世界速度
2d screen velocity to 3d world velocity while camera is rotated
我正在创建一个小型演示游戏,您可以在其中绕地球旋转并将卫星发射到 space。但是我的计算有点问题。
您可以将鼠标从平台拖动到一个方向。这是您将卫星射向的方向。因为相机围绕地球旋转,向上与向前不同。对于卫星的方向,我需要一个Vector3(direction/velocity).
所以我的数据是屏幕上平台的前向和鼠标拖动方向。
因此,当用户将其拖动到 (-0.7, 0.7) 时,这意味着饱和发射方向应为 (0, 0, 1)。 global/World 前进方向。
那么如何将那些 2d 屏幕位置和方向转换为世界方向?
PlayCanvas有一个非常有用的功能我们可以利用。 implementation如下:
* @description Convert a point from 2D canvas pixel space to 3D world space.
* @param {Number} x x coordinate on PlayCanvas' canvas element.
* @param {Number} y y coordinate on PlayCanvas' canvas element.
* @param {Number} z The distance from the camera in world space to create the new point.
* @param {Number} cw The width of PlayCanvas' canvas element.
* @param {Number} ch The height of PlayCanvas' canvas element.
* @param {pc.Vec3} [worldCoord] 3D vector to receive world coordinate result.
* @returns {pc.Vec3} The world space coordinate.
*/
screenToWorld: function (x, y, z, cw, ch, worldCoord) {
...
我们可以使用这个函数将鼠标拖动线的起点和终点(图中分别为A
和B
)转换为世界space中的3D线。转换后我们必须从两个投影点中减去相机的世界位置,并对结果向量进行归一化。
[z
参数与此目的无关,因为我们只对 方向 向量感兴趣,而不是实际点,因此只需将其设置为例如1.]
那么这给我们带来了什么?由这两个向量跨越的 平面 :
速度方向必须满足三个条件:
- 垂直于发射场的表面法线(即与表面相切)。
- 平行于我们刚刚找到的平面。
- 在从 A 到 B 的方向上有一个分量。
设:
- 屏幕点
A
和 B
分别投影到方向向量 U
和 V
。
发射场的表面法线(站在那里的人看到的 "up" 方向)是 N
:
其中(ψ, φ) = (lat, long)
.
Finally, the (un-normalized) velocity direction is simply given by cross(N, cross(A, B))
. Note that the order of operations matters.
形象化:
编辑:
第二个图的小错误:U×V
应该是V×U
,但是预期的结果N×(U×V)
还是正确的
注意UxV
不一定垂直于N
。当它 平行 到 N
时,蓝色平面 "scrapes" 表面,即绿线 AB
与渲染的地球表面相切on-screen,发射场。
我正在创建一个小型演示游戏,您可以在其中绕地球旋转并将卫星发射到 space。但是我的计算有点问题。
您可以将鼠标从平台拖动到一个方向。这是您将卫星射向的方向。因为相机围绕地球旋转,向上与向前不同。对于卫星的方向,我需要一个Vector3(direction/velocity).
所以我的数据是屏幕上平台的前向和鼠标拖动方向。
那么如何将那些 2d 屏幕位置和方向转换为世界方向?
PlayCanvas有一个非常有用的功能我们可以利用。 implementation如下:
* @description Convert a point from 2D canvas pixel space to 3D world space.
* @param {Number} x x coordinate on PlayCanvas' canvas element.
* @param {Number} y y coordinate on PlayCanvas' canvas element.
* @param {Number} z The distance from the camera in world space to create the new point.
* @param {Number} cw The width of PlayCanvas' canvas element.
* @param {Number} ch The height of PlayCanvas' canvas element.
* @param {pc.Vec3} [worldCoord] 3D vector to receive world coordinate result.
* @returns {pc.Vec3} The world space coordinate.
*/
screenToWorld: function (x, y, z, cw, ch, worldCoord) {
...
我们可以使用这个函数将鼠标拖动线的起点和终点(图中分别为A
和B
)转换为世界space中的3D线。转换后我们必须从两个投影点中减去相机的世界位置,并对结果向量进行归一化。
[z
参数与此目的无关,因为我们只对 方向 向量感兴趣,而不是实际点,因此只需将其设置为例如1.]
那么这给我们带来了什么?由这两个向量跨越的 平面 :
速度方向必须满足三个条件:
- 垂直于发射场的表面法线(即与表面相切)。
- 平行于我们刚刚找到的平面。
- 在从 A 到 B 的方向上有一个分量。
设:
- 屏幕点
A
和B
分别投影到方向向量U
和V
。 发射场的表面法线(站在那里的人看到的 "up" 方向)是
N
:其中
(ψ, φ) = (lat, long)
.
Finally, the (un-normalized) velocity direction is simply given by
cross(N, cross(A, B))
. Note that the order of operations matters.
形象化:
编辑:
第二个图的小错误:
U×V
应该是V×U
,但是预期的结果N×(U×V)
还是正确的注意
UxV
不一定垂直于N
。当它 平行 到N
时,蓝色平面 "scrapes" 表面,即绿线AB
与渲染的地球表面相切on-screen,发射场。