diff --git a/racevisionGame/src/main/java/visualiser/Controllers/RaceController.java b/racevisionGame/src/main/java/visualiser/Controllers/RaceController.java index 46afe65e..cd450f18 100644 --- a/racevisionGame/src/main/java/visualiser/Controllers/RaceController.java +++ b/racevisionGame/src/main/java/visualiser/Controllers/RaceController.java @@ -17,8 +17,10 @@ import javafx.scene.layout.Pane; import javafx.scene.layout.StackPane; import javafx.scene.shape.MeshView; import javafx.scene.shape.Sphere; +import javafx.scene.transform.Translate; import javafx.util.Callback; import network.Messages.Enums.RaceStatusEnum; +import shared.dataInput.RaceDataSource; import shared.exceptions.BoatNotFoundException; import shared.exceptions.MarkNotFoundException; import shared.model.Leg; @@ -29,6 +31,7 @@ import visualiser.gameController.Keys.ControlKey; import visualiser.layout.Subject3D; import visualiser.layout.View3D; import visualiser.model.*; +import visualiser.utils.GPSConverter; import java.io.IOException; import java.net.URL; @@ -175,7 +178,7 @@ public class RaceController extends Controller { } private void initialiseView3D(VisualiserRaceEvent race) { - int scale = 5000; + int scale = 1; ObservableList subjects = FXCollections.observableArrayList(); @@ -184,39 +187,59 @@ public class RaceController extends Controller { importer.read(asset); view3D = new View3D(); - view3D.setDistance(100); + view3D.setDistance(1050); view3D.setYaw(0); - view3D.setPitch(20); + view3D.setPitch(60); + //view3D.rotateCamera(-90, 1, 0, 0); + //view3D.updatePosition(0, 200, 0); + RaceDataSource raceData = visualiserRace.getVisualiserRaceState().getRaceDataSource(); + + double lat1 = raceData.getMapTopLeft().getLatitude(); + double long1 = raceData.getMapTopLeft().getLongitude(); + double lat2 = raceData.getMapBottomRight().getLatitude(); + double long2 = raceData.getMapBottomRight().getLongitude(); + System.out.println(view3D.getWidth()); + System.out.println(view3D.getHeight()); + final GPSConverter gpsConverter = new GPSConverter(lat1, long1, lat2, long2, (int)450, (int)450); view3D.setItems(subjects); canvasBase.getChildren().add(0, view3D); for(Mark mark: race.getVisualiserRaceState().getMarks()) { Subject3D subject = new Subject3D(new Sphere(5)); - subject.setX(mark.getPosition().getLongitude() * scale); - subject.setZ(mark.getPosition().getLatitude() * scale); +// subject.setX(mark.getPosition().getLongitude() * scale); +// subject.setZ(mark.getPosition().getLatitude()* scale); + subject.setX(gpsConverter.convertGPS(mark.getPosition()).getX() * scale); + subject.setZ(gpsConverter.convertGPS(mark.getPosition()).getY() * scale); subjects.add(subject); } for(VisualiserBoat boat: race.getVisualiserRaceState().getBoats()) { - Subject3D subject = new Subject3D(new MeshView(importer.getImport())); + MeshView mesh = new MeshView(importer.getImport()); + Subject3D subject = new Subject3D(mesh); subjects.add(subject); AnimationTimer trackBoat = new AnimationTimer() { @Override public void handle(long now) { subject.setHeading(boat.getBearing().degrees()); - subject.setX(boat.getPosition().getLongitude() * scale); - subject.setZ(boat.getPosition().getLatitude()* scale); +// subject.setHeading(0); +// subject.setX(boat.getPosition().getLongitude() * scale); +// subject.setZ(boat.getPosition().getLatitude()* scale); + double x = gpsConverter.convertGPS(boat.getPosition()).getX() * scale; + //System.out.println(x); + subject.setX(x); + subject.setZ(gpsConverter.convertGPS(boat.getPosition()).getY() * scale); if(boat.getSourceID() == race.getVisualiserRaceState().getPlayerBoatID()) { - view3D.updatePivot(subject.getPosition()); + //view3D.updatePivot(subject.getPosition()); } - view3D.setYaw(boat.getBearing().degrees()); + //view3D.setYaw(boat.getBearing().degrees()); } }; trackBoat.start(); } + view3D.updatePivot(new Translate(250, 0, 210)); } diff --git a/racevisionGame/src/main/java/visualiser/layout/Subject3D.java b/racevisionGame/src/main/java/visualiser/layout/Subject3D.java index 4bb6f6af..adfd93ab 100644 --- a/racevisionGame/src/main/java/visualiser/layout/Subject3D.java +++ b/racevisionGame/src/main/java/visualiser/layout/Subject3D.java @@ -33,6 +33,9 @@ public class Subject3D { this.heading = new Rotate(0, Rotate.Y_AXIS); this.mesh.getTransforms().addAll(position, heading, new Rotate(90, Rotate.X_AXIS), new Rotate(180, Rotate.Y_AXIS)); + this.position.xProperty().addListener(((observable, oldValue, newValue) -> System.out.println("Boat x: " + newValue))); + this.position.yProperty().addListener(((observable, oldValue, newValue) -> System.out.println("Boat y: " + newValue))); + this.position.zProperty().addListener(((observable, oldValue, newValue) -> System.out.println("Boat z: " + newValue))); } public Shape3D getMesh() { diff --git a/racevisionGame/src/main/java/visualiser/layout/View3D.java b/racevisionGame/src/main/java/visualiser/layout/View3D.java index f3607ce0..95a6cfeb 100644 --- a/racevisionGame/src/main/java/visualiser/layout/View3D.java +++ b/racevisionGame/src/main/java/visualiser/layout/View3D.java @@ -2,6 +2,7 @@ package visualiser.layout; import javafx.collections.ListChangeListener; import javafx.collections.ObservableList; +import javafx.geometry.Point3D; import javafx.scene.Group; import javafx.scene.PerspectiveCamera; import javafx.scene.SubScene; @@ -77,7 +78,7 @@ public class View3D extends Pane { // Set up view frustum nearClip = 0.1; - farClip = 1000.0; + farClip = 3000.0; camera.setNearClip(nearClip); camera.setFarClip(farClip); @@ -87,7 +88,7 @@ public class View3D extends Pane { yaw = new Rotate(0, Rotate.Y_AXIS); pitch = new Rotate(0, Rotate.X_AXIS); camera.getTransforms().addAll(pivot, yaw, pitch, distance); - //camera.setTranslateZ(-1000); + centerCamera(); this.camera = camera; return camera; @@ -118,6 +119,13 @@ public class View3D extends Pane { this.pivot.setY(pivot.getY()); this.pivot.setZ(pivot.getZ()); } + + public void updatePosition(double x, double y, double z) { + this.distance.setX(x); + this.distance.setY(y); + this.distance.setZ(z); + } + /** * Set distance of camera from pivot * @param distance in units @@ -141,4 +149,13 @@ public class View3D extends Pane { public void setPitch(double pitch) { this.pitch.setAngle(-pitch); } + + public void centerCamera(){ + } + + public void rotateCamera(double angle, double x, double y, double z){ + camera.setRotationAxis(new Point3D(x, y, z)); + camera.setRotate(-90); + } + } diff --git a/racevisionGame/src/main/java/visualiser/utils/GPSConverter.java b/racevisionGame/src/main/java/visualiser/utils/GPSConverter.java new file mode 100644 index 00000000..55a162b2 --- /dev/null +++ b/racevisionGame/src/main/java/visualiser/utils/GPSConverter.java @@ -0,0 +1,91 @@ +package visualiser.utils; + +import shared.model.GPSCoordinate; +import visualiser.model.GraphCoordinate; + +/** + * Created by fwy13 on 7/09/17. + */ +public class GPSConverter { + double longRight; + double longLeft; + double latBottom; + double latTop; + int paneWidth; + int paneHeight; + + public GPSConverter(double latTop, double longLeft, double latBottom, double longRight, double paneWidth, double paneHeight){ + this.longRight = longRight; + this.longLeft = longLeft; + this.latBottom = latBottom; + this.latTop = latTop; + this.paneWidth = (int)paneWidth; + this.paneHeight = (int)paneHeight; + } + + /** + * Converts GPS coordinates to coordinates for container. + * It is assumed that the provided GPSCoordinate will always be within the GPSCoordinate boundaries of the RaceMap. + * + * @param lat GPS latitude + * @param lon GPS longitude + * @return GraphCoordinate (pair of doubles) + * @see GraphCoordinate + */ + private GraphCoordinate convertGPS(double lat, double lon) { + + //Calculate the width/height, in gps coordinates, of the map. + double longWidth = longRight - longLeft; + double latHeight = latBottom - latTop; + + //Calculate the distance between the specified coordinate and the edge of the map. + double longDelta = lon - longLeft; + double latDelta = lat - latTop; + + //Calculate the proportion along horizontally, from the left, the coordinate should be. + double longProportion = longDelta / longWidth; + //Calculate the proportion along vertically, from the top, the coordinate should be. + double latProportion = latDelta / latHeight; + //System.out.println(latProportion + " " + longProportion); + + + //Check which pixel dimension of our map is smaller. We use this to ensure that any rendered stuff retains its correct aspect ratio, and that everything is visible on screen. + int smallerDimension = Math.min(paneWidth, paneHeight); + + //Calculate the x and y pixel coordinates. + //We take the complement of latProportion to flip it. + int x = (int) (longProportion * smallerDimension); + int y = (int) (latProportion * smallerDimension); + + //Because we try to maintain the correct aspect ratio, we will end up with "spare" pixels along the larger dimension (e.g., width 800, height 600, 200 extra pixels along width). + int extraPixels = Math.abs(paneWidth - paneHeight); + //We therefore "center" the coordinates along this larger dimension, by adding half of the extra pixels. + if (paneWidth > paneHeight) { + x += extraPixels / 2; + } else { + y += extraPixels / 2; + } + + + //Finally, create the GraphCoordinate. + GraphCoordinate graphCoordinate = new GraphCoordinate(x, y); + + + return graphCoordinate; + + } + + /** + * Converts the GPS Coordinate to GraphCoordinate. + * It is assumed that the provided GPSCoordinate will always be within the GPSCoordinate boundaries of the RaceMap. + * + * @param coordinate GPSCoordinate representation of Latitude and Longitude. + * @return GraphCoordinate that the GPS is coordinates are to be displayed on the map. + * @see GraphCoordinate + * @see GPSCoordinate + */ + public GraphCoordinate convertGPS(GPSCoordinate coordinate) { + return convertGPS(coordinate.getLatitude(), coordinate.getLongitude()); + } + +}