package com.javamarcher.systems; import org.joml.Matrix4f; import org.joml.Vector3f; import org.joml.Vector4f; import com.javamarcher.ecs.component.CameraTransform; import com.javamarcher.window.MainWindow; public class Camera { private static final Vector3f RIGHT = new Vector3f(1, 0, 0); private static final Vector3f UP = new Vector3f(0, 1, 0); private static final Vector3f FORWARD = new Vector3f(0, 0, 1); private final CameraTransform transform = new CameraTransform(); private final Matrix4f viewMatrix = new Matrix4f(); private final Matrix4f projectionMatrix = new Matrix4f(); public float farPlane = 100f; public float nearPlane = 0.1f; public float fov = 60f; private final Vector3f lookAtPosition = new Vector3f(); public Camera() { viewMatrix.identity(); projectionMatrix.identity(); calculateProjectionMatrix(); } public void update(double dt) { calculateViewMatrix(); } public void calculateViewMatrix() { viewMatrix.identity(); lookAtPosition.set(transform.position).add(transform.forward); viewMatrix.lookAt( transform.position.x, transform.position.y, transform.position.z, // Cam Position lookAtPosition.x, lookAtPosition.y, lookAtPosition.z, // Target transform.up.x, transform.up.y, transform.up.z); // Up } public void calculateProjectionMatrix() { projectionMatrix.identity(); projectionMatrix.perspective((float) Math.toRadians(fov), getAspectRatio(), nearPlane, farPlane); } /** * Returns the frustum corner vectors in this format: <br><br> * * Top left corner: row: 1, index: 1<br> * Top Right corner: row: 0, index: 0<br> * Bottom right corner: row: 3, index: 3<br> * Bottom left corner: row: 2, index: 2<br> */ public Matrix4f GetFrustumCorners() { final Matrix4f corners = new Matrix4f(); corners.identity(); final float halfFov = fov * 0.5f; final float tanFov = (float) Math.tan(Math.toRadians(halfFov)); final Vector3f toRight = new Vector3f(RIGHT).mul(tanFov).mul(getAspectRatio()); final Vector3f toTop = new Vector3f(UP).mul(tanFov).negate(); final Vector3f topLeft = new Vector3f(FORWARD).sub(toRight).add(toTop).negate().normalize(); final Vector3f topRight = new Vector3f(FORWARD).add(toRight).add(toTop).negate().normalize(); final Vector3f bottomRight = new Vector3f(FORWARD).add(toRight).sub(toTop).negate().normalize(); final Vector3f bottomLeft = new Vector3f(FORWARD).sub(toRight).sub(toTop).negate().normalize(); corners.setRow(1, new Vector4f(topLeft, 0)); corners.setRow(0, new Vector4f(topRight, 0)); corners.setRow(3, new Vector4f(bottomRight, 0)); corners.setRow(2, new Vector4f(bottomLeft, 0)); return corners; } private float getAspectRatio() { return (float) MainWindow.WIDTH / (float) MainWindow.HEIGHT; } public CameraTransform getTransform() { return transform; } public Matrix4f getViewMatrix() { return viewMatrix; } public Matrix4f getProjectionMatrix() { return projectionMatrix; } }