很抱歉,如果之前曾问过这个问题,我确实进行了搜索,但没有找到答案。
我的问题是,我想在相机的X和Y旋转相关的情况下在所有3个轴上移动。
这是我所做的:
private static void fly(int addX, int addY){ //parameters are the direction change relative to the current rotation
float angleX = rotation.x + addX; //angle is basically the direction, into which we will be moving(when moving forward this is always the same as our actual rotation, therefore addX and addY would be 0, 0)
float angleY = rotation.y + addY;
float speed = (moveSpeed * 0.0002f) * delta;
float hypotenuse = speed; //the length that is SUPPOSED TO BE moved overall on all 3 axes
/* Y-Z side*/
//Hypotenuse, Adjacent and Opposite side lengths of a triangle on the Y-Z side
//The point where the Hypotenuse and the Adjacent meet is where the player currently is.
//OppYZ is the opposite of this triangle, which is the ammount that should be moved on the Y axis.
//the Adjacent is not used, don't get confused by it. I just put it there, so it looks nicer.
float HypYZ = speed;
float AdjYZ = (float) (HypYZ * Math.cos(Math.toRadians(angleX))); //adjacent is on the Z axis
float OppYZ = (float) (HypYZ * Math.sin(Math.toRadians(angleX))); //opposite is on the Y axis
/* X-Z side*/
//Side lengths of a triangle on the Y-Z side
//The point where the Hypotenuse and the Adjacent meet is where the player currently is.
float HypXZ = speed;
float AdjXZ = (float) (HypXZ * Math.cos(Math.toRadians(angleY))); //on X
float OppXZ = (float) (HypXZ * Math.sin(Math.toRadians(angleY))); //on Z
position.x += AdjXZ;
position.y += OppYZ;
position.z += OppXZ;
}
我仅在向前移动(参数:0、90)或向后移动(参数:180、270)时实现此方法,因为在侧向移动时无法在Y轴上发生移动,因为您不会在Z轴上旋转。 (侧身走的方法工作得很好,所以我不会添加它。)
问题是当我向上看90度或向下看-90度然后向前移动时,我应该只在Y轴上(垂直)移动,但由于某种原因,我也向前移动(这意味着在Z轴上,作为X轴)是扫射)。
我确实意识到这种方式的移动速度不是恒定的。如果您有解决方案,我也很乐意接受。
最佳答案
我认为您的错误在于以下事实:您没有在水平面上和垂直面上完全投影出距离(运动量hypothenuse
)。
换句话说,无论您选择了什么方向,即使您已经在垂直方向Y上移动了hypothenuse
的一部分,您现在正在做的事情都是在水平面X-Z中移动hypothenuse
的点。
您可能想要做的是将总计为hypothenuse
的点移动。
因此,您必须评估在水平面上发生了多少移动,在垂直轴上发生了多少移动。你的方向给你答案。
现在,我现在还不清楚您的两个角度代表什么。我强烈建议您在这种情况下使用Tait–Bryan angles(仅使用打哈欠和俯仰,因为您似乎不需要滚动-称为Z旋转),以简化计算。
在此配置中,打哈欠角显然类似于您对angleY
的定义,而俯仰角将是水平面与hypothenuse
向量之间的角度(而不是平面YZ中的投影角度) )。
需要澄清的架构:
与:s
从初始位置P_0
到P_1
(hypothenuse
)的移动量a_y
打哈欠角和a_p
俯仰角一D_x
,D_y
,D_z
每个轴的位移(要添加到position
中,即AdjXZ
,OppYZ
和OppXZ
)
因此,如果查看此表示形式,可以看到X-Z中的三角形没有s
作为斜边,而是其投影s_xz
。此距离的评估非常简单:如果将自己置于三角形P_0
P_1
P_1xz
中,则可以看到s_xz = s * cos(a_p)
。这给你:
float HypXZ = speed * Math.cos(Math.toRadians(angleP))); // s_xz
float AdjXZ = (float) (HypXZ * Math.cos(Math.toRadians(angleY))); // D_x
float OppXZ = (float) (HypXZ * Math.sin(Math.toRadians(angleY))); // D_z
至于
D_y
即OppYZ
,再次将自己置于三角形P_0
P_1
P_1xz
中,您将获得:float OppYZ = (float) (speed * Math.sin(Math.toRadians(angleP))); // D_y
现在,如果用
angleX
实际表示的是我想像的仰角,则代码中的angleP = angleX
和HypXZ = AdjYZ
。进行此更正后,如果
angleX = 90
或angleX = -90
,则HypXZ = speed * cos(angleX) = speed * cos(90deg) = speed * 0;
...因此是
AdjXZ = 0
和OppXZ = 0
。在水平面内无运动。注意:
要检查您的计算是否正确,您可以验证是否实际移动了所需移动量的点(
hypothenuse
即speed
即s
)。使用勾股定理:s² = s_xz² + D_z² // Applied in the triangle P_0 P_1 P_1xz
= D_x² + D_y² + D_z² // Applied in the triangle P_0 P_1x P_1xz
有了上面给出的位移的定义:
D_x² + D_y² + D_z²
= (s * cos(a_p) * cos(a_y))² + (s * cos(a_p) * sin(a_y))² + (s * sin(a_p))²
= s² * (cos(a_p)² * cos(a_y)² + cos(a_p)² * sin(a_y)² + sin(a_p)²)
= s² * (cos(a_p)² * (cos(a_y)² + sin(a_y)²) + sin(a_p)²)
= s² * (cos(a_p)² * 1 + sin(a_p)²)
= s² * (cos(a_p)² + sin(a_p)²)
= s² * 1 // Correct
希望对您有所帮助...再见!