Immutable view of GridAlignedBB

This commit is contained in:
Jozufozu 2021-09-04 19:57:32 -07:00
parent fe304041c5
commit dc6a9daeb1
7 changed files with 304 additions and 234 deletions

View file

@ -5,7 +5,6 @@ import com.jozufozu.flywheel.core.AtlasStitcher;
import com.jozufozu.flywheel.core.Contexts; import com.jozufozu.flywheel.core.Contexts;
import com.jozufozu.flywheel.core.Materials; import com.jozufozu.flywheel.core.Materials;
import com.jozufozu.flywheel.core.PartialModel; import com.jozufozu.flywheel.core.PartialModel;
import com.jozufozu.flywheel.light.debug.DebugView;
import com.jozufozu.flywheel.vanilla.VanillaInstances; import com.jozufozu.flywheel.vanilla.VanillaInstances;
import net.minecraftforge.eventbus.api.IEventBus; import net.minecraftforge.eventbus.api.IEventBus;

View file

@ -10,6 +10,7 @@ import com.jozufozu.flywheel.light.GridAlignedBB;
import com.jozufozu.flywheel.light.ILightUpdateListener; import com.jozufozu.flywheel.light.ILightUpdateListener;
import com.jozufozu.flywheel.light.LightProvider; import com.jozufozu.flywheel.light.LightProvider;
import com.jozufozu.flywheel.light.ListenerStatus; import com.jozufozu.flywheel.light.ListenerStatus;
import com.jozufozu.flywheel.light.ReadOnlyBox;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.LightType; import net.minecraft.world.LightType;
@ -73,7 +74,7 @@ public abstract class AbstractInstance implements IInstance, ILightUpdateListene
} }
@Override @Override
public void onLightUpdate(LightProvider world, LightType type, GridAlignedBB changed) { public void onLightUpdate(LightProvider world, LightType type, ReadOnlyBox changed) {
updateLight(); updateLight();
} }

View file

