繁体   English   中英

3D“免费”相机的三角学

[英]Trigonometry of a 3D “free” camera

很抱歉,如果以前曾问过这个问题,我确实进行了搜索,但没有找到答案。

我的问题是,我想在相机的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您的水平面和竖直一个)。

换句话说,无论所选择的方向,你现在在做什么权利移动你的点hypothenuse在水平面XZ,即使你已经将它的一部分的hypothenuse在垂直方向Y.

您可能想做的是将hypothenuse数量的总和转移。

因此,您必须评估在水平面上发生了多少移动,在垂直轴上发生了多少移动。 你的方向给你答案。

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

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

需要澄清的架构:

Evaluation of the displacement given two angles

与:

  • s你从初始位置的移动量P_0P_1hypothenuse
  • a_y的打哈欠角和a_p的音高一
  • D_xD_yD_z每个轴的位移(将添加到position ,即AdjXZOppYZOppXZ

因此,如果查看此表示形式,可以看到XZ中的三角形没有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_yOppYZ ,再次将自己置于三角形P_0 P_1 P_1xz ,您将获得:

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

现在,如果用angleX实际表示的是我angleX仰角 ,则在代码中angleP = angleXHypXZ = AdjYZ

进行此校正后,如果angleX = 90angleX = -90 ,则

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

...因此AdjXZ = 0OppXZ = 0 在水平面内无运动。


注意:

要检查,如果你的计算是正确的,你可以验证,如果你真的将你的运动所需量(点hypothenusespeeds )。 使用勾股定理:

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

希望对您有所帮助...再见!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM