mirror of
https://github.com/michaelrausch/Party-Parrots-At-Sea.git
synced 2026-05-09 14:28:43 +00:00
Ported game rendering to 3d environment for boats and markers.
#implement
This commit is contained in:
@@ -5,7 +5,6 @@ import javafx.application.Application;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.scene.Parent;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.SceneAntialiasing;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.stage.Stage;
|
||||
import org.apache.commons.cli.CommandLine;
|
||||
@@ -69,7 +68,7 @@ public class App extends Application {
|
||||
public void start(Stage primaryStage) throws Exception {
|
||||
Parent root = FXMLLoader.load(getClass().getResource("/views/StartScreenView.fxml"));
|
||||
primaryStage.setTitle("Party Parrots at Sea");
|
||||
Scene scene = new Scene(root, 1530, 960, false, SceneAntialiasing.BALANCED);
|
||||
Scene scene = new Scene(root, 1530, 960);
|
||||
scene.getStylesheets().add(getClass().getResource("/css/master.css").toString());
|
||||
primaryStage.setScene(scene);
|
||||
// primaryStage.setMaxWidth(1530);
|
||||
|
||||
@@ -451,6 +451,19 @@ public class GameView extends Pane {
|
||||
raceBorder.getPoints().setAll(boundaryPoints);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rescales the race to the size of the window.
|
||||
*
|
||||
* @param limitingCoordinates the set of geo points that contains the extremities of the race.
|
||||
*/
|
||||
private void rescaleRace(List<GeoPoint> limitingCoordinates) {
|
||||
//Check is called once to avoid unnecessarily change the course limits once the race is running
|
||||
findMinMaxPoint(limitingCoordinates);
|
||||
double minLonToMaxLon = scaleRaceExtremities();
|
||||
calculateReferencePointLocation(minLonToMaxLon);
|
||||
// drawGoogleMap();
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces all tokens in the course with those passed in
|
||||
*
|
||||
@@ -487,18 +500,6 @@ public class GameView extends Pane {
|
||||
});
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Rescales the race to the size of the window.
|
||||
*
|
||||
* @param limitingCoordinates the set of geo points that contains the extremities of the race.
|
||||
*/
|
||||
private void rescaleRace(List<GeoPoint> limitingCoordinates) {
|
||||
//Check is called once to avoid unnecessarily change the course limits once the race is running
|
||||
findMinMaxPoint(limitingCoordinates);
|
||||
double minLonToMaxLon = scaleRaceExtremities();
|
||||
calculateReferencePointLocation(minLonToMaxLon);
|
||||
// drawGoogleMap();
|
||||
}
|
||||
|
||||
private void setSelectedBoat(BoatObject bo, Boolean isSelected) {
|
||||
if (this.selectedBoat == bo && !isSelected) {
|
||||
|
||||
@@ -1,13 +1,40 @@
|
||||
package seng302.visualiser;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javafx.animation.AnimationTimer;
|
||||
import javafx.application.Platform;
|
||||
import javafx.geometry.Point2D;
|
||||
import javafx.geometry.Point3D;
|
||||
import javafx.scene.*;
|
||||
import javafx.scene.Group;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.ParallelCamera;
|
||||
import javafx.scene.SceneAntialiasing;
|
||||
import javafx.scene.SubScene;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.scene.input.KeyEvent;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.scene.paint.PhongMaterial;
|
||||
import javafx.scene.shape.Sphere;
|
||||
import javafx.scene.paint.Paint;
|
||||
import javafx.scene.shape.Polygon;
|
||||
import javafx.scene.text.Text;
|
||||
import javafx.scene.transform.Rotate;
|
||||
import javafx.scene.transform.Scale;
|
||||
import javafx.scene.transform.Translate;
|
||||
import seng302.visualiser.fxObjects.assets_3D.BoatMeshType;
|
||||
import seng302.gameServer.messages.RoundingSide;
|
||||
import seng302.model.ClientYacht;
|
||||
import seng302.model.GeoPoint;
|
||||
import seng302.model.Limit;
|
||||
import seng302.model.mark.CompoundMark;
|
||||
import seng302.model.mark.Corner;
|
||||
import seng302.model.mark.Mark;
|
||||
import seng302.utilities.GeoUtility;
|
||||
import seng302.visualiser.fxObjects.assets_2D.AnnotationBox;
|
||||
import seng302.visualiser.fxObjects.assets_2D.BoatObject;
|
||||
import seng302.visualiser.fxObjects.assets_2D.CourseBoundary;
|
||||
import seng302.visualiser.fxObjects.assets_2D.Gate;
|
||||
import seng302.visualiser.fxObjects.assets_3D.ModelFactory;
|
||||
import seng302.visualiser.fxObjects.assets_3D.ModelType;
|
||||
|
||||
@@ -22,104 +49,458 @@ public class GameView3D {
|
||||
|
||||
Group root3D;
|
||||
SubScene view;
|
||||
PerspectiveCamera camera;
|
||||
ParallelCamera camera;
|
||||
Group gameObjects;
|
||||
|
||||
private double bufferSize = 0;
|
||||
private double canvasWidth = 200;
|
||||
private double canvasHeight = 200;
|
||||
private boolean horizontalInversion = false;
|
||||
|
||||
|
||||
|
||||
|
||||
private double distanceScaleFactor;
|
||||
private ScaleDirection scaleDirection;
|
||||
private GeoPoint minLatPoint, minLonPoint, maxLatPoint, maxLonPoint;
|
||||
private double referencePointX, referencePointY;
|
||||
private double metersPerPixelX, metersPerPixelY;
|
||||
|
||||
final double SCALE_DELTA = 1.1;
|
||||
|
||||
private Text fpsDisplay = new Text();
|
||||
private Polygon raceBorder = new CourseBoundary();
|
||||
|
||||
/* Note that if either of these is null then values for it have not been added and the other
|
||||
should be used as the limits of the map. */
|
||||
private List<Limit> borderPoints;
|
||||
private Map<Mark, Group> markerObjects;
|
||||
|
||||
private Map<ClientYacht, BoatObject> boatObjects = new HashMap<>();
|
||||
private Map<ClientYacht, AnnotationBox> annotations = new HashMap<>();
|
||||
private BoatObject selectedBoat = null;
|
||||
private Group annotationsGroup = new Group();
|
||||
private Group wakesGroup = new Group();
|
||||
private Group boatObjectGroup = new Group();
|
||||
private Group trails = new Group();
|
||||
private Group markers = new Group();
|
||||
private Group tokens = new Group();
|
||||
private List<CompoundMark> course = new ArrayList<>();
|
||||
private List<Node> mapTokens;
|
||||
|
||||
private ImageView mapImage = new ImageView();
|
||||
|
||||
//FRAME RATE
|
||||
|
||||
private AnimationTimer timer;
|
||||
private int NUM_SAMPLES = 10;
|
||||
private final long[] frameTimes = new long[NUM_SAMPLES];
|
||||
private Double frameRate = 60.0;
|
||||
private int frameTimeIndex = 0;
|
||||
private boolean arrayFilled = false;
|
||||
private ClientYacht playerYacht;
|
||||
private double windDir = 0.0;
|
||||
|
||||
double scaleFactor = 1;
|
||||
|
||||
private enum ScaleDirection {
|
||||
HORIZONTAL,
|
||||
VERTICAL
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public GameView3D () {
|
||||
camera = new PerspectiveCamera(true);
|
||||
// camera = new PerspectiveCamera(true);
|
||||
camera = new ParallelCamera();
|
||||
camera.getTransforms().addAll(
|
||||
new Translate(0,0, -DEFAULT_CAMERA_DEPTH)
|
||||
);
|
||||
camera.setFarClip(Double.MAX_VALUE);
|
||||
camera.setNearClip(0.1);
|
||||
camera.setFieldOfView(FOV);
|
||||
// camera.setFieldOfView(FOV);
|
||||
gameObjects = new Group();
|
||||
gameObjects.getTransforms().add(new Scale(4,4,4));
|
||||
root3D = new Group(camera, gameObjects);
|
||||
view = new SubScene(
|
||||
root3D, 1000, 1000, true, SceneAntialiasing.BALANCED
|
||||
);
|
||||
view.setCamera(camera);
|
||||
view.setFill(Color.SKYBLUE);
|
||||
Sphere s = new Sphere(1);
|
||||
s.setMaterial(new PhongMaterial(Color.RED));
|
||||
Sphere left = new Sphere(1);
|
||||
left.setMaterial(new PhongMaterial(Color.LEMONCHIFFON));
|
||||
left.getTransforms().add(new Translate(-Math.tan(Math.toRadians(FOV / 2)) * DEFAULT_CAMERA_DEPTH, 0, 0));
|
||||
Sphere right = new Sphere(1);
|
||||
right.setMaterial(new PhongMaterial(Color.ROSYBROWN));
|
||||
right.getTransforms().add(new Translate(Math.tan(Math.toRadians(FOV / 2)) * DEFAULT_CAMERA_DEPTH, 0, 0));
|
||||
Sphere top = new Sphere(1);
|
||||
top.setMaterial(new PhongMaterial(Color.TEAL));
|
||||
top.getTransforms().add(new Translate(0,-Math.tan(Math.toRadians(FOV / 2)) * DEFAULT_CAMERA_DEPTH, 0));
|
||||
Sphere bottom = new Sphere(1);
|
||||
bottom.setMaterial(new PhongMaterial(Color.BLANCHEDALMOND));
|
||||
bottom.getTransforms().add(new Translate(0, Math.tan(Math.toRadians(FOV / 2)) * DEFAULT_CAMERA_DEPTH, 0));
|
||||
|
||||
Node boat = ModelFactory.boatGameView(BoatMeshType.DINGHY, Color.BLUE).getAssets();
|
||||
Node boat2 = ModelFactory.boatGameView(BoatMeshType.DINGHY, Color.BROWN).getAssets();
|
||||
boat2.getTransforms().add(new Translate(0,20, 0));
|
||||
Node boat3 = ModelFactory.boatGameView(BoatMeshType.DINGHY, Color.RED).getAssets();
|
||||
boat3.getTransforms().add(new Translate(0,-20, 0));
|
||||
|
||||
Node sMarker = ModelFactory.importModel(ModelType.START_MARKER).getAssets();
|
||||
sMarker.getTransforms().add(0, new Translate(30, 30, 0));
|
||||
|
||||
Node fMarker = ModelFactory.importModel(ModelType.FINISH_MARKER).getAssets();
|
||||
fMarker.getTransforms().add(0, new Translate(30, -30, 0));
|
||||
|
||||
Node marker = ModelFactory.importModel(ModelType.PLAIN_MARKER).getAssets();
|
||||
marker.getTransforms().add(0, new Translate(30, 0, 0));
|
||||
|
||||
Node coin = ModelFactory.importModel(ModelType.VELOCITY_COIN).getAssets();
|
||||
coin.setTranslateX(coin.getTranslateX() - 30);
|
||||
|
||||
camera.getTransforms().add(new Rotate(30, new Point3D(1,0,0)));
|
||||
camera.setLayoutX(camera.getLayoutX()-400);
|
||||
camera.setLayoutY(camera.getLayoutX()-600);
|
||||
// gameObjects.getChildren().addAll(raceBorder, markers, tokens);
|
||||
gameObjects.getChildren().addAll(
|
||||
ModelFactory.importModel(ModelType.OCEAN).getAssets(),
|
||||
s, left, right, top, bottom,
|
||||
boat, boat2, boat3,
|
||||
sMarker, fMarker, marker,
|
||||
coin
|
||||
ModelFactory.importModel(ModelType.OCEAN).getAssets(), markers
|
||||
);
|
||||
|
||||
// Sphere s = new Sphere(1);
|
||||
// s.setMaterial(new PhongMaterial(Color.RED));
|
||||
// Sphere left = new Sphere(1);
|
||||
// left.setMaterial(new PhongMaterial(Color.LEMONCHIFFON));
|
||||
// left.getTransforms().add(new Translate(-Math.tan(Math.toRadians(FOV / 2)) * DEFAULT_CAMERA_DEPTH, 0, 0));
|
||||
// Sphere right = new Sphere(1);
|
||||
// right.setMaterial(new PhongMaterial(Color.ROSYBROWN));
|
||||
// right.getTransforms().add(new Translate(Math.tan(Math.toRadians(FOV / 2)) * DEFAULT_CAMERA_DEPTH, 0, 0));
|
||||
// Sphere top = new Sphere(1);
|
||||
// top.setMaterial(new PhongMaterial(Color.TEAL));
|
||||
// top.getTransforms().add(new Translate(0,-Math.tan(Math.toRadians(FOV / 2)) * DEFAULT_CAMERA_DEPTH, 0));
|
||||
// Sphere bottom = new Sphere(1);
|
||||
// bottom.setMaterial(new PhongMaterial(Color.BLANCHEDALMOND));
|
||||
// bottom.getTransforms().add(new Translate(0, Math.tan(Math.toRadians(FOV / 2)) * DEFAULT_CAMERA_DEPTH, 0));
|
||||
//
|
||||
// Node boat = ModelFactory.boatGameView(BoatMeshType.DINGHY, Color.BLUE).getAssets();
|
||||
// Node boat2 = ModelFactory.boatGameView(BoatMeshType.DINGHY, Color.BROWN).getAssets();
|
||||
// boat2.getTransforms().add(new Translate(0,20, 0));
|
||||
// Node boat3 = ModelFactory.boatGameView(BoatMeshType.DINGHY, Color.RED).getAssets();
|
||||
// boat3.getTransforms().add(new Translate(0,-20, 0));
|
||||
//
|
||||
// Node sMarker = ModelFactory.importModel(ModelType.START_MARKER).getAssets();
|
||||
// sMarker.getTransforms().add(0, new Translate(30, 30, 0));
|
||||
//
|
||||
// Node fMarker = ModelFactory.importModel(ModelType.FINISH_MARKER).getAssets();
|
||||
// fMarker.getTransforms().add(0, new Translate(30, -30, 0));
|
||||
//
|
||||
// Node marker = ModelFactory.importModel(ModelType.PLAIN_MARKER).getAssets();
|
||||
// marker.getTransforms().add(0, new Translate(30, 0, 0));
|
||||
//
|
||||
// Node coin = ModelFactory.importModel(ModelType.VELOCITY_COIN).getAssets();
|
||||
// coin.setTranslateX(coin.getTranslateX() - 30);
|
||||
//
|
||||
// gameObjects.getChildren().addAll(
|
||||
// ModelFactory.importModel(ModelType.OCEAN).getAssets(),
|
||||
// s, left, right, top, bottom,
|
||||
// boat, boat2, boat3,
|
||||
// sMarker, fMarker, marker,
|
||||
// coin
|
||||
// );
|
||||
|
||||
view.sceneProperty().addListener((obs, old, scene) -> {
|
||||
if (scene!=null)
|
||||
enableCameraMovement(scene);
|
||||
if (scene != null) {
|
||||
scene.addEventHandler(KeyEvent.KEY_PRESSED, this::cameraMovement);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void enableCameraMovement(Scene s) {
|
||||
s.setOnKeyPressed(event -> {
|
||||
switch (event.getCode()) {
|
||||
case UP:
|
||||
camera.getTransforms().addAll(new Rotate(0.5, new Point3D(1,0,0)));
|
||||
break;
|
||||
case DOWN:
|
||||
camera.getTransforms().addAll(new Rotate(-0.5, new Point3D(1,0,0)));
|
||||
break;
|
||||
case LEFT:
|
||||
camera.getTransforms().addAll(new Rotate(-0.5, new Point3D(0,1,0)));
|
||||
break;
|
||||
case RIGHT:
|
||||
camera.getTransforms().addAll(new Rotate(0.5, new Point3D(0,1,0)));
|
||||
break;
|
||||
case SPACE:
|
||||
camera.getTransforms().addAll(new Translate(0, 0, 0.75));
|
||||
break;
|
||||
case Z:
|
||||
camera.getTransforms().addAll(new Translate(0, 0, -0.75));
|
||||
break;
|
||||
case W:
|
||||
camera.getTransforms().addAll(new Translate(0, 1, 0));
|
||||
break;
|
||||
case S:
|
||||
camera.getTransforms().addAll(new Translate(0, -1, 0));
|
||||
break;
|
||||
case A:
|
||||
camera.getTransforms().addAll(new Translate(-1, 0, 0));
|
||||
break;
|
||||
case D:
|
||||
camera.getTransforms().addAll(new Translate(1, 0, 0));
|
||||
break;
|
||||
public void updateCourse(List<CompoundMark> newCourse, List<Corner> sequence) {
|
||||
markerObjects = new HashMap<>();
|
||||
|
||||
for (Corner corner : sequence) { //Makes course out of all compound marks.
|
||||
for (CompoundMark compoundMark : newCourse) {
|
||||
if (corner.getCompoundMarkID() == compoundMark.getId()) {
|
||||
course.add(compoundMark);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: 16/08/17 Updating mark roundings here. It should not happen here. Nor should it be done this way.
|
||||
for (Corner corner : sequence){
|
||||
CompoundMark compoundMark = course.get(corner.getSeqID() - 1);
|
||||
compoundMark.setRoundingSide(
|
||||
RoundingSide.getRoundingSide(corner.getRounding())
|
||||
);
|
||||
}
|
||||
|
||||
final List<Gate> gates = new ArrayList<>();
|
||||
Paint colour = Color.BLACK;
|
||||
//Creates new markers
|
||||
for (CompoundMark cMark : newCourse) {
|
||||
//Set start and end colour
|
||||
// if (cMark.getId() == sequence.get(0).getCompoundMarkID()) {
|
||||
// colour = Color.GREEN;
|
||||
// } else if (cMark.getId() == sequence.get(sequence.size() - 1).getCompoundMarkID()) {
|
||||
// colour = Color.RED;
|
||||
// }
|
||||
//Create mark dots
|
||||
for (Mark mark : cMark.getMarks()) {
|
||||
makeAndBindMarker(mark);
|
||||
}
|
||||
// //Create gate line
|
||||
// if (cMark.isGate()) {
|
||||
// for (int i = 1; i < cMark.getMarks().size(); i++) {
|
||||
// gates.add(
|
||||
// makeAndBindGate(
|
||||
// markerObjects.get(cMark.getSubMark(i)),
|
||||
// markerObjects.get(cMark.getSubMark(i + 1)),
|
||||
// colour
|
||||
// )
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
// colour = Color.BLACK;
|
||||
}
|
||||
|
||||
//Scale race to markers if there is no border.
|
||||
if (borderPoints == null) {
|
||||
rescaleRace(new ArrayList<>(markerObjects.keySet()));
|
||||
}
|
||||
//Move the Markers to initial position.
|
||||
markerObjects.forEach(((mark, marker) -> {
|
||||
Point2D p2d = findScaledXY(mark.getLat(), mark.getLng());
|
||||
System.out.println(mark.toString() + " " + p2d.toString());
|
||||
marker.setLayoutX(p2d.getX());
|
||||
marker.setLayoutY(p2d.getY());
|
||||
}));
|
||||
Platform.runLater(() -> {
|
||||
markers.getChildren().clear();
|
||||
markers.getChildren().addAll(gates);
|
||||
markers.getChildren().addAll(markerObjects.values());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Marker and binds it's position to the given Mark.
|
||||
*
|
||||
* @param observableMark The mark to bind the marker to.
|
||||
*/
|
||||
private void makeAndBindMarker(Mark observableMark) {
|
||||
|
||||
Group marker = ModelFactory.importModel(ModelType.PLAIN_MARKER).getAssets();
|
||||
|
||||
markerObjects.put(observableMark, marker);
|
||||
observableMark.addPositionListener((mark, lat, lon) -> {
|
||||
Point2D p2d = findScaledXY(lat, lon);
|
||||
markerObjects.get(mark).setLayoutX(p2d.getX());
|
||||
markerObjects.get(mark).setLayoutY(p2d.getY());
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the class variables minLatPoint, maxLatPoint, minLonPoint, maxLonPoint to the point with
|
||||
* the leftmost point, rightmost point, southern most point and northern most point
|
||||
* respectively.
|
||||
*/
|
||||
private void findMinMaxPoint(List<GeoPoint> points) {
|
||||
List<GeoPoint> sortedPoints = new ArrayList<>(points);
|
||||
sortedPoints.sort(Comparator.comparingDouble(GeoPoint::getLat));
|
||||
minLatPoint = new GeoPoint(sortedPoints.get(0).getLat(), sortedPoints.get(0).getLng());
|
||||
GeoPoint maxLat = sortedPoints.get(sortedPoints.size() - 1);
|
||||
maxLatPoint = new GeoPoint(maxLat.getLat(), maxLat.getLng());
|
||||
|
||||
sortedPoints.sort(Comparator.comparingDouble(GeoPoint::getLng));
|
||||
minLonPoint = new GeoPoint(sortedPoints.get(0).getLat(), sortedPoints.get(0).getLng());
|
||||
GeoPoint maxLon = sortedPoints.get(sortedPoints.size() - 1);
|
||||
maxLonPoint = new GeoPoint(maxLon.getLat(), maxLon.getLng());
|
||||
if (maxLonPoint.getLng() - minLonPoint.getLng() > 180) {
|
||||
horizontalInversion = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the location of a reference point, this is always the point with minimum latitude,
|
||||
* in relation to the canvas.
|
||||
*
|
||||
* @param minLonToMaxLon The horizontal distance between the point of minimum longitude to
|
||||
* maximum longitude.
|
||||
*/
|
||||
private void calculateReferencePointLocation(double minLonToMaxLon) {
|
||||
GeoPoint referencePoint = minLatPoint;
|
||||
double referenceAngle;
|
||||
|
||||
if (scaleDirection == ScaleDirection.HORIZONTAL) {
|
||||
referenceAngle = Math.abs(
|
||||
GeoUtility.getBearingRad(referencePoint, minLonPoint)
|
||||
);
|
||||
referencePointX =
|
||||
-100 + distanceScaleFactor * Math.sin(referenceAngle) * GeoUtility
|
||||
.getDistance(referencePoint, minLonPoint);
|
||||
referenceAngle = Math.abs(GeoUtility.getDistance(referencePoint, maxLatPoint));
|
||||
referencePointY = -100 + canvasHeight - (bufferSize + bufferSize);
|
||||
referencePointY -= distanceScaleFactor * Math.cos(referenceAngle) * GeoUtility
|
||||
.getDistance(referencePoint, maxLatPoint);
|
||||
referencePointY = referencePointY / 2;
|
||||
referencePointY += bufferSize;
|
||||
referencePointY += distanceScaleFactor * Math.cos(referenceAngle) * GeoUtility
|
||||
.getDistance(referencePoint, maxLatPoint);
|
||||
} else {
|
||||
referencePointY = -100 + canvasHeight - bufferSize;
|
||||
referenceAngle = Math.abs(
|
||||
Math.toRadians(
|
||||
GeoUtility.getDistance(referencePoint, minLonPoint)
|
||||
)
|
||||
);
|
||||
referencePointX = -100 + bufferSize;
|
||||
referencePointX += distanceScaleFactor * Math.sin(referenceAngle) * GeoUtility
|
||||
.getDistance(referencePoint, minLonPoint);
|
||||
referencePointX +=
|
||||
((canvasWidth - (bufferSize + bufferSize)) - (minLonToMaxLon * distanceScaleFactor))
|
||||
/ 2;
|
||||
}
|
||||
if (horizontalInversion) {
|
||||
referencePointX = -100 + canvasWidth - bufferSize - (referencePointX - bufferSize);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Finds the scale factor necessary to fit all race markers within the onscreen map and assigns
|
||||
* it to distanceScaleFactor Returns the max horizontal distance of the map.
|
||||
*/
|
||||
private double scaleRaceExtremities() {
|
||||
|
||||
double vertAngle = Math.abs(
|
||||
GeoUtility.getBearingRad(minLatPoint, maxLatPoint)
|
||||
);
|
||||
double vertDistance =
|
||||
Math.cos(vertAngle) * GeoUtility.getDistance(minLatPoint, maxLatPoint);
|
||||
double horiAngle = Math.abs(
|
||||
GeoUtility.getBearingRad(minLonPoint, maxLonPoint)
|
||||
);
|
||||
if (horiAngle <= (Math.PI / 2)) {
|
||||
horiAngle = (Math.PI / 2) - horiAngle;
|
||||
} else {
|
||||
horiAngle = horiAngle - (Math.PI / 2);
|
||||
}
|
||||
double horiDistance =
|
||||
Math.cos(horiAngle) * GeoUtility.getDistance(minLonPoint, maxLonPoint);
|
||||
|
||||
double vertScale = (canvasHeight - (bufferSize + bufferSize)) / vertDistance;
|
||||
|
||||
if ((horiDistance * vertScale) > (canvasWidth - (bufferSize + bufferSize))) {
|
||||
distanceScaleFactor = (canvasWidth - (bufferSize + bufferSize)) / horiDistance;
|
||||
scaleDirection = ScaleDirection.HORIZONTAL;
|
||||
} else {
|
||||
distanceScaleFactor = vertScale;
|
||||
scaleDirection = ScaleDirection.VERTICAL;
|
||||
}
|
||||
return horiDistance;
|
||||
}
|
||||
|
||||
private Point2D findScaledXY(GeoPoint unscaled) {
|
||||
return findScaledXY(unscaled.getLat(), unscaled.getLng());
|
||||
}
|
||||
|
||||
private Point2D findScaledXY(double unscaledLat, double unscaledLon) {
|
||||
double distanceFromReference;
|
||||
double angleFromReference;
|
||||
double xAxisLocation = referencePointX;
|
||||
double yAxisLocation = referencePointY;
|
||||
|
||||
angleFromReference = GeoUtility.getBearingRad(
|
||||
minLatPoint, new GeoPoint(unscaledLat, unscaledLon)
|
||||
);
|
||||
distanceFromReference = GeoUtility.getDistance(
|
||||
minLatPoint, new GeoPoint(unscaledLat, unscaledLon)
|
||||
);
|
||||
if (angleFromReference >= 0 && angleFromReference <= Math.PI / 2) {
|
||||
xAxisLocation += Math
|
||||
.round(distanceScaleFactor * Math.sin(angleFromReference) * distanceFromReference);
|
||||
yAxisLocation -= Math
|
||||
.round(distanceScaleFactor * Math.cos(angleFromReference) * distanceFromReference);
|
||||
} else if (angleFromReference >= 0) {
|
||||
angleFromReference = angleFromReference - Math.PI / 2;
|
||||
xAxisLocation += Math
|
||||
.round(distanceScaleFactor * Math.cos(angleFromReference) * distanceFromReference);
|
||||
yAxisLocation += Math
|
||||
.round(distanceScaleFactor * Math.sin(angleFromReference) * distanceFromReference);
|
||||
} else if (angleFromReference < 0 && angleFromReference >= -Math.PI / 2) {
|
||||
angleFromReference = Math.abs(angleFromReference);
|
||||
xAxisLocation -= Math
|
||||
.round(distanceScaleFactor * Math.sin(angleFromReference) * distanceFromReference);
|
||||
yAxisLocation -= Math
|
||||
.round(distanceScaleFactor * Math.cos(angleFromReference) * distanceFromReference);
|
||||
} else {
|
||||
angleFromReference = Math.abs(angleFromReference) - Math.PI / 2;
|
||||
xAxisLocation -= Math
|
||||
.round(distanceScaleFactor * Math.cos(angleFromReference) * distanceFromReference);
|
||||
yAxisLocation += Math
|
||||
.round(distanceScaleFactor * Math.sin(angleFromReference) * distanceFromReference);
|
||||
}
|
||||
if (horizontalInversion) {
|
||||
xAxisLocation = canvasWidth - bufferSize - (xAxisLocation - bufferSize);
|
||||
}
|
||||
return new Point2D(xAxisLocation, yAxisLocation);
|
||||
}
|
||||
|
||||
public void cameraMovement(KeyEvent event) {
|
||||
switch (event.getCode()) {
|
||||
case UP:
|
||||
camera.getTransforms().addAll(new Rotate(0.5, new Point3D(1,0,0)));
|
||||
break;
|
||||
case DOWN:
|
||||
camera.getTransforms().addAll(new Rotate(-0.5, new Point3D(1,0,0)));
|
||||
break;
|
||||
case LEFT:
|
||||
camera.getTransforms().addAll(new Rotate(-0.5, new Point3D(0,1,0)));
|
||||
break;
|
||||
case RIGHT:
|
||||
camera.getTransforms().addAll(new Rotate(0.5, new Point3D(0,1,0)));
|
||||
break;
|
||||
case X:
|
||||
camera.getTransforms().addAll(new Translate(0, 0, 1.5));
|
||||
break;
|
||||
case Z:
|
||||
camera.getTransforms().addAll(new Translate(0, 0, -1.5));
|
||||
break;
|
||||
case W:
|
||||
camera.getTransforms().addAll(new Translate(0, 1, 0));
|
||||
break;
|
||||
case S:
|
||||
camera.getTransforms().addAll(new Translate(0, -1, 0));
|
||||
break;
|
||||
case A:
|
||||
camera.getTransforms().addAll(new Translate(-1, 0, 0));
|
||||
break;
|
||||
case D:
|
||||
camera.getTransforms().addAll(new Translate(1, 0, 0));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rescales the race to the size of the window.
|
||||
*
|
||||
* @param limitingCoordinates the set of geo points that contains the extremities of the race.
|
||||
*/
|
||||
private void rescaleRace(List<GeoPoint> limitingCoordinates) {
|
||||
//Check is called once to avoid unnecessarily change the course limits once the race is running
|
||||
findMinMaxPoint(limitingCoordinates);
|
||||
double minLonToMaxLon = scaleRaceExtremities();
|
||||
calculateReferencePointLocation(minLonToMaxLon);
|
||||
// drawGoogleMap();
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws all the boats.
|
||||
* @param yachts The yachts to set in the race
|
||||
*/
|
||||
public void setBoats(List<ClientYacht> yachts) {
|
||||
BoatObject newBoat;
|
||||
final List<Group> wakes = new ArrayList<>();
|
||||
for (ClientYacht clientYacht : yachts) {
|
||||
Color colour = clientYacht.getColour();
|
||||
newBoat = new BoatObject();
|
||||
// newBoat.addSelectedBoatListener(this::setSelectedBoat);
|
||||
newBoat.setFill(colour);
|
||||
boatObjects.put(clientYacht, newBoat);
|
||||
// createAndBindAnnotationBox(clientYacht, colour);
|
||||
// wakesGroup.getChildren().add(newBoat.getWake());
|
||||
// wakes.add(newBoat.getWake());
|
||||
boatObjectGroup.getChildren().add(newBoat);
|
||||
// trails.getChildren().add(newBoat.getTrail());
|
||||
|
||||
clientYacht.addLocationListener((boat, lat, lon, heading, sailIn, velocity) -> {
|
||||
BoatObject bo = boatObjects.get(boat);
|
||||
Point2D p2d = findScaledXY(lat, lon);
|
||||
bo.moveTo(p2d.getX(), p2d.getY(), heading, velocity, sailIn, windDir);
|
||||
// annotations.get(boat).setLocation(p2d.getX(), p2d.getY());
|
||||
bo.setTrajectory(
|
||||
heading,
|
||||
velocity,
|
||||
metersPerPixelX,
|
||||
metersPerPixelY);
|
||||
});
|
||||
}
|
||||
// annotationsGroup.getChildren().addAll(annotations.values());
|
||||
Platform.runLater(() -> {
|
||||
gameObjects.getChildren().addAll(boatObjectGroup);
|
||||
// gameObjects.addAll(trails);
|
||||
// gameObjects.addAll(wakes);
|
||||
// gameObjects.addAll(annotationsGroup);
|
||||
// gameObjects.addAll(boatObjectGroup);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -42,8 +42,7 @@ import seng302.model.RaceState;
|
||||
import seng302.model.mark.CompoundMark;
|
||||
import seng302.model.mark.Mark;
|
||||
import seng302.model.stream.xml.parser.RaceXMLData;
|
||||
import seng302.visualiser.GameView;
|
||||
import seng302.visualiser.controllers.annotations.Annotation;
|
||||
import seng302.visualiser.GameView3D;
|
||||
import seng302.visualiser.controllers.annotations.ImportantAnnotationController;
|
||||
import seng302.visualiser.controllers.annotations.ImportantAnnotationDelegate;
|
||||
import seng302.visualiser.controllers.annotations.ImportantAnnotationsState;
|
||||
@@ -86,7 +85,7 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
||||
private Map<Integer, ClientYacht> participants;
|
||||
private Map<Integer, CompoundMark> markers;
|
||||
private RaceXMLData courseData;
|
||||
private GameView gameView;
|
||||
private GameView3D gameView;
|
||||
private RaceState raceState;
|
||||
|
||||
private Timeline timerTimeline;
|
||||
@@ -140,32 +139,32 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
||||
});
|
||||
|
||||
updateOrder(raceState.getPlayerPositions());
|
||||
gameView = new GameView();
|
||||
gameView.setFrameRateFXText(fpsDisplay);
|
||||
Platform.runLater(() -> contentAnchorPane.getChildren().add(0, gameView));
|
||||
gameView.setBoats(new ArrayList<>(participants.values()));
|
||||
gameView.updateBorder(raceData.getCourseLimit());
|
||||
gameView.updateTokens(raceData.getTokens());
|
||||
gameView.updateCourse(
|
||||
new ArrayList<>(raceData.getCompoundMarks().values()), raceData.getMarkSequence()
|
||||
);
|
||||
gameView.enableZoom();
|
||||
gameView.setBoatAsPlayer(player);
|
||||
gameView.startRace();
|
||||
|
||||
raceState.addCollisionListener(gameView::drawCollision);
|
||||
raceState.windDirectionProperty().addListener((obs, oldDirection, newDirection) -> {
|
||||
gameView.setWindDir(newDirection.doubleValue());
|
||||
Platform.runLater(() -> updateWindDirection(newDirection.doubleValue()));
|
||||
});
|
||||
raceState.windSpeedProperty().addListener((obs, oldSpeed, newSpeed) ->
|
||||
Platform.runLater(() -> updateWindSpeed(newSpeed.doubleValue()))
|
||||
gameView = new GameView3D();
|
||||
// gameView.setFrameRateFXText(fpsDisplay);
|
||||
Platform.runLater(() -> contentAnchorPane.getChildren().add(0, gameView.getAssets()));
|
||||
gameView.setBoats(new ArrayList<>(participants.values()));
|
||||
// gameView.updateBorder(raceData.getCourseLimit());
|
||||
// gameView.updateTokens(raceData.getTokens());
|
||||
gameView.updateCourse(
|
||||
new ArrayList<>(raceData.getCompoundMarks().values()), raceData.getMarkSequence()
|
||||
);
|
||||
Platform.runLater(() -> {
|
||||
updateWindDirection(raceState.windDirectionProperty().doubleValue());
|
||||
updateWindSpeed(raceState.getWindSpeed());
|
||||
});
|
||||
gameView.setWindDir(raceState.windDirectionProperty().doubleValue());
|
||||
// gameView.enableZoom();
|
||||
// gameView.setBoatAsPlayer(player);
|
||||
// gameView.startRace();
|
||||
|
||||
// raceState.addCollisionListener(gameView::drawCollision);
|
||||
// raceState.windDirectionProperty().addListener((obs, oldDirection, newDirection) -> {
|
||||
// gameView.setWindDir(newDirection.doubleValue());
|
||||
// Platform.runLater(() -> updateWindDirection(newDirection.doubleValue()));
|
||||
// });
|
||||
// raceState.windSpeedProperty().addListener((obs, oldSpeed, newSpeed) ->
|
||||
// Platform.runLater(() -> updateWindSpeed(newSpeed.doubleValue()))
|
||||
// );
|
||||
// Platform.runLater(() -> {
|
||||
// updateWindDirection(raceState.windDirectionProperty().doubleValue());
|
||||
// updateWindSpeed(raceState.getWindSpeed());
|
||||
// });
|
||||
// gameView.setWindDir(raceState.windDirectionProperty().doubleValue());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -207,9 +206,9 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
||||
}
|
||||
|
||||
private void initialiseFPSCheckBox() {
|
||||
toggleFps.selectedProperty().addListener((obs, oldVal, newVal) ->
|
||||
gameView.setFPSVisibility(toggleFps.isSelected())
|
||||
);
|
||||
// toggleFps.selectedProperty().addListener((obs, oldVal, newVal) ->
|
||||
// gameView.setFPSVisibility(toggleFps.isSelected())
|
||||
// );
|
||||
}
|
||||
|
||||
private void initialiseAnnotationSlider() {
|
||||
@@ -550,7 +549,7 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
||||
//Null check is if the listener is fired but nothing selected
|
||||
yachtSelectionComboBox.valueProperty().addListener((obs, lastSelection, selectedBoat) -> {
|
||||
if (selectedBoat != null) {
|
||||
gameView.selectBoat(selectedBoat);
|
||||
// gameView.selectBoat(selectedBoat);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -582,31 +581,31 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
||||
}
|
||||
|
||||
private void setAnnotations(Integer annotationLevel) {
|
||||
switch (annotationLevel) {
|
||||
// No Annotations
|
||||
case 0:
|
||||
gameView.setAnnotationVisibilities(
|
||||
false, false, false, false, false, false
|
||||
);
|
||||
break;
|
||||
// Important Annotations
|
||||
case 1:
|
||||
gameView.setAnnotationVisibilities(
|
||||
importantAnnotations.getAnnotationState(Annotation.NAME),
|
||||
importantAnnotations.getAnnotationState(Annotation.SPEED),
|
||||
importantAnnotations.getAnnotationState(Annotation.ESTTIMETONEXTMARK),
|
||||
importantAnnotations.getAnnotationState(Annotation.LEGTIME),
|
||||
importantAnnotations.getAnnotationState(Annotation.TRACK),
|
||||
importantAnnotations.getAnnotationState(Annotation.WAKE)
|
||||
);
|
||||
break;
|
||||
// All Annotations
|
||||
case 2:
|
||||
gameView.setAnnotationVisibilities(
|
||||
true, true, true, true, true, true
|
||||
);
|
||||
break;
|
||||
}
|
||||
// switch (annotationLevel) {
|
||||
// // No Annotations
|
||||
// case 0:
|
||||
// gameView.setAnnotationVisibilities(
|
||||
// false, false, false, false, false, false
|
||||
// );
|
||||
// break;
|
||||
// // Important Annotations
|
||||
// case 1:
|
||||
// gameView.setAnnotationVisibilities(
|
||||
// importantAnnotations.getAnnotationState(Annotation.NAME),
|
||||
// importantAnnotations.getAnnotationState(Annotation.SPEED),
|
||||
// importantAnnotations.getAnnotationState(Annotation.ESTTIMETONEXTMARK),
|
||||
// importantAnnotations.getAnnotationState(Annotation.LEGTIME),
|
||||
// importantAnnotations.getAnnotationState(Annotation.TRACK),
|
||||
// importantAnnotations.getAnnotationState(Annotation.WAKE)
|
||||
// );
|
||||
// break;
|
||||
// // All Annotations
|
||||
// case 2:
|
||||
// gameView.setAnnotationVisibilities(
|
||||
// true, true, true, true, true, true
|
||||
// );
|
||||
// break;
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
@@ -630,7 +629,7 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
||||
}
|
||||
|
||||
public void updateRaceData (RaceXMLData raceData) {
|
||||
gameView.updateBorder(raceData.getCourseLimit());
|
||||
gameView.updateTokens(raceData.getTokens());
|
||||
// gameView.updateBorder(raceData.getCourseLimit());
|
||||
// gameView.updateTokens(raceData.getTokens());
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,6 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javafx.application.Platform;
|
||||
import javafx.geometry.Point2D;
|
||||
import javafx.geometry.Point3D;
|
||||
import javafx.scene.AmbientLight;
|
||||
import javafx.scene.Group;
|
||||
import javafx.scene.Node;
|
||||
@@ -103,9 +102,9 @@ public class BoatObject extends Group {
|
||||
private void initChildren(double... points) {
|
||||
boatPoly = makeBoatPolygon();
|
||||
boatPoly.getAssets().getTransforms().addAll(
|
||||
new Rotate(-40, new Point3D(1,0,0)),
|
||||
rotation,
|
||||
new Rotate(-90, new Point3D(0,0,1))
|
||||
// new Rotate(-40, new Point3D(1,0,0)),
|
||||
rotation
|
||||
// new Rotate(-90, new Point3D(0,0,1))
|
||||
);
|
||||
boatPoly.getAssets().getTransforms().add(new Scale(5, 5, 5));
|
||||
// boatPoly.setDrawMode(DrawMode.FILL);
|
||||
@@ -219,21 +218,21 @@ public class BoatObject extends Group {
|
||||
rotateTo(rotation, sailIn, windDir);
|
||||
boatPoly.getAssets().setLayoutX(x);
|
||||
boatPoly.getAssets().setLayoutY(y);
|
||||
if (sailIn) {
|
||||
// sail.getPoints().clear();
|
||||
// sail.getPoints().addAll(0.0, 0.0, 4.0, 1.5, 8.0, 3.0, 12.0, 3.5, 16.0, 3.0, 20.0, 1.5, 24.0, 0.0);
|
||||
// sail.getPoints().addAll(0.0, 0.0, 24.0, 0.0);
|
||||
sail.setLayoutX(x);
|
||||
sail.setLayoutY(y);
|
||||
} else {
|
||||
animateSail();
|
||||
sail.setLayoutX(x);
|
||||
sail.setLayoutY(y);
|
||||
}
|
||||
wake.setLayoutX(x);
|
||||
wake.setLayoutY(y);
|
||||
// if (sailIn) {
|
||||
//// sail.getPoints().clear();
|
||||
//// sail.getPoints().addAll(0.0, 0.0, 4.0, 1.5, 8.0, 3.0, 12.0, 3.5, 16.0, 3.0, 20.0, 1.5, 24.0, 0.0);
|
||||
//// sail.getPoints().addAll(0.0, 0.0, 24.0, 0.0);
|
||||
// sail.setLayoutX(x);
|
||||
// sail.setLayoutY(y);
|
||||
// } else {
|
||||
//// animateSail();
|
||||
// sail.setLayoutX(x);
|
||||
// sail.setLayoutY(y);
|
||||
// }
|
||||
// wake.setLayoutX(x);
|
||||
// wake.setLayoutY(y);
|
||||
});
|
||||
wake.setRotation(rotation, velocity);
|
||||
// wake.setRotation(rotation, velocity);
|
||||
// rotateTo(rotation);
|
||||
// boatPoly.setLayoutX(x);
|
||||
// boatPoly.setLayoutY(y);
|
||||
@@ -263,7 +262,7 @@ public class BoatObject extends Group {
|
||||
|
||||
private void rotateTo(double heading, boolean sailsIn, double windDir) {
|
||||
rotation.setAngle(heading);
|
||||
if (sailsIn) {
|
||||
if (!sailsIn) {
|
||||
boatPoly.showSail();
|
||||
Double sailWindOffset = 30.0;
|
||||
Double upwindAngleLimit = 15.0;
|
||||
|
||||
@@ -8,6 +8,7 @@ import javafx.scene.AmbientLight;
|
||||
import javafx.scene.Group;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.scene.paint.PhongMaterial;
|
||||
import javafx.scene.shape.Circle;
|
||||
import javafx.scene.shape.MeshView;
|
||||
import javafx.scene.transform.Rotate;
|
||||
import javafx.scene.transform.Scale;
|
||||
@@ -53,7 +54,8 @@ public class ModelFactory {
|
||||
public static BoatModel boatGameView(BoatMeshType boatType, Color primaryColour) {
|
||||
Group boatAssets = getUnmodifiedBoatModel(boatType, primaryColour);
|
||||
boatAssets.getTransforms().setAll(
|
||||
new Scale(0.5, 0.5, 0.5)
|
||||
new Rotate(-90, new Point3D(0,0,1)),
|
||||
new Scale(0.2, 0.2, 0.2)
|
||||
);
|
||||
return new BoatModel(boatAssets, null, boatType);
|
||||
}
|
||||
@@ -77,9 +79,14 @@ public class ModelFactory {
|
||||
}
|
||||
|
||||
public static Model importModel(ModelType tokenType) {
|
||||
ColModelImporter importer = new ColModelImporter();
|
||||
importer.read(ModelFactory.class.getResource("/meshes/" + tokenType.filename));
|
||||
Group assets = new Group(importer.getImport());
|
||||
Group assets;
|
||||
if (tokenType.filename == null) {
|
||||
assets = new Group();
|
||||
} else {
|
||||
ColModelImporter importer = new ColModelImporter();
|
||||
importer.read(ModelFactory.class.getResource("/meshes/" + tokenType.filename));
|
||||
assets = new Group(importer.getImport());
|
||||
}
|
||||
switch (tokenType) {
|
||||
case VELOCITY_COIN:
|
||||
return makeCoinPickup(assets);
|
||||
@@ -122,9 +129,13 @@ public class ModelFactory {
|
||||
return new Model(area, null);
|
||||
}
|
||||
|
||||
private static Model makeOcean(Group plane) {
|
||||
plane.setScaleY(100);
|
||||
plane.setScaleX(100);
|
||||
return new Model(plane, null);
|
||||
private static Model makeOcean(Group group) {
|
||||
// group.setScaleY(Double.MAX_VALUE);
|
||||
// group.setScaleX(Double.MAX_VALUE);
|
||||
// group.getTransforms().add(new Rotate(90, new Point3D(1, 0, 0)));
|
||||
Circle ocean = new Circle(0,0,1000, Color.DEEPSKYBLUE);
|
||||
ocean.setStroke(Color.TRANSPARENT);
|
||||
group.getChildren().add(ocean);
|
||||
return new Model(group, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package seng302.visualiser.fxObjects.assets_3D;
|
||||
|
||||
/**
|
||||
* Enum for models. Values should be the name of the file and files should be .dae files with texture
|
||||
* information included.
|
||||
* information included. Can be null in which case assets are assumed to be empty.
|
||||
*/
|
||||
public enum ModelType {
|
||||
|
||||
@@ -11,7 +11,9 @@ public enum ModelType {
|
||||
START_MARKER ("start_marker.dae"),
|
||||
PLAIN_MARKER ("plain_marker.dae"),
|
||||
MARK_AREA ("mark_area.dae"),
|
||||
OCEAN ("ocean.dae");
|
||||
OCEAN (null),
|
||||
BORDER_PYLON (null),
|
||||
BORDER_BARRIER (null);
|
||||
|
||||
final String filename;
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,100 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
|
||||
<asset>
|
||||
<contributor>
|
||||
<author>Blender User</author>
|
||||
<authoring_tool>Blender 2.78.0 commit date:2016-09-26, commit time:12:42, hash:4bb1e22</authoring_tool>
|
||||
</contributor>
|
||||
<created>2017-09-09T12:27:53</created>
|
||||
<modified>2017-09-09T12:27:53</modified>
|
||||
<unit name="meter" meter="1"/>
|
||||
<up_axis>Z_UP</up_axis>
|
||||
</asset>
|
||||
<library_images/>
|
||||
<library_effects>
|
||||
<effect id="Material_001-effect">
|
||||
<profile_COMMON>
|
||||
<technique sid="common">
|
||||
<phong>
|
||||
<emission>
|
||||
<color sid="emission">0 0 0 1</color>
|
||||
</emission>
|
||||
<ambient>
|
||||
<color sid="ambient">0 0 0 1</color>
|
||||
</ambient>
|
||||
<diffuse>
|
||||
<color sid="diffuse">0.64 0.001709759 0 1</color>
|
||||
</diffuse>
|
||||
<specular>
|
||||
<color sid="specular">0.5 0.5 0.5 1</color>
|
||||
</specular>
|
||||
<shininess>
|
||||
<float sid="shininess">50</float>
|
||||
</shininess>
|
||||
<index_of_refraction>
|
||||
<float sid="index_of_refraction">1</float>
|
||||
</index_of_refraction>
|
||||
</phong>
|
||||
</technique>
|
||||
</profile_COMMON>
|
||||
</effect>
|
||||
</library_effects>
|
||||
<library_materials>
|
||||
<material id="Material_001-material" name="Material_001">
|
||||
<instance_effect url="#Material_001-effect"/>
|
||||
</material>
|
||||
</library_materials>
|
||||
<library_geometries>
|
||||
<geometry id="Plane-mesh" name="Plane">
|
||||
<mesh>
|
||||
<source id="Plane-mesh-positions">
|
||||
<float_array id="Plane-mesh-positions-array" count="24">-1 -1 0 1 -1 0 -1 1 0 1 1 0 -1 -1 0.002058923 1 -1 0.002058923 -1 1 0.002058923 1 1 0.002058923</float_array>
|
||||
<technique_common>
|
||||
<accessor source="#Plane-mesh-positions-array" count="8" stride="3">
|
||||
<param name="X" type="float"/>
|
||||
<param name="Y" type="float"/>
|
||||
<param name="Z" type="float"/>
|
||||
</accessor>
|
||||
</technique_common>
|
||||
</source>
|
||||
<source id="Plane-mesh-normals">
|
||||
<float_array id="Plane-mesh-normals-array" count="18">0 0 -1 0 0 1 0 1 0 0 -1 0 1 0 0 -1 0 0</float_array>
|
||||
<technique_common>
|
||||
<accessor source="#Plane-mesh-normals-array" count="6" stride="3">
|
||||
<param name="X" type="float"/>
|
||||
<param name="Y" type="float"/>
|
||||
<param name="Z" type="float"/>
|
||||
</accessor>
|
||||
</technique_common>
|
||||
</source>
|
||||
<vertices id="Plane-mesh-vertices">
|
||||
<input semantic="POSITION" source="#Plane-mesh-positions"/>
|
||||
</vertices>
|
||||
<polylist material="Material_001-material" count="12">
|
||||
<input semantic="VERTEX" source="#Plane-mesh-vertices" offset="0"/>
|
||||
<input semantic="NORMAL" source="#Plane-mesh-normals" offset="1"/>
|
||||
<vcount>3 3 3 3 3 3 3 3 3 3 3 3 </vcount>
|
||||
<p>2 0 1 0 0 0 5 1 6 1 4 1 2 2 7 2 3 2 1 3 4 3 0 3 3 4 5 4 1 4 0 5 6 5 2 5 2 0 3 0 1 0 5 1 7 1 6 1 2 2 6 2 7 2 1 3 5 3 4 3 3 4 7 4 5 4 0 5 4 5 6 5</p>
|
||||
</polylist>
|
||||
</mesh>
|
||||
</geometry>
|
||||
</library_geometries>
|
||||
<library_controllers/>
|
||||
<library_visual_scenes>
|
||||
<visual_scene id="Scene" name="Scene">
|
||||
<node id="Plane" name="Plane" type="NODE">
|
||||
<matrix sid="transform">8 0 0 0 0 8 0 0 0 0 8 0 0 0 0 1</matrix>
|
||||
<instance_geometry url="#Plane-mesh" name="Plane">
|
||||
<bind_material>
|
||||
<technique_common>
|
||||
<instance_material symbol="Material_001-material" target="#Material_001-material"/>
|
||||
</technique_common>
|
||||
</bind_material>
|
||||
</instance_geometry>
|
||||
</node>
|
||||
</visual_scene>
|
||||
</library_visual_scenes>
|
||||
<scene>
|
||||
<instance_visual_scene url="#Scene"/>
|
||||
</scene>
|
||||
</COLLADA>
|
||||
Reference in New Issue
Block a user