java - 使用 lwjgl 实现第三人称相机

标签 java opengl lwjgl matrix-multiplication

我已经多次尝试实现第三人称相机,但我似乎无法让它工作。移动和缩放工作正常,但旋转却给我带来了很多麻烦:

  1. 当改变相机的俯仰角(即从你看玩家的高度)时,相机总是在玩家的位置绕世界 x 轴旋转,而不是相机 x 轴

  2. 当改变玩家周围的角度时,相机总是围绕玩家位置的世界 z 轴旋转,而不是相机 z 轴

  3. 当向任意方向旋转相机时,它会沿着该方向缓慢移动,而不是停留在距玩家位置的固定偏移处

我已经尝试过更改矩阵乘法顺序,但这没有帮助,我也尝试过查看矩阵,但这根本不起作用,会产生各种其他问题。我知道,使用数学库会让这变得容易得多,但这不是我的目标。我想至少尝试理解这背后的数学原理并理解我的错误。

我的 Matrix4f 类(class):


import java.nio.FloatBuffer;
import java.util.Arrays;
import java.util.Iterator;

import com.engine.toolbox.ArrayUtils;
import com.engine.toolbox.BufferUtils;
import com.engine.toolbox.math.vectors.Vector3f;
import com.engine.toolbox.math.vectors.Vector4f;

public class Matrix4f extends Matrix{

    public float m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44;

    public Matrix4f(float m11, float m12, float m13, float m14,
                    float m21, float m22, float m23, float m24,
                    float m31, float m32, float m33, float m34,
                    float m41, float m42, float m43, float m44) {
        super(new Float[] { m11, m12, m13, m14, 
                            m21, m22, m23, m24, 
                            m31, m32, m33, m34, 
                            m41, m42, m43, m44});
        this.m11 = m11;
        this.m12 = m12;
        this.m13 = m13;
        this.m14 = m14;
        this.m21 = m21;
        this.m22 = m22;
        this.m23 = m23;
        this.m24 = m24;
        this.m31 = m31;
        this.m32 = m32;
        this.m33 = m33;
        this.m34 = m34;
        this.m41 = m41;
        this.m42 = m42;
        this.m43 = m43;
        this.m44 = m44;

    }

    @Override
    public Iterator<Float> iterator() {
        return Arrays.asList(this.toRawTypes()).iterator();
    }