@ -1,7 +1,5 @@
package com.jozufozu.flywheel.light; package com.jozufozu.flywheel.light;
import static com.jozufozu.flywheel.util.RenderUtil.isPowerOf2;
import com.jozufozu.flywheel.util.RenderUtil; import com.jozufozu.flywheel.util.RenderUtil;
import net.minecraft.util.Direction; 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.SectionPos;
import net.minecraft.util.math.vector.Vector3i; import net.minecraft.util.math.vector.Vector3i;
public class GridAlignedBB { public class GridAlignedBB implements ReadOnlyBox {
public int minX; private int minX;
public int minY; private int minY;
public int minZ; private int minZ;
public int maxX; private int maxX;
public int maxY; private int maxY;
public int maxZ; private int maxZ;
public GridAlignedBB(int minX, int minY, int minZ, int maxX, int maxY, int maxZ) { public GridAlignedBB(int minX, int minY, int minZ, int maxX, int maxY, int maxZ) {
this.minX = minX; this.minX = minX;
@ -31,10 +29,6 @@ public class GridAlignedBB {
return new GridAlignedBB(-radius, -radius, -radius, radius + 1, radius + 1, radius + 1); 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) { public static GridAlignedBB from(AxisAlignedBB aabb) {
int minX = (int) Math.floor(aabb.minX); int minX = (int) Math.floor(aabb.minX);
int minY = (int) Math.floor(aabb.minY); 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); 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() { public void fixMinMax() {
int minX = Math.min(this.minX, this.maxX); int minX = Math.min(this.getMinX(), this.getMaxX());
int minY = Math.min(this.minY, this.maxY); int minY = Math.min(this.getMinY(), this.getMaxY());
int minZ = Math.min(this.minZ, this.maxZ); int minZ = Math.min(this.getMinZ(), this.getMaxZ());
int maxX = Math.max(this.minX, this.maxX); int maxX = Math.max(this.getMinX(), this.getMaxX());
int maxY = Math.max(this.minY, this.maxY); int maxY = Math.max(this.getMinY(), this.getMaxY());
int maxZ = Math.max(this.minZ, this.maxZ); int maxZ = Math.max(this.getMinZ(), this.getMaxZ());
this.minX = minX; this.setMinX(minX);
this.minY = minY; this.setMinY(minY);
this.minZ = minZ; this.setMinZ(minZ);
this.maxX = maxX; this.setMaxX(maxX);
this.maxY = maxY; this.setMaxY(maxY);
this.maxZ = maxZ; this.setMaxZ(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;
} }
public void translate(Vector3i by) { public void translate(Vector3i by) {
@ -126,12 +78,12 @@ public class GridAlignedBB {
} }
public void translate(int x, int y, int z) { public void translate(int x, int y, int z) {
minX += x; setMinX(getMinX() + x);
maxX += x; setMaxX(getMaxX() + x);
minY += y; setMinY(getMinY() + y);
maxY += y; setMaxY(getMaxY() + y);
minZ += z; setMinZ(getMinZ() + z);
maxZ += z; setMaxZ(getMaxZ() + z);
} }
public void mirrorAbout(Direction.Axis axis) { public void mirrorAbout(Direction.Axis axis) {
@ -141,15 +93,15 @@ public class GridAlignedBB {
int flipY = axisVec.getY() - 1; int flipY = axisVec.getY() - 1;
int flipZ = axisVec.getZ() - 1; int flipZ = axisVec.getZ() - 1;
int maxX = this.maxX * flipX; int maxX = this.getMaxX() * flipX;
int maxY = this.maxY * flipY; int maxY = this.getMaxY() * flipY;
int maxZ = this.maxZ * flipZ; int maxZ = this.getMaxZ() * flipZ;
this.maxX = this.minX * flipX; this.setMaxX(this.getMinX() * flipX);
this.maxY = this.minY * flipY; this.setMaxY(this.getMinY() * flipY);
this.maxZ = this.minZ * flipZ; this.setMaxZ(this.getMinZ() * flipZ);
this.minX = maxX; this.setMinX(maxX);
this.minY = maxY; this.setMinY(maxY);
this.minZ = maxZ; this.setMinZ(maxZ);
} }
/** /**
@ -168,12 +120,12 @@ public class GridAlignedBB {
int diffY = newSizeY - sizeY; int diffY = newSizeY - sizeY;
int diffZ = newSizeZ - sizeZ; int diffZ = newSizeZ - sizeZ;
minX -= diffX / 2; // floor division for the minimums setMinX(getMinX() - diffX / 2); // floor division for the minimums
minY -= diffY / 2; setMinY(getMinY() - diffY / 2);
minZ -= diffZ / 2; setMinZ(getMinZ() - diffZ / 2);
maxX += (diffX + 1) / 2; // ceiling divison for the maximums setMaxX(getMaxX() + (diffX + 1) / 2); // ceiling divison for the maximums
maxY += (diffY + 1) / 2; setMaxY(getMaxY() + (diffY + 1) / 2);
maxZ += (diffZ + 1) / 2; setMaxZ(getMaxZ() + (diffZ + 1) / 2);
} }
/** /**
@ -184,14 +136,9 @@ public class GridAlignedBB {
int sizeY = RenderUtil.nextPowerOf2(sizeY()); int sizeY = RenderUtil.nextPowerOf2(sizeY());
int sizeZ = RenderUtil.nextPowerOf2(sizeZ()); int sizeZ = RenderUtil.nextPowerOf2(sizeZ());
this.maxX = this.minX + sizeX; this.setMaxX(this.getMinX() + sizeX);
this.maxY = this.minY + sizeY; this.setMaxY(this.getMinY() + sizeY);
this.maxZ = this.minZ + sizeZ; this.setMaxZ(this.getMinZ() + sizeZ);
}
public boolean hasPowerOf2Sides() {
// this is only true if all individual side lengths are powers of 2
return isPowerOf2(volume());
} }
public void grow(int s) { public void grow(int s) {
@ -199,109 +146,57 @@ public class GridAlignedBB {
} }
public void grow(int x, int y, int z) { public void grow(int x, int y, int z) {
minX -= x; setMinX(getMinX() - x);
minY -= y; setMinY(getMinY() - y);
minZ -= z; setMinZ(getMinZ() - z);
maxX += x; setMaxX(getMaxX() + x);
maxY += y; setMaxY(getMaxY() + y);
maxZ += z; setMaxZ(getMaxZ() + z);
} }
public GridAlignedBB intersect(GridAlignedBB other) { public void intersectAssign(ReadOnlyBox other) {
int minX = Math.max(this.minX, other.minX); this.setMinX(Math.max(this.getMinX(), other.getMinX()));
int minY = Math.max(this.minY, other.minY); this.setMinY(Math.max(this.getMinY(), other.getMinY()));
int minZ = Math.max(this.minZ, other.minZ); this.setMinZ(Math.max(this.getMinZ(), other.getMinZ()));
int maxX = Math.min(this.maxX, other.maxX); this.setMaxX(Math.min(this.getMaxX(), other.getMaxX()));
int maxY = Math.min(this.maxY, other.maxY); this.setMaxY(Math.min(this.getMaxY(), other.getMaxY()));
int maxZ = Math.min(this.maxZ, other.maxZ); this.setMaxZ(Math.min(this.getMaxZ(), other.getMaxZ()));
return new GridAlignedBB(minX, minY, minZ, maxX, maxY, maxZ);
} }
public void intersectAssign(GridAlignedBB other) { public void unionAssign(ReadOnlyBox other) {
this.minX = Math.max(this.minX, other.minX); this.setMinX(Math.min(this.getMinX(), other.getMinX()));
this.minY = Math.max(this.minY, other.minY); this.setMinY(Math.min(this.getMinY(), other.getMinY()));
this.minZ = Math.max(this.minZ, other.minZ); this.setMinZ(Math.min(this.getMinZ(), other.getMinZ()));
this.maxX = Math.min(this.maxX, other.maxX); this.setMaxX(Math.max(this.getMaxX(), other.getMaxX()));
this.maxY = Math.min(this.maxY, other.maxY); this.setMaxY(Math.max(this.getMaxY(), other.getMaxY()));
this.maxZ = Math.min(this.maxZ, other.maxZ); this.setMaxZ(Math.max(this.getMaxZ(), other.getMaxZ()));
}
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(AxisAlignedBB other) { public void unionAssign(AxisAlignedBB other) {
this.minX = Math.min(this.minX, (int) Math.floor(other.minX)); this.setMinX(Math.min(this.getMinX(), (int) Math.floor(other.minX)));
this.minY = Math.min(this.minY, (int) Math.floor(other.minY)); this.setMinY(Math.min(this.getMinY(), (int) Math.floor(other.minY)));
this.minZ = Math.min(this.minZ, (int) Math.floor(other.minZ)); this.setMinZ(Math.min(this.getMinZ(), (int) Math.floor(other.minZ)));
this.maxX = Math.max(this.maxX, (int) Math.ceil(other.maxX)); this.setMaxX(Math.max(this.getMaxX(), (int) Math.ceil(other.maxX)));
this.maxY = Math.max(this.maxY, (int) Math.ceil(other.maxY)); this.setMaxY(Math.max(this.getMaxY(), (int) Math.ceil(other.maxY)));
this.maxZ = Math.max(this.maxZ, (int) Math.ceil(other.maxZ)); this.setMaxZ(Math.max(this.getMaxZ(), (int) Math.ceil(other.maxZ)));
} }
public void assign(AxisAlignedBB other) { public void assign(AxisAlignedBB other) {
this.minX = (int) Math.floor(other.minX); this.setMinX((int) Math.floor(other.minX));
this.minY = (int) Math.floor(other.minY); this.setMinY((int) Math.floor(other.minY));
this.minZ = (int) Math.floor(other.minZ); this.setMinZ((int) Math.floor(other.minZ));
this.maxX = (int) Math.ceil(other.maxX); this.setMaxX((int) Math.ceil(other.maxX));
this.maxY = (int) Math.ceil(other.maxY); this.setMaxY((int) Math.ceil(other.maxY));
this.maxZ = (int) Math.ceil(other.maxZ); this.setMaxZ((int) Math.ceil(other.maxZ));
} }
public void assign(GridAlignedBB other) { public void assign(ReadOnlyBox other) {
this.minX = other.minX; this.setMinX(other.getMinX());
this.minY = other.minY; this.setMinY(other.getMinY());
this.minZ = other.minZ; this.setMinZ(other.getMinZ());
this.maxX = other.maxX; this.setMaxX(other.getMaxX());
this.maxY = other.maxY; this.setMaxY(other.getMaxY());
this.maxZ = other.maxZ; this.setMaxZ(other.getMaxZ());
}
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);
} }
@Override @Override
@ -309,19 +204,79 @@ public class GridAlignedBB {
if (this == o) return true; if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false; if (o == null || getClass() != o.getClass()) return false;
GridAlignedBB that = (GridAlignedBB) o; ReadOnlyBox that = (ReadOnlyBox) o;
return this.sameAs(that); return this.sameAs(that);
} }
@Override @Override
public int hashCode() { public int hashCode() {
int result = minX; int result = getMinX();
result = 31 * result + minY; result = 31 * result + getMinY();
result = 31 * result + minZ; result = 31 * result + getMinZ();
result = 31 * result + maxX; result = 31 * result + getMaxX();
result = 31 * result + maxY; result = 31 * result + getMaxY();
result = 31 * result + maxZ; result = 31 * result + getMaxZ();
return result; 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;
}
} }

View file

@ -4,14 +4,14 @@ import net.minecraft.world.LightType;
public interface ILightUpdateListener { public interface ILightUpdateListener {
GridAlignedBB getVolume(); ReadOnlyBox getVolume();
ListenerStatus status(); ListenerStatus status();
/** /**
* Called when a light updates in a chunk the implementor cares about. * 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. * Called when the server sends light data to the client.

View file

@ -50,17 +50,17 @@ public class LightUpdater {
if (listener instanceof IMovingListener) if (listener instanceof IMovingListener)
movingListeners.add(((IMovingListener) listener)); movingListeners.add(((IMovingListener) listener));
GridAlignedBB box = listener.getVolume(); ReadOnlyBox box = listener.getVolume();
LongSet sections = this.sections.getAndResetContainment(listener); LongSet sections = this.sections.getAndResetContainment(listener);
LongSet chunks = this.chunks.getAndResetContainment(listener); LongSet chunks = this.chunks.getAndResetContainment(listener);
int minX = SectionPos.blockToSectionCoord(box.minX); int minX = SectionPos.blockToSectionCoord(box.getMinX());
int minY = SectionPos.blockToSectionCoord(box.minY); int minY = SectionPos.blockToSectionCoord(box.getMinY());
int minZ = SectionPos.blockToSectionCoord(box.minZ); int minZ = SectionPos.blockToSectionCoord(box.getMinZ());
int maxX = SectionPos.blockToSectionCoord(box.maxX); int maxX = SectionPos.blockToSectionCoord(box.getMaxX());
int maxY = SectionPos.blockToSectionCoord(box.maxY); int maxY = SectionPos.blockToSectionCoord(box.getMaxY());
int maxZ = SectionPos.blockToSectionCoord(box.maxZ); int maxZ = SectionPos.blockToSectionCoord(box.getMaxZ());
for (int x = minX; x <= maxX; x++) { for (int x = minX; x <= maxX; x++) {
for (int z = minZ; z <= maxZ; z++) { for (int z = minZ; z <= maxZ; z++) {
@ -88,10 +88,10 @@ public class LightUpdater {
set.removeIf(l -> l.status().shouldRemove()); set.removeIf(l -> l.status().shouldRemove());
GridAlignedBB chunkBox = GridAlignedBB.from(SectionPos.of(sectionPos)); ReadOnlyBox chunkBox = GridAlignedBB.from(SectionPos.of(sectionPos));
for (ILightUpdateListener listener : set) { 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; return sectionPos & 0xFFFFFFFFFFF_00000L;
} }
public Stream<GridAlignedBB> getAllBoxes() { public Stream<ReadOnlyBox> getAllBoxes() {
return chunks.stream().map(ILightUpdateListener::getVolume); return chunks.stream().map(ILightUpdateListener::getVolume);
} }

View file

@ -76,36 +76,36 @@ public class LightVolume {
this.textureVolume.nextPowerOf2Centered(); this.textureVolume.nextPowerOf2Centered();
} }
public GridAlignedBB getTextureVolume() { public ReadOnlyBox getTextureVolume() {
return GridAlignedBB.copy(textureVolume); return textureVolume;
} }
public GridAlignedBB getSampleVolume() { public ReadOnlyBox getSampleVolume() {
return GridAlignedBB.copy(sampleVolume); return sampleVolume;
} }
public int getMinX() { public int getMinX() {
return textureVolume.minX; return textureVolume.getMinX();
} }
public int getMinY() { public int getMinY() {
return textureVolume.minY; return textureVolume.getMinY();
} }
public int getMinZ() { public int getMinZ() {
return textureVolume.minZ; return textureVolume.getMinZ();
} }
public int getMaxX() { public int getMaxX() {
return textureVolume.maxX; return textureVolume.getMaxX();
} }
public int getMaxY() { public int getMaxY() {
return textureVolume.maxY; return textureVolume.getMaxY();
} }
public int getMaxZ() { public int getMaxZ() {
return textureVolume.maxZ; return textureVolume.getMaxZ();
} }
public int getSizeX() { 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 (removed) return;
if (!changedVolume.intersects(sampleVolume)) return; if (!changedVolume.intersects(sampleVolume)) return;
@ -173,9 +173,9 @@ public class LightVolume {
BlockPos.Mutable pos = new BlockPos.Mutable(); BlockPos.Mutable pos = new BlockPos.Mutable();
int shiftX = textureVolume.minX; int shiftX = textureVolume.getMinX();
int shiftY = textureVolume.minY; int shiftY = textureVolume.getMinY();
int shiftZ = textureVolume.minZ; int shiftZ = textureVolume.getMinZ();
sampleVolume.forEachContained((x, y, z) -> { sampleVolume.forEachContained((x, y, z) -> {
pos.set(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. * @param worldVolume the region in the world to copy data from.
*/ */
public void copyBlock(LightProvider world, GridAlignedBB worldVolume) { public void copyBlock(LightProvider world, ReadOnlyBox worldVolume) {
int xShift = textureVolume.minX; int xShift = textureVolume.getMinX();
int yShift = textureVolume.minY; int yShift = textureVolume.getMinY();
int zShift = textureVolume.minZ; int zShift = textureVolume.getMinZ();
worldVolume.forEachContained((x, y, z) -> { worldVolume.forEachContained((x, y, z) -> {
int light = world.getLight(LightType.BLOCK, 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. * @param worldVolume the region in the world to copy data from.
*/ */
public void copySky(LightProvider world, GridAlignedBB worldVolume) { public void copySky(LightProvider world, ReadOnlyBox worldVolume) {
int xShift = textureVolume.minX; int xShift = textureVolume.getMinX();
int yShift = textureVolume.minY; int yShift = textureVolume.getMinY();
int zShift = textureVolume.minZ; int zShift = textureVolume.getMinZ();
worldVolume.forEachContained((x, y, z) -> { worldVolume.forEachContained((x, y, z) -> {
int light = world.getLight(LightType.SKY, 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. * @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(); BlockPos.Mutable pos = new BlockPos.Mutable();
int xShift = textureVolume.minX; int xShift = textureVolume.getMinX();
int yShift = textureVolume.minY; int yShift = textureVolume.getMinY();
int zShift = textureVolume.minZ; int zShift = textureVolume.getMinZ();
worldVolume.forEachContained((x, y, z) -> { worldVolume.forEachContained((x, y, z) -> {
pos.set(x, y, z); pos.set(x, y, z);

View file

@ -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());
}
}