Refactoring, terrain, lots of changes

This commit is contained in:
satellite 2021-04-01 23:08:49 -04:00
parent 40c66f713c
commit 34c5776296
32 changed files with 711 additions and 165 deletions

View File

@ -88,6 +88,12 @@
</dependency>
<dependency>
<groupId>cz.advel.jbullet</groupId>
<artifactId>jbullet</artifactId>
<version>20101010-1</version>
</dependency>
<dependency>
<groupId>electrosphere</groupId>

View File

@ -0,0 +1,25 @@
package electrosphere.cfg;
/**
*
* @author satellite
*/
//Main configuration file for application
public class MainConfig {
//Main directory of project resources
public String projectMainDirectory;
//
//Terrain
//
//Do we load terrain?
public boolean loadTerrain;
//If load terrain, where from?
public String loadTerrainLocation;
}

View File

@ -6,6 +6,8 @@
package electrosphere.entity;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
/**
*
@ -18,6 +20,8 @@ public class Entity {
int id;
HashMap<String,Object> data;
LinkedList<String> dataKeys;
@ -25,12 +29,26 @@ public class Entity {
return id;
}
public HashMap<String, Object> getData() {
return data;
// HashMap<String, Object> getData() {
// return data;
// }
public void putData(String key, Object o){
data.put(key,o);
dataKeys.add(key);
}
public List<String> getDataKeys(){
return dataKeys;
}
public Object getData(String key){
return data.get(key);
}
public Entity(){
data = new HashMap();
dataKeys = new LinkedList();
id = entity_id_iterator;
entity_id_iterator++;
}

View File

@ -5,7 +5,7 @@
*/
package electrosphere.entity;
import electrosphere.RendererObjects.Model;
import electrosphere.renderer.Model;
import electrosphere.main.Globals;
import org.joml.Quaternionf;
import org.joml.Vector3f;
@ -17,27 +17,27 @@ import org.joml.Vector3f;
public class EntityUtil {
public static Vector3f getEntityPosition(Entity e){
return (Vector3f)e.getData().get("position");
return (Vector3f)e.getData("position");
}
public static Quaternionf getEntityRotation(Entity e){
return (Quaternionf)e.getData().get("rotation");
return (Quaternionf)e.getData("rotation");
}
public static Vector3f getEntityScale(Entity e){
return (Vector3f)e.getData().get("scale");
return (Vector3f)e.getData("scale");
}
public static Model getEntityModel(Entity e){
return (Model)e.getData().get("model");
return (Model)e.getData("model");
}
public static Entity spawnDrawableEntity(Model m){
Entity rVal = new Entity();
rVal.getData().put("model", m);
rVal.getData().put("position", new Vector3f(0,0,0));
rVal.getData().put("rotation", new Quaternionf().rotateAxis((float)0, new Vector3f(1,0,0)));
rVal.getData().put("scale", new Vector3f(1,1,1));
rVal.putData("model", m);
rVal.putData("position", new Vector3f(0,0,0));
rVal.putData("rotation", new Quaternionf().rotateAxis((float)0, new Vector3f(1,0,0)));
rVal.putData("scale", new Vector3f(1,1,1));
Globals.entityList.add(rVal);
Globals.drawableList.add(rVal);
return rVal;

View File

@ -0,0 +1,20 @@
package electrosphere.game.cell;
/**
*
* @author satellite
*/
public class CellManager {
DrawCell[][] cells;
int drawRadius = 5;
int drawStepdownInterval = 2;
int drawStepdownValue = 10;
public CellManager(){
cells = new DrawCell[drawRadius * 2 + 1][drawRadius * 2 + 1];
}
}

View File

@ -0,0 +1,30 @@
package electrosphere.game.cell;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityUtil;
import electrosphere.renderer.Model;
import electrosphere.util.Utilities;
/**
*
* @author satellite
*/
public class DrawCell {
float[][] elevation;
public DrawCell(float[][] elevation){
this.elevation = elevation;
}
/**
* Generates a drawable entity based on this chunk
* @param stride The stride between indices used to generate "sparse" meshes
* @return A drawable entity that contains the terrain mesh of a certain stride
*/
public Entity generateDrawableEntity(int stride){
Model terrainModel = Utilities.create_terrain_model(elevation, stride);
Entity rVal = EntityUtil.spawnDrawableEntity(terrainModel);
return rVal;
}
}

View File

@ -0,0 +1,100 @@
package electrosphere.game.terrain;
import com.google.gson.Gson;
import electrosphere.main.Globals;
import electrosphere.terraingen.TerrainGen;
import electrosphere.terraingen.models.TerrainModel;
import electrosphere.util.Utilities;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
/**
*
* @author satellite
*/
public class TerrainManager {
//This is the dimension in x and y of the chunk
int chunkSize = 200;
//The size of the world in discrete units * must be multiple of 200
int worldSizeDiscrete = 2000;
int dynamicInterpolationRatio = 200;
TerrainModel model;
public TerrainManager(int chunkSize, int worldSizeDiscrete){
this.chunkSize = chunkSize;
this.worldSizeDiscrete = worldSizeDiscrete;
}
public void generate(){
TerrainGen terrainGen = new TerrainGen();
terrainGen.setInterpolationRatio(worldSizeDiscrete/200);
terrainGen.setDynamicInterpolationRatio(dynamicInterpolationRatio);
terrainGen.setRandomSeed(0);
model = terrainGen.generateModel();
}
public void save(){
Gson gson = new Gson();
String terrainOutRaw = gson.toJson(model);
try {
Files.write(new File(Globals.mainConfig.loadTerrainLocation).toPath(), terrainOutRaw.getBytes());
} catch (IOException ex) {
ex.printStackTrace();
}
}
public void load(){
Gson gson = new Gson();
model = gson.fromJson(Utilities.readFileToString(new File(Globals.mainConfig.loadTerrainLocation)), TerrainModel.class);
}
public float[][] getTerrainAtChunk(int x, int y){
return model.getElevationForChunk(x, y);
}
public float getHeightAtPosition(float x, float y){
//get chunk coordinate space of input x,y
int chunkX = (int)Math.floor(x / chunkSize);
int chunkY = (int)Math.floor(y / chunkSize);
//get local coordinate space of input x,y
float localX = x - chunkX * chunkSize;
float localY = y - chunkY * chunkSize;
//get chunk elevation map
float[][] chunkElevationMap = getTerrainAtChunk(chunkX,chunkY);
//floored variants of local values
int localXf = (int)Math.floor(localX);
int localYf = (int)Math.floor(localY);
/*
Average some inner value.
01 11
0.3 0.4 0.5
0.1 0.2 0.3
00 10
*/
//interp elevation from map
float elevation00 = chunkElevationMap[(int)localX+0][(int)localY+0];
float elevation10 = chunkElevationMap[(int)localX+1][(int)localY+0];
float elevation01 = chunkElevationMap[(int)localX+0][(int)localY+1];
float elevation11 = chunkElevationMap[(int)localX+1][(int)localY+1];
float rVal =
(1-(localX-localXf))*(1-(localY-localYf)) * elevation00 +
( (localX-localXf))*(1-(localY-localYf)) * elevation10 +
(1-(localX-localXf))*( (localY-localYf)) * elevation01 +
( (localX-localXf))*( (localY-localYf)) * elevation11
;
return rVal;
}
}

View File

@ -1,14 +1,15 @@
package electrosphere.main;
import electrosphere.RendererObjects.Camera;
import electrosphere.RendererObjects.Light.DirectionalLight;
import electrosphere.RendererObjects.Light.PointLight;
import electrosphere.RendererObjects.Light.SpotLight;
import electrosphere.RendererObjects.Material;
import electrosphere.RendererObjects.Model;
import electrosphere.RendererObjects.texture.Texture;
import electrosphere.RendererObjects.texture.TextureMap;
import electrosphere.renderer.Camera;
import electrosphere.renderer.light.DirectionalLight;
import electrosphere.renderer.light.PointLight;
import electrosphere.renderer.light.SpotLight;
import electrosphere.renderer.Material;
import electrosphere.renderer.Model;
import electrosphere.renderer.texture.Texture;
import electrosphere.renderer.texture.TextureMap;
import com.google.gson.Gson;
import electrosphere.cfg.MainConfig;
import electrosphere.entity.Entity;
import java.io.File;
import java.io.IOException;
@ -19,6 +20,8 @@ import java.util.logging.Logger;
import org.joml.Matrix4f;
import org.joml.Vector3f;
import electrosphere.util.ModelLoader;
import java.util.concurrent.CopyOnWriteArrayList;
import org.lwjgl.glfw.GLFWErrorCallback;
/**
*
@ -26,6 +29,22 @@ import electrosphere.util.ModelLoader;
*/
public class Globals {
//
//Config
//
public static MainConfig mainConfig;
//
//Generic OpenGL Statements
//
//Callback function for opengl errors
public final static GLFWErrorCallback ERROR_CALLBACK = GLFWErrorCallback.createPrint(System.err);
public static long window;
//
//OpenGL - Other
//
@ -45,8 +64,8 @@ public class Globals {
public static TextureMap textureMapDefault;
public static ArrayList<Entity> entityList;
public static ArrayList<Entity> drawableList;
public static CopyOnWriteArrayList<Entity> entityList;
public static CopyOnWriteArrayList<Entity> drawableList;
public static Camera cameraVisible;
@ -54,6 +73,16 @@ public class Globals {
//Game specific models
//
//chunk stuff
//constant for how far in game units you have to move to load chunks
//array of chunks around view
public static boolean[][] loadedChunk;
public static Entity[][] chunks;
//famous fuckin last words, but temporary solution
//global arraylist of values for the skybox colors
public static ArrayList<Vector3f> skyboxColors;
@ -78,8 +107,8 @@ public class Globals {
textureMapDefault = gson.fromJson(Files.newBufferedReader(new File(Thread.currentThread().getContextClassLoader().getResource("Textures/default_texture_map.json").getFile()).toPath()), TextureMap.class); //only the best of coding practices :)
} catch (IOException ex) { ex.printStackTrace(); } //TODO: handle better :tm:
//create entity list
entityList = new ArrayList();
drawableList = new ArrayList();
entityList = new CopyOnWriteArrayList();
drawableList = new CopyOnWriteArrayList();
//create the camera object that generates view matrix
cameraVisible = new Camera();
//init game specific variables

View File

@ -1,13 +1,16 @@
package electrosphere.main;
import electrosphere.RendererObjects.Camera;
import electrosphere.RendererObjects.Material;
import electrosphere.RendererObjects.Model;
import electrosphere.RendererObjects.RenderUtils;
import electrosphere.RendererObjects.ShaderProgram;
import electrosphere.RendererObjects.texture.Texture;
import com.google.gson.Gson;
import electrosphere.cfg.MainConfig;
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.EntityUtil;
import electrosphere.game.terrain.TerrainManager;
import electrosphere.terraingen.TerrainGen;
import electrosphere.terraingen.models.TerrainModel;
import java.util.ArrayList;
@ -28,7 +31,14 @@ 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.util;
import electrosphere.util.Utilities;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
@ -36,12 +46,6 @@ import electrosphere.util.util;
* @author amaterasu
*/
public class Main {
//
//Generic OpenGL Statements
//
//Callback function for opengl errors
private final static GLFWErrorCallback ERROR_CALLBACK = GLFWErrorCallback.createPrint(System.err);
private static long window;
@ -56,7 +60,7 @@ public class Main {
public static float deltaTime = 0.0f;
public static float lastFrame = 0.0f;
//View Controls
public static float view_Range = 2000.0f;
public static float view_Range = 200000.0f;
public static Camera camera_Current = new Camera();
/*
Mouse Controls
@ -90,10 +94,15 @@ public class Main {
public static Model model;
static TerrainManager terrainManager;
public static void main(String args[]){
Utilities.loadMainConfig();
//
//
// I N I T I A L I Z A T I O N
@ -103,7 +112,7 @@ public class Main {
//run initialization stuff
//Create opengl
createOpenglContext();
RenderUtils.createOpenglContext();
//init global variables
Globals.initGlobals();
@ -118,7 +127,7 @@ public class Main {
Entity player = new Entity();
player.getData().put("position", new Vector3f(0f,6f,0f));
player.putData("position", new Vector3f(0f,6f,0f));
@ -133,7 +142,7 @@ public class Main {
//main loop
while (!glfwWindowShouldClose(window)) {
while (!glfwWindowShouldClose(Globals.window)) {
/*
Frame calculation
@ -168,32 +177,32 @@ public class Main {
/// I N P U T C O N T R O L S
///
cameraSpeed = 2.5f * deltaTime;
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {
if (glfwGetKey(Globals.window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {
break;
}
if (glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS) {
if (glfwGetKey(Globals.window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS) {
if(CAMERA_UNDER_FREE_CONTROL) {
//cameraSpeed = cameraSpeed * 100;
} else if(PLAYER_UNDER_USER_CONTROL) {
}
}
if(glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS){
if(glfwGetKey(Globals.window, GLFW_KEY_W) == GLFW_PRESS){
EntityUtil.getEntityPosition(player).add(new Vector3f(-camera_Current.pos_Center.x,0,-camera_Current.pos_Center.z));
}
if(glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS){
if(glfwGetKey(Globals.window, GLFW_KEY_S) == GLFW_PRESS){
EntityUtil.getEntityPosition(player).add(new Vector3f(camera_Current.pos_Center.x,0,camera_Current.pos_Center.z));
}
if(glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS){
if(glfwGetKey(Globals.window, GLFW_KEY_D) == GLFW_PRESS){
EntityUtil.getEntityPosition(player).add(new Vector3f(-camera_Current.pos_Center.x,0,-camera_Current.pos_Center.z).rotateY((float)(-90 * Math.PI / 180)));
}
if(glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS){
if(glfwGetKey(Globals.window, GLFW_KEY_A) == GLFW_PRESS){
EntityUtil.getEntityPosition(player).add(new Vector3f(-camera_Current.pos_Center.x,0,-camera_Current.pos_Center.z).rotateY((float)(90 * Math.PI / 180)));
}
if(glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS){
if(glfwGetKey(Globals.window, GLFW_KEY_SPACE) == GLFW_PRESS){
EntityUtil.getEntityPosition(player).add(new Vector3f(0,0.6f,0));
}
if(glfwGetKey(window, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS){
if(glfwGetKey(Globals.window, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS){
EntityUtil.getEntityPosition(player).add(new Vector3f(0,-0.6f,0));
}
@ -227,7 +236,7 @@ public class Main {
//check and call events and swap the buffers
glfwSwapBuffers(window);
glfwSwapBuffers(Globals.window);
glfwPollEvents();
}
//Terminate the program.
@ -250,61 +259,11 @@ public class Main {
public static void createOpenglContext(){
//Sets the variables that control the window sizing
int screenWidth = 1920;
int screenHeight = 1080;
//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);
//Creates the window reference object
window = glfwCreateWindow(screenWidth, screenHeight, "LearnOpenGL", NULL, NULL);
//Errors for failure to create window (IE: No GUI mode on linux ?)
if (window == NULL) {
System.out.println("Failed to make window.");
glfwTerminate();
}
//Makes the window that was just created the current OS-level window context
glfwMakeContextCurrent(window);
//Maximize it
glfwMaximizeWindow(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(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
//Points the texture uniforms in the shader programs at the correct variables
//
// 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 updateMouseVariables(){
glfwGetCursorPos(window, mouse_X_Buffer, mouse_Y_Buffer);
glfwGetCursorPos(Globals.window, mouse_X_Buffer, mouse_Y_Buffer);
xpos = mouse_X_Buffer[0];
ypos = mouse_Y_Buffer[0];
float xoffset = (float) (xpos - mouse_lastX) * mouseSensitivity;
@ -342,8 +301,16 @@ public class Main {
static void initWorld(){
TerrainGen terrainGen = new TerrainGen();
TerrainModel terrainModel = terrainGen.generateModel();
float[][] elevation = terrainModel.getElevation();
float[][] elevation;
terrainManager = new TerrainManager(1000,2000);
if(Globals.mainConfig.loadTerrain){
terrainManager.load();
} else {
terrainManager.generate();
terrainManager.save();
}
elevation = terrainManager.getTerrainAtChunk(10, 10);
Model terrainModel = Utilities.create_terrain_model(elevation,10);
Entity terrainEntity = EntityUtil.spawnDrawableEntity(terrainModel);
}
}

View File

@ -1,4 +1,4 @@
package electrosphere.RendererObjects;
package electrosphere.renderer;
import java.util.ArrayList;
import java.util.Iterator;

View File

@ -1,4 +1,4 @@
package electrosphere.RendererObjects;
package electrosphere.renderer;
import java.util.ArrayList;
import org.joml.Matrix4f;

View File

@ -1,4 +1,4 @@
package electrosphere.RendererObjects;
package electrosphere.renderer;
import java.util.ArrayList;
import java.util.HashMap;

View File

@ -1,4 +1,4 @@
package electrosphere.RendererObjects;
package electrosphere.renderer;
import java.util.ArrayList;
import java.util.HashMap;
@ -28,7 +28,7 @@ public class Bone {
deform = new Matrix4f();
final_transform = new Matrix4f();
boneID = raw_data.mName().dataString();
inverseBindPoseMatrix = electrosphere.util.util.convertAIMatrix(raw_data.mOffsetMatrix());
inverseBindPoseMatrix = electrosphere.util.Utilities.convertAIMatrix(raw_data.mOffsetMatrix());
this.raw_data = raw_data;
}
}

View File

@ -1,4 +1,4 @@
package electrosphere.RendererObjects;
package electrosphere.renderer;
import org.joml.Matrix4f;
import org.joml.Quaternionf;

View File

@ -1,4 +1,4 @@
package electrosphere.RendererObjects;
package electrosphere.renderer;
import org.joml.Quaternionf;
import org.joml.Vector3f;

View File

@ -3,7 +3,7 @@
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package electrosphere.RendererObjects.Light;
package electrosphere.renderer.light;
import org.joml.Vector3f;

View File

@ -3,7 +3,7 @@
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package electrosphere.RendererObjects.Light;
package electrosphere.renderer.light;
import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL31.GL_UNIFORM_BUFFER;

View File

@ -3,7 +3,7 @@
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package electrosphere.RendererObjects.Light;
package electrosphere.renderer.light;
import org.joml.Vector3f;

View File

@ -3,7 +3,7 @@
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package electrosphere.RendererObjects.Light;
package electrosphere.renderer.light;
import org.joml.Vector3f;

View File

@ -3,9 +3,9 @@
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package electrosphere.RendererObjects;
package electrosphere.renderer;
import electrosphere.RendererObjects.texture.Texture;
import electrosphere.renderer.texture.Texture;
import org.lwjgl.PointerBuffer;
import org.lwjgl.assimp.AIMaterial;
import org.lwjgl.assimp.AIMaterialProperty;

View File

@ -1,8 +1,8 @@
package electrosphere.RendererObjects;
package electrosphere.renderer;
import electrosphere.main.Globals;
import electrosphere.main.Main;
import electrosphere.RendererObjects.Light.LightBuffer;
import electrosphere.renderer.light.LightBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.ArrayList;
@ -243,7 +243,7 @@ public class Mesh {
// System.out.println("Num weights: " + currentBoneData.mNumWeights());
Bone currentBone = new Bone();
currentBone.boneID = currentBoneData.mName().dataString();
currentBone.inverseBindPoseMatrix = electrosphere.util.util.convertAIMatrix(currentBoneData.mOffsetMatrix());
currentBone.inverseBindPoseMatrix = electrosphere.util.Utilities.convertAIMatrix(currentBoneData.mOffsetMatrix());
currentBone.numWeights = currentBoneData.mNumWeights();
currentBone.weights = new HashMap();
Iterator<AIVertexWeight> weightIterator = currentBoneData.mWeights().iterator();

View File

@ -1,4 +1,4 @@
package electrosphere.RendererObjects;
package electrosphere.renderer;
import electrosphere.main.Globals;
import java.io.File;
@ -21,7 +21,7 @@ import static org.lwjgl.opengl.GL13.*;
import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL20.*;
import static org.lwjgl.opengl.GL30.*;
import electrosphere.RendererObjects.texture.TextureMap;
import electrosphere.renderer.texture.TextureMap;
import java.nio.FloatBuffer;
import java.util.HashMap;
import java.util.Iterator;
@ -119,7 +119,7 @@ public class Model {
//parse animation nodes and form hierarchy
//
AINode rootNode = s.mRootNode();
rVal.globalInverseTransform = electrosphere.util.util.convertAIMatrix(rootNode.mTransformation());
rVal.globalInverseTransform = electrosphere.util.Utilities.convertAIMatrix(rootNode.mTransformation());
// System.out.println("Global inverse transform");
// System.out.println(globalInverseTransform);
rVal.root_anim_node = rVal.build_anim_node_map(s.mRootNode(),null);
@ -324,7 +324,7 @@ public class Model {
// System.out.println("\n\n\n\n");
// }
} else {
n.transform = n.transform.mul(electrosphere.util.util.convertAIMatrix(n.raw_data.mTransformation()));
n.transform = n.transform.mul(electrosphere.util.Utilities.convertAIMatrix(n.raw_data.mTransformation()));
}
Iterator<AnimNode> node_iterator = n.children.iterator();
while(node_iterator.hasNext()){

View File

@ -3,24 +3,45 @@
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package electrosphere.RendererObjects;
package electrosphere.renderer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.ArrayList;
import java.util.Iterator;
import electrosphere.main.Globals;
import static electrosphere.main.Main.view_Range;
import org.joml.Matrix4f;
import org.joml.Vector3f;
import org.lwjgl.BufferUtils;
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.glfwSetInputMode;
import static org.lwjgl.glfw.GLFW.glfwTerminate;
import static org.lwjgl.glfw.GLFW.glfwWindowHint;
import org.lwjgl.opengl.GL;
import org.lwjgl.opengl.GL11;
import static org.lwjgl.opengl.GL11.GL_BLEND;
import static org.lwjgl.opengl.GL11.GL_DEPTH_TEST;
import static org.lwjgl.opengl.GL11.GL_FLOAT;
import static org.lwjgl.opengl.GL11.GL_INT;
import static org.lwjgl.opengl.GL11.GL_LEQUAL;
import static org.lwjgl.opengl.GL11.GL_LESS;
import static org.lwjgl.opengl.GL11.GL_ONE_MINUS_SRC_ALPHA;
import static org.lwjgl.opengl.GL11.GL_SHORT;
import static org.lwjgl.opengl.GL11.GL_SRC_ALPHA;
import static org.lwjgl.opengl.GL11.GL_TRIANGLES;
import static org.lwjgl.opengl.GL11.GL_UNSIGNED_INT;
import static org.lwjgl.opengl.GL11.glBlendFunc;
import static org.lwjgl.opengl.GL11.glEnable;
import org.lwjgl.opengl.GL15;
import static org.lwjgl.opengl.GL15.GL_ARRAY_BUFFER;
import static org.lwjgl.opengl.GL15.GL_STATIC_DRAW;
@ -37,12 +58,75 @@ import static org.lwjgl.opengl.GL20.glUseProgram;
import static org.lwjgl.opengl.GL20.glVertexAttribPointer;
import static org.lwjgl.opengl.GL30.glBindVertexArray;
import static org.lwjgl.opengl.GL30.glGenVertexArrays;
import static org.lwjgl.system.MemoryUtil.NULL;
/**
*
* @author amaterasu
*/
public class RenderUtils {
public static void createOpenglContext(){
//Sets the variables that control the window sizing
int screenWidth = 1920;
int screenHeight = 1080;
//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);
//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);
//Points the texture uniforms in the shader programs at the correct variables
//
// 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 Model createSkyboxModel(Material optionalMaterial){
Model skyboxModel = new Model();
skyboxModel.meshes = new ArrayList();

View File

@ -1,4 +1,4 @@
package electrosphere.RendererObjects;
package electrosphere.renderer;
import electrosphere.main.Main;
import java.io.BufferedReader;

View File

@ -3,7 +3,7 @@
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package electrosphere.RendererObjects.texture;
package electrosphere.renderer.texture;
import java.awt.Color;
import java.awt.image.BufferedImage;

View File

@ -1,4 +1,4 @@
package electrosphere.RendererObjects.texture;
package electrosphere.renderer.texture;
import java.util.ArrayList;
import java.util.HashMap;

View File

@ -1,11 +1,11 @@
package electrosphere.util;
import electrosphere.main.Globals;
import electrosphere.RendererObjects.Material;
import electrosphere.RendererObjects.Mesh;
import electrosphere.RendererObjects.Model;
import electrosphere.RendererObjects.texture.Texture;
import electrosphere.RendererObjects.texture.TextureMap;
import electrosphere.renderer.Material;
import electrosphere.renderer.Mesh;
import electrosphere.renderer.Model;
import electrosphere.renderer.texture.Texture;
import electrosphere.renderer.texture.TextureMap;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;

View File

@ -1,18 +1,23 @@
package electrosphere.util;
import electrosphere.RendererObjects.Material;
import electrosphere.RendererObjects.Mesh;
import electrosphere.RendererObjects.Model;
import electrosphere.RendererObjects.ShaderProgram;
import electrosphere.RendererObjects.texture.Texture;
import electrosphere.RendererObjects.texture.TextureMap;
import electrosphere.renderer.Material;
import electrosphere.renderer.Mesh;
import electrosphere.renderer.Model;
import electrosphere.renderer.ShaderProgram;
import electrosphere.renderer.texture.Texture;
import electrosphere.renderer.texture.TextureMap;
import com.google.gson.Gson;
import electrosphere.cfg.MainConfig;
import electrosphere.main.Globals;
import electrosphere.main.Main;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.joml.Matrix4f;
@ -25,7 +30,7 @@ import static org.lwjgl.opengl.GL30.glGenVertexArrays;
*
* @author awhoove
*/
public class util {
public class Utilities {
@ -70,25 +75,33 @@ public class util {
return rVal;
}
public static Model create_terrain_model(float[][] heightfield){
public static Model create_terrain_model(float[][] heightfield, int stride){
Model rVal = new Model();
rVal.meshes = new ArrayList();
Mesh m = new Mesh();
int width = heightfield.length;
int height = heightfield[0].length;
FloatBuffer vertices = BufferUtils.createFloatBuffer(width * height * 3);
FloatBuffer normals = BufferUtils.createFloatBuffer(width * height * 3);
IntBuffer faces = BufferUtils.createIntBuffer((width - 1) * (height - 1) * 2 * 3);
FloatBuffer texture_coords = BufferUtils.createFloatBuffer(width * height * 2);
for(int x = 0; x < width; x++){
for(int y = 0; y < height; y++){
int actualWidth = width / stride;
int actualHeight = height / stride;
System.out.println(actualWidth + " " + actualHeight);
System.out.println((actualWidth - 1) * (actualHeight - 1));
FloatBuffer vertices = BufferUtils.createFloatBuffer(actualWidth * actualHeight * 3);
FloatBuffer normals = BufferUtils.createFloatBuffer(actualWidth * actualHeight * 3);
IntBuffer faces = BufferUtils.createIntBuffer((actualWidth - 1) * (actualHeight - 1) * 2 * 3);
FloatBuffer texture_coords = BufferUtils.createFloatBuffer(actualWidth * actualHeight * 2);
for(int x = 0; x < width; x = x + stride){
for(int y = 0; y < height; y = y + stride){
//deal with vertex
vertices.put(x);
vertices.put(heightfield[x][y]);
vertices.put(y);
//deal with normal
if(x < width - 1){
if(y < height - 1){
if(x / stride < actualWidth - 1){
if(y / stride < actualHeight - 1){
float hL;
if(x > 0){
hL = heightfield[x-1][y];
@ -125,7 +138,7 @@ public class util {
normals.put(Normal.z);
}
} else {
if(y < height - 1){
if(y / stride < actualHeight - 1){
float hL = heightfield[x-1][y];
float hR = heightfield[x][y];
float hD = heightfield[x][y+1];
@ -153,8 +166,8 @@ public class util {
}
}
//deal with texture coordinates
if(x % 2 == 0){
if(y % 2 == 0){
if(x / stride % 2 == 0){
if(y / stride % 2 == 0){
texture_coords.put(0);
texture_coords.put(0);
} else {
@ -162,7 +175,7 @@ public class util {
texture_coords.put(1);
}
} else {
if(y % 2 == 0){
if(y / stride % 2 == 0){
texture_coords.put(1);
texture_coords.put(0);
} else {
@ -171,13 +184,13 @@ public class util {
}
}
//deal with faces
if(x < width - 1 && y < height - 1){
faces.put((x + 0) * height + (y + 0));
faces.put((x + 0) * height + (y + 1));
faces.put((x + 1) * height + (y + 0));
faces.put((x + 1) * height + (y + 0));
faces.put((x + 0) * height + (y + 1));
faces.put((x + 1) * height + (y + 1));
if(x / stride < actualWidth - 1 && y / stride < actualHeight - 1){
faces.put((x / stride + 0) * actualHeight + (y / stride + 0));
faces.put((x / stride + 0) * actualHeight + (y / stride + 1));
faces.put((x / stride + 1) * actualHeight + (y / stride + 0));
faces.put((x / stride + 1) * actualHeight + (y / stride + 0));
faces.put((x / stride + 0) * actualHeight + (y / stride + 1));
faces.put((x / stride + 1) * actualHeight + (y / stride + 1));
}
}
}
@ -200,11 +213,11 @@ public class util {
glBindVertexArray(0);
m.parent = rVal;
Material grass_mat = new Material();
Texture grass_texture = new Texture("Textures/grass_texture.jpg");
grass_mat.set_diffuse(grass_texture);
grass_mat.set_specular(grass_texture);
m.set_material(grass_mat);
Material groundMat = new Material();
Texture groundTex = new Texture("Textures/Ground/Dirt1.png");
groundMat.set_diffuse(groundTex);
groundMat.set_specular(groundTex);
m.set_material(groundMat);
rVal.meshes.add(m);
return rVal;
@ -231,4 +244,51 @@ public class util {
ex.printStackTrace(); // just for testing :thinking:
}
}
static final int maxReadFails = 3;
static final int READ_TIMEOUT_DURATION = 5;
public static String readFileToString(File f){
String rVal = "";
BufferedReader reader;
try {
reader = Files.newBufferedReader(f.toPath());
int failCounter = 0;
boolean reading = true;
StringBuilder builder = new StringBuilder("");
while(reading){
if(reader.ready()){
failCounter = 0;
int nextValue = reader.read();
if(nextValue == -1){
reading = false;
} else {
builder.append((char)nextValue);
}
} else {
failCounter++;
if(failCounter > maxReadFails){
reading = false;
} else {
try {
TimeUnit.MILLISECONDS.sleep(READ_TIMEOUT_DURATION);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
}
rVal = builder.toString();
} catch (IOException ex) {
ex.printStackTrace();
}
return rVal;
}
public static void loadMainConfig(){
Gson gson = new Gson();
String configRaw = Utilities.readFileToString(new File(Main.class.getResource("/Config/localconfig.json").getPath()));
Globals.mainConfig = gson.fromJson(configRaw, MainConfig.class);
}
}

View File

@ -0,0 +1,5 @@
{
"projectMainDirectory" : "/Users/satellite/p/Renderer/src/main/resources/Config",
"loadTerrain" : true,
"loadTerrainLocation" : "/Users/satellite/p/Renderer/src/main/resources/Config/terrain.json"
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,145 @@
#version 330 core
out vec4 FragColor;
struct Material {
sampler2D diffuse;
sampler2D specular;
float shininess;
};
struct DirLight {
vec3 direction;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
struct PointLight {
vec3 position;
float constant;
float linear;
float quadratic;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
struct SpotLight {
vec3 position;
vec3 direction;
float cutOff;
float outerCutOff;
float constant;
float linear;
float quadratic;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
#define NR_POINT_LIGHTS 10
in vec3 FragPos;
in vec3 Normal;
in vec2 TexCoord;
uniform vec3 viewPos;
uniform DirLight dirLight;
uniform PointLight pointLights[NR_POINT_LIGHTS];
uniform SpotLight spotLight;
uniform Material material;
//texture stuff
uniform sampler2D ourTexture;
uniform int hasTransparency;
// function prototypes
vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir);
vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir);
vec3 CalcSpotLight(SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir);
void main(){
if(hasTransparency == 1){
if(texture(material.diffuse, TexCoord).a < 0.1){
discard;
}
}
vec3 norm = normalize(Normal);
vec3 viewDir = normalize(viewPos - FragPos);
vec3 reflected = reflect(viewDir,norm);
vec3 result = CalcDirLight(dirLight, norm, viewDir);
FragColor = vec4(result, texture(material.diffuse, TexCoord).a);
}
// calculates the color when using a directional light.
vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir){
vec3 lightDir = normalize(-light.direction);
// diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
// specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
// combine results
vec3 texColor = texture(material.diffuse, TexCoord).rgb;
vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoord).rgb);
vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoord).rgb);
//vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoord).rgb);
return (ambient + diffuse);// + specular);
}
// calculates the color when using a point light.
vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir){
vec3 lightDir = normalize(light.position - fragPos);
// diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
// specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
// attenuation
float distance = length(light.position - fragPos);
float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance));
// combine results
vec3 ambient = light.ambient * vec4(texture(material.diffuse, TexCoord)).xyz;
vec3 diffuse = light.diffuse * diff * vec4(texture(material.diffuse, TexCoord)).xyz;
vec3 specular = light.specular * spec * vec4(texture(material.specular, TexCoord)).xyz;
ambient *= attenuation;
diffuse *= attenuation;
specular *= attenuation;
return (ambient + diffuse + specular);
}
// calculates the color when using a spot light.
vec3 CalcSpotLight(SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir)
{
vec3 lightDir = normalize(light.position - fragPos);
// diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
// specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
// attenuation
float distance = length(light.position - fragPos);
float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance));
// spotlight intensity
float theta = dot(lightDir, normalize(-light.direction));
float epsilon = light.cutOff - light.outerCutOff;
float intensity = clamp((theta - light.outerCutOff) / epsilon, 0.0, 1.0);
// combine results
vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoord));
vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoord));
vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoord));
ambient *= attenuation * intensity;
diffuse *= attenuation * intensity;
specular *= attenuation * intensity;
return (ambient + diffuse + specular);
}

View File

@ -0,0 +1,56 @@
//Vertex Shader
#version 330 core
//input buffers
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
layout (location = 2) in vec4 aWeights;
layout (location = 3) in vec4 aIndex;
layout (location = 4) in vec2 aTex;
//coordinate space transformation matrices
uniform mat4 transform;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
//bone related variables
const int MAX_WEIGHTS = 4;
const int MAX_BONES = 100;
uniform mat4 bones[MAX_BONES];
uniform int hasBones;
uniform int numBones;
//output buffers
out vec3 Normal;
out vec3 FragPos;
out vec2 TexCoord;
void main()
{
//calculate bone transform
mat4 BoneTransform = (bones[int(aIndex[0])] * aWeights[0]);
BoneTransform = BoneTransform + (bones[int(aIndex[1])] * aWeights[1]);
BoneTransform = BoneTransform + (bones[int(aIndex[2])] * aWeights[2]);
BoneTransform = BoneTransform + (bones[int(aIndex[3])] * aWeights[3]);
//apply bone transform to position vectors
vec4 FinalVertex = BoneTransform * vec4(aPos, 1.0);
vec4 FinalNormal = BoneTransform * vec4(aNormal, 1.0);
//make sure the W component is 1.0
FinalVertex = vec4(FinalVertex.xyz, 1.0);
FinalNormal = vec4(FinalNormal.xyz, 1.0);
//push frag, normal, and texture positions to fragment shader
FragPos = vec3(model * FinalVertex);
Normal = mat3(transpose(inverse(model))) * aNormal;
TexCoord = aTex;
//set final position with opengl space
gl_Position = projection * view * model * FinalVertex;
}