207 lines
5.2 KiB
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())+"]";
|
|
}
|
|
}
|