    public Matrix4f invert() {
        Matrix4f matrixOfMinors =   new Matrix4f(   new Matrix3f(   m22, m23, m24,
                                                                    m32, m33, m34,
                                                                    m42, m43, m44).getDeterminant(), new Matrix3f(  m21, m23, m24,
                                                                                                                    m31, m33, m34,
                                                                                                                    m41, m43, m44).getDeterminant(), new Matrix3f(  m21, m22, m24,
                                                                                                                                                                    m31, m32, m34,
                                                                                                                                                                    m41, m42, m44).getDeterminant(), new Matrix3f(  m21, m22, m23,
                                                                                                                                                                                                                    m31, m32, m33,
                                                                                                                                                                                                                    m41, m42, m43).getDeterminant(),
                                                    new Matrix3f(   m12, m13, m14,
                                                                    m32, m33, m34,
                                                                    m42, m43, m44).getDeterminant(), new Matrix3f(  m11, m13, m14,
                                                                                                                    m31, m33, m34,
                                                                                                                    m41, m43, m44).getDeterminant(), new Matrix3f(  m11, m12, m14,
                                                                                                                                                                    m31, m32, m34,
                                                                                                                                                                    m41, m42, m44).getDeterminant(), new Matrix3f(  m11, m12, m23,
                                                                                                                                                                                                                    m31, m32, m33,
                                                                                                                                                                                                                    m41, m42, m43).getDeterminant(),
                                                    new Matrix3f(   m12, m13, m14,
                                                                    m22, m23, m24,
                                                                    m42, m43, m44).getDeterminant(), new Matrix3f(  m11, m13, m14,
                                                                                                                    m21, m23, m24,
                                                                                                                    m41, m43, m44).getDeterminant(), new Matrix3f(  m11, m12, m14,
                                                                                                                                                                    m21, m22, m24,
                                                                                                                                                                    m41, m42, m44).getDeterminant(), new Matrix3f(  m11, m12, m23,
                                                                                                                                                                                                                    m21, m22, m23,
                                                                                                                                                                                                                    m41, m42, m43).getDeterminant(),
                                                    new Matrix3f(   m12, m13, m14,
                                                                    m22, m23, m24,
                                                                    m32, m33, m34).getDeterminant(), new Matrix3f(  m11, m13, m14,
                                                                                                                    m21, m23, m24,
                                                                                                                    m31, m33, m34).getDeterminant(), new Matrix3f(  m11, m12, m14,
                                                                                                                                                                    m21, m22, m24,
                                                                                                                                                                    m31, m32, m34).getDeterminant(), new Matrix3f(  m11, m12, m23,
                                                                                                                                                                                                                    m21, m22, m23,
                                                                                                                                                                                                                    m31, m32, m33).getDeterminant());
        matrixOfMinors.m12 = -m12;
        matrixOfMinors.m14 = -m14;

        matrixOfMinors.m21 = -m21;
        matrixOfMinors.m23 = -m23;

        matrixOfMinors.m32 = -m32;
        matrixOfMinors.m34 = -m34;

        matrixOfMinors.m41 = -m41;
        matrixOfMinors.m43 = -m43;

        float temp = 0;

        temp = matrixOfMinors.m12;
        matrixOfMinors.m12 = matrixOfMinors.m21;
        matrixOfMinors.m21 = temp;

        temp = matrixOfMinors.m13;
        matrixOfMinors.m13= matrixOfMinors.m31;
        matrixOfMinors.m31 = temp;

        temp = matrixOfMinors.m23;
        matrixOfMinors.m23 = matrixOfMinors.m32;
        matrixOfMinors.m32 = temp;

        temp = matrixOfMinors.m14;
        matrixOfMinors.m14 = matrixOfMinors.m41;
        matrixOfMinors.m41 = temp;

        temp = matrixOfMinors.m24;
        matrixOfMinors.m24 = matrixOfMinors.m42;
        matrixOfMinors.m42 = temp;

        temp = matrixOfMinors.m34;
        matrixOfMinors.m34 = matrixOfMinors.m43;
        matrixOfMinors.m43 = temp;

        float d = this.getDeterminant();
        return new Matrix4f(matrixOfMinors.m11/d, matrixOfMinors.m12/d, matrixOfMinors.m13/d, matrixOfMinors.m14/d,
                            matrixOfMinors.m21/d, matrixOfMinors.m22/d, matrixOfMinors.m23/d, matrixOfMinors.m24/d,
                            matrixOfMinors.m31/d, matrixOfMinors.m32/d, matrixOfMinors.m33/d, matrixOfMinors.m34/d,
                            matrixOfMinors.m41/d, matrixOfMinors.m42/d, matrixOfMinors.m43/d, matrixOfMinors.m44/d);
    }

    public float getDeterminant() {
        return  m11*(new Matrix3f(  m22, m23, m24,
                                    m32, m33, m34,
                                    m42, m43, m44).getDeterminant()) - 
                m12*(new Matrix3f(  m21, m23, m24,
                                    m31, m33, m34,
                                    m41, m43, m44).getDeterminant()) + 
                m13*(new Matrix3f(  m21, m22, m24,
                                    m31, m32, m34,
                                    m41, m42, m44).getDeterminant()) - 
                m14*(new Matrix3f(  m21, m22, m23,
                                    m31, m32, m33,
                                    m41, m42, m43).getDeterminant());
    }

    public static Matrix4f identity() {
        return new Matrix4f(1, 0, 0, 0, 
                            0, 1, 0, 0, 
                            0, 0, 1, 0, 
                            0, 0, 0, 1);
    }

    public static Matrix4f perspective(float aspectRatio, float viewAngle, float nearPlane, float farPlane) {
        return new Matrix4f((float) (1/(aspectRatio*Math.tan((viewAngle/2)))),  0,                                      0,                                          0,
                            0,                                                  (float) (1/(Math.tan((viewAngle/2)))),  0,                                          0,
                            0,                                                  0,                                      -(farPlane+nearPlane)/(farPlane-nearPlane), (2*farPlane*nearPlane)/(farPlane-nearPlane),
                            0,                                                  0,                                      -1,                                         1);
    }

    public static Matrix4f translation(Vector3f translation) {
        Matrix4f result = Matrix4f.identity();
        result.m14 = translation.x;
        result.m24 = translation.y;
        result.m34 = translation.z;
        return result;
    }

