我正在研究一个简单的OpenGL世界 - 到目前为止,我已经随机放置了一堆立方体,并且放大缩放非常有趣。但是我准备继续前进了。我想在我的相机前放下块,但是我在使用三维角度时遇到了麻烦。我已经习惯了2d的东西,在哪里找到一个终点,我们只是按照以下方式做点什么:
endy = y + (sin(theta)*power);
endx = x + (cos(theta)*power);
然而,当我添加第三维时,我不知道该怎么做!在我看来,第二维平面的功率将由z轴的cos(θ)*功率决定,但我不是正面的。如果这是正确的,在我看来我会做这样的事情:
endz = z + (sin(xtheta)*power);
power2 = cos(xtheta) * power;
endx = x + (cos(ytheta) * power2);
endy = y + (sin(ytheta) * power2);
(其中x theta是上/下θ,y =左/右theta)
我是否接近正确的轨道?如何在给定当前点和两个角度的情况下找到终点?
答案 0 :(得分:2)
使用欧拉角在3D环境中效果不佳,有几个问题和极端情况它们根本不起作用。而你实际上甚至不必使用它们。
你应该做的是利用这样一个事实,即转换矩阵不是别的,然后协调以易于理解的形式写下来的系统基础。所以你有你的modelview矩阵MV。这包括模型空间转换,然后是视图转换(列主要矩阵从右到左乘法):
MV = V * M
所以我们想知道的是,“相机”在世界范围内。这是通过逆视图矩阵V^-1
给出的。您当然可以使用Gauss Jordan方法反转视图矩阵,但大多数情况下,您的视图矩阵将由3×3旋转矩阵和添加的平移矢量列P组成。
R P
0 1
回想一下
(M * N)^-1 = N^-1 * M^-1
以及
(M * N)^T = M^T * N^T
所以看来转置和反转之间存在某种关系。并非所有的转置矩阵都是它们的逆矩阵,但有一些矩阵的转置是逆的。即它是所谓的标准正交矩阵。旋转是正交的。所以
R^-1 = R^T
整齐!这允许我们通过以下方式找到视图矩阵的逆矩阵(我建议你尝试将其证明为exersice):
V = / R P \
\ 0 1 /
V^-1 = / R^T -P \
\ 0 1 /
那么这有助于我们将新物体放置在离相机一定距离的场景中?嗯,V是从世界空间到相机空间的转换,所以V ^ -1从相机转换到世界空间。因此,考虑到相机空间中的一个点,您可以将其转换回世界空间。假设您想要在距离d
的视图中心放置一些东西。在相机空间中,这将是点(0, 0, -d, 1)
。乘以V ^ -1:
V^-1 * (0, 0, -d, 1) = (R^T)_z * d - P
这正是你想要的。在你的OpenGL程序中,你的某个地方有你的视图矩阵V,可能还没有正确命名,但无论如何它都存在。假设你使用旧的OpenGL-1和GLU的gluLookAt:
void display(void)
{
/* setup viewport, clear, set projection, etc. */
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(...);
/* the modelview matrix now holds the View transform */
此时我们可以提取模型视图矩阵
GLfloat view[16];
glGetFloatv(GL_MODELVIEW_MATRIX, view);
现在view
按列主要顺序排列。如果我们直接使用它,我们可以直接解决这些列。但请记住转置是旋转的反转,所以我们实际上想要第3行向量。因此,我们假设您保持view
,以便在事件处理程序(外部显示)中执行以下操作:
GLfloat z_row[3];
z_row[0] = view[2];
z_row[1] = view[6];
z_row[2] = view[10];
我们想要这个职位
GLfloat * const p_column = &view[12];
现在我们可以计算距离d
的新对象位置:
GLfloat new_object_pos[3] = {
z_row[0]*d - p_column[0],
z_row[1]*d - p_column[1],
z_row[2]*d - p_column[2],
};
你有。正如您所看到的,无论您何时使用角度或三角函数,它都只是直线代数。
答案 1 :(得分:0)
嗯,我接近了,经过一些测试,我发现了我的实现的正确公式,它看起来像这样:
endy = cam.get_pos().y - (sin(toRad(180-cam.get_rot().x))*power1);
power2 = cos(toRad(180-cam.get_rot().x))*power1;
endx = cam.get_pos().x - (sin(toRad(180-cam.get_rot().y))*power2);
endz = cam.get_pos().z - (cos(toRad(180-cam.get_rot().y))*power2);
这需要我的相机的位置和旋转角度,并得到相应的点。像魅力一样工作=]