当前位置: 首页 > 知识库问答 >
问题:

OpenGL 2.0矩阵不能工作

宋勇
2023-03-14

我使用Java和OpenGL(LWJGL)来设置一些矩阵,我不想使用内置的方法,因为我也想在Android上工作,所以使用LWJGL的矩阵类是不合适的。目前我正在建立一个透视图,使用一个视场70,znear 0.1,zfar 1000。使用当前设置旋转只会导致奇怪的结果,不是以正确的方式旋转,对象被奇怪地缩放,经常消失。

下面是Matrix4D类:

public class Matrix4D {

/* The values within this matrix */
public float[] values;

/* The default constructor */
public Matrix4D() {
    //Create the values
    this.values = new float[16];
}

/* The constructor with the values given */
public Matrix4D(float[] values) {
    //Create the values
    this.values = values;
}

/* The constructor with the values given */
public Matrix4D(float[][] values) {
    //Load the values
    load(values);
}

/* The method used to set the values given a 2 dimensional array */
public void load(float[][] values) {
    this.values = new float[] {
            values[0][0], values[0][1], values[0][2], values[0][3],
            values[1][0], values[1][1], values[1][2], values[1][3],
            values[2][0], values[2][1], values[2][2], values[2][3],
            values[3][0], values[3][1], values[3][2], values[3][3]
    };
}

/* The method used to get a value using the coordinate within this matrix */
public float get(int x, int y) {
    //Get the position
    int position = x + (y * 4);
    //Return the value
    return this.values[position];
}

/* The method used to return a string representation of this matrix */
public String toString() {
    //Return the string
    return "[ " + this.values[0] + " " + this.values[1] + " " + + this.values[2] + " " + + this.values[3] + " ]" + "\n" +
           "[ " + this.values[4] + " " + this.values[5] + " " + + this.values[6] + " " + + this.values[7] + " ]" + "\n" +
           "[ " + this.values[8] + " " + this.values[9] + " " + + this.values[10] + " " + + this.values[11] + " ]" + "\n" +
           "[ " + this.values[12] + " " + this.values[13] + " " + + this.values[14] + " " + + this.values[15] + " ]";
}

/* The method used to get the values */
public float[] getValues() { return this.values; }

/* The method used to get the values in a 2D array */
public float[][] getValues2DArray() {
    //The array
    float[][] array = new float[4][4];
    //Go through each value
    int column = 0;
    int row = 0;
    while (column * row < array.length) {
        row ++;
        if (row >= 4) {
            column++;
            row = 0;
        }
        array[column][row] = this.values[column * row];
    }
    //Return the array
    return array;
}

}

下面是Matrix类(用于在矩阵上设置和执行计算):