    public static Matrix4f scale(Vector3f scale) {
        Matrix4f result = Matrix4f.identity();
        result.m11 = scale.x;
        result.m22 = scale.y;
        result.m33 = scale.z;
        return result;
    }

    public Matrix4f minus(Matrix4f m) {
        return new Matrix4f(m11-m.m11, m12-m.m12, m13-m.m13, m14-m.m14,
                            m21-m.m21, m22-m.m22, m13-m.m23, m24-m.m24,
                            m31-m.m31, m32-m.m32, m13-m.m33, m34-m.m34,
                            m41-m.m41, m42-m.m42, m13-m.m43, m44-m.m44);
    }

    public Matrix4f plus(Matrix4f m) {
        return new Matrix4f(m11+m.m11, m12+m.m12, m13+m.m13, m14+m.m14,
                            m21+m.m21, m22+m.m22, m13+m.m23, m24+m.m24,
                            m31+m.m31, m32+m.m32, m13+m.m33, m34+m.m34,
                            m41+m.m41, m42+m.m42, m13+m.m43, m44+m.m44);
    }

    public Matrix4f multiply(Matrix4f m) {
        Vector4f r1 = new Vector4f(m11, m12, m13, m14);
        Vector4f r2 = new Vector4f(m21, m22, m23, m24);
        Vector4f r3 = new Vector4f(m31, m32, m33, m34);
        Vector4f r4 = new Vector4f(m41, m42, m43, m44);

        Vector4f c1 = new Vector4f(m.m11, m.m21, m.m31, m.m41);
        Vector4f c2 = new Vector4f(m.m12, m.m22, m.m32, m.m42);
        Vector4f c3 = new Vector4f(m.m13, m.m23, m.m33, m.m43);
        Vector4f c4 = new Vector4f(m.m14, m.m24, m.m34, m.m44);

        return new Matrix4f(r1.dot(c1), r1.dot(c2), r1.dot(c3), r1.dot(c4), 
                            r2.dot(c1), r2.dot(c2), r2.dot(c3), r2.dot(c4),
                            r3.dot(c1), r3.dot(c2), r3.dot(c3), r3.dot(c4),
                            r4.dot(c1), r4.dot(c2), r4.dot(c3), r4.dot(c4));
    }

    public Vector4f multiply(Vector4f v) {
        return new Vector4f(m11*v.x+m12*v.y+m13*v.z+m14*v.w, 
                            m21*v.x+m22*v.y+m23*v.z+m24*v.w, 
                            m31*v.x+m32*v.y+m33*v.z+m34*v.w, 
                            m41*v.x+m42*v.y+m43*v.z+m44*v.w);
    }

    public static Matrix4f lookAt(Vector3f eye, Vector3f target, Vector3f up) {

        Vector3f direction = eye.minus(target).normalize();    
        Vector3f right = direction.cross(up).normalize();
        Vector3f camUp = right.cross(direction);

        direction = direction.negate();

        Matrix4f viewMatrix = new Matrix4f(
                right.x, right.y, right.z, -right.dot(eye),
                camUp.x, camUp.y, camUp.z, -camUp.dot(eye),
                direction.x, direction.y, direction.z, -direction.dot(eye),
                0, 0, 0, 1);

        return viewMatrix;
    }

    public String toString() {
        return  "" +    this.m11 + " " + this.m12 + " " + this.m13 + " " + this.m14 + "\n" + 
                        this.m21 + " " + this.m22 + " " + this.m23 + " " + this.m24 + "\n" + 
                        this.m31 + " " + this.m32 + " " + this.m33 + " " + this.m34 + "\n" + 
                        this.m41 + " " + this.m42 + " " + this.m43 + " " + this.m44 + "\n";
    }

    public FloatBuffer toFloatBuffer() {
        return BufferUtils.createFloatBuffer(ArrayUtils.toFloatArray(this.toRawTypes()));
    }
}

还有我的相机类别:


import com.engine.componentsystem.Component;
import com.engine.eventsystem.eventtypes.engineevents.UpdateEvent;
import com.engine.eventsystem.eventtypes.mouseevents.MouseMovedEvent;
import com.engine.eventsystem.eventtypes.mouseevents.MousePressedEvent;
import com.engine.eventsystem.eventtypes.mouseevents.MouseReleasedEvent;
import com.engine.eventsystem.eventtypes.mouseevents.MouseScrolledEvent;
import com.engine.toolbox.math.matrix.Matrix4f;
import com.engine.toolbox.math.quaternion.Quaternion;
import com.engine.toolbox.math.vectors.Vector3f;

