围绕另一个旋转3D点

时间:2012-11-07 18:19:20

标签: c++ math opengl trigonometry

我的程序中有一个函数,它将一个点(x_p,y_p,z_p)绕另一个点(x_m,y_m,z_m)旋转角度w_nx& w_ny。新坐标存储在全局变量x_n,y_n和z_n中。围绕y轴旋转(因此更改w_nx的值 - 以便y值不受损害)正常工作,但是只要围绕x轴或z轴旋转(更改w_ny的值)坐标不再准确。我评论了我认为我的错误在线,但我无法弄清楚该代码有什么问题。

任何人都可以帮助我吗?

void rotate(float x_m, float y_m, float z_m, float x_p, float y_p, float z_p, float w_nx ,float w_ny)
    {
        float z_b = z_p - z_m;
        float x_b = x_p - x_m;
        float y_b = y_p - y_m;
        float length_ = sqrt((z_b*z_b)+(x_b*x_b)+(y_b*y_b));
        float w_bx = asin(z_b/sqrt((x_b*x_b)+(z_b*z_b))) + w_nx;
        float w_by = asin(x_b/sqrt((x_b*x_b)+(y_b*y_b))) + w_ny; //<- there must be that fault
        x_n = cos(w_bx)*sin(w_by)*length_+x_m;
        z_n = sin(w_bx)*sin(w_by)*length_+z_m;
        y_n = cos(w_by)*length_+y_m;
    }

4 个答案:

答案 0 :(得分:4)

代码几乎可以做什么:

  • 计算差异向量
  • 将矢量转换为spherical coordinates
  • 将w_nx和wn_y添加到倾角和方位角(参见术语链接)
  • 将修改后的球面坐标转换回笛卡尔坐标

有两个问题:

  • 转换不正确,你做的计算是两个倾斜矢量(一个沿x轴,另一个沿y轴)
  • 即使计算正确,球面坐标的变换也不能绕两轴旋转

因此在这种情况下使用矩阵和向量数学会有所帮助:

b = p - m
b = RotationMatrixAroundX(wn_x) * b
b = RotationMatrixAroundY(wn_y) * b
n = m + b

basic rotation matrices

答案 1 :(得分:3)

尝试使用矢量数学。决定你旋转的顺序,首先是x,然后是y。

如果沿z旋转,[z'= z]

x' = x*cos a - y*sin a;
y' = x*sin a + y*cos a;  

对y轴重复:[y''= y']

x'' = x'*cos b - z' * sin b;
z'' = x'*sin b + z' * cos b;  

再次沿x轴旋转:[x'''= x'']

y''' = y'' * cos c - z'' * sin c
z''' = y'' * sin c + z'' * cos c

最后围绕某个特定的“点”旋转的问题:

首先从坐标中减去该点,然后应用旋转,最后将该点添加回结果。

据我所知,这个问题与“万向节锁”密切相关。角度w_ny不能相对于固定的xyz坐标系测量,而是测量通过应用角度w_nx旋转的坐标系。

正如kakTuZ所观察到的,您的代码将点转换为球坐标。这没有什么本质上的错误 - 经度和纬度可以到达地球上的所有地方。如果一个人不关心地球赤道平面相对于它绕太阳的轨迹倾斜,那对我来说没关系。

沿着第一个w_ny不旋转下一个参考轴的结果是两个在赤道处彼此相距1 km的点,在极点处彼此靠近并且在90度的纬度处彼此靠近,它们接触。尽管明显的目的是让它们在旋转的地方保持1公里。

答案 2 :(得分:0)

如果你想变换坐标系而不是只需要3个角的点。但你是对的 - 对于转换点2个角度就足够了。有关详细信息,请Wikipedia ...

但是当你使用opengl时,你真的应该使用像glRotatef这样的opengl函数。这些功能将在GPU上计算 - 而不是作为您的功能在CPU上计算。该文档为here

答案 3 :(得分:0)

像许多人所说的那样,你应该使用glRotatef来旋转它以进行渲染。对于碰撞处理,您可以通过在其渲染点将其位置向量乘以堆栈顶部的OpenGL ModelView矩阵来获取其世界空间位置。使用glGetFloatv获取该矩阵,然后将其与您自己的矢量矩阵乘法函数相乘,或者使用您可以在线轻松获得的众多矩阵之一。

但是,那将是一种痛苦!相反,请考虑使用GL反馈缓冲区。这个缓冲区只是存储绘制图元的点而不是实际绘制图元,然后你可以从那里访问它们。
This是一个很好的起点。