From 21fb8b0e3afd39a9883eb19749cd5296bc8383ec Mon Sep 17 00:00:00 2001 From: austin Date: Thu, 29 May 2025 11:37:49 -0400 Subject: [PATCH] legacy code reorg --- docs/src/progress/renderertodo.md | 1 + .../electrosphere/data/entity/item/Item.java | 4 +- .../java/electrosphere/engine/Globals.java | 19 +- .../loadingthreads/InitialAssetLoading.java | 6 +- .../electrosphere/renderer/RenderUtils.java | 1683 +---------------- .../renderer/RenderingEngine.java | 4 +- .../renderer/meshgen/EngineMeshgen.java | 463 +++++ .../renderer/meshgen/GeometryModelGen.java | 402 ++++ .../renderer/meshgen/HeightmapMeshgen.java | 801 ++++++++ 9 files changed, 1695 insertions(+), 1688 deletions(-) create mode 100644 src/main/java/electrosphere/renderer/meshgen/EngineMeshgen.java create mode 100644 src/main/java/electrosphere/renderer/meshgen/GeometryModelGen.java create mode 100644 src/main/java/electrosphere/renderer/meshgen/HeightmapMeshgen.java diff --git a/docs/src/progress/renderertodo.md b/docs/src/progress/renderertodo.md index c9f1302c..9516ebde 100644 --- a/docs/src/progress/renderertodo.md +++ b/docs/src/progress/renderertodo.md @@ -2053,6 +2053,7 @@ Scaffolding towns and character jobs data Properly async-ify inventory/item related tests Fix viewport interaction with lod emitter service Fix most tests +Rendering engine legacy code reorganization diff --git a/src/main/java/electrosphere/data/entity/item/Item.java b/src/main/java/electrosphere/data/entity/item/Item.java index 92970337..c266eaee 100644 --- a/src/main/java/electrosphere/data/entity/item/Item.java +++ b/src/main/java/electrosphere/data/entity/item/Item.java @@ -15,7 +15,7 @@ import electrosphere.data.entity.graphics.NonproceduralModel; import electrosphere.data.voxel.VoxelType; import electrosphere.engine.Globals; import electrosphere.engine.assetmanager.AssetDataStrings; -import electrosphere.renderer.RenderUtils; +import electrosphere.renderer.meshgen.GeometryModelGen; /** * Data on a given item @@ -177,7 +177,7 @@ public class Item extends CommonEntityType { Map> meshUniformMap = new HashMap>(); Map uniforms = new HashMap(); uniforms.put("blockAtlasIndex",Globals.blockTextureAtlas.getVoxelTypeOffset(blockType.getId())); - meshUniformMap.put(RenderUtils.MESH_NAME_BLOCK_SINGLE,uniforms); + meshUniformMap.put(GeometryModelGen.MESH_NAME_BLOCK_SINGLE,uniforms); modelData.setUniforms(meshUniformMap); //set item class diff --git a/src/main/java/electrosphere/engine/Globals.java b/src/main/java/electrosphere/engine/Globals.java index 2f9875ff..62199084 100644 --- a/src/main/java/electrosphere/engine/Globals.java +++ b/src/main/java/electrosphere/engine/Globals.java @@ -20,11 +20,12 @@ import electrosphere.engine.profiler.Profiler; import electrosphere.logger.LoggerInterface; import electrosphere.net.config.NetConfig; import electrosphere.net.monitor.NetMonitor; -import electrosphere.renderer.RenderUtils; import electrosphere.renderer.RenderingEngine; import electrosphere.renderer.actor.instance.InstanceManager; import electrosphere.renderer.loading.ModelPretransforms; +import electrosphere.renderer.meshgen.EngineMeshgen; import electrosphere.renderer.meshgen.FluidChunkModelGeneration; +import electrosphere.renderer.meshgen.GeometryModelGen; import electrosphere.renderer.shader.ShaderOptionMap; import electrosphere.renderer.shader.VisualShader; import electrosphere.renderer.texture.TextureMap; @@ -279,9 +280,9 @@ public class Globals { //create font manager fontManager = new FontManager(); fontManager.loadFonts(); - assetManager.registerModelWithPath(RenderUtils.createBitmapCharacter(), AssetDataStrings.BITMAP_CHARACTER_MODEL); + assetManager.registerModelWithPath(EngineMeshgen.createBitmapCharacter(), AssetDataStrings.BITMAP_CHARACTER_MODEL); //particle billboard model - assetManager.registerModelWithPath(RenderUtils.createParticleModel(), AssetDataStrings.MODEL_PARTICLE); + assetManager.registerModelWithPath(EngineMeshgen.createParticleModel(), AssetDataStrings.MODEL_PARTICLE); //initialize required windows WindowUtils.initBaseWindows(); //init default shaderProgram @@ -292,15 +293,15 @@ public class Globals { //init fluid shader program FluidChunkModelGeneration.fluidChunkShaderProgram = VisualShader.loadSpecificShader("/Shaders/entities/fluid2/fluid2.vs", "/Shaders/entities/fluid2/fluid2.fs"); //init models - assetManager.registerModelWithPath(RenderUtils.createUnitsphere(), AssetDataStrings.UNITSPHERE); - assetManager.registerModelWithPath(RenderUtils.createUnitCylinder(), AssetDataStrings.UNITCYLINDER); - assetManager.registerModelWithPath(RenderUtils.createUnitCube(), AssetDataStrings.UNITCUBE); - assetManager.registerModelWithPath(RenderUtils.createBlockSingleModel(), AssetDataStrings.MODEL_BLOCK_SINGLE); + assetManager.registerModelWithPath(GeometryModelGen.createUnitsphere(), AssetDataStrings.UNITSPHERE); + assetManager.registerModelWithPath(GeometryModelGen.createUnitCylinder(), AssetDataStrings.UNITCYLINDER); + assetManager.registerModelWithPath(GeometryModelGen.createUnitCube(), AssetDataStrings.UNITCUBE); + assetManager.registerModelWithPath(GeometryModelGen.createBlockSingleModel(), AssetDataStrings.MODEL_BLOCK_SINGLE); assetManager.addModelPathToQueue("Models/basic/geometry/SmallCube.fbx"); assetManager.addModelPathToQueue("Models/basic/geometry/unitcapsule.glb"); assetManager.addModelPathToQueue("Models/basic/geometry/unitplane.fbx"); assetManager.addModelPathToQueue("Models/basic/geometry/unitcube.fbx"); - assetManager.registerModelWithPath(RenderUtils.createPlaneModel("Shaders/core/plane/plane.vs", "Shaders/core/plane/plane.fs"), AssetDataStrings.MODEL_IMAGE_PLANE); + assetManager.registerModelWithPath(GeometryModelGen.createPlaneModel("Shaders/core/plane/plane.vs", "Shaders/core/plane/plane.fs"), AssetDataStrings.MODEL_IMAGE_PLANE); assetManager.addShaderToQueue("Shaders/core/plane/plane.vs", "Shaders/core/plane/plane.fs"); //init pose models for basic shapes @@ -310,7 +311,7 @@ public class Globals { } //image panel - ImagePanel.imagePanelModelPath = assetManager.registerModel(RenderUtils.createPlaneModel("Shaders/core/imagepanel/imagepanel.vs", "Shaders/core/imagepanel/imagepanel.fs")); + ImagePanel.imagePanelModelPath = assetManager.registerModel(GeometryModelGen.createPlaneModel("Shaders/core/imagepanel/imagepanel.vs", "Shaders/core/imagepanel/imagepanel.fs")); Globals.assetManager.addShaderToQueue("Shaders/ui/plainBox/plainBox.vs", "Shaders/ui/plainBox/plainBox.fs"); diff --git a/src/main/java/electrosphere/engine/loadingthreads/InitialAssetLoading.java b/src/main/java/electrosphere/engine/loadingthreads/InitialAssetLoading.java index 0b104463..01c8c27b 100644 --- a/src/main/java/electrosphere/engine/loadingthreads/InitialAssetLoading.java +++ b/src/main/java/electrosphere/engine/loadingthreads/InitialAssetLoading.java @@ -20,7 +20,7 @@ import electrosphere.engine.Globals; import electrosphere.engine.assetmanager.AssetDataStrings; import electrosphere.engine.assetmanager.queue.QueuedTexture; import electrosphere.logger.LoggerInterface; -import electrosphere.renderer.RenderUtils; +import electrosphere.renderer.meshgen.GeometryModelGen; import electrosphere.renderer.texture.TextureAtlas; import electrosphere.util.FileUtils; @@ -129,7 +129,7 @@ public class InitialAssetLoading { //if items have been created, must update the hard-coded shader values to reflect the actual atlas values if(Globals.gameConfigCurrent.getItemMap().getItem(type.getName()) != null){ Item item = Globals.gameConfigCurrent.getItemMap().getItem(type.getName()); - item.getGraphicsTemplate().getModel().getUniforms().get(RenderUtils.MESH_NAME_BLOCK_SINGLE).put("blockAtlasIndex",iterator); + item.getGraphicsTemplate().getModel().getUniforms().get(GeometryModelGen.MESH_NAME_BLOCK_SINGLE).put("blockAtlasIndex",iterator); } //iterate @@ -161,7 +161,7 @@ public class InitialAssetLoading { for(BlockType blockType : Globals.gameConfigCurrent.getBlockData().getTypes()){ String typeId = "block:" + blockType.getName(); Item item = Globals.gameConfigCurrent.getItemMap().getItem(typeId); - item.getGraphicsTemplate().getModel().getUniforms().get(RenderUtils.MESH_NAME_BLOCK_SINGLE).put("blockAtlasIndex",Globals.blockTextureAtlas.getVoxelTypeOffset(blockType.getId())); + item.getGraphicsTemplate().getModel().getUniforms().get(GeometryModelGen.MESH_NAME_BLOCK_SINGLE).put("blockAtlasIndex",Globals.blockTextureAtlas.getVoxelTypeOffset(blockType.getId())); } } diff --git a/src/main/java/electrosphere/renderer/RenderUtils.java b/src/main/java/electrosphere/renderer/RenderUtils.java index 76e5ad2e..c24aebe9 100644 --- a/src/main/java/electrosphere/renderer/RenderUtils.java +++ b/src/main/java/electrosphere/renderer/RenderUtils.java @@ -1,633 +1,33 @@ package electrosphere.renderer; import electrosphere.engine.Globals; -import electrosphere.engine.assetmanager.AssetDataStrings; -import java.nio.FloatBuffer; -import java.nio.IntBuffer; import java.util.LinkedList; import java.util.List; import electrosphere.renderer.actor.ActorTextureMask; -import electrosphere.renderer.model.Material; import electrosphere.renderer.model.Mesh; import electrosphere.renderer.model.Model; -import electrosphere.renderer.shader.VisualShader; import electrosphere.renderer.texture.Texture; -import org.joml.Vector3f; -import org.lwjgl.BufferUtils; - -import static org.lwjgl.opengl.GL11.GL_FLOAT; -import org.lwjgl.opengl.GL40; -import org.lwjgl.util.par.ParShapes; -import org.lwjgl.util.par.ParShapesMesh; - /** * Utilities to assist with rendering */ public class RenderUtils { /** - * Name of the mesh for the single block model + * Generates a volumetric texture mask + * @param meshName The name of the mesh to mask + * @return The texture mask to replace that mesh's texture with a volumetric texture */ - public static final String MESH_NAME_BLOCK_SINGLE = "cube"; - - - - static int createScreenTextureVAO(OpenGLState openGLState){ - int rVal = GL40.glGenVertexArrays(); - openGLState.glBindVertexArray(rVal); - //vertices - FloatBuffer vertexArrayBufferData = BufferUtils.createFloatBuffer(12); - vertexArrayBufferData.put(-1.0f); - vertexArrayBufferData.put( 1.0f); - - vertexArrayBufferData.put(-1.0f); - vertexArrayBufferData.put(-1.0f); - - vertexArrayBufferData.put( 1.0f); - vertexArrayBufferData.put(-1.0f); - - vertexArrayBufferData.put(-1.0f); - vertexArrayBufferData.put( 1.0f); - - vertexArrayBufferData.put( 1.0f); - vertexArrayBufferData.put(-1.0f); - - vertexArrayBufferData.put( 1.0f); - vertexArrayBufferData.put( 1.0f); - vertexArrayBufferData.flip(); - int vertexBuffer = GL40.glGenBuffers(); - GL40.glBindBuffer(GL40.GL_ARRAY_BUFFER, vertexBuffer); - GL40.glBufferData(GL40.GL_ARRAY_BUFFER, vertexArrayBufferData, GL40.GL_STATIC_DRAW); - GL40.glVertexAttribPointer(0, 2, GL_FLOAT, false, 0, 0); - GL40.glEnableVertexAttribArray(0); - - - - - - //texture coords - FloatBuffer textureArrayBufferData = BufferUtils.createFloatBuffer(12); - textureArrayBufferData.put(0.0f); - textureArrayBufferData.put(1.0f); - - textureArrayBufferData.put(0.0f); - textureArrayBufferData.put(0.0f); - - textureArrayBufferData.put(1.0f); - textureArrayBufferData.put(0.0f); - - textureArrayBufferData.put(0.0f); - textureArrayBufferData.put(1.0f); - - textureArrayBufferData.put(1.0f); - textureArrayBufferData.put(0.0f); - - textureArrayBufferData.put(1.0f); - textureArrayBufferData.put(1.0f); - textureArrayBufferData.flip(); - int textureCoordBuffer = GL40.glGenBuffers(); - GL40.glBindBuffer(GL40.GL_ARRAY_BUFFER, textureCoordBuffer); - GL40.glBufferData(GL40.GL_ARRAY_BUFFER, textureArrayBufferData, GL40.GL_STATIC_DRAW); - GL40.glVertexAttribPointer(1, 2, GL_FLOAT, false, 0, 0); - GL40.glEnableVertexAttribArray(1); - - return rVal; - } - - - - - // public static void recaptureScreen(){ - // //Makes the window that was just created the current OS-level window context - // // glfwMakeContextCurrent(Globals.window); - // //Maximize it - // // glfwMaximizeWindow(Globals.window); - // //grab focus - // GLFW.glfwFocusWindow(Globals.window); - // //apply mouse controls state - // if(Globals.controlHandler.isMouseVisible()){ - // Globals.controlHandler.showMouse(); - // } else { - // Globals.controlHandler.hideMouse(); - // } - // } - - - - - - - - - - public static Model createParticleModel(){ - Model particleModel = new Model(); - - - Mesh particleMesh = new Mesh("particleBillboard"); - - - // - // VAO - // - OpenGLState openGLState = Globals.renderingEngine.getOpenGLState(); - particleMesh.generateVAO(openGLState); - - - - - - - - - - - float[] vertexcoords = { - -1.0f, 1.0f, 0.0f, - 1.0f, 1.0f, 0.0f, - -1.0f, -1.0f, 0.0f, - 1.0f, -1.0f, 0.0f, - }; - - // - //Buffer data to GPU - // - - try { - int vertexCount = vertexcoords.length / 3; - FloatBuffer vertexArrayBufferData = BufferUtils.createFloatBuffer(vertexCount * 3); - float[] temp = new float[3]; - for (int i = 0; i < vertexCount; i++) { - temp[0] = vertexcoords[i * 3 + 0]; - temp[1] = vertexcoords[i * 3 + 1]; - temp[2] = vertexcoords[i * 3 + 2]; - vertexArrayBufferData.put(temp); - } - vertexArrayBufferData.flip(); - particleMesh.bufferVertices(vertexArrayBufferData, 3); - } catch (NullPointerException ex){ - ex.printStackTrace(); - } - - int[] facedata = { - 0,1,2, - 1,2,3, - }; - - // - // FACES - // - int faceCount = facedata.length / 3; - int elementCount = facedata.length; - IntBuffer elementArrayBufferData = BufferUtils.createIntBuffer(elementCount); - for(int i = 0; i < faceCount; i++){ - int[] temp = new int[3]; - temp[0] = facedata[i * 3 + 0]; - temp[1] = facedata[i * 3 + 1]; - temp[2] = facedata[i * 3 + 2]; - elementArrayBufferData.put(temp); - } - elementArrayBufferData.flip(); - particleMesh.bufferFaces(elementArrayBufferData,elementCount); - - // - // TEXTURE COORDS - // - FloatBuffer texture_coords = BufferUtils.createFloatBuffer(8); - float[] texturedata = { - 0,1, - 1,1, - 0,0, - 1,0 - }; - texture_coords.put(texturedata); - texture_coords.flip(); - particleMesh.bufferTextureCoords(texture_coords, 2); - - - - VisualShader shader = VisualShader.smartAssembleOITProgram(); - particleMesh.setShader(shader); - - - - - openGLState.glBindVertexArray(0); - - - - - particleMesh.setMaterial(Material.createExisting(AssetDataStrings.TEXTURE_PARTICLE)); - - - - - particleMesh.setParent(particleModel); - - - particleModel.getMeshes().add(particleMesh); - - - return particleModel; - } - - - public static Model createPlaneModel(String vertexShader, String fragmentShader){ - Model rVal = new Model(); - - - Mesh planeMesh = new Mesh("plane"); - - - - // - // VAO - // - OpenGLState openGLState = Globals.renderingEngine.getOpenGLState(); - planeMesh.generateVAO(openGLState); - - - - - - - - - - - float[] vertexcoords = { - -1.0f, 1.0f, 0.0f, - 1.0f, 1.0f, 0.0f, - -1.0f, -1.0f, 0.0f, - 1.0f, -1.0f, 0.0f, - - }; - - // - //Buffer data to GPU - // - - try { - int vertexCount = vertexcoords.length / 3; - FloatBuffer vertexArrayBufferData = BufferUtils.createFloatBuffer(vertexCount * 3); - float[] temp = new float[3]; - for (int i = 0; i < vertexCount; i++) { - temp[0] = vertexcoords[i * 3 + 0]; - temp[1] = vertexcoords[i * 3 + 1]; - temp[2] = vertexcoords[i * 3 + 2]; - vertexArrayBufferData.put(temp); - } - vertexArrayBufferData.flip(); - planeMesh.bufferVertices(vertexArrayBufferData, 3); - } catch (NullPointerException ex){ - ex.printStackTrace(); - } - - int[] facedata = { - 0,1,2, - 1,2,3, - }; - - // - // FACES - // - int faceCount = facedata.length / 3; - int elementCount = facedata.length; - IntBuffer elementArrayBufferData = BufferUtils.createIntBuffer(elementCount); - for(int i = 0; i < faceCount; i++){ - int[] temp = new int[3]; - temp[0] = facedata[i * 3 + 0]; - temp[1] = facedata[i * 3 + 1]; - temp[2] = facedata[i * 3 + 2]; - elementArrayBufferData.put(temp); - } - elementArrayBufferData.flip(); - planeMesh.bufferFaces(elementArrayBufferData,elementCount); - - // - // TEXTURE COORDS - // - FloatBuffer texture_coords = BufferUtils.createFloatBuffer(8); - float[] texturedata = { - 0,1, - 1,1, - 0,0, - 1,0 - }; - texture_coords.put(texturedata); - texture_coords.flip(); - planeMesh.bufferTextureCoords(texture_coords, 2); - - - - - planeMesh.setShader(VisualShader.loadSpecificShader(vertexShader,fragmentShader)); - - - - - openGLState.glBindVertexArray(0); - - - - - - - - - - planeMesh.setParent(rVal); - - - rVal.getMeshes().add(planeMesh); - - - return rVal; - } - - /** - * Generates a unit sphere model - * @return The model - */ - public static Model createUnitsphere(){ - Model model = new Model(); - Mesh sphereMesh = new Mesh("sphere"); - OpenGLState openGLState = Globals.renderingEngine.getOpenGLState(); - sphereMesh.generateVAO(openGLState); - - //buffer coords - ParShapesMesh data = ParShapes.par_shapes_create_parametric_sphere(10, 5); - int numPoints = data.npoints(); - - //verts - { - FloatBuffer verts = data.points(numPoints * 3); - FloatBuffer vertsFinal = BufferUtils.createFloatBuffer(verts.limit()); //reallocating to BufferUtils buffer to help minimize memory errors - vertsFinal.put(verts); - vertsFinal.flip(); - sphereMesh.bufferVertices(vertsFinal, 3); - } - - //indices - { - IntBuffer indices = data.triangles(data.ntriangles() * 3); - IntBuffer indicesFinal = BufferUtils.createIntBuffer(indices.limit()); //reallocating to BufferUtils buffer to help minimize memory errors - indicesFinal.put(indices); - indicesFinal.flip(); - sphereMesh.bufferFaces(indicesFinal, data.ntriangles() * 3); - } - - //texture coords - { - FloatBuffer texCoords = data.tcoords(numPoints * 3); - FloatBuffer texCoordsFinal = BufferUtils.createFloatBuffer(texCoords.limit()); //reallocating to BufferUtils buffer to help minimize memory errors - texCoordsFinal.put(texCoords); - texCoordsFinal.flip(); - sphereMesh.bufferTextureCoords(texCoordsFinal, 2); - } - - - //setup extra structures - Material mat = Material.createExisting(AssetDataStrings.TEXTURE_TEAL_TRANSPARENT); - sphereMesh.setMaterial(mat); - sphereMesh.setShader(VisualShader.smartAssembleShader()); - openGLState.glBindVertexArray(0); - sphereMesh.setParent(model); - model.getMeshes().add(sphereMesh); - - return model; - } - - /** - * Creates a unit cylinder model - * @return The model - */ - public static Model createUnitCylinder(){ - Model model = new Model(); - Mesh sphereMesh = new Mesh("cylinder"); - OpenGLState openGLState = Globals.renderingEngine.getOpenGLState(); - sphereMesh.generateVAO(openGLState); - - //buffer coords - ParShapesMesh data = ParShapes.par_shapes_create_cylinder(10, 2); - ParShapes.par_shapes_rotate(data, (float)(Math.PI / 2.0), new float[]{-1,0,0}); - ParShapes.par_shapes_translate(data, 0, -0.5f, 0); - ParShapes.par_shapes_scale(data, -1.0f, 2.0f, 1.0f); - int numPoints = data.npoints(); - - //verts - { - FloatBuffer verts = data.points(numPoints * 3); - FloatBuffer vertsFinal = BufferUtils.createFloatBuffer(verts.limit()); //reallocating to BufferUtils buffer to help minimize memory errors - vertsFinal.put(verts); - vertsFinal.flip(); - sphereMesh.bufferVertices(vertsFinal, 3); - } - - //indices - { - IntBuffer indices = data.triangles(data.ntriangles() * 3); - IntBuffer indicesFinal = BufferUtils.createIntBuffer(indices.limit()); //reallocating to BufferUtils buffer to help minimize memory errors - indicesFinal.put(indices); - indicesFinal.flip(); - sphereMesh.bufferFaces(indicesFinal, data.ntriangles() * 3); - } - - //texture coords - { - FloatBuffer texCoords = data.tcoords(numPoints * 3); - FloatBuffer texCoordsFinal = BufferUtils.createFloatBuffer(texCoords.limit()); //reallocating to BufferUtils buffer to help minimize memory errors - texCoordsFinal.put(texCoords); - texCoordsFinal.flip(); - sphereMesh.bufferTextureCoords(texCoordsFinal, 2); - } - - //setup extra structures - Material mat = Material.createExisting(AssetDataStrings.TEXTURE_TEAL_TRANSPARENT); - sphereMesh.setMaterial(mat); - sphereMesh.setShader(VisualShader.smartAssembleShader()); - openGLState.glBindVertexArray(0); - sphereMesh.setParent(model); - model.getMeshes().add(sphereMesh); - - return model; - } - - /** - * Creates a unit cylinder model - * @return The model - */ - public static Model createUnitCube(){ - Model model = new Model(); - Mesh sphereMesh = new Mesh("cube"); - OpenGLState openGLState = Globals.renderingEngine.getOpenGLState(); - sphereMesh.generateVAO(openGLState); - - //buffer coords - int numTriangles = 12; - - //verts - BufferUtils.createFloatBuffer(3 * 8); - FloatBuffer verts = BufferUtils.createFloatBuffer(3 * 8); - verts.put(new float[]{ - -0.5f,-0.5f,-0.5f, - 0.5f,-0.5f,-0.5f, - -0.5f, 0.5f,-0.5f, - 0.5f, 0.5f,-0.5f, - - -0.5f,-0.5f, 0.5f, - 0.5f,-0.5f, 0.5f, - -0.5f, 0.5f, 0.5f, - 0.5f, 0.5f, 0.5f, - }); - verts.flip(); - sphereMesh.bufferVertices(verts, 3); - - //indices - IntBuffer indices = BufferUtils.createIntBuffer(3*12); - indices.put(new int[]{ - //Top - 2, 6, 7, - 2, 3, 7, - - //Bottom - 0, 4, 5, - 0, 1, 5, - - //Left - 0, 2, 6, - 0, 4, 6, - - //Right - 1, 3, 7, - 1, 5, 7, - - //Front - 0, 2, 3, - 0, 1, 3, - - //Back - 4, 6, 7, - 4, 5, 7 - }); - indices.flip(); - sphereMesh.bufferFaces(indices, numTriangles * 3); - - //texture coords - FloatBuffer texCoords = BufferUtils.createFloatBuffer(2*8); - texCoords.put(new float[]{ - 0,0, - 1,0, - 0,1, - 1,1, - - 0,0, - 0,1, - 1,0, - 1,1, - }); - texCoords.flip(); - sphereMesh.bufferTextureCoords(texCoords, 2); - - //setup extra structures - Material mat = Material.createExisting(AssetDataStrings.TEXTURE_TEAL_TRANSPARENT); - sphereMesh.setMaterial(mat); - sphereMesh.setShader(VisualShader.smartAssembleShader()); - openGLState.glBindVertexArray(0); - sphereMesh.setParent(model); - model.getMeshes().add(sphereMesh); - - return model; - } - - /** - * Creates a unit cylinder model - * @return The model - */ - public static Model createBlockSingleModel(){ - Model model = new Model(); - Mesh cubeMesh = new Mesh(RenderUtils.MESH_NAME_BLOCK_SINGLE); - OpenGLState openGLState = Globals.renderingEngine.getOpenGLState(); - cubeMesh.generateVAO(openGLState); - - //buffer coords - int numTriangles = 12; - - //verts - BufferUtils.createFloatBuffer(3 * 8); - FloatBuffer verts = BufferUtils.createFloatBuffer(3 * 8); - verts.put(new float[]{ - -0.1f,-0.1f,-0.1f, - 0.1f,-0.1f,-0.1f, - -0.1f, 0.1f,-0.1f, - 0.1f, 0.1f,-0.1f, - - -0.1f,-0.1f, 0.1f, - 0.1f,-0.1f, 0.1f, - -0.1f, 0.1f, 0.1f, - 0.1f, 0.1f, 0.1f, - }); - verts.flip(); - cubeMesh.bufferVertices(verts, 3); - - //indices - IntBuffer indices = BufferUtils.createIntBuffer(3*12); - indices.put(new int[]{ - //Top - 2, 6, 7, - 2, 3, 7, - - //Bottom - 0, 4, 5, - 0, 1, 5, - - //Left - 0, 2, 6, - 0, 4, 6, - - //Right - 1, 3, 7, - 1, 5, 7, - - //Front - 0, 2, 3, - 0, 1, 3, - - //Back - 4, 6, 7, - 4, 5, 7 - }); - indices.flip(); - cubeMesh.bufferFaces(indices, numTriangles * 3); - - //texture coords - FloatBuffer texCoords = BufferUtils.createFloatBuffer(2*8); - texCoords.put(new float[]{ - 0,0, - 1,0, - 0,1, - 1,1, - - 0,0, - 0,1, - 1,0, - 1,1, - }); - texCoords.flip(); - cubeMesh.bufferTextureCoords(texCoords, 2); - - //setup extra structures - Material mat = Material.createExisting(AssetDataStrings.TEXTURE_BLOCK_ATLAS); - cubeMesh.setMaterial(mat); - cubeMesh.setShader(VisualShader.loadSpecificShader(AssetDataStrings.SHADER_BLOCK_SINGLE_VERT, AssetDataStrings.SHADER_BLOCK_SINGLE_FRAG)); - openGLState.glBindVertexArray(0); - cubeMesh.setParent(model); - model.getMeshes().add(cubeMesh); - - return model; + public static ActorTextureMask generateVolumetricTextureMask(String meshName){ + List textureList = new LinkedList(); + textureList.add(Globals.renderingEngine.getVolumeFrontfaceTexture()); + textureList.add(Globals.renderingEngine.getVolumeBackfaceTexture()); + List uniformList = new LinkedList(); + uniformList.add("volumeDepthFrontface"); + uniformList.add("volumeDepthBackface"); + return new ActorTextureMask(meshName,textureList,uniformList); } /** @@ -643,1066 +43,5 @@ public class RenderUtils { return model; } - - @Deprecated - public static Model createBitmapDisplay(){ - - Model rVal = new Model(); - Mesh m = new Mesh(AssetDataStrings.ASSET_STRING_BITMAP_FONT_MESH_NAME); - OpenGLState openGLState = Globals.renderingEngine.getOpenGLState(); - m.generateVAO(openGLState); - //vertices - FloatBuffer vertexArrayBufferData = BufferUtils.createFloatBuffer(12); - vertexArrayBufferData.put( 0); - vertexArrayBufferData.put( 1); - - vertexArrayBufferData.put( 0); - vertexArrayBufferData.put( 0); - - vertexArrayBufferData.put( 1); - vertexArrayBufferData.put( 0); - - vertexArrayBufferData.put( 0); - vertexArrayBufferData.put( 1); - - vertexArrayBufferData.put( 1); - vertexArrayBufferData.put( 0); - - vertexArrayBufferData.put( 1); - vertexArrayBufferData.put( 1); - vertexArrayBufferData.flip(); - - - IntBuffer faceArrayBufferData = BufferUtils.createIntBuffer(6); - faceArrayBufferData.put(0); - faceArrayBufferData.put(1); - faceArrayBufferData.put(2); - - faceArrayBufferData.put(3); - faceArrayBufferData.put(4); - faceArrayBufferData.put(5); - faceArrayBufferData.flip(); - - - - //texture coords - FloatBuffer textureArrayBufferData = BufferUtils.createFloatBuffer(12); - textureArrayBufferData.put(0); - textureArrayBufferData.put(1); - - textureArrayBufferData.put(0); - textureArrayBufferData.put(0); - - textureArrayBufferData.put(1); - textureArrayBufferData.put(0); - - textureArrayBufferData.put(0); - textureArrayBufferData.put(1); - - textureArrayBufferData.put(1); - textureArrayBufferData.put(0); - - textureArrayBufferData.put(1); - textureArrayBufferData.put(1); - textureArrayBufferData.flip(); - - - //buffer vertices - m.bufferVertices(vertexArrayBufferData, 2); - //buffer normals - m.bufferNormals(vertexArrayBufferData, 2); - //buffer faces - m.bufferFaces(faceArrayBufferData, 2); - //buffer texture coords - m.bufferTextureCoords(textureArrayBufferData, 2); - - - m.setShader(VisualShader.loadSpecificShader("/Shaders/ui/font/basicbitmap/basicbitmap.vs", "/Shaders/ui/font/basicbitmap/basicbitmap.fs")); - - - openGLState.glBindVertexArray(0); - m.setParent(rVal); - - Material uiMat = Material.create("/Textures/Fonts/myfont1-harsher.png"); - m.setMaterial(uiMat); - rVal.getMaterials().add(uiMat); - - rVal.getMeshes().add(m); - - return rVal; - } - - - - - - /** - * Creates a model to use to show bitmap characters - * @return The model - */ - public static Model createBitmapCharacter(){ - - Model rVal = new Model(); - Mesh m = new Mesh(AssetDataStrings.ASSET_STRING_BITMAP_FONT_MESH_NAME); - OpenGLState openGLState = Globals.renderingEngine.getOpenGLState(); - m.generateVAO(openGLState); - //vertices - FloatBuffer vertexArrayBufferData = BufferUtils.createFloatBuffer(12); - vertexArrayBufferData.put(-1); - vertexArrayBufferData.put( 1); - - vertexArrayBufferData.put(-1); - vertexArrayBufferData.put(-1); - - vertexArrayBufferData.put( 1); - vertexArrayBufferData.put(-1); - - vertexArrayBufferData.put(-1); - vertexArrayBufferData.put( 1); - - vertexArrayBufferData.put( 1); - vertexArrayBufferData.put(-1); - - vertexArrayBufferData.put( 1); - vertexArrayBufferData.put( 1); - vertexArrayBufferData.flip(); - - - IntBuffer faceArrayBufferData = BufferUtils.createIntBuffer(6); - faceArrayBufferData.put(0); - faceArrayBufferData.put(1); - faceArrayBufferData.put(2); - - faceArrayBufferData.put(3); - faceArrayBufferData.put(4); - faceArrayBufferData.put(5); - faceArrayBufferData.flip(); - - - - //texture coords - FloatBuffer textureArrayBufferData = BufferUtils.createFloatBuffer(12); - textureArrayBufferData.put(0); - textureArrayBufferData.put(1); - - textureArrayBufferData.put(0); - textureArrayBufferData.put(0); - - textureArrayBufferData.put(1); - textureArrayBufferData.put(0); - - textureArrayBufferData.put(0); - textureArrayBufferData.put(1); - - textureArrayBufferData.put(1); - textureArrayBufferData.put(0); - - textureArrayBufferData.put(1); - textureArrayBufferData.put(1); - textureArrayBufferData.flip(); - - - //buffer vertices - m.bufferVertices(vertexArrayBufferData, 2); - //buffer normals - m.bufferNormals(vertexArrayBufferData, 2); - //buffer faces - m.bufferFaces(faceArrayBufferData, 6); - //buffer texture coords - m.bufferTextureCoords(textureArrayBufferData, 2); - - - m.setShader(VisualShader.loadSpecificShader("/Shaders/ui/font/bitmapchar/bitmapchar.vs", "/Shaders/ui/font/bitmapchar/bitmapchar.fs")); - - - openGLState.glBindVertexArray(0); - m.setParent(rVal); - - rVal.getMeshes().add(m); - - return rVal; - } - - - - public static Model createInWindowPanel(String vertexShader, String fragmentShader){ - - Model rVal = new Model(); - Mesh m = new Mesh("plane"); - OpenGLState openGLState = Globals.renderingEngine.getOpenGLState(); - m.generateVAO(openGLState); - //vertices - FloatBuffer vertexArrayBufferData = BufferUtils.createFloatBuffer(12); - vertexArrayBufferData.put(-1); - vertexArrayBufferData.put( 1); - - vertexArrayBufferData.put(-1); - vertexArrayBufferData.put(-1); - - vertexArrayBufferData.put( 1); - vertexArrayBufferData.put(-1); - - vertexArrayBufferData.put(-1); - vertexArrayBufferData.put( 1); - - vertexArrayBufferData.put( 1); - vertexArrayBufferData.put(-1); - - vertexArrayBufferData.put( 1); - vertexArrayBufferData.put( 1); - vertexArrayBufferData.flip(); - - - IntBuffer faceArrayBufferData = BufferUtils.createIntBuffer(6); - faceArrayBufferData.put(0); - faceArrayBufferData.put(1); - faceArrayBufferData.put(2); - - faceArrayBufferData.put(3); - faceArrayBufferData.put(4); - faceArrayBufferData.put(5); - faceArrayBufferData.flip(); - - - - //texture coords - FloatBuffer textureArrayBufferData = BufferUtils.createFloatBuffer(12); - textureArrayBufferData.put(0); - textureArrayBufferData.put(1); - - textureArrayBufferData.put(0); - textureArrayBufferData.put(0); - - textureArrayBufferData.put(1); - textureArrayBufferData.put(0); - - textureArrayBufferData.put(0); - textureArrayBufferData.put(1); - - textureArrayBufferData.put(1); - textureArrayBufferData.put(0); - - textureArrayBufferData.put(1); - textureArrayBufferData.put(1); - textureArrayBufferData.flip(); - - - //buffer vertices - m.bufferVertices(vertexArrayBufferData, 2); - //buffer normals - m.bufferNormals(vertexArrayBufferData, 2); - //buffer faces - m.bufferFaces(faceArrayBufferData, 2); - //buffer texture coords - m.bufferTextureCoords(textureArrayBufferData, 2); - - - m.setShader(VisualShader.loadSpecificShader(vertexShader, fragmentShader)); - - - openGLState.glBindVertexArray(0); - m.setParent(rVal); - - rVal.getMeshes().add(m); - - return rVal; - } - - - - - public static Model createTerrainModelPrecomputedShader(OpenGLState openGLState, float[][] heightfield, float[][] texturemap, VisualShader program, int stride){ - Model rVal = new Model(); - Mesh m = new Mesh("terrain"); - int width = heightfield.length; - int height = heightfield[0].length; - - int actualWidth = (int)Math.ceil(1.0f * width / (1.0f * stride)); - int actualHeight = (int)Math.ceil(1.0f * height / (1.0f * stride)); - - -// System.out.println(actualWidth + " " + actualHeight); - -// System.out.println((actualWidth - 1) * (actualHeight - 1)); - - FloatBuffer vertices; - FloatBuffer normals; - IntBuffer faces; - FloatBuffer texture_coords; - FloatBuffer textureIndices; - if(stride * actualWidth > width){ - int drawWidth = actualWidth + 1; - int drawHeight = actualHeight + 1; - vertices = BufferUtils.createFloatBuffer(drawWidth * drawHeight * 12); - normals = BufferUtils.createFloatBuffer(drawWidth * drawHeight * 12); - faces = BufferUtils.createIntBuffer((drawWidth - 1) * (drawHeight - 1) * 2 * 3); - texture_coords = BufferUtils.createFloatBuffer(drawWidth * drawHeight * 8); - textureIndices = BufferUtils.createFloatBuffer(drawWidth * drawHeight * 16); - } else { - vertices = BufferUtils.createFloatBuffer(actualWidth * actualHeight * 12); - normals = BufferUtils.createFloatBuffer(actualWidth * actualHeight * 12); - faces = BufferUtils.createIntBuffer((actualWidth - 1) * (actualHeight - 1) * 2 * 3); - texture_coords = BufferUtils.createFloatBuffer(actualWidth * actualHeight * 8); - textureIndices = BufferUtils.createFloatBuffer(actualWidth * actualHeight * 16); - } - - int incrementer = 0; - // int numFaces = (actualWidth - 1) * (actualHeight - 1) * 2 * 3; - for(int x = 0; x < width - 1; x = x + stride){ - for(int y = 0; y < height - 1; y = y + stride){ - //deal with vertex - //0,0 - vertices.put(x); - vertices.put(heightfield[x][y]); - vertices.put(y); - //1,0 - vertices.put(x + stride); - vertices.put(heightfield[x+stride][y]); - vertices.put(y); - //0,1 - vertices.put(x); - vertices.put(heightfield[x][y+stride]); - vertices.put(y + stride); - //1,1 - vertices.put(x + stride); - vertices.put(heightfield[x+stride][y+stride]); - vertices.put(y + stride); - //deal with normal - Vector3f normal = calculateTerrainNormal(heightfield, actualWidth, actualHeight, stride, x, y); - normals.put(normal.x); - normals.put(normal.y); - normals.put(normal.z); - normal = calculateTerrainNormal(heightfield, actualWidth, actualHeight, stride, x + stride, y); - normals.put(normal.x); - normals.put(normal.y); - normals.put(normal.z); - normal = calculateTerrainNormal(heightfield, actualWidth, actualHeight, stride, x, y + stride); - normals.put(normal.x); - normals.put(normal.y); - normals.put(normal.z); - normal = calculateTerrainNormal(heightfield, actualWidth, actualHeight, stride, x + stride, y + stride); - normals.put(normal.x); - normals.put(normal.y); - normals.put(normal.z); - //deal with texture coordinates -// if(x / stride % 2 == 0){ -// if(y / stride % 2 == 0){ -// texture_coords.put(0); -// texture_coords.put(0); -// texture_coords.put(1); -// texture_coords.put(0); -// texture_coords.put(0); -// texture_coords.put(1); -// texture_coords.put(1); -// texture_coords.put(1); -// } else { -// texture_coords.put(0); -// texture_coords.put(1); -// } -// } else { -// if(y / stride % 2 == 0){ -// texture_coords.put(1); -// texture_coords.put(0); -// } else { -// texture_coords.put(1); -// texture_coords.put(1); -// } -// } - texture_coords.put(0); - texture_coords.put(0); - texture_coords.put(1); - texture_coords.put(0); - texture_coords.put(0); - texture_coords.put(1); - texture_coords.put(1); - texture_coords.put(1); - - if(x + stride < width - 1 && y + stride < height - 1){ -// texturemap[x+stride][y+stride]; - for(int i = 0; i < 4 ; i++){ -// textureIndices.put(1); -// textureIndices.put(0); -// textureIndices.put(0); -// textureIndices.put(0); - textureIndices.put(texturemap[x][y]); - textureIndices.put(texturemap[x+stride][y]); - textureIndices.put(texturemap[x][y+stride]); - textureIndices.put(texturemap[x+stride][y+stride]); - } - } else { - for(int i = 0; i < 4 ; i++){ - textureIndices.put(0); - textureIndices.put(0); - textureIndices.put(0); - textureIndices.put(0); - } - } - - - //deal with faces - if(1.0f * x / stride < actualWidth - 1 && 1.0f * y / stride < actualHeight - 1){ - faces.put(incrementer * 4 + 0); - faces.put(incrementer * 4 + 1); - faces.put(incrementer * 4 + 2); - faces.put(incrementer * 4 + 1); - faces.put(incrementer * 4 + 2); - faces.put(incrementer * 4 + 3); - } - incrementer++; - } - } - - vertices.flip(); - normals.flip(); - faces.flip(); - texture_coords.flip(); - textureIndices.flip(); - - m.generateVAO(openGLState); - //buffer vertices - m.bufferVertices(vertices, 3); - //buffer normals - m.bufferNormals(normals, 3); - //buffer faces - m.bufferFaces(faces,incrementer*2); - //buffer texture coords - m.bufferTextureCoords(texture_coords, 2); - //texture indices - m.bufferCustomFloatAttribArray(textureIndices, 4, 5); - m.setShader(program); - openGLState.glBindVertexArray(0); - m.setParent(rVal); - - Material groundMat = Material.create("/Textures/Ground/Dirt1.png"); - m.setMaterial(groundMat); - - rVal.getMeshes().add(m); - return rVal; - } - - - static float MINIMIZATION_DIFF_MAX = 0.001f; - - public static Model createMinimizedTerrainModelPrecomputedShader(float[][] heightfield, float[][] texturemap, VisualShader program, int stride){ - - class QuadToGenerate { - //coords are inclusive - int startX; - int endX; - int startY; - int endY; - float min; - float max; - float texture; - boolean homogeneousTexture; - - QuadToGenerate(int startX, int startY, int endX, int endY, float diff, float min, float max, boolean homogeneousTexture, float texture){ - this.startX = startX; - this.startY = startY; - this.endX = endX; - this.endY = endY; - this.min = min; - this.max = max; - this.texture = texture; - this.homogeneousTexture = homogeneousTexture; - } - - } - - - Model rVal = new Model(); - Mesh m = new Mesh("terrain"); - OpenGLState openGLState = Globals.renderingEngine.getOpenGLState(); - int width = heightfield.length; - int height = heightfield[0].length; - - int actualWidth = (int)Math.ceil(1.0f * width / (1.0f * stride)); - int actualHeight = (int)Math.ceil(1.0f * height / (1.0f * stride)); - - -// System.out.println(actualWidth + " " + actualHeight); - -// System.out.println((actualWidth - 1) * (actualHeight - 1)); - - FloatBuffer vertices; - FloatBuffer normals; - IntBuffer faces; - FloatBuffer texture_coords; - FloatBuffer textureIndices; - if(stride * actualWidth > width){ - int drawWidth = actualWidth + 1; - int drawHeight = actualHeight + 1; - vertices = BufferUtils.createFloatBuffer(drawWidth * drawHeight * 12); - normals = BufferUtils.createFloatBuffer(drawWidth * drawHeight * 12); - faces = BufferUtils.createIntBuffer((drawWidth - 1) * (drawHeight - 1) * 2 * 3); - texture_coords = BufferUtils.createFloatBuffer(drawWidth * drawHeight * 8); - textureIndices = BufferUtils.createFloatBuffer(drawWidth * drawHeight * 16); - } else { - vertices = BufferUtils.createFloatBuffer(actualWidth * actualHeight * 12); - normals = BufferUtils.createFloatBuffer(actualWidth * actualHeight * 12); - faces = BufferUtils.createIntBuffer((actualWidth - 1) * (actualHeight - 1) * 2 * 3); - texture_coords = BufferUtils.createFloatBuffer(actualWidth * actualHeight * 8); - textureIndices = BufferUtils.createFloatBuffer(actualWidth * actualHeight * 16); - } - - - //merge along y - - List firstPhaseQuads = new LinkedList(); - QuadToGenerate quadCurrent = null; - float minVal = 0; - float maxVal = 0; - for(int x = 0; x < width - 1; x = x + stride){ - quadCurrent = null; - for(int y = 0; y < height - 1; y = y + stride){ - if((x == 5 && y == 2)){ - // System.out.println(quadCurrent); -// continue; - } - if(quadCurrent == null){ - minVal = 100000000; - maxVal = 0; - //minval - if(heightfield[x][y] < minVal){ - minVal = heightfield[x][y]; - } - if(heightfield[x+stride][y] < minVal){ - minVal = heightfield[x+stride][y]; - } - if(heightfield[x][y+stride] < minVal){ - minVal = heightfield[x][y+stride]; - } - if(heightfield[x+stride][y+stride] < minVal){ - minVal = heightfield[x+stride][y+stride]; - } - //maxval - if(heightfield[x][y] > maxVal){ - maxVal = heightfield[x][y]; - } - if(heightfield[x+stride][y] > maxVal){ - maxVal = heightfield[x+stride][y]; - } - if(heightfield[x][y+stride] > maxVal){ - maxVal = heightfield[x][y+stride]; - } - if(heightfield[x+stride][y+stride] > maxVal){ - maxVal = heightfield[x+stride][y+stride]; - } - boolean textureMatch = false; - float texture = -1; - if(x+stride < width - 1 && y+stride < height - 1 && - texturemap[x][y] == texturemap[x+stride][y] && - texturemap[x][y] == texturemap[x][y+stride] && - texturemap[x][y] == texturemap[x+stride][y+stride]){ - - textureMatch = true; - texture = texturemap[x][y]; - } else { -// if(x > 8 && (x+stride < width - 1) && (y+stride < height -1)){ -// System.out.println( -// (x+stride < width - 1) + " " + -// (y+stride < height -1) + " " + -// (texturemap[x][y] == texturemap[x+stride][y]) + " " + -// (texturemap[x][y] == texturemap[x][y+stride]) + " " + -// (texturemap[x][y] == texturemap[x+stride][y+stride]) -// ); -// } - } - if(textureMatch){ - quadCurrent = new QuadToGenerate(x,y,x+stride,y+stride,maxVal - minVal,minVal,maxVal,textureMatch,texture); - } else { - firstPhaseQuads.add(new QuadToGenerate(x,y,x+stride,y+stride,maxVal - minVal,minVal,maxVal,textureMatch,texture)); - // quadCurrent = null; - } - } else { - float newMin = minVal; - float newMax = maxVal; - //min - if(heightfield[x][y+stride] < newMin){ - newMin = heightfield[x][y+stride]; - } - if(heightfield[x+stride][y+stride] < newMin){ - newMin = heightfield[x+stride][y+stride]; - } - //max - if(heightfield[x][y+stride] > newMax){ - newMax = heightfield[x][y+stride]; - } - if(heightfield[x+stride][y+stride] > newMax){ - newMax = heightfield[x+stride][y+stride]; - } - if(y+stride < height - 1 && x+stride < width - 1){ - if(newMax - newMin < MINIMIZATION_DIFF_MAX && - quadCurrent.texture == texturemap[x+stride][y] && - quadCurrent.texture == texturemap[x ][y+stride] && - quadCurrent.texture == texturemap[x+stride][y+stride] && - quadCurrent.homogeneousTexture - ){ - //add to quad - quadCurrent.endY = y + stride; - quadCurrent.min = newMax; - quadCurrent.max = newMax; - } else { - //push quad - firstPhaseQuads.add(quadCurrent); - firstPhaseQuads.add(new QuadToGenerate(x,y,x+stride,y+stride,maxVal - minVal,minVal,maxVal,false,0)); - quadCurrent = null; -// System.out.println("Push"); - } - } else { - if(newMax - newMin < MINIMIZATION_DIFF_MAX){ - //add to quad - quadCurrent.endY = y + stride; - quadCurrent.min = newMax; - quadCurrent.max = newMax; - } else { - //push quad that we were building - firstPhaseQuads.add(quadCurrent); - // quadCurrent = null; - //create new quad from what we were just analyzing - boolean textureMatch = false; - float texture = -1; - quadCurrent = new QuadToGenerate(x,y,x+stride,y+stride,maxVal - minVal,minVal,maxVal,textureMatch,texture); -// System.out.println("Push"); - } - } - } - } - if(quadCurrent != null){ - firstPhaseQuads.add(quadCurrent); - } - } - - List finalQuads = new LinkedList(); - // for(QuadToGenerate current : firstPhaseQuads){ - // finalQuads.add(current); - // } - -// System.out.println(finalQuads.size()); - - //merge along x - - // QuadToGenerate currentQuad = null; - List toSkip = new LinkedList(); - for(QuadToGenerate currentQuad : firstPhaseQuads){ - // toRemove.clear(); - if(toSkip.contains(currentQuad)){ - continue; - } - for(QuadToGenerate currentPotentialMatch : firstPhaseQuads){ - if(currentPotentialMatch.startX <= currentQuad.startX){ - continue; - } - if(currentPotentialMatch.startX > currentQuad.endX){ - break; - } - if(currentPotentialMatch.startY != currentQuad.startY){ - continue; - } - if(currentPotentialMatch.endY != currentQuad.endY){ - continue; - } - if( - !(currentQuad.homogeneousTexture && - currentPotentialMatch.homogeneousTexture && - currentQuad.texture == currentPotentialMatch.texture) - ){ - continue; - } - if(currentQuad.min < currentPotentialMatch.min && currentQuad.max < currentPotentialMatch.max){ - float min = currentQuad.min; - float max = currentPotentialMatch.max; - if(max - min < MINIMIZATION_DIFF_MAX){ - currentQuad.endX = currentPotentialMatch.endX; - currentQuad.max = currentPotentialMatch.max; - toSkip.add(currentPotentialMatch); - } - } else if(currentQuad.min > currentPotentialMatch.min && currentQuad.max > currentPotentialMatch.max){ - float min = currentPotentialMatch.min; - float max = currentQuad.max; - if(max - min < MINIMIZATION_DIFF_MAX){ - currentQuad.endX = currentPotentialMatch.endX; - currentQuad.min = currentPotentialMatch.min; - toSkip.add(currentPotentialMatch); - } - } else { - if(currentQuad.min < currentPotentialMatch.min){ - currentQuad.endX = currentPotentialMatch.endX; - } else { - currentQuad.endX = currentPotentialMatch.endX; - currentQuad.min = currentPotentialMatch.min; - currentQuad.max = currentPotentialMatch.max; - } - toSkip.add(currentPotentialMatch); - } - } - finalQuads.add(currentQuad); - } - // for(QuadToGenerate currentIteration : firstPhaseQuads){ - // if(currentQuad == null){ - // currentQuad = currentIteration; - // } else { - // //if should merge: - // if( - // currentQuad.homogeneousTexture && - // currentIteration.homogeneousTexture && - // currentQuad.texture == currentIteration.texture - // ){ - // if(currentQuad.min < currentIteration.min && currentQuad.max < currentIteration.max){ - // float min = currentQuad.min; - // float max = currentIteration.max; - // if(max - min < MINIMIZATION_DIFF_MAX){ - // currentQuad.endX = currentIteration.endX; - // currentQuad.max = currentIteration.max; - // } else { - // finalQuads.add(currentQuad); - // currentQuad = currentIteration; - // } - // } else if(currentQuad.min > currentIteration.min && currentQuad.max > currentIteration.max){ - // float min = currentIteration.min; - // float max = currentQuad.max; - // if(max - min < MINIMIZATION_DIFF_MAX){ - // currentQuad.endX = currentIteration.endX; - // currentQuad.min = currentIteration.min; - // } else { - // finalQuads.add(currentQuad); - // currentQuad = currentIteration; - // } - // } else { - // if(currentQuad.min < currentIteration.min){ - // currentQuad.endX = currentIteration.endX; - // } else { - // currentQuad.endX = currentIteration.endX; - // currentQuad.min = currentIteration.min; - // currentQuad.max = currentIteration.max; - // } - // } - // } else { - // finalQuads.add(currentQuad); - // currentQuad = currentIteration; - // } - // } - // } - // finalQuads.add(currentQuad); - - // for(QuadToGenerate current : finalQuads){ - // if(current.startX > 0 && current.startY > 0 && current.endX < 99 && current.endY < 99){ - // System.out.println(current.startX + " " + current.startY + " " + current.endX + " " + current.endY); - // } - // } - - // System.out.println("AAAAAAAAAAAAAAAAAA"); -// System.out.println(finalQuads.size()); - - int incrementer = 0; - - for(QuadToGenerate current : finalQuads){ - //deal with vertex - //0,0 - vertices.put(current.startX); - vertices.put(heightfield[current.startX][current.startY]); - vertices.put(current.startY); - //1,0 - vertices.put(current.endX); - vertices.put(heightfield[current.endX][current.startY]); - vertices.put(current.startY); - //0,1 - vertices.put(current.startX); - vertices.put(heightfield[current.startX][current.endY]); - vertices.put(current.endY); - //1,1 - vertices.put(current.endX); - vertices.put(heightfield[current.endX][current.endY]); - vertices.put(current.endY); - //deal with normal - Vector3f normal = calculateTerrainNormal(heightfield, actualWidth, actualHeight, stride, current.startX, current.startY); - normals.put(normal.x); - normals.put(normal.y); - normals.put(normal.z); - normal = calculateTerrainNormal(heightfield, actualWidth, actualHeight, stride, current.endX, current.startY); - normals.put(normal.x); - normals.put(normal.y); - normals.put(normal.z); - normal = calculateTerrainNormal(heightfield, actualWidth, actualHeight, stride, current.startX, current.endY); - normals.put(normal.x); - normals.put(normal.y); - normals.put(normal.z); - normal = calculateTerrainNormal(heightfield, actualWidth, actualHeight, stride, current.endX, current.endY); - normals.put(normal.x); - normals.put(normal.y); - normals.put(normal.z); - //deal with texture coordinates -// if(x / stride % 2 == 0){ -// if(y / stride % 2 == 0){ -// texture_coords.put(0); -// texture_coords.put(0); -// texture_coords.put(1); -// texture_coords.put(0); -// texture_coords.put(0); -// texture_coords.put(1); -// texture_coords.put(1); -// texture_coords.put(1); -// } else { -// texture_coords.put(0); -// texture_coords.put(1); -// } -// } else { -// if(y / stride % 2 == 0){ -// texture_coords.put(1); -// texture_coords.put(0); -// } else { -// texture_coords.put(1); -// texture_coords.put(1); -// } -// } - texture_coords.put(0); - texture_coords.put(0); - texture_coords.put(current.endX - current.startX); - texture_coords.put(0); - texture_coords.put(0); - texture_coords.put(current.endY - current.startY); - texture_coords.put(current.endX - current.startX); - texture_coords.put(current.endY - current.startY); - - if(current.endX < width - 1 && current.endY < height - 1){ -// texturemap[x+stride][y+stride]; - for(int i = 0; i < 4 ; i++){ -// textureIndices.put(1); -// textureIndices.put(0); -// textureIndices.put(0); -// textureIndices.put(0); - textureIndices.put(texturemap[current.startX][current.startY]); - textureIndices.put(texturemap[current.endX][current.startY]); - textureIndices.put(texturemap[current.startX][current.endY]); - textureIndices.put(texturemap[current.endX][current.endY]); - } - } else { - for(int i = 0; i < 4 ; i++){ - textureIndices.put(0); - textureIndices.put(0); - textureIndices.put(0); - textureIndices.put(0); - } - } - - - //deal with faces - faces.put(incrementer * 4 + 0); - faces.put(incrementer * 4 + 1); - faces.put(incrementer * 4 + 2); - faces.put(incrementer * 4 + 1); - faces.put(incrementer * 4 + 2); - faces.put(incrementer * 4 + 3); - - incrementer++; - } - - - -// int numFaces = (actualWidth - 1) * (actualHeight - 1) * 2 * 3; -// for(int x = 0; x < width - 1; x = x + stride){ -// for(int y = 0; y < height - 1; y = y + stride){ -// //deal with vertex -// //0,0 -// vertices.put(x); -// vertices.put(heightfield[x][y]); -// vertices.put(y); -// //1,0 -// vertices.put(x + stride); -// vertices.put(heightfield[x+stride][y]); -// vertices.put(y); -// //0,1 -// vertices.put(x); -// vertices.put(heightfield[x][y+stride]); -// vertices.put(y + stride); -// //1,1 -// vertices.put(x + stride); -// vertices.put(heightfield[x+stride][y+stride]); -// vertices.put(y + stride); -// //deal with normal -// Vector3f normal = calculateTerrainNormal(heightfield, actualWidth, actualHeight, stride, x, y); -// normals.put(normal.x); -// normals.put(normal.y); -// normals.put(normal.z); -// normal = calculateTerrainNormal(heightfield, actualWidth, actualHeight, stride, x + stride, y); -// normals.put(normal.x); -// normals.put(normal.y); -// normals.put(normal.z); -// normal = calculateTerrainNormal(heightfield, actualWidth, actualHeight, stride, x, y + stride); -// normals.put(normal.x); -// normals.put(normal.y); -// normals.put(normal.z); -// normal = calculateTerrainNormal(heightfield, actualWidth, actualHeight, stride, x + stride, y + stride); -// normals.put(normal.x); -// normals.put(normal.y); -// normals.put(normal.z); -// //deal with texture coordinates -//// if(x / stride % 2 == 0){ -//// if(y / stride % 2 == 0){ -//// texture_coords.put(0); -//// texture_coords.put(0); -//// texture_coords.put(1); -//// texture_coords.put(0); -//// texture_coords.put(0); -//// texture_coords.put(1); -//// texture_coords.put(1); -//// texture_coords.put(1); -//// } else { -//// texture_coords.put(0); -//// texture_coords.put(1); -//// } -//// } else { -//// if(y / stride % 2 == 0){ -//// texture_coords.put(1); -//// texture_coords.put(0); -//// } else { -//// texture_coords.put(1); -//// texture_coords.put(1); -//// } -//// } -// texture_coords.put(0); -// texture_coords.put(0); -// texture_coords.put(1); -// texture_coords.put(0); -// texture_coords.put(0); -// texture_coords.put(1); -// texture_coords.put(1); -// texture_coords.put(1); -// -// if(x + stride < width - 1 && y + stride < height - 1){ -//// texturemap[x+stride][y+stride]; -// for(int i = 0; i < 4 ; i++){ -//// textureIndices.put(1); -//// textureIndices.put(0); -//// textureIndices.put(0); -//// textureIndices.put(0); -// textureIndices.put(texturemap[x][y]); -// textureIndices.put(texturemap[x+stride][y]); -// textureIndices.put(texturemap[x][y+stride]); -// textureIndices.put(texturemap[x+stride][y+stride]); -// } -// } else { -// for(int i = 0; i < 4 ; i++){ -// textureIndices.put(0); -// textureIndices.put(0); -// textureIndices.put(0); -// textureIndices.put(0); -// } -// } -// -// -// //deal with faces -// if(1.0f * x / stride < actualWidth - 1 && 1.0f * y / stride < actualHeight - 1){ -// faces.put(incrementer * 4 + 0); -// faces.put(incrementer * 4 + 1); -// faces.put(incrementer * 4 + 2); -// faces.put(incrementer * 4 + 1); -// faces.put(incrementer * 4 + 2); -// faces.put(incrementer * 4 + 3); -// } -// incrementer++; -// } -// } - - // System.out.println(incrementer + " quads"); - - vertices.flip(); - normals.flip(); - faces.flip(); - texture_coords.flip(); - textureIndices.flip(); - - m.generateVAO(openGLState); - //buffer vertices - m.bufferVertices(vertices, 3); - //buffer normals - m.bufferNormals(normals, 3); - //buffer faces - m.bufferFaces(faces,incrementer*2); - //buffer texture coords - m.bufferTextureCoords(texture_coords, 2); - //texture indices - m.bufferCustomFloatAttribArray(textureIndices, 4, 5); - m.setShader(program); - openGLState.glBindVertexArray(0); - m.setParent(rVal); - - Material groundMat = Material.create("/Textures/Ground/Dirt1.png"); - m.setMaterial(groundMat); - - rVal.getMeshes().add(m); - return rVal; - } - - static Vector3f calculateTerrainNormal(float[][] heightfield, int actualWidth, int actualHeight, int stride, int x, int y){ - Vector3f rVal = new Vector3f(); - if(x / stride < actualWidth - 1){ - if(y / stride < actualHeight - 1){ - float hL; - if(x > 0){ - hL = heightfield[x-1][y]; - } else { - hL = heightfield[x][y]; - } - float hR = heightfield[x+1][y]; - float hD = heightfield[x][y+1]; - float hU; - if(y > 0){ - hU = heightfield[x][y-1]; - } else { - hU = heightfield[x][y]; - } - rVal = new Vector3f(hL - hR, 2.0f, hD - hU); - rVal.normalize(); - } else { - float hL; - if(x > 0){ - hL = heightfield[x-1][y]; - } else { - hL = heightfield[x][y]; - } - float hR = heightfield[x+1][y]; - float hD = heightfield[x][y]; - float hU = heightfield[x][y-1]; - rVal = new Vector3f(hL - hR, 2.0f, hD - hU); - rVal.normalize(); - } - } else { - if(y / stride < actualHeight - 1){ - float hL = heightfield[x-1][y]; - float hR = heightfield[x][y]; - float hD = heightfield[x][y+1]; - float hU; - if(y > 0){ - hU = heightfield[x][y-1]; - } else { - hU = heightfield[x][y]; - } - rVal = new Vector3f(hL - hR, 2.0f, hD - hU); - rVal.normalize(); - } else { - float hL = heightfield[x-1][y]; - float hR = heightfield[x][y]; - float hD = heightfield[x][y]; - float hU = heightfield[x][y-1]; - rVal = new Vector3f(hL - hR, 2.0f, hD - hU); - rVal.normalize(); - } - } - return rVal; - } - - public static ActorTextureMask generateVolumetricTextureMask(String meshName){ - List textureList = new LinkedList(); - textureList.add(Globals.renderingEngine.getVolumeFrontfaceTexture()); - textureList.add(Globals.renderingEngine.getVolumeBackfaceTexture()); - List uniformList = new LinkedList(); - uniformList.add("volumeDepthFrontface"); - uniformList.add("volumeDepthBackface"); - return new ActorTextureMask(meshName,textureList,uniformList); - } - - - } diff --git a/src/main/java/electrosphere/renderer/RenderingEngine.java b/src/main/java/electrosphere/renderer/RenderingEngine.java index 4da9d764..4a864f0f 100644 --- a/src/main/java/electrosphere/renderer/RenderingEngine.java +++ b/src/main/java/electrosphere/renderer/RenderingEngine.java @@ -1,6 +1,5 @@ package electrosphere.renderer; -import static electrosphere.renderer.RenderUtils.createScreenTextureVAO; 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.GL30.GL_FRAMEBUFFER; @@ -38,6 +37,7 @@ import electrosphere.renderer.framebuffer.FramebufferUtils; import electrosphere.renderer.framebuffer.Renderbuffer; import electrosphere.renderer.hw.HardwareData; import electrosphere.renderer.light.LightManager; +import electrosphere.renderer.meshgen.EngineMeshgen; import electrosphere.renderer.model.Material; import electrosphere.renderer.pipelines.CompositePipeline; import electrosphere.renderer.pipelines.FirstPersonItemsPipeline; @@ -373,7 +373,7 @@ public class RenderingEngine { //init screen rendering quadrant - screenTextureVAO = createScreenTextureVAO(this.openGLState); + screenTextureVAO = EngineMeshgen.createScreenTextureVAO(this.openGLState); screenTextureShaders = VisualShader.loadSpecificShader("/Shaders/core/screentexture/simple1/simple1.vs", "/Shaders/core/screentexture/simple1/simple1.fs"); //default framebuffer diff --git a/src/main/java/electrosphere/renderer/meshgen/EngineMeshgen.java b/src/main/java/electrosphere/renderer/meshgen/EngineMeshgen.java new file mode 100644 index 00000000..02b26eae --- /dev/null +++ b/src/main/java/electrosphere/renderer/meshgen/EngineMeshgen.java @@ -0,0 +1,463 @@ +package electrosphere.renderer.meshgen; + +import java.nio.FloatBuffer; +import java.nio.IntBuffer; + +import org.lwjgl.BufferUtils; +import org.lwjgl.opengl.GL45; + +import electrosphere.engine.Globals; +import electrosphere.engine.assetmanager.AssetDataStrings; +import electrosphere.renderer.OpenGLState; +import electrosphere.renderer.model.Material; +import electrosphere.renderer.model.Mesh; +import electrosphere.renderer.model.Model; +import electrosphere.renderer.shader.VisualShader; + +/** + * Generates core engine models + */ +public class EngineMeshgen { + + public static int createScreenTextureVAO(OpenGLState openGLState){ + int rVal = GL45.glGenVertexArrays(); + openGLState.glBindVertexArray(rVal); + //vertices + FloatBuffer vertexArrayBufferData = BufferUtils.createFloatBuffer(12); + vertexArrayBufferData.put(-1.0f); + vertexArrayBufferData.put( 1.0f); + + vertexArrayBufferData.put(-1.0f); + vertexArrayBufferData.put(-1.0f); + + vertexArrayBufferData.put( 1.0f); + vertexArrayBufferData.put(-1.0f); + + vertexArrayBufferData.put(-1.0f); + vertexArrayBufferData.put( 1.0f); + + vertexArrayBufferData.put( 1.0f); + vertexArrayBufferData.put(-1.0f); + + vertexArrayBufferData.put( 1.0f); + vertexArrayBufferData.put( 1.0f); + vertexArrayBufferData.flip(); + int vertexBuffer = GL45.glGenBuffers(); + GL45.glBindBuffer(GL45.GL_ARRAY_BUFFER, vertexBuffer); + GL45.glBufferData(GL45.GL_ARRAY_BUFFER, vertexArrayBufferData, GL45.GL_STATIC_DRAW); + GL45.glVertexAttribPointer(0, 2, GL45.GL_FLOAT, false, 0, 0); + GL45.glEnableVertexAttribArray(0); + + + + + + //texture coords + FloatBuffer textureArrayBufferData = BufferUtils.createFloatBuffer(12); + textureArrayBufferData.put(0.0f); + textureArrayBufferData.put(1.0f); + + textureArrayBufferData.put(0.0f); + textureArrayBufferData.put(0.0f); + + textureArrayBufferData.put(1.0f); + textureArrayBufferData.put(0.0f); + + textureArrayBufferData.put(0.0f); + textureArrayBufferData.put(1.0f); + + textureArrayBufferData.put(1.0f); + textureArrayBufferData.put(0.0f); + + textureArrayBufferData.put(1.0f); + textureArrayBufferData.put(1.0f); + textureArrayBufferData.flip(); + int textureCoordBuffer = GL45.glGenBuffers(); + GL45.glBindBuffer(GL45.GL_ARRAY_BUFFER, textureCoordBuffer); + GL45.glBufferData(GL45.GL_ARRAY_BUFFER, textureArrayBufferData, GL45.GL_STATIC_DRAW); + GL45.glVertexAttribPointer(1, 2, GL45.GL_FLOAT, false, 0, 0); + GL45.glEnableVertexAttribArray(1); + + return rVal; + } + + + + + public static Model createParticleModel(){ + Model particleModel = new Model(); + + + Mesh particleMesh = new Mesh("particleBillboard"); + + + // + // VAO + // + OpenGLState openGLState = Globals.renderingEngine.getOpenGLState(); + particleMesh.generateVAO(openGLState); + + + + + + + + + + + float[] vertexcoords = { + -1.0f, 1.0f, 0.0f, + 1.0f, 1.0f, 0.0f, + -1.0f, -1.0f, 0.0f, + 1.0f, -1.0f, 0.0f, + }; + + // + //Buffer data to GPU + // + + try { + int vertexCount = vertexcoords.length / 3; + FloatBuffer vertexArrayBufferData = BufferUtils.createFloatBuffer(vertexCount * 3); + float[] temp = new float[3]; + for (int i = 0; i < vertexCount; i++) { + temp[0] = vertexcoords[i * 3 + 0]; + temp[1] = vertexcoords[i * 3 + 1]; + temp[2] = vertexcoords[i * 3 + 2]; + vertexArrayBufferData.put(temp); + } + vertexArrayBufferData.flip(); + particleMesh.bufferVertices(vertexArrayBufferData, 3); + } catch (NullPointerException ex){ + ex.printStackTrace(); + } + + int[] facedata = { + 0,1,2, + 1,2,3, + }; + + // + // FACES + // + int faceCount = facedata.length / 3; + int elementCount = facedata.length; + IntBuffer elementArrayBufferData = BufferUtils.createIntBuffer(elementCount); + for(int i = 0; i < faceCount; i++){ + int[] temp = new int[3]; + temp[0] = facedata[i * 3 + 0]; + temp[1] = facedata[i * 3 + 1]; + temp[2] = facedata[i * 3 + 2]; + elementArrayBufferData.put(temp); + } + elementArrayBufferData.flip(); + particleMesh.bufferFaces(elementArrayBufferData,elementCount); + + // + // TEXTURE COORDS + // + FloatBuffer texture_coords = BufferUtils.createFloatBuffer(8); + float[] texturedata = { + 0,1, + 1,1, + 0,0, + 1,0 + }; + texture_coords.put(texturedata); + texture_coords.flip(); + particleMesh.bufferTextureCoords(texture_coords, 2); + + + + VisualShader shader = VisualShader.smartAssembleOITProgram(); + particleMesh.setShader(shader); + + + + + openGLState.glBindVertexArray(0); + + + + + particleMesh.setMaterial(Material.createExisting(AssetDataStrings.TEXTURE_PARTICLE)); + + + + + particleMesh.setParent(particleModel); + + + particleModel.getMeshes().add(particleMesh); + + + return particleModel; + } + + + @Deprecated + public static Model createBitmapDisplay(){ + + Model rVal = new Model(); + Mesh m = new Mesh(AssetDataStrings.ASSET_STRING_BITMAP_FONT_MESH_NAME); + OpenGLState openGLState = Globals.renderingEngine.getOpenGLState(); + m.generateVAO(openGLState); + //vertices + FloatBuffer vertexArrayBufferData = BufferUtils.createFloatBuffer(12); + vertexArrayBufferData.put( 0); + vertexArrayBufferData.put( 1); + + vertexArrayBufferData.put( 0); + vertexArrayBufferData.put( 0); + + vertexArrayBufferData.put( 1); + vertexArrayBufferData.put( 0); + + vertexArrayBufferData.put( 0); + vertexArrayBufferData.put( 1); + + vertexArrayBufferData.put( 1); + vertexArrayBufferData.put( 0); + + vertexArrayBufferData.put( 1); + vertexArrayBufferData.put( 1); + vertexArrayBufferData.flip(); + + + IntBuffer faceArrayBufferData = BufferUtils.createIntBuffer(6); + faceArrayBufferData.put(0); + faceArrayBufferData.put(1); + faceArrayBufferData.put(2); + + faceArrayBufferData.put(3); + faceArrayBufferData.put(4); + faceArrayBufferData.put(5); + faceArrayBufferData.flip(); + + + + //texture coords + FloatBuffer textureArrayBufferData = BufferUtils.createFloatBuffer(12); + textureArrayBufferData.put(0); + textureArrayBufferData.put(1); + + textureArrayBufferData.put(0); + textureArrayBufferData.put(0); + + textureArrayBufferData.put(1); + textureArrayBufferData.put(0); + + textureArrayBufferData.put(0); + textureArrayBufferData.put(1); + + textureArrayBufferData.put(1); + textureArrayBufferData.put(0); + + textureArrayBufferData.put(1); + textureArrayBufferData.put(1); + textureArrayBufferData.flip(); + + + //buffer vertices + m.bufferVertices(vertexArrayBufferData, 2); + //buffer normals + m.bufferNormals(vertexArrayBufferData, 2); + //buffer faces + m.bufferFaces(faceArrayBufferData, 2); + //buffer texture coords + m.bufferTextureCoords(textureArrayBufferData, 2); + + + m.setShader(VisualShader.loadSpecificShader("/Shaders/ui/font/basicbitmap/basicbitmap.vs", "/Shaders/ui/font/basicbitmap/basicbitmap.fs")); + + + openGLState.glBindVertexArray(0); + m.setParent(rVal); + + Material uiMat = Material.create("/Textures/Fonts/myfont1-harsher.png"); + m.setMaterial(uiMat); + rVal.getMaterials().add(uiMat); + + rVal.getMeshes().add(m); + + return rVal; + } + + + + + + /** + * Creates a model to use to show bitmap characters + * @return The model + */ + public static Model createBitmapCharacter(){ + + Model rVal = new Model(); + Mesh m = new Mesh(AssetDataStrings.ASSET_STRING_BITMAP_FONT_MESH_NAME); + OpenGLState openGLState = Globals.renderingEngine.getOpenGLState(); + m.generateVAO(openGLState); + //vertices + FloatBuffer vertexArrayBufferData = BufferUtils.createFloatBuffer(12); + vertexArrayBufferData.put(-1); + vertexArrayBufferData.put( 1); + + vertexArrayBufferData.put(-1); + vertexArrayBufferData.put(-1); + + vertexArrayBufferData.put( 1); + vertexArrayBufferData.put(-1); + + vertexArrayBufferData.put(-1); + vertexArrayBufferData.put( 1); + + vertexArrayBufferData.put( 1); + vertexArrayBufferData.put(-1); + + vertexArrayBufferData.put( 1); + vertexArrayBufferData.put( 1); + vertexArrayBufferData.flip(); + + + IntBuffer faceArrayBufferData = BufferUtils.createIntBuffer(6); + faceArrayBufferData.put(0); + faceArrayBufferData.put(1); + faceArrayBufferData.put(2); + + faceArrayBufferData.put(3); + faceArrayBufferData.put(4); + faceArrayBufferData.put(5); + faceArrayBufferData.flip(); + + + + //texture coords + FloatBuffer textureArrayBufferData = BufferUtils.createFloatBuffer(12); + textureArrayBufferData.put(0); + textureArrayBufferData.put(1); + + textureArrayBufferData.put(0); + textureArrayBufferData.put(0); + + textureArrayBufferData.put(1); + textureArrayBufferData.put(0); + + textureArrayBufferData.put(0); + textureArrayBufferData.put(1); + + textureArrayBufferData.put(1); + textureArrayBufferData.put(0); + + textureArrayBufferData.put(1); + textureArrayBufferData.put(1); + textureArrayBufferData.flip(); + + + //buffer vertices + m.bufferVertices(vertexArrayBufferData, 2); + //buffer normals + m.bufferNormals(vertexArrayBufferData, 2); + //buffer faces + m.bufferFaces(faceArrayBufferData, 6); + //buffer texture coords + m.bufferTextureCoords(textureArrayBufferData, 2); + + + m.setShader(VisualShader.loadSpecificShader("/Shaders/ui/font/bitmapchar/bitmapchar.vs", "/Shaders/ui/font/bitmapchar/bitmapchar.fs")); + + + openGLState.glBindVertexArray(0); + m.setParent(rVal); + + rVal.getMeshes().add(m); + + return rVal; + } + + + + public static Model createInWindowPanel(String vertexShader, String fragmentShader){ + + Model rVal = new Model(); + Mesh m = new Mesh("plane"); + OpenGLState openGLState = Globals.renderingEngine.getOpenGLState(); + m.generateVAO(openGLState); + //vertices + FloatBuffer vertexArrayBufferData = BufferUtils.createFloatBuffer(12); + vertexArrayBufferData.put(-1); + vertexArrayBufferData.put( 1); + + vertexArrayBufferData.put(-1); + vertexArrayBufferData.put(-1); + + vertexArrayBufferData.put( 1); + vertexArrayBufferData.put(-1); + + vertexArrayBufferData.put(-1); + vertexArrayBufferData.put( 1); + + vertexArrayBufferData.put( 1); + vertexArrayBufferData.put(-1); + + vertexArrayBufferData.put( 1); + vertexArrayBufferData.put( 1); + vertexArrayBufferData.flip(); + + + IntBuffer faceArrayBufferData = BufferUtils.createIntBuffer(6); + faceArrayBufferData.put(0); + faceArrayBufferData.put(1); + faceArrayBufferData.put(2); + + faceArrayBufferData.put(3); + faceArrayBufferData.put(4); + faceArrayBufferData.put(5); + faceArrayBufferData.flip(); + + + + //texture coords + FloatBuffer textureArrayBufferData = BufferUtils.createFloatBuffer(12); + textureArrayBufferData.put(0); + textureArrayBufferData.put(1); + + textureArrayBufferData.put(0); + textureArrayBufferData.put(0); + + textureArrayBufferData.put(1); + textureArrayBufferData.put(0); + + textureArrayBufferData.put(0); + textureArrayBufferData.put(1); + + textureArrayBufferData.put(1); + textureArrayBufferData.put(0); + + textureArrayBufferData.put(1); + textureArrayBufferData.put(1); + textureArrayBufferData.flip(); + + + //buffer vertices + m.bufferVertices(vertexArrayBufferData, 2); + //buffer normals + m.bufferNormals(vertexArrayBufferData, 2); + //buffer faces + m.bufferFaces(faceArrayBufferData, 2); + //buffer texture coords + m.bufferTextureCoords(textureArrayBufferData, 2); + + + m.setShader(VisualShader.loadSpecificShader(vertexShader, fragmentShader)); + + + openGLState.glBindVertexArray(0); + m.setParent(rVal); + + rVal.getMeshes().add(m); + + return rVal; + } + +} diff --git a/src/main/java/electrosphere/renderer/meshgen/GeometryModelGen.java b/src/main/java/electrosphere/renderer/meshgen/GeometryModelGen.java new file mode 100644 index 00000000..598c25bc --- /dev/null +++ b/src/main/java/electrosphere/renderer/meshgen/GeometryModelGen.java @@ -0,0 +1,402 @@ +package electrosphere.renderer.meshgen; + +import java.nio.FloatBuffer; +import java.nio.IntBuffer; + +import org.lwjgl.BufferUtils; +import org.lwjgl.util.par.ParShapes; +import org.lwjgl.util.par.ParShapesMesh; + +import electrosphere.engine.Globals; +import electrosphere.engine.assetmanager.AssetDataStrings; +import electrosphere.renderer.OpenGLState; +import electrosphere.renderer.model.Material; +import electrosphere.renderer.model.Mesh; +import electrosphere.renderer.model.Model; +import electrosphere.renderer.shader.VisualShader; + +/** + * Generates full models of basic geometry + */ +public class GeometryModelGen { + + + + /** + * Name of the mesh for the single block model + */ + public static final String MESH_NAME_BLOCK_SINGLE = "cube"; + + + + + + /** + * Generates a plane model + * @param vertexShader The vertex shader + * @param fragmentShader The fragment shader + * @return The model + */ + public static Model createPlaneModel(String vertexShader, String fragmentShader){ + Model rVal = new Model(); + Mesh planeMesh = new Mesh("plane"); + // + // VAO + // + OpenGLState openGLState = Globals.renderingEngine.getOpenGLState(); + planeMesh.generateVAO(openGLState); + + float[] vertexcoords = { + -1.0f, 1.0f, 0.0f, + 1.0f, 1.0f, 0.0f, + -1.0f, -1.0f, 0.0f, + 1.0f, -1.0f, 0.0f, + + }; + + // + //Buffer data to GPU + // + + try { + int vertexCount = vertexcoords.length / 3; + FloatBuffer vertexArrayBufferData = BufferUtils.createFloatBuffer(vertexCount * 3); + float[] temp = new float[3]; + for (int i = 0; i < vertexCount; i++) { + temp[0] = vertexcoords[i * 3 + 0]; + temp[1] = vertexcoords[i * 3 + 1]; + temp[2] = vertexcoords[i * 3 + 2]; + vertexArrayBufferData.put(temp); + } + vertexArrayBufferData.flip(); + planeMesh.bufferVertices(vertexArrayBufferData, 3); + } catch (NullPointerException ex){ + ex.printStackTrace(); + } + + int[] facedata = { + 0,1,2, + 1,2,3, + }; + + // + // FACES + // + int faceCount = facedata.length / 3; + int elementCount = facedata.length; + IntBuffer elementArrayBufferData = BufferUtils.createIntBuffer(elementCount); + for(int i = 0; i < faceCount; i++){ + int[] temp = new int[3]; + temp[0] = facedata[i * 3 + 0]; + temp[1] = facedata[i * 3 + 1]; + temp[2] = facedata[i * 3 + 2]; + elementArrayBufferData.put(temp); + } + elementArrayBufferData.flip(); + planeMesh.bufferFaces(elementArrayBufferData,elementCount); + + // + // TEXTURE COORDS + // + FloatBuffer texture_coords = BufferUtils.createFloatBuffer(8); + float[] texturedata = { + 0,1, + 1,1, + 0,0, + 1,0 + }; + texture_coords.put(texturedata); + texture_coords.flip(); + planeMesh.bufferTextureCoords(texture_coords, 2); + + + planeMesh.setShader(VisualShader.loadSpecificShader(vertexShader,fragmentShader)); + openGLState.glBindVertexArray(0); + planeMesh.setParent(rVal); + rVal.getMeshes().add(planeMesh); + return rVal; + } + + /** + * Generates a unit sphere model + * @return The model + */ + public static Model createUnitsphere(){ + Model model = new Model(); + Mesh sphereMesh = new Mesh("sphere"); + OpenGLState openGLState = Globals.renderingEngine.getOpenGLState(); + sphereMesh.generateVAO(openGLState); + + //buffer coords + ParShapesMesh data = ParShapes.par_shapes_create_parametric_sphere(10, 5); + int numPoints = data.npoints(); + + //verts + { + FloatBuffer verts = data.points(numPoints * 3); + FloatBuffer vertsFinal = BufferUtils.createFloatBuffer(verts.limit()); //reallocating to BufferUtils buffer to help minimize memory errors + vertsFinal.put(verts); + vertsFinal.flip(); + sphereMesh.bufferVertices(vertsFinal, 3); + } + + //indices + { + IntBuffer indices = data.triangles(data.ntriangles() * 3); + IntBuffer indicesFinal = BufferUtils.createIntBuffer(indices.limit()); //reallocating to BufferUtils buffer to help minimize memory errors + indicesFinal.put(indices); + indicesFinal.flip(); + sphereMesh.bufferFaces(indicesFinal, data.ntriangles() * 3); + } + + //texture coords + { + FloatBuffer texCoords = data.tcoords(numPoints * 3); + FloatBuffer texCoordsFinal = BufferUtils.createFloatBuffer(texCoords.limit()); //reallocating to BufferUtils buffer to help minimize memory errors + texCoordsFinal.put(texCoords); + texCoordsFinal.flip(); + sphereMesh.bufferTextureCoords(texCoordsFinal, 2); + } + + + //setup extra structures + Material mat = Material.createExisting(AssetDataStrings.TEXTURE_TEAL_TRANSPARENT); + sphereMesh.setMaterial(mat); + sphereMesh.setShader(VisualShader.smartAssembleShader()); + openGLState.glBindVertexArray(0); + sphereMesh.setParent(model); + model.getMeshes().add(sphereMesh); + + return model; + } + + /** + * Creates a unit cylinder model + * @return The model + */ + public static Model createUnitCylinder(){ + Model model = new Model(); + Mesh sphereMesh = new Mesh("cylinder"); + OpenGLState openGLState = Globals.renderingEngine.getOpenGLState(); + sphereMesh.generateVAO(openGLState); + + //buffer coords + ParShapesMesh data = ParShapes.par_shapes_create_cylinder(10, 2); + ParShapes.par_shapes_rotate(data, (float)(Math.PI / 2.0), new float[]{-1,0,0}); + ParShapes.par_shapes_translate(data, 0, -0.5f, 0); + ParShapes.par_shapes_scale(data, -1.0f, 2.0f, 1.0f); + int numPoints = data.npoints(); + + //verts + { + FloatBuffer verts = data.points(numPoints * 3); + FloatBuffer vertsFinal = BufferUtils.createFloatBuffer(verts.limit()); //reallocating to BufferUtils buffer to help minimize memory errors + vertsFinal.put(verts); + vertsFinal.flip(); + sphereMesh.bufferVertices(vertsFinal, 3); + } + + //indices + { + IntBuffer indices = data.triangles(data.ntriangles() * 3); + IntBuffer indicesFinal = BufferUtils.createIntBuffer(indices.limit()); //reallocating to BufferUtils buffer to help minimize memory errors + indicesFinal.put(indices); + indicesFinal.flip(); + sphereMesh.bufferFaces(indicesFinal, data.ntriangles() * 3); + } + + //texture coords + { + FloatBuffer texCoords = data.tcoords(numPoints * 3); + FloatBuffer texCoordsFinal = BufferUtils.createFloatBuffer(texCoords.limit()); //reallocating to BufferUtils buffer to help minimize memory errors + texCoordsFinal.put(texCoords); + texCoordsFinal.flip(); + sphereMesh.bufferTextureCoords(texCoordsFinal, 2); + } + + //setup extra structures + Material mat = Material.createExisting(AssetDataStrings.TEXTURE_TEAL_TRANSPARENT); + sphereMesh.setMaterial(mat); + sphereMesh.setShader(VisualShader.smartAssembleShader()); + openGLState.glBindVertexArray(0); + sphereMesh.setParent(model); + model.getMeshes().add(sphereMesh); + + return model; + } + + /** + * Creates a unit cylinder model + * @return The model + */ + public static Model createUnitCube(){ + Model model = new Model(); + Mesh sphereMesh = new Mesh("cube"); + OpenGLState openGLState = Globals.renderingEngine.getOpenGLState(); + sphereMesh.generateVAO(openGLState); + + //buffer coords + int numTriangles = 12; + + //verts + BufferUtils.createFloatBuffer(3 * 8); + FloatBuffer verts = BufferUtils.createFloatBuffer(3 * 8); + verts.put(new float[]{ + -0.5f,-0.5f,-0.5f, + 0.5f,-0.5f,-0.5f, + -0.5f, 0.5f,-0.5f, + 0.5f, 0.5f,-0.5f, + + -0.5f,-0.5f, 0.5f, + 0.5f,-0.5f, 0.5f, + -0.5f, 0.5f, 0.5f, + 0.5f, 0.5f, 0.5f, + }); + verts.flip(); + sphereMesh.bufferVertices(verts, 3); + + //indices + IntBuffer indices = BufferUtils.createIntBuffer(3*12); + indices.put(new int[]{ + //Top + 2, 6, 7, + 2, 3, 7, + + //Bottom + 0, 4, 5, + 0, 1, 5, + + //Left + 0, 2, 6, + 0, 4, 6, + + //Right + 1, 3, 7, + 1, 5, 7, + + //Front + 0, 2, 3, + 0, 1, 3, + + //Back + 4, 6, 7, + 4, 5, 7 + }); + indices.flip(); + sphereMesh.bufferFaces(indices, numTriangles * 3); + + //texture coords + FloatBuffer texCoords = BufferUtils.createFloatBuffer(2*8); + texCoords.put(new float[]{ + 0,0, + 1,0, + 0,1, + 1,1, + + 0,0, + 0,1, + 1,0, + 1,1, + }); + texCoords.flip(); + sphereMesh.bufferTextureCoords(texCoords, 2); + + //setup extra structures + Material mat = Material.createExisting(AssetDataStrings.TEXTURE_TEAL_TRANSPARENT); + sphereMesh.setMaterial(mat); + sphereMesh.setShader(VisualShader.smartAssembleShader()); + openGLState.glBindVertexArray(0); + sphereMesh.setParent(model); + model.getMeshes().add(sphereMesh); + + return model; + } + + /** + * Creates a unit cylinder model + * @return The model + */ + public static Model createBlockSingleModel(){ + Model model = new Model(); + Mesh cubeMesh = new Mesh(GeometryModelGen.MESH_NAME_BLOCK_SINGLE); + OpenGLState openGLState = Globals.renderingEngine.getOpenGLState(); + cubeMesh.generateVAO(openGLState); + + //buffer coords + int numTriangles = 12; + + //verts + BufferUtils.createFloatBuffer(3 * 8); + FloatBuffer verts = BufferUtils.createFloatBuffer(3 * 8); + verts.put(new float[]{ + -0.1f,-0.1f,-0.1f, + 0.1f,-0.1f,-0.1f, + -0.1f, 0.1f,-0.1f, + 0.1f, 0.1f,-0.1f, + + -0.1f,-0.1f, 0.1f, + 0.1f,-0.1f, 0.1f, + -0.1f, 0.1f, 0.1f, + 0.1f, 0.1f, 0.1f, + }); + verts.flip(); + cubeMesh.bufferVertices(verts, 3); + + //indices + IntBuffer indices = BufferUtils.createIntBuffer(3*12); + indices.put(new int[]{ + //Top + 2, 6, 7, + 2, 3, 7, + + //Bottom + 0, 4, 5, + 0, 1, 5, + + //Left + 0, 2, 6, + 0, 4, 6, + + //Right + 1, 3, 7, + 1, 5, 7, + + //Front + 0, 2, 3, + 0, 1, 3, + + //Back + 4, 6, 7, + 4, 5, 7 + }); + indices.flip(); + cubeMesh.bufferFaces(indices, numTriangles * 3); + + //texture coords + FloatBuffer texCoords = BufferUtils.createFloatBuffer(2*8); + texCoords.put(new float[]{ + 0,0, + 1,0, + 0,1, + 1,1, + + 0,0, + 0,1, + 1,0, + 1,1, + }); + texCoords.flip(); + cubeMesh.bufferTextureCoords(texCoords, 2); + + //setup extra structures + Material mat = Material.createExisting(AssetDataStrings.TEXTURE_BLOCK_ATLAS); + cubeMesh.setMaterial(mat); + cubeMesh.setShader(VisualShader.loadSpecificShader(AssetDataStrings.SHADER_BLOCK_SINGLE_VERT, AssetDataStrings.SHADER_BLOCK_SINGLE_FRAG)); + openGLState.glBindVertexArray(0); + cubeMesh.setParent(model); + model.getMeshes().add(cubeMesh); + + return model; + } + +} diff --git a/src/main/java/electrosphere/renderer/meshgen/HeightmapMeshgen.java b/src/main/java/electrosphere/renderer/meshgen/HeightmapMeshgen.java new file mode 100644 index 00000000..40b2e657 --- /dev/null +++ b/src/main/java/electrosphere/renderer/meshgen/HeightmapMeshgen.java @@ -0,0 +1,801 @@ +package electrosphere.renderer.meshgen; + +import java.nio.FloatBuffer; +import java.nio.IntBuffer; +import java.util.LinkedList; +import java.util.List; + +import org.joml.Vector3f; +import org.lwjgl.BufferUtils; + +import electrosphere.engine.Globals; +import electrosphere.renderer.OpenGLState; +import electrosphere.renderer.model.Material; +import electrosphere.renderer.model.Mesh; +import electrosphere.renderer.model.Model; +import electrosphere.renderer.shader.VisualShader; + +public class HeightmapMeshgen { + + public static Model createTerrainModelPrecomputedShader(OpenGLState openGLState, float[][] heightfield, float[][] texturemap, VisualShader program, int stride){ + Model rVal = new Model(); + Mesh m = new Mesh("terrain"); + int width = heightfield.length; + int height = heightfield[0].length; + + int actualWidth = (int)Math.ceil(1.0f * width / (1.0f * stride)); + int actualHeight = (int)Math.ceil(1.0f * height / (1.0f * stride)); + + +// System.out.println(actualWidth + " " + actualHeight); + +// System.out.println((actualWidth - 1) * (actualHeight - 1)); + + FloatBuffer vertices; + FloatBuffer normals; + IntBuffer faces; + FloatBuffer texture_coords; + FloatBuffer textureIndices; + if(stride * actualWidth > width){ + int drawWidth = actualWidth + 1; + int drawHeight = actualHeight + 1; + vertices = BufferUtils.createFloatBuffer(drawWidth * drawHeight * 12); + normals = BufferUtils.createFloatBuffer(drawWidth * drawHeight * 12); + faces = BufferUtils.createIntBuffer((drawWidth - 1) * (drawHeight - 1) * 2 * 3); + texture_coords = BufferUtils.createFloatBuffer(drawWidth * drawHeight * 8); + textureIndices = BufferUtils.createFloatBuffer(drawWidth * drawHeight * 16); + } else { + vertices = BufferUtils.createFloatBuffer(actualWidth * actualHeight * 12); + normals = BufferUtils.createFloatBuffer(actualWidth * actualHeight * 12); + faces = BufferUtils.createIntBuffer((actualWidth - 1) * (actualHeight - 1) * 2 * 3); + texture_coords = BufferUtils.createFloatBuffer(actualWidth * actualHeight * 8); + textureIndices = BufferUtils.createFloatBuffer(actualWidth * actualHeight * 16); + } + + int incrementer = 0; + // int numFaces = (actualWidth - 1) * (actualHeight - 1) * 2 * 3; + for(int x = 0; x < width - 1; x = x + stride){ + for(int y = 0; y < height - 1; y = y + stride){ + //deal with vertex + //0,0 + vertices.put(x); + vertices.put(heightfield[x][y]); + vertices.put(y); + //1,0 + vertices.put(x + stride); + vertices.put(heightfield[x+stride][y]); + vertices.put(y); + //0,1 + vertices.put(x); + vertices.put(heightfield[x][y+stride]); + vertices.put(y + stride); + //1,1 + vertices.put(x + stride); + vertices.put(heightfield[x+stride][y+stride]); + vertices.put(y + stride); + //deal with normal + Vector3f normal = calculateTerrainNormal(heightfield, actualWidth, actualHeight, stride, x, y); + normals.put(normal.x); + normals.put(normal.y); + normals.put(normal.z); + normal = calculateTerrainNormal(heightfield, actualWidth, actualHeight, stride, x + stride, y); + normals.put(normal.x); + normals.put(normal.y); + normals.put(normal.z); + normal = calculateTerrainNormal(heightfield, actualWidth, actualHeight, stride, x, y + stride); + normals.put(normal.x); + normals.put(normal.y); + normals.put(normal.z); + normal = calculateTerrainNormal(heightfield, actualWidth, actualHeight, stride, x + stride, y + stride); + normals.put(normal.x); + normals.put(normal.y); + normals.put(normal.z); + //deal with texture coordinates +// if(x / stride % 2 == 0){ +// if(y / stride % 2 == 0){ +// texture_coords.put(0); +// texture_coords.put(0); +// texture_coords.put(1); +// texture_coords.put(0); +// texture_coords.put(0); +// texture_coords.put(1); +// texture_coords.put(1); +// texture_coords.put(1); +// } else { +// texture_coords.put(0); +// texture_coords.put(1); +// } +// } else { +// if(y / stride % 2 == 0){ +// texture_coords.put(1); +// texture_coords.put(0); +// } else { +// texture_coords.put(1); +// texture_coords.put(1); +// } +// } + texture_coords.put(0); + texture_coords.put(0); + texture_coords.put(1); + texture_coords.put(0); + texture_coords.put(0); + texture_coords.put(1); + texture_coords.put(1); + texture_coords.put(1); + + if(x + stride < width - 1 && y + stride < height - 1){ +// texturemap[x+stride][y+stride]; + for(int i = 0; i < 4 ; i++){ +// textureIndices.put(1); +// textureIndices.put(0); +// textureIndices.put(0); +// textureIndices.put(0); + textureIndices.put(texturemap[x][y]); + textureIndices.put(texturemap[x+stride][y]); + textureIndices.put(texturemap[x][y+stride]); + textureIndices.put(texturemap[x+stride][y+stride]); + } + } else { + for(int i = 0; i < 4 ; i++){ + textureIndices.put(0); + textureIndices.put(0); + textureIndices.put(0); + textureIndices.put(0); + } + } + + + //deal with faces + if(1.0f * x / stride < actualWidth - 1 && 1.0f * y / stride < actualHeight - 1){ + faces.put(incrementer * 4 + 0); + faces.put(incrementer * 4 + 1); + faces.put(incrementer * 4 + 2); + faces.put(incrementer * 4 + 1); + faces.put(incrementer * 4 + 2); + faces.put(incrementer * 4 + 3); + } + incrementer++; + } + } + + vertices.flip(); + normals.flip(); + faces.flip(); + texture_coords.flip(); + textureIndices.flip(); + + m.generateVAO(openGLState); + //buffer vertices + m.bufferVertices(vertices, 3); + //buffer normals + m.bufferNormals(normals, 3); + //buffer faces + m.bufferFaces(faces,incrementer*2); + //buffer texture coords + m.bufferTextureCoords(texture_coords, 2); + //texture indices + m.bufferCustomFloatAttribArray(textureIndices, 4, 5); + m.setShader(program); + openGLState.glBindVertexArray(0); + m.setParent(rVal); + + Material groundMat = Material.create("/Textures/Ground/Dirt1.png"); + m.setMaterial(groundMat); + + rVal.getMeshes().add(m); + return rVal; + } + + + static float MINIMIZATION_DIFF_MAX = 0.001f; + + public static Model createMinimizedTerrainModelPrecomputedShader(float[][] heightfield, float[][] texturemap, VisualShader program, int stride){ + + class QuadToGenerate { + //coords are inclusive + int startX; + int endX; + int startY; + int endY; + float min; + float max; + float texture; + boolean homogeneousTexture; + + QuadToGenerate(int startX, int startY, int endX, int endY, float diff, float min, float max, boolean homogeneousTexture, float texture){ + this.startX = startX; + this.startY = startY; + this.endX = endX; + this.endY = endY; + this.min = min; + this.max = max; + this.texture = texture; + this.homogeneousTexture = homogeneousTexture; + } + + } + + + Model rVal = new Model(); + Mesh m = new Mesh("terrain"); + OpenGLState openGLState = Globals.renderingEngine.getOpenGLState(); + int width = heightfield.length; + int height = heightfield[0].length; + + int actualWidth = (int)Math.ceil(1.0f * width / (1.0f * stride)); + int actualHeight = (int)Math.ceil(1.0f * height / (1.0f * stride)); + + +// System.out.println(actualWidth + " " + actualHeight); + +// System.out.println((actualWidth - 1) * (actualHeight - 1)); + + FloatBuffer vertices; + FloatBuffer normals; + IntBuffer faces; + FloatBuffer texture_coords; + FloatBuffer textureIndices; + if(stride * actualWidth > width){ + int drawWidth = actualWidth + 1; + int drawHeight = actualHeight + 1; + vertices = BufferUtils.createFloatBuffer(drawWidth * drawHeight * 12); + normals = BufferUtils.createFloatBuffer(drawWidth * drawHeight * 12); + faces = BufferUtils.createIntBuffer((drawWidth - 1) * (drawHeight - 1) * 2 * 3); + texture_coords = BufferUtils.createFloatBuffer(drawWidth * drawHeight * 8); + textureIndices = BufferUtils.createFloatBuffer(drawWidth * drawHeight * 16); + } else { + vertices = BufferUtils.createFloatBuffer(actualWidth * actualHeight * 12); + normals = BufferUtils.createFloatBuffer(actualWidth * actualHeight * 12); + faces = BufferUtils.createIntBuffer((actualWidth - 1) * (actualHeight - 1) * 2 * 3); + texture_coords = BufferUtils.createFloatBuffer(actualWidth * actualHeight * 8); + textureIndices = BufferUtils.createFloatBuffer(actualWidth * actualHeight * 16); + } + + + //merge along y + + List firstPhaseQuads = new LinkedList(); + QuadToGenerate quadCurrent = null; + float minVal = 0; + float maxVal = 0; + for(int x = 0; x < width - 1; x = x + stride){ + quadCurrent = null; + for(int y = 0; y < height - 1; y = y + stride){ + if((x == 5 && y == 2)){ + // System.out.println(quadCurrent); +// continue; + } + if(quadCurrent == null){ + minVal = 100000000; + maxVal = 0; + //minval + if(heightfield[x][y] < minVal){ + minVal = heightfield[x][y]; + } + if(heightfield[x+stride][y] < minVal){ + minVal = heightfield[x+stride][y]; + } + if(heightfield[x][y+stride] < minVal){ + minVal = heightfield[x][y+stride]; + } + if(heightfield[x+stride][y+stride] < minVal){ + minVal = heightfield[x+stride][y+stride]; + } + //maxval + if(heightfield[x][y] > maxVal){ + maxVal = heightfield[x][y]; + } + if(heightfield[x+stride][y] > maxVal){ + maxVal = heightfield[x+stride][y]; + } + if(heightfield[x][y+stride] > maxVal){ + maxVal = heightfield[x][y+stride]; + } + if(heightfield[x+stride][y+stride] > maxVal){ + maxVal = heightfield[x+stride][y+stride]; + } + boolean textureMatch = false; + float texture = -1; + if(x+stride < width - 1 && y+stride < height - 1 && + texturemap[x][y] == texturemap[x+stride][y] && + texturemap[x][y] == texturemap[x][y+stride] && + texturemap[x][y] == texturemap[x+stride][y+stride]){ + + textureMatch = true; + texture = texturemap[x][y]; + } else { +// if(x > 8 && (x+stride < width - 1) && (y+stride < height -1)){ +// System.out.println( +// (x+stride < width - 1) + " " + +// (y+stride < height -1) + " " + +// (texturemap[x][y] == texturemap[x+stride][y]) + " " + +// (texturemap[x][y] == texturemap[x][y+stride]) + " " + +// (texturemap[x][y] == texturemap[x+stride][y+stride]) +// ); +// } + } + if(textureMatch){ + quadCurrent = new QuadToGenerate(x,y,x+stride,y+stride,maxVal - minVal,minVal,maxVal,textureMatch,texture); + } else { + firstPhaseQuads.add(new QuadToGenerate(x,y,x+stride,y+stride,maxVal - minVal,minVal,maxVal,textureMatch,texture)); + // quadCurrent = null; + } + } else { + float newMin = minVal; + float newMax = maxVal; + //min + if(heightfield[x][y+stride] < newMin){ + newMin = heightfield[x][y+stride]; + } + if(heightfield[x+stride][y+stride] < newMin){ + newMin = heightfield[x+stride][y+stride]; + } + //max + if(heightfield[x][y+stride] > newMax){ + newMax = heightfield[x][y+stride]; + } + if(heightfield[x+stride][y+stride] > newMax){ + newMax = heightfield[x+stride][y+stride]; + } + if(y+stride < height - 1 && x+stride < width - 1){ + if(newMax - newMin < MINIMIZATION_DIFF_MAX && + quadCurrent.texture == texturemap[x+stride][y] && + quadCurrent.texture == texturemap[x ][y+stride] && + quadCurrent.texture == texturemap[x+stride][y+stride] && + quadCurrent.homogeneousTexture + ){ + //add to quad + quadCurrent.endY = y + stride; + quadCurrent.min = newMax; + quadCurrent.max = newMax; + } else { + //push quad + firstPhaseQuads.add(quadCurrent); + firstPhaseQuads.add(new QuadToGenerate(x,y,x+stride,y+stride,maxVal - minVal,minVal,maxVal,false,0)); + quadCurrent = null; +// System.out.println("Push"); + } + } else { + if(newMax - newMin < MINIMIZATION_DIFF_MAX){ + //add to quad + quadCurrent.endY = y + stride; + quadCurrent.min = newMax; + quadCurrent.max = newMax; + } else { + //push quad that we were building + firstPhaseQuads.add(quadCurrent); + // quadCurrent = null; + //create new quad from what we were just analyzing + boolean textureMatch = false; + float texture = -1; + quadCurrent = new QuadToGenerate(x,y,x+stride,y+stride,maxVal - minVal,minVal,maxVal,textureMatch,texture); +// System.out.println("Push"); + } + } + } + } + if(quadCurrent != null){ + firstPhaseQuads.add(quadCurrent); + } + } + + List finalQuads = new LinkedList(); + // for(QuadToGenerate current : firstPhaseQuads){ + // finalQuads.add(current); + // } + +// System.out.println(finalQuads.size()); + + //merge along x + + // QuadToGenerate currentQuad = null; + List toSkip = new LinkedList(); + for(QuadToGenerate currentQuad : firstPhaseQuads){ + // toRemove.clear(); + if(toSkip.contains(currentQuad)){ + continue; + } + for(QuadToGenerate currentPotentialMatch : firstPhaseQuads){ + if(currentPotentialMatch.startX <= currentQuad.startX){ + continue; + } + if(currentPotentialMatch.startX > currentQuad.endX){ + break; + } + if(currentPotentialMatch.startY != currentQuad.startY){ + continue; + } + if(currentPotentialMatch.endY != currentQuad.endY){ + continue; + } + if( + !(currentQuad.homogeneousTexture && + currentPotentialMatch.homogeneousTexture && + currentQuad.texture == currentPotentialMatch.texture) + ){ + continue; + } + if(currentQuad.min < currentPotentialMatch.min && currentQuad.max < currentPotentialMatch.max){ + float min = currentQuad.min; + float max = currentPotentialMatch.max; + if(max - min < MINIMIZATION_DIFF_MAX){ + currentQuad.endX = currentPotentialMatch.endX; + currentQuad.max = currentPotentialMatch.max; + toSkip.add(currentPotentialMatch); + } + } else if(currentQuad.min > currentPotentialMatch.min && currentQuad.max > currentPotentialMatch.max){ + float min = currentPotentialMatch.min; + float max = currentQuad.max; + if(max - min < MINIMIZATION_DIFF_MAX){ + currentQuad.endX = currentPotentialMatch.endX; + currentQuad.min = currentPotentialMatch.min; + toSkip.add(currentPotentialMatch); + } + } else { + if(currentQuad.min < currentPotentialMatch.min){ + currentQuad.endX = currentPotentialMatch.endX; + } else { + currentQuad.endX = currentPotentialMatch.endX; + currentQuad.min = currentPotentialMatch.min; + currentQuad.max = currentPotentialMatch.max; + } + toSkip.add(currentPotentialMatch); + } + } + finalQuads.add(currentQuad); + } + // for(QuadToGenerate currentIteration : firstPhaseQuads){ + // if(currentQuad == null){ + // currentQuad = currentIteration; + // } else { + // //if should merge: + // if( + // currentQuad.homogeneousTexture && + // currentIteration.homogeneousTexture && + // currentQuad.texture == currentIteration.texture + // ){ + // if(currentQuad.min < currentIteration.min && currentQuad.max < currentIteration.max){ + // float min = currentQuad.min; + // float max = currentIteration.max; + // if(max - min < MINIMIZATION_DIFF_MAX){ + // currentQuad.endX = currentIteration.endX; + // currentQuad.max = currentIteration.max; + // } else { + // finalQuads.add(currentQuad); + // currentQuad = currentIteration; + // } + // } else if(currentQuad.min > currentIteration.min && currentQuad.max > currentIteration.max){ + // float min = currentIteration.min; + // float max = currentQuad.max; + // if(max - min < MINIMIZATION_DIFF_MAX){ + // currentQuad.endX = currentIteration.endX; + // currentQuad.min = currentIteration.min; + // } else { + // finalQuads.add(currentQuad); + // currentQuad = currentIteration; + // } + // } else { + // if(currentQuad.min < currentIteration.min){ + // currentQuad.endX = currentIteration.endX; + // } else { + // currentQuad.endX = currentIteration.endX; + // currentQuad.min = currentIteration.min; + // currentQuad.max = currentIteration.max; + // } + // } + // } else { + // finalQuads.add(currentQuad); + // currentQuad = currentIteration; + // } + // } + // } + // finalQuads.add(currentQuad); + + // for(QuadToGenerate current : finalQuads){ + // if(current.startX > 0 && current.startY > 0 && current.endX < 99 && current.endY < 99){ + // System.out.println(current.startX + " " + current.startY + " " + current.endX + " " + current.endY); + // } + // } + + // System.out.println("AAAAAAAAAAAAAAAAAA"); +// System.out.println(finalQuads.size()); + + int incrementer = 0; + + for(QuadToGenerate current : finalQuads){ + //deal with vertex + //0,0 + vertices.put(current.startX); + vertices.put(heightfield[current.startX][current.startY]); + vertices.put(current.startY); + //1,0 + vertices.put(current.endX); + vertices.put(heightfield[current.endX][current.startY]); + vertices.put(current.startY); + //0,1 + vertices.put(current.startX); + vertices.put(heightfield[current.startX][current.endY]); + vertices.put(current.endY); + //1,1 + vertices.put(current.endX); + vertices.put(heightfield[current.endX][current.endY]); + vertices.put(current.endY); + //deal with normal + Vector3f normal = calculateTerrainNormal(heightfield, actualWidth, actualHeight, stride, current.startX, current.startY); + normals.put(normal.x); + normals.put(normal.y); + normals.put(normal.z); + normal = calculateTerrainNormal(heightfield, actualWidth, actualHeight, stride, current.endX, current.startY); + normals.put(normal.x); + normals.put(normal.y); + normals.put(normal.z); + normal = calculateTerrainNormal(heightfield, actualWidth, actualHeight, stride, current.startX, current.endY); + normals.put(normal.x); + normals.put(normal.y); + normals.put(normal.z); + normal = calculateTerrainNormal(heightfield, actualWidth, actualHeight, stride, current.endX, current.endY); + normals.put(normal.x); + normals.put(normal.y); + normals.put(normal.z); + //deal with texture coordinates +// if(x / stride % 2 == 0){ +// if(y / stride % 2 == 0){ +// texture_coords.put(0); +// texture_coords.put(0); +// texture_coords.put(1); +// texture_coords.put(0); +// texture_coords.put(0); +// texture_coords.put(1); +// texture_coords.put(1); +// texture_coords.put(1); +// } else { +// texture_coords.put(0); +// texture_coords.put(1); +// } +// } else { +// if(y / stride % 2 == 0){ +// texture_coords.put(1); +// texture_coords.put(0); +// } else { +// texture_coords.put(1); +// texture_coords.put(1); +// } +// } + texture_coords.put(0); + texture_coords.put(0); + texture_coords.put(current.endX - current.startX); + texture_coords.put(0); + texture_coords.put(0); + texture_coords.put(current.endY - current.startY); + texture_coords.put(current.endX - current.startX); + texture_coords.put(current.endY - current.startY); + + if(current.endX < width - 1 && current.endY < height - 1){ +// texturemap[x+stride][y+stride]; + for(int i = 0; i < 4 ; i++){ +// textureIndices.put(1); +// textureIndices.put(0); +// textureIndices.put(0); +// textureIndices.put(0); + textureIndices.put(texturemap[current.startX][current.startY]); + textureIndices.put(texturemap[current.endX][current.startY]); + textureIndices.put(texturemap[current.startX][current.endY]); + textureIndices.put(texturemap[current.endX][current.endY]); + } + } else { + for(int i = 0; i < 4 ; i++){ + textureIndices.put(0); + textureIndices.put(0); + textureIndices.put(0); + textureIndices.put(0); + } + } + + + //deal with faces + faces.put(incrementer * 4 + 0); + faces.put(incrementer * 4 + 1); + faces.put(incrementer * 4 + 2); + faces.put(incrementer * 4 + 1); + faces.put(incrementer * 4 + 2); + faces.put(incrementer * 4 + 3); + + incrementer++; + } + + + +// int numFaces = (actualWidth - 1) * (actualHeight - 1) * 2 * 3; +// for(int x = 0; x < width - 1; x = x + stride){ +// for(int y = 0; y < height - 1; y = y + stride){ +// //deal with vertex +// //0,0 +// vertices.put(x); +// vertices.put(heightfield[x][y]); +// vertices.put(y); +// //1,0 +// vertices.put(x + stride); +// vertices.put(heightfield[x+stride][y]); +// vertices.put(y); +// //0,1 +// vertices.put(x); +// vertices.put(heightfield[x][y+stride]); +// vertices.put(y + stride); +// //1,1 +// vertices.put(x + stride); +// vertices.put(heightfield[x+stride][y+stride]); +// vertices.put(y + stride); +// //deal with normal +// Vector3f normal = calculateTerrainNormal(heightfield, actualWidth, actualHeight, stride, x, y); +// normals.put(normal.x); +// normals.put(normal.y); +// normals.put(normal.z); +// normal = calculateTerrainNormal(heightfield, actualWidth, actualHeight, stride, x + stride, y); +// normals.put(normal.x); +// normals.put(normal.y); +// normals.put(normal.z); +// normal = calculateTerrainNormal(heightfield, actualWidth, actualHeight, stride, x, y + stride); +// normals.put(normal.x); +// normals.put(normal.y); +// normals.put(normal.z); +// normal = calculateTerrainNormal(heightfield, actualWidth, actualHeight, stride, x + stride, y + stride); +// normals.put(normal.x); +// normals.put(normal.y); +// normals.put(normal.z); +// //deal with texture coordinates +//// if(x / stride % 2 == 0){ +//// if(y / stride % 2 == 0){ +//// texture_coords.put(0); +//// texture_coords.put(0); +//// texture_coords.put(1); +//// texture_coords.put(0); +//// texture_coords.put(0); +//// texture_coords.put(1); +//// texture_coords.put(1); +//// texture_coords.put(1); +//// } else { +//// texture_coords.put(0); +//// texture_coords.put(1); +//// } +//// } else { +//// if(y / stride % 2 == 0){ +//// texture_coords.put(1); +//// texture_coords.put(0); +//// } else { +//// texture_coords.put(1); +//// texture_coords.put(1); +//// } +//// } +// texture_coords.put(0); +// texture_coords.put(0); +// texture_coords.put(1); +// texture_coords.put(0); +// texture_coords.put(0); +// texture_coords.put(1); +// texture_coords.put(1); +// texture_coords.put(1); +// +// if(x + stride < width - 1 && y + stride < height - 1){ +//// texturemap[x+stride][y+stride]; +// for(int i = 0; i < 4 ; i++){ +//// textureIndices.put(1); +//// textureIndices.put(0); +//// textureIndices.put(0); +//// textureIndices.put(0); +// textureIndices.put(texturemap[x][y]); +// textureIndices.put(texturemap[x+stride][y]); +// textureIndices.put(texturemap[x][y+stride]); +// textureIndices.put(texturemap[x+stride][y+stride]); +// } +// } else { +// for(int i = 0; i < 4 ; i++){ +// textureIndices.put(0); +// textureIndices.put(0); +// textureIndices.put(0); +// textureIndices.put(0); +// } +// } +// +// +// //deal with faces +// if(1.0f * x / stride < actualWidth - 1 && 1.0f * y / stride < actualHeight - 1){ +// faces.put(incrementer * 4 + 0); +// faces.put(incrementer * 4 + 1); +// faces.put(incrementer * 4 + 2); +// faces.put(incrementer * 4 + 1); +// faces.put(incrementer * 4 + 2); +// faces.put(incrementer * 4 + 3); +// } +// incrementer++; +// } +// } + + // System.out.println(incrementer + " quads"); + + vertices.flip(); + normals.flip(); + faces.flip(); + texture_coords.flip(); + textureIndices.flip(); + + m.generateVAO(openGLState); + //buffer vertices + m.bufferVertices(vertices, 3); + //buffer normals + m.bufferNormals(normals, 3); + //buffer faces + m.bufferFaces(faces,incrementer*2); + //buffer texture coords + m.bufferTextureCoords(texture_coords, 2); + //texture indices + m.bufferCustomFloatAttribArray(textureIndices, 4, 5); + m.setShader(program); + openGLState.glBindVertexArray(0); + m.setParent(rVal); + + Material groundMat = Material.create("/Textures/Ground/Dirt1.png"); + m.setMaterial(groundMat); + + rVal.getMeshes().add(m); + return rVal; + } + + static Vector3f calculateTerrainNormal(float[][] heightfield, int actualWidth, int actualHeight, int stride, int x, int y){ + Vector3f rVal = new Vector3f(); + if(x / stride < actualWidth - 1){ + if(y / stride < actualHeight - 1){ + float hL; + if(x > 0){ + hL = heightfield[x-1][y]; + } else { + hL = heightfield[x][y]; + } + float hR = heightfield[x+1][y]; + float hD = heightfield[x][y+1]; + float hU; + if(y > 0){ + hU = heightfield[x][y-1]; + } else { + hU = heightfield[x][y]; + } + rVal = new Vector3f(hL - hR, 2.0f, hD - hU); + rVal.normalize(); + } else { + float hL; + if(x > 0){ + hL = heightfield[x-1][y]; + } else { + hL = heightfield[x][y]; + } + float hR = heightfield[x+1][y]; + float hD = heightfield[x][y]; + float hU = heightfield[x][y-1]; + rVal = new Vector3f(hL - hR, 2.0f, hD - hU); + rVal.normalize(); + } + } else { + if(y / stride < actualHeight - 1){ + float hL = heightfield[x-1][y]; + float hR = heightfield[x][y]; + float hD = heightfield[x][y+1]; + float hU; + if(y > 0){ + hU = heightfield[x][y-1]; + } else { + hU = heightfield[x][y]; + } + rVal = new Vector3f(hL - hR, 2.0f, hD - hU); + rVal.normalize(); + } else { + float hL = heightfield[x-1][y]; + float hR = heightfield[x][y]; + float hD = heightfield[x][y]; + float hU = heightfield[x][y-1]; + rVal = new Vector3f(hL - hR, 2.0f, hD - hU); + rVal.normalize(); + } + } + return rVal; + } + +}