public class Matrix {

/* The different matrices */
public static Matrix4D modelMatrix = new Matrix4D();
public static Matrix4D viewMatrix = new Matrix4D();
public static Matrix4D projectionMatrix = new Matrix4D();
public static Matrix4D modelViewProjectionMatrix = new Matrix4D();

/* The static method used to load an identity matrix */
public static void loadIdentity(Matrix4D matrix) {
    //Load the identity matrix
    matrix.load(new float[][] {
            new float[] { 1, 0, 0, 0 },
            new float[] { 0, 1, 0, 0 },
            new float[] { 0, 0, 1, 0 },
            new float[] { 0, 0, 0, 1 },
    });
}

/* The static method used to add two matrices together */
public static Matrix4D add(Matrix4D matrixA, Matrix4D matrixB) {
    //Create a new matrix
    Matrix4D matrix = new Matrix4D();
    //Go through each value
    for (int a = 0; a < matrix.values.length; a++)
        //Assign the current value
        matrix.values[a] = matrixA.values[a] + matrixB.values[a];
    //Return the matrix
    return matrix;
}

/* The static method used to subtract a matrix (B) from another (A) */
public static Matrix4D subtract(Matrix4D matrixA, Matrix4D matrixB) {
    //Create a new matrix
    Matrix4D matrix = new Matrix4D();
    //Go through each value
    for (int a = 0; a < matrix.values.length; a++)
        //Assign the current value
        matrix.values[a] = matrixB.values[a] - matrixA.values[a];
    //Return the matrix
    return matrix;
}

/* The static method used to multiply two matrices together */
public static Matrix4D multiply(Matrix4D matrixA, Matrix4D matrixB) {
    //Create a new matrix
    Matrix4D matrix = new Matrix4D(new float[][] {
            new float[] {
                    (matrixA.values[0] * matrixB.values[0]) + (matrixA.values[1] * matrixB.values[4]) + (matrixA.values[2] * matrixB.values[8]) + (matrixA.values[3] * matrixB.values[12]),
                    (matrixA.values[0] * matrixB.values[1]) + (matrixA.values[1] * matrixB.values[5]) + (matrixA.values[2] * matrixB.values[9]) + (matrixA.values[3] * matrixB.values[13]),
                    (matrixA.values[0] * matrixB.values[2]) + (matrixA.values[1] * matrixB.values[6]) + (matrixA.values[2] * matrixB.values[10]) + (matrixA.values[3] * matrixB.values[14]),
                    (matrixA.values[0] * matrixB.values[3]) + (matrixA.values[1] * matrixB.values[7]) + (matrixA.values[2] * matrixB.values[11]) + (matrixA.values[3] * matrixB.values[15])
            },
            new float[] {
                    (matrixA.values[4] * matrixB.values[0]) + (matrixA.values[5] * matrixB.values[4]) + (matrixA.values[6] * matrixB.values[8]) + (matrixA.values[7] * matrixB.values[12]),
                    (matrixA.values[4] * matrixB.values[1]) + (matrixA.values[5] * matrixB.values[5]) + (matrixA.values[6] * matrixB.values[9]) + (matrixA.values[7] * matrixB.values[13]),
                    (matrixA.values[4] * matrixB.values[2]) + (matrixA.values[5] * matrixB.values[6]) + (matrixA.values[6] * matrixB.values[10]) + (matrixA.values[7] * matrixB.values[14]),
                    (matrixA.values[4] * matrixB.values[3]) + (matrixA.values[5] * matrixB.values[7]) + (matrixA.values[6] * matrixB.values[11]) + (matrixA.values[7] * matrixB.values[15])
            },
            new float[] {
                    (matrixA.values[8] * matrixB.values[0]) + (matrixA.values[9] * matrixB.values[4]) + (matrixA.values[10] * matrixB.values[8]) + (matrixA.values[11] * matrixB.values[12]),
                    (matrixA.values[8] * matrixB.values[1]) + (matrixA.values[9] * matrixB.values[5]) + (matrixA.values[10] * matrixB.values[9]) + (matrixA.values[11] * matrixB.values[13]),
                    (matrixA.values[8] * matrixB.values[2]) + (matrixA.values[9] * matrixB.values[6]) + (matrixA.values[10] * matrixB.values[10]) + (matrixA.values[11] * matrixB.values[14]),
                    (matrixA.values[8] * matrixB.values[3]) + (matrixA.values[9] * matrixB.values[7]) + (matrixA.values[10] * matrixB.values[11]) + (matrixA.values[11] * matrixB.values[15])
            },
            new float[] {
                    (matrixA.values[12] * matrixB.values[0]) + (matrixA.values[13] * matrixB.values[4]) + (matrixA.values[14] * matrixB.values[8]) + (matrixA.values[15] * matrixB.values[12]),
                    (matrixA.values[12] * matrixB.values[1]) + (matrixA.values[13] * matrixB.values[5]) + (matrixA.values[14] * matrixB.values[9]) + (matrixA.values[15] * matrixB.values[13]),
                    (matrixA.values[12] * matrixB.values[2]) + (matrixA.values[13] * matrixB.values[6]) + (matrixA.values[14] * matrixB.values[10]) + (matrixA.values[15] * matrixB.values[14]),
                    (matrixA.values[12] * matrixB.values[3]) + (matrixA.values[13] * matrixB.values[7]) + (matrixA.values[14] * matrixB.values[11]) + (matrixA.values[15] * matrixB.values[15])
            }
    });
    //Return the matrix
    return matrix;
}

/* The static method used to transpose a matrix */
public static Matrix4D transpose(Matrix4D matrix) {
    //Get the values from the matrix
    float[][] values = matrix.getValues2DArray();
    //The new values
    float[][] newValues = new float[4][4];
    //Go through the array
    for (int y = 0; y < values.length; y++) {
        for (int x = 0; x < values[y].length; x++) {
            //Assign the new value
            newValues[x][y] = values[y][x];
        }
    }
    //Return the matrix
    return new Matrix4D(newValues);
}

/* The static method used to translate a matrix */
public static Matrix4D translate(Matrix4D matrix, Vector3D vector) {
    //The transform matrix
    Matrix4D transform = new Matrix4D(new float[][] {
            new float[] { 0, 0, 0, vector.x },
            new float[] { 0, 0, 0, vector.y },
            new float[] { 0, 0, 0, vector.z },
            new float[] { 0, 0, 0, 0 },
    });
    //Add onto the matrix and return the result
    return add(matrix, transform);
}

/* The static method used to rotate a matrix */
public static Matrix4D rotate(Matrix4D matrix, float angle, int x, int y, int z) {
    //The transform matrix
    Matrix4D transform = new Matrix4D();
    //Calculate the values needed
    float cos = (float) Math.cos(angle);
    float sin = (float) Math.sin(angle);
    //Check the x y and z values
    if (x == 1) {
        transform.load(new float[][] {
                new float[] { 0, 0, 0, 0 },
                new float[] { 0, cos, -sin, 0 },
                new float[] { 0, sin, cos, 0 },
                new float[] { 0, 0, 0, 0 },
        });
    } else if (y == 1) {
        transform.load(new float[][] {
                new float[] { cos, 0, sin, 0 },
                new float[] { 0, 0, 0, 0 },
                new float[] { -sin, 0, cos, 0 },
                new float[] { 0, 0, 0, 0 },
        });
    } else if (z == 1) {
        transform.load(new float[][] {
                new float[] { cos, -sin, 0, 0 },
                new float[] { sin, cos, 0, 0 },
                new float[] { 0, 0, 0, 0 },
                new float[] { 0, 0, 0, 0 },
        });
    }
    //Add onto the matrix and return the result
    return add(matrix, transform);
}

/* The static method used to scale a matrix */
public static Matrix4D scale(Matrix4D matrix, Vector3D vector) {
    //The transform matrix
    Matrix4D transform = new Matrix4D(new float[][] {
            new float[] { vector.x, 0, 0, 0 },
            new float[] { 0, vector.y, 0, 0 },
            new float[] { 0, 0, vector.z, 0 },
            new float[] { 0, 0, 0, 0 },
    });
    //Add onto the matrix and return the result
    return add(matrix, transform);
}

/* The static method used to return an orthographic projection matrix */
public static Matrix4D ortho(float left, float right, float top, float bottom, float zfar, float znear) {
    return new Matrix4D(new float[][] {
            new float[] { 2 / (right - left), 0, 0, -((right + left) / (right - left)) },
            new float[] { 0, 2 / (top - bottom), 0, -((top + bottom) / (top - bottom)) },
            new float[] { 0, 0, -2 / (zfar - znear), -((zfar + znear) / (zfar - znear)) },
            new float[] { 0, 0, 0, 1 },
    });
}

/* The static method used to return a perspective projection matrix */
public static Matrix4D perspective(float fov, float aspect, float zNear, float zFar) {
    float f = (float) (1f / Math.tan(fov / 2f));
    return new Matrix4D(new float[][] {
            new float[] { f / aspect, 0, 0, 0 },
            new float[] { 0, f, 0, 0 },
            new float[] { 0, 0, (zFar + zNear) / (zFar - zNear), (2 * zFar * zNear) / (zNear - zFar) },
            new float[] { 0, 0, -1, 0 },
    });
}

}

