diff --git a/src/main/java/com/seibel/lod/core/builders/bufferBuilding/CubicLodTemplate.java b/src/main/java/com/seibel/lod/core/builders/bufferBuilding/CubicLodTemplate.java index addfbb66c..b37de0fa1 100644 --- a/src/main/java/com/seibel/lod/core/builders/bufferBuilding/CubicLodTemplate.java +++ b/src/main/java/com/seibel/lod/core/builders/bufferBuilding/CubicLodTemplate.java @@ -41,8 +41,8 @@ public class CubicLodTemplate { private static final ILodConfigWrapperSingleton CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class); - public static void addLodToBuffer(long data, long topData, long botData, long[][][] adjData, byte detailLevel, - int offsetPosX, int offsetOosZ, LodQuadBuilder quadBuilder, DebugMode debugging) + public static void addLodToBuffer(long data, long topData, long botData, long[][][] adjData, + boolean[] adjFillBlack, byte detailLevel,int offsetPosX, int offsetOosZ, LodQuadBuilder quadBuilder, DebugMode debugging) { short width = (short) (1 << detailLevel); short x = (short) LevelPosUtil.convert(detailLevel, offsetPosX, LodUtil.BLOCK_DETAIL_LEVEL); @@ -83,6 +83,6 @@ public class CubicLodTemplate x, y, z, // setOffset color, // setColor DataPointUtil.getLightSky(data), DataPointUtil.getLightBlock(data), // setLights - topData, botData, adjData); // setAdjData + topData, botData, adjData, adjFillBlack); // setAdjData } } diff --git a/src/main/java/com/seibel/lod/core/objects/opengl/LodBox.java b/src/main/java/com/seibel/lod/core/objects/opengl/LodBox.java index 361a05e2f..4fde518cf 100644 --- a/src/main/java/com/seibel/lod/core/objects/opengl/LodBox.java +++ b/src/main/java/com/seibel/lod/core/objects/opengl/LodBox.java @@ -4,13 +4,15 @@ import com.seibel.lod.core.enums.LodDirection; import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler; import com.seibel.lod.core.util.ColorUtil; import com.seibel.lod.core.util.DataPointUtil; +import com.seibel.lod.core.util.LodUtil; import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper; public class LodBox { private static final IMinecraftClientWrapper MC = SingletonHandler.get(IMinecraftClientWrapper.class); public static void addBoxQuadsToBuilder(LodQuadBuilder builder, short xSize, short ySize, short zSize, short x, - short y, short z, int color, byte skyLight, byte blockLight, long topData, long botData, long[][][] adjData) + short y, short z, int color, byte skyLight, byte blockLight, long topData, long botData, long[][][] adjData, + boolean[] adjFillBlack) { short maxX = (short) (x + xSize); short maxY = (short) (y + ySize); @@ -32,71 +34,79 @@ public class LodBox { builder.addQuadDown(x, y, z, xSize, zSize, ColorUtil.applyShade(color, MC.getShade(LodDirection.DOWN)), skyLightBot, blockLight); //If the adj pos is at the same level we cull the faces normally, otherwise we divide the face in two and cull the two part separately - //NORTH face vertex creation - if (adjData[LodDirection.NORTH.ordinal() - 2] == null) { - builder.addQuadAdj(LodDirection.NORTH, x, y, z, xSize, ySize, ColorUtil.rgbToInt(0, 0, 0), (byte) 15, (byte) 15); - } else if (adjData[LodDirection.NORTH.ordinal() - 2].length == 1) + //NORTH face vertex creation { - makeAdjQuads(builder, adjData[LodDirection.NORTH.ordinal() - 2][0], LodDirection.NORTH, x, y, z, xSize, ySize, - color, skyLightTop, blockLight); - }else { - makeAdjQuads(builder, adjData[LodDirection.NORTH.ordinal() - 2][0], LodDirection.NORTH, x, y, z, (short) (xSize/2), ySize, - color, skyLightTop, blockLight); - makeAdjQuads(builder, adjData[LodDirection.NORTH.ordinal() - 2][1], LodDirection.NORTH, (short) (x+xSize/2), y, z, (short) (xSize/2), ySize, - color, skyLightTop, blockLight); + long[][] adjDataNorth = adjData[LodDirection.NORTH.ordinal() - 2]; + int adjOverlapNorth = adjFillBlack[LodDirection.NORTH.ordinal() - 2] ? ColorUtil.BLACK : ColorUtil.TRANSPARENT; + if (adjDataNorth == null) { + // builder.addQuadAdj(LodDirection.NORTH, x, y, z, xSize, ySize, ColorUtil.rgbToInt(0, 0, 0), (byte) 15, (byte) 15); + } else if (adjDataNorth.length == 1) { + makeAdjQuads(builder, adjDataNorth[0], LodDirection.NORTH, x, y, z, xSize, ySize, + color, adjOverlapNorth, skyLightTop, blockLight); + } else { + makeAdjQuads(builder, adjDataNorth[0], LodDirection.NORTH, x, y, z, (short) (xSize / 2), ySize, + color, adjOverlapNorth, skyLightTop, blockLight); + makeAdjQuads(builder, adjDataNorth[1], LodDirection.NORTH, (short) (x + xSize / 2), y, z, (short) (xSize / 2), ySize, + color, adjOverlapNorth, skyLightTop, blockLight); + } } //SOUTH face vertex creation - if (adjData[LodDirection.SOUTH.ordinal() - 2] == null) { - builder.addQuadAdj(LodDirection.SOUTH, x, y, maxZ, xSize, ySize, ColorUtil.rgbToInt(0, 0, 0), (byte) 15, (byte) 15); - } else if (adjData[LodDirection.SOUTH.ordinal() - 2].length == 1) { - makeAdjQuads(builder, adjData[LodDirection.SOUTH.ordinal() - 2][0], LodDirection.SOUTH, x, y, maxZ, xSize, ySize, - color, skyLightTop, blockLight); - }else { - makeAdjQuads(builder, adjData[LodDirection.SOUTH.ordinal() - 2][0], LodDirection.SOUTH, x, y, maxZ, (short) (xSize/2), ySize, - color, skyLightTop, blockLight); - - makeAdjQuads(builder, adjData[LodDirection.SOUTH.ordinal() - 2][1], LodDirection.SOUTH, (short) (x+xSize/2), y, maxZ, (short) (xSize/2), ySize, - color, skyLightTop, blockLight); + long[][] adjDataSouth = adjData[LodDirection.SOUTH.ordinal() - 2]; + int adjOverlapSouth = adjFillBlack[LodDirection.SOUTH.ordinal() - 2] ? ColorUtil.BLACK : ColorUtil.TRANSPARENT; + if (adjDataSouth == null) { + //builder.addQuadAdj(LodDirection.SOUTH, x, y, maxZ, xSize, ySize, ColorUtil.rgbToInt(0, 0, 0), (byte) 15, (byte) 15); + } else if (adjDataSouth.length == 1) { + makeAdjQuads(builder, adjDataSouth[0], LodDirection.SOUTH, x, y, maxZ, xSize, ySize, + color, adjOverlapSouth, skyLightTop, blockLight); + } else { + makeAdjQuads(builder, adjDataSouth[0], LodDirection.SOUTH, x, y, maxZ, (short) (xSize / 2), ySize, + color, adjOverlapSouth, skyLightTop, blockLight); + + makeAdjQuads(builder, adjDataSouth[1], LodDirection.SOUTH, (short) (x + xSize / 2), y, maxZ, (short) (xSize / 2), ySize, + color, adjOverlapSouth, skyLightTop, blockLight); + } } //WEST face vertex creation - - if (adjData[LodDirection.WEST.ordinal() - 2] == null) { - builder.addQuadAdj(LodDirection.WEST, x, y, z, zSize, ySize, ColorUtil.rgbToInt(0, 0, 0), (byte) 15, (byte) 15); - } else if (adjData[LodDirection.WEST.ordinal() - 2].length == 1) { - makeAdjQuads(builder, adjData[LodDirection.WEST.ordinal() - 2][0], LodDirection.WEST, x, y, z, zSize, ySize, color, - skyLightTop, blockLight); - }else { - makeAdjQuads(builder, adjData[LodDirection.WEST.ordinal() - 2][0], LodDirection.WEST, x, y, z, (short) (zSize/2), ySize, color, - skyLightTop, blockLight); - makeAdjQuads(builder, adjData[LodDirection.WEST.ordinal() - 2][1], LodDirection.WEST, x, y, (short) (z+zSize/2), (short) (zSize/2), ySize, color, - skyLightTop, blockLight); - + long[][] adjDataWest = adjData[LodDirection.WEST.ordinal() - 2]; + int adjOverlapWest = adjFillBlack[LodDirection.WEST.ordinal() - 2] ? ColorUtil.BLACK : ColorUtil.TRANSPARENT; + if (adjDataWest == null) { + //builder.addQuadAdj(LodDirection.WEST, x, y, z, zSize, ySize, ColorUtil.rgbToInt(0, 0, 0), (byte) 15, (byte) 15); + } else if (adjDataWest.length == 1) { + makeAdjQuads(builder, adjDataWest[0], LodDirection.WEST, x, y, z, zSize, ySize, + color, adjOverlapWest, skyLightTop, blockLight); + } else { + makeAdjQuads(builder, adjDataWest[0], LodDirection.WEST, x, y, z, (short) (zSize / 2), ySize, + color, adjOverlapWest, skyLightTop, blockLight); + makeAdjQuads(builder, adjDataWest[1], LodDirection.WEST, x, y, (short) (z + zSize / 2), (short) (zSize / 2), ySize, + color, adjOverlapWest, skyLightTop, blockLight); + } } //EAST face vertex creation - - if (adjData[LodDirection.EAST.ordinal() - 2] == null) { - builder.addQuadAdj(LodDirection.EAST, maxX, y, z, zSize, ySize, ColorUtil.rgbToInt(0, 0, 0), (byte) 15, (byte) 15); - } else if (adjData[LodDirection.EAST.ordinal() - 2].length == 1) { - makeAdjQuads(builder, adjData[LodDirection.EAST.ordinal() - 2][0], LodDirection.EAST, maxX, y, z, zSize, ySize, - color, skyLightTop, blockLight); - }else { - makeAdjQuads(builder, adjData[LodDirection.EAST.ordinal() - 2][0], LodDirection.EAST, maxX, y, z, (short) (zSize/2), ySize, - color, skyLightTop, blockLight); - makeAdjQuads(builder, adjData[LodDirection.EAST.ordinal() - 2][1], LodDirection.EAST, maxX, y, (short) (z+zSize/2), (short) (zSize/2), ySize, - color, skyLightTop, blockLight); - + long[][] adjDataEast = adjData[LodDirection.EAST.ordinal() - 2]; + int adjOverlapEast = adjFillBlack[LodDirection.EAST.ordinal() - 2] ? ColorUtil.BLACK : ColorUtil.TRANSPARENT; + if (adjData[LodDirection.EAST.ordinal() - 2] == null) { + //builder.addQuadAdj(LodDirection.EAST, maxX, y, z, zSize, ySize, ColorUtil.rgbToInt(0, 0, 0), (byte) 15, (byte) 15); + } else if (adjDataEast.length == 1) { + makeAdjQuads(builder, adjDataEast[0], LodDirection.EAST, maxX, y, z, zSize, ySize, + color, adjOverlapEast, skyLightTop, blockLight); + } else { + makeAdjQuads(builder, adjDataEast[0], LodDirection.EAST, maxX, y, z, (short) (zSize / 2), ySize, + color, adjOverlapEast, skyLightTop, blockLight); + makeAdjQuads(builder, adjDataEast[1], LodDirection.EAST, maxX, y, (short) (z + zSize / 2), (short) (zSize / 2), ySize, + color, adjOverlapEast, skyLightTop, blockLight); + } } } private static void makeAdjQuads(LodQuadBuilder builder, long[] adjData, LodDirection direction, short x, short y, - short z, short w0, short wy, int color, byte upSkyLight, byte blockLight) { + short z, short w0, short wy, int color, int overlapColor, byte upSkyLight, byte blockLight) { color = ColorUtil.applyShade(color, MC.getShade(direction)); long[] dataPoint = adjData; if (dataPoint == null || DataPointUtil.isVoid(dataPoint[0])) { @@ -107,7 +117,7 @@ public class LodBox { int i; boolean firstFace = true; boolean allAbove = true; - short nextStartingHeight = -1; + short previousDepth = -1; byte nextSkyLight = upSkyLight; // TODO transparency ocean floor fix @@ -139,11 +149,11 @@ public class LodBox { blockLight); } else { // Now: depth < height < y < previousDepth < maxY - if (nextStartingHeight == -1) + if (previousDepth == -1) throw new RuntimeException("Loop error"); - builder.addQuadAdj(direction, x, y, z, w0, (short) (nextStartingHeight - y), color, + builder.addQuadAdj(direction, x, y, z, w0, (short) (previousDepth - y), color, DataPointUtil.getLightSky(adjPoint), blockLight); - nextStartingHeight = -1; + previousDepth = -1; } break; } @@ -152,24 +162,32 @@ public class LodBox { if (y + wy <= height) { // Basically: ________ y < maxY <= height // _______&&: depth <= y < maxY - // The face is inside adj face completely. Don't draw. + // The face is inside adj face completely. + if (overlapColor != 0) { + builder.addQuadAdj(direction, x, y, z, w0, wy, overlapColor, (byte) 15, (byte) 15); + } break; } // Otherwise: ________ y <= Height < maxY // _______&&: depth <= y _________ < maxY // the adj data intersects the lower part of the current data + if (height > y && overlapColor != 0) { + builder.addQuadAdj(direction, x, y, z, w0, (short) (height-y), overlapColor, (byte) 15, (byte) 15); + } // if this is the only face, use the maxY and break, // if there was another face we finish the last one and break if (firstFace) { builder.addQuadAdj(direction, x, height, z, w0, (short) (y + wy - height), color, DataPointUtil.getLightSky(adjPoint), blockLight); } else { - // Now: depth <= y <= height < previousDepth < maxY - if (nextStartingHeight == -1) + // Now: depth <= y <= height <= previousDepth < maxY + if (previousDepth == -1) throw new RuntimeException("Loop error"); - builder.addQuadAdj(direction, x, height, z, w0, (short) (nextStartingHeight - height), color, - DataPointUtil.getLightSky(adjPoint), blockLight); - nextStartingHeight = -1; + if (previousDepth > height) { + builder.addQuadAdj(direction, x, height, z, w0, (short) (previousDepth - height), color, + DataPointUtil.getLightSky(adjPoint), blockLight); + } + previousDepth = -1; } break; } @@ -181,24 +199,32 @@ public class LodBox { // Basically: y _______ < maxY <= height // _______&&: y < depth < maxY // the adj data intersects the higher part of the current data + if (overlapColor != 0) { + builder.addQuadAdj(direction, x, depth, z, w0, (short) (y+wy-depth), overlapColor, (byte) 15, (byte) 15); + } // we start the creation of a new face } else { // Otherwise: y < _____ height < maxY // _______&&: y < depth ______ < maxY + if (overlapColor != 0) { + builder.addQuadAdj(direction, x, depth, z, w0, (short) (height-depth), overlapColor, (byte) 15, (byte) 15); + } if (firstFace) { builder.addQuadAdj(direction, x, height, z, w0, (short) (y + wy - height), color, DataPointUtil.getLightSky(adjPoint), blockLight); } else { - // Now: y < depth < height < previousDepth < maxY - if (nextStartingHeight == -1) + // Now: y < depth < height <= previousDepth < maxY + if (previousDepth == -1) throw new RuntimeException("Loop error"); - builder.addQuadAdj(direction, x, height, z, w0, (short) (nextStartingHeight - height), color, - DataPointUtil.getLightSky(adjPoint), blockLight); - nextStartingHeight = -1; + if (previousDepth > height) { + builder.addQuadAdj(direction, x, height, z, w0, (short) (previousDepth - height), color, + DataPointUtil.getLightSky(adjPoint), blockLight); + } + previousDepth = -1; } } // set next top as current depth - nextStartingHeight = depth; + previousDepth = depth; firstFace = false; nextSkyLight = upSkyLight; if (i + 1 < adjData.length && DataPointUtil.doesItExist(adjData[i + 1])) @@ -207,11 +233,10 @@ public class LodBox { if (allAbove) { builder.addQuadAdj(direction, x, y, z, w0, wy, color, upSkyLight, blockLight); - } else if (nextStartingHeight != -1) { + } else if (previousDepth != -1) { // We need to finish the last quad. - builder.addQuadAdj(direction, x, y, z, w0, (short) (nextStartingHeight - y), color, nextSkyLight, + builder.addQuadAdj(direction, x, y, z, w0, (short) (previousDepth - y), color, nextSkyLight, blockLight); } } - } diff --git a/src/main/java/com/seibel/lod/core/objects/opengl/LodQuadBuilder.java b/src/main/java/com/seibel/lod/core/objects/opengl/LodQuadBuilder.java index cbb6df6d2..995af90bc 100644 --- a/src/main/java/com/seibel/lod/core/objects/opengl/LodQuadBuilder.java +++ b/src/main/java/com/seibel/lod/core/objects/opengl/LodQuadBuilder.java @@ -39,6 +39,8 @@ public class LodQuadBuilder { Quad(short x, short y, short z, short w0, short w1, int color, byte skylight, byte blocklight, LodDirection dir) { + if (w0 == 0 || w1 == 0) throw new IllegalArgumentException("Size 0 quad!"); + if (w0 < 0 || w1 < 0) throw new IllegalArgumentException("Negative sized quad!"); this.x = x; this.y = y; this.z = z; @@ -373,7 +375,6 @@ public class LodQuadBuilder { long mergeCount = 0; long preQuadsCount = getCurrentQuadsCount(); if (preQuadsCount<=1) return; - long skipperMerge = 0; for (int i=0; i<6; i++) { mergeCount += mergeQuadsPass1(i); if (i>=2) { @@ -387,8 +388,8 @@ public class LodQuadBuilder { } } long postQuadsCount = getCurrentQuadsCount(); - //if (mergeCount != 0) - // ApiShared.LOGGER.info("Merged {}/{}({}) quads, skip {}", mergeCount, preQuadsCount, mergeCount/(double)preQuadsCount, skipperMerge); + if (mergeCount != 0) + ApiShared.LOGGER.info("Merged {}/{}({}) quads", mergeCount, preQuadsCount, mergeCount/(double)preQuadsCount); } public Iterator makeVertexBuffers() { diff --git a/src/main/java/com/seibel/lod/core/objects/opengl/RenderRegion.java b/src/main/java/com/seibel/lod/core/objects/opengl/RenderRegion.java index 118903417..bdf3d04fd 100644 --- a/src/main/java/com/seibel/lod/core/objects/opengl/RenderRegion.java +++ b/src/main/java/com/seibel/lod/core/objects/opengl/RenderRegion.java @@ -283,6 +283,7 @@ public class RenderRegion implements AutoCloseable continue; long[][][] adjData = new long[4][][]; + boolean[] adjUseBlack = new boolean[4]; // We extract the adj data in the four cardinal direction @@ -305,7 +306,9 @@ public class RenderRegion implements AutoCloseable int zAdj = posZ + lodDirection.getNormal().z; int chunkXAdj = LevelPosUtil.getChunkPos(detailLevel, xAdj); int chunkZAdj = LevelPosUtil.getChunkPos(detailLevel, zAdj); - if (chunkGrid.get(chunkXAdj, chunkZAdj)!=null) continue; + if (chunkGrid.get(chunkXAdj, chunkZAdj)!=null) { + adjUseBlack[lodDirection.ordinal()-2] = true; + } boolean isCrossRegionBoundary = LevelPosUtil.getRegion(detailLevel, xAdj) != region.regionPosX || LevelPosUtil.getRegion(detailLevel, zAdj) != region.regionPosZ; @@ -370,7 +373,7 @@ public class RenderRegion implements AutoCloseable long adjDataBot = i + 1 < posData.length ? posData[i + 1] : DataPointUtil.EMPTY_DATA; // We send the call to create the vertices - CubicLodTemplate.addLodToBuffer(data, adjDataTop, adjDataBot, adjData, detailLevel, + CubicLodTemplate.addLodToBuffer(data, adjDataTop, adjDataBot, adjData, adjUseBlack, detailLevel, LevelPosUtil.getRegionModule(detailLevel, posX), LevelPosUtil.getRegionModule(detailLevel, posZ), quadBuilder, debugMode); } diff --git a/src/main/java/com/seibel/lod/core/util/ColorUtil.java b/src/main/java/com/seibel/lod/core/util/ColorUtil.java index fd509b13a..0333dd145 100644 --- a/src/main/java/com/seibel/lod/core/util/ColorUtil.java +++ b/src/main/java/com/seibel/lod/core/util/ColorUtil.java @@ -34,6 +34,10 @@ public class ColorUtil //________ DH mod color format is: 0xAA RR GG BB //OpenGL RGBA format native order: 0xRR GG BB AA //_ OpenGL RGBA format Java Order: 0xAA BB GG RR + + public static final int BLACK = rgbToInt(0,0,0); + public static final int WHITE = rgbToInt(255,255,255); + public static final int TRANSPARENT = rgbToInt(0, 0, 0, 0); private static final IMinecraftClientWrapper MC = SingletonHandler.get(IMinecraftClientWrapper.class);