Merge terrain library into main project

This commit is contained in:
austin 2021-06-13 12:57:16 -04:00
parent beac110bc6
commit 8c4f902652
17 changed files with 3528 additions and 375 deletions

View File

@ -100,14 +100,6 @@
<artifactId>commons-crypto</artifactId>
<version>1.1.0</version>
</dependency>
<dependency>
<groupId>electrosphere</groupId>
<artifactId>TerrainGen</artifactId>
<version>0.1</version>
</dependency>
</dependencies>

View File

@ -382,7 +382,7 @@ public class LoadingThread extends Thread {
// }
for(int i = 0; i < 50; i++){
for(int i = 0; i < 10; i++){
Random rand = new Random();
String treePath = "Models/tree1.fbx";
Entity tree = EntityUtils.spawnDrawableEntity(treePath);

View File

@ -2,8 +2,8 @@ package electrosphere.game.terrain;
import com.google.gson.Gson;
import electrosphere.main.Globals;
import electrosphere.terraingen.TerrainGen;
import electrosphere.terraingen.models.TerrainModel;
import electrosphere.game.terrain.generation.TerrainGen;
import electrosphere.game.terrain.generation.models.TerrainModel;
import electrosphere.util.Utilities;
import java.io.File;
import java.io.IOException;

View File

@ -0,0 +1,17 @@
package electrosphere.game.terrain.generation;
/**
*
* @author satellite
*/
class Continent {
public int dim_x;
public int dim_y;
public int size = 0;
public int[][] elevation;
public int[][] chart_Precipitation;
public int[][] chart_Temperature;
public int[][] chart_Climate;
public int[][] chart_Wind_Macro;
public Region[][] regions;
}

View File

@ -0,0 +1,144 @@
package electrosphere.game.terrain.generation;
/**
*
* @author satellite
*/
class Hotspot {
int x;
int y;
int life_current;
int life_max;
int magnitude_current;
int magnitude_max;
TerrainGenerator parent;
public Hotspot(int x, int y, int life_max, int magnitude, TerrainGenerator parent) {
this.x = x;
this.y = y;
this.life_current = 0;
this.life_max = life_max;
this.magnitude_current = 1;
this.magnitude_max = magnitude;
this.parent = parent;
}
public void simulate() {
if ((1.0f - (Math.abs((life_max / 2) - life_current) / (life_max / 2))) > 0.8f) {
magnitude_current = magnitude_max;
} else if ((1.0f - (Math.abs((life_max / 2) - life_current) / (life_max / 2))) > 0.6f) {
magnitude_current = (int) (0.8f * magnitude_max);
} else if ((1.0f - (Math.abs((life_max / 2) - life_current) / (life_max / 2))) > 0.4f) {
magnitude_current = (int) (0.6f * magnitude_max);
} else if ((1.0f - (Math.abs((life_max / 2) - life_current) / (life_max / 2))) > 0.2f) {
magnitude_current = (int) (0.4f * magnitude_max);
} else {
magnitude_current = (int) (0.2f * magnitude_max);
}
//affect asthenosphere heat
if (magnitude_current == 1) {
parent.asthenosphere_Heat[x][y] = (int) (100.0f - Math.abs((life_max / 2) - life_current) * 100 / (life_max / 2));
} else if (magnitude_current == 2) {
parent.asthenosphere_Heat[x][y] = (int) (100.0f - Math.abs((life_max / 2) - life_current) * 100 / (life_max / 2));
if (x + 1 < parent.DIMENSION) {
parent.asthenosphere_Heat[x + 1][y] = (int) (100.0f - Math.abs((life_max / 2) - life_current) * 100 / (life_max / 2));
}
if (x - 1 >= 0) {
parent.asthenosphere_Heat[x - 1][y] = (int) (100.0f - Math.abs((life_max / 2) - life_current) * 100 / (life_max / 2));
}
if (y + 1 < parent.DIMENSION) {
parent.asthenosphere_Heat[x][y + 1] = (int) (100.0f - Math.abs((life_max / 2) - life_current) * 100 / (life_max / 2));
}
if (y - 1 >= 0) {
parent.asthenosphere_Heat[x][y - 1] = (int) (100.0f - Math.abs((life_max / 2) - life_current) * 100 / (life_max / 2));
}
} else if (magnitude_current == 3) {
parent.asthenosphere_Heat[x][y] = (int) (100.0f - Math.abs((life_max / 2) - life_current) * 100 / (life_max / 2));
if (x + 1 < parent.DIMENSION) {
parent.asthenosphere_Heat[x + 1][y] = (int) (100.0f - Math.abs((life_max / 2) - life_current) * 100 / (life_max / 2));
}
if (x - 1 >= 0) {
parent.asthenosphere_Heat[x - 1][y] = (int) (100.0f - Math.abs((life_max / 2) - life_current) * 100 / (life_max / 2));
}
if (y + 1 < parent.DIMENSION) {
parent.asthenosphere_Heat[x][y + 1] = (int) (100.0f - Math.abs((life_max / 2) - life_current) * 100 / (life_max / 2));
if (x + 1 < parent.DIMENSION) {
parent.asthenosphere_Heat[x + 1][y + 1] = (int) (100.0f - Math.abs((life_max / 2) - life_current) * 100 / (life_max / 2));
}
if (x - 1 >= 0) {
parent.asthenosphere_Heat[x - 1][y + 1] = (int) (100.0f - Math.abs((life_max / 2) - life_current) * 100 / (life_max / 2));
}
}
if (y - 1 >= 0) {
parent.asthenosphere_Heat[x][y - 1] = (int) (100.0f - Math.abs((life_max / 2) - life_current) * 100 / (life_max / 2));
if (x + 1 < parent.DIMENSION) {
parent.asthenosphere_Heat[x + 1][y - 1] = (int) (100.0f - Math.abs((life_max / 2) - life_current) * 100 / (life_max / 2));
}
if (x - 1 >= 0) {
parent.asthenosphere_Heat[x - 1][y - 1] = (int) (100.0f - Math.abs((life_max / 2) - life_current) * 100 / (life_max / 2));
}
}
} else if (magnitude_current == 4) {
parent.asthenosphere_Heat[x][y] = (int) (100.0f - Math.abs((life_max / 2) - life_current) * 100 / (life_max / 2));
if (x + 1 < parent.DIMENSION) {
parent.asthenosphere_Heat[x + 1][y] = (int) (100.0f - Math.abs((life_max / 2) - life_current) * 100 / (life_max / 2));
}
if (x - 1 >= 0) {
parent.asthenosphere_Heat[x - 1][y] = (int) (100.0f - Math.abs((life_max / 2) - life_current) * 100 / (life_max / 2));
}
if (y + 1 < parent.DIMENSION) {
parent.asthenosphere_Heat[x][y + 1] = (int) (100.0f - Math.abs((life_max / 2) - life_current) * 100 / (life_max / 2));
if (x + 1 < parent.DIMENSION) {
parent.asthenosphere_Heat[x + 1][y + 1] = (int) (100.0f - Math.abs((life_max / 2) - life_current) * 100 / (life_max / 2));
}
if (x - 1 >= 0) {
parent.asthenosphere_Heat[x - 1][y + 1] = (int) (100.0f - Math.abs((life_max / 2) - life_current) * 100 / (life_max / 2));
}
}
if (y - 1 >= 0) {
parent.asthenosphere_Heat[x][y - 1] = (int) (100.0f - Math.abs((life_max / 2) - life_current) * 100 / (life_max / 2));
if (x + 1 < parent.DIMENSION) {
parent.asthenosphere_Heat[x + 1][y - 1] = (int) (100.0f - Math.abs((life_max / 2) - life_current) * 100 / (life_max / 2));
}
if (x - 1 >= 0) {
parent.asthenosphere_Heat[x - 1][y - 1] = (int) (100.0f - Math.abs((life_max / 2) - life_current) * 100 / (life_max / 2));
}
}
} else if (magnitude_current == 5) {
parent.asthenosphere_Heat[x][y] = (int) (100.0f - Math.abs((life_max / 2) - life_current) * 100 / (life_max / 2));
if (x + 1 < parent.DIMENSION) {
parent.asthenosphere_Heat[x + 1][y] = (int) (100.0f - Math.abs((life_max / 2) - life_current) * 100 / (life_max / 2));
}
if (x - 1 >= 0) {
parent.asthenosphere_Heat[x - 1][y] = (int) (100.0f - Math.abs((life_max / 2) - life_current) * 100 / (life_max / 2));
}
if (y + 1 < parent.DIMENSION) {
parent.asthenosphere_Heat[x][y + 1] = (int) (100.0f - Math.abs((life_max / 2) - life_current) * 100 / (life_max / 2));
if (x + 1 < parent.DIMENSION) {
parent.asthenosphere_Heat[x + 1][y + 1] = (int) (100.0f - Math.abs((life_max / 2) - life_current) * 100 / (life_max / 2));
}
if (x - 1 >= 0) {
parent.asthenosphere_Heat[x - 1][y + 1] = (int) (100.0f - Math.abs((life_max / 2) - life_current) * 100 / (life_max / 2));
}
}
if (y - 1 >= 0) {
parent.asthenosphere_Heat[x][y - 1] = (int) (100.0f - Math.abs((life_max / 2) - life_current) * 100 / (life_max / 2));
if (x + 1 < parent.DIMENSION) {
parent.asthenosphere_Heat[x + 1][y - 1] = (int) (100.0f - Math.abs((life_max / 2) - life_current) * 100 / (life_max / 2));
}
if (x - 1 >= 0) {
parent.asthenosphere_Heat[x - 1][y - 1] = (int) (100.0f - Math.abs((life_max / 2) - life_current) * 100 / (life_max / 2));
}
}
}
life_current++;
}
public void add_to_elevation(int x, int y, int magnitude){
parent.elevation[x][y] = parent.elevation[x][y] + magnitude;
if(parent.elevation[x][y] > 100){
parent.elevation[x][y] = 100;
}
}
}

View File

@ -0,0 +1,218 @@
package electrosphere.game.terrain.generation;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
/**
*
* @author satellite
*/
class InterpolationDisplay extends JPanel{
@Override
public void paint(Graphics g) {
if(TerrainGen.display_toggle == 0) {
for (int x = 0; x < TerrainGen.DIMENSION; x++) {
for (int y = 0; y < TerrainGen.DIMENSION; y++) {
if (TerrainGen.mountain_parsed[x][y] > TerrainGen.mountain_Threshold - 1) {
g.setColor(new Color((int) (TerrainGen.elevation[x][y] / 100.0 * 254 * (TerrainGen.brightness / 100.0)), 1, 1));
} else if (TerrainGen.ocean_parsed[x][y] > TerrainGen.ocean_Threshold - 1) {
g.setColor(
new Color(
1,
(int) ((TerrainGen.elevation[x][y] + 50) / 100.0 * 254 * (TerrainGen.brightness / 100.0)),
(int) ((TerrainGen.elevation[x][y] + 50) / 100.0 * 254 * (TerrainGen.brightness / 100.0))
)
);
} else {
g.setColor(new Color(1, (int) (TerrainGen.elevation[x][y] / 100.0 * 254 * (TerrainGen.brightness / 100.0)), 1));
}
g.fillRect(x * 2 + 25, y * 2 + 25, 2, 2);
}
}
} else if(TerrainGen.display_toggle == 1){
for (int x = 0; x < TerrainGen.DIMENSION; x++) {
for (int y = 0; y < TerrainGen.DIMENSION; y++) {
if (TerrainGen.precipitation_Chart[x][y] > 0) {
g.setColor(
new Color(
1,
(int) ((TerrainGen.elevation[x][y]) / 100.0 * 254 * (TerrainGen.brightness / 100.0)),
(int) ((TerrainGen.elevation[x][y]) / 100.0 * 254 * (TerrainGen.brightness / 100.0))
)
);
} else {
g.setColor(new Color((int) (TerrainGen.elevation[x][y] / 100.0 * 254 * (TerrainGen.brightness / 100.0)), 1, 1));
}
g.fillRect(x * 2 + 25, y * 2 + 25, 2, 2);
}
}
} else if(TerrainGen.display_toggle == 2){
for (int x = 0; x < TerrainGen.DIMENSION; x++) {
for (int y = 0; y < TerrainGen.DIMENSION; y++) {
// if (TerrainInterpolator.precipitation_Chart[x][y] > 0) {
g.setColor(
new Color(
(int) ((TerrainGen.temperature_Chart[x][y]) / 100.0 * 254 * (TerrainGen.brightness / 100.0)),
(int) ((TerrainGen.elevation[x][y]) / 100.0 * 254 * (TerrainGen.brightness / 100.0)),
1
)
);
// } else {
// g.setColor(new Color((int) (TerrainInterpolator.elevation[x][y] / 100.0 * 254 * (TerrainInterpolator.brightness / 100.0)), 1, 1));
// }
g.fillRect(x * 2 + 25, y * 2 + 25, 2, 2);
}
}
} else if(TerrainGen.display_toggle == 3){
for (int x = 0; x < TerrainGen.DIMENSION; x++) {
for (int y = 0; y < TerrainGen.DIMENSION; y++) {
if (TerrainGen.climate_category[x][y] == 0) {
g.setColor(Color.BLUE);
// g.setColor(
// new Color(
// 1,
// (int) ((TerrainInterpolator.elevation[x][y]) / 100.0 * 254 * (TerrainInterpolator.brightness / 100.0)),
// (int) ((TerrainInterpolator.elevation[x][y]) / 100.0 * 254 * (TerrainInterpolator.brightness / 100.0))
// )
// );
} else if(TerrainGen.climate_category[x][y] == 1){
g.setColor(Color.RED);
// g.setColor(
// new Color(
// 1,
// (int) ((TerrainInterpolator.elevation[x][y]) / 100.0 * 254 * (TerrainInterpolator.brightness / 100.0)),
// 1
// )
// );
} else if(TerrainGen.climate_category[x][y] == 2){
g.setColor(Color.GREEN);
// g.setColor(
// new Color(
// 1,
// (int) ((TerrainInterpolator.elevation[x][y]) / 100.0 * 254 * (TerrainInterpolator.brightness / 100.0)),
// 1
// )
// );
} else if(TerrainGen.climate_category[x][y] == 3){
g.setColor(Color.YELLOW);
// g.setColor(
// new Color(
// 1,
// 1,
// (int) ((TerrainInterpolator.elevation[x][y]) / 100.0 * 254 * (TerrainInterpolator.brightness / 100.0))
// )
// );
} else if(TerrainGen.climate_category[x][y] == 4){
g.setColor(
new Color(
(int) ((TerrainGen.elevation[x][y]) / 100.0 * 254 * (TerrainGen.brightness / 100.0)),
(int) ((TerrainGen.elevation[x][y]) / 100.0 * 254 * (TerrainGen.brightness / 100.0)),
1
)
);
g.setColor(Color.ORANGE);
} else if(TerrainGen.climate_category[x][y] == 5){
g.setColor(
new Color(
(int) ((TerrainGen.elevation[x][y]) / 100.0 * 254 * (TerrainGen.brightness / 100.0)),
1,
(int) ((TerrainGen.elevation[x][y]) / 100.0 * 254 * (TerrainGen.brightness / 100.0))
)
);
g.setColor(Color.BLACK);
} else if(TerrainGen.climate_category[x][y] == 6){
g.setColor(
new Color(
(int) ((TerrainGen.elevation[x][y]) / 100.0 * 254 * (TerrainGen.brightness / 100.0)),
(int) ((TerrainGen.elevation[x][y]) / 100.0 * 254 * (TerrainGen.brightness / 100.0)),
(int) ((TerrainGen.elevation[x][y]) / 100.0 * 254 * (TerrainGen.brightness / 100.0))
)
);
} else {
g.setColor(new Color((int) (TerrainGen.elevation[x][y] / 100.0 * 254 * (TerrainGen.brightness / 100.0)), 1, 1));
}
g.fillRect(x * 2 + 25, y * 2 + 25, 2, 2);
}
}
} else if(TerrainGen.display_toggle == 4){
for (int x = 0; x < TerrainGen.DIMENSION; x++) {
for (int y = 0; y < TerrainGen.DIMENSION; y++) {
if (TerrainGen.continent_Number[x][y] > 8) {
g.setColor(Color.PINK);
} else if (TerrainGen.continent_Number[x][y] > 7) {
g.setColor(Color.DARK_GRAY);
} else if (TerrainGen.continent_Number[x][y] > 6) {
g.setColor(Color.CYAN);
} else if (TerrainGen.continent_Number[x][y] > 5) {
g.setColor(Color.GRAY);
} else if (TerrainGen.continent_Number[x][y] > 4) {
g.setColor(Color.orange);
} else if (TerrainGen.continent_Number[x][y] > 3) {
g.setColor(Color.green);
} else if (TerrainGen.continent_Number[x][y] > 2) {
g.setColor(Color.yellow);
} else if (TerrainGen.continent_Number[x][y] > 1) {
g.setColor(Color.blue);
} else if (TerrainGen.continent_Number[x][y] > 0) {
g.setColor(Color.red);
} else {
g.setColor(Color.BLACK);
}
g.fillRect(x * 2 + 25, y * 2 + 25, 2, 2);
}
}
} else if (TerrainGen.display_toggle == 5) {
Continent current = TerrainGen.continents.get(TerrainGen.current_Continent);
g.drawString("dim_x: " + current.dim_x, 20, 20);
g.drawString("dim_y: " + current.dim_y, 20, 30);
for (int x = 0; x < current.dim_x; x++) {
for (int y = 0; y < current.dim_y; y++) {
if (current.elevation[x][y] > 10) {
g.setColor(new Color(1, (int) (current.elevation[x][y] / 100.0 * 254 * (TerrainGen.brightness / 100.0)), 1));
g.fillRect(50 + x * 2, 50 + y * 2, 2, 2);
}
}
}
} else if (TerrainGen.display_toggle == 6){
Continent current = TerrainGen.continents.get(TerrainGen.current_Continent);
for(int x = 0; x < Region.REGION_DIMENSION; x++){
for(int y = 0; y < Region.REGION_DIMENSION; y++){
if(current.regions[TerrainGen.current_Region_X][TerrainGen.current_Region_Y].chart_Drainage[x][y] > 0){
g.setColor(Color.BLUE);
} else {
g.setColor(Color.BLACK);
}
g.fillRect(50 + x * 2, 50 + y * 2, 2, 2);
}
}
}
// if(TerrainInterpolator.display_toggle == 0) {
// g.drawString("Elevation Raws", 10, 10);
// for (int x = 0; x < 100; x++) {
// for (int y = 0; y < 100; y++) {
// g.setColor(new Color(1, (int) (TerrainInterpolator.elevation[x][y] / 100.0 * 254 * (TerrainInterpolator.brightness / 100.0)), 1));
// g.fillRect(x * 2 + 25, y * 2 + 25, 2, 2);
// }
// }
// } else if(TerrainInterpolator.display_toggle == 1) {
// g.drawString("Parsed Mountains", 10, 10);
// for (int x = 0; x < 100; x++) {
// for (int y = 0; y < 100; y++) {
// if(TerrainInterpolator.mountain_parsed[x][y] > TerrainInterpolator.mountain_Threshold - 1){
// g.setColor(new Color((int) (TerrainInterpolator.elevation[x][y] / 100.0 * 254 * (TerrainInterpolator.brightness / 100.0)), 1, 1));
// } else {
// g.setColor(new Color(1, (int) (TerrainInterpolator.elevation[x][y] / 100.0 * 254 * (TerrainInterpolator.brightness / 100.0)), 1));
// }
// g.fillRect(x * 2 + 25, y * 2 + 25, 2, 2);
// }
// }
// } else if(TerrainInterpolator.display_toggle == 2){
// g.drawString("Oceans", 10, 10);
// } else if(TerrainInterpolator.display_toggle == 3){
// g.drawString("Continents", 10, 10);
// } else if(TerrainInterpolator.display_toggle == 4){
// g.drawString("Temperatures", 10, 10);
// }
}
}

View File

@ -0,0 +1,9 @@
package electrosphere.game.terrain.generation;
/**
*
* @author satellite
*/
class MidoceanicRidge {
}

View File

@ -0,0 +1,19 @@
package electrosphere.game.terrain.generation;
/**
*
* @author satellite
*/
class Region {
public static int REGION_DIMENSION = 100;
int chart_Elevation[][];
int chart_Drainage[][];
int chart_Max_Water_Flow[][];
int elevation_Goal;
Region neighbors[][];
public boolean finished_Drainage_Simulation = false;
public Region(){
neighbors = new Region[3][3];
neighbors[1][1] = null;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,314 @@
package electrosphere.game.terrain.generation;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Random;
/**
*
* @author satellite
*/
class TerrainGenerator {
static int DIMENSION = 200;
static int[][] asthenosphere_Heat;
static int[][] rock_Hardness;
static int[][] elevation;
static int[][] smoothed_elevation;
static int new_Elevation[][];
static Vector[][] currents;
static ArrayList<Hotspot> spots = new ArrayList();
static int Time = 0;
static final int ELEVATION_DATA_LENGTH = 50;
static int[] elevation_Data;
static int current_Max_Elevation_Data = 1;
static int lifespan = 75000;
public TerrainGenerator(){
}
public void set_Dimension(int new_Dim){
DIMENSION = new_Dim;
}
public void set_Lifespan(int new_Lifespan){
lifespan = new_Lifespan;
}
public void run(){
asthenosphere_Heat = new int[DIMENSION][DIMENSION];
elevation = new int[DIMENSION][DIMENSION];
smoothed_elevation = new int[DIMENSION][DIMENSION];
new_Elevation = new int[DIMENSION][DIMENSION];
currents = new Vector[DIMENSION][DIMENSION];
for(int x = 0; x < DIMENSION; x++){
for(int y = 0; y < DIMENSION; y++){
currents[x][y] = new Vector();
}
}
elevation_Data = new int[ELEVATION_DATA_LENGTH];
for(int x = 0; x < ELEVATION_DATA_LENGTH; x++){
elevation_Data[x] = 0;
}
long last_Time = System.currentTimeMillis();
while(true){
Time++;
if(spots.size() >= 1){
ArrayList<Hotspot> to_Remove = new ArrayList();
Iterator<Hotspot> spot_Iterator = spots.iterator();
while(spot_Iterator.hasNext()){
Hotspot current_Spot = spot_Iterator.next();
if(current_Spot.life_current >= current_Spot.life_max){
to_Remove.add(current_Spot);
}
}
spot_Iterator = to_Remove.iterator();
while(spot_Iterator.hasNext()){
Hotspot current_Spot = spot_Iterator.next();
spots.remove(current_Spot);
}
}
if(spots.size() < 5){
spots.add(new Hotspot(electrosphere.game.terrain.generation.Utilities.random_Integer(0, DIMENSION - 1),electrosphere.game.terrain.generation.Utilities.random_Integer(0, DIMENSION - 1),electrosphere.game.terrain.generation.Utilities.random_Integer(6000, 10000), electrosphere.game.terrain.generation.Utilities.random_Integer(3, 5), this));
}
for(int x = 0; x < DIMENSION; x++){
for(int y = 0; y < DIMENSION; y++){
asthenosphere_Heat[x][y] = 0;
}
}
if(spots.size() >= 1){
Iterator<Hotspot> spot_Iterator = spots.iterator();
while(spot_Iterator.hasNext()){
Hotspot current_Spot = spot_Iterator.next();
current_Spot.simulate();
}
}
// try {
// TimeUnit.MILLISECONDS.sleep(1);
// } catch (InterruptedException ex) {
// }
heat_To_Elevation();
construct_Convection_Cells();
apply_Vectors_To_Elevation();
calculate_Smoothed_Elevations();
if(Time % 500 == 0) {
long new_Time = System.currentTimeMillis();
long time_Delta = new_Time - last_Time;
last_Time = new_Time;
System.out.println("Progress: " + Time + "/" + lifespan + " ETA: " + (time_Delta * (lifespan - Time) / 1000 / 500) + "S");
}
if(Time > lifespan){
break;
}
}
}
public int[][] get_Terrain(){
return elevation;
}
public int[][] get_Terrain_Smoothed(){
return smoothed_elevation;
}
static void heat_To_Elevation(){
for(int x = 0; x < DIMENSION; x++){
for(int y = 0; y < DIMENSION; y++){
if(asthenosphere_Heat[x][y] > 25){
if(electrosphere.game.terrain.generation.Utilities.random_Integer(1, 10) == 10){
elevation[x][y] = elevation[x][y] + 1;
if(elevation[x][y] > 100){
elevation[x][y] = 100;
}
}
}
}
}
}
static void construct_Convection_Cells(){
boolean is_cell_type_1 = false;
int fourth = DIMENSION / 4;
for(int x = 0; x < DIMENSION; x++){
for(int y = 0; y < DIMENSION; y++){
int normalized_x = x;
int normalized_y = y;
if(y < fourth || (y < fourth * 3 && y > (fourth * 2) - 1)){
is_cell_type_1 = true;
if(normalized_y > fourth){
normalized_y = normalized_y - fourth * 2;
}
} else {
is_cell_type_1 = false;
if(normalized_y > fourth * 2 + 1){
normalized_y = normalized_y - fourth * 3;
} else {
normalized_y = normalized_y - fourth;
}
}
while(normalized_x > fourth){
normalized_x = normalized_x - fourth;
}
if(normalized_x < 0){
normalized_x = 0;
}
if(normalized_y < 0){
normalized_y = 0;
}
int eigth = fourth / 2;
normalized_y = normalized_y - eigth;
normalized_x = normalized_x - eigth;
float magnitude = (float)Math.sqrt(Math.pow(normalized_y, 2) + Math.pow(normalized_x, 2));
if(magnitude < fourth / 10){
normalized_x = normalized_x + fourth / 10;
magnitude = (float)Math.sqrt(Math.pow(normalized_y, 2) + Math.pow(normalized_x, 2));
}
double offset_angle = Math.atan2(normalized_y / magnitude, normalized_x / magnitude);
if(offset_angle < 0){
offset_angle = offset_angle + Math.PI * 2;
}
double vector_angle = offset_angle;
if(is_cell_type_1){
offset_angle = offset_angle + Math.PI / 2;
} else {
offset_angle = offset_angle - Math.PI / 2;
}
while(offset_angle > Math.PI * 2){
offset_angle = offset_angle - Math.PI * 2;
}
while(offset_angle < 0){
offset_angle = offset_angle + Math.PI * 2;
}
currents[x][y].x = (int)(99 * Math.cos(offset_angle));
currents[x][y].y = (int)(99 * Math.sin(offset_angle));
}
}
}
static void apply_Vectors_To_Elevation(){
int current_Elev[][] = new int[DIMENSION][DIMENSION];
for(int x = 0; x < DIMENSION; x++){
for(int y = 0; y < DIMENSION; y++){
new_Elevation[x][y] = 0;
current_Elev[x][y] = elevation[x][y];
}
}
for(int x = 0; x < DIMENSION; x++){
for(int y = 0; y < DIMENSION; y++){
boolean transfer = false;
if (electrosphere.game.terrain.generation.Utilities.random_Integer(1, 50) == 1) {
transfer = true;
}
int transfer_goal;
if(electrosphere.game.terrain.generation.Utilities.random_Integer(1, 2)==1){
transfer_goal = electrosphere.game.terrain.generation.Utilities.random_Integer(20, 60);
} else {
transfer_goal = electrosphere.game.terrain.generation.Utilities.random_Integer(0, 60);
}
if(electrosphere.game.terrain.generation.Utilities.random_Integer(1, 2)==1){
if (currents[x][y].x >= 0) {
if (transfer) {
if (x + 1 < DIMENSION) {
while(new_Elevation[x + 1][y] + current_Elev[x + 1][y] < 99 && current_Elev[x][y] > transfer_goal){
new_Elevation[x + 1][y]++;
current_Elev[x][y]--;
}
} else {
}
}
} else {
if (transfer) {
if (x - 1 >= 0) {
while(new_Elevation[x - 1][y] + current_Elev[x - 1][y] < 99 && current_Elev[x][y] > transfer_goal){
new_Elevation[x - 1][y]++;
current_Elev[x][y]--;
}
} else {
}
}
}
} else {
if (currents[x][y].y >= 0) {
if (transfer) {
if (y + 1 < DIMENSION) { // V REPLACE THIS WITH GOAL
while(new_Elevation[x][y + 1] + current_Elev[x][y + 1] < 99 && current_Elev[x][y] > transfer_goal){
new_Elevation[x][y + 1]++;
current_Elev[x][y]--;
}
} else {
}
}
} else {
if (transfer) {
if (y - 1 >= 0) {
while(new_Elevation[x][y - 1] + current_Elev[x][y - 1] < 99 && current_Elev[x][y] > transfer_goal){
new_Elevation[x][y - 1]++;
current_Elev[x][y]--;
}
} else {
}
}
}
}
}
}
for(int x = 0; x < DIMENSION; x++){
for(int y = 0; y < DIMENSION; y++){
new_Elevation[x][y] = new_Elevation[x][y] + current_Elev[x][y];
while(new_Elevation[x][y] > 99){
new_Elevation[x][y] = 99;
}
elevation[x][y] = new_Elevation[x][y];
}
}
}
static void grab_Elevation_Data(){
int new_Elevation_Data_Val = 0;
for(int x = 0; x < DIMENSION; x++){
for(int y = 0; y < DIMENSION; y++){
new_Elevation_Data_Val = new_Elevation_Data_Val + elevation[x][y];
}
}
for(int x = 1; x < ELEVATION_DATA_LENGTH; x++){
elevation_Data[x-1] = elevation_Data[x];
}
elevation_Data[ELEVATION_DATA_LENGTH - 1] = new_Elevation_Data_Val;
if(new_Elevation_Data_Val > current_Max_Elevation_Data){
current_Max_Elevation_Data = new_Elevation_Data_Val;
}
}
static void calculate_Smoothed_Elevations(){
int[][] buffer = new int[DIMENSION][DIMENSION];
for(int x = 1; x < DIMENSION - 2; x++){
for(int y = 1; y < DIMENSION - 2; y++){
buffer[x][y] = elevation[x][y] * 4 * elevation[x+1][y] * 2 + elevation[x-1][y] * 2 + elevation[x][y+1] * 2 +
elevation[x][y-1] * 2 + elevation[x+1][y+1] + elevation[x+1][y-1] + elevation[x-1][y+1] + elevation[x-1][y-1];
buffer[x][y] = (int)(buffer[x][y] / 16.0);
while(buffer[x][y] > 100){
buffer[x][y] = buffer[x][y]/2;
}
smoothed_elevation[x][y] = buffer[x][y];
}
}
for(int x = 1; x < DIMENSION - 2; x++){
for(int y = 1; y < DIMENSION - 2; y++){
buffer[x][y] = smoothed_elevation[x][y] * 4 * smoothed_elevation[x+1][y] * 2 + smoothed_elevation[x-1][y] * 2 + smoothed_elevation[x][y+1] * 2 +
smoothed_elevation[x][y-1] * 2 + smoothed_elevation[x+1][y+1] + smoothed_elevation[x+1][y-1] + smoothed_elevation[x-1][y+1] + smoothed_elevation[x-1][y-1];
buffer[x][y] = (int)(buffer[x][y] / 16.0);
while(buffer[x][y] > 100){
buffer[x][y] = buffer[x][y]/2;
}
smoothed_elevation[x][y] = buffer[x][y];
}
}
}
}

View File

@ -0,0 +1,260 @@
package electrosphere.game.terrain.generation;
import java.awt.Point;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Random;
import java.util.concurrent.TimeUnit;
/**
*
* @author awhoove
*/
class Utilities {
static long seed = 0;
static Random rand = new Random(seed);
public static void seed_Random_Functions(long seed){
rand = new Random(seed);
}
//Finds midpoint of cluster of arbitrary points.
public static Point average_Points(Point[] objects){
Point rVal = null;
int x = 0;
int y = 0;
for(int i = 0; i < objects.length; i++){
x = x + objects[i].x;
y = y + objects[i].y;
}
x = x / objects.length;
y = y / objects.length;
rVal = new Point(x,y);
return rVal;
}
public static void sleep(int milliseconds){
try {
TimeUnit.MILLISECONDS.sleep(milliseconds);
} catch (InterruptedException ex) {
System.out.println("Sleep failed lol.");
}
}
public static int random_Integer(int Min, int Max){
return Min + (int)(rand.nextDouble() * ((Max - Min) + 1));
}
public static int random_Range_Distribution_Even(int ... range){
if(range.length % 2 != 0){
System.out.println("Invalid number of parameters for range in a function call to \"random_Range_Distribution_Even\"!");
return -1;
} else {
int total = 0;
int i = 0;
while(i < range.length/2 + 1){
total = total + range[i+1] - range[i] + 1;
i=i+2;
}
int temp = random_Integer(1,total);
int incrementer = 0;
i = 0;
while(incrementer + range[i+1] - range[i] + 1 < temp){
incrementer = incrementer + range[i+1] - range[i] + 1;
i=i+2;
}
return range[i] + (temp - incrementer) - 1;
}
}
public static float distance_Between_Points(Point point_One, Point point_Two){
float rVal = 0.0f;
rVal = (float)Math.sqrt(Math.pow(point_One.y - point_Two.y, 2) + Math.pow(point_One.x - point_Two.x, 2));
return rVal;
}
public static float angle_Between_Points(Point p1, Point p2){
float rVal = 0.0f;
rVal = (float)Math.atan2(p1.y - p2.y, p1.x - p2.x);
if(rVal < 0){
rVal = rVal + (float)(Math.PI * 2);
}
return rVal;
}
public static Point centerpoint_Of_Circle_From_Three_Points(Point p1, Point p2, Point p3){
Point rVal = null;
final double offset = Math.pow(p2.x, 2) + Math.pow(p2.y, 2);
final double bc = (Math.pow(p1.x, 2) + Math.pow(p1.y, 2) - offset) / 2.0;
final double cd = (offset - Math.pow(p3.x, 2) - Math.pow(p3.y, 2)) / 2.0;
final double det = (p1.x - p2.x) * (p2.y - p3.y) - (p2.x - p3.x) * (p1.y - p2.y);
if (Math.abs(det) < 0.000001) {
return null;
}
final double idet = 1 / det;
final double centerx = (bc * (p2.y - p3.y) - cd * (p1.y - p2.y)) * idet;
final double centery = (cd * (p1.x - p2.x) - bc * (p2.x - p3.x)) * idet;
return new Point((int)centerx,(int)centery);
/*
float slope_1 = (p2.y - p1.y) / (p2.x - p1.x);
float slope_2 = (p3.y - p2.y) / (p3.x - p2.x);
//http://paulbourke.net/geometry/circlesphere/
float intersect_X = (slope_1*slope_2*(p1.y-p3.y)+slope_2*(p1.x+p2.x)-slope_1*(p2.x+p3.x))/(2*(slope_2-slope_1));
float intersect_Y = -(1/slope_1)*(intersect_X - (p2.x+p3.x)/2)+(p2.y+p3.y)/2;
rVal = new Point((int)intersect_X, (int)intersect_Y);
return rVal;
*/
}
public static String pull_Random_String_From_File(File source){
String rVal = "";
int line_To_Go_To;
try {
BufferedReader reader = new BufferedReader(new FileReader(source));
line_To_Go_To = random_Integer(1,Integer.parseInt(reader.readLine()));
int i = 0;
while(i<line_To_Go_To - 1){
reader.readLine();
i++;
if(i > 5000){
break;
}
}
rVal = reader.readLine();
} catch (FileNotFoundException ex) {
System.out.println("Utilities/pull_Random_String_From_File failed to read from "+source+" (File not found).");
} catch (IOException ex){
System.out.println("Utilities/pull_Random_String_From_File failed to read from "+source+" (IOException).");
}
return rVal;
}
public static String pull_Ordered_String_From_File(File source, int dest){
String rVal = "";
try {
BufferedReader reader = new BufferedReader(new FileReader(source));
int i = 0;
while(i<dest){
reader.readLine();
i++;
}
rVal = reader.readLine();
} catch (FileNotFoundException ex) {
System.out.println("Utilities/pull_Random_String_From_File failed to read from "+source+" (File not found).");
} catch (IOException ex){
System.out.println("Utilities/pull_Random_String_From_File failed to read from "+source+" (IOException).");
}
return rVal;
}
public static int number_Of_Char_In_String(String s, char c){
int rVal = 0;
for(int i = 0; i < s.length(); i++){
if(s.charAt(i)==c){
rVal++;
}
}
return rVal;
}
public static int get_Position_Of_Next_Instance_Of_Char_In_String(String s, char c){
int rVal = 0;
for(int i = 0; i < s.length(); i++){
if(s.charAt(i)==c){
rVal = i;
break;
}
}
return rVal;
}
public static int get_Position_Of_Nth_Instance_Of_Char_In_String(String s, char c, int n){
int rVal = 0;
int itterator = n;
for(int i = 0; i < s.length(); i++){
if(s.charAt(i)==c){
if(itterator>0){
itterator--;
} else {
rVal = i;
break;
}
}
}
return rVal;
}
public static float[] linearize_Float_Array_Column_Major(float[][] in){
float[] rVal = new float[in[0].length * in.length];
for(int x = 0; x < in.length; x++){
for(int y = 0; y < in[0].length; y++){
rVal[x*in[0].length + y] = in[x][y];
}
}
return rVal;
}
public static void print_Linearized_Array(float[] in){
for(int i = 0; i < in.length; i++){
System.out.println(in[i]);
}
}
public static float[] linearize_Float_Array_Row_Major(float[][] in){
float[] rVal = new float[in[0].length * in.length];
for(int y = 0; y < in[0].length; y++){
for(int x = 0; x < in.length; x++){
rVal[x*in[0].length + y] = in[x][y];
}
}
return rVal;
}
public static String string_To_First_Space(String s){
String rVal = null;
for(int i = 0; i < s.length(); i++){
if(s.charAt(i)==' '){
rVal = s.substring(0, i);
break;
}
}
if(rVal == null){
rVal = s;
}
return rVal;
}
public static int position_To_First_Space(String s){
int rVal = -1;
for(int i = 0; i < s.length(); i++){
if(s.charAt(i)==' '){
rVal = i;
break;
}
}
return rVal;
}
public static int number_Of_Spaces_In_String(String s){
int rVal = 0;
for(int i = 0; i < s.length(); i++){
if(s.charAt(i)==' '){
rVal++;
}
}
return rVal;
}
public static String get_Face_From_OBJ_Format(String s){
String rVal = "";
int counter = 0;
for(int i = 0; i < s.length(); i++){
counter = i;
if(s.charAt(i)=='/'){
break;
}
}
if(counter+1 == s.length()){
counter++;
}
rVal = s.substring(0, counter);
return rVal;
}
}

View File

@ -0,0 +1,10 @@
package electrosphere.game.terrain.generation;
/**
*
* @author satellite
*/
class Vector {
public int x;
public int y;
}

View File

@ -0,0 +1,694 @@
package electrosphere.game.terrain.generation.models;
import java.util.Random;
public class TerrainModel {
int dynamicInterpolationRatio;
int discreteArrayDimension;
float[][] elevation;
long[][] chunkRandomizer;
float randomDampener = 0.4f;
TerrainModel() {
}
public TerrainModel(int dimension, float[][] elevation, long[][] chunkRandomizer, int dynamicInterpolationRatio){
this.dynamicInterpolationRatio = dynamicInterpolationRatio;
this.discreteArrayDimension = dimension;
this.elevation = elevation;
this.chunkRandomizer = chunkRandomizer;
}
public static TerrainModel constructTerrainModel(int dimension, int dynamicInterpolationRatio){
TerrainModel rVal = new TerrainModel();
rVal.discreteArrayDimension = dimension;
rVal.dynamicInterpolationRatio = dynamicInterpolationRatio;
return rVal;
}
public float[][] getElevation(){
return elevation;
}
public void setRandomDampener(float f){
randomDampener = f;
}
/**
* Dynamically interpolates a chunk of a specific size from the pre-existing elevation map
* @param x The x position on the elevation map to get a chunk from
* @param y The y position on the elevation map to get a chunk from
* @return Dynamically interpolated float array of elevations of chunk
*/
public float[][] getElevationForChunk(int x, int y){
Random rand = new Random(chunkRandomizer[x][y]);
//this is what we intend to return from the function
float[][] rVal = new float[dynamicInterpolationRatio][dynamicInterpolationRatio];
/*
So we're looking at chunk x,y
if this is our grid:
4 0.1 0.2 0.3 0.4
^
| 3 0.1 0.2 0.3 0.4
|
| 2 0.1 0.2 0.3 0.4
x 1 0.1 0.2 0.3 0.4
0 1 2 3
y ---- >
say we're looking at x=2,y=1
"macroValues" should contain the values for bounds x = [1,3] and y = [0,2]
the goal is to have the "center" of the output chunk have the value the
elevation grid at x=2,y=1
*/
//set macroValues
float[][] macroValues = getMacroValuesAtPosition(x,y);
int halfLength = dynamicInterpolationRatio/2;
/*
Four quadrants we're generating
_____________________
|1 |2 |
| | |
| | |
| | |
|__________|__________|
|3 |4 |
| | |
| | |
|__________|__________|
First set of loops is quadrant 1
then quadrant 2
then quadrant 3
then quadrant 4
*/
int outXOffset = 0;
int outYOffset = 0;
for(int i = 0; i < halfLength; i++){
for(int j = 0; j < halfLength; j++){
rVal[i+outXOffset][j+outYOffset] =
(1.0f * (halfLength - i) * (halfLength - j))/(halfLength * halfLength) * macroValues[0][0] +
(1.0f * (0 - i) * (halfLength - j))/(halfLength * halfLength) * macroValues[1][0] +
(1.0f * (halfLength - i) * (0 - j))/(halfLength * halfLength) * macroValues[0][1] +
(1.0f * (0 - i) * (0 - j))/(halfLength * halfLength) * macroValues[1][1]
;
}
}
outXOffset = halfLength;
for(int i = 0; i < halfLength; i++){
for(int j = 0; j < halfLength; j++){
rVal[i+outXOffset][j+outYOffset] =
(1.0f * (halfLength - i) * (halfLength - j))/(halfLength * halfLength) * macroValues[1][0] +
(1.0f * (0 - i) * (halfLength - j))/(halfLength * halfLength) * macroValues[2][0] +
(1.0f * (halfLength - i) * (0 - j))/(halfLength * halfLength) * macroValues[1][1] +
(1.0f * (0 - i) * (0 - j))/(halfLength * halfLength) * macroValues[2][1]
;
}
}
outXOffset = 0;
outYOffset = halfLength;
for(int i = 0; i < halfLength; i++){
for(int j = 0; j < halfLength; j++){
rVal[i+outXOffset][j+outYOffset] =
(1.0f * (halfLength - i) * (halfLength - j))/(halfLength * halfLength) * macroValues[0][1] +
(1.0f * (0 - i) * (halfLength - j))/(halfLength * halfLength) * macroValues[1][1] +
(1.0f * (halfLength - i) * (0 - j))/(halfLength * halfLength) * macroValues[0][2] +
(1.0f * (0 - i) * (0 - j))/(halfLength * halfLength) * macroValues[1][2]
;
}
}
outXOffset = halfLength;
for(int i = 0; i < halfLength; i++){
for(int j = 0; j < halfLength; j++){
rVal[i+outXOffset][j+outYOffset] =
(1.0f * (halfLength - i) * (halfLength - j))/(halfLength * halfLength) * macroValues[1][1] +
(1.0f * (0 - i) * (halfLength - j))/(halfLength * halfLength) * macroValues[2][1] +
(1.0f * (halfLength - i) * (0 - j))/(halfLength * halfLength) * macroValues[1][2] +
(1.0f * (0 - i) * (0 - j))/(halfLength * halfLength) * macroValues[2][2]
;
}
}
return rVal;
}
/*
!!!ASSUMPTIONS!!!
square matricies of data
object has already been initialized
dynamicInterpolationRatio is set to some valid power of 2
*/
/**
* Dynamically interpolates a chunk of a specific size from the pre-existing elevation map
* Includes the boundary of the chunk as well
* @param x The x position on the elevation map to get a chunk from
* @param y The y position on the elevation map to get a chunk from
* @return Dynamically interpolated float array of elevations of chunk
*/
public float[][] getAugmentedElevationForChunk(float[][] macroValues, long[][] randomizerValues){
//this is what we intend to return from the function
float[][] rVal = new float[dynamicInterpolationRatio+1][dynamicInterpolationRatio+1];
/*
So we're looking at chunk x,y
if this is our grid:
4 0.1 0.2 0.3 0.4
^
| 3 0.1 0.2 0.3 0.4
|
| 2 0.1 0.2 0.3 0.4
x 1 0.1 0.2 0.3 0.4
0 1 2 3
y ---- >
say we're looking at x=2,y=1
"macroValues" should contain the values for x = [1,3] and y = [0,2]
the goal is to have the "center" of the output chunk have the value the
elevation grid at x=2,y=1
*/
/*
Our "macro values" at the edges of this chunk need to be haldway between this chunk's center height value and the next
Why? think about it for a second
If we have some grid with chunks a and b
0.1 0.2 0.3 0.8
0.4 a b 0.9
0.5 0.6 0.7 1.0
to generate a chunk at point a that smoothly merges into chunk b, you need
the chunk at a to know the value of b
but you don't want the right edge of the chunk at a to be the VALUE of b
because then it would work
so if we have two chunks
_____________________ _____________________
| | || | |
| | || | |
| | || | |
| | || | |
|__________a__________**__________b__________|
| | || | |
| | || | |
| | || | |
|__________|__________||__________|__________|
you want the value at ** to be half way between a and b
the corner cases are even worse, you have to average all four
_____________________ _____________________
| | || | |
| | || | |
| | || | |
| | || | |
|__________a__________||__________b__________|
| | || | |
| | || | |
| | || | |
|__________|__________**__________|__________|
_____________________**_____________________
| | || | |
| | || | |
| | || | |
| | || | |
|__________c__________||__________d__________|
| | || | |
| | || | |
| | || | |
|__________|__________||__________|__________|
*/
float[][] newMacroValues = new float[3][3];
newMacroValues[0][0] = (macroValues[0][0] + macroValues[0][1] + macroValues[1][0] + macroValues[1][1]) / 4.0f;
newMacroValues[2][0] = (macroValues[2][0] + macroValues[2][1] + macroValues[1][0] + macroValues[1][1]) / 4.0f;
newMacroValues[0][2] = (macroValues[0][2] + macroValues[0][1] + macroValues[1][2] + macroValues[1][1]) / 4.0f;
newMacroValues[2][2] = (macroValues[2][2] + macroValues[2][1] + macroValues[1][2] + macroValues[1][1]) / 4.0f;
newMacroValues[1][0] = (macroValues[1][0] + macroValues[1][1]) / 2.0f;
newMacroValues[0][1] = (macroValues[0][1] + macroValues[1][1]) / 2.0f;
newMacroValues[1][2] = (macroValues[1][2] + macroValues[1][1]) / 2.0f;
newMacroValues[2][1] = (macroValues[2][1] + macroValues[1][1]) / 2.0f;
newMacroValues[1][1] = macroValues[1][1];
macroValues = newMacroValues;
// System.out.println("discreteArrayDimension: " + discreteArrayDimension);
//The following values + random seed are what are primarily used for calculating elevation map
//If you want to transmit the output of this model without transmitting the entire field
//transmit these numbers + seeds
// System.out.println("Macro values for " + x + "," + y + "\n");
// System.out.println(macroValues[0][0] + " " + macroValues[1][0] + " " + macroValues[2][0]);
// System.out.println(macroValues[0][1] + " " + macroValues[1][1] + " " + macroValues[2][1]);
// System.out.println(macroValues[0][2] + " " + macroValues[1][2] + " " + macroValues[2][2]);
// System.out.println();
int halfLength = dynamicInterpolationRatio/2;
/*
Four quadrants we're generating
_____________________
|1 |2 |
| | |
| | |
| | |
|__________|__________|
|3 |4 |
| | |
| | |
|__________|__________|
First set of loops is quadrant 1
then quadrant 2
then quadrant 3
then quadrant 4
0,0 1,0 2,0
_____________________
|1 |2 |
| | |
| | |
| | |
0,1 |__________|__________| 2,1
|3 |4 |
| | |
| | |
|__________|__________|
0,2 1,2 2,2
Where the "macro values" correspond to on our array
*/
int outXOffset = 0;
int outYOffset = 0;
long quadrantRandom =
randomizerValues[0][0] +
randomizerValues[1][0] +
randomizerValues[0][1] +
randomizerValues[1][1];
Random quadRand = new Random(quadrantRandom);
for(int i = 0; i < halfLength; i++){
for(int j = 0; j < halfLength; j++){
rVal[i+outXOffset][j+outYOffset] =
(1.0f * (halfLength - i) * (halfLength - j))/(halfLength * halfLength) * macroValues[0][0] +
(1.0f * (i - 0) * (halfLength - j))/(halfLength * halfLength) * macroValues[1][0] +
(1.0f * (halfLength - i) * (j - 0))/(halfLength * halfLength) * macroValues[0][1] +
(1.0f * (i - 0) * (j - 0))/(halfLength * halfLength) * macroValues[1][1] +
quadRand.nextFloat() * randomDampener
;
}
}
quadrantRandom =
randomizerValues[1][0] +
randomizerValues[2][0] +
randomizerValues[1][1] +
randomizerValues[2][1];
quadRand = new Random(quadrantRandom);
outXOffset = halfLength;
for(int i = 0; i < halfLength; i++){
for(int j = 0; j < halfLength; j++){
rVal[i+outXOffset][j+outYOffset] =
(1.0f * (halfLength - i) * (halfLength - j))/(halfLength * halfLength) * macroValues[1][0] +
(1.0f * (i - 0) * (halfLength - j))/(halfLength * halfLength) * macroValues[2][0] +
(1.0f * (halfLength - i) * (j - 0))/(halfLength * halfLength) * macroValues[1][1] +
(1.0f * (i - 0) * (j - 0))/(halfLength * halfLength) * macroValues[2][1] +
quadRand.nextFloat() * randomDampener
;
}
}
quadrantRandom =
randomizerValues[0][1] +
randomizerValues[1][1] +
randomizerValues[0][2] +
randomizerValues[1][2];
quadRand = new Random(quadrantRandom);
outXOffset = 0;
outYOffset = halfLength;
for(int i = 0; i < halfLength; i++){
for(int j = 0; j < halfLength; j++){
rVal[i+outXOffset][j+outYOffset] =
(1.0f * (halfLength - i) * (halfLength - j))/(halfLength * halfLength) * macroValues[0][1] +
(1.0f * (i - 0) * (halfLength - j))/(halfLength * halfLength) * macroValues[1][1] +
(1.0f * (halfLength - i) * (j - 0))/(halfLength * halfLength) * macroValues[0][2] +
(1.0f * (i - 0) * (j - 0))/(halfLength * halfLength) * macroValues[1][2] +
quadRand.nextFloat() * randomDampener
;
}
}
quadrantRandom =
randomizerValues[1][1] +
randomizerValues[2][1] +
randomizerValues[1][2] +
randomizerValues[2][2];
quadRand = new Random(quadrantRandom);
outXOffset = halfLength;
for(int i = 0; i < halfLength; i++){
for(int j = 0; j < halfLength; j++){
rVal[i+outXOffset][j+outYOffset] =
(1.0f * (halfLength - i) * (halfLength - j))/(halfLength * halfLength) * macroValues[1][1] +
(1.0f * (i - 0) * (halfLength - j))/(halfLength * halfLength) * macroValues[2][1] +
(1.0f * (halfLength - i) * (j - 0))/(halfLength * halfLength) * macroValues[1][2] +
(1.0f * (i - 0) * (j - 0))/(halfLength * halfLength) * macroValues[2][2] +
quadRand.nextFloat() * randomDampener
;
}
}
/*
Four quadrants we're generating
------------>
_____________________
| |1 |2 |
| | | | |
| | | | |
| | | | |
| |__________|__________| |
| |3 |4 | |
| | | | |
V | | | V
|__________|__________|
---------->
filling in along these arrows now
this is the "order" of the edges:
1 2
3 5
4 6
7 8
the corresponding randoms for each edge are
1
2 3
4
*/
Random edge1Rand = new Random(randomizerValues[1][1] + randomizerValues[1][0]);
Random edge2Rand = new Random(randomizerValues[1][1] + randomizerValues[0][1]);
Random edge3Rand = new Random(randomizerValues[1][1] + randomizerValues[2][1]);
Random edge4Rand = new Random(randomizerValues[1][1] + randomizerValues[1][2]);
for(int i = 0; i < halfLength; i++){
//edge 1
rVal[i][0] =
(1.0f * (halfLength - i) / halfLength) * macroValues[0][0] +
(1.0f * (i - 0) / halfLength) * macroValues[1][0] +
edge1Rand.nextFloat() * randomDampener
;
//edge 2
rVal[i+halfLength][0] =
(1.0f * (halfLength - i) / halfLength) * macroValues[1][0] +
(1.0f * (i - 0) / halfLength) * macroValues[2][0] +
edge1Rand.nextFloat() * randomDampener
;
//edge 3
rVal[0][i] =
(1.0f * (halfLength - i) / halfLength) * macroValues[0][0] +
(1.0f * (i - 0) / halfLength) * macroValues[0][1] +
edge2Rand.nextFloat() * randomDampener
;
//edge 4
rVal[0][i+halfLength] =
(1.0f * (halfLength - i) / halfLength) * macroValues[0][1] +
(1.0f * (i - 0) / halfLength) * macroValues[0][2] +
edge2Rand.nextFloat() * randomDampener
;
//edge 5
rVal[dynamicInterpolationRatio][i] =
(1.0f * (halfLength - i) / halfLength) * macroValues[2][0] +
(1.0f * (i - 0) / halfLength) * macroValues[2][1] +
edge3Rand.nextFloat() * randomDampener
;
//edge 6
rVal[dynamicInterpolationRatio][i+halfLength] =
(1.0f * (halfLength - i) / halfLength) * macroValues[2][1] +
(1.0f * (i - 0) / halfLength) * macroValues[2][2] +
edge3Rand.nextFloat() * randomDampener
;
//edge 7
rVal[i][dynamicInterpolationRatio] =
(1.0f * (halfLength - i) / halfLength) * macroValues[0][2] +
(1.0f * (i - 0) / halfLength) * macroValues[1][2] +
edge4Rand.nextFloat() * randomDampener
;
//edge 8
rVal[i+halfLength][dynamicInterpolationRatio] =
(1.0f * (halfLength - i) / halfLength) * macroValues[1][2] +
(1.0f * (i - 0) / halfLength) * macroValues[2][2] +
edge4Rand.nextFloat() * randomDampener
;
}
//"Because it is passed over twice" this doesn't get the right value after the loops
//so we do it manually to correct
// rVal[0][dynamicInterpolationRatio] =
// macroValues[0][2] +
// new Random(randomizerValues[0][2] + randomizerValues[1][2]).nextFloat()
// ;
//"Because array dimensions" this doesn't end up getting filled in
//so we have to do it manually
//set final corner at bottom right
rVal[dynamicInterpolationRatio][dynamicInterpolationRatio] =
macroValues[2][2] +
new Random(randomizerValues[1][2] + randomizerValues[2][2]).nextFloat() * randomDampener
;
return rVal;
}
/*
So we're looking at chunk x,y
if this is our grid:
4 0.1 0.2 0.3 0.4
^
| 3 0.1 0.2 0.3 0.4
|
| 2 0.1 0.2 0.3 0.4
x 1 0.1 0.2 0.3 0.4
0 1 2 3
y ---- >
say we're looking at x=2,y=1
"macroValues" should contain the values for x = [1,3] and y = [0,2]
the goal is to have the "center" of the output chunk have the value the
elevation grid at x=2,y=1
*/
public float[][] getMacroValuesAtPosition(int x, int y){
float[][] rVal = new float[3][3];
rVal[1][1] = elevation[x][y];
if(x - 1 >= 0){
rVal[0][1] = elevation[x-1][y];
if(y - 1 >= 0){
rVal[0][0] = elevation[x-1][y-1];
}
if(y + 1 < discreteArrayDimension){
rVal[0][2] = elevation[x-1][y+1];
}
}
if(x + 1 < discreteArrayDimension){
rVal[2][1] = elevation[x+1][y];
if(y - 1 >= 0){
rVal[2][0] = elevation[x+1][y-1];
}
if(y + 1 < discreteArrayDimension){
rVal[2][2] = elevation[x+1][y+1];
}
}
if(y - 1 >= 0){
rVal[1][0] = elevation[x][y-1];
}
if(y + 1 < discreteArrayDimension){
rVal[1][2] = elevation[x][y+1];
}
return rVal;
}
/*
So we're looking at chunk x,y
if this is our grid:
4 0.1 0.2 0.3 0.4
^
| 3 0.1 0.2 0.3 0.4
|
| 2 0.1 0.2 0.3 0.4
x 1 0.1 0.2 0.3 0.4
0 1 2 3
y ---- >
say we're looking at x=2,y=1
"macroValues" should contain the values for x = [1,3] and y = [0,2]
the goal is to have the "center" of the output chunk have the value the
elevation grid at x=2,y=1
*/
public long[][] getRandomizerValuesAtPosition(int x, int y){
long[][] rVal = new long[3][3];
rVal[1][1] = chunkRandomizer[x][y];
if(x - 1 >= 0){
rVal[0][1] = chunkRandomizer[x-1][y];
if(y - 1 >= 0){
rVal[0][0] = chunkRandomizer[x-1][y-1];
}
if(y + 1 < discreteArrayDimension){
rVal[0][2] = chunkRandomizer[x-1][y+1];
}
}
if(x + 1 < discreteArrayDimension){
rVal[2][1] = chunkRandomizer[x+1][y];
if(y - 1 >= 0){
rVal[2][0] = chunkRandomizer[x+1][y-1];
}
if(y + 1 < discreteArrayDimension){
rVal[2][2] = chunkRandomizer[x+1][y+1];
}
}
if(y - 1 >= 0){
rVal[1][0] = chunkRandomizer[x][y-1];
}
if(y + 1 < discreteArrayDimension){
rVal[1][2] = chunkRandomizer[x][y+1];
}
return rVal;
}
}

View File

@ -27,6 +27,7 @@ import electrosphere.net.client.ClientNetworking;
import electrosphere.net.server.Server;
import electrosphere.renderer.ModelUtils;
import electrosphere.renderer.RenderUtils;
import electrosphere.renderer.RenderingEngine;
import electrosphere.renderer.ShaderProgram;
import electrosphere.renderer.assetmanager.AssetDataStrings;
import electrosphere.renderer.assetmanager.AssetManager;
@ -61,6 +62,11 @@ public class Globals {
public static MainConfig mainConfig;
//
//Rendering Engine
//
public static RenderingEngine renderingEngine;
//
//Client connection to server

View File

@ -5,14 +5,10 @@ import electrosphere.cfg.MainConfig;
import electrosphere.controls.ControlHandler;
import electrosphere.entity.CameraEntityUtils;
import electrosphere.entity.types.creature.CreatureUtils;
import electrosphere.renderer.Camera;
import electrosphere.renderer.Material;
import electrosphere.renderer.Model;
import electrosphere.renderer.RenderUtils;
import electrosphere.renderer.ShaderProgram;
import electrosphere.renderer.texture.Texture;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.EntityUtils;
import electrosphere.entity.state.MovementTree;
import electrosphere.entity.types.hitbox.HitboxUtils;
@ -22,17 +18,7 @@ import electrosphere.game.state.AttachUtils;
import electrosphere.game.state.LoadingThread;
import electrosphere.game.state.SimulationState;
import electrosphere.game.state.SimulationState.SimulationStateMachine;
import electrosphere.game.terrain.TerrainManager;
import electrosphere.net.client.ClientNetworkMessage;
import electrosphere.net.client.ClientNetworking;
import electrosphere.net.server.Server;
import electrosphere.renderer.Actor;
import electrosphere.renderer.ui.font.FontUtils;
import electrosphere.renderer.ModelUtils;
import electrosphere.renderer.ui.WidgetUtils;
import electrosphere.renderer.ui.font.TextBox;
import electrosphere.terraingen.TerrainGen;
import electrosphere.terraingen.models.TerrainModel;
import electrosphere.renderer.RenderingEngine;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Random;
@ -42,14 +28,6 @@ import org.joml.Quaternionf;
import org.joml.Vector3f;
import org.lwjgl.glfw.*;
import static org.lwjgl.glfw.GLFW.*;
import org.lwjgl.opengl.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL13.*;
import static org.lwjgl.opengl.GL14.*;
import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL20.*;
import static org.lwjgl.opengl.GL30.*;
import static org.lwjgl.system.MemoryUtil.NULL;
import electrosphere.util.ModelLoader;
import electrosphere.util.Utilities;
import java.io.File;
@ -62,10 +40,7 @@ import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author amaterasu
*/
public class Main {
@ -138,7 +113,8 @@ public class Main {
Globals.initGlobals();
//create the drawing context
RenderUtils.createOpenglContext();
Globals.renderingEngine = new RenderingEngine();
Globals.renderingEngine.createOpenglContext();
//init default resources
Globals.initDefaultGraphicalResources();
@ -274,7 +250,7 @@ public class Main {
RenderUtils.drawScreen();
Globals.renderingEngine.drawScreen();
if(glfwWindowShouldClose(Globals.window)){

View File

@ -115,17 +115,7 @@ import static org.lwjgl.system.MemoryUtil.NULL;
*/
public class RenderUtils {
public static final int GL_DEFAULT_FRAMEBUFFER = 0;
public static final int GL_DEFAULT_RENDERBUFFER = 0;
static Framebuffer screenFramebuffer;
static Renderbuffer screenRenderbuffer;
static int screenTextureVAO;
static ShaderProgram screenTextureShaders;
static ShaderProgram lightDepthShaderProgram;
static Framebuffer lightDepthBuffer;
public static boolean renderHitboxes = true;
static int createScreenTextureVAO(){
int rVal = glGenVertexArrays();
@ -189,71 +179,7 @@ public class RenderUtils {
return rVal;
}
public static void createOpenglContext(){
//Sets the variables that control the window sizing
int screenWidth = Globals.WINDOW_WIDTH;
int screenHeight = Globals.WINDOW_HEIGHT;
//Initializes opengl
glfwInit();
//Gives hints to glfw to control how opengl will be used
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE); Allows you to make the background transparent
// glfwWindowHint(GLFW_OPACITY, 23);
//Creates the window reference object
Globals.window = glfwCreateWindow(screenWidth, screenHeight, "LearnOpenGL", NULL, NULL);
//Errors for failure to create window (IE: No GUI mode on linux ?)
if (Globals.window == NULL) {
System.out.println("Failed to make window.");
glfwTerminate();
}
//Makes the window that was just created the current OS-level window context
glfwMakeContextCurrent(Globals.window);
//Maximize it
glfwMaximizeWindow(Globals.window);
//Creates the OpenGL capabilities for the program.
GL.createCapabilities();
//This enables Z-buffering so that farther-back polygons are not drawn over nearer ones
glEnable(GL_DEPTH_TEST);
// Support for transparency
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//Hide the cursor and capture it
glfwSetInputMode(Globals.window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
//init screen rendering quadrant
screenTextureVAO = createScreenTextureVAO();
// initScreenTextureShaderProgram();
screenTextureShaders = ShaderProgram.loadSpecificShader("/Shaders/screentexture/simple1/simple1.vs", "/Shaders/screentexture/simple1/simple1.fs");
// screenTextureShaders = ShaderProgram.loadSpecificShader("/Shaders/screentexture/drawDepthBuffer/drawDepthBuffer.vs", "/Shaders/screentexture/drawDepthBuffer/drawDepthBuffer.fs");
//generate framebuffers
screenFramebuffer = FramebufferUtils.generateScreensizeTextureFramebuffer();
glBindFramebuffer(GL_FRAMEBUFFER, GL_DEFAULT_FRAMEBUFFER);
glBindRenderbuffer(GL_RENDERBUFFER, GL_DEFAULT_RENDERBUFFER);
lightDepthShaderProgram = ShaderProgram.loadSpecificShader("/Shaders/lightDepth/lightDepth.vs", "/Shaders/lightDepth/lightDepth.fs");
Globals.depthMapShaderProgramLoc = lightDepthShaderProgram.shaderProgram;
lightDepthBuffer = FramebufferUtils.generateDepthBuffer();
Globals.shadowMapTextureLoc = lightDepthBuffer.getTexture();
// glEnable(GL_CULL_FACE); // enabled for shadow mapping
//
// Projection and View matrix creation
//
Globals.projectionMatrix = new Matrix4f();
Globals.viewMatrix = new Matrix4f();
float FOV = (float)(120.0f * Math.PI /180.0f);
Globals.projectionMatrix.setPerspective(FOV, 1.0f, 0.1f, view_Range);
Globals.viewMatrix.translation(new Vector3f(0.0f,0.0f,-3.0f));
}
public static void recaptureScreen(){
@ -506,266 +432,6 @@ public class RenderUtils {
}
public static void drawScreen(){
//
//first pass: generate depth map
//
if(Globals.RENDER_FLAG_RENDER_SHADOW_MAP){
renderShadowMapFramebufferContent();
}
/*
Render content to the game framebuffer
*/
if(Globals.RENDER_FLAG_RENDER_SCREEN_FRAMEBUFFER_CONTENT){
renderGameFramebufferContent();
}
//bind default FBO
glBindFramebuffer(GL_FRAMEBUFFER,0);
glDisable(GL_DEPTH_TEST);
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
/*
Render the game framebuffer texture to a quad
*/
if(Globals.RENDER_FLAG_RENDER_SCREEN_FRAMEBUFFER){
renderScreenFramebuffer();
}
/*
Render black background
*/
if(Globals.RENDER_FLAG_RENDER_BLACK_BACKGROUND){
renderBlackBackground();
}
/*
Render any ui elements
*/
if(Globals.RENDER_FLAG_RENDER_UI){
renderUI();
}
//check and call events and swap the buffers
glfwSwapBuffers(Globals.window);
glfwPollEvents();
}
static void renderShadowMapFramebufferContent(){
Matrix4f modelTransformMatrix = new Matrix4f();
//set the viewport to shadow map size
glViewport(0, 0, 4096, 4096);
glEnable(GL_DEPTH_TEST);
lightDepthBuffer.bind();
glClear(GL_DEPTH_BUFFER_BIT);
//set matrices for light render
float near_plane = 0.001f, far_plane = 100.5f;
Matrix4f lightProjection = new Matrix4f().setOrtho(-10.0f, 10.0f, -10.0f, 10.0f, near_plane, far_plane);//glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, near_plane, far_plane);
Matrix4f lightView = new Matrix4f().lookAt(
new Vector3f(-20.0f, 40.0f, -10.0f),
new Vector3f( 0.0f, 0.0f, 0.0f),
new Vector3f( 0.0f, 1.0f, 0.0f)
);
Globals.lightDepthMatrix = new Matrix4f(lightProjection).mul(lightView);
glUseProgram(lightDepthShaderProgram.shaderProgram);
glUniformMatrix4fv(glGetUniformLocation(lightDepthShaderProgram.shaderProgram, "lightSpaceMatrix"), false, Globals.lightDepthMatrix.get(new float[16]));
// glCullFace(GL_FRONT);
//
// D R A W A L L E N T I T I E S
//
modelTransformMatrix = new Matrix4f();
for(Entity currentEntity : Globals.entityManager.getDrawable()){
//fetch actor
Actor currentActor = EntityUtils.getEntityActor(currentEntity);
//increment animations
if(currentActor.getCurrentAnimation() != null){
currentActor.incrementAnimationTime(deltaTime * 500);
}
//calculate and apply model transform
modelTransformMatrix.identity();
modelTransformMatrix.translate(new Vector3f(EntityUtils.getEntityPosition(currentEntity)).sub(CameraEntityUtils.getCameraCenter(Globals.playerCamera)).sub(new Vector3f(0,1,0)));
modelTransformMatrix.rotate(EntityUtils.getEntityRotation(currentEntity));
modelTransformMatrix.scale(EntityUtils.getEntityScale(currentEntity));
currentActor.applyModelMatrix(modelTransformMatrix);
//draw
currentActor.drawForDepthBuffer();
}
//bind default framebuffer
glBindFramebuffer(GL_FRAMEBUFFER,0);
//reset texture
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, 0);
//reset the viewport to screen size
glViewport(0, 0, Globals.WINDOW_WIDTH, Globals.WINDOW_HEIGHT);
//resume culling backface
// glCullFace(GL_BACK);
}
static void renderGameFramebufferContent(){
Matrix4f modelTransformMatrix = new Matrix4f();
//bind screen fbo
screenFramebuffer.bind();
glEnable(GL_DEPTH_TEST);
///
/// R E N D E R I N G S T U F F
///
//Sets the background color.
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//
// D R A W A L L E N T I T I E S
//
modelTransformMatrix = new Matrix4f();
for(Entity currentEntity : Globals.entityManager.getDrawable()){
//fetch actor
Actor currentActor = EntityUtils.getEntityActor(currentEntity);
//increment animations
//this is incremented in the shadow calculations
// if(currentActor.getCurrentAnimation() != null){
// currentActor.incrementAnimationTime(deltaTime * 500);
// }
//calculate and apply model transform
modelTransformMatrix.identity();
modelTransformMatrix.translate(new Vector3f(EntityUtils.getEntityPosition(currentEntity)).sub(CameraEntityUtils.getCameraCenter(Globals.playerCamera)).sub(new Vector3f(0,1,0)));
modelTransformMatrix.rotate(EntityUtils.getEntityRotation(currentEntity));
modelTransformMatrix.scale(EntityUtils.getEntityScale(currentEntity));
currentActor.applyModelMatrix(modelTransformMatrix);
//draw
currentActor.draw();
// Model currentModel = Globals.assetManager.fetchModel(EntityUtils.getEntityModelPath(currentEntity));
// if(currentModel != null){
// if(currentModel.currentAnimation != null){
// currentModel.incrementTime(deltaTime * 500);
// }
// currentModel.modelMatrix = new Matrix4f();
// currentModel.modelMatrix.translate(new Vector3f(EntityUtils.getEntityPosition(currentEntity)).sub(CameraEntityUtils.getCameraCenter(Globals.playerCamera)).sub(new Vector3f(0,1,0)));
// currentModel.modelMatrix.rotate(EntityUtils.getEntityRotation(currentEntity));
// currentModel.modelMatrix.scale(EntityUtils.getEntityScale(currentEntity));
// currentModel.draw();
// }
}
if(renderHitboxes){
for(Entity currentHitbox : Globals.hitboxManager.getAllHitboxes()){
Model hitboxModel;
if(currentHitbox.getData(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE).equals(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HURT)){
if((hitboxModel = Globals.assetManager.fetchModel("Models/unitsphere.fbx")) != null){
Vector3f position = EntityUtils.getEntityPosition(currentHitbox);
modelTransformMatrix.identity();
modelTransformMatrix.translate(new Vector3f(position).sub(CameraEntityUtils.getCameraCenter(Globals.playerCamera)).sub(new Vector3f(0,1,0)));
// modelTransformMatrix.translate(-0.25f, 0.0f, 0.5f); //center sphere
modelTransformMatrix.scale((Float)currentHitbox.getData(EntityDataStrings.COLLISION_ENTITY_DATA_RADIUS) * 2);
hitboxModel.modelMatrix = modelTransformMatrix;
hitboxModel.draw();
}
} else if(currentHitbox.getData(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE).equals(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HIT)){
if((hitboxModel = Globals.assetManager.fetchModel("Models/unitsphere_1.fbx")) != null){
Vector3f position = EntityUtils.getEntityPosition(currentHitbox);
modelTransformMatrix.identity();
modelTransformMatrix.translate(new Vector3f(position).sub(CameraEntityUtils.getCameraCenter(Globals.playerCamera)).sub(new Vector3f(0,1,0)));
// modelTransformMatrix.translate(-0.25f, 0.0f, 0.5f); //center sphere
modelTransformMatrix.scale((Float)currentHitbox.getData(EntityDataStrings.COLLISION_ENTITY_DATA_RADIUS) * 2);
hitboxModel.modelMatrix = modelTransformMatrix;
hitboxModel.draw();
}
}
}
}
// glBindVertexArray(0);
}
static void renderScreenFramebuffer(){
//
//unbind texture channels
//
//What does this mean?
//essentially there are two channels we're using to draw mesh textures
//we have to glBindTexture to pointer 0 for BOTH channels, otherwise
//the leftover texture gets used to draw the screen framebuffer quad
//which doesnt work
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE0);
//render full screen quad
glUseProgram(screenTextureShaders.shaderProgram);
glBindVertexArray(screenTextureVAO);
glBindTexture(GL_TEXTURE_2D, screenFramebuffer.getTexture());
// glBindTexture(GL_TEXTURE_2D, lightDepthBuffer.getTexture());
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
}
static void renderUI(){
Matrix4f modelTransformMatrix = new Matrix4f();
for(Widget currentWidget : Globals.widgetManager.getWidgetList()){
if(currentWidget.isDraw()){
currentWidget.draw();
}
}
// for(Entity currentEntity : Globals.entityManager.getUIElements()){
// Actor uiActor = EntityUtils.getEntityActor(currentEntity);
// if(currentEntity.getDataKeys().contains(EntityDataStrings.DATA_STRING_UI_ELEMENT_FONT)){
// modelTransformMatrix.identity();
// modelTransformMatrix.translate(EntityUtils.getEntityPosition(currentEntity));
// uiActor.applyModelMatrix(modelTransformMatrix);
// }
// uiActor.drawUI();
// }
}
static void renderBlackBackground(){
//render full screen quad
glUseProgram(screenTextureShaders.shaderProgram);
glBindVertexArray(screenTextureVAO);
Globals.blackTexture.bind();
// glBindTexture(GL_TEXTURE_2D, screenFramebuffer.getTexture());
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
}
}

View File

@ -0,0 +1,412 @@
package electrosphere.renderer;
import electrosphere.entity.CameraEntityUtils;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.EntityUtils;
import electrosphere.main.Globals;
import static electrosphere.main.Main.deltaTime;
import static electrosphere.main.Main.view_Range;
import static electrosphere.renderer.RenderUtils.createScreenTextureVAO;
import electrosphere.renderer.framebuffer.Framebuffer;
import electrosphere.renderer.framebuffer.FramebufferUtils;
import electrosphere.renderer.framebuffer.Renderbuffer;
import electrosphere.renderer.ui.Widget;
import org.joml.Matrix4f;
import org.joml.Vector3f;
import static org.lwjgl.glfw.GLFW.GLFW_CONTEXT_VERSION_MAJOR;
import static org.lwjgl.glfw.GLFW.GLFW_CONTEXT_VERSION_MINOR;
import static org.lwjgl.glfw.GLFW.GLFW_CURSOR;
import static org.lwjgl.glfw.GLFW.GLFW_CURSOR_DISABLED;
import static org.lwjgl.glfw.GLFW.GLFW_OPENGL_CORE_PROFILE;
import static org.lwjgl.glfw.GLFW.GLFW_OPENGL_PROFILE;
import static org.lwjgl.glfw.GLFW.glfwCreateWindow;
import static org.lwjgl.glfw.GLFW.glfwInit;
import static org.lwjgl.glfw.GLFW.glfwMakeContextCurrent;
import static org.lwjgl.glfw.GLFW.glfwMaximizeWindow;
import static org.lwjgl.glfw.GLFW.glfwPollEvents;
import static org.lwjgl.glfw.GLFW.glfwSetInputMode;
import static org.lwjgl.glfw.GLFW.glfwSwapBuffers;
import static org.lwjgl.glfw.GLFW.glfwTerminate;
import static org.lwjgl.glfw.GLFW.glfwWindowHint;
import org.lwjgl.opengl.GL;
import static org.lwjgl.opengl.GL11.GL_BLEND;
import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.GL_DEPTH_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.GL_DEPTH_TEST;
import static org.lwjgl.opengl.GL11.GL_ONE_MINUS_SRC_ALPHA;
import static org.lwjgl.opengl.GL11.GL_SRC_ALPHA;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D;
import static org.lwjgl.opengl.GL11.GL_TRIANGLES;
import static org.lwjgl.opengl.GL11.glBindTexture;
import static org.lwjgl.opengl.GL11.glBlendFunc;
import static org.lwjgl.opengl.GL11.glClear;
import static org.lwjgl.opengl.GL11.glClearColor;
import static org.lwjgl.opengl.GL11.glDisable;
import static org.lwjgl.opengl.GL11.glDrawArrays;
import static org.lwjgl.opengl.GL11.glEnable;
import static org.lwjgl.opengl.GL11.glViewport;
import static org.lwjgl.opengl.GL13.GL_TEXTURE0;
import static org.lwjgl.opengl.GL13.GL_TEXTURE1;
import static org.lwjgl.opengl.GL13.GL_TEXTURE2;
import static org.lwjgl.opengl.GL13.GL_TEXTURE3;
import static org.lwjgl.opengl.GL13.glActiveTexture;
import static org.lwjgl.opengl.GL20.glGetUniformLocation;
import static org.lwjgl.opengl.GL20.glUniformMatrix4fv;
import static org.lwjgl.opengl.GL20.glUseProgram;
import static org.lwjgl.opengl.GL30.GL_FRAMEBUFFER;
import static org.lwjgl.opengl.GL30.GL_RENDERBUFFER;
import static org.lwjgl.opengl.GL30.glBindFramebuffer;
import static org.lwjgl.opengl.GL30.glBindRenderbuffer;
import static org.lwjgl.opengl.GL30.glBindVertexArray;
import static org.lwjgl.system.MemoryUtil.NULL;
public class RenderingEngine {
public static final int GL_DEFAULT_FRAMEBUFFER = 0;
public static final int GL_DEFAULT_RENDERBUFFER = 0;
static Framebuffer screenFramebuffer;
static Renderbuffer screenRenderbuffer;
static int screenTextureVAO;
static ShaderProgram screenTextureShaders;
static ShaderProgram lightDepthShaderProgram;
static Framebuffer lightDepthBuffer;
public static boolean renderHitboxes = true;
public void createOpenglContext(){
//Sets the variables that control the window sizing
int screenWidth = Globals.WINDOW_WIDTH;
int screenHeight = Globals.WINDOW_HEIGHT;
//Initializes opengl
glfwInit();
//Gives hints to glfw to control how opengl will be used
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE); Allows you to make the background transparent
// glfwWindowHint(GLFW_OPACITY, 23);
//Creates the window reference object
Globals.window = glfwCreateWindow(screenWidth, screenHeight, "LearnOpenGL", NULL, NULL);
//Errors for failure to create window (IE: No GUI mode on linux ?)
if (Globals.window == NULL) {
System.out.println("Failed to make window.");
glfwTerminate();
}
//Makes the window that was just created the current OS-level window context
glfwMakeContextCurrent(Globals.window);
//Maximize it
glfwMaximizeWindow(Globals.window);
//Creates the OpenGL capabilities for the program.
GL.createCapabilities();
//This enables Z-buffering so that farther-back polygons are not drawn over nearer ones
glEnable(GL_DEPTH_TEST);
// Support for transparency
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//Hide the cursor and capture it
glfwSetInputMode(Globals.window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
//init screen rendering quadrant
screenTextureVAO = createScreenTextureVAO();
// initScreenTextureShaderProgram();
screenTextureShaders = ShaderProgram.loadSpecificShader("/Shaders/screentexture/simple1/simple1.vs", "/Shaders/screentexture/simple1/simple1.fs");
// screenTextureShaders = ShaderProgram.loadSpecificShader("/Shaders/screentexture/drawDepthBuffer/drawDepthBuffer.vs", "/Shaders/screentexture/drawDepthBuffer/drawDepthBuffer.fs");
//generate framebuffers
screenFramebuffer = FramebufferUtils.generateScreensizeTextureFramebuffer();
glBindFramebuffer(GL_FRAMEBUFFER, GL_DEFAULT_FRAMEBUFFER);
glBindRenderbuffer(GL_RENDERBUFFER, GL_DEFAULT_RENDERBUFFER);
lightDepthShaderProgram = ShaderProgram.loadSpecificShader("/Shaders/lightDepth/lightDepth.vs", "/Shaders/lightDepth/lightDepth.fs");
Globals.depthMapShaderProgramLoc = lightDepthShaderProgram.shaderProgram;
lightDepthBuffer = FramebufferUtils.generateDepthBuffer();
Globals.shadowMapTextureLoc = lightDepthBuffer.getTexture();
// glEnable(GL_CULL_FACE); // enabled for shadow mapping
//
// Projection and View matrix creation
//
Globals.projectionMatrix = new Matrix4f();
Globals.viewMatrix = new Matrix4f();
float FOV = (float)(120.0f * Math.PI /180.0f);
Globals.projectionMatrix.setPerspective(FOV, 1.0f, 0.1f, view_Range);
Globals.viewMatrix.translation(new Vector3f(0.0f,0.0f,-3.0f));
}
public void drawScreen(){
//
//first pass: generate depth map
//
if(Globals.RENDER_FLAG_RENDER_SHADOW_MAP){
renderShadowMapFramebufferContent();
}
/*
Render content to the game framebuffer
*/
if(Globals.RENDER_FLAG_RENDER_SCREEN_FRAMEBUFFER_CONTENT){
renderGameFramebufferContent();
}
//bind default FBO
glBindFramebuffer(GL_FRAMEBUFFER,0);
glDisable(GL_DEPTH_TEST);
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
/*
Render the game framebuffer texture to a quad
*/
if(Globals.RENDER_FLAG_RENDER_SCREEN_FRAMEBUFFER){
renderScreenFramebuffer();
}
/*
Render black background
*/
if(Globals.RENDER_FLAG_RENDER_BLACK_BACKGROUND){
renderBlackBackground();
}
/*
Render any ui elements
*/
if(Globals.RENDER_FLAG_RENDER_UI){
renderUI();
}
//check and call events and swap the buffers
glfwSwapBuffers(Globals.window);
glfwPollEvents();
}
static void renderShadowMapFramebufferContent(){
Matrix4f modelTransformMatrix = new Matrix4f();
//set the viewport to shadow map size
glViewport(0, 0, 4096, 4096);
glEnable(GL_DEPTH_TEST);
lightDepthBuffer.bind();
glClear(GL_DEPTH_BUFFER_BIT);
//set matrices for light render
float near_plane = 0.001f, far_plane = 100.5f;
Matrix4f lightProjection = new Matrix4f().setOrtho(-10.0f, 10.0f, -10.0f, 10.0f, near_plane, far_plane);//glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, near_plane, far_plane);
Matrix4f lightView = new Matrix4f().lookAt(
new Vector3f(-20.0f, 40.0f, -10.0f),
new Vector3f( 0.0f, 0.0f, 0.0f),
new Vector3f( 0.0f, 1.0f, 0.0f)
);
Globals.lightDepthMatrix = new Matrix4f(lightProjection).mul(lightView);
glUseProgram(lightDepthShaderProgram.shaderProgram);
glUniformMatrix4fv(glGetUniformLocation(lightDepthShaderProgram.shaderProgram, "lightSpaceMatrix"), false, Globals.lightDepthMatrix.get(new float[16]));
// glCullFace(GL_FRONT);
//
// D R A W A L L E N T I T I E S
//
modelTransformMatrix = new Matrix4f();
for(Entity currentEntity : Globals.entityManager.getDrawable()){
//fetch actor
Actor currentActor = EntityUtils.getEntityActor(currentEntity);
//increment animations
if(currentActor.getCurrentAnimation() != null){
currentActor.incrementAnimationTime(deltaTime * 500);
}
//calculate and apply model transform
modelTransformMatrix.identity();
modelTransformMatrix.translate(new Vector3f(EntityUtils.getEntityPosition(currentEntity)).sub(CameraEntityUtils.getCameraCenter(Globals.playerCamera)).sub(new Vector3f(0,1,0)));
modelTransformMatrix.rotate(EntityUtils.getEntityRotation(currentEntity));
modelTransformMatrix.scale(EntityUtils.getEntityScale(currentEntity));
currentActor.applyModelMatrix(modelTransformMatrix);
//draw
currentActor.drawForDepthBuffer();
}
//bind default framebuffer
glBindFramebuffer(GL_FRAMEBUFFER,0);
//reset texture
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, 0);
//reset the viewport to screen size
glViewport(0, 0, Globals.WINDOW_WIDTH, Globals.WINDOW_HEIGHT);
//resume culling backface
// glCullFace(GL_BACK);
}
static void renderGameFramebufferContent(){
Matrix4f modelTransformMatrix = new Matrix4f();
//bind screen fbo
screenFramebuffer.bind();
glEnable(GL_DEPTH_TEST);
///
/// R E N D E R I N G S T U F F
///
//Sets the background color.
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//
// D R A W A L L E N T I T I E S
//
modelTransformMatrix = new Matrix4f();
for(Entity currentEntity : Globals.entityManager.getDrawable()){
//fetch actor
Actor currentActor = EntityUtils.getEntityActor(currentEntity);
//increment animations
//this is incremented in the shadow calculations
// if(currentActor.getCurrentAnimation() != null){
// currentActor.incrementAnimationTime(deltaTime * 500);
// }
//calculate and apply model transform
modelTransformMatrix.identity();
modelTransformMatrix.translate(new Vector3f(EntityUtils.getEntityPosition(currentEntity)).sub(CameraEntityUtils.getCameraCenter(Globals.playerCamera)).sub(new Vector3f(0,1,0)));
modelTransformMatrix.rotate(EntityUtils.getEntityRotation(currentEntity));
modelTransformMatrix.scale(EntityUtils.getEntityScale(currentEntity));
currentActor.applyModelMatrix(modelTransformMatrix);
//draw
currentActor.draw();
// Model currentModel = Globals.assetManager.fetchModel(EntityUtils.getEntityModelPath(currentEntity));
// if(currentModel != null){
// if(currentModel.currentAnimation != null){
// currentModel.incrementTime(deltaTime * 500);
// }
// currentModel.modelMatrix = new Matrix4f();
// currentModel.modelMatrix.translate(new Vector3f(EntityUtils.getEntityPosition(currentEntity)).sub(CameraEntityUtils.getCameraCenter(Globals.playerCamera)).sub(new Vector3f(0,1,0)));
// currentModel.modelMatrix.rotate(EntityUtils.getEntityRotation(currentEntity));
// currentModel.modelMatrix.scale(EntityUtils.getEntityScale(currentEntity));
// currentModel.draw();
// }
}
if(renderHitboxes){
for(Entity currentHitbox : Globals.hitboxManager.getAllHitboxes()){
Model hitboxModel;
if(currentHitbox.getData(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE).equals(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HURT)){
if((hitboxModel = Globals.assetManager.fetchModel("Models/unitsphere.fbx")) != null){
Vector3f position = EntityUtils.getEntityPosition(currentHitbox);
modelTransformMatrix.identity();
modelTransformMatrix.translate(new Vector3f(position).sub(CameraEntityUtils.getCameraCenter(Globals.playerCamera)).sub(new Vector3f(0,1,0)));
// modelTransformMatrix.translate(-0.25f, 0.0f, 0.5f); //center sphere
modelTransformMatrix.scale((Float)currentHitbox.getData(EntityDataStrings.COLLISION_ENTITY_DATA_RADIUS) * 2);
hitboxModel.modelMatrix = modelTransformMatrix;
hitboxModel.draw();
}
} else if(currentHitbox.getData(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE).equals(EntityDataStrings.COLLISION_ENTITY_DATA_TYPE_HIT)){
if((hitboxModel = Globals.assetManager.fetchModel("Models/unitsphere_1.fbx")) != null){
Vector3f position = EntityUtils.getEntityPosition(currentHitbox);
modelTransformMatrix.identity();
modelTransformMatrix.translate(new Vector3f(position).sub(CameraEntityUtils.getCameraCenter(Globals.playerCamera)).sub(new Vector3f(0,1,0)));
// modelTransformMatrix.translate(-0.25f, 0.0f, 0.5f); //center sphere
modelTransformMatrix.scale((Float)currentHitbox.getData(EntityDataStrings.COLLISION_ENTITY_DATA_RADIUS) * 2);
hitboxModel.modelMatrix = modelTransformMatrix;
hitboxModel.draw();
}
}
}
}
// glBindVertexArray(0);
}
static void renderScreenFramebuffer(){
//
//unbind texture channels
//
//What does this mean?
//essentially there are two channels we're using to draw mesh textures
//we have to glBindTexture to pointer 0 for BOTH channels, otherwise
//the leftover texture gets used to draw the screen framebuffer quad
//which doesnt work
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE0);
//render full screen quad
glUseProgram(screenTextureShaders.shaderProgram);
glBindVertexArray(screenTextureVAO);
glBindTexture(GL_TEXTURE_2D, screenFramebuffer.getTexture());
// glBindTexture(GL_TEXTURE_2D, lightDepthBuffer.getTexture());
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
}
static void renderUI(){
Matrix4f modelTransformMatrix = new Matrix4f();
for(Widget currentWidget : Globals.widgetManager.getWidgetList()){
if(currentWidget.isDraw()){
currentWidget.draw();
}
}
// for(Entity currentEntity : Globals.entityManager.getUIElements()){
// Actor uiActor = EntityUtils.getEntityActor(currentEntity);
// if(currentEntity.getDataKeys().contains(EntityDataStrings.DATA_STRING_UI_ELEMENT_FONT)){
// modelTransformMatrix.identity();
// modelTransformMatrix.translate(EntityUtils.getEntityPosition(currentEntity));
// uiActor.applyModelMatrix(modelTransformMatrix);
// }
// uiActor.drawUI();
// }
}
static void renderBlackBackground(){
//render full screen quad
glUseProgram(screenTextureShaders.shaderProgram);
glBindVertexArray(screenTextureVAO);
Globals.blackTexture.bind();
// glBindTexture(GL_TEXTURE_2D, screenFramebuffer.getTexture());
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
}
}