最后,建立透视/正投影的方法是:

/* The static method to setup an orthographic view given the width, height
 * znear and zfar values */
public static void setupOrtho(float width, float height, float znear , float zfar) {
    Matrix.loadIdentity(Matrix.modelMatrix);
    Matrix.loadIdentity(Matrix.viewMatrix);
    Matrix.projectionMatrix = Matrix.ortho(0, width, 0, height, znear, zfar);
}

/* The static method used to setup a perspective view given the
 * fov, z near and z far value */
public static void setupPerspective(float fov, float zNear, float zFar) {
    setupPerspective(fov, (float) (Settings.Window.Width / Settings.Window.Height), zNear, zFar);
}

/* The static method used to setup a perspective view given the
 * fov, aspect ratio, z near and z far values */
public static void setupPerspective(float fov, float aspect, float zNear, float zFar) {
    Matrix.loadIdentity(Matrix.modelMatrix);
    Matrix.loadIdentity(Matrix.viewMatrix);
    Matrix.projectionMatrix = Matrix.perspective(fov, aspect, zNear, zFar);
}

渲染所有这些并将矩阵传递给我使用的着色器

    //Multiply the matrices together
    Matrix4D modelViewMatrix = Matrix.multiply(Matrix.modelMatrix, Matrix.viewMatrix);
    Matrix.modelViewProjectionMatrix = (Matrix.multiply(modelViewMatrix, Matrix.projectionMatrix));
    System.out.println(Matrix.modelViewProjectionMatrix.toString() + "\n");

