2 * Sixth - System for data storage, computation, exploration and interaction.
3 * Copyright ©2012-2016, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of version 3 of the GNU Lesser General Public License
7 * or later as published by the Free Software Foundation.
10 package eu.svjatoslav.sixth.e3d.gui;
12 import eu.svjatoslav.sixth.e3d.geometry.Point3D;
14 public class Avatar implements ViewUpdateListener {
16 public static final double SPEED_LIMIT = 30;
18 * Just in case we want to adjust global speed for some reason.
20 private static final double SPEED_MULTIPLIER = .02d;
22 * Avatar movement speed, relative to avatar itself. When avatar coordinates
23 * are updated within the world, avatar orientation relative to the world is
26 private final Point3D movementDirection = new Point3D();
27 public double avatarAcceleration = 0.1;
29 * Avatar location within the 3D world.
31 private Point3D location = new Point3D();
34 * Avatar orientation on the X-Z plane. It changes when turning left or
37 private double orientationXZ;
40 * Avatar orientation on the Y-Z plane. It changes when looking up or down.
42 private double orientationYZ;
47 public Avatar(final Avatar sourceView) {
48 setLocation(new Point3D(sourceView.location));
49 setAngleXZ(sourceView.getAngleXZ());
50 setAngleYZ(sourceView.getAngleYZ());
53 public Avatar(final Point3D location) {
54 setLocation(location);
57 public Avatar(final Point3D location, final float angleXZ,
58 final float angleYZ) {
59 setLocation(location);
65 public boolean beforeViewUpdate(final ViewContext viewContext,
66 final int millisecondsSinceLastFrame) {
68 final Point3D locationBeforeUpdate = new Point3D(location);
69 updateLocation(millisecondsSinceLastFrame);
71 final double distanceMoved = location
72 .getDistanceTo(locationBeforeUpdate);
74 return distanceMoved > 0.03;
78 public void enforceSpeedLimit() {
79 final double currentSpeed = movementDirection
80 .getDistanceTo(Point3D.ZERO);
82 if (currentSpeed <= SPEED_LIMIT)
85 movementDirection.scaleDown(currentSpeed / SPEED_LIMIT);
88 public double getAngleXZ() {
92 public void setAngleXZ(final double angleXZ) {
93 orientationXZ = angleXZ;
96 public double getAngleYZ() {
100 public void setAngleYZ(final double angleYZ) {
101 orientationYZ = angleYZ;
104 public Point3D getLocation() {
108 public void setLocation(final Point3D location) {
109 this.location = location;
112 public Point3D getMovementDirection() {
113 return movementDirection;
116 public double getMovementSpeed() {
117 return movementDirection.getDistanceTo(Point3D.ZERO);
121 * Update camera location based on current speed
123 public void updateLocation(final int millisecondsPassedSinceLastFrame) {
125 // translate user coordinates based on avatar movement speed, and avatar
126 // orientation in the world
128 location.x -= (float) Math.sin(getAngleXZ())
129 * getMovementDirection().z * SPEED_MULTIPLIER
130 * millisecondsPassedSinceLastFrame;
131 location.z += (float) Math.cos(getAngleXZ())
132 * getMovementDirection().z * SPEED_MULTIPLIER
133 * millisecondsPassedSinceLastFrame;
135 location.x += (float) Math.cos(getAngleXZ())
136 * getMovementDirection().x * SPEED_MULTIPLIER
137 * millisecondsPassedSinceLastFrame;
138 location.z += (float) Math.sin(getAngleXZ())
139 * getMovementDirection().x * SPEED_MULTIPLIER
140 * millisecondsPassedSinceLastFrame;
142 location.y += getMovementDirection().y * SPEED_MULTIPLIER
143 * millisecondsPassedSinceLastFrame;
146 final double millisecondFriction = 1.005;
147 // apply friction to progressively slow movement
148 for (int i = 0; i < millisecondsPassedSinceLastFrame; i++) {
149 getMovementDirection().x = getMovementDirection().x
150 / millisecondFriction;
151 getMovementDirection().y = getMovementDirection().y
152 / millisecondFriction;
153 getMovementDirection().z = getMovementDirection().z
154 / millisecondFriction;