1

我的程序中有一个函数,它将一个点(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

4 回答 4

5

代码几乎做了什么:

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

有两个问题:

  • 转换不正确,您所做的计算是针对两个倾角向量(一个沿 x 轴,另一个沿 y 轴)
  • 即使计算正确,球坐标中的变换也不同于绕两个轴旋转

因此,在这种情况下,使用矩阵和向量数学将有助于:

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

基本旋转矩阵

于 2012-11-07T20:54:21.087 回答
4

尝试使用向量数学。决定你旋转的顺序,首先沿着 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 公里的距离。

于 2012-11-07T18:27:16.993 回答
0

如果要转换坐标系而不仅仅是点,则需要 3 个角度。但你是对的 - 对于转换点 2 个角度就足够了。有关详细信息,请咨询维基百科...

但是当你使用 opengl 时,你真的应该使用 opengl 函数,比如glRotatef. 这些函数将在 GPU 上计算 - 而不是作为您的函数在 CPU 上计算。文档在这里

于 2012-11-07T19:00:38.307 回答
0

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

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

于 2012-11-07T22:05:48.810 回答