diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/world/Camera.java b/src/main/java/ru/windcorp/progressia/client/graphics/world/Camera.java index 7e8a59d3..ab997771 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/world/Camera.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/world/Camera.java @@ -18,6 +18,7 @@ package ru.windcorp.progressia.client.graphics.world; import static java.lang.Math.*; +import static ru.windcorp.progressia.common.util.FloatMathUtils.*; import java.util.Collection; import java.util.function.Consumer; @@ -74,11 +75,32 @@ public void applyCameraRotation(Mat4 output) { private float fieldOfView; + /* + * Cache + */ + + private final Vec3 lastAnchorPosition = new Vec3(); + private float lastAnchorYaw; + private float lastAnchorPitch; + + private final Mat4 lastCameraMatrix = new Mat4(); + + private final Vec3 lastAnchorLookingAt = new Vec3(); + private final Vec3 lastAnchorUp = new Vec3(); + + { + invalidateCache(); + } + public Camera(float fieldOfView) { setFieldOfView(fieldOfView); } public Camera() {} + + /* + * apply() and subroutines + */ public void apply(WorldRenderHelper helper) { applyPerspective(helper); @@ -87,6 +109,8 @@ public void apply(WorldRenderHelper helper) { applyMode(helper); applyDirection(helper); applyPosition(helper); + + cacheCameraTransform(helper); } private void applyPerspective(WorldRenderHelper helper) { @@ -121,22 +145,48 @@ private void applyMode(WorldRenderHelper helper) { } private void applyDirection(WorldRenderHelper helper) { + float pitch = anchor.getCameraPitch(); + float yaw = anchor.getCameraYaw(); + helper.pushViewTransform() - .rotateY(-anchor.getCameraPitch()) - .rotateZ(-anchor.getCameraYaw()); + .rotateY(-pitch) + .rotateZ(-yaw); + + this.lastAnchorYaw = yaw; + this.lastAnchorPitch = pitch; + + this.lastAnchorLookingAt.set( + cos(pitch) * cos(yaw), + cos(pitch) * sin(yaw), + sin(pitch) + ); + this.lastAnchorUp.set( + cos(pitch + PI_F / 2) * cos(yaw), + cos(pitch + PI_F / 2) * sin(yaw), + sin(pitch + PI_F / 2) + ); } private void applyPosition(WorldRenderHelper helper) { Vec3 v = Vectors.grab3(); anchor.getCameraPosition(v); - v.negate(); + this.lastAnchorPosition.set(v); + v.negate(); helper.pushViewTransform().translate(v); Vectors.release(v); } + private void cacheCameraTransform(WorldRenderHelper helper) { + this.lastCameraMatrix.set(helper.getViewTransform()); + } + + /* + * FOV management + */ + private float computeFovY() { float widthOverHeight = GraphicsInterface.getAspectRatio(); @@ -159,6 +209,10 @@ public void setFieldOfView(float fieldOfView) { this.fieldOfView = fieldOfView; } + /* + * Anchor management + */ + public Anchor getAnchor() { return anchor; } @@ -171,6 +225,7 @@ public void setAnchor(Anchor anchor) { if (anchor == null) { this.anchor = null; this.modes = null; + invalidateCache(); return; } @@ -189,6 +244,22 @@ public void setAnchor(Anchor anchor) { this.currentModeIndex = 0; } + private void invalidateCache() { + this.lastAnchorPosition.set(Float.NaN); + this.lastAnchorYaw = Float.NaN; + this.lastAnchorPitch = Float.NaN; + + this.lastCameraMatrix.set( + Float.NaN, Float.NaN, Float.NaN, Float.NaN, + Float.NaN, Float.NaN, Float.NaN, Float.NaN, + Float.NaN, Float.NaN, Float.NaN, Float.NaN, + Float.NaN, Float.NaN, Float.NaN, Float.NaN + ); + + this.lastAnchorLookingAt.set(Float.NaN); + this.lastAnchorUp.set(Float.NaN); + } + public Anchor.Mode getMode() { return modes[currentModeIndex]; } @@ -201,4 +272,28 @@ public void selectNextMode() { } } + public float getLastAnchorYaw() { + return lastAnchorYaw; + } + + public float getLastAnchorPitch() { + return lastAnchorPitch; + } + + public Vec3 getLastAnchorPosition() { + return lastAnchorPosition; + } + + public Mat4 getLastCameraMatrix() { + return lastCameraMatrix; + } + + public Vec3 getLastAnchorLookingAt() { + return lastAnchorLookingAt; + } + + public Vec3 getLastAnchorUp() { + return lastAnchorUp; + } + } diff --git a/src/main/java/ru/windcorp/progressia/common/util/FloatMathUtils.java b/src/main/java/ru/windcorp/progressia/common/util/FloatMathUtils.java index bdf3deca..89449ab2 100644 --- a/src/main/java/ru/windcorp/progressia/common/util/FloatMathUtils.java +++ b/src/main/java/ru/windcorp/progressia/common/util/FloatMathUtils.java @@ -14,6 +14,18 @@ public static float normalizeAngle(float a) { return a - 2*PI_F * floor((a + PI_F) / (2*PI_F)); } + public static float sin(float x) { + return (float) Math.sin(x); + } + + public static float cos(float x) { + return (float) Math.cos(x); + } + + public static float tan(float x) { + return (float) Math.tan(x); + } + private FloatMathUtils() {} }