从相机坐标计算世界坐标

Calculating world coordinates from camera coordinates

我有一个以 2D 呈现的世界,我正在从顶部查看它。 Tjat 看起来像这样(地砖还没有纹理,只有随机的绿色):

在渲染我的实体之前,我像这样变换模型视图矩阵(position 是位置,zoom 是相机的变焦,ROTATION 是 45):

glScalef(this.zoom, this.zoom, 1);
glTranslatef(this.position.x, this.position.y, 0);
glRotatef(ROTATION, 0, 0, 1);

现在我想计算相机当前位置的世界坐标。我正在尝试的是用 glPushMatrix 创建一个新矩阵,然后以与摄像机变换相同的方式对其进行变换,然后获取矩阵并将给定的摄像机坐标与其相乘:

private Vector2f toWorldCoordinates(Vector2f position) {

    glPushMatrix();

    // do the same as when rendering
    glScalef(this.zoom, this.zoom, 1);
    glTranslatef(this.position.x, this.position.y, 0);
    glRotatef(ROTATION, 0, 0, 1);

    // get the model-view matrix
    ByteBuffer m = ByteBuffer.allocateDirect(64);
    m.order(ByteOrder.nativeOrder());
    glGetFloatv(GL_MODELVIEW_MATRIX, m);

    // calculate transformed position
    float x = (position.x * m.getFloat(0)) + (position.y * m.getFloat(4)) + m.getFloat(12);
    float y = (position.x * m.getFloat(1)) + (position.y * m.getFloat(5)) + m.getFloat(13);
    System.out.println(x + "/" + y);

    glPopMatrix();
    return new Vector2f(x, y);
}

现在的问题是:这适用于 x 坐标,但是 y 坐标是错误的并且始终为 0。我是否以某种方式误用了矩阵?有没有 "smoother" 从眼睛坐标获取世界坐标的方法?

问题在于您的呼叫方式 getFloat()。当您使用 ByteBuffer 上的索引调用它时,索引是缓冲区中开始读取浮点数的字节数,而不是浮点数。您需要将每个索引乘以 4:

float x = (position.x * m.getFloat(0)) + (position.y * m.getFloat(16)) + m.getFloat(48);
float y = (position.x * m.getFloat(4)) + (position.y * m.getFloat(20)) + m.getFloat(52);

但是鉴于 x 已经为您工作,我怀疑您可能还需要转置矩阵坐标,因此正确的代码是:

float x = (position.x * m.getFloat(0)) + (position.y * m.getFloat(4)) + m.getFloat(12);
float y = (position.x * m.getFloat(16)) + (position.y * m.getFloat(20)) + m.getFloat(28);

(巧合的是,将矩阵的第一行转置到第一列得到的索引是原来的 4 倍,因此在 x 而不是 y 的情况下,这两个错误相互抵消)。

如果您正在寻找一种更流畅的方法,请考虑使用 gluUnProject,尽管您可能需要应用一些额外的变换(它从 window 映射到对象坐标).