package net.krazyweb.opengl;
import net.krazyweb.renderer.Camera;
import net.krazyweb.renderer.MatrixMath;
import org.lwjgl.util.vector.Matrix4f;
import org.lwjgl.util.vector.Vector3f;
import org.lwjgl.util.vector.Vector4f;
public class OpenGLCamera implements Camera {
public Vector3f position;
private float horizontalAngle;
private float verticalAngle;
private int width, height;
private float maxVerticalAngle = (float) Math.toRadians(89.0f);
private float fullRotation = (float) Math.toRadians(360.0f);
private float fieldOfView;
private float aspect;
private float near;
private float far;
private float yScale;
private float xScale;
private float frustum_length;
public OpenGLCamera(Vector3f pos, int w, int h, float fov, float near, float far) {
position = pos;
horizontalAngle = 0;
verticalAngle = 0;
width = w;
height = h;
fieldOfView = fov;
aspect = (float) width / (float) height;
this.near = near;
this.far = far;
yScale = (float) (1.0f / Math.tan(Math.toRadians(fieldOfView / 2f)));
xScale = yScale / aspect;
frustum_length = far - near;
}
public Matrix4f viewMatrix() {
Matrix4f camera = projection();
Matrix4f.mul(camera, orientation(), camera);
Vector3f negPosition = new Vector3f();
position.negate(negPosition);
camera.translate(negPosition);
return camera;
}
public Matrix4f orthoMatrix() {
float left = 0.0f + position.x;
float right = width + position.x;
float bottom = 0.0f + position.y;
float top = height + position.y;
Matrix4f camera = new Matrix4f();
camera.m00 = 2.0f / (right - left);
camera.m11 = 2.0f / (top - bottom);
camera.m22 = -2.0f / (far - near);
camera.m30 = -((right + left) / (right - left));
camera.m31 = -((top + bottom) / (top - bottom));
camera.m32 = -((far + near) / (far - near));
camera.m33 = 1.0f;
return camera;
}
public void offsetPosition(Vector3f displacement) {
Vector3f.add(position, displacement, position);
}
public void offsetOrientation(float upAngle, float rightAngle) {
horizontalAngle += rightAngle;
while(horizontalAngle > fullRotation) horizontalAngle -= fullRotation;
while(horizontalAngle < 0.0f) horizontalAngle += fullRotation;
verticalAngle += upAngle;
if (verticalAngle > maxVerticalAngle) verticalAngle = maxVerticalAngle;
if (verticalAngle < -maxVerticalAngle) verticalAngle = -maxVerticalAngle;
}
private Matrix4f projection() {
Matrix4f projection = new Matrix4f();
projection.m00 = xScale;
projection.m11 = yScale;
projection.m22 = -((far + near) / frustum_length);
projection.m23 = -1;
projection.m32 = -((2 * near * far) / frustum_length);
return projection;
}
private Matrix4f orientation() {
Matrix4f orientation = new Matrix4f();
orientation.rotate(verticalAngle, new Vector3f(1, 0, 0));
orientation.rotate(horizontalAngle, new Vector3f(0, 1, 0));
return orientation;
}
public Vector3f up() {
Vector4f up = MatrixMath.multiply((Matrix4f) orientation().invert(), new Vector4f(0, 1, 0, 1));
return new Vector3f(up.x, up.y, up.z);
}
public Vector3f forward() {
Vector4f forward = MatrixMath.multiply((Matrix4f) orientation().invert(), new Vector4f(0, 0, -1, 1));
return new Vector3f(forward.x, forward.y, forward.z);
}
public Vector3f right() {
Vector4f right = MatrixMath.multiply((Matrix4f) orientation().invert(), new Vector4f(1, 0, 0, 1));
return new Vector3f(right.x, right.y, right.z);
}
@Override
public void setPosition(Vector3f displacement) {
position = displacement;
}
@Override
public void setOrientation(float upAngle, float rightAngle) {
horizontalAngle = rightAngle;
while(horizontalAngle > fullRotation) horizontalAngle -= fullRotation;
while(horizontalAngle < 0.0f) horizontalAngle += fullRotation;
verticalAngle = upAngle;
if (verticalAngle > maxVerticalAngle) verticalAngle = maxVerticalAngle;
if (verticalAngle < -maxVerticalAngle) verticalAngle = -maxVerticalAngle;
}
}