diff --git a/src/main/java/com/jozufozu/flywheel/FlywheelClient.java b/src/main/java/com/jozufozu/flywheel/FlywheelClient.java index 8e08e111c..9cf2e6f79 100644 --- a/src/main/java/com/jozufozu/flywheel/FlywheelClient.java +++ b/src/main/java/com/jozufozu/flywheel/FlywheelClient.java @@ -5,7 +5,6 @@ import com.jozufozu.flywheel.core.AtlasStitcher; import com.jozufozu.flywheel.core.Contexts; import com.jozufozu.flywheel.core.Materials; import com.jozufozu.flywheel.core.PartialModel; -import com.jozufozu.flywheel.light.debug.DebugView; import com.jozufozu.flywheel.vanilla.VanillaInstances; import net.minecraftforge.eventbus.api.IEventBus; diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/AbstractInstance.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/AbstractInstance.java index 8c985b56b..766d63c32 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/AbstractInstance.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/AbstractInstance.java @@ -10,6 +10,7 @@ import com.jozufozu.flywheel.light.GridAlignedBB; import com.jozufozu.flywheel.light.ILightUpdateListener; import com.jozufozu.flywheel.light.LightProvider; import com.jozufozu.flywheel.light.ListenerStatus; +import com.jozufozu.flywheel.light.ReadOnlyBox; import net.minecraft.util.math.BlockPos; import net.minecraft.world.LightType; @@ -73,7 +74,7 @@ public abstract class AbstractInstance implements IInstance, ILightUpdateListene } @Override - public void onLightUpdate(LightProvider world, LightType type, GridAlignedBB changed) { + public void onLightUpdate(LightProvider world, LightType type, ReadOnlyBox changed) { updateLight(); } diff --git a/src/main/java/com/jozufozu/flywheel/light/GridAlignedBB.java b/src/main/java/com/jozufozu/flywheel/light/GridAlignedBB.java index 706359d58..5838c335f 100644 --- a/src/main/java/com/jozufozu/flywheel/light/GridAlignedBB.java +++ b/src/main/java/com/jozufozu/flywheel/light/GridAlignedBB.java @@ -1,7 +1,5 @@ package com.jozufozu.flywheel.light; -import static com.jozufozu.flywheel.util.RenderUtil.isPowerOf2; - import com.jozufozu.flywheel.util.RenderUtil; import net.minecraft.util.Direction; @@ -10,13 +8,13 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.SectionPos; import net.minecraft.util.math.vector.Vector3i; -public class GridAlignedBB { - public int minX; - public int minY; - public int minZ; - public int maxX; - public int maxY; - public int maxZ; +public class GridAlignedBB implements ReadOnlyBox { + private int minX; + private int minY; + private int minZ; + private int maxX; + private int maxY; + private int maxZ; public GridAlignedBB(int minX, int minY, int minZ, int maxX, int maxY, int maxZ) { this.minX = minX; @@ -31,10 +29,6 @@ public class GridAlignedBB { return new GridAlignedBB(-radius, -radius, -radius, radius + 1, radius + 1, radius + 1); } - public static GridAlignedBB copy(GridAlignedBB bb) { - return new GridAlignedBB(bb.minX, bb.minY, bb.minZ, bb.maxX, bb.maxY, bb.maxZ); - } - public static GridAlignedBB from(AxisAlignedBB aabb) { int minX = (int) Math.floor(aabb.minX); int minY = (int) Math.floor(aabb.minY); @@ -63,62 +57,20 @@ public class GridAlignedBB { return new GridAlignedBB(startX, 0, startZ, startX + 16, 256, startZ + 16); } - public static AxisAlignedBB toAABB(GridAlignedBB bb) { - return new AxisAlignedBB(bb.minX, bb.minY, bb.minZ, bb.maxX, bb.maxY, bb.maxZ); - } - - public GridAlignedBB copy() { - return copy(this); - } - - public boolean sameAs(GridAlignedBB other) { - return minX == other.minX && minY == other.minY && minZ == other.minZ && maxX == other.maxX && maxY == other.maxY && maxZ == other.maxZ; - } - - public boolean sameAs(AxisAlignedBB other) { - return minX == Math.floor(other.minX) - && minY == Math.floor(other.minY) - && minZ == Math.floor(other.minZ) - && maxX == Math.ceil(other.maxX) - && maxY == Math.ceil(other.maxY) - && maxZ == Math.ceil(other.maxZ); - } - public void fixMinMax() { - int minX = Math.min(this.minX, this.maxX); - int minY = Math.min(this.minY, this.maxY); - int minZ = Math.min(this.minZ, this.maxZ); - int maxX = Math.max(this.minX, this.maxX); - int maxY = Math.max(this.minY, this.maxY); - int maxZ = Math.max(this.minZ, this.maxZ); + int minX = Math.min(this.getMinX(), this.getMaxX()); + int minY = Math.min(this.getMinY(), this.getMaxY()); + int minZ = Math.min(this.getMinZ(), this.getMaxZ()); + int maxX = Math.max(this.getMinX(), this.getMaxX()); + int maxY = Math.max(this.getMinY(), this.getMaxY()); + int maxZ = Math.max(this.getMinZ(), this.getMaxZ()); - this.minX = minX; - this.minY = minY; - this.minZ = minZ; - this.maxX = maxX; - this.maxY = maxY; - this.maxZ = maxZ; - } - - public int sizeX() { - return maxX - minX; - } - - public int sizeY() { - return maxY - minY; - } - - public int sizeZ() { - return maxZ - minZ; - } - - public int volume() { - return sizeX() * sizeY() * sizeZ(); - } - - public boolean empty() { - // if any dimension has side length 0 this box contains no volume - return minX == maxX || minY == maxY || minZ == maxZ; + this.setMinX(minX); + this.setMinY(minY); + this.setMinZ(minZ); + this.setMaxX(maxX); + this.setMaxY(maxY); + this.setMaxZ(maxZ); } public void translate(Vector3i by) { @@ -126,12 +78,12 @@ public class GridAlignedBB { } public void translate(int x, int y, int z) { - minX += x; - maxX += x; - minY += y; - maxY += y; - minZ += z; - maxZ += z; + setMinX(getMinX() + x); + setMaxX(getMaxX() + x); + setMinY(getMinY() + y); + setMaxY(getMaxY() + y); + setMinZ(getMinZ() + z); + setMaxZ(getMaxZ() + z); } public void mirrorAbout(Direction.Axis axis) { @@ -141,15 +93,15 @@ public class GridAlignedBB { int flipY = axisVec.getY() - 1; int flipZ = axisVec.getZ() - 1; - int maxX = this.maxX * flipX; - int maxY = this.maxY * flipY; - int maxZ = this.maxZ * flipZ; - this.maxX = this.minX * flipX; - this.maxY = this.minY * flipY; - this.maxZ = this.minZ * flipZ; - this.minX = maxX; - this.minY = maxY; - this.minZ = maxZ; + int maxX = this.getMaxX() * flipX; + int maxY = this.getMaxY() * flipY; + int maxZ = this.getMaxZ() * flipZ; + this.setMaxX(this.getMinX() * flipX); + this.setMaxY(this.getMinY() * flipY); + this.setMaxZ(this.getMinZ() * flipZ); + this.setMinX(maxX); + this.setMinY(maxY); + this.setMinZ(maxZ); } /** @@ -168,12 +120,12 @@ public class GridAlignedBB { int diffY = newSizeY - sizeY; int diffZ = newSizeZ - sizeZ; - minX -= diffX / 2; // floor division for the minimums - minY -= diffY / 2; - minZ -= diffZ / 2; - maxX += (diffX + 1) / 2; // ceiling divison for the maximums - maxY += (diffY + 1) / 2; - maxZ += (diffZ + 1) / 2; + setMinX(getMinX() - diffX / 2); // floor division for the minimums + setMinY(getMinY() - diffY / 2); + setMinZ(getMinZ() - diffZ / 2); + setMaxX(getMaxX() + (diffX + 1) / 2); // ceiling divison for the maximums + setMaxY(getMaxY() + (diffY + 1) / 2); + setMaxZ(getMaxZ() + (diffZ + 1) / 2); } /** @@ -184,14 +136,9 @@ public class GridAlignedBB { int sizeY = RenderUtil.nextPowerOf2(sizeY()); int sizeZ = RenderUtil.nextPowerOf2(sizeZ()); - this.maxX = this.minX + sizeX; - this.maxY = this.minY + sizeY; - this.maxZ = this.minZ + sizeZ; - } - - public boolean hasPowerOf2Sides() { - // this is only true if all individual side lengths are powers of 2 - return isPowerOf2(volume()); + this.setMaxX(this.getMinX() + sizeX); + this.setMaxY(this.getMinY() + sizeY); + this.setMaxZ(this.getMinZ() + sizeZ); } public void grow(int s) { @@ -199,109 +146,57 @@ public class GridAlignedBB { } public void grow(int x, int y, int z) { - minX -= x; - minY -= y; - minZ -= z; - maxX += x; - maxY += y; - maxZ += z; + setMinX(getMinX() - x); + setMinY(getMinY() - y); + setMinZ(getMinZ() - z); + setMaxX(getMaxX() + x); + setMaxY(getMaxY() + y); + setMaxZ(getMaxZ() + z); } - public GridAlignedBB intersect(GridAlignedBB other) { - int minX = Math.max(this.minX, other.minX); - int minY = Math.max(this.minY, other.minY); - int minZ = Math.max(this.minZ, other.minZ); - int maxX = Math.min(this.maxX, other.maxX); - int maxY = Math.min(this.maxY, other.maxY); - int maxZ = Math.min(this.maxZ, other.maxZ); - return new GridAlignedBB(minX, minY, minZ, maxX, maxY, maxZ); + public void intersectAssign(ReadOnlyBox other) { + this.setMinX(Math.max(this.getMinX(), other.getMinX())); + this.setMinY(Math.max(this.getMinY(), other.getMinY())); + this.setMinZ(Math.max(this.getMinZ(), other.getMinZ())); + this.setMaxX(Math.min(this.getMaxX(), other.getMaxX())); + this.setMaxY(Math.min(this.getMaxY(), other.getMaxY())); + this.setMaxZ(Math.min(this.getMaxZ(), other.getMaxZ())); } - public void intersectAssign(GridAlignedBB other) { - this.minX = Math.max(this.minX, other.minX); - this.minY = Math.max(this.minY, other.minY); - this.minZ = Math.max(this.minZ, other.minZ); - this.maxX = Math.min(this.maxX, other.maxX); - this.maxY = Math.min(this.maxY, other.maxY); - this.maxZ = Math.min(this.maxZ, other.maxZ); - } - - public GridAlignedBB union(GridAlignedBB other) { - int minX = Math.min(this.minX, other.minX); - int minY = Math.min(this.minY, other.minY); - int minZ = Math.min(this.minZ, other.minZ); - int maxX = Math.max(this.maxX, other.maxX); - int maxY = Math.max(this.maxY, other.maxY); - int maxZ = Math.max(this.maxZ, other.maxZ); - return new GridAlignedBB(minX, minY, minZ, maxX, maxY, maxZ); - } - - public void unionAssign(GridAlignedBB other) { - this.minX = Math.min(this.minX, other.minX); - this.minY = Math.min(this.minY, other.minY); - this.minZ = Math.min(this.minZ, other.minZ); - this.maxX = Math.max(this.maxX, other.maxX); - this.maxY = Math.max(this.maxY, other.maxY); - this.maxZ = Math.max(this.maxZ, other.maxZ); + public void unionAssign(ReadOnlyBox other) { + this.setMinX(Math.min(this.getMinX(), other.getMinX())); + this.setMinY(Math.min(this.getMinY(), other.getMinY())); + this.setMinZ(Math.min(this.getMinZ(), other.getMinZ())); + this.setMaxX(Math.max(this.getMaxX(), other.getMaxX())); + this.setMaxY(Math.max(this.getMaxY(), other.getMaxY())); + this.setMaxZ(Math.max(this.getMaxZ(), other.getMaxZ())); } public void unionAssign(AxisAlignedBB other) { - this.minX = Math.min(this.minX, (int) Math.floor(other.minX)); - this.minY = Math.min(this.minY, (int) Math.floor(other.minY)); - this.minZ = Math.min(this.minZ, (int) Math.floor(other.minZ)); - this.maxX = Math.max(this.maxX, (int) Math.ceil(other.maxX)); - this.maxY = Math.max(this.maxY, (int) Math.ceil(other.maxY)); - this.maxZ = Math.max(this.maxZ, (int) Math.ceil(other.maxZ)); + this.setMinX(Math.min(this.getMinX(), (int) Math.floor(other.minX))); + this.setMinY(Math.min(this.getMinY(), (int) Math.floor(other.minY))); + this.setMinZ(Math.min(this.getMinZ(), (int) Math.floor(other.minZ))); + this.setMaxX(Math.max(this.getMaxX(), (int) Math.ceil(other.maxX))); + this.setMaxY(Math.max(this.getMaxY(), (int) Math.ceil(other.maxY))); + this.setMaxZ(Math.max(this.getMaxZ(), (int) Math.ceil(other.maxZ))); } public void assign(AxisAlignedBB other) { - this.minX = (int) Math.floor(other.minX); - this.minY = (int) Math.floor(other.minY); - this.minZ = (int) Math.floor(other.minZ); - this.maxX = (int) Math.ceil(other.maxX); - this.maxY = (int) Math.ceil(other.maxY); - this.maxZ = (int) Math.ceil(other.maxZ); + this.setMinX((int) Math.floor(other.minX)); + this.setMinY((int) Math.floor(other.minY)); + this.setMinZ((int) Math.floor(other.minZ)); + this.setMaxX((int) Math.ceil(other.maxX)); + this.setMaxY((int) Math.ceil(other.maxY)); + this.setMaxZ((int) Math.ceil(other.maxZ)); } - public void assign(GridAlignedBB other) { - this.minX = other.minX; - this.minY = other.minY; - this.minZ = other.minZ; - this.maxX = other.maxX; - this.maxY = other.maxY; - this.maxZ = other.maxZ; - } - - public boolean intersects(GridAlignedBB other) { - return this.intersects(other.minX, other.minY, other.minZ, other.maxX, other.maxY, other.maxZ); - } - - public boolean contains(GridAlignedBB other) { - return other.minX >= this.minX && other.maxX <= this.maxX && other.minY >= this.minY && other.maxY <= this.maxY && other.minZ >= this.minZ && other.maxZ <= this.maxZ; - } - - public boolean isContainedBy(GridAlignedBB other) { - return other.contains(this); - } - - public boolean intersects(int minX, int minY, int minZ, int maxX, int maxY, int maxZ) { - return this.minX < maxX && this.maxX > minX && this.minY < maxY && this.maxY > minY && this.minZ < maxZ && this.maxZ > minZ; - } - - public void forEachContained(ICoordinateConsumer func) { - if (empty()) return; - - for (int x = minX; x < maxX; x++) { - for (int y = Math.max(minY, 0); y < Math.min(maxY, 255); y++) { // clamp to world height limits - for (int z = minZ; z < maxZ; z++) { - func.consume(x, y, z); - } - } - } - } - - public AxisAlignedBB toAABB() { - return toAABB(this); + public void assign(ReadOnlyBox other) { + this.setMinX(other.getMinX()); + this.setMinY(other.getMinY()); + this.setMinZ(other.getMinZ()); + this.setMaxX(other.getMaxX()); + this.setMaxY(other.getMaxY()); + this.setMaxZ(other.getMaxZ()); } @Override @@ -309,19 +204,79 @@ public class GridAlignedBB { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - GridAlignedBB that = (GridAlignedBB) o; + ReadOnlyBox that = (ReadOnlyBox) o; return this.sameAs(that); } @Override public int hashCode() { - int result = minX; - result = 31 * result + minY; - result = 31 * result + minZ; - result = 31 * result + maxX; - result = 31 * result + maxY; - result = 31 * result + maxZ; + int result = getMinX(); + result = 31 * result + getMinY(); + result = 31 * result + getMinZ(); + result = 31 * result + getMaxX(); + result = 31 * result + getMaxY(); + result = 31 * result + getMaxZ(); return result; } + + @Override + public int getMinX() { + return minX; + } + + @Override + public int getMinY() { + return minY; + } + + @Override + public int getMinZ() { + return minZ; + } + + @Override + public int getMaxX() { + return maxX; + } + + @Override + public int getMaxY() { + return maxY; + } + + @Override + public int getMaxZ() { + return maxZ; + } + + public GridAlignedBB setMinX(int minX) { + this.minX = minX; + return this; + } + + public GridAlignedBB setMinY(int minY) { + this.minY = minY; + return this; + } + + public GridAlignedBB setMinZ(int minZ) { + this.minZ = minZ; + return this; + } + + public GridAlignedBB setMaxX(int maxX) { + this.maxX = maxX; + return this; + } + + public GridAlignedBB setMaxY(int maxY) { + this.maxY = maxY; + return this; + } + + public GridAlignedBB setMaxZ(int maxZ) { + this.maxZ = maxZ; + return this; + } } diff --git a/src/main/java/com/jozufozu/flywheel/light/ILightUpdateListener.java b/src/main/java/com/jozufozu/flywheel/light/ILightUpdateListener.java index ffbc00afd..659d9e819 100644 --- a/src/main/java/com/jozufozu/flywheel/light/ILightUpdateListener.java +++ b/src/main/java/com/jozufozu/flywheel/light/ILightUpdateListener.java @@ -4,14 +4,14 @@ import net.minecraft.world.LightType; public interface ILightUpdateListener { - GridAlignedBB getVolume(); + ReadOnlyBox getVolume(); ListenerStatus status(); /** * Called when a light updates in a chunk the implementor cares about. */ - void onLightUpdate(LightProvider world, LightType type, GridAlignedBB changed); + void onLightUpdate(LightProvider world, LightType type, ReadOnlyBox changed); /** * Called when the server sends light data to the client. diff --git a/src/main/java/com/jozufozu/flywheel/light/LightUpdater.java b/src/main/java/com/jozufozu/flywheel/light/LightUpdater.java index e0ba3072b..5563d6cd6 100644 --- a/src/main/java/com/jozufozu/flywheel/light/LightUpdater.java +++ b/src/main/java/com/jozufozu/flywheel/light/LightUpdater.java @@ -50,17 +50,17 @@ public class LightUpdater { if (listener instanceof IMovingListener) movingListeners.add(((IMovingListener) listener)); - GridAlignedBB box = listener.getVolume(); + ReadOnlyBox box = listener.getVolume(); LongSet sections = this.sections.getAndResetContainment(listener); LongSet chunks = this.chunks.getAndResetContainment(listener); - int minX = SectionPos.blockToSectionCoord(box.minX); - int minY = SectionPos.blockToSectionCoord(box.minY); - int minZ = SectionPos.blockToSectionCoord(box.minZ); - int maxX = SectionPos.blockToSectionCoord(box.maxX); - int maxY = SectionPos.blockToSectionCoord(box.maxY); - int maxZ = SectionPos.blockToSectionCoord(box.maxZ); + int minX = SectionPos.blockToSectionCoord(box.getMinX()); + int minY = SectionPos.blockToSectionCoord(box.getMinY()); + int minZ = SectionPos.blockToSectionCoord(box.getMinZ()); + int maxX = SectionPos.blockToSectionCoord(box.getMaxX()); + int maxY = SectionPos.blockToSectionCoord(box.getMaxY()); + int maxZ = SectionPos.blockToSectionCoord(box.getMaxZ()); for (int x = minX; x <= maxX; x++) { for (int z = minZ; z <= maxZ; z++) { @@ -88,10 +88,10 @@ public class LightUpdater { set.removeIf(l -> l.status().shouldRemove()); - GridAlignedBB chunkBox = GridAlignedBB.from(SectionPos.of(sectionPos)); + ReadOnlyBox chunkBox = GridAlignedBB.from(SectionPos.of(sectionPos)); for (ILightUpdateListener listener : set) { - listener.onLightUpdate(provider, type, chunkBox.copy()); + listener.onLightUpdate(provider, type, chunkBox); } } @@ -122,7 +122,7 @@ public class LightUpdater { return sectionPos & 0xFFFFFFFFFFF_00000L; } - public Stream getAllBoxes() { + public Stream getAllBoxes() { return chunks.stream().map(ILightUpdateListener::getVolume); } diff --git a/src/main/java/com/jozufozu/flywheel/light/LightVolume.java b/src/main/java/com/jozufozu/flywheel/light/LightVolume.java index 9e4ea178e..f44b59c85 100644 --- a/src/main/java/com/jozufozu/flywheel/light/LightVolume.java +++ b/src/main/java/com/jozufozu/flywheel/light/LightVolume.java @@ -76,36 +76,36 @@ public class LightVolume { this.textureVolume.nextPowerOf2Centered(); } - public GridAlignedBB getTextureVolume() { - return GridAlignedBB.copy(textureVolume); + public ReadOnlyBox getTextureVolume() { + return textureVolume; } - public GridAlignedBB getSampleVolume() { - return GridAlignedBB.copy(sampleVolume); + public ReadOnlyBox getSampleVolume() { + return sampleVolume; } public int getMinX() { - return textureVolume.minX; + return textureVolume.getMinX(); } public int getMinY() { - return textureVolume.minY; + return textureVolume.getMinY(); } public int getMinZ() { - return textureVolume.minZ; + return textureVolume.getMinZ(); } public int getMaxX() { - return textureVolume.maxX; + return textureVolume.getMaxX(); } public int getMaxY() { - return textureVolume.maxY; + return textureVolume.getMaxY(); } public int getMaxZ() { - return textureVolume.maxZ; + return textureVolume.getMaxZ(); } public int getSizeX() { @@ -144,7 +144,7 @@ public class LightVolume { } } - public void notifyLightUpdate(LightProvider world, LightType type, GridAlignedBB changedVolume) { + public void notifyLightUpdate(LightProvider world, LightType type, ReadOnlyBox changedVolume) { if (removed) return; if (!changedVolume.intersects(sampleVolume)) return; @@ -173,9 +173,9 @@ public class LightVolume { BlockPos.Mutable pos = new BlockPos.Mutable(); - int shiftX = textureVolume.minX; - int shiftY = textureVolume.minY; - int shiftZ = textureVolume.minZ; + int shiftX = textureVolume.getMinX(); + int shiftY = textureVolume.getMinY(); + int shiftZ = textureVolume.getMinZ(); sampleVolume.forEachContained((x, y, z) -> { pos.set(x, y, z); @@ -194,10 +194,10 @@ public class LightVolume { * * @param worldVolume the region in the world to copy data from. */ - public void copyBlock(LightProvider world, GridAlignedBB worldVolume) { - int xShift = textureVolume.minX; - int yShift = textureVolume.minY; - int zShift = textureVolume.minZ; + public void copyBlock(LightProvider world, ReadOnlyBox worldVolume) { + int xShift = textureVolume.getMinX(); + int yShift = textureVolume.getMinY(); + int zShift = textureVolume.getMinZ(); worldVolume.forEachContained((x, y, z) -> { int light = world.getLight(LightType.BLOCK, x, y, z); @@ -213,10 +213,10 @@ public class LightVolume { * * @param worldVolume the region in the world to copy data from. */ - public void copySky(LightProvider world, GridAlignedBB worldVolume) { - int xShift = textureVolume.minX; - int yShift = textureVolume.minY; - int zShift = textureVolume.minZ; + public void copySky(LightProvider world, ReadOnlyBox worldVolume) { + int xShift = textureVolume.getMinX(); + int yShift = textureVolume.getMinY(); + int zShift = textureVolume.getMinZ(); worldVolume.forEachContained((x, y, z) -> { int light = world.getLight(LightType.SKY, x, y, z); @@ -232,12 +232,12 @@ public class LightVolume { * * @param worldVolume the region in the world to copy data from. */ - public void copyLight(LightProvider world, GridAlignedBB worldVolume) { + public void copyLight(LightProvider world, ReadOnlyBox worldVolume) { BlockPos.Mutable pos = new BlockPos.Mutable(); - int xShift = textureVolume.minX; - int yShift = textureVolume.minY; - int zShift = textureVolume.minZ; + int xShift = textureVolume.getMinX(); + int yShift = textureVolume.getMinY(); + int zShift = textureVolume.getMinZ(); worldVolume.forEachContained((x, y, z) -> { pos.set(x, y, z); diff --git a/src/main/java/com/jozufozu/flywheel/light/ReadOnlyBox.java b/src/main/java/com/jozufozu/flywheel/light/ReadOnlyBox.java new file mode 100644 index 000000000..5b53f02d6 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/light/ReadOnlyBox.java @@ -0,0 +1,115 @@ +package com.jozufozu.flywheel.light; + +import static com.jozufozu.flywheel.util.RenderUtil.isPowerOf2; + +import net.minecraft.util.math.AxisAlignedBB; + +public interface ReadOnlyBox { + int getMinX(); + + int getMinY(); + + int getMinZ(); + + int getMaxX(); + + int getMaxY(); + + int getMaxZ(); + + default int sizeX() { + return getMaxX() - getMinX(); + } + + default int sizeY() { + return getMaxY() - getMinY(); + } + + default int sizeZ() { + return getMaxZ() - getMinZ(); + } + + default int volume() { + return sizeX() * sizeY() * sizeZ(); + } + + default boolean empty() { + // if any dimension has side length 0 this box contains no volume + return getMinX() == getMaxX() || getMinY() == getMaxY() || getMinZ() == getMaxZ(); + } + + default boolean sameAs(ReadOnlyBox other) { + return getMinX() == other.getMinX() && getMinY() == other.getMinY() && getMinZ() == other.getMinZ() && getMaxX() == other.getMaxX() && getMaxY() == other.getMaxY() && getMaxZ() == other.getMaxZ(); + } + + default boolean sameAs(AxisAlignedBB other) { + return getMinX() == Math.floor(other.minX) + && getMinY() == Math.floor(other.minY) + && getMinZ() == Math.floor(other.minZ) + && getMaxX() == Math.ceil(other.maxX) + && getMaxY() == Math.ceil(other.maxY) + && getMaxZ() == Math.ceil(other.maxZ); + } + + default boolean hasPowerOf2Sides() { + // this is only true if all individual side lengths are powers of 2 + return isPowerOf2(volume()); + } + + default GridAlignedBB intersect(ReadOnlyBox other) { + int minX = Math.max(this.getMinX(), other.getMinX()); + int minY = Math.max(this.getMinY(), other.getMinY()); + int minZ = Math.max(this.getMinZ(), other.getMinZ()); + int maxX = Math.min(this.getMaxX(), other.getMaxX()); + int maxY = Math.min(this.getMaxY(), other.getMaxY()); + int maxZ = Math.min(this.getMaxZ(), other.getMaxZ()); + return new GridAlignedBB(minX, minY, minZ, maxX, maxY, maxZ); + } + + default ReadOnlyBox union(ReadOnlyBox other) { + int minX = Math.min(this.getMinX(), other.getMinX()); + int minY = Math.min(this.getMinY(), other.getMinY()); + int minZ = Math.min(this.getMinZ(), other.getMinZ()); + int maxX = Math.max(this.getMaxX(), other.getMaxX()); + int maxY = Math.max(this.getMaxY(), other.getMaxY()); + int maxZ = Math.max(this.getMaxZ(), other.getMaxZ()); + return new GridAlignedBB(minX, minY, minZ, maxX, maxY, maxZ); + } + + + default boolean intersects(ReadOnlyBox other) { + return this.intersects(other.getMinX(), other.getMinY(), other.getMinZ(), other.getMaxX(), other.getMaxY(), other.getMaxZ()); + } + + default boolean contains(ReadOnlyBox other) { + return other.getMinX() >= this.getMinX() && other.getMaxX() <= this.getMaxX() && other.getMinY() >= this.getMinY() && other.getMaxY() <= this.getMaxY() && other.getMinZ() >= this.getMinZ() && other.getMaxZ() <= this.getMaxZ(); + } + + default boolean isContainedBy(GridAlignedBB other) { + return other.contains(this); + } + + default boolean intersects(int minX, int minY, int minZ, int maxX, int maxY, int maxZ) { + return this.getMinX() < maxX && this.getMaxX() > minX && this.getMinY() < maxY && this.getMaxY() > minY && this.getMinZ() < maxZ && this.getMaxZ() > minZ; + } + + default void forEachContained(ICoordinateConsumer func) { + if (empty()) return; + + for (int x = getMinX(); x < getMaxX(); x++) { + for (int y = Math.max(getMinY(), 0); y < Math.min(getMaxY(), 255); y++) { // clamp to world height limits + for (int z = getMinZ(); z < getMaxZ(); z++) { + func.consume(x, y, z); + } + } + } + } + + default AxisAlignedBB toAABB() { + return new AxisAlignedBB(getMinX(), getMinY(), getMinZ(), getMaxX(), getMaxY(), getMaxZ()); + } + + default GridAlignedBB copy() { + return new GridAlignedBB(getMinX(), getMinY(), getMinZ(), getMaxX(), getMaxY(), getMaxZ()); + } +}