ace-of-shades-2/client/src/main/java/nl/andrewl/aos2_client/Camera.java

143 lines
3.9 KiB
Java

package nl.andrewl.aos2_client;
import nl.andrewl.aos_core.MathUtils;
import nl.andrewl.aos_core.model.Player;
import org.joml.Matrix4f;
import org.joml.Vector2f;
import org.joml.Vector3f;
/**
* Represents the player camera in the game world.
*/
public class Camera {
public static final Vector3f UP = new Vector3f(0, 1, 0);
public static final Vector3f DOWN = new Vector3f(0, -1, 0);
public static final Vector3f RIGHT = new Vector3f(1, 0, 0);
public static final Vector3f LEFT = new Vector3f(-1, 0, 0);
public static final Vector3f FORWARD = new Vector3f(0, 0, -1);
public static final Vector3f BACKWARD = new Vector3f(0, 0, 1);
/**
* The x, y, and z position of the camera in the world.
*/
private final Vector3f position;
private final Vector3f velocity;
/**
* The camera's angular orientation. X refers to the rotation about the
* vertical axis, while Y refers to the rotation about the horizontal axis.
* <p>
* The Y axis orientation is limited to between 0 and PI, with 0
* being looking straight down, and PI looking straight up.
* </p>
* <p>
* The X axis orientation is limited to between 0 and 2 PI, with 0
* being looking at the - Z axis.
* </p>
*/
private final Vector2f orientation;
private final Matrix4f viewTransform;
private final float[] viewTransformData = new float[16];
public Camera() {
this.position = new Vector3f();
this.velocity = new Vector3f();
this.orientation = new Vector2f(0, (float) (Math.PI / 2));
this.viewTransform = new Matrix4f();
}
public void setToPlayer(Player p) {
position.set(p.getEyePosition());
velocity.set(p.getVelocity());
}
public void setToPlayerScopeView(Player p) {
Vector3f pos = new Vector3f();
Matrix4f tx = p.getHeldItemTransform();
tx.transformPosition(pos);
position.set(pos);
velocity.set(p.getVelocity());
}
public void setOrientationToPlayer(Player p) {
orientation.set(p.getOrientation());
}
public Matrix4f getViewTransform() {
return viewTransform;
}
public float[] getViewTransformData() {
return viewTransformData;
}
public Vector2f getOrientation() {
return orientation;
}
public Vector3f getPosition() {
return position;
}
public Vector3f getVelocity() {
return velocity;
}
public void setPosition(float x, float y, float z) {
if (position.x != x || position.y != y || position.z != z) {
position.set(x, y, z);
updateViewTransform();
}
}
public void setVelocity(float x, float y, float z) {
velocity.set(x, y, z);
}
public void setOrientation(float x, float y) {
orientation.set(
MathUtils.normalize(x, 0, Math.PI * 2),
MathUtils.clamp(y, 0, (float) (Math.PI))
);
updateViewTransform();
}
public void setOrientationDegrees(float x, float y) {
setOrientation((float) Math.toRadians(x), (float) Math.toRadians(y));
}
public void interpolatePosition(float dt) {
Vector3f movement = new Vector3f(velocity).mul(dt);
position.add(movement);
updateViewTransform();
}
public void updateViewTransform() {
viewTransform.identity();
viewTransform.rotate(-orientation.y + ((float) Math.PI / 2), RIGHT);
viewTransform.rotate(-orientation.x, UP);
viewTransform.translate(-position.x, -position.y, -position.z);
viewTransform.get(viewTransformData);
}
public Vector3f getViewVector() {
float y = (float) (orientation.y + Math.PI / 2);
return new Vector3f(
(float) (Math.sin(orientation.x) * Math.cos(y)),
(float) -Math.sin(y),
(float) (Math.cos(orientation.x) * Math.cos(y))
).normalize();
}
public void move(Vector3f relativeMotion) {
Vector3f actualMotion = new Vector3f(relativeMotion).mul(0.1f);
Matrix4f moveTransform = new Matrix4f();
moveTransform.rotate(orientation.x, UP);
moveTransform.transformDirection(actualMotion);
position.add(actualMotion);
updateViewTransform();
// System.out.printf("Position: x=%.2f, y=%.2f, z=%.2f%n", position.x, position.y, position.z);
}
}