@ -0,0 +1,46 @@
|
|||||||
|
package visualiser.Commands.VisualiserRaceCommands;
|
||||||
|
|
||||||
|
import javafx.scene.media.AudioClip;
|
||||||
|
import mock.model.commandFactory.Command;
|
||||||
|
import network.Messages.YachtEvent;
|
||||||
|
import shared.exceptions.BoatNotFoundException;
|
||||||
|
import visualiser.model.VisualiserBoat;
|
||||||
|
import visualiser.model.VisualiserRaceState;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by zwu18 on 4/09/17.
|
||||||
|
*/
|
||||||
|
public class BoatCollisionCommand implements Command {
|
||||||
|
|
||||||
|
YachtEvent yachtEvent;
|
||||||
|
|
||||||
|
VisualiserRaceState visualiserRace;
|
||||||
|
|
||||||
|
public BoatCollisionCommand(YachtEvent yachtEvent, VisualiserRaceState visualiserRace){
|
||||||
|
this.yachtEvent = yachtEvent;
|
||||||
|
this.visualiserRace = visualiserRace;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute() {
|
||||||
|
|
||||||
|
if(visualiserRace.getPlayerBoatID()==yachtEvent.getSourceID()){
|
||||||
|
//System.out.println("I crashed!");
|
||||||
|
AudioClip sound = new AudioClip(this.getClass().getResource("/visualiser/sounds/collision.wav").toExternalForm());
|
||||||
|
sound.play();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
//System.out.println("Someone else crashed!");
|
||||||
|
AudioClip sound = new AudioClip(this.getClass().getResource("/visualiser/sounds/quietcollision.wav").toExternalForm());
|
||||||
|
sound.play();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
VisualiserBoat boat = visualiserRace.getBoat(yachtEvent.getSourceID());
|
||||||
|
boat.setHasCollided(true);
|
||||||
|
} catch (BoatNotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
package visualiser.layout;
|
||||||
|
|
||||||
|
import javafx.scene.shape.Shape3D;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by connortaylorbrown on 13/09/17.
|
||||||
|
*/
|
||||||
|
public class Annotation3D extends Subject3D {
|
||||||
|
/**
|
||||||
|
* Constructor for view subject wrapper
|
||||||
|
*
|
||||||
|
* @param mesh to be rendered
|
||||||
|
*/
|
||||||
|
public Annotation3D(Shape3D mesh) {
|
||||||
|
super(mesh, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prevent rescaling of this subject
|
||||||
|
* @param scale ignored
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setScale(double scale) {}
|
||||||
|
}
|
||||||
@ -0,0 +1,89 @@
|
|||||||
|
package visualiser.layout;
|
||||||
|
|
||||||
|
import com.sun.corba.se.impl.orbutil.graph.Graph;
|
||||||
|
import javafx.scene.shape.Box;
|
||||||
|
import javafx.scene.shape.MeshView;
|
||||||
|
import javafx.scene.shape.Rectangle;
|
||||||
|
import javafx.scene.shape.Sphere;
|
||||||
|
import shared.model.GPSCoordinate;
|
||||||
|
import visualiser.model.GraphCoordinate;
|
||||||
|
import visualiser.utils.GPSConverter;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class that creates a 3d boundary based on gps coordinates
|
||||||
|
*/
|
||||||
|
public class Boundary3D {
|
||||||
|
|
||||||
|
public static double thickness = 1;
|
||||||
|
private List<Subject3D> boundaryNodes = new ArrayList<>();
|
||||||
|
private List<Subject3D> boundaryConnectors = new ArrayList<>();
|
||||||
|
private GPSConverter gpsConverter;
|
||||||
|
|
||||||
|
public Boundary3D(List<GPSCoordinate> points, GPSConverter gpsConverter){
|
||||||
|
this.gpsConverter = gpsConverter;
|
||||||
|
setBoundaryNodes(points);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Splits up the list so that it generates a edge of the boundary
|
||||||
|
* @param points boundary gpscoordinate
|
||||||
|
*/
|
||||||
|
private void setBoundaryNodes(List<GPSCoordinate> points){
|
||||||
|
if (points.size() < 2){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
System.out.println(points.size());
|
||||||
|
for (int i = 0; i < points.size(); i++){
|
||||||
|
if (i + 1 != points.size()){
|
||||||
|
addBound(points.get(i), points.get(i + 1));
|
||||||
|
} else {
|
||||||
|
addBound(points.get(i), points.get(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a two point boundary this will create a sphere at coord1 and a line to coord 2
|
||||||
|
* this is to reduce double up (2 spheres in one point).
|
||||||
|
* @param coord1 point to make sphere and start the line.
|
||||||
|
* @param coord2 point to end the line.
|
||||||
|
*/
|
||||||
|
private void addBound(GPSCoordinate coord1, GPSCoordinate coord2){
|
||||||
|
GraphCoordinate graphCoord1 = gpsConverter.convertGPS(coord1);
|
||||||
|
GraphCoordinate graphCoord2 = gpsConverter.convertGPS(coord2);
|
||||||
|
GraphCoordinate avgCoord = new GraphCoordinate((graphCoord1.getX() + graphCoord2.getX()) / 2,
|
||||||
|
(graphCoord1.getY() + graphCoord2.getY()) / 2);
|
||||||
|
|
||||||
|
double a = (graphCoord1.getX() - graphCoord2.getX());
|
||||||
|
double b = (graphCoord1.getY() - graphCoord2.getY());
|
||||||
|
double c = Math.sqrt(a * a + b * b);
|
||||||
|
|
||||||
|
|
||||||
|
Subject3D bound1 = new Annotation3D(new Sphere(thickness * 2));
|
||||||
|
bound1.setX(graphCoord1.getX());
|
||||||
|
bound1.setZ(graphCoord1.getY());
|
||||||
|
boundaryNodes.add(bound1);
|
||||||
|
|
||||||
|
Subject3D connector = new Annotation3D(new Box(c, thickness, thickness));
|
||||||
|
connector.setX(avgCoord.getX());
|
||||||
|
connector.setZ(avgCoord.getY());
|
||||||
|
double angle = 90 + Math.toDegrees(GPSConverter.getAngle(graphCoord2, graphCoord1));
|
||||||
|
connector.setHeading(angle);
|
||||||
|
|
||||||
|
boundaryConnectors.add(connector);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the 3d objects to draw
|
||||||
|
* @return 3d boundary to draw
|
||||||
|
*/
|
||||||
|
public List<Subject3D> getBoundaryNodes(){
|
||||||
|
//these two must be concatenated with nodes after connectors else the spheres will not overlap the lines
|
||||||
|
ArrayList<Subject3D> result = new ArrayList<>(boundaryConnectors);
|
||||||
|
result.addAll(boundaryNodes);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
package visualiser.layout;
|
||||||
|
|
||||||
|
import javafx.scene.paint.Color;
|
||||||
|
import javafx.scene.paint.PhongMaterial;
|
||||||
|
import javafx.scene.shape.Cylinder;
|
||||||
|
import javafx.scene.transform.Rotate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by cbt24 on 14/09/17.
|
||||||
|
*/
|
||||||
|
public class Shockwave extends Subject3D {
|
||||||
|
public Shockwave(double radius) {
|
||||||
|
super(new Cylinder(radius,0),0);
|
||||||
|
getMesh().getTransforms().add(new Rotate(-90, Rotate.X_AXIS));
|
||||||
|
getMesh().setMaterial(new PhongMaterial(new Color(0,0,0,0)));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,163 @@
|
|||||||
|
package visualiser.layout;
|
||||||
|
|
||||||
|
import javafx.geometry.Point3D;
|
||||||
|
import javafx.scene.image.Image;
|
||||||
|
import javafx.scene.paint.Color;
|
||||||
|
import javafx.scene.paint.PhongMaterial;
|
||||||
|
import javafx.scene.shape.MeshView;
|
||||||
|
import javafx.scene.transform.Rotate;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a skyBox
|
||||||
|
*/
|
||||||
|
public class SkyBox {
|
||||||
|
private int size;
|
||||||
|
private double x;
|
||||||
|
private double y;
|
||||||
|
private double z;
|
||||||
|
private double freq;
|
||||||
|
private double yshift;
|
||||||
|
private double clipOverlap;
|
||||||
|
private List<Subject3D> skyBoxPlanes = new ArrayList<>();
|
||||||
|
|
||||||
|
public SkyBox(int edgeLength, double freq, double x, double y, double z) {
|
||||||
|
this.size = edgeLength;
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.z = z;
|
||||||
|
this.freq = freq;
|
||||||
|
this.yshift = -size/64;
|
||||||
|
clipOverlap = 0;
|
||||||
|
makeSkyBox();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void makeSkyBox() {
|
||||||
|
addTop();
|
||||||
|
addFront();
|
||||||
|
addBack();
|
||||||
|
addLeft();
|
||||||
|
addRight();
|
||||||
|
//addSeaOverlay();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addTop() {
|
||||||
|
MeshView surface = makeSurface(new Image(getClass().getClassLoader().getResourceAsStream("images/skybox/ThickCloudsWaterUp2048.png")), size);
|
||||||
|
|
||||||
|
surface.setRotationAxis(new Point3D(0, 0, 1));
|
||||||
|
surface.setRotate(180);
|
||||||
|
|
||||||
|
surface.setTranslateX(x);
|
||||||
|
surface.setTranslateY(y - size + 1);
|
||||||
|
surface.setTranslateZ(z);
|
||||||
|
|
||||||
|
Subject3D top = new SkyBoxPlane(surface,0);
|
||||||
|
skyBoxPlanes.add(top);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addRight() {
|
||||||
|
MeshView surface = makeSurface(new Image(getClass().getClassLoader().getResourceAsStream("images/skybox/ThickCloudsWaterRight2048.png")), size + 1);
|
||||||
|
|
||||||
|
surface.setTranslateX(size/2);
|
||||||
|
surface.setTranslateY(size/2);
|
||||||
|
surface.setRotationAxis(new Point3D(1, 0, 0));
|
||||||
|
surface.setRotate(90);
|
||||||
|
surface.setTranslateX(-size/2);
|
||||||
|
surface.setTranslateY(-size/2);
|
||||||
|
|
||||||
|
surface.setTranslateX(x);
|
||||||
|
surface.setTranslateY(y + yshift);
|
||||||
|
surface.setTranslateZ(z + size/2 - clipOverlap);
|
||||||
|
|
||||||
|
|
||||||
|
Subject3D right = new SkyBoxPlane(surface,0);
|
||||||
|
skyBoxPlanes.add(right);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addLeft() {
|
||||||
|
MeshView surface = makeSurface(new Image(getClass().getClassLoader().getResourceAsStream("images/skybox/ThickCloudsWaterLeft2048.png")), size + 1);
|
||||||
|
|
||||||
|
surface.setTranslateX(size/2);
|
||||||
|
surface.setTranslateY(size/2);
|
||||||
|
surface.setRotationAxis(new Point3D(1, 0, 0));
|
||||||
|
surface.setRotate(-90);
|
||||||
|
surface.setTranslateX(-size/2);
|
||||||
|
surface.setTranslateY(-size/2);
|
||||||
|
|
||||||
|
surface.setScaleX(-1);
|
||||||
|
surface.setScaleZ(-1);
|
||||||
|
|
||||||
|
surface.setTranslateX(x);
|
||||||
|
surface.setTranslateY(y + yshift);
|
||||||
|
surface.setTranslateZ(z - size/2 + clipOverlap);
|
||||||
|
|
||||||
|
|
||||||
|
Subject3D left = new SkyBoxPlane(surface,0);
|
||||||
|
skyBoxPlanes.add(left);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addBack() {
|
||||||
|
MeshView surface = makeSurface(new Image(getClass().getClassLoader().getResourceAsStream("images/skybox/ThickCloudsWaterBack2048.png")), size);
|
||||||
|
surface.getTransforms().add(new Rotate(90, 0, 0));
|
||||||
|
|
||||||
|
surface.setRotationAxis(new Point3D(1, 0, 0));
|
||||||
|
surface.setRotate(-90);
|
||||||
|
|
||||||
|
surface.setScaleY(-1);
|
||||||
|
surface.setScaleZ(-1);
|
||||||
|
|
||||||
|
surface.setTranslateX(x - size/2 + clipOverlap);
|
||||||
|
surface.setTranslateY(y + yshift);
|
||||||
|
surface.setTranslateZ(z);
|
||||||
|
|
||||||
|
Subject3D back = new SkyBoxPlane(surface,0);
|
||||||
|
skyBoxPlanes.add(back);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addFront() {
|
||||||
|
MeshView surface = makeSurface(new Image(getClass().getClassLoader().getResourceAsStream("images/skybox/ThickCloudsWaterFront2048.png")), size);
|
||||||
|
|
||||||
|
surface.setTranslateX(size/2);
|
||||||
|
surface.setTranslateY(size/2);
|
||||||
|
surface.setRotationAxis(new Point3D(0, 0, 1));
|
||||||
|
surface.setRotate(-90);
|
||||||
|
surface.setTranslateX(-size/2);
|
||||||
|
surface.setTranslateY(-size/2);
|
||||||
|
|
||||||
|
surface.setTranslateX(x + size/2 - clipOverlap);
|
||||||
|
surface.setTranslateY(y + yshift);
|
||||||
|
surface.setTranslateZ(z);
|
||||||
|
|
||||||
|
Subject3D front = new SkyBoxPlane(surface,0);
|
||||||
|
skyBoxPlanes.add(front);
|
||||||
|
}
|
||||||
|
|
||||||
|
private MeshView makeSurface(Image diffuseMap, int size) {
|
||||||
|
|
||||||
|
PhongMaterial material = new PhongMaterial();
|
||||||
|
material.setDiffuseColor(Color.web("#FFFFFF"));
|
||||||
|
material.setSpecularColor(Color.web("#000000"));
|
||||||
|
material.setDiffuseMap(diffuseMap);
|
||||||
|
|
||||||
|
Plane3D plane = new Plane3D(size, size, 10, 10);
|
||||||
|
MeshView surface = new MeshView(plane);
|
||||||
|
surface.setMaterial(material);
|
||||||
|
surface.setMouseTransparent(true);
|
||||||
|
return surface;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addSeaOverlay() {
|
||||||
|
SeaSurface seaSurface = new SeaSurface(size * 3, freq);
|
||||||
|
seaSurface.setX(x);
|
||||||
|
seaSurface.setY(y - size/4 + 1);
|
||||||
|
seaSurface.setZ(z);
|
||||||
|
skyBoxPlanes.add(seaSurface);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Subject3D> getSkyBoxPlanes() {
|
||||||
|
return skyBoxPlanes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
package visualiser.layout;
|
||||||
|
|
||||||
|
import javafx.scene.shape.Shape3D;
|
||||||
|
|
||||||
|
public class SkyBoxPlane extends Subject3D {
|
||||||
|
|
||||||
|
public SkyBoxPlane(Shape3D mesh, int sourceID) {
|
||||||
|
super(mesh,sourceID);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setScale(double scale) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 5.0 MiB |
|
After Width: | Height: | Size: 3.6 MiB |
|
After Width: | Height: | Size: 4.8 MiB |
|
After Width: | Height: | Size: 4.4 MiB |
|
After Width: | Height: | Size: 4.6 MiB |
|
After Width: | Height: | Size: 2.4 MiB |
|
After Width: | Height: | Size: 78 KiB |
|
After Width: | Height: | Size: 103 KiB |
|
After Width: | Height: | Size: 85 KiB |
|
After Width: | Height: | Size: 99 KiB |
|
After Width: | Height: | Size: 48 KiB |
@ -0,0 +1,51 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<Race>
|
||||||
|
<RaceID>5326</RaceID>
|
||||||
|
<RaceType>FLEET</RaceType>
|
||||||
|
<CreationTimeDate>RACE_CREATION_TIME</CreationTimeDate>
|
||||||
|
<RaceStartTime Postpone="false" Time="RACE_START_TIME"/>
|
||||||
|
<Participants>
|
||||||
|
</Participants>
|
||||||
|
<CompoundMarkSequence>
|
||||||
|
<Corner SeqID="1" CompoundMarkID="1" Rounding="SP" ZoneSize="3" />
|
||||||
|
<Corner SeqID="2" CompoundMarkID="2" Rounding="Port" ZoneSize="3" />
|
||||||
|
<Corner SeqID="3" CompoundMarkID="4" Rounding="Port" ZoneSize="3" />
|
||||||
|
<Corner SeqID="4" CompoundMarkID="3" Rounding="Starboard" ZoneSize="3" />
|
||||||
|
<Corner SeqID="5" CompoundMarkID="4" Rounding="Port" ZoneSize="3" />
|
||||||
|
<Corner SeqID="6" CompoundMarkID="5" Rounding="SP" ZoneSize="3"/>
|
||||||
|
</CompoundMarkSequence>
|
||||||
|
<Course>
|
||||||
|
<CompoundMark CompoundMarkID="1" Name="Start Line">
|
||||||
|
<Mark SeqId="1" Name="PRO" TargetLat="32.296577" TargetLng="-64.854304" SourceID="101"/>
|
||||||
|
<Mark SeqId="2" Name="PIN" TargetLat="32.293771" TargetLng="-64.855242" SourceID="102"/>
|
||||||
|
</CompoundMark>
|
||||||
|
<CompoundMark CompoundMarkID="2" Name="Marker 1">
|
||||||
|
<Mark Name="Marker1" TargetLat="32.293039" TargetLng="-64.843983" SourceID="103"/>
|
||||||
|
</CompoundMark>
|
||||||
|
<CompoundMark CompoundMarkID="3" Name="Windward Gate">
|
||||||
|
<Mark Name="WGL" SeqId="1" TargetLat="32.28468" TargetLng="-64.850045" SourceID="104"/>
|
||||||
|
<Mark Name="WGR" SeqId="2" TargetLat="32.280164" TargetLng="-64.847591" SourceID="105"/>
|
||||||
|
</CompoundMark>
|
||||||
|
<CompoundMark CompoundMarkID="4" Name="Leeward Gate">
|
||||||
|
<Mark Name="LGL" SeqId="1" TargetLat="32.309693" TargetLng="-64.835249" SourceID="106"/>
|
||||||
|
<Mark Name="LGR" SeqId="2" TargetLat="32.308046" TargetLng="-64.831785" SourceID="107"/>
|
||||||
|
</CompoundMark>
|
||||||
|
<CompoundMark CompoundMarkID="5" Name="Finish Line">
|
||||||
|
<Mark Name="FL" SeqId="1" TargetLat="32.317379" TargetLng="-64.839291" SourceID="108"/>
|
||||||
|
<Mark Name="FR" SeqId="2" TargetLat="32.317257" TargetLng="-64.83626" SourceID="109"/>
|
||||||
|
</CompoundMark>
|
||||||
|
</Course>
|
||||||
|
<CourseLimit>
|
||||||
|
<Limit Lat="32.313922" Lon="-64.837168" SeqID="1"/>
|
||||||
|
<Limit Lat="32.317379" Lon="-64.839291" SeqID="2"/>
|
||||||
|
<Limit Lat="32.317911" Lon="-64.836996" SeqID="3"/>
|
||||||
|
<Limit Lat="32.317257" Lon="-64.83626" SeqID="4"/>
|
||||||
|
<Limit Lat="32.304273" Lon="-64.822834" SeqID="5"/>
|
||||||
|
<Limit Lat="32.279097" Lon="-64.841545" SeqID="6"/>
|
||||||
|
<Limit Lat="32.279604" Lon="-64.849871" SeqID="7"/>
|
||||||
|
<Limit Lat="32.289545" Lon="-64.854162" SeqID="8"/>
|
||||||
|
<Limit Lat="32.290198" Lon="-64.858711" SeqID="9"/>
|
||||||
|
<Limit Lat="32.297164" Lon="-64.856394" SeqID="10"/>
|
||||||
|
<Limit Lat="32.296148" Lon="-64.849184" SeqID="11"/>
|
||||||
|
</CourseLimit>
|
||||||
|
</Race>
|
||||||