LWJGL 3中的查看矩阵未正确显示

时间:2018-08-01 02:49:20

标签: java opengl matrix lwjgl

我的相机类中的视图矩阵已正确设置,具有旋转和负平移功能,但是它将相机移动到其他位置,我似乎找不到我的模型。旋转和平移矩阵起作用了,因为平移起作用了,我的模型和投影矩阵也起作用了,但是当我添加视图矩阵时,它仅显示模型的一部分。顺便说一句,做了我自己的矩阵数学课。

矩阵数学类

package engine.maths;

public class Matrix4f {
    private float[][] matrix;

    public Matrix4f() {
        matrix = new float[4][4];
    }

    public Matrix4f identity() {
        matrix[0][0] = 1;   matrix[0][1] = 0;   matrix[0][2] = 0;   matrix[0][3] = 0;
        matrix[1][0] = 0;   matrix[1][1] = 1;   matrix[1][2] = 0;   matrix[1][3] = 0;
        matrix[2][0] = 0;   matrix[2][1] = 0;   matrix[2][2] = 1;   matrix[2][3] = 0;
        matrix[3][0] = 0;   matrix[3][1] = 0;   matrix[3][2] = 0;   matrix[3][3] = 1;

        return this;
    }

    public Matrix4f translate(Vector3f vector) {
        matrix[0][0] = 1;   matrix[0][1] = 0;   matrix[0][2] = 0;   matrix[0][3] = vector.getX();
        matrix[1][0] = 0;   matrix[1][1] = 1;   matrix[1][2] = 0;   matrix[1][3] = vector.getY();
        matrix[2][0] = 0;   matrix[2][1] = 0;   matrix[2][2] = 1;   matrix[2][3] = vector.getZ();
        matrix[3][0] = 0;   matrix[3][1] = 0;   matrix[3][2] = 0;   matrix[3][3] = 1;

        return this;
    }

    public Matrix4f rotate(Vector3f vector) {
        Matrix4f rotateX = new Matrix4f();
        Matrix4f rotateY = new Matrix4f();
        Matrix4f rotateZ = new Matrix4f();

        Vector3f rotatedVector = new Vector3f((float) Math.toRadians(vector.getX()), (float) Math.toRadians(vector.getY()), (float) Math.toRadians(vector.getZ()));

        rotateZ.matrix[0][0] = (float)Math.cos(rotatedVector.getZ()); rotateZ.matrix[0][1] = -(float)Math.sin(rotatedVector.getZ()); rotateZ.matrix[0][2] = 0; rotateZ.matrix[0][3] = 0;
        rotateZ.matrix[1][0] = (float)Math.sin(rotatedVector.getZ()); rotateZ.matrix[1][1] =  (float)Math.cos(rotatedVector.getZ()); rotateZ.matrix[1][2] = 0; rotateZ.matrix[1][3] = 0;
        rotateZ.matrix[2][0] = 0;                                     rotateZ.matrix[2][1] = 0;                                      rotateZ.matrix[2][2] = 1; rotateZ.matrix[2][3] = 0;
        rotateZ.matrix[3][0] = 0;                                     rotateZ.matrix[3][1] = 0;                                      rotateZ.matrix[3][2] = 0; rotateZ.matrix[3][3] = 1;

        rotateX.matrix[0][0] = 1; rotateX.matrix[0][1] = 0;                                     rotateX.matrix[0][2] = 0;                                      rotateX.matrix[0][3] = 0;
        rotateX.matrix[1][0] = 0; rotateX.matrix[1][1] = (float)Math.cos(rotatedVector.getX()); rotateX.matrix[1][2] = -(float)Math.sin(rotatedVector.getX()); rotateX.matrix[1][3] = 0;
        rotateX.matrix[2][0] = 0; rotateX.matrix[2][1] = (float)Math.sin(rotatedVector.getX()); rotateX.matrix[2][2] = (float)Math.cos(rotatedVector.getX());  rotateX.matrix[2][3] = 0;
        rotateX.matrix[3][0] = 0; rotateX.matrix[3][1] = 0;                                     rotateX.matrix[3][2] = 0;                                      rotateX.matrix[3][3] = 1;

        rotateY.matrix[0][0] = (float)Math.cos(rotatedVector.getY()); rotateY.matrix[0][1] = 0; rotateY.matrix[0][2] = -(float)Math.sin(rotatedVector.getY()); rotateY.matrix[0][3] = 0;
        rotateY.matrix[1][0] = 0;                                     rotateY.matrix[1][1] = 1; rotateY.matrix[1][2] = 0;                                      rotateY.matrix[1][3] = 0;
        rotateY.matrix[2][0] = (float)Math.sin(rotatedVector.getY()); rotateY.matrix[2][1] = 0; rotateY.matrix[2][2] = (float)Math.cos(rotatedVector.getY());  rotateY.matrix[2][3] = 0;
        rotateY.matrix[3][0] = 0;                                     rotateY.matrix[3][1] = 0; rotateY.matrix[3][2] = 0;                                      rotateY.matrix[3][3] = 1;

        matrix = rotateZ.mul(rotateY.mul(rotateX)).getMatrix();

        return this;
    }

    public Matrix4f scale(Vector3f vector) {
        matrix[0][0] = vector.getX(); matrix[0][1] = 0;             matrix[0][2] = 0;             matrix[0][3] = 0;
        matrix[1][0] = 0;             matrix[1][1] = vector.getY(); matrix[1][2] = 0;             matrix[1][3] = 0;
        matrix[2][0] = 0;             matrix[2][1] = 0;             matrix[2][2] = vector.getZ(); matrix[2][3] = 0;
        matrix[3][0] = 0;             matrix[3][1] = 0;             matrix[3][2] = 0;             matrix[3][3] = 1;

        return this;
    }

