2

很抱歉,如果之前有人问过这个问题,我确实搜索过,但没有找到答案。

我的问题是,我想在相机的 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 轴是扫射)。

我确实意识到这种方式的移动速度不是恒定的。如果您对此有解决方案,我也很乐意接受。

4

1 回答 1

5

我认为你的错误在于你没有将你的距离(你的移动量hypothenuse)完全投射到你的水平平面和垂直平面上。

换句话说,无论选择什么方向,您现在所做的都是hypothenuse在水平平面 XZ 中移动您的点,即使您已经hypothenuse在垂直方向 Y 上移动了它的一部分。

您可能想要做的是将您的hypothenuse数量点作为总数移动。

所以你必须评估有多少运动发生在水平面上,有多少发生在垂直轴上。你的方向会给你答案。

现在,我现在还不清楚你的 2 个角度代表什么。我强烈建议您在这种情况下使用Tait-Bryan 角度(仅使用yawnpitch,因为您似乎不需要滚动- 您称之为 Z 旋转),以简化计算。

在这种配置中,打哈欠角显然与您对 的定义相似angleY,而俯仰角将是水平面和hypothenuse向量之间的角度(而不是在平面 YZ 中的投影角度)。

澄清的模式:

给定两个角度的位移评估

和 :

  • s您从初始位置P_0P_1( hypothenuse)的移动量
  • a_y打哈欠角和a_p俯仰角一
  • D_x, D_y,D_z每个轴的位移(要添加到position, 即AdjXZ,OppYZOppXZ

因此,如果您查看此表示,您会发现 XZ 中的三角形没有sas 斜边,而是它的投影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_yie OppYZ,再次将自己置于三角形P_0 P_1 P_1xz中,您将获得:

float OppYZ = (float) (speed * Math.sin(Math.toRadians(angleP))); // D_y

现在,如果angleX你真的像我想的那样指的是仰角angleP = angleX,那么HypXZ = AdjYZ在你的代码中。

有了这个更正,如果angleX = 90angleX = -90,则

HypXZ = speed * cos(angleX) = speed * cos(90deg) = speed * 0;

... 因此AdjXZ = 0OppXZ = 0. 在水平面上没有移动。


笔记:

要检查您的计算是否正确,您可以验证您是否实际移动了所需移动量的点(hypothenusespeedie 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

希望它有所帮助......再见!

于 2013-05-28T13:13:48.113 回答