diff --git a/src/main/java/com/seibel/lod/builders/bufferBuilding/LodBufferBuilder.java b/src/main/java/com/seibel/lod/builders/bufferBuilding/LodBufferBuilder.java index cdf72c067..279b87909 100644 --- a/src/main/java/com/seibel/lod/builders/bufferBuilding/LodBufferBuilder.java +++ b/src/main/java/com/seibel/lod/builders/bufferBuilding/LodBufferBuilder.java @@ -360,6 +360,25 @@ public class LodBufferBuilder long data; for (int verticalIndex = 0; verticalIndex < lodDim.getMaxVerticalData(detailLevel, posX, posZ); verticalIndex++) { + if(verticalIndex > 0) + { + adjData.get(Direction.UP)[0] = lodDim.getData(detailLevel, posX, posZ, verticalIndex - 1); + } + else + { + adjData.get(Direction.UP)[0] = DataPointUtil.EMPTY_DATA; + } + + + if(verticalIndex < lodDim.getMaxVerticalData(detailLevel, posX, posZ) - 1) + { + adjData.get(Direction.DOWN)[0] = lodDim.getData(detailLevel, posX, posZ, verticalIndex + 1); + } + else + { + adjData.get(Direction.DOWN)[0] = DataPointUtil.EMPTY_DATA; + } + data = lodDim.getData(detailLevel, posX, posZ, verticalIndex); if (DataPointUtil.isVoid(data) || !DataPointUtil.doesItExist(data)) break; diff --git a/src/main/java/com/seibel/lod/builders/bufferBuilding/lodTemplates/Box.java b/src/main/java/com/seibel/lod/builders/bufferBuilding/lodTemplates/Box.java index 65fc50774..20753cf64 100644 --- a/src/main/java/com/seibel/lod/builders/bufferBuilding/lodTemplates/Box.java +++ b/src/main/java/com/seibel/lod/builders/bufferBuilding/lodTemplates/Box.java @@ -151,6 +151,8 @@ public class Box */ public final Map adjHeight; public final Map adjDepth; + public final Map skyLights; + public byte blockLight; /** Holds if the given direction should be culled or not */ public final boolean[] culling; @@ -163,7 +165,15 @@ public class Box boxWidth = new int[3]; colorMap = new int[6]; - + skyLights = new HashMap() + {{ + put(Direction.UP, new byte[1]); + put(Direction.DOWN, new byte[1]); + put(Direction.EAST, new byte[LodUtil.MAX_NUMBER_OF_VERTICAL_LODS]); + put(Direction.WEST, new byte[LodUtil.MAX_NUMBER_OF_VERTICAL_LODS]); + put(Direction.SOUTH, new byte[LodUtil.MAX_NUMBER_OF_VERTICAL_LODS]); + put(Direction.NORTH, new byte[LodUtil.MAX_NUMBER_OF_VERTICAL_LODS]); + }}; adjHeight = new HashMap() {{ put(Direction.EAST, new int[LodUtil.MAX_NUMBER_OF_VERTICAL_LODS]); @@ -182,6 +192,16 @@ public class Box culling = new boolean[6]; } + /** + * Set the light of the columns + * @param skyLight + * @param blockLight + */ + public void setLights(int skyLight, int blockLight) + { + this.blockLight = (byte) blockLight; + skyLights.get(Direction.UP)[0] = (byte) skyLight; + } /** * Set the color of the columns @@ -216,25 +236,36 @@ public class Box } } + /** + */ + public byte getSkyLight(Direction direction, int verticalIndex) + { + if(direction == Direction.UP || direction == Direction.DOWN) + return skyLights.get(direction)[0]; + else + return skyLights.get(direction)[verticalIndex]; + } + /** + */ + public int getBlockLight() + { + return blockLight; + } /** clears this box, resetting everything to default values */ public void reset() { Arrays.fill(boxWidth, 0); Arrays.fill(boxOffset, 0); Arrays.fill(colorMap, 0); - + blockLight = 0; for (Direction direction : ADJ_DIRECTIONS) { - // TODO wouldn't we want to set all adjHeightAndDepth - // to VOID_FACE regardless of the culled status? - if (isCulled(direction)) - continue; - for (int i = 0; i < adjHeight.get(direction).length; i++) { adjHeight.get(direction)[i] = VOID_FACE; adjDepth.get(direction)[i] = VOID_FACE; + skyLights.get(direction)[i] = 0; } } } @@ -242,8 +273,6 @@ public class Box /** determine which faces should be culled */ public void setUpCulling(int cullingDistance, BlockPos playerPos) { - //TODO is passing playerPos needed? - playerPos = MinecraftWrapper.INSTANCE.getPlayer().blockPosition(); for (Direction direction : DIRECTIONS) { if (direction == Direction.DOWN || direction == Direction.WEST || direction == Direction.NORTH) @@ -254,6 +283,7 @@ public class Box { culling[DIRECTION_INDEX.get(direction)] = playerPos.get(direction.getAxis()) < getFacePos(direction) - cullingDistance; } + culling[DIRECTION_INDEX.get(direction)] = false; } } @@ -277,10 +307,30 @@ public class Box int depth; int minY = getMinY(); int maxY = getMaxY(); + long singleAdjDataPoint; + + /* TODO implement attached vertical face culling + //Up direction case + if(DataPointUtil.doesItExist(adjData.get(Direction.UP))) + { + height = DataPointUtil.getHeight(singleAdjDataPoint); + depth = DataPointUtil.getDepth(singleAdjDataPoint); + }*/ + //Down direction case + singleAdjDataPoint = adjData.get(Direction.DOWN)[0]; + if(DataPointUtil.doesItExist(singleAdjDataPoint)) + { + skyLights.get(Direction.DOWN)[0] = (byte) DataPointUtil.getLightSky(singleAdjDataPoint); + + }else + { + skyLights.get(Direction.DOWN)[0] = skyLights.get(Direction.UP)[0]; + } for (Direction direction : ADJ_DIRECTIONS) { - //if (isCulled(direction)) - // continue; + singleAdjDataPoint = 0; + if (isCulled(direction)) + continue; long[] dataPoint = adjData.get(direction); if (dataPoint == null || DataPointUtil.isVoid(dataPoint[0])) @@ -296,8 +346,8 @@ public class Box int faceToDraw = 0; boolean firstFace = true; boolean toFinish = false; + int toFinishIndex = 0; boolean allAbove = true; - long singleAdjDataPoint; for (i = 0; i < dataPoint.length; i++) { singleAdjDataPoint = dataPoint[i]; @@ -319,10 +369,12 @@ public class Box { adjHeight.get(direction)[0] = getMaxY(); adjDepth.get(direction)[0] = getMinY(); + skyLights.get(direction)[0] = skyLights.get(Direction.UP)[0]; } else { adjDepth.get(direction)[faceToDraw] = getMinY(); + skyLights.get(direction)[faceToDraw] = (byte) 0; } faceToDraw++; toFinish = false; @@ -347,10 +399,12 @@ public class Box { adjHeight.get(direction)[0] = getMaxY(); adjDepth.get(direction)[0] = height; + skyLights.get(direction)[0] = skyLights.get(Direction.UP)[0]; } else { adjDepth.get(direction)[faceToDraw] = height; + skyLights.get(direction)[faceToDraw] = (byte) DataPointUtil.getLightSky(singleAdjDataPoint); } toFinish = false; faceToDraw++; @@ -361,8 +415,10 @@ public class Box // the adj data intersects the higher part of the current data // we start the creation of a new face adjHeight.get(direction)[faceToDraw] = depth; + //skyLights.get(direction)[faceToDraw] = (byte) DataPointUtil.getLightSky(singleAdjDataPoint); firstFace = false; toFinish = true; + toFinishIndex = i + 1; } else { @@ -375,10 +431,12 @@ public class Box } adjDepth.get(direction)[faceToDraw] = height; + skyLights.get(direction)[faceToDraw] = (byte) DataPointUtil.getLightSky(singleAdjDataPoint); faceToDraw++; adjHeight.get(direction)[faceToDraw] = depth; firstFace = false; toFinish = true; + toFinishIndex = i + 1; } } } @@ -387,11 +445,24 @@ public class Box { adjHeight.get(direction)[0] = getMaxY(); adjDepth.get(direction)[0] = getMinY(); + skyLights.get(direction)[0] = skyLights.get(Direction.UP)[0]; faceToDraw++; } else if (toFinish) { adjDepth.get(direction)[faceToDraw] = minY; + if(toFinishIndex < dataPoint.length) + { + singleAdjDataPoint = dataPoint[toFinishIndex]; + if (DataPointUtil.doesItExist(singleAdjDataPoint)) + { + skyLights.get(direction)[faceToDraw] = (byte) DataPointUtil.getLightSky(singleAdjDataPoint); + } + else + { + skyLights.get(direction)[faceToDraw] = skyLights.get(Direction.UP)[0]; + } + } faceToDraw++; } diff --git a/src/main/java/com/seibel/lod/builders/bufferBuilding/lodTemplates/CubicLodTemplate.java b/src/main/java/com/seibel/lod/builders/bufferBuilding/lodTemplates/CubicLodTemplate.java index a15344653..81faf157e 100644 --- a/src/main/java/com/seibel/lod/builders/bufferBuilding/lodTemplates/CubicLodTemplate.java +++ b/src/main/java/com/seibel/lod/builders/bufferBuilding/lodTemplates/CubicLodTemplate.java @@ -19,8 +19,12 @@ package com.seibel.lod.builders.bufferBuilding.lodTemplates; import com.seibel.lod.enums.DebugMode; +import com.seibel.lod.render.LodRenderer; +import com.seibel.lod.util.ColorUtil; import com.seibel.lod.util.DataPointUtil; import com.seibel.lod.util.LodUtil; +import com.seibel.lod.wrappers.MinecraftWrapper; +import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.texture.NativeImage; import net.minecraft.util.Direction; @@ -55,8 +59,7 @@ public class CubicLodTemplate extends AbstractLodTemplate if (debugging != DebugMode.OFF) color = LodUtil.DEBUG_DETAIL_LEVEL_COLORS[detailLevel].getRGB(); else - color = DataPointUtil.getLightColor(data, lightMap); - + color = DataPointUtil.getColor(data); generateBoundingBox( box, @@ -67,6 +70,8 @@ public class CubicLodTemplate extends AbstractLodTemplate bufferCenterBlockPos, adjData, color, + DataPointUtil.getLightSky(data), + DataPointUtil.getLightBlock(data), adjShadeDisabled); addBoundingBoxToBuffer(buffer, box); @@ -78,6 +83,8 @@ public class CubicLodTemplate extends AbstractLodTemplate BlockPos bufferCenterBlockPos, Map adjData, int color, + int skyLight, + int blockLight, boolean[] adjShadeDisabled) { // don't add an LOD if it is empty @@ -96,6 +103,7 @@ public class CubicLodTemplate extends AbstractLodTemplate double z = -bufferCenterBlockPos.getZ(); box.reset(); box.setColor(color, adjShadeDisabled); + box.setLights(skyLight, blockLight); box.setWidth(width, height - depth, width); box.setOffset((int) (xOffset + x), (int) (depth + yOffset), (int) (zOffset + z)); box.setUpCulling(32, bufferCenterBlockPos); @@ -104,21 +112,29 @@ public class CubicLodTemplate extends AbstractLodTemplate private void addBoundingBoxToBuffer(BufferBuilder buffer, Box box) { + int color; + int skyLight; + int blockLight; for (Direction direction : Box.DIRECTIONS) { - // TODO what does adjacentIndex mean? - int adjIndex = 0; - while (box.shouldRenderFace(direction, adjIndex)) + if(box.isCulled(direction)) + continue; + int verticalFaceIndex = 0; + while (box.shouldRenderFace(direction, verticalFaceIndex)) { for (int vertexIndex = 0; vertexIndex < 4; vertexIndex++) { + color = box.getColor(direction); + skyLight = box.getSkyLight(direction, verticalFaceIndex); + blockLight = box.getBlockLight(); + color = ColorUtil.applyLightValue(color, skyLight, blockLight, MinecraftWrapper.INSTANCE.getCurrentLightMap()); addPosAndColor(buffer, box.getX(direction, vertexIndex), - box.getY(direction, vertexIndex, adjIndex), + box.getY(direction, vertexIndex, verticalFaceIndex), box.getZ(direction, vertexIndex), - box.getColor(direction)); + color); } - adjIndex++; + verticalFaceIndex++; } } } diff --git a/src/main/java/com/seibel/lod/util/ColorUtil.java b/src/main/java/com/seibel/lod/util/ColorUtil.java index 2ddfdbaf9..015262cf9 100644 --- a/src/main/java/com/seibel/lod/util/ColorUtil.java +++ b/src/main/java/com/seibel/lod/util/ColorUtil.java @@ -1,5 +1,7 @@ package com.seibel.lod.util; +import net.minecraft.client.renderer.texture.NativeImage; + import java.awt.*; public class ColorUtil @@ -50,6 +52,17 @@ public class ColorUtil return (getAlpha(color) << 24) | ((int) Math.min(getRed(color) * shade, 255) << 16) | ((int) Math.min(getGreen(color) * shade, 255) << 8) | (int) Math.min(getBlue(color) * shade, 255); } + /** This method apply the lightmap to the color to use */ + public static int applyLightValue(int color, int skyLight, int blockLight, NativeImage lightMap) + { + int lightColor = lightMap.getPixelRGBA(blockLight, skyLight); + int red = ColorUtil.getBlue(lightColor); + int green = ColorUtil.getGreen(lightColor); + int blue = ColorUtil.getRed(lightColor); + + return ColorUtil.multiplyRGBcolors(color, ColorUtil.rgbToInt(red, green, blue)); + } + /** Edit the given color as an HSV (Hue Saturation Value) color */ public static int applySaturationAndBrightnessMultipliers(int color, float saturationMultiplier, float brightnessMultiplier) { diff --git a/src/main/java/com/seibel/lod/util/ThreadMapUtil.java b/src/main/java/com/seibel/lod/util/ThreadMapUtil.java index b8e389990..653caa7b8 100644 --- a/src/main/java/com/seibel/lod/util/ThreadMapUtil.java +++ b/src/main/java/com/seibel/lod/util/ThreadMapUtil.java @@ -56,10 +56,12 @@ public class ThreadMapUtil { if (!adjDataMap.containsKey(Thread.currentThread().getName()) || (adjDataMap.get(Thread.currentThread().getName()) == null) - || (adjDataMap.get(Thread.currentThread().getName()).get(Direction.UP) == null) - || (adjDataMap.get(Thread.currentThread().getName()).get(Direction.UP).length != verticalData)) + || (adjDataMap.get(Thread.currentThread().getName()).get(Direction.NORTH) == null) + || (adjDataMap.get(Thread.currentThread().getName()).get(Direction.NORTH).length != verticalData)) { adjDataMap.put(Thread.currentThread().getName(), new HashMap()); + adjDataMap.get(Thread.currentThread().getName()).put(Direction.UP, new long[1]); + adjDataMap.get(Thread.currentThread().getName()).put(Direction.DOWN, new long[1]); for (Direction direction : Box.ADJ_DIRECTIONS) adjDataMap.get(Thread.currentThread().getName()).put(direction, new long[verticalData]); }