Code cleanup and formatting.
[sixth-3d.git] / src / main / java / eu / svjatoslav / sixth / e3d / gui / Avatar.java
index ea90687..52d78b2 100755 (executable)
@@ -1,41 +1,46 @@
 /*
- * Sixth - System for data storage, computation, exploration and interaction.
- * Copyright ©2012-2016, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
- * 
+ * Sixth 3D engine. Copyright ©2012-2018, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of version 3 of the GNU Lesser General Public License
  * or later as published by the Free Software Foundation.
+ *
  */
 
 package eu.svjatoslav.sixth.e3d.gui;
 
 import eu.svjatoslav.sixth.e3d.geometry.Point3D;
 
-public class Avatar implements ViewUpdateListener {
+import static java.lang.Math.cos;
+import static java.lang.Math.sin;
+
+public class Avatar implements ViewRenderListener {
 
     public static final double SPEED_LIMIT = 30;
     /**
      * Just in case we want to adjust global speed for some reason.
      */
     private static final double SPEED_MULTIPLIER = .02d;
+    /**
+     * Determines amount of friction user experiences every millisecond while moving around in space.
+     */
+    private static final double MILLISECOND_FRICTION = 1.005;
     /**
      * Avatar movement speed, relative to avatar itself. When avatar coordinates
      * are updated within the world, avatar orientation relative to the world is
      * taken into account.
      */
-    private final Point3D movementDirection = new Point3D();
+    private final Point3D movementVector = new Point3D();
     public double avatarAcceleration = 0.1;
     /**
      * Avatar location within the 3D world.
      */
     private Point3D location = new Point3D();
-
     /**
      * Avatar orientation on the X-Z plane. It changes when turning left or
      * right.
      */
     private double orientationXZ;
-
     /**
      * Avatar orientation on the Y-Z plane. It changes when looking up or down.
      */
@@ -62,27 +67,26 @@ public class Avatar implements ViewUpdateListener {
     }
 
     @Override
-    public boolean beforeViewUpdate(final ViewContext viewContext,
-                                    final int millisecondsSinceLastFrame) {
+    public boolean beforeRender(final ViewPanel viewPanel, final int millisecondsSinceLastFrame) {
 
         final Point3D locationBeforeUpdate = new Point3D(location);
-        updateLocation(millisecondsSinceLastFrame);
-
-        final double distanceMoved = location
-                .getDistanceTo(locationBeforeUpdate);
+        translateAvatarLocation(millisecondsSinceLastFrame);
+        applyFrictionToUserMovement(millisecondsSinceLastFrame);
+        return isFrameRepaintNeeded(locationBeforeUpdate);
+    }
 
+    private boolean isFrameRepaintNeeded(Point3D locationBeforeUpdate) {
+        final double distanceMoved = location.getDistanceTo(locationBeforeUpdate);
         return distanceMoved > 0.03;
-
     }
 
     public void enforceSpeedLimit() {
-        final double currentSpeed = movementDirection
-                .getDistanceTo(Point3D.ZERO);
+        final double currentSpeed = movementVector.getVectorLength();
 
         if (currentSpeed <= SPEED_LIMIT)
             return;
 
-        movementDirection.scaleDown(currentSpeed / SPEED_LIMIT);
+        movementVector.scaleDown(currentSpeed / SPEED_LIMIT);
     }
 
     public double getAngleXZ() {
@@ -109,49 +113,48 @@ public class Avatar implements ViewUpdateListener {
         this.location = location;
     }
 
-    public Point3D getMovementDirection() {
-        return movementDirection;
+    public Point3D getMovementVector() {
+        return movementVector;
     }
 
     public double getMovementSpeed() {
-        return movementDirection.getDistanceTo(Point3D.ZERO);
+        return movementVector.getVectorLength();
+    }
+
+    private void applyFrictionToUserMovement(int millisecondsPassedSinceLastFrame) {
+        for (int i = 0; i < millisecondsPassedSinceLastFrame; i++)
+            applyMillisecondFrictionToUserMovementVector();
+    }
+
+    private void applyMillisecondFrictionToUserMovementVector() {
+        getMovementVector().x /= MILLISECOND_FRICTION;
+        getMovementVector().y /= MILLISECOND_FRICTION;
+        getMovementVector().z /= MILLISECOND_FRICTION;
     }
 
     /**
-     * Update camera location based on current speed
+     * Translate coordinates based on avatar movement vector and avatar orientation in the world.
+     *
+     * @param millisecondsPassedSinceLastFrame We want avatar movement to be independent of framerate.
+     *                                         Therefore we take frame rendering time into account when translating
+     *                                         avatar between consecutive frames.
      */
-    public void updateLocation(final int millisecondsPassedSinceLastFrame) {
-
-        // translate user coordinates based on avatar movement speed, and avatar
-        // orientation in the world
-        {
-            location.x -= (float) Math.sin(getAngleXZ())
-                    * getMovementDirection().z * SPEED_MULTIPLIER
-                    * millisecondsPassedSinceLastFrame;
-            location.z += (float) Math.cos(getAngleXZ())
-                    * getMovementDirection().z * SPEED_MULTIPLIER
-                    * millisecondsPassedSinceLastFrame;
-
-            location.x += (float) Math.cos(getAngleXZ())
-                    * getMovementDirection().x * SPEED_MULTIPLIER
-                    * millisecondsPassedSinceLastFrame;
-            location.z += (float) Math.sin(getAngleXZ())
-                    * getMovementDirection().x * SPEED_MULTIPLIER
-                    * millisecondsPassedSinceLastFrame;
-
-            location.y += getMovementDirection().y * SPEED_MULTIPLIER
-                    * millisecondsPassedSinceLastFrame;
-        }
-
-        final double millisecondFriction = 1.005;
-        // apply friction to progressively slow movement
-        for (int i = 0; i < millisecondsPassedSinceLastFrame; i++) {
-            getMovementDirection().x = getMovementDirection().x
-                    / millisecondFriction;
-            getMovementDirection().y = getMovementDirection().y
-                    / millisecondFriction;
-            getMovementDirection().z = getMovementDirection().z
-                    / millisecondFriction;
-        }
+    private void translateAvatarLocation(int millisecondsPassedSinceLastFrame) {
+        location.x -= (float) sin(getAngleXZ())
+                * getMovementVector().z * SPEED_MULTIPLIER
+                * millisecondsPassedSinceLastFrame;
+        location.z += (float) cos(getAngleXZ())
+                * getMovementVector().z * SPEED_MULTIPLIER
+                * millisecondsPassedSinceLastFrame;
+
+        location.x += (float) cos(getAngleXZ())
+                * getMovementVector().x * SPEED_MULTIPLIER
+                * millisecondsPassedSinceLastFrame;
+        location.z += (float) sin(getAngleXZ())
+                * getMovementVector().x * SPEED_MULTIPLIER
+                * millisecondsPassedSinceLastFrame;
+
+        location.y += getMovementVector().y * SPEED_MULTIPLIER
+                * millisecondsPassedSinceLastFrame;
     }
 }