如何在OpenGL中获取对象的坐标

时间:2011-11-24 14:51:38

标签: opengl

我希望能够在翻译和旋转后得到一个物体(例如三角形)的坐标,我想这样做的原因是以后我可以进行碰撞检测并计算物体之间的距离。坐标。我想我可能不得不使用gluProject但不确定。还有不同坐标空间之间的差异,例如:世界,物体等。

我下面有一些代码,它是一个正方形中间的圆圈,我怎么能检测到圆圈接触到其中一个边缘时,我可以使用向上,向下,向左,向右键移动它改变x或y坐标,但我只想做一些基本的碰撞检测,我不知道该怎么做。

glPushMatrix();
    glColor3f(0.0f, 1.0f, 0.0f);
    glTranslatef(0.0f, 0.0f, -5.0f);

    glScalef(0.5f, 0.5f, 0.0f);
    glBegin(GL_POLYGON); 
        glVertex3f(-5.0f, -5.0f, 0.0f);
        glVertex3f(5.0f, -5.0f, 0.0f);
        glVertex3f(5.0f, 5.0f, 0.0f);
        glVertex3f(-5.0f, 5.0f, 0.0f);
    glEnd();
glPopMatrix();

glPushMatrix();


    glColor3f(1.0f, 0.0f, 0.0f);
    glTranslatef(x, y, -20.0f);

    glBegin(GL_POINTS);
        glVertex3f(-5, -5, 10.0f);
    glEnd();

    GLUquadricObj *qobj = gluNewQuadric();
    gluQuadricDrawStyle(qobj, GLU_FILL);
    gluSphere(qobj, 1.0f, 20, 20);
    gluDeleteQuadric(qobj);
glPopMatrix();

3 个答案:

答案 0 :(得分:11)

  

不同坐标空间之间的区别是什么?世界,物体等。

