package loon.action.camera;
import loon.geom.Matrix4;
import loon.geom.Quaternion;
import loon.geom.Transforms;
import loon.geom.Vector3f;
public class FPSCamera extends EmptyCamera {
private static final float ANGLE_LIMIT_X = 60;
private Quaternion rotation;
private Vector3f position;
private Vector3f forward;
private Vector3f right;
private Vector3f up;
private float angleX;
public FPSCamera() {
this(70, 1f, 0.01f, 100);
}
public FPSCamera(float fovy, float aspect, float zNear, float zFar) {
super();
_viewMatrix4 = Transforms.createPerspective(fovy, aspect, zNear, zFar);
position = new Vector3f(0, 0, 1);
rotation = new Quaternion();
forward = new Vector3f();
right = new Vector3f();
up = new Vector3f();
}
public FPSCamera lookAt(Vector3f point) {
return lookAt(point, getUp().normalizeSelf());
}
public FPSCamera lookAt(Vector3f point, Vector3f up) {
rotation = Transforms.createLookAtQuaternion(position, point, up,
rotation);
return this;
}
public Vector3f getUp() {
return rotation.multiply(Vector3f.AXIS_Y(), up);
}
public FPSCamera lookAt(Vector3f position, Vector3f point, Vector3f up) {
return setPosition(position).lookAt(point, up);
}
public FPSCamera moveForward(float amount) {
return move(getForward(), amount);
}
public FPSCamera move(Vector3f dir, float amount) {
position.addSelf(dir.normalize().scale(amount));
return this;
}
public Vector3f getForward() {
return rotation.multiply(forward.set(Vector3f.AXIS_Z()).negateSelf(),
forward);
}
public FPSCamera moveBackward(float amount) {
return move(getForward().negate(), amount);
}
public FPSCamera moveLeft(float amount) {
return move(getRight().negate(), amount);
}
public Vector3f getRight() {
return rotation.multiply(Vector3f.AXIS_X(), right);
}
public FPSCamera moveRight(float amount) {
return move(getRight(), amount);
}
public FPSCamera moveUp(float amount) {
return move(getUp(), amount);
}
public FPSCamera moveDown(float amount) {
return move(getUp().negateSelf(), amount);
}
public FPSCamera rotateX(float angle) {
angleX += angle;
if (angleX < -ANGLE_LIMIT_X || angleX > ANGLE_LIMIT_X) {
angleX -= angle;
return this;
}
Quaternion tempQuat = Quaternion.TMP();
Quaternion xRot = tempQuat.set(Vector3f.AXIS_X(), angle);
rotation.multiplySelf(xRot);
return this;
}
public FPSCamera rotateY(float angle) {
Quaternion tempQuat = Quaternion.TMP();
Quaternion yRot = tempQuat.set(Vector3f.AXIS_Y(), angle);
rotation.set(yRot.multiplySelf(rotation));
return this;
}
public FPSCamera lerp(FPSCamera p, float alpha) {
position.lerpSelf(p.position, alpha);
rotation.lerpSelf(p.rotation, alpha);
return this;
}
public FPSCamera slerp(FPSCamera p, float alpha) {
position.lerpSelf(p.position, alpha);
rotation.slerpSelf(p.rotation, alpha);
return this;
}
public FPSCamera initProjection(float fovy, float aspect, float zNear,
float zFar) {
Transforms.createPerspective(fovy, aspect, zNear, zFar, _projMatrix4);
return this;
}
public FPSCamera initProjection(float width, float height) {
return initProjection(0, width, height, 0, 0.01f, 100f);
}
public FPSCamera initProjection(float left, float right, float bottom,
float top, float zNear, float zFar) {
Transforms.createFrustum(left, right, bottom, top, zNear, zFar,
_projMatrix4);
return this;
}
@Override
public void setup() {
super.setup();
Vector3f tempVec3 = Vector3f.TMP();
Matrix4 tempMat4 = Matrix4.TMP();
Quaternion tempQuat = Quaternion.TMP();
_viewMatrix4
.idt()
.mul(Transforms.createRotation(tempQuat.set(rotation)
.invertSelf(), tempMat4))
.mul(Transforms.createTranslation(tempVec3.set(position)
.negateSelf(), tempMat4));
}
public Vector3f getPosition() {
return position;
}
public FPSCamera setPosition(Vector3f position) {
this.position.set(position);
return this;
}
public Quaternion getRotation() {
return rotation;
}
public FPSCamera setRotation(Quaternion rotation) {
this.rotation.set(rotation);
return this;
}
}