C++ 围绕另一个点旋转一个三维点

C++ 围绕另一个点旋转一个三维点,c++,math,opengl,trigonometry,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

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

尝试使用向量数学。决定旋转的顺序,先沿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旋转下一个参考轴的结果是,两个在赤道处相距1km的点在极点处相互靠近,在90度纬度处相互接触。即使明显的目的是让它们在旋转的地方保持1公里的距离。

尝试使用矢量数学。决定旋转的顺序,先沿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旋转下一个参考轴的结果是,两个在赤道处相距1km的点在极点处相互靠近,在90度纬度处相互接触。即使明显的目的是使它们在旋转的地方保持1公里的距离。

如果要变换坐标系而不仅仅是点,则需要3个角度。但你是对的-对于变换点,两个角度就足够了。有关详细信息,请询问


但是当你使用opengl时,你真的应该使用像glRotatef这样的opengl函数。这些函数将在GPU上计算,而不是在CPU上计算。如果要变换坐标系而不是仅变换点,则需要3个角度,文档为。

。但你是对的-对于变换点,两个角度就足够了。有关详细信息,请询问


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

代码的基本功能:

计算差分向量 将向量转换为 将w_nx和wn_y添加到倾角和方位角中。有关术语,请参见链接 将修改后的球坐标转换回笛卡尔坐标 有两个问题:

转换不正确,您所做的计算是针对两个倾斜向量,一个沿x轴,另一个沿y轴 即使计算是正确的,球坐标中的变换也不同于绕两个轴旋转 因此,在这种情况下,使用矩阵和向量数学将有助于:

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

.

该代码的基本功能:

计算差分向量 将向量转换为 将w_nx和wn_y添加到倾角和方位角中。有关术语,请参见链接 将修改后的球坐标转换回笛卡尔坐标 有两个问题:

转换不正确,您所做的计算是针对两个倾斜向量,一个沿x轴,另一个沿y轴 即使计算是正确的,球坐标中的变换也不同于旋转 绕两个轴 因此,在这种情况下,使用矩阵和向量数学将有助于:

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

.

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

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

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

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

为什么要使用3个角度?2够了,我从哪里得到y?@Andifust有z'=z,y=y',x'=x缺失。这三个计算是旋转矩阵的矩阵乘法。如果你沿着y轴旋转,y不会改变,等等。这一切看起来都很好,但我已经做到了——有人能告诉我代码中的错误在哪里吗?求你了@我不确定,但我认为这个解决方案是错误的。您必须更正以下行:z=z'*sinb+x'*cosb;->z=x'*sinb+z'*cosb;z'=z*sinc+y*cosc->z'=y*sinc+z*cosc。这有意义吗?为什么使用3个角度?2够了,我从哪里得到y?@Andifust有z'=z,y=y',x'=x缺失。这三个计算是旋转矩阵的矩阵乘法。如果你沿着y轴旋转,y不会改变,等等。这一切看起来都很好,但我已经做到了——有人能告诉我代码中的错误在哪里吗?求你了@我不确定,但我认为这个解决方案是错误的。您必须更正以下行:z=z'*sinb+x'*cosb;->z=x'*sinb+z'*cosb;z'=z*sinc+y*cosc->z'=y*sinc+z*cosc。这有意义吗?如果你使用图形库,我肯定你可以使用矩阵和向量。通过矩阵旋转一个点将简化您的算法。@ahenderson您的意思是实现吗;如果您还不熟悉这个术语,您应该仔细阅读万向节锁。我无法立即判断您的代码是否会受到影响,但当您使用Euler角度进行此类旋转时,这是一个常见的缺陷。我尝试使用glrotatef,但它只会旋转图形,而不是顶点的坐标,我需要旋转坐标以检查碰撞!如果你使用我相信一个图形库会有一个矩阵和向量,你可以使用。通过矩阵旋转一个点将简化您的算法。@ahenderson您的意思是实现吗;如果您还不熟悉这个术语,您应该仔细阅读万向节锁。我无法立即判断您的代码是否会受到影响,但当您使用Euler角度进行此类旋转时,这是一个常见的缺陷。我尝试使用glrotatef,但它只会旋转图形,而不是顶点的坐标,我需要旋转坐标以检查碰撞!我尝试使用glrotatef,但它只会旋转图形,而不是坐标,我需要旋转坐标以检查冲突。哦,你想做手动共谋检查。。。当我学习的时候,我已经实现了一个,这是一个痛苦和缓慢的过程。也许你应该考虑使用一个我试图使用GLATATEF,但它只转动图纸,而不是坐标,我需要旋转坐标,以便检查碰撞,你想做手工勾结检查…当我学习的时候,我已经实现了一个,这是一个痛苦和缓慢的过程。也许你应该考虑使用