Separate LightVolume and GPULightVolume
- LightVolumes now can act as a light cache with configurable size - More GridAlignedBB changes - Remove ILightUpdateListeners - Simplify pulley rendering using LightVolume
This commit is contained in:
parent
d13bf42c22
commit
6fcc960189
9 changed files with 100 additions and 143 deletions
|
@ -27,7 +27,7 @@ import org.apache.commons.lang3.tuple.Pair;
|
|||
|
||||
import com.jozufozu.flywheel.backend.IFlywheelWorld;
|
||||
import com.jozufozu.flywheel.light.GridAlignedBB;
|
||||
import com.jozufozu.flywheel.light.ReadOnlyBox;
|
||||
import com.jozufozu.flywheel.light.ImmutableBox;
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.AllMovementBehaviours;
|
||||
import com.simibubi.create.content.contraptions.base.IRotate;
|
||||
|
@ -1143,7 +1143,7 @@ public abstract class Contraption {
|
|||
|
||||
GridAlignedBB betterBounds = GridAlignedBB.ofRadius(radius);
|
||||
|
||||
ReadOnlyBox contraptionBounds = GridAlignedBB.from(bounds);
|
||||
ImmutableBox contraptionBounds = GridAlignedBB.from(bounds);
|
||||
if (axis == Direction.Axis.X) {
|
||||
betterBounds.setMaxX(contraptionBounds.getMaxX());
|
||||
betterBounds.setMinX(contraptionBounds.getMinX());
|
||||
|
|
|
@ -6,10 +6,10 @@ import net.minecraft.world.LightType;
|
|||
|
||||
public abstract class ContraptionLighter<C extends Contraption> implements ILightUpdateListener {
|
||||
protected final C contraption;
|
||||
public final LightVolume lightVolume;
|
||||
public final GPULightVolume lightVolume;
|
||||
protected final LightUpdater lightUpdater;
|
||||
|
||||
protected GridAlignedBB bounds;
|
||||
protected final GridAlignedBB bounds;
|
||||
|
||||
protected boolean scheduleRebuild;
|
||||
|
||||
|
@ -18,15 +18,14 @@ public abstract class ContraptionLighter<C extends Contraption> implements ILigh
|
|||
lightUpdater = LightUpdater.get(contraption.entity.level);
|
||||
|
||||
bounds = getContraptionBounds();
|
||||
growBoundsForEdgeData();
|
||||
|
||||
lightVolume = new LightVolume(contraptionBoundsToVolume(bounds));
|
||||
lightVolume = new GPULightVolume(bounds);
|
||||
|
||||
lightVolume.initialize(contraption.entity.level);
|
||||
lightVolume.initialize(lightUpdater.getProvider());
|
||||
scheduleRebuild = true;
|
||||
|
||||
lightUpdater.addListener(this);
|
||||
|
||||
lightVolume.initialize(this.contraption.entity.level);
|
||||
}
|
||||
|
||||
public abstract GridAlignedBB getContraptionBounds();
|
||||
|
@ -37,26 +36,28 @@ public abstract class ContraptionLighter<C extends Contraption> implements ILigh
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onLightUpdate(LightProvider world, LightType type, ReadOnlyBox changed) {
|
||||
lightVolume.notifyLightUpdate(world, type, changed);
|
||||
public void onLightUpdate(LightProvider world, LightType type, ImmutableBox changed) {
|
||||
lightVolume.onLightUpdate(world, type, changed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLightPacket(LightProvider world, int chunkX, int chunkZ) {
|
||||
lightVolume.notifyLightPacket(world, chunkX, chunkZ);
|
||||
lightVolume.onLightPacket(world, chunkX, chunkZ);
|
||||
}
|
||||
|
||||
protected GridAlignedBB contraptionBoundsToVolume(ReadOnlyBox box) {
|
||||
GridAlignedBB bounds = box.copy();
|
||||
protected void growBoundsForEdgeData() {
|
||||
bounds.grow(2); // so we have at least enough data on the edges to avoid artifacts and have smooth lighting
|
||||
bounds.setMinY(Math.max(bounds.getMinY(), 0));
|
||||
bounds.setMaxY(Math.min(bounds.getMaxY(), 255));
|
||||
|
||||
return bounds;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReadOnlyBox getVolume() {
|
||||
public ImmutableBox getVolume() {
|
||||
return bounds;
|
||||
}
|
||||
|
||||
public void delete() {
|
||||
lightUpdater.removeListener(this);
|
||||
lightVolume.delete();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ package com.simibubi.create.content.contraptions.components.structureMovement;
|
|||
import com.jozufozu.flywheel.light.GridAlignedBB;
|
||||
import com.jozufozu.flywheel.light.IMovingListener;
|
||||
import com.jozufozu.flywheel.light.LightProvider;
|
||||
import com.jozufozu.flywheel.light.ReadOnlyBox;
|
||||
import com.jozufozu.flywheel.light.ImmutableBox;
|
||||
import com.simibubi.create.foundation.config.AllConfigs;
|
||||
|
||||
public class NonStationaryLighter<C extends Contraption> extends ContraptionLighter<C> implements IMovingListener {
|
||||
|
@ -16,14 +16,15 @@ public class NonStationaryLighter<C extends Contraption> extends ContraptionLigh
|
|||
if (getVolume().volume() > AllConfigs.CLIENT.maxContraptionLightVolume.get())
|
||||
return false;
|
||||
|
||||
ReadOnlyBox contraptionBounds = getContraptionBounds();
|
||||
ImmutableBox contraptionBounds = getContraptionBounds();
|
||||
|
||||
if (bounds.sameAs(contraptionBounds)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bounds.assign(contraptionBounds);
|
||||
lightVolume.move(contraption.entity.level, contraptionBoundsToVolume(bounds));
|
||||
growBoundsForEdgeData();
|
||||
|
||||
lightVolume.move(provider, bounds);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
package com.simibubi.create.content.contraptions.components.structureMovement.pulley;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.jozufozu.flywheel.backend.instancing.IDynamicInstance;
|
||||
import com.jozufozu.flywheel.backend.instancing.Instancer;
|
||||
import com.jozufozu.flywheel.backend.material.MaterialManager;
|
||||
|
@ -9,23 +7,21 @@ import com.jozufozu.flywheel.core.instancing.ConditionalInstance;
|
|||
import com.jozufozu.flywheel.core.instancing.GroupInstance;
|
||||
import com.jozufozu.flywheel.core.instancing.SelectInstance;
|
||||
import com.jozufozu.flywheel.core.materials.OrientedData;
|
||||
import com.jozufozu.flywheel.light.BasicProvider;
|
||||
import com.jozufozu.flywheel.light.GridAlignedBB;
|
||||
import com.jozufozu.flywheel.light.IMovingListener;
|
||||
import com.jozufozu.flywheel.light.LightProvider;
|
||||
import com.jozufozu.flywheel.light.ListenerStatus;
|
||||
import com.jozufozu.flywheel.light.ReadOnlyBox;
|
||||
import com.jozufozu.flywheel.light.ImmutableBox;
|
||||
import com.jozufozu.flywheel.light.LightUpdater;
|
||||
import com.jozufozu.flywheel.light.LightVolume;
|
||||
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
||||
import com.simibubi.create.content.contraptions.relays.encased.ShaftInstance;
|
||||
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.vector.Vector3f;
|
||||
import net.minecraft.world.IBlockDisplayReader;
|
||||
import net.minecraft.world.LightType;
|
||||
|
||||
public abstract class AbstractPulleyInstance extends ShaftInstance implements IDynamicInstance {
|
||||
public abstract class AbstractPulleyInstance extends ShaftInstance implements IDynamicInstance, IMovingListener {
|
||||
|
||||
final OrientedData coil;
|
||||
final SelectInstance<OrientedData> magnet;
|
||||
|
@ -36,9 +32,8 @@ public abstract class AbstractPulleyInstance extends ShaftInstance implements ID
|
|||
protected final Direction rotatingAbout;
|
||||
protected final Vector3f rotationAxis;
|
||||
|
||||
private byte[] bLight = new byte[1];
|
||||
private byte[] sLight = new byte[1];
|
||||
private GridAlignedBB volume;
|
||||
private final GridAlignedBB volume = new GridAlignedBB();
|
||||
private final LightVolume light;
|
||||
|
||||
public AbstractPulleyInstance(MaterialManager dispatcher, KineticTileEntity tile) {
|
||||
super(dispatcher, tile);
|
||||
|
@ -46,8 +41,7 @@ public abstract class AbstractPulleyInstance extends ShaftInstance implements ID
|
|||
rotatingAbout = Direction.get(Direction.AxisDirection.POSITIVE, axis);
|
||||
rotationAxis = rotatingAbout.step();
|
||||
|
||||
coil = getCoilModel()
|
||||
.createInstance()
|
||||
coil = getCoilModel().createInstance()
|
||||
.setPosition(getInstancePosition());
|
||||
|
||||
magnet = new SelectInstance<>(this::getMagnetModelIndex);
|
||||
|
@ -55,49 +49,60 @@ public abstract class AbstractPulleyInstance extends ShaftInstance implements ID
|
|||
.addModel(getHalfMagnetModel());
|
||||
|
||||
rope = new GroupInstance<>(getRopeModel());
|
||||
halfRope = new ConditionalInstance<>(getHalfRopeModel())
|
||||
.withCondition(this::shouldRenderHalfRope);
|
||||
halfRope = new ConditionalInstance<>(getHalfRopeModel()).withCondition(this::shouldRenderHalfRope);
|
||||
|
||||
updateOffset();
|
||||
updateVolume();
|
||||
|
||||
light = new LightVolume(volume);
|
||||
light.initialize(LightUpdater.get(world).getProvider());
|
||||
|
||||
beginFrame();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beginFrame() {
|
||||
updateOffset();
|
||||
|
||||
transformModels();
|
||||
}
|
||||
|
||||
private void transformModels() {
|
||||
resizeRope();
|
||||
|
||||
coil.setRotation(rotationAxis.rotationDegrees(offset * 180));
|
||||
magnet.update().get().ifPresent(data ->
|
||||
{
|
||||
int index = Math.max(0, MathHelper.floor(offset));
|
||||
|
||||
int neededRopeCount = getNeededRopeCount();
|
||||
rope.resize(neededRopeCount);
|
||||
|
||||
magnet.update()
|
||||
.get()
|
||||
.ifPresent(data -> {
|
||||
int i = Math.max(0, MathHelper.floor(offset));
|
||||
short packed = light.getPackedLight(pos.getX(), pos.getY() - i, pos.getZ());
|
||||
data.setPosition(getInstancePosition())
|
||||
.nudge(0, -offset, 0)
|
||||
.setBlockLight(bLight[index])
|
||||
.setSkyLight(sLight[index]);
|
||||
}
|
||||
);
|
||||
.setBlockLight(LightVolume.unpackBlock(packed))
|
||||
.setSkyLight(LightVolume.unpackSky(packed));
|
||||
});
|
||||
|
||||
halfRope.update().get().ifPresent(rope -> {
|
||||
float f = offset % 1;
|
||||
float halfRopeNudge = f > .75f ? f - 1 : f;
|
||||
halfRope.update()
|
||||
.get()
|
||||
.ifPresent(rope1 -> {
|
||||
float f = offset % 1;
|
||||
float halfRopeNudge = f > .75f ? f - 1 : f;
|
||||
|
||||
rope.setPosition(getInstancePosition())
|
||||
.nudge(0, -halfRopeNudge, 0)
|
||||
.setBlockLight(bLight[0])
|
||||
.setSkyLight(sLight[0]);
|
||||
});
|
||||
short packed = light.getPackedLight(pos.getX(), pos.getY(), pos.getZ());
|
||||
rope1.setPosition(getInstancePosition())
|
||||
.nudge(0, -halfRopeNudge, 0)
|
||||
.setBlockLight(LightVolume.unpackBlock(packed))
|
||||
.setSkyLight(LightVolume.unpackSky(packed));
|
||||
});
|
||||
|
||||
if (isRunning()) {
|
||||
int size = rope.size();
|
||||
int bottomY = pos.getY() - size;
|
||||
for (int i = 0; i < size; i++) {
|
||||
short packed = light.getPackedLight(pos.getX(), bottomY + i, pos.getZ());
|
||||
|
||||
rope.get(i)
|
||||
.setPosition(getInstancePosition())
|
||||
.nudge(0, -offset + i + 1, 0)
|
||||
.setBlockLight(bLight[size - i])
|
||||
.setSkyLight(sLight[size - i]);
|
||||
.setBlockLight(LightVolume.unpackBlock(packed))
|
||||
.setSkyLight(LightVolume.unpackSky(packed));
|
||||
}
|
||||
} else {
|
||||
rope.clear();
|
||||
|
@ -117,6 +122,7 @@ public abstract class AbstractPulleyInstance extends ShaftInstance implements ID
|
|||
magnet.delete();
|
||||
rope.clear();
|
||||
halfRope.delete();
|
||||
light.delete();
|
||||
}
|
||||
|
||||
protected abstract Instancer<OrientedData> getRopeModel();
|
||||
|
@ -133,23 +139,24 @@ public abstract class AbstractPulleyInstance extends ShaftInstance implements ID
|
|||
|
||||
protected abstract boolean isRunning();
|
||||
|
||||
protected void resizeRope() {
|
||||
int neededRopeCount = getNeededRopeCount();
|
||||
rope.resize(neededRopeCount);
|
||||
|
||||
int length = MathHelper.ceil(offset);
|
||||
|
||||
if (volume == null || bLight.length < length + 1) {
|
||||
volume = GridAlignedBB.from(pos.below(length), pos);
|
||||
volume.fixMinMax();
|
||||
|
||||
bLight = Arrays.copyOf(bLight, length + 1);
|
||||
sLight = Arrays.copyOf(sLight, length + 1);
|
||||
|
||||
initLight(BasicProvider.get(world), volume);
|
||||
|
||||
needsUpdate = true;
|
||||
@Override
|
||||
public boolean update(LightProvider provider) {
|
||||
if (updateVolume()) {
|
||||
light.move(provider, volume);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean updateVolume() {
|
||||
int length = MathHelper.ceil(offset) + 2;
|
||||
|
||||
if (volume.sizeY() < length) {
|
||||
volume.assign(pos.below(length), pos)
|
||||
.fixMinMax();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void updateOffset() {
|
||||
|
@ -167,7 +174,7 @@ public abstract class AbstractPulleyInstance extends ShaftInstance implements ID
|
|||
|
||||
private int getMagnetModelIndex() {
|
||||
if (isRunning() || offset == 0) {
|
||||
return offset > .25f ? 0 : 1;
|
||||
return offset > .25f ? 0 : 1;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
@ -178,25 +185,14 @@ public abstract class AbstractPulleyInstance extends ShaftInstance implements ID
|
|||
return false;
|
||||
}
|
||||
|
||||
boolean needsUpdate;
|
||||
@Override
|
||||
public ImmutableBox getVolume() {
|
||||
return volume;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLightUpdate(LightProvider world, LightType type, ReadOnlyBox changed) {
|
||||
initLight(world, changed.intersect(volume));
|
||||
}
|
||||
|
||||
private void initLight(LightProvider world, ReadOnlyBox changed) {
|
||||
int top = this.pos.getY();
|
||||
BlockPos.Mutable pos = new BlockPos.Mutable();
|
||||
changed.forEachContained((x, y, z) -> {
|
||||
pos.set(x, y, z);
|
||||
byte block = (byte) world.getLight(LightType.BLOCK, x, y, z);
|
||||
byte sky = (byte) world.getLight(LightType.SKY, x, y, z);
|
||||
|
||||
int i = top - y;
|
||||
|
||||
bLight[i] = block;
|
||||
sLight[i] = sky;
|
||||
});
|
||||
public void onLightUpdate(LightProvider world, LightType type, ImmutableBox changed) {
|
||||
super.onLightUpdate(world, type, changed);
|
||||
light.onLightUpdate(world, type, changed);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,11 +9,9 @@ import com.simibubi.create.content.contraptions.fluids.actors.HosePulleyTileEnti
|
|||
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
||||
|
||||
public class HosePulleyInstance extends AbstractPulleyInstance {
|
||||
final HosePulleyTileEntity tile = (HosePulleyTileEntity) super.tile;
|
||||
|
||||
public HosePulleyInstance(MaterialManager dispatcher, HosePulleyTileEntity tile) {
|
||||
super(dispatcher, tile);
|
||||
beginFrame();
|
||||
}
|
||||
|
||||
protected Instancer<OrientedData> getRopeModel() {
|
||||
|
@ -41,7 +39,7 @@ public class HosePulleyInstance extends AbstractPulleyInstance {
|
|||
}
|
||||
|
||||
protected float getOffset() {
|
||||
return tile.getInterpolatedOffset(AnimationTickHolder.getPartialTicks());
|
||||
return ((HosePulleyTileEntity) tile).getInterpolatedOffset(AnimationTickHolder.getPartialTicks());
|
||||
}
|
||||
|
||||
protected boolean isRunning() {
|
||||
|
|
|
@ -9,11 +9,8 @@ import com.simibubi.create.AllBlocks;
|
|||
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
||||
|
||||
public class RopePulleyInstance extends AbstractPulleyInstance {
|
||||
final PulleyTileEntity tile = (PulleyTileEntity) super.tile;
|
||||
|
||||
public RopePulleyInstance(MaterialManager dispatcher, PulleyTileEntity tile) {
|
||||
super(dispatcher, tile);
|
||||
beginFrame();
|
||||
}
|
||||
|
||||
protected Instancer<OrientedData> getRopeModel() {
|
||||
|
@ -38,10 +35,10 @@ public class RopePulleyInstance extends AbstractPulleyInstance {
|
|||
|
||||
protected float getOffset() {
|
||||
float partialTicks = AnimationTickHolder.getPartialTicks();
|
||||
return PulleyRenderer.getTileOffset(partialTicks, tile);
|
||||
return PulleyRenderer.getTileOffset(partialTicks, (PulleyTileEntity) tile);
|
||||
}
|
||||
|
||||
protected boolean isRunning() {
|
||||
return tile.running || tile.isVirtual();
|
||||
return ((PulleyTileEntity) tile).running || tile.isVirtual();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
package com.simibubi.create.content.contraptions.components.structureMovement.render;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.jozufozu.flywheel.light.GridAlignedBB;
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import com.simibubi.create.foundation.renderState.SuperRenderTypeBuffer;
|
||||
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
||||
import com.simibubi.create.foundation.utility.Pair;
|
||||
import com.simibubi.create.foundation.utility.outliner.AABBOutline;
|
||||
|
||||
public class LightVolumeDebugger {
|
||||
public static void render(MatrixStack ms, SuperRenderTypeBuffer buffer) {
|
||||
// ContraptionRenderDispatcher.RENDERERS.values()
|
||||
// .stream()
|
||||
// .flatMap(r -> {
|
||||
// GridAlignedBB texture = r.getLighter().lightVolume.getTextureVolume();
|
||||
// GridAlignedBB sample = r.getLighter().lightVolume.getSampleVolume();
|
||||
//
|
||||
// ArrayList<Pair<GridAlignedBB, Integer>> pairs = new ArrayList<>(2);
|
||||
//
|
||||
// pairs.add(Pair.of(texture, 0xFFFFFF));
|
||||
// pairs.add(Pair.of(sample, 0xFFFF00));
|
||||
//
|
||||
// return pairs.stream();
|
||||
// })
|
||||
// .map(pair -> {
|
||||
// AABBOutline outline = new AABBOutline(GridAlignedBB.toAABB(pair.getFirst()));
|
||||
//
|
||||
// outline.getParams().colored(pair.getSecond());
|
||||
// return outline;
|
||||
// })
|
||||
// .forEach(outline -> outline.render(ms, buffer, AnimationTickHolder.getPartialTicks()));
|
||||
}
|
||||
}
|
|
@ -14,7 +14,6 @@ import com.jozufozu.flywheel.backend.model.ModelRenderer;
|
|||
import com.jozufozu.flywheel.core.model.IModel;
|
||||
import com.jozufozu.flywheel.core.model.WorldModel;
|
||||
import com.jozufozu.flywheel.event.BeginFrameEvent;
|
||||
import com.jozufozu.flywheel.light.GridAlignedBB;
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
|
||||
|
@ -85,7 +84,7 @@ public class RenderedContraption extends ContraptionRenderInfo {
|
|||
|
||||
Vector3d cameraPos = event.getCameraPos();
|
||||
|
||||
lightBox = lighter.lightVolume.getTextureVolume().toAABB()
|
||||
lightBox = lighter.lightVolume.toAABB()
|
||||
.move(-cameraPos.x, -cameraPos.y, -cameraPos.z);
|
||||
}
|
||||
|
||||
|
@ -111,7 +110,7 @@ public class RenderedContraption extends ContraptionRenderInfo {
|
|||
}
|
||||
renderLayers.clear();
|
||||
|
||||
lighter.lightVolume.delete();
|
||||
lighter.delete();
|
||||
|
||||
materialManager.delete();
|
||||
kinetics.invalidate();
|
||||
|
|
|
@ -18,7 +18,7 @@ import com.jozufozu.flywheel.light.ILightUpdateListener;
|
|||
import com.jozufozu.flywheel.light.LightProvider;
|
||||
import com.jozufozu.flywheel.light.LightUpdater;
|
||||
import com.jozufozu.flywheel.light.ListenerStatus;
|
||||
import com.jozufozu.flywheel.light.ReadOnlyBox;
|
||||
import com.jozufozu.flywheel.light.ImmutableBox;
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.content.contraptions.base.IRotate;
|
||||
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
||||
|
@ -553,7 +553,7 @@ public class BeltTileEntity extends KineticTileEntity implements ILightUpdateLis
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onLightUpdate(LightProvider world, LightType type, ReadOnlyBox changed) {
|
||||
public void onLightUpdate(LightProvider world, LightType type, ImmutableBox changed) {
|
||||
GridAlignedBB beltVolume = getVolume();
|
||||
|
||||
if (beltVolume.intersects(changed)) {
|
||||
|
|
Loading…
Reference in a new issue