glGetFloat(GL_MODELVIEW_MATRIX,modelview)返回一个单位矩阵

时间:2018-09-20 13:22:42

标签: java opengl lwjgl

我正在尝试将3d点坐标转换为2d屏幕坐标。

但是,问题是当我实现它并运行程序时,即使我更改了摄像头的位置,输出也没有变化。即使我可以完全看到3D模型,输出也通常超出屏幕坐标范围(因此,任何点或三角形都不会超出屏幕坐标范围)。

将3d坐标转换为2d坐标的方法:

public Vector2f get2DFrom3D(float x, float y, float z)
{

    FloatBuffer screen_coords = BufferUtils.createFloatBuffer(4);
    IntBuffer viewport = BufferUtils.createIntBuffer(16);
    FloatBuffer modelview = BufferUtils.createFloatBuffer(16);
    FloatBuffer projection = BufferUtils.createFloatBuffer(16);

    GL11.glGetFloat(GL11.GL_MODELVIEW_MATRIX, modelview);
    System.out.println("modelview:");
    displayFloatBuffer(modelview);

    GL11.glGetFloat(GL11.GL_PROJECTION_MATRIX, projection);
    System.out.println("projection:");
    displayFloatBuffer(projection);

    GL11.glGetInteger(GL11.GL_VIEWPORT, viewport);
    System.out.println("viewport:");
    displayIntBuffer(viewport);

    boolean result = GLU.gluProject(x, y, z, modelview, projection, viewport, screen_coords);
    if (result)
    {
        System.out.printf("Convert [ %6.2f %6.2f %6.2f ] -> Screen [ %4d %4d ]\n", x, y, z, (int)screen_coords.get(0), (int)(screen_coords.get(3)-screen_coords.get(1)));
        return new Vector2f((int)screen_coords.get(0), (int)(screen_coords.get(3)-screen_coords.get(1)));
    }
    else
    {
        return null;
    }
}

通过这种方法创建投影矩阵,并将其直接加载到顶点着色器中:

private void createProjectionMatrix(){
        float aspectRatio = (float) Display.getWidth() / (float) Display.getHeight();
        float y_scale = (float) ((1f / Math.tan(Math.toRadians(FOV / 2f))) * aspectRatio);
        float x_scale = y_scale / aspectRatio;
        float frustum_length = FAR_PLANE - NEAR_PLANE;

        projectionMatrix = new Matrix4f();
        projectionMatrix.m00 = x_scale;
        projectionMatrix.m11 = y_scale;
        projectionMatrix.m22 = -((FAR_PLANE + NEAR_PLANE) / frustum_length);
        projectionMatrix.m23 = -1;
        projectionMatrix.m32 = -((2 * NEAR_PLANE * FAR_PLANE) / frustum_length);
        projectionMatrix.m33 = 0;
    }

顶点着色器:

#version 400 core

in vec3 position;

uniform mat4 transformationMatrix;
uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;

void main(void) {

    vec4 worldPosition = transformationMatrix * vec4(position, 1);
    gl_Position = projectionMatrix * viewMatrix * worldPosition;

}

渲染器:

public void render(Entity entity, int displayMode) {

    RawModel model = entity.getModel();

    shader.start();
    GL30.glBindVertexArray(model.getVaoID());
    GL20.glEnableVertexAttribArray(0);
    GL20.glEnableVertexAttribArray(1);

    Matrix4f transformationMatrix = Maths.createTransformationMatrix(entity.getPosition(), entity.getRotX(),
            entity.getRotY(), entity.getRotZ(), entity.getScale());
    shader.loadTransformationMatrix(transformationMatrix);

    GL11.glDrawElements(GL11.GL_TRIANGLES, model.getVertexAmount(), GL11.GL_UNSIGNED_INT, 0);

    GL20.glDisableVertexAttribArray(0);
    GL20.glDisableVertexAttribArray(1);
    GL30.glBindVertexArray(0);
    shader.stop();
}

然后,我调试代码并看到:

GL11.glGetFloat(GL11.GL_MODELVIEW_MATRIX, modelView);
GL11.glGetFloat(GL11.GL_PROJECTION_MATRIX, projection);

这些行只是不采用我定义的真实矩阵值。它们只是4阶身份矩阵。然后,我搜索了glMatrixMode来设置矩阵或设置gl_ModelViewMatrix,但是事实证明,我使用的opengl版本不再支持这些矩阵。

所以,我认为问题是我以某种方式与那些变量相关,并且以某种方式需要设置它们。最后但并非最不重要的是,这是get2DFrom3D方法的输出:

modelview:
1.0 0.0 0.0 0.0 
0.0 1.0 0.0 0.0 
0.0 0.0 1.0 0.0 
0.0 0.0 0.0 1.0 
projection:
1.0 0.0 0.0 0.0 
0.0 1.0 0.0 0.0 
0.0 0.0 1.0 0.0 
0.0 0.0 0.0 1.0 
viewport:
0 0 1209 891 
0 0 0 0 
0 0 0 0 
0 0 0 0

我认为只有视口是正确的,但是modelview和投影矩阵看起来好像没有加载为其计算的值。

注意:我目前正在使用lwjgl 2.9.3。

1 个答案:

答案 0 :(得分:0)

我找到了解决问题的方法,并且效果很好。这是我的新get2DFrom3D方法:

public Vector2f get2DFrom3D(float x, float y, float z)
{
    FloatBuffer screen_coords = BufferUtils.createFloatBuffer(4);
    IntBuffer viewport = BufferUtils.createIntBuffer(16);
    FloatBuffer modelview = BufferUtils.createFloatBuffer(16);  
    FloatBuffer projection = BufferUtils.createFloatBuffer(16);

    Matrix4f modelviewMatrix = new Matrix4f();
    Matrix4f transformationMatrix = new Matrix4f();
    Matrix4f.mul(transformationMatrix
            , Maths.createViewMatrix(camera)
            , modelviewMatrix);

    modelviewMatrix.store(modelview);
    modelview.rewind();

    projectionMatrix.store(projection);
    projection.rewind();

    GL11.glGetInteger(GL11.GL_VIEWPORT, viewport);

    boolean result = GLU.gluProject(x, y, z, modelview, projection, viewport, screen_coords);

    if (result)
    {
        Vector2f vector = new Vector2f((int)screen_coords.get(0), (int)(screen_coords.get(1)));
        return vector;
    }
    else
    {
        return null;
    }
}

不是使用glGetFloat方法来获取模型视图和投影矩阵。相反,我使用了在其他类中已经创建的矩阵,并将这些矩阵作为参数传递。然后,我将矩阵转换为缓冲区,以便可以使用它们。倒回它们之后,我终于可以从gluProject中获取点的正确屏幕坐标。

即使问题解决了,我仍然不知道为什么这些行不起作用:

  GL11.glGetFloat(GL11.GL_MODELVIEW_MATRIX, modelview);
    System.out.println("modelview:");
    displayFloatBuffer(modelview);

    GL11.glGetFloat(GL11.GL_PROJECTION_MATRIX, projection);