如何将本地对象坐标转换为世界坐标?

时间:2011-05-06 16:37:30

标签: c++ opengl

我需要一种简单的方法将我的对象坐标转换为世界坐标,以便a可以在那个坐标系中找到它们并进行碰撞检测吗?

2 个答案:

答案 0 :(得分:24)

首先,一些背景知识。在3D图形中,您需要担心几个向量空间:

  • 模型空间 - 这些通常是您为OpenGL指定的坐标
  • 世界空间 - 相对于世界上的某个中心点指定坐标。
  • 查看空间 - 相对于相机指定坐标
  • 投影空间 - 屏幕上的所有内容均适合每个维度的[-1, +1]区间。

坐标是均匀指定的,因此每个向量都有组件(x, y, z, w),其中w是缩放系数。您可以获得3空格中的坐标(x/w, y/w, z/w)。某些变换需要缩放因子,例如透视投影,这是非均匀坐标无法实现的。

将坐标从一个向量空间转换为另一个向量空间需要4x4矩阵。你可以有三种不同的矩阵:

  • 模型矩阵(模型到世界)
  • 查看矩阵(世界观看)
  • 投影矩阵(投影空间视图)

您可以使用以下公式将坐标C投影到屏幕上:

C' = P * V * M * C

OpenGL内部维护两个矩阵:modelview(模型和视图相乘)和投影。还有一个我们不会担心的纹理矩阵。当您致电glMatrixMode时,您正在这些矩阵之间切换。使用glLoadIdentity将当前矩阵替换为单位矩阵。您可以使用glTranslatefglRotatefgluProjection等函数将变换应用于当前矩阵。这些函数中的每一个只创建一个4x4矩阵,即特定变换的实现,然后将当前矩阵乘以它。您可以在OpenGL 2.1 reference pages中查看转换矩阵的内容。


现在回答实际问题。您需要为场景中的每个对象维护一个4x4模型矩阵。模型矩阵将包含将模型坐标更改为世界坐标所需的所有变换。例如,每次调用glTranslate时,都会更新模型矩阵:

T  = [ 1 0 0 x ]
     [ 0 1 0 y ]
     [ 0 0 1 z ]
     [ 0 0 0 1 ]
M' = M * T

然后,您可以使用模型矩阵将坐标转换为世界空间(确保它们首先是同质坐标;如果不是,则设置w = 1):

V' = V * M

由于您并行维护这些转换,因此您实际上不再需要维护OpenGL模型视图矩阵。您可以将模型矩阵作为制服传递到着色器。您可以用类似的方式维护自己的视图和投影矩阵。这在最近的OpenGL版本中是必需的;所有矩阵处理函数都已弃用。

答案 1 :(得分:4)

您可以使用虚拟摄像机视图矩阵的逆的乘积( V -1 )乘以对象的ModelView矩阵(V * M)世界坐标。

使用:

在gluLookAt()函数之后得到V.

glGetFloatv(GL_MODELVIEW_MATRIX,camViewMatrix)

然后反转矩阵并存储它(用于稍后在代码中相乘。)

在使用相同GL函数的所有glTranslatef(),glRotatef()和glScale()命令之后,您将在要绘制对象的位置获得V * M:

glGetFloatv(GL_MODELVIEW_MATRIX,objectsModelViewMatrix);

V -1 *( V * M )== M

然后多个两个矩阵,得到的矩阵包含位置,m12 = x,m13 = y和m14 = z

C代码的更多细节: https://sourceforge.net/p/openantz/wiki/Local_to_World_Coordinates/