这主要是约定问题,但是:

  • 模型空间(=局部空间)是特定模型相对于其“中心”的坐标空间。如果你有一个带有模型的文件,坐标会围绕它的某个点(例如它的几何中心,它的底部,实际上是任何东西)。

  • 场景空间(=世界空间)是相对于场景任意点的坐标空间

  • 眼睛空间(=查看空间)是相机位于(0,0,0)点的空间,x朝右,y朝上和z面对 out 屏幕(-z =更深)

  • 剪辑空间(-1,-1,*)是视口左下角的位置,(1,1,*)是视口的右上角,Z坐标是(-1,1)仅表示深度(再次更小Z =更深)。 (片段

  • 屏幕空间(=窗口坐标)与上面相同,只是坐标从-1..1重新调整为与当前视口范围匹配的基于像素的值和深度范围。

通过将(在OpenGL约定中通常是左乘)乘以模型矩阵(其中包含模型在场景中的位置的信息),将坐标从模型空间转换为场景空间。如果你有一个场景层次结构,对象可以有许多“堆叠”模型矩阵(剑相对于手臂的放置,相对于骑士的手臂,相对于场景的骑士)。

然后通过乘以视图矩阵(通常连接到“相机”对象)将坐标转换为眼睛空间。

之后,使用投影矩阵将这些坐标转换为屏幕空间,以便OpenGL将这些坐标映射到实际的屏幕像素(取决于视口设置)。

一些事实:

  • 模型和视图矩阵通常包含平移,旋转和/或缩放,而投影矩阵通常包含透视变换,这使得屏幕上的对象看起来更小。

  • 旧OpenGL(2.x及更早版本)要求您将矩阵放在两个“矩阵堆栈”上:

    • GL_MODELVIEW堆栈应包含View * Model(或View * Model1 * Model2 ... * ModelN),
    • GL_PROJECTION堆栈,它只包含Projection矩阵。

这些也可以是单个矩阵,而不是堆栈,但是引入了堆栈(以及glPushMatrixglPopMatrix),让程序员可以轻松地“保存和加载”它们。在计算中只使用每个堆栈中的“最顶层”矩阵。

投影矩阵通常使用gluPerspective或等效项创建。视图矩阵可以使用gluLookAt(或类似于模型矩阵),并且可以使用glTranslateglRotateglScale轻松汇编模型矩阵。

(注意:OpenGL 3.1+删除了这些功能,允许您使用任何矩阵和您喜欢的任何约定)


知道:

  

我希望能够在翻译和旋转后得到一个物体(例如三角形)的坐标,我想这样做的原因是以后我可以进行碰撞检测并计算物体之间的距离。坐标

计算所有物理的合理方法是在场景空间中进行。

因此,如果您有一个模型(例如三角形网格),要获得场景空间中任何顶点的位置,您需要仅将其乘以模型的模型矩阵(或在层次结构的情况下,由其所有模型矩阵)。


关于gluProject,如果您想知道 - 这是一种方便的方法,它允许您将一组坐标乘以当前PROJECTION*MODELVIEW并执行视口转换以查看它最终会在屏幕中的位置空格,而gluUnProject则相反。

参考:http://www.opengl.org/resources/faq/technical/transformations.htm

答案 1 :(得分:3)

除了Kos的回答,请记住 OpenGL不是场景管理库。它只是一个绘图API,可以将内容绘制到屏幕上然后忘记它们。同样地,它对“对象”是什么没有任何理解,它只知道三角形,甚至在绘制之后它们也记不起来。从来没有想过为什么你必须每帧重新渲染整个场景?

因此,要了解对象在场景中的绝对位置,请自行跟踪转换,并从中计算出它的位置。

答案 2 :(得分:0)

mx,我只是错误的光标坐标

import numpy as np

我不知道glunproject并重新计算(glunproject的开放版本)

def CalculateRealCoordinates(mx, my):

    Inverseofmodelviewmatrix = np.linalg.inv(glGetDoublev(GL_MODELVIEW_MATRIX))
    Inverseofprojectionmatrix = np.linalg.inv(glGetDoublev(GL_PROJECTION_MATRIX))

    WindowCoordinates_x = mx
    WindowCoordinates_y = my

    # glViewport(x, y, w, h)
    glViewports = glGetIntegerv(GL_VIEWPORT)

    NormalizedDeviceCoordinates_x = (WindowCoordinates_x - (
            glViewports[0] + (glViewports[2] / 2))) * (2 / glViewports[2])
    NormalizedDeviceCoordinates_y = (WindowCoordinates_y - (
            glViewports[1] + (glViewports[3] / 2))) * (2 / glViewports[3])

    w = 1
    ClipCoordinates_x = NormalizedDeviceCoordinates_x * w
    ClipCoordinates_y = NormalizedDeviceCoordinates_y * w

    ClipCoordinatesMatrix = [[ClipCoordinates_x],
                             [-ClipCoordinates_y],
                             [0],
                             [0]]

    ClipCoordinatesMatrix = np.array(ClipCoordinatesMatrix)

    EyeCoordinatesMatrix = np.matmul(Inverseofprojectionmatrix, ClipCoordinatesMatrix)

    RealCoordinatesMatrix = np.matmul(Inverseofmodelviewmatrix, EyeCoordinatesMatrix)

    RealCoordinates_x = RealCoordinatesMatrix[0, 0]
    RealCoordinates_y = RealCoordinatesMatrix[1, 0]

    return RealCoordinates_x, RealCoordinates_y

内置gluUnProject版本:

def CalculateRealCoordinates(mx, my):

    WindowCoordinates_x = mx
    WindowCoordinates_y = my
    WindowCoordinates_z = 0

    RealCoordinates = gluUnProject(WindowCoordinates_x, WindowCoordinates_y, WindowCoordinates_z, glGetDoublev(GL_MODELVIEW_MATRIX), glGetDoublev(GL_PROJECTION_MATRIX), glGetIntegerv(GL_VIEWPORT))

    RealCoordinates_x = RealCoordinates[0]
    RealCoordinates_y = RealCoordinates[1]

    return RealCoordinates_x, RealCoordinates_y

,如果您只想撤消MODELVIEW_MATRIX

# your projection matrix must be like this -->
# [[1. 0. 0. 0.]
#  [0. 1. 0. 0.]
#  [0. 0. 1. 0.]
#  [0. 0. 0. 1.]]

def CalculateRealCoordinates(mx, my):
    Inverseofmodelviewmatrix = np.linalg.inv(glGetDoublev(GL_MODELVIEW_MATRIX))

    WindowCoordinates_x = mx
    WindowCoordinates_y = my

    glViewports = glGetIntegerv(GL_VIEWPORT)

    NormalizedDeviceCoordinates_x = (WindowCoordinates_x - (glViewports[0] + (glViewports[2] / 2))) * (
                2 / glViewports[2])
    NormalizedDeviceCoordinates_y = (WindowCoordinates_y - (glViewports[1] + (glViewports[3] / 2))) * (
                2 / glViewports[3])

    NormalizedDeviceMatrix = [[NormalizedDeviceCoordinates_x],
                              [NormalizedDeviceCoordinates_y],
                              [0],
                              [0]]
    NormalizedDeviceMatrix = np.array(NormalizedDeviceMatrix)

    RealCoordinates = np.matmul(Inverseofmodelviewmatrix, NormalizedDeviceMatrix)
    print("RealCoordinates:", RealCoordinates)

    RealCoordinates_x = RealCoordinates[0, 0]
    RealCoordinates_y = RealCoordinates[1, 0]

    return RealCoordinates_x, -RealCoordinates_y