public class CameraComponent extends Component{

    private boolean right = false, left = false;
    private float mouseX = 0, mouseY = 0, oldMouseX, oldMouseY;

    private float distanceFromTarget = -5, angleAroundTarget;

    private Vector3f position = new Vector3f(0.0f), rotation = new Vector3f(0.0f), target;

    public CameraComponent() {}

    public Vector3f getPosition() {
        return position;
    }

    public Vector3f getRotation() {
        return rotation;
    }

    public Vector3f getTarget() {
        return target;
    }

    private float calculateHorizontalDistance() {
        return (float) (this.distanceFromTarget*Math.cos(Math.toRadians(this.rotation.x)));
    }

    private float calculateVerticalDistance() {
        return (float) (this.distanceFromTarget*Math.sin(Math.toRadians(this.rotation.x)));
    }

    public Matrix4f getViewMatrix() {
        Matrix4f result = Matrix4f.identity();
        Matrix4f rotationM = Quaternion.fromEuler(rotation).toMatrix();
        Matrix4f translation = Matrix4f.translation(position.negate());
        Matrix4f origin = Matrix4f.translation(target);
        Matrix4f Iorigin = Matrix4f.translation(target.negate());

        System.out.println("target: " + target);
        System.out.println("position: " + position);
        System.out.println("rotation: " + rotation);

        result = result.multiply(translation);
        result = result.multiply(origin);
        result = result.multiply(rotationM);
        result = result.multiply(Iorigin);
        return result;
    }

    @Override
    public void onAttach() {
        this.target = ((PositionComponent) parent.getComponent(PositionComponent.class)).getPosition();
    }

    @Override
    public boolean onMouseScrolled(MouseScrolledEvent event) {
        this.distanceFromTarget += event.getyOffset()*0.7f;
        return false;
    }

    @Override
    public boolean onMousePressed(MousePressedEvent event) {
        if(event.getButton() == 0 && event.getMods() == 1) {
            left = true;
        }
        if(event.getButton() == 1 && event.getMods() == 1) {
            right = true;
        }
        return false;
    }

    @Override
    public boolean onMouseReleased(MouseReleasedEvent event) {
        if(event.getButton() == 0) {
            left = false;
        }
        if(event.getButton() == 1) {
            right = false;
        }
        return false;
    }

    @Override
    public boolean onMouseMoved(MouseMovedEvent event) {
        oldMouseX = mouseX;
        oldMouseY = mouseY;
        mouseX = event.getX();
        mouseY = event.getY();
        if(left) {
            this.angleAroundTarget -= (mouseX-oldMouseX)*0.01f;
        }
        if(right) {
            this.rotation.x -= (mouseY-oldMouseY)*0.01f;
        }
        return false;
    }

    @Override
    public void onUpdate(UpdateEvent event) {
        this.target = ((PositionComponent) parent.getComponent(PositionComponent.class)).getPosition();
        float horizantalDistance = calculateHorizontalDistance();
        float verticalDistance = calculateVerticalDistance();
        float theta = ((RotationComponent) parent.getComponent(RotationComponent.class)).getRotation().y + angleAroundTarget;

        float xOffset = (float) (horizantalDistance*Math.sin(Math.toRadians(theta)));
        float zOffset = (float) (horizantalDistance*Math.cos(Math.toRadians(theta)));

        this.position.x = target.x - xOffset;
        this.position.y = target.y + verticalDistance;
        this.position.z = target.z - zOffset;

        this.rotation.y = (float) (Math.toRadians(180.0f) - theta);
    }

}

最佳答案

所以我设法解决了我的问题,

  1. 更改为矩阵乘法顺序,先旋转,然后移动(我还在 Matrix4f 类中添加了新函数,以使其更容易)
