X-Git-Url: http://www2.svjatoslav.eu/gitweb/?p=sixth-3d.git;a=blobdiff_plain;f=src%2Fmain%2Fjava%2Feu%2Fsvjatoslav%2Fsixth%2Fe3d%2Fgui%2FAvatar.java;h=52d78b2471fe836b1707393061d3a205125d7d13;hp=ea9068733f41f4b16383fec27256e2f5e02474ac;hb=e56f9b775bd49c31e8efab7204bee699036942b3;hpb=6213716671ccab6b7256de41838e1f5401ce173c diff --git a/src/main/java/eu/svjatoslav/sixth/e3d/gui/Avatar.java b/src/main/java/eu/svjatoslav/sixth/e3d/gui/Avatar.java index ea90687..52d78b2 100755 --- a/src/main/java/eu/svjatoslav/sixth/e3d/gui/Avatar.java +++ b/src/main/java/eu/svjatoslav/sixth/e3d/gui/Avatar.java @@ -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; } }