在着色器中,我将当前顶点的位置与模型视图投影marix相乘。

共有1个答案

厉钊
2023-03-14

你的矩阵相乘的顺序似乎不对。当组合矩阵变换时,方程右边的一个将是执行的第一个变换。

您将矩阵计算为模型×视图×投影。当将其乘以向量时,将首先执行投影,然后是视图转换,最后是模型转换。显然这不是你想要的。

你的最终矩阵应该像投影×视图×模型那样计算,以正确的顺序进行转换。

 类似资料:
  • 我有一个基本的OpenGL应用程序,我想使用我的投影矩阵。 这是我的矩阵: (WorldCoordinates是Matrix4结构,它只包含一个名为m的变量,即浮点[4][4])(宽度和高度是两个s)。然后,我使用以下方法将此坐标应用于我的<code>顶点 (Shader是一个类,并且有一个绑定()方法,它只是glUseProgram)。 这是我的顶点着色器GLSL 使用这个,它不起作用。但将gl

  • 在使用numpy的python中,假设我有两个矩阵: 稀疏矩阵 密集的x*y矩阵 现在我想做,它将返回一个密集的矩阵。 但是,我只关心中非零的单元格,这意味着如果我这样做了,对我的应用程序不会有任何影响 <代码>S\u=S*S\u 显然,这将是对操作的浪费,因为我想把在

  • 着色器语言中通过关键字mat2、mat3、mat4分别声明一个2x2矩阵、3x3矩阵、4x4矩阵,通过内置函数mat2()、mat3()、mat4()分别创建一个2x2矩阵、3x3矩阵、4x4矩阵。 关键字 数据类型 mat2 2x2矩阵,4个元素 mat3 3x3矩阵,9个元素 mat4 4x4矩阵,16个元素 声明变量 关键子mat4声明一个4x4矩阵 mat4 matrix4; 构造函数赋

  • 注:我也在这里的Eigen论坛上发表了这篇文章 我想用一个3x3矩阵预乘3xN个矩阵,即,变换3D点,如p_dest=T*p_source 初始化矩阵后: 而且 进行NT重复只是为了计算平均时间 我很惊讶逐列乘法比直接乘法快4/5倍(如果我不使用,直接乘法甚至更慢,但这没有问题,因为它是临时复制)。我尝试将NUMCOLS从0改为1000000,关系是线性的。

  • 我有一个看起来像这样的请求: http://localhost:8080/car/BMW;颜色=红色 返回汽车模型及其颜色作为 json 数据。如果我在没有指定颜色的情况下执行请求,它将默认为绿色。 Java代码: 当我将url复制/粘贴到浏览器时,它会按预期返回json,但当我尝试放心地获取它时,我收到404未找到错误。我尝试发送带有参数(“颜色”,颜色)的请求,但它只是忽略参数并返回默认jso

  • 我在查看一些代码时发现了以下内容: 有什么区别呢?顺便说一句:我对矩阵很陌生