    public Matrix4f projection(float fov, float aspectRatio, float zNear, float zFar) {
        float tanHalfFOV = (float) Math.tan(Math.toRadians(fov / 2));
        float zRange = zNear - zFar;

        matrix[0][0] = 1.0f / (tanHalfFOV * aspectRatio); matrix[0][1] = 0;                 matrix[0][2] = 0;                        matrix[0][3] = 0;
        matrix[1][0] = 0;                                 matrix[1][1] = 1.0f / tanHalfFOV; matrix[1][2] = 0;                        matrix[1][3] = 0;
        matrix[2][0] = 0;                                 matrix[2][1] = 0;                 matrix[2][2] = (-zNear - zFar) / zRange; matrix[2][3] = 2 * zFar * zNear / zRange;
        matrix[3][0] = 0;                                 matrix[3][1] = 0;                 matrix[3][2] = 1;                        matrix[3][3] = 0;

        return this;
    }

    public Matrix4f mul(Matrix4f m) {
        Matrix4f result = new Matrix4f();

        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                result.set(i, j, matrix[i][0] * m.get(0, j) +
                                 matrix[i][1] * m.get(1, j) +
                                 matrix[i][2] * m.get(2, j) +
                                 matrix[i][3] * m.get(3, j));
            }
        }

        return result;
    }

    public float[][] getMatrix() {
        return matrix;
    }

    public void setMatrix(float[][] matrix) {
        this.matrix = matrix;
    }

    public float get(int x, int y) {
        return matrix[x][y];
    }

    public void set(int x, int y, float value) {
        matrix[x][y] = value;
    }

    public String toString() {
        String matrix = "";
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                matrix += (Float.toString(get(i, j)) + ", ");
            }
            matrix += "\n";
        }
        return matrix + "";
    }
}

相机类别

package engine.rendering;

import engine.maths.Matrix4f;
import engine.maths.Vector3f;

public class Camera {
    private Vector3f position, rotation;
    public Camera(Vector3f position, Vector3f rotation) {
        this.position = position;
        this.rotation = rotation;
    }

    public Matrix4f getViewMatrix() {
        Matrix4f rotationMatrix = new Matrix4f().identity().rotate(rotation);
        Vector3f negativePosition = new Vector3f(-position.getX(), -position.getY(), -position.getZ());
        Matrix4f translationMatrix = new Matrix4f().identity().translate(negativePosition);
        return rotationMatrix.mul(translationMatrix);
    }

    public void addPosition(float x, float y, float z) {
        position.add(new Vector3f(x, y, z));
    }

    public void addPosition(Vector3f value) {
        position.add(value);
    }

    public void setPosition(float x, float y, float z) {
        position = new Vector3f(x, y, z);
    }

    public void setPosition(Vector3f pos) {
        position = pos;
    }

    public Vector3f getPosition() {
        return position;
    }

    public void addRotation(float x, float y, float z) {
        rotation.add(new Vector3f(x, y, z));
    }

    public void addRotation(Vector3f value) {
        rotation.add(value);
    }

    public void setRotation(float x, float y, float z) {
        rotation = new Vector3f(x, y, z);
    }

    public void setRotation(Vector3f rot) {
        rotation = rot;
    }

    public Vector3f getRotation() {
        return rotation;
    }
}

加载矩阵类

package engine.shaders;

import engine.maths.Matrix4f;

public class BasicShader extends Shader {

    private static final String VERTEX_FILE = "src/engine/shaders/basicVertexShader.glsl";
    private static final String FRAGMENT_FILE = "src/engine/shaders/basicFragmentShader.glsl";

    private int tvpMatrixLocation;

    private Matrix4f transformationMatrix = new Matrix4f().identity(), projectionMatrix = new Matrix4f().identity(), viewMatrix = new Matrix4f().identity();

    public BasicShader() {
        super(VERTEX_FILE, FRAGMENT_FILE);
    }

    @Override
    protected void bindAttributes() {
        super.bindAttribute(0, "position");
        super.bindAttribute(1, "textCoords");
    }

    @Override
    protected void getAllUniforms() {
        tvpMatrixLocation = super.getUniform("tvpMatrix");
    }

    public void useMatrices() {
        super.loadMatrixUniform(tvpMatrixLocation, transformationMatrix.mul(projectionMatrix.mul(viewMatrix)));
    }

    public void loadTransformationMatrix(Matrix4f matrix) {
        transformationMatrix = matrix;
    }

    public void loadProjectionMatrix(Matrix4f matrix) {
        projectionMatrix = matrix;
    }

    public void loadViewMatrix(Matrix4f matrix) {
        viewMatrix = matrix;
    }
}

2 个答案:

答案 0 :(得分:0)

您的投影矩阵有错误:matrix[3][2] = 1必须为-1

这是由于OpenGL NDC空间是特殊的,叉积XxY给出的是-Z而不是Z

令人惊讶的事实是,所有可见对象在视图空间中都必须具有负Z坐标。

答案 1 :(得分:0)

这没有任何意义:

super.loadMatrixUniform(tvpMatrixLocation, transformationMatrix.mul(projectionMatrix.mul(viewMatrix)));

无论您使用哪种约定以及mul()方法实际上乘以的顺序。您要么以T*P*VV*P*T结尾,但两者都不正确(对于典型的用例,在投影后不应用其他变换)。