result = result.rotate((float) -this.rotation.x, new Vector3f(1f, 0f, 0f));
result = result.rotate((float) this.rotation.y, new Vector3f(0f, 1f, 0f));
result = result.translate(position.negate());
  • 修复了四元数类中所犯的错误,该错误破坏了旋转(我忘记了将度数转换为弧度)
  • roll = (float) Math.toRadians(roll);
    pitch = (float) Math.toRadians(pitch);
    yaw = (float) Math.toRadians(yaw);
    

    改进的相机类(我添加了 float 平滑以消除运动中的所有抖动):

    package com.assec.engine.componentsystem.components;
    
    import com.assec.engine.componentsystem.Component;
    import com.assec.engine.eventsystem.engineevents.UpdateEvent;
    import com.assec.engine.eventsystem.mouseevents.MouseMovedEvent;
    import com.assec.engine.eventsystem.mouseevents.MousePressedEvent;
    import com.assec.engine.eventsystem.mouseevents.MouseReleasedEvent;
    import com.assec.engine.eventsystem.mouseevents.MouseScrolledEvent;
    import com.assec.engine.toolbox.math.SmoothFloat;
    import com.assec.engine.toolbox.math.matrix.Matrix4f;
    import com.assec.engine.toolbox.math.vectors.Vector3f;
    
    public class CameraComponent extends Component{
    
        private boolean right = false, left = false;
        private float mouseX = 0.0f, mouseY = 0.0f, oldMouseX, oldMouseY;
    
        private SmoothFloat distanceFromTarget = new SmoothFloat(-10.0f, 5.0f);
        private SmoothFloat angleAroundTarget = new SmoothFloat(0.0f, 10.0f);
    
        private SmoothFloat pitch = new SmoothFloat(0.0f, 10.0f);
    
        private Vector3f position = new Vector3f(0.0f), rotation = new Vector3f(0.0f), target;
    
        public CameraComponent() {}
    
        public Vector3f getPosition() {
            return position;
        }
    
        public Vector3f getRotation() {
            return rotation;
        }
    
        public Vector3f getTarget() {
            return target;
        }
    
        private float calculateHorizontalDistance() {
            return (float) (this.distanceFromTarget.getActual()*Math.cos(Math.toRadians(this.rotation.x)));
        }
    
        private float calculateVerticalDistance() {
            return (float) (this.distanceFromTarget.getActual()*Math.sin(Math.toRadians(this.rotation.x)));
        }
    
        public Matrix4f getViewMatrix() {
            Matrix4f result = Matrix4f.identity();
    
            this.target = new Vector3f(0.0f);
    
            this.rotation.x = pitch.getActual();
            this.rotation.x%= 360;
    
            float horizontalDistance = calculateHorizontalDistance();
            float verticalDistance = calculateVerticalDistance();
            float theta = angleAroundTarget.getActual();
    
            float xOffset = (float) (horizontalDistance*Math.sin(Math.toRadians(theta)));
            float zOffset = (float) (horizontalDistance*Math.cos(Math.toRadians(theta)));
    
            this.position.x = target.x - xOffset;
            this.position.y = target.y + verticalDistance;
            this.position.z = target.z - zOffset;
    
            this.rotation.y = 360.0f - theta;
            this.rotation.y%= 360;
    
            result = result.rotate((float) -this.rotation.x, new Vector3f(1f, 0f, 0f));
            result = result.rotate((float) this.rotation.y, new Vector3f(0f, 1f, 0f));
            result = result.translate(position.negate());
    
            return result;
        }
    
        @Override
        public void onAttach() {
            this.target = ((PositionComponent) parent.getComponent(PositionComponent.class)).getPosition();
            this.target = new Vector3f(0.0f);
        }
    
        @Override
        public boolean onMouseScrolled(MouseScrolledEvent event) {
            this.distanceFromTarget.increaseTarget(-event.getyOffset()*0.7f);
            return false;
        }
    
        @Override
        public boolean onMousePressed(MousePressedEvent event) {
            if(event.getButton() == 0 && event.getMods() == 1) {
                left = true;
            }
            if(event.getButton() == 1 && event.getMods() == 1) {
                right = true;
            }
            return false;
        }
    
        @Override
        public boolean onMouseReleased(MouseReleasedEvent event) {
            if(event.getButton() == 0) {
                left = false;
            }
            if(event.getButton() == 1) {
                right = false;
            }
            return false;
        }
    
        @Override
        public boolean onMouseMoved(MouseMovedEvent event) {
            oldMouseX = mouseX;
            oldMouseY = mouseY;
            mouseX = (float) event.getX();
            mouseY = (float) event.getY();
            if(left) {
                this.angleAroundTarget.increaseTarget(-(mouseX-oldMouseX)*0.1f);
            }
            if(right) {
                this.pitch.increaseTarget(-(mouseY-oldMouseY)*0.1f);
            }
            return false;
        }
    
        @Override
        public void onUpdate(UpdateEvent event) {
            this.angleAroundTarget.update(0.01f);
            this.distanceFromTarget.update(0.01f);
            this.pitch.update(0.01f);
        }
    
    }
    
    

    改进的Matrix4f类:

    package com.assec.engine.toolbox.math.matrix;
    
    import java.nio.FloatBuffer;
    import java.util.Arrays;
    import java.util.Iterator;
    
    import com.assec.engine.toolbox.ArrayUtils;
    import com.assec.engine.toolbox.BufferUtils;
    import com.assec.engine.toolbox.math.quaternion.Quaternion;
    import com.assec.engine.toolbox.math.vectors.Vector3f;
    import com.assec.engine.toolbox.math.vectors.Vector4f;
    
    public class Matrix4f extends Matrix{
    
        public float m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44;
    
        public Matrix4f(float m11, float m12, float m13, float m14,
                        float m21, float m22, float m23, float m24,
                        float m31, float m32, float m33, float m34,
                        float m41, float m42, float m43, float m44) {
            super(new Float[] { m11, m12, m13, m14, 
                                m21, m22, m23, m24, 
                                m31, m32, m33, m34, 
                                m41, m42, m43, m44});
            this.m11 = m11;
            this.m12 = m12;
            this.m13 = m13;
            this.m14 = m14;
            this.m21 = m21;
            this.m22 = m22;
            this.m23 = m23;
            this.m24 = m24;
            this.m31 = m31;
            this.m32 = m32;
            this.m33 = m33;
            this.m34 = m34;
            this.m41 = m41;
            this.m42 = m42;
            this.m43 = m43;
            this.m44 = m44;
    
        }
    
        @Override
        public Iterator<Float> iterator() {
            return Arrays.asList(this.toRawTypes()).iterator();
        }
    
        public Matrix4f invert() {
            Matrix4f matrixOfMinors =   new Matrix4f(   new Matrix3f(   m22, m23, m24,
                                                                        m32, m33, m34,
                                                                        m42, m43, m44).getDeterminant(), new Matrix3f(  m21, m23, m24,
                                                                                                                        m31, m33, m34,
                                                                                                                        m41, m43, m44).getDeterminant(), new Matrix3f(  m21, m22, m24,
                                                                                                                                                                        m31, m32, m34,
                                                                                                                                                                        m41, m42, m44).getDeterminant(), new Matrix3f(  m21, m22, m23,
                                                                                                                                                                                                                        m31, m32, m33,
                                                                                                                                                                                                                        m41, m42, m43).getDeterminant(),
                                                        new Matrix3f(   m12, m13, m14,
                                                                        m32, m33, m34,
                                                                        m42, m43, m44).getDeterminant(), new Matrix3f(  m11, m13, m14,
                                                                                                                        m31, m33, m34,
                                                                                                                        m41, m43, m44).getDeterminant(), new Matrix3f(  m11, m12, m14,
                                                                                                                                                                        m31, m32, m34,
                                                                                                                                                                        m41, m42, m44).getDeterminant(), new Matrix3f(  m11, m12, m23,
                                                                                                                                                                                                                        m31, m32, m33,
                                                                                                                                                                                                                        m41, m42, m43).getDeterminant(),
                                                        new Matrix3f(   m12, m13, m14,
                                                                        m22, m23, m24,
                                                                        m42, m43, m44).getDeterminant(), new Matrix3f(  m11, m13, m14,
                                                                                                                        m21, m23, m24,
                                                                                                                        m41, m43, m44).getDeterminant(), new Matrix3f(  m11, m12, m14,
                                                                                                                                                                        m21, m22, m24,
                                                                                                                                                                        m41, m42, m44).getDeterminant(), new Matrix3f(  m11, m12, m23,
                                                                                                                                                                                                                        m21, m22, m23,
                                                                                                                                                                                                                        m41, m42, m43).getDeterminant(),
                                                        new Matrix3f(   m12, m13, m14,
                                                                        m22, m23, m24,
                                                                        m32, m33, m34).getDeterminant(), new Matrix3f(  m11, m13, m14,
                                                                                                                        m21, m23, m24,
                                                                                                                        m31, m33, m34).getDeterminant(), new Matrix3f(  m11, m12, m14,
                                                                                                                                                                        m21, m22, m24,
                                                                                                                                                                        m31, m32, m34).getDeterminant(), new Matrix3f(  m11, m12, m23,
                                                                                                                                                                                                                        m21, m22, m23,
                                                                                                                                                                                                                        m31, m32, m33).getDeterminant());
            matrixOfMinors.m12 = -m12;
            matrixOfMinors.m14 = -m14;
    
            matrixOfMinors.m21 = -m21;
            matrixOfMinors.m23 = -m23;
    
            matrixOfMinors.m32 = -m32;
            matrixOfMinors.m34 = -m34;
    
            matrixOfMinors.m41 = -m41;
            matrixOfMinors.m43 = -m43;
    
            float temp = 0;
    
            temp = matrixOfMinors.m12;
            matrixOfMinors.m12 = matrixOfMinors.m21;
            matrixOfMinors.m21 = temp;
    
            temp = matrixOfMinors.m13;
            matrixOfMinors.m13= matrixOfMinors.m31;
            matrixOfMinors.m31 = temp;
    
            temp = matrixOfMinors.m23;
            matrixOfMinors.m23 = matrixOfMinors.m32;
            matrixOfMinors.m32 = temp;
    
            temp = matrixOfMinors.m14;
            matrixOfMinors.m14 = matrixOfMinors.m41;
            matrixOfMinors.m41 = temp;
    
            temp = matrixOfMinors.m24;
            matrixOfMinors.m24 = matrixOfMinors.m42;
            matrixOfMinors.m42 = temp;
    
            temp = matrixOfMinors.m34;
            matrixOfMinors.m34 = matrixOfMinors.m43;
            matrixOfMinors.m43 = temp;
    
            float d = this.getDeterminant();
            return new Matrix4f(matrixOfMinors.m11/d, matrixOfMinors.m12/d, matrixOfMinors.m13/d, matrixOfMinors.m14/d,
                                matrixOfMinors.m21/d, matrixOfMinors.m22/d, matrixOfMinors.m23/d, matrixOfMinors.m24/d,
                                matrixOfMinors.m31/d, matrixOfMinors.m32/d, matrixOfMinors.m33/d, matrixOfMinors.m34/d,
                                matrixOfMinors.m41/d, matrixOfMinors.m42/d, matrixOfMinors.m43/d, matrixOfMinors.m44/d);
        }
    
        public float getDeterminant() {
            return  m11*(new Matrix3f(  m22, m23, m24,
                                        m32, m33, m34,
                                        m42, m43, m44).getDeterminant()) - 
                    m12*(new Matrix3f(  m21, m23, m24,
                                        m31, m33, m34,
                                        m41, m43, m44).getDeterminant()) + 
                    m13*(new Matrix3f(  m21, m22, m24,
                                        m31, m32, m34,
                                        m41, m42, m44).getDeterminant()) - 
                    m14*(new Matrix3f(  m21, m22, m23,
                                        m31, m32, m33,
                                        m41, m42, m43).getDeterminant());
        }
    
        public static Matrix4f identity() {
            return new Matrix4f(1, 0, 0, 0, 
                                0, 1, 0, 0, 
                                0, 0, 1, 0, 
                                0, 0, 0, 1);
        }
    
        public static Matrix4f perspective(float aspectRatio, float viewAngle, float nearPlane, float farPlane) {
            return new Matrix4f((float) (1/(aspectRatio*Math.tan((viewAngle/2)))),  0,                                      0,                                          0,
                                0,                                                  (float) (1/(Math.tan((viewAngle/2)))),  0,                                          0,
                                0,                                                  0,                                      -((farPlane+nearPlane)/(farPlane-nearPlane)), -(2*farPlane*nearPlane)/(farPlane-nearPlane),
                                0,                                                  0,                                      -1,                                         1);
        }
    
        public static Matrix4f translation(Vector3f translation) {
            Matrix4f result = Matrix4f.identity();
            result.m14 = translation.x;
            result.m24 = translation.y;
            result.m34 = translation.z;
            return result;
        }
    
        public static Matrix4f scale(Vector3f scale) {
            Matrix4f result = Matrix4f.identity();
            result.m11 = scale.x;
            result.m22 = scale.y;
            result.m33 = scale.z;
            return result;
        }
    
        public Matrix4f minus(Matrix4f m) {
            return new Matrix4f(m11-m.m11, m12-m.m12, m13-m.m13, m14-m.m14,
                                m21-m.m21, m22-m.m22, m13-m.m23, m24-m.m24,
                                m31-m.m31, m32-m.m32, m13-m.m33, m34-m.m34,
                                m41-m.m41, m42-m.m42, m13-m.m43, m44-m.m44);
        }
    
        public Matrix4f plus(Matrix4f m) {
            return new Matrix4f(m11+m.m11, m12+m.m12, m13+m.m13, m14+m.m14,
                                m21+m.m21, m22+m.m22, m13+m.m23, m24+m.m24,
                                m31+m.m31, m32+m.m32, m13+m.m33, m34+m.m34,
                                m41+m.m41, m42+m.m42, m13+m.m43, m44+m.m44);
        }
    
        public Matrix4f multiply(Matrix4f m) {
            Vector4f r1 = new Vector4f(m11, m12, m13, m14);
            Vector4f r2 = new Vector4f(m21, m22, m23, m24);
            Vector4f r3 = new Vector4f(m31, m32, m33, m34);
            Vector4f r4 = new Vector4f(m41, m42, m43, m44);
    
            Vector4f c1 = new Vector4f(m.m11, m.m21, m.m31, m.m41);
            Vector4f c2 = new Vector4f(m.m12, m.m22, m.m32, m.m42);
            Vector4f c3 = new Vector4f(m.m13, m.m23, m.m33, m.m43);
            Vector4f c4 = new Vector4f(m.m14, m.m24, m.m34, m.m44);
    
            return new Matrix4f(r1.dot(c1), r1.dot(c2), r1.dot(c3), r1.dot(c4), 
                                r2.dot(c1), r2.dot(c2), r2.dot(c3), r2.dot(c4),
                                r3.dot(c1), r3.dot(c2), r3.dot(c3), r3.dot(c4),
                                r4.dot(c1), r4.dot(c2), r4.dot(c3), r4.dot(c4));
        }
    
        public Vector4f multiply(Vector4f v) {
            return new Vector4f(m11*v.x+m12*v.y+m13*v.z+m14*v.w, 
                                m21*v.x+m22*v.y+m23*v.z+m24*v.w, 
                                m31*v.x+m32*v.y+m33*v.z+m34*v.w, 
                                m41*v.x+m42*v.y+m43*v.z+m44*v.w);
        }
    
        public Matrix4f rotate(float angle, Vector3f axis) {
            Matrix4f rotation = Quaternion.fromEuler(axis.normalized().scaled(angle)).toMatrix();
            return this.multiply(rotation);
        }
    
        public Matrix4f translate(Vector3f translation) {
            Matrix4f translate = Matrix4f.translation(translation);
            return this.multiply(translate);
        }
    
        public static Matrix4f lookAt(Vector3f eye, Vector3f target, Vector3f up) {
    
            Vector3f direction = eye.minus(target).normalized();    
            Vector3f right = direction.cross(up).normalized();
            Vector3f camUp = right.cross(direction);
    
            direction = direction.negate();
    
            Matrix4f viewMatrix = new Matrix4f(
                    right.x, right.y, right.z, -right.dot(eye),
                    camUp.x, camUp.y, camUp.z, -camUp.dot(eye),
                    direction.x, direction.y, direction.z, -direction.dot(eye),
                    0.0f, 0.0f, 0.0f, 1.0f);
            return viewMatrix;
        }
    
        public String toString() {
            return  "" +    this.m11 + " " + this.m12 + " " + this.m13 + " " + this.m14 + "\n" + 
                            this.m21 + " " + this.m22 + " " + this.m23 + " " + this.m24 + "\n" + 
                            this.m31 + " " + this.m32 + " " + this.m33 + " " + this.m34 + "\n" + 
                            this.m41 + " " + this.m42 + " " + this.m43 + " " + this.m44 + "\n";
        }
    
        public FloatBuffer toFloatBuffer() {
            return BufferUtils.createFloatBuffer(ArrayUtils.toFloatArray(this.toRawTypes()));
        }
    }
    
    

    关于java - 使用 lwjgl 实现第三人称相机,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59912629/

    相关文章:

    java - 使用 TransferHandler 拖放图像

    java - 如何使用Contains或matches返回true?

    c++ - 更改对象的原点使其沿不同的轴移动

    java - LWJGL 旋转物体

    java - WebSocket 握手期间出错(意外响应代码 : 400)

    java文件选择器

    c++ - 创建一个创建全屏覆盖的程序

    linux - glXChooseFBConfig 无法选择支持的配置

    java - 安装在 Canvas 上的 LWJGL 显示器无法生成鼠标事件

    java - glCallList 与 slick-util