SeaSurface files have been added to display the surface in the lobby. Surface is now drawn in the lobby

This commit is contained in:
hba56
2017-09-12 21:55:23 +12:00
parent 3301798411
commit 4dcff5c009
4 changed files with 356 additions and 5 deletions
@@ -0,0 +1,125 @@
package visualiser.layout;
import javafx.scene.shape.TriangleMesh;
import java.util.ArrayList;
import java.util.List;
/**
* 3D plane
*/
public class Plane3D extends TriangleMesh{
/**
* Length is up down, and width is left right. Drawn on the x-y plane with z kept at 0.
* @param width width of the plane
* @param length length of the plane
* @param subdivisionsWidth number of divisions along the width of the plane
* @param subdivisionsLength number of division along the length of the plane
*/
public Plane3D(float width, float length, int subdivisionsWidth, int subdivisionsLength){
//add texture points and vertex points
float subWidth = width / (float) subdivisionsWidth;
float subLength = length / (float) subdivisionsLength;
ArrayList<Float> pointsList = new ArrayList<>();
ArrayList<Float> textureCoord = new ArrayList<>();
float startW = -width/2;
float startL = -length/2;
for (float l = 0; l <= length; l += subLength) {
for (float w = 0; w <= width; w += subWidth){
//add points
pointsList.add(w + startW);
pointsList.add(l + startL);
pointsList.add(0f);
//addTexture coords
textureCoord.add(1 - w/width);
textureCoord.add(1 - l/length);
}
}
this.getPoints().setAll(copyListToArray(pointsList));
this.getTexCoords().setAll(copyListToArray(textureCoord));
//connect points to make faces
ArrayList<Integer> faces = new ArrayList<>();
int listSize = pointsList.size()/3;
int divsInRow = subdivisionsWidth + 1;
for (int i = 0; i < listSize; i++){
int row = i/divsInRow;
if (row < 1){
continue;
}
boolean notFirstCol = (i) % divsInRow != 0;
boolean notLastCol = (i + 1) % divsInRow != 0;
if (notFirstCol){
faces.add(i);
faces.add(i);
// printPointAtIndex(i);
faces.add(i - divsInRow);
faces.add(i - divsInRow);
// printPointAtIndex(i - divsInRow);
faces.add(i - 1);
faces.add(i - 1);
// printPointAtIndex(i-1);
}
if (notLastCol) {
faces.add(i - divsInRow + 1);
faces.add(i - divsInRow + 1);
// printPointAtIndex(i - divsInRow + 1);
faces.add(i - divsInRow);
faces.add(i - divsInRow);
// printPointAtIndex(i - divsInRow);
faces.add(i);
faces.add(i);
// printPointAtIndex(i);
}
}
this.getFaces().setAll(copyListToIntArray(faces));
}
/**
* Testing function to see if the points are correct
* @param index index that the points correspond to (remember 3 is a point)
*/
private void printPointAtIndex(int index){
int i = index * 3;
float x = this.getPoints().get(i);
float y = this.getPoints().get(i + 1);
float z = this.getPoints().get(i + 2);
System.out.println(String.format("Point at %d is x:%f, y:%f, z:%f", index, x, y, z));
}
/**
* copies the list to a float array because java List.toArray isn't working
* @param list list to copy
* @return array
*/
private static float[] copyListToArray(List<Float> list){
float[] res = new float[list.size()];
for (int i = 0; i < list.size(); i++){
res[i] = list.get(i);
}
return res;
}
/**
* copies the list to an integer array because java List.toArray isn't working
* @param list list to copy
* @return array
*/
private static int[] copyListToIntArray(List<Integer> list){
int[] res = new int[list.size()];
for (int i = 0; i < list.size(); i++){
res[i] = list.get(i);
}
return res;
}
}
@@ -0,0 +1,135 @@
package visualiser.layout;
import javafx.scene.image.Image;
import javafx.scene.image.PixelWriter;
import javafx.scene.image.WritableImage;
import javafx.scene.paint.Color;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.MeshView;
import visualiser.utils.PerlinNoiseGenerator;
/**
* Creates a SeaSurface
*/
public class SeaSurface {
private float[][] noiseArray;
private Subject3D surface;
/**
* Sea Surface Constructor
* @param size size of the sea surface (has to be square for simplicity's sake)
* @param freq frequency the perlin noise is to be generated at
* @param x offset that the sea should be set at position-wise
* @param z offset that the sea should be set at position-wise
*/
public SeaSurface(int size, double freq, double x, double y, double z){
noiseArray = PerlinNoiseGenerator.createNoise(size, freq);
createSurface();
surface.setZ(z);
surface.setY(y);
surface.setX(x);
}
/**
* Creates the sea surface
*/
private void createSurface(){
Image diffuseMap = createImage(noiseArray.length, noiseArray);
PhongMaterial material = new PhongMaterial();
material.setDiffuseMap(diffuseMap);
//material.setSpecularColor(Color.WHITE);
Plane3D seaPlane = new Plane3D(noiseArray.length, noiseArray.length, 10, 10);
MeshView seaSurface = new MeshView(seaPlane);
// Box seaSurface = new Box(noiseArray.length, 0.1, noiseArray.length);
seaSurface.setMaterial(material);
seaSurface.setMouseTransparent(true);
seaSurface.toFront();
//seaSurface.setRotationAxis(new Point3D(1, 0, 0));
//seaSurface.setRotate(90);
surface = new Subject3D(seaSurface);
}
/**
* Create texture for uv mapping
* @param size size of the image to make
* @param noise array of noise
* @return image that is created
*/
private Image createImage(double size, float[][] noise) {
int width = (int) size;
int height = (int) size;
WritableImage wr = new WritableImage(width, height);
PixelWriter pw = wr.getPixelWriter();
//interpolate colours based on noise
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
float value = noise[x][y];
double gray = normalizeValue(value, -.5, .5, 0., 1.);
gray = clamp(gray, 0, 1);
//values to interpolate on
Color brightBlue = new Color(0.06, 0.5, .78, 1);
Color lightBlue = new Color(0.15, 0.68, .88, 1);
Color lighterBlue = new Color(0.28, 0.73, .91, 1);
Color colour = Color.WHITE.interpolate(brightBlue, gray).interpolate(lighterBlue, gray).interpolate(lightBlue, gray);
pw.setColor(x, y, colour);
}
}
return wr;
}
/**
* Nomalises the values so that the colours are correct
* @param value value to normalise
* @param min current min
* @param max current max
* @param newMin new min
* @param newMax new max
* @return returns normalised value
*/
private static double normalizeValue(double value, double min, double max, double newMin, double newMax) {
return (value - min) * (newMax - newMin) / (max - min) + newMin;
}
/**
* clamps a value between a min and max
* @param value value to clamp
* @param min minimum value it can be
* @param max maximum value it can be
* @return result after clamp
*/
private static double clamp(double value, double min, double max) {
if (Double.compare(value, min) < 0)
return min;
if (Double.compare(value, max) > 0)
return max;
return value;
}
/**
* Get surface
* @return the surface so it can be drawn
*/
public Subject3D getSurface(){
return surface;
}
}