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