diff --git a/src/main/java/backsun/lod/proxy/ClientProxy.java b/src/main/java/backsun/lod/proxy/ClientProxy.java index 3d1dd62e5..859c14a60 100644 --- a/src/main/java/backsun/lod/proxy/ClientProxy.java +++ b/src/main/java/backsun/lod/proxy/ClientProxy.java @@ -4,8 +4,13 @@ import backsun.lod.renderer.CustomRenderer; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.block.model.ModelResourceLocation; import net.minecraft.item.Item; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.chunk.Chunk; +import net.minecraftforge.client.event.FOVUpdateEvent; import net.minecraftforge.client.event.RenderWorldLastEvent; import net.minecraftforge.client.model.ModelLoader; +import net.minecraftforge.event.world.ChunkEvent; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; public class ClientProxy extends CommonProxy @@ -28,4 +33,38 @@ public class ClientProxy extends CommonProxy { renderer.drawTest(Minecraft.getMinecraft(), event.getPartialTicks()); } + + @SubscribeEvent + public void fovUpdateEvent(FOVUpdateEvent event) + { + renderer.updateFOVModifier(event.getNewfov()); + } + + @SubscribeEvent + public void chunkLoadEvent(ChunkEvent event) + { + Chunk ch = event.getChunk(); + Minecraft mc = Minecraft.getMinecraft(); + if(renderer != null && ch != null && renderer.biomes != null && mc.world != null && mc.world.getBiomeProvider() != null) + { + try + { + if(renderer.distanceToPlayer(ch.x * 16, 70, ch.z * 16, mc.player.posX, 70, mc.player.posZ) > mc.gameSettings.renderDistanceChunks * 16 * 2) + { + int biome = Biome.getIdForBiome(ch.getBiome(new BlockPos(ch.x, 70, ch.z), mc.world.getBiomeProvider())); + renderer.biomes[ch.x+32][ch.z+32] = biome; + System.out.println(renderer.biomes[ch.x+32][ch.z+32]); + } + else + { + renderer.biomes[ch.x+32][ch.z+32] = -1; + } + } + catch(IndexOutOfBoundsException e) + { + + } + + } + } } diff --git a/src/main/java/backsun/lod/renderer/CustomRenderer.java b/src/main/java/backsun/lod/renderer/CustomRenderer.java index 3a51d2ea0..ca2be5c94 100644 --- a/src/main/java/backsun/lod/renderer/CustomRenderer.java +++ b/src/main/java/backsun/lod/renderer/CustomRenderer.java @@ -17,6 +17,7 @@ import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.world.biome.Biome; /** * @@ -29,13 +30,18 @@ public class CustomRenderer private float farPlaneDistance; private Tessellator tessellator; - private BufferBuilder worldRenderer; + private BufferBuilder bufferBuilder; // make sure this is an even number, or else it won't align with the chunk grid - public final int viewDistanceMultiplier = 12; + public final int viewDistanceMultiplier = 12;//12; private float fovModifierHandPrev; private float fovModifierHand; - public boolean debugging = false; + private float fovModifier = 1.1f; + private float fov = 70 * 1.1f; + + public int biomes[][]; + + public boolean debugging = true; /** * constructor @@ -45,7 +51,17 @@ public class CustomRenderer mc = Minecraft.getMinecraft(); tessellator = Tessellator.getInstance(); - worldRenderer = tessellator.getBuffer(); + bufferBuilder = tessellator.getBuffer(); + + biomes = new int[64][64]; + + for(int i = 0; i < 64; i++) + { + for(int j = 0; j < 64; j++) + { + biomes[i][j] = -1; + } + } // GL11.GL_MODELVIEW //5888 // GL11.GL_PROJECTION //5889 @@ -57,13 +73,10 @@ public class CustomRenderer */ private void setProjectionMatrix(float partialTicks) { - // update the fov - float fov = getFOVModifier(partialTicks, true); - // create a new view frustum so that the squares can be drawn outside the normal view distance GlStateManager.matrixMode(GL11.GL_PROJECTION); GlStateManager.loadIdentity(); - // farPlaneDistance // 10 chunks = 160 + // farPlaneDistance // 10 chunks = 160 0.0125f Project.gluPerspective(fov, (float) mc.displayWidth / (float) mc.displayHeight, 0.0125f, farPlaneDistance * viewDistanceMultiplier); } @@ -74,16 +87,20 @@ public class CustomRenderer */ public void drawTest(Minecraft mc, float partialTicks) { + // used for debugging and viewing how long different processes take + mc.world.profiler.startSection("LOD setup"); + + long startTime = System.nanoTime(); + + // determine how far the game's render distance is currently set farPlaneDistance = mc.gameSettings.renderDistanceChunks * 16; - setupFog(); + // enable the fog +// setupFog(); // set the new model view matrix setProjectionMatrix(partialTicks); - // used for debugging - mc.world.profiler.startSection("lod setup"); - // set the required open GL settings GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); GL11.glLineWidth(2.0f); @@ -96,22 +113,36 @@ public class CustomRenderer // get the camera location Entity entity = mc.player; - double x = entity.lastTickPosX + (entity.posX - entity.lastTickPosX) * partialTicks; - double y = entity.lastTickPosY + (entity.posY - entity.lastTickPosY) * partialTicks; - double z = entity.lastTickPosZ + (entity.posZ - entity.lastTickPosZ) * partialTicks; + double cameraX = entity.lastTickPosX + (entity.posX - entity.lastTickPosX) * partialTicks; + double cameraY = entity.lastTickPosY + (entity.posY - entity.lastTickPosY) * partialTicks; + double cameraZ = entity.lastTickPosZ + (entity.posZ - entity.lastTickPosZ) * partialTicks; - int playerXChunkOffset = ((int) x / 16) * 16; - int playerZChunkOffset = ((int) z / 16) * 16; + int playerXChunkOffset = ((int) cameraX / 16) * 16; + int playerZChunkOffset = ((int) cameraZ / 16) * 16; - Color grass = new Color(80, 104, 50, 255); +// System.out.println(mc.world.getBiome(new BlockPos(cameraX, cameraY, cameraZ))); + + + int alpha = 255; + Color error = new Color(255, 0, 225, alpha); // bright pink + Color grass = new Color(80, 104, 50, alpha); + Color water = new Color(37, 51, 174, alpha); + Color swamp = new Color(60, 63, 32, alpha); + Color mountain = new Color(100, 100, 100, alpha); + + Color red = Color.RED; Color black = Color.BLACK; Color white = Color.WHITE; + Color invisible = new Color(0,0,0,0); + + + // set how big the squares will be and how far they will go int totalLength = (int) farPlaneDistance * viewDistanceMultiplier; int squareSideLength = 16; - int numbOfBoxesWide = totalLength / squareSideLength; - //TODO start distance is about 2 * farPlaneDistance + int numbOfBoxesWide = (totalLength / squareSideLength); + //XXX start distance is about 2 * farPlaneDistance // size of a single square int bbx = squareSideLength; @@ -137,7 +168,12 @@ public class CustomRenderer if (debugging && numbOfBoxesWide % 2 == 0) evenWidth = true; - mc.world.profiler.endStartSection("lod setup"); + + + + + + mc.world.profiler.endStartSection("LOD generation"); // x axis for (int i = 0; i < numbOfBoxesWide; i++) @@ -150,41 +186,143 @@ public class CustomRenderer for (int j = 0; j < numbOfBoxesWide; j++) { // update where this square will be drawn - double xoffset = -x + (squareSideLength * i) + startX; - double yoffset = -y; - double zoffset = -z + (squareSideLength * j) + startZ; + double xoffset = -cameraX + // start at x = 0 + (squareSideLength * i) + // offset by the number of LOD blocks + startX; // offset so the center LOD block is underneath the player + double zoffset = -cameraZ + (squareSideLength * j) + startZ; + + + int chunkX = ((squareSideLength * j) + startX) / 16; + int chunkZ = ((squareSideLength * i) + startZ) / 16; + + +// if (distanceToPlayer(chunkX * 16, 70, chunkZ * 16, cameraX, 70, cameraZ) < farPlaneDistance * 2) +// { +// // near to player +// c = black; +// } +// else +// { +// // far from player +// c = white; +//// System.out.println("loading"); +//// mc.world.getChunkProvider().loadChunk(chunkX, chunkZ); +// } + + Color c; + Biome biome = null; + try + { + biome = Biome.getBiome(biomes[chunkX+32][chunkZ+32]); + } + catch(IndexOutOfBoundsException e) + { + c = white; + } + + double yoffset = -cameraY + mc.world.provider.getAverageGroundLevel(); + + +// if (i == (numbOfBoxesWide / 2) && j == i) +// System.out.println("\nx " + (int)cameraX + " z " + (int)cameraZ + "\nx " + chunkX * 16 + " z " + chunkZ * 16 + "\t" + biome.getBiomeName()); + + + // TODO fix this so that chunks outside of the view distance are loaded and the biomes are read + // TODO fix so that the chunks within view distance aren't always plains + if(biome != null) + { + // add the color + switch (Biome.getIdForBiome(biome)) + { + case -1: // unloaded + c = red; + break; + case 0: // ocean + c = water; + break; + case 24: // deep ocean + c = water; + break; + case 7: // river + c = water; + break; + case 1: // plains +// c = invisible; + c = grass; + break; + case 6: // swamp + c = swamp; + break; + case 3: //extreme hills + c = mountain; + break; + case 34: // extreme hills with trees + c = mountain; + break; + default: + c = error; + break; + } + } + else + { + c = black; + } + + + + // if debugging draw the squares as a black and white checker board +// if (debugging) +// { +// if (alternateColor) +// c = white; +// else +// c = black; +// // draw the first square as red +// if (i == 0 && j == 0) +// c = Color.RED; +// +// colorArray[i + (j * numbOfBoxesWide)] = c; +// +// alternateColor = !alternateColor; +// } + + // add the color to the array + colorArray[i + (j * numbOfBoxesWide)] = c; // add the new box to the array lodArray[i + (j * numbOfBoxesWide)] = new AxisAlignedBB(bbx, bby, bbz, 0, bby, 0).offset(xoffset, yoffset, zoffset); - colorArray[i + (j * numbOfBoxesWide)] = grass; - // if debugging draw the squares as a black and white checker board - if (debugging) - { - Color c; - if (alternateColor) - c = white; - else - c = black; - // draw the first square as red - if (i == 0 && j == 0) - c = Color.RED; - - colorArray[i + (j * numbOfBoxesWide)] = c; - - alternateColor = !alternateColor; - } + } } - mc.world.profiler.endStartSection("lod pre draw"); + + + + mc.world.profiler.endStartSection("LOD pre draw"); + + // send the LODs over to the GPU + sendDataToGPU(lodArray, colorArray); + + + + + + mc.world.profiler.endStartSection("LOD draw"); // draw the LODs - drawBoxArray(lodArray, colorArray); + tessellator.draw(); + + + + + + + + mc.world.profiler.endStartSection("LOD cleanup"); - // end the profile section (so we can see how long it took to draw the LODs) - mc.world.profiler.endSection(); // this must be done otherwise other parts of the screen may be drawn with a fog effect // IE the GUI @@ -198,54 +336,36 @@ public class CustomRenderer GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_FILL); GL11.glEnable(GL11.GL_CULL_FACE); GL11.glEnable(GL11.GL_TEXTURE_2D); + + + // 7 - 5 ms + // 16 ms = 60 hz + long endTime = System.nanoTime(); +// System.out.println((endTime - startTime) + " :ns"); + + // end of profiler tracking + mc.world.profiler.endSection(); } - private void VBO() + + public double distanceToPlayer(int x, int y, int z, double cameraX, double cameraY, double cameraZ) { -// this.vboEnabled = OpenGlHelper.useVbo(); -// this.vertexBufferFormat = new VertexFormat(); -// this.vertexBufferFormat.addElement(new VertexFormatElement(0, VertexFormatElement.EnumType.FLOAT, VertexFormatElement.EnumUsage.POSITION, 3)); -// -// if (this.skyVBO != null) -// { -// this.skyVBO.deleteGlBuffers(); -// } -// if (this.vboEnabled) -// { -// starVBO = new VertexBuffer(this.vertexBufferFormat); -// this.renderStars(bufferbuilder); -// bufferbuilder.finishDrawing(); -// bufferbuilder.reset(); -// this.starVBO.bufferData(bufferbuilder.getByteBuffer()); -// } -// -// -// this.skyVBO.bindBuffer(); -// GlStateManager.glEnableClientState(32884); -// GlStateManager.glVertexPointer(3, 5126, 12, 0); -// this.skyVBO.drawArrays(7); -// this.skyVBO.unbindBuffer(); -// GlStateManager.glDisableClientState(32884); -// -// -// //rendersky -// bufferBuilderIn.begin(7, DefaultVertexFormats.POSITION); -// bufferBuilderIn.pos((double) f, (double) posY, (double) l).endVertex(); + if(cameraY == y) + return Math.sqrt(Math.pow((x - cameraX),2) + Math.pow((z - cameraZ),2)); + + return Math.sqrt(Math.pow((x - cameraX),2) + Math.pow((y - cameraY),2) + Math.pow((z - cameraZ),2)); } /** - * TODO improve this method's speed - * * draw an array of cubes (or squares) with the given colors - * @param bb the cube to draw - * @param red - * @param green - * @param blue - * @param alpha + * + * @param bbArray + * @param colorArray */ - private void drawBoxArray(AxisAlignedBB[] bbArray, Color[] colorArray) + private void sendDataToGPU(AxisAlignedBB[] bbArray, Color[] colorArray) { - worldRenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR); + bufferBuilder.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR); + int red; int green; @@ -256,73 +376,76 @@ public class CustomRenderer int colorIndex = 0; for (AxisAlignedBB bb : bbArray) { + // get the color of this LOD object red = colorArray[colorIndex].getRed(); green = colorArray[colorIndex].getGreen(); blue = colorArray[colorIndex].getBlue(); alpha = colorArray[colorIndex].getAlpha(); - // TODO which side is this? - worldRenderer.pos(bb.minX, bb.minY, bb.minZ).color(red, green, blue, alpha).endVertex(); - worldRenderer.pos(bb.maxX, bb.minY, bb.minZ).color(red, green, blue, alpha).endVertex(); - worldRenderer.pos(bb.maxX, bb.minY, bb.maxZ).color(red, green, blue, alpha).endVertex(); - worldRenderer.pos(bb.minX, bb.minY, bb.maxZ).color(red, green, blue, alpha).endVertex(); + bufferBuilder.pos(bb.minX, bb.minY, bb.minZ).color(red, green, blue, alpha).endVertex(); + bufferBuilder.pos(bb.maxX, bb.minY, bb.minZ).color(red, green, blue, alpha).endVertex(); + bufferBuilder.pos(bb.maxX, bb.minY, bb.maxZ).color(red, green, blue, alpha).endVertex(); + bufferBuilder.pos(bb.minX, bb.minY, bb.maxZ).color(red, green, blue, alpha).endVertex(); // only draw the other 5 sides if there is some thickness to this box if (bb.minY != bb.maxY) { - worldRenderer.pos(bb.minX, bb.maxY, bb.minZ).color(red, green, blue, alpha).endVertex(); - worldRenderer.pos(bb.maxX, bb.maxY, bb.minZ).color(red, green, blue, alpha).endVertex(); - worldRenderer.pos(bb.maxX, bb.maxY, bb.maxZ).color(red, green, blue, alpha).endVertex(); - worldRenderer.pos(bb.minX, bb.maxY, bb.maxZ).color(red, green, blue, alpha).endVertex(); + bufferBuilder.pos(bb.minX, bb.maxY, bb.minZ).color(red, green, blue, alpha).endVertex(); + bufferBuilder.pos(bb.maxX, bb.maxY, bb.minZ).color(red, green, blue, alpha).endVertex(); + bufferBuilder.pos(bb.maxX, bb.maxY, bb.maxZ).color(red, green, blue, alpha).endVertex(); + bufferBuilder.pos(bb.minX, bb.maxY, bb.maxZ).color(red, green, blue, alpha).endVertex(); - worldRenderer.pos(bb.minX, bb.minY, bb.maxZ).color(red, green, blue, alpha).endVertex(); - worldRenderer.pos(bb.minX, bb.maxY, bb.maxZ).color(red, green, blue, alpha).endVertex(); - worldRenderer.pos(bb.maxX, bb.maxY, bb.maxZ).color(red, green, blue, alpha).endVertex(); - worldRenderer.pos(bb.maxX, bb.minY, bb.maxZ).color(red, green, blue, alpha).endVertex(); + bufferBuilder.pos(bb.minX, bb.minY, bb.maxZ).color(red, green, blue, alpha).endVertex(); + bufferBuilder.pos(bb.minX, bb.maxY, bb.maxZ).color(red, green, blue, alpha).endVertex(); + bufferBuilder.pos(bb.maxX, bb.maxY, bb.maxZ).color(red, green, blue, alpha).endVertex(); + bufferBuilder.pos(bb.maxX, bb.minY, bb.maxZ).color(red, green, blue, alpha).endVertex(); - worldRenderer.pos(bb.minX, bb.minY, bb.minZ).color(red, green, blue, alpha).endVertex(); - worldRenderer.pos(bb.minX, bb.maxY, bb.minZ).color(red, green, blue, alpha).endVertex(); - worldRenderer.pos(bb.maxX, bb.maxY, bb.minZ).color(red, green, blue, alpha).endVertex(); - worldRenderer.pos(bb.maxX, bb.minY, bb.minZ).color(red, green, blue, alpha).endVertex(); + bufferBuilder.pos(bb.minX, bb.minY, bb.minZ).color(red, green, blue, alpha).endVertex(); + bufferBuilder.pos(bb.minX, bb.maxY, bb.minZ).color(red, green, blue, alpha).endVertex(); + bufferBuilder.pos(bb.maxX, bb.maxY, bb.minZ).color(red, green, blue, alpha).endVertex(); + bufferBuilder.pos(bb.maxX, bb.minY, bb.minZ).color(red, green, blue, alpha).endVertex(); - worldRenderer.pos(bb.minX, bb.minY, bb.minZ).color(red, green, blue, alpha).endVertex(); - worldRenderer.pos(bb.minX, bb.minY, bb.maxZ).color(red, green, blue, alpha).endVertex(); - worldRenderer.pos(bb.minX, bb.maxY, bb.maxZ).color(red, green, blue, alpha).endVertex(); - worldRenderer.pos(bb.minX, bb.maxY, bb.minZ).color(red, green, blue, alpha).endVertex(); + bufferBuilder.pos(bb.minX, bb.minY, bb.minZ).color(red, green, blue, alpha).endVertex(); + bufferBuilder.pos(bb.minX, bb.minY, bb.maxZ).color(red, green, blue, alpha).endVertex(); + bufferBuilder.pos(bb.minX, bb.maxY, bb.maxZ).color(red, green, blue, alpha).endVertex(); + bufferBuilder.pos(bb.minX, bb.maxY, bb.minZ).color(red, green, blue, alpha).endVertex(); - worldRenderer.pos(bb.maxX, bb.minY, bb.minZ).color(red, green, blue, alpha).endVertex(); - worldRenderer.pos(bb.maxX, bb.minY, bb.maxZ).color(red, green, blue, alpha).endVertex(); - worldRenderer.pos(bb.maxX, bb.maxY, bb.maxZ).color(red, green, blue, alpha).endVertex(); - worldRenderer.pos(bb.maxX, bb.maxY, bb.minZ).color(red, green, blue, alpha).endVertex(); + bufferBuilder.pos(bb.maxX, bb.minY, bb.minZ).color(red, green, blue, alpha).endVertex(); + bufferBuilder.pos(bb.maxX, bb.minY, bb.maxZ).color(red, green, blue, alpha).endVertex(); + bufferBuilder.pos(bb.maxX, bb.maxY, bb.maxZ).color(red, green, blue, alpha).endVertex(); + bufferBuilder.pos(bb.maxX, bb.maxY, bb.minZ).color(red, green, blue, alpha).endVertex(); } // so we can get the next color colorIndex++; } - - mc.world.profiler.endStartSection("lod draw"); - - tessellator.draw(); } + /** * Sets up and enables the fog to be rendered. */ private void setupFog() { - float f = farPlaneDistance * (viewDistanceMultiplier * 0.5f); GlStateManager.setFogDensity(0.1f); - GlStateManager.setFogStart(farPlaneDistance * (viewDistanceMultiplier * 0.25f)); - GlStateManager.setFogEnd(f); + // near fog + GlStateManager.setFogEnd(farPlaneDistance * 2.0f); + GlStateManager.setFogStart(farPlaneDistance * 2.25f); + + // far fog +// GlStateManager.setFogStart(farPlaneDistance * (viewDistanceMultiplier * 0.25f)); +// GlStateManager.setFogEnd(farPlaneDistance * (viewDistanceMultiplier * 0.5f)); GlStateManager.enableFog(); } /** + * possible replacement : mc.gameSettings.fovSetting * fovModifier; + * * Originally from Minecraft's EntityRenderer * Changes the field of view of the player depending on if they are underwater or not */ - public float getFOVModifier(float partialTicks, boolean useFOVSetting) + public float getFOV(float partialTicks, boolean useFOVSetting) { Entity entity = mc.getRenderViewEntity(); float f = 70.0F; @@ -378,4 +501,19 @@ public class CustomRenderer fovModifierHand = 0.1F; } } + + + /** + * + * @param newfov + */ + public void updateFOVModifier(float newFov) + { + fovModifier = newFov; + + // update the fov + fov = mc.gameSettings.fovSetting * fovModifier;//getFOV(partialTicks, true); + } + + } \ No newline at end of file diff --git a/src/main/java/net/minecraft/client/renderer/EntityRenderer.java b/src/main/java/net/minecraft/client/renderer/EntityRenderer.java index abf096885..37ad82d8d 100644 --- a/src/main/java/net/minecraft/client/renderer/EntityRenderer.java +++ b/src/main/java/net/minecraft/client/renderer/EntityRenderer.java @@ -723,13 +723,12 @@ public class EntityRenderer implements IResourceManagerReloadListener { GlStateManager.translate((-(pass * 2 - 1)) * 0.07F, 0.0F, 0.0F); } - - // should never be called -// if (this.cameraZoom != 1.0D) -// { -// GlStateManager.translate((float)this.cameraYaw, (float)(-this.cameraPitch), 0.0F); -// GlStateManager.scale(this.cameraZoom, this.cameraZoom, 1.0D); -// } + + if (this.cameraZoom != 1.0D) + { + GlStateManager.translate((float) this.cameraYaw, (float) (-this.cameraPitch), 0.0F); + GlStateManager.scale(this.cameraZoom, this.cameraZoom, 1.0D); + } float fov = mc.entityRenderer.getFOVModifier(partialTicks, true); // System.out.println("ER: " + fov + "\t\t pt: " + partialTicks);