2012-11-07 91 views
0

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

任何人都可以帮助我吗?

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; 
    } 
+1

如果你使用[tag:opengl]我确定一个图形库将有一个矩阵和载体植入,你可以使用。通过矩阵旋转点将简化您的算法。 – andre

+2

@ahenderson你的意思是“执行”? ;) – leemes

+0

如果你还不熟悉这个术语,你应该阅读“Gimbal Lock”。我不能立即告诉你的代码是否会受到它的影响,但当你使用“欧拉角”进行这种旋转时,这是一个常见的缺陷。 – Rook

回答

2

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

+1

你为什么要用3个角度? 2足够了,我从哪里得到'''? –

+1

@AndiFaust有'z'= z','y''= y'','x'''= x'''丢失。这三个计算是与“旋转矩阵”的矩阵乘法。 – leemes

+0

如果你沿Y轴旋转,Y不会改变等 –

0

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

但是,当你使用opengl你真的应该使用opengl函数,如glRotatef。这些函数将在GPU上进行计算 - 而不是CPU上的函数。该文档是here

+0

我试图使用'glrotatef',但它只是转动绘图,而不是坐标,我需要旋转坐标以检查碰撞 –

+0

哦,你想要做手动合谋检查......我已经当我学习时实施了一个,这是一个痛苦和缓慢。也许你应该考虑使用[物理引擎](http://en.wikipedia.org/wiki/Physics_engine) – Andreas

4

什么代码几乎确实:

  • 计算差矢量
  • 转换载体导入spherical coordinates
  • 附加w_nx和wn_y到的倾斜和方位角(参见链接术语)
  • 转换改性球坐标返回到笛卡尔坐标

有两个p roblems:

  • 转换是不正确的,你做的计算是两个倾角矢量(一个沿x轴,其他沿y轴)
  • 即便计算是正确的,在球面坐标变换是不一样的使用矩阵和矢量数学将有助于在此情况下围绕两个轴旋转

因此:

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

basic rotation matrices

0

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

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