SeaSurface files have been added to display the surface in the lobby. Surface is now drawn in the lobby
parent
3301798411
commit
4dcff5c009
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,88 @@
|
||||
package visualiser.utils;
|
||||
|
||||
/**
|
||||
* Perlin Noise Generator
|
||||
*/
|
||||
public class PerlinNoiseGenerator {
|
||||
|
||||
|
||||
/**
|
||||
* Create an array of the given size with values of perlin noise
|
||||
* @param size size of array that you wish to create
|
||||
* @param freq frequency that the noise is to be generated at.
|
||||
* @return noise generated
|
||||
*/
|
||||
public static float[][] createNoise( int size, double freq) {
|
||||
float[][] noiseArray = new float[(int) size][(int) size];
|
||||
|
||||
for (int x = 0; x < size; x++) {
|
||||
for (int y = 0; y < size; y++) {
|
||||
|
||||
double frequency = freq / (double) size;
|
||||
|
||||
double noise = ImprovedNoise.noise(x * frequency, y * frequency, 0);
|
||||
|
||||
noiseArray[x][y] = (float) noise;
|
||||
}
|
||||
}
|
||||
|
||||
return noiseArray;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Perlin noise generator
|
||||
*
|
||||
* // JAVA REFERENCE IMPLEMENTATION OF IMPROVED NOISE - COPYRIGHT 2002 KEN PERLIN.
|
||||
* // http://mrl.nyu.edu/~perlin/paper445.pdf
|
||||
* // http://mrl.nyu.edu/~perlin/noise/
|
||||
*/
|
||||
public final static class ImprovedNoise {
|
||||
static public double noise(double x, double y, double z) {
|
||||
int X = (int)Math.floor(x) & 255, // FIND UNIT CUBE THAT
|
||||
Y = (int)Math.floor(y) & 255, // CONTAINS POINT.
|
||||
Z = (int)Math.floor(z) & 255;
|
||||
x -= Math.floor(x); // FIND RELATIVE X,Y,Z
|
||||
y -= Math.floor(y); // OF POINT IN CUBE.
|
||||
z -= Math.floor(z);
|
||||
double u = fade(x), // COMPUTE FADE CURVES
|
||||
v = fade(y), // FOR EACH OF X,Y,Z.
|
||||
w = fade(z);
|
||||
int A = p[X ]+Y, AA = p[A]+Z, AB = p[A+1]+Z, // HASH COORDINATES OF
|
||||
B = p[X+1]+Y, BA = p[B]+Z, BB = p[B+1]+Z; // THE 8 CUBE CORNERS,
|
||||
|
||||
return lerp(w, lerp(v, lerp(u, grad(p[AA ], x , y , z ), // AND ADD
|
||||
grad(p[BA ], x-1, y , z )), // BLENDED
|
||||
lerp(u, grad(p[AB ], x , y-1, z ), // RESULTS
|
||||
grad(p[BB ], x-1, y-1, z ))),// FROM 8
|
||||
lerp(v, lerp(u, grad(p[AA+1], x , y , z-1 ), // CORNERS
|
||||
grad(p[BA+1], x-1, y , z-1 )), // OF CUBE
|
||||
lerp(u, grad(p[AB+1], x , y-1, z-1 ),
|
||||
grad(p[BB+1], x-1, y-1, z-1 ))));
|
||||
}
|
||||
static double fade(double t) { return t * t * t * (t * (t * 6 - 15) + 10); }
|
||||
static double lerp(double t, double a, double b) { return a + t * (b - a); }
|
||||
static double grad(int hash, double x, double y, double z) {
|
||||
int h = hash & 15; // CONVERT LO 4 BITS OF HASH CODE
|
||||
double u = h<8 ? x : y, // INTO 12 GRADIENT DIRECTIONS.
|
||||
v = h<4 ? y : h==12||h==14 ? x : z;
|
||||
return ((h&1) == 0 ? u : -u) + ((h&2) == 0 ? v : -v);
|
||||
}
|
||||
static final int p[] = new int[512], permutation[] = { 151,160,137,91,90,15,
|
||||
131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
|
||||
190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
|
||||
88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
|
||||
77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
|
||||
102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
|
||||
135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
|
||||
5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
|
||||
223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
|
||||
129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
|
||||
251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
|
||||
49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
|
||||
138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180
|
||||
};
|
||||
static { for (int i=0; i < 256 ; i++) p[256+i] = p[i] = permutation[i]; }
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in new issue