SimpleJavaEngine/src/main/java/speiger/src/coreengine/rendering/input/camera/Camera.java

207 lines
5.2 KiB
Java

package speiger.src.coreengine.rendering.input.camera;
import java.text.DecimalFormat;
import java.util.List;
import java.util.function.Consumer;
import speiger.src.collections.objects.lists.ObjectArrayList;
import speiger.src.coreengine.math.MathUtils;
import speiger.src.coreengine.math.vector.floats.Vec2f;
import speiger.src.coreengine.math.vector.floats.Vec3f;
import speiger.src.coreengine.math.vector.ints.Vec2i;
import speiger.src.coreengine.math.vector.ints.Vec3i;
import speiger.src.coreengine.math.vector.matrix.Matrix4f;
import speiger.src.coreengine.rendering.input.window.Window;
public class Camera
{
static final Vec3f X_ROTATION = Vec3f.of(1, 0, 0);
static final Vec3f Y_ROTATION = Vec3f.of(0, 1, 0);
Vec3f position = Vec3f.mutable();
Vec3f lastPosition = Vec3f.mutable();
Vec2f rotation = Vec2f.mutable();
Vec2f lastRotation = Vec2f.mutable();
boolean moved = false;
boolean rotated = false;
Matrix4f viewMatrix = createViewMatrix();
Matrix4f invertedViewMatrix = new Matrix4f(viewMatrix).invert();
ICameraController controller;
Frustrum frustrum;
boolean changed = false;
List<Consumer<Camera>> listeners = new ObjectArrayList<>();
public Camera(Window window)
{
frustrum = new Frustrum(this);
window.addListener(frustrum, false);
setController(controller);
}
public void setController(ICameraController cont)
{
cont = cont == null ? DefaultCameraController.INSTANCE : cont;
if(controller != null)
{
controller.onRemoved(this);
}
controller = cont;
cont.onAdded(this);
}
public void addListener(Consumer<Camera> listner)
{
listeners.add(listner);
}
public void onInput()
{
controller.onInputUpdate(this);
}
public void update(float particalTicks)
{
controller.updateCamera(this, particalTicks);
moved = !lastPosition.equals(position);
rotated = !rotation.equals(lastRotation);
if(rotated || moved)
{
viewMatrix = createViewMatrix();
invertedViewMatrix.load(viewMatrix).invert();
lastPosition.set(position);
lastRotation.set(rotation);
frustrum.update();
changed = true;
for(Consumer<Camera> listener : listeners)
{
listener.accept(this);
}
}
else
{
changed = false;
}
}
public Matrix4f createViewMatrix()
{
Matrix4f viewMatrix = new Matrix4f();
viewMatrix.rotate((float)Math.toRadians(rotation.getX()), X_ROTATION);
viewMatrix.rotate((float)Math.toRadians(rotation.getY()), Y_ROTATION);
viewMatrix.translate(position.copy().invert());
return viewMatrix;
}
public boolean isChanged()
{
return changed;
}
public boolean wasMoved()
{
return moved;
}
public boolean wasRotated()
{
return rotated;
}
public Matrix4f getViewMatrix()
{
return viewMatrix;
}
public Matrix4f getInvertedViewMatrix()
{
return invertedViewMatrix;
}
public Frustrum getFrustrum()
{
return frustrum;
}
public ICameraController getController()
{
return controller;
}
public <T extends ICameraController> T getController(Class<T> clz)
{
return (T)controller;
}
public Vec3f getPosition()
{
return position;
}
public Vec3f getLookDirection()
{
float f = MathUtils.cos(-rotation.getY() * 0.017453292F - (float)Math.PI);
float f1 = MathUtils.sin(-rotation.getY() * 0.017453292F - (float)Math.PI);
float f2 = -MathUtils.cos(-rotation.getX() * 0.017453292F);
float f3 = MathUtils.sin(-rotation.getX() * 0.017453292F);
return Vec3f.of(f1 * f2, f3, f * f2);
}
public Camera setCameraChanged()
{
changed = true;
return this;
}
public void setPosition(Vec3f vec, boolean update)
{
position.set(vec);
if(update)
{
controller.onPositionUpdate(this);
}
}
public Vec2i getActualCenter(){return controller.getCenter(this);}
public Vec2i getSolidPosition(){return Vec2i.of((int)position.getX(), (int)position.getZ());}
public void rotate(Vec2i vec){rotate(vec.getY(), vec.getX());}
public void rotate(Vec2f vec){rotate(vec.getY(), vec.getX());}
public void rotate(float x, float y){rotation.add(x, y);}
public void move(Vec3f vec){move(vec.getX(), vec.getY(), vec.getZ());}
public void move(Vec3i vec){move(vec.getX(), vec.getY(), vec.getZ());}
public void move(float x, float y, float z){position.add(x, y, z);}
public void moveRotated(float x, float y, float z)
{
if(z != 0)
{
position.add(MathUtils.sin(Math.toRadians(getYaw())) * -1.0f * z, 0, MathUtils.cos(Math.toRadians(getYaw())) * z);
}
if(x != 0)
{
position.add(MathUtils.sin(Math.toRadians(getYaw() - 90)) * -1.0f * x, 0, MathUtils.cos(Math.toRadians(getYaw() - 90)) * x);
}
if(y != 0)
{
position.add(0F, y, 0F);
}
}
public Vec2f getRotation(){return rotation;}
public float getYaw(){return rotation.getY();}
public void setYaw(float value){rotation.setY(value);}
public float pitch(){return rotation.getX();}
public void setPitch(float value){rotation.setX(value);}
@Override
public String toString()
{
DecimalFormat format = new DecimalFormat("###,###");
return "Camera[x="+format.format(position.getX())+", y="+format.format(position.getY())+", z="+format.format(position.getZ())+", Yaw="+format.format(getYaw())+", Pitch="+format.format(pitch())+"]";
}
}