【问题标题】:View Matrix in LWJGL 3 not showing rightLWJGL 3 中的查看矩阵未正确显示
【发布时间】:2018-08-01 02:49:19
【问题描述】:

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

矩阵数学类

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;
    }
}

【问题讨论】:

  • 您是否确认您添加了正确的矩阵旋转?您必须验证您是否使用了正确的度量(弧度/度)。否则你可以只使用像 JOML 这样的库,它可能性能更高(不使用 2D 数组)并且功能更完整。
  • @vandench 我使用旋转来旋转我的游戏对象,它工作正常

标签: java opengl matrix lwjgl


【解决方案1】:

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

这是由于 OpenGL NDC 空间特殊,叉积 XxY 得到 -Z 而不是 Z

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

【讨论】:

  • 这是关于左手和右手投影矩阵的吗?另外,它不起作用...
【解决方案2】:

这没有任何意义:

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

无论您使用什么约定,以及mul() 方法实际乘以哪个顺序。你要么最终得到T*P*V,要么得到V*P*T,这两个都不正确(对于在投影后不应用一些额外转换的典型用例)。

【讨论】:

  • 那么顺序是什么
  • 取决于您的约定,P*V*TT*V*P
猜你喜欢
  • 1970-01-01
  • 2017-07-08
  • 1970-01-01
  • 2013-01-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-21
  • 1970-01-01
相关资源
最近更新 更多