From 52eed2bab38d5415a1615f9cb6e555f5f9c96030 Mon Sep 17 00:00:00 2001 From: JozsefA Date: Mon, 15 Mar 2021 14:20:13 -0700 Subject: [PATCH] Instanced Gauges and Valves, DRY lighting. --- .../com/simibubi/create/AllTileEntities.java | 7 +- .../contraptions/base/KineticData.java | 5 +- .../base/KineticTileInstance.java | 6 - .../base/SingleRotatingInstance.java | 6 +- .../components/fan/FanInstance.java | 13 +- .../components/flywheel/FlyWheelInstance.java | 14 +- .../flywheel/engine/EngineInstance.java | 5 +- .../components/mixer/MixerInstance.java | 9 +- .../components/press/PressInstance.java | 4 +- .../chassis/StickerInstance.java | 4 +- .../gantry/GantryCarriageInstance.java | 4 +- .../fluids/pipes/FluidValveBlock.java | 7 +- .../fluids/pipes/FluidValveInstance.java | 91 +++++++++ .../fluids/pipes/FluidValveRenderer.java | 4 + .../relays/belt/BeltInstance.java | 11 +- .../relays/encased/SplitShaftInstance.java | 7 +- .../relays/gauge/GaugeInstance.java | 173 ++++++++++++++++++ .../relays/gauge/GaugeRenderer.java | 9 +- .../relays/gearbox/GearboxInstance.java | 9 +- .../block/mechanicalArm/ArmInstance.java | 9 +- .../block/SchematicannonInstance.java | 11 +- .../backend/instancing/InstancedModel.java | 8 + .../instancing/InstancedTileRenderer.java | 6 + .../instancing/TileEntityInstance.java | 20 +- .../backend/instancing/impl/IFlatLight.java | 26 +++ .../backend/instancing/impl/ModelData.java | 4 +- .../create/foundation/utility/Couple.java | 5 + .../foundation/utility/MatrixStacker.java | 9 + .../utility/animation/LerpedFloat.java | 4 + 29 files changed, 383 insertions(+), 107 deletions(-) create mode 100644 src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidValveInstance.java create mode 100644 src/main/java/com/simibubi/create/content/contraptions/relays/gauge/GaugeInstance.java create mode 100644 src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/IFlatLight.java diff --git a/src/main/java/com/simibubi/create/AllTileEntities.java b/src/main/java/com/simibubi/create/AllTileEntities.java index f65fa76ea..256d46aa9 100644 --- a/src/main/java/com/simibubi/create/AllTileEntities.java +++ b/src/main/java/com/simibubi/create/AllTileEntities.java @@ -77,6 +77,7 @@ import com.simibubi.create.content.contraptions.relays.belt.BeltRenderer; import com.simibubi.create.content.contraptions.relays.belt.BeltTileEntity; import com.simibubi.create.content.contraptions.relays.elementary.SimpleKineticTileEntity; import com.simibubi.create.content.contraptions.relays.encased.*; +import com.simibubi.create.content.contraptions.relays.gauge.GaugeInstance; import com.simibubi.create.content.contraptions.relays.gauge.GaugeRenderer; import com.simibubi.create.content.contraptions.relays.gauge.SpeedGaugeTileEntity; import com.simibubi.create.content.contraptions.relays.gauge.StressGaugeTileEntity; @@ -260,7 +261,7 @@ public class AllTileEntities { public static final TileEntityEntry FLUID_VALVE = Create.registrate() .tileEntity("fluid_valve", FluidValveTileEntity::new) - .instance(() -> ShaftInstance::new) + .instance(() -> FluidValveInstance::new) .validBlocks(AllBlocks.FLUID_VALVE) .renderer(() -> FluidValveRenderer::new) .register(); @@ -515,14 +516,14 @@ public class AllTileEntities { public static final TileEntityEntry SPEEDOMETER = Create.registrate() .tileEntity("speedometer", SpeedGaugeTileEntity::new) - .instance(() -> ShaftInstance::new) + .instance(() -> GaugeInstance.Speed::new) .validBlocks(AllBlocks.SPEEDOMETER) .renderer(() -> GaugeRenderer::speed) .register(); public static final TileEntityEntry STRESSOMETER = Create.registrate() .tileEntity("stressometer", StressGaugeTileEntity::new) - .instance(() -> ShaftInstance::new) + .instance(() -> GaugeInstance.Stress::new) .validBlocks(AllBlocks.STRESSOMETER) .renderer(() -> GaugeRenderer::stress) .register(); diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/KineticData.java b/src/main/java/com/simibubi/create/content/contraptions/base/KineticData.java index 36ce074fd..944223f5c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/KineticData.java +++ b/src/main/java/com/simibubi/create/content/contraptions/base/KineticData.java @@ -4,12 +4,13 @@ import java.nio.ByteBuffer; import com.simibubi.create.foundation.render.backend.instancing.InstanceData; import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; +import com.simibubi.create.foundation.render.backend.instancing.impl.IFlatLight; import com.simibubi.create.foundation.utility.ColorHelper; import net.minecraft.client.renderer.Vector3f; import net.minecraft.util.math.BlockPos; -public class KineticData> extends InstanceData { +public class KineticData> extends InstanceData implements IFlatLight { private float x; private float y; private float z; @@ -65,11 +66,13 @@ public class KineticData> extends InstanceData { return (D) this; } + @Override public D setBlockLight(int blockLight) { this.blockLight = (byte) ((blockLight & 0xF) << 4); return (D) this; } + @Override public D setSkyLight(int skyLight) { this.skyLight = (byte) ((skyLight & 0xF) << 4); return (D) this; diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileInstance.java b/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileInstance.java index 71cdb735d..be44b81f3 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileInstance.java @@ -36,12 +36,6 @@ public abstract class KineticTileInstance extends T return key; } - protected final void relight(InstanceKey> key) { - key.getInstance() - .setBlockLight(world.getLightLevel(LightType.BLOCK, pos)) - .setSkyLight(world.getLightLevel(LightType.SKY, pos)); - } - protected float getRotationOffset(final Direction.Axis axis) { float offset = CogWheelBlock.isLargeCog(lastState) ? 11.25f : 0; double d = (((axis == Direction.Axis.X) ? 0 : pos.getX()) + ((axis == Direction.Axis.Y) ? 0 : pos.getY()) diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/SingleRotatingInstance.java b/src/main/java/com/simibubi/create/content/contraptions/base/SingleRotatingInstance.java index a84f620b6..44e9c93d0 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/SingleRotatingInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/base/SingleRotatingInstance.java @@ -4,14 +4,10 @@ import static com.simibubi.create.content.contraptions.base.KineticTileEntityRen import com.simibubi.create.foundation.render.backend.instancing.InstanceKey; import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; -import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderRegistry; import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; import net.minecraft.block.BlockState; -import net.minecraft.tileentity.TileEntityType; import net.minecraft.util.Direction; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.fml.DistExecutor; public class SingleRotatingInstance extends KineticTileInstance { @@ -35,7 +31,7 @@ public class SingleRotatingInstance extends KineticTileInstance { final Direction direction = lastState.get(FACING); BlockPos behind = pos.offset(direction.getOpposite()); - putLight(shaft, behind); + relight(behind, shaft.getInstance()); BlockPos inFront = pos.offset(direction); - putLight(fan, inFront); - } - - private void putLight(InstanceKey key, BlockPos pos) { - int blockLight = world.getLightLevel(LightType.BLOCK, pos); - int skyLight = world.getLightLevel(LightType.SKY, pos); - - key.getInstance() - .setBlockLight(blockLight) - .setSkyLight(skyLight); + relight(inFront, fan.getInstance()); } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlyWheelInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlyWheelInstance.java index 0e8ff918d..bb2279a6f 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlyWheelInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlyWheelInstance.java @@ -150,20 +150,10 @@ public class FlyWheelInstance extends KineticTileInstance im @Override public void updateLight() { - int block = world.getLightLevel(LightType.BLOCK, pos); - int sky = world.getLightLevel(LightType.SKY, pos); - - shaft.getInstance().setBlockLight(block).setSkyLight(sky); - wheel.getInstance().setBlockLight(block).setSkyLight(sky); + relight(pos, shaft.getInstance(), wheel.getInstance()); if (connection != null) { - BlockPos pos = this.pos.offset(connection); - - int connectionBlock = world.getLightLevel(LightType.BLOCK, pos); - int connectionSky = world.getLightLevel(LightType.SKY, pos); - connectors.stream() - .map(InstanceKey::getInstance) - .forEach(data -> data.setBlockLight(connectionBlock).setSkyLight(connectionSky)); + relight(this.pos.offset(connection), connectors.stream().map(InstanceKey::getInstance)); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/EngineInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/EngineInstance.java index 297016881..cac76a426 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/EngineInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/EngineInstance.java @@ -66,9 +66,6 @@ public class EngineInstance extends TileEntityInstance { @Override public void updateLight() { - int block = world.getLightLevel(LightType.BLOCK, pos); - int sky = world.getLightLevel(LightType.SKY, pos); - - frame.getInstance().setBlockLight(block).setSkyLight(sky); + relight(pos, frame.getInstance()); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MixerInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MixerInstance.java index 0f49c8eb6..d8325b5b0 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MixerInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MixerInstance.java @@ -92,14 +92,9 @@ public class MixerInstance extends ShaftlessCogInstance implements ITickableInst public void updateLight() { super.updateLight(); - BlockPos down = pos.down(); - mixerHead.getInstance() - .setBlockLight(world.getLightLevel(LightType.BLOCK, down)) - .setSkyLight(world.getLightLevel(LightType.SKY, down)); + relight(pos.down(), mixerHead.getInstance()); - mixerPole.getInstance() - .setBlockLight(world.getLightLevel(LightType.BLOCK, pos)) - .setSkyLight(world.getLightLevel(LightType.SKY, pos)); + relight(pos, mixerPole.getInstance()); } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/press/PressInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/press/PressInstance.java index 8c4c1b89e..8af6fa19f 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/press/PressInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/press/PressInstance.java @@ -67,9 +67,7 @@ public class PressInstance extends ShaftInstance implements ITickableInstance { public void updateLight() { super.updateLight(); - pressHead.getInstance() - .setBlockLight(world.getLightLevel(LightType.BLOCK, pos)) - .setSkyLight(world.getLightLevel(LightType.SKY, pos)); + relight(pos, pressHead.getInstance()); } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/StickerInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/StickerInstance.java index b8ea44bf2..6e692fcb9 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/StickerInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/StickerInstance.java @@ -63,9 +63,7 @@ public class StickerInstance extends TileEntityInstance imple @Override public void updateLight() { - head.getInstance() - .setBlockLight(world.getLightLevel(LightType.BLOCK, pos)) - .setSkyLight(world.getLightLevel(LightType.SKY, pos)); + relight(pos, head.getInstance()); } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryCarriageInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryCarriageInstance.java index 0d86bdd9a..1b9cc2e27 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryCarriageInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryCarriageInstance.java @@ -81,9 +81,7 @@ public class GantryCarriageInstance extends ShaftInstance implements ITickableIn @Override public void updateLight() { - gantryCogs.getInstance() - .setBlockLight(world.getLightLevel(LightType.BLOCK, pos)) - .setSkyLight(world.getLightLevel(LightType.SKY, pos)); + relight(pos, gantryCogs.getInstance()); } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidValveBlock.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidValveBlock.java index aa93364de..ad9a85022 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidValveBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidValveBlock.java @@ -25,6 +25,8 @@ import net.minecraft.world.TickPriority; import net.minecraft.world.World; import net.minecraft.world.server.ServerWorld; +import javax.annotation.Nonnull; + public class FluidValveBlock extends DirectionalAxisKineticBlock implements IAxisPipe { public static final BooleanProperty ENABLED = BooleanProperty.create("enabled"); @@ -60,9 +62,10 @@ public class FluidValveBlock extends DirectionalAxisKineticBlock implements IAxi return AllTileEntities.FLUID_VALVE.create(); } + @Nonnull public static Axis getPipeAxis(BlockState state) { if (!(state.getBlock() instanceof FluidValveBlock)) - return null; + throw new IllegalStateException("Provided BlockState is for a different block."); Direction facing = state.get(FACING); boolean alongFirst = !state.get(AXIS_ALONG_FIRST_COORDINATE); for (Axis axis : Iterate.axes) { @@ -74,7 +77,7 @@ public class FluidValveBlock extends DirectionalAxisKineticBlock implements IAxi } return axis; } - return null; + throw new IllegalStateException("Impossible axis."); } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidValveInstance.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidValveInstance.java new file mode 100644 index 000000000..fac0a31ca --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidValveInstance.java @@ -0,0 +1,91 @@ +package com.simibubi.create.content.contraptions.fluids.pipes; + +import com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.AllBlockPartials; +import com.simibubi.create.content.contraptions.base.KineticTileEntity; +import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; +import com.simibubi.create.content.contraptions.relays.encased.ShaftInstance; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.render.backend.RenderMaterials; +import com.simibubi.create.foundation.render.backend.instancing.ITickableInstance; +import com.simibubi.create.foundation.render.backend.instancing.InstanceKey; +import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; +import com.simibubi.create.foundation.render.backend.instancing.impl.ModelData; +import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.AnimationTickHolder; +import com.simibubi.create.foundation.utility.MatrixStacker; +import net.minecraft.block.BlockState; +import net.minecraft.util.Direction; +import net.minecraft.util.math.MathHelper; + +public class FluidValveInstance extends ShaftInstance implements ITickableInstance { + + protected InstanceKey pointer; + + protected double xRot; + protected double yRot; + protected int pointerRotationOffset; + + public FluidValveInstance(InstancedTileRenderer dispatcher, KineticTileEntity tile) { + super(dispatcher, tile); + } + + @Override + protected void init() { + super.init(); + + Direction facing = lastState.get(FluidValveBlock.FACING); + + yRot = AngleHelper.horizontalAngle(facing); + xRot = facing == Direction.UP ? 0 : facing == Direction.DOWN ? 180 : 90; + + Direction.Axis pipeAxis = FluidValveBlock.getPipeAxis(lastState); + Direction.Axis shaftAxis = KineticTileEntityRenderer.getRotationAxisOf(tile); + + pointerRotationOffset = 0; + if (pipeAxis.isHorizontal() && shaftAxis == Direction.Axis.Z || pipeAxis.isVertical()) + pointerRotationOffset = 90; + + pointer = modelManager.basicMaterial().getModel(AllBlockPartials.FLUID_VALVE_POINTER, lastState).createInstance(); + + updateLight(); + transformPointer((FluidValveTileEntity) tile); + } + + @Override + public void tick() { + + FluidValveTileEntity valve = (FluidValveTileEntity) tile; + + if (valve.pointer.settled()) return; + + transformPointer(valve); + } + + private void transformPointer(FluidValveTileEntity valve) { + float pointerRotation = MathHelper.lerp(valve.pointer.getValue(AnimationTickHolder.getPartialTicks()), 0, -90); + + MatrixStack ms = new MatrixStack(); + MatrixStacker.of(ms) + .translate(getFloatingPos()) + .centre() + .rotateY(yRot) + .rotateX(xRot) + .rotateY(pointerRotationOffset + pointerRotation) + .unCentre(); + + pointer.getInstance().setTransform(ms); + } + + @Override + public void updateLight() { + super.updateLight(); + relight(pos, pointer.getInstance()); + } + + @Override + public void remove() { + super.remove(); + pointer.delete(); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidValveRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidValveRenderer.java index 729d37d7d..14439f84a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidValveRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidValveRenderer.java @@ -5,6 +5,7 @@ import com.simibubi.create.AllBlockPartials; import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.MatrixStacker; @@ -25,6 +26,9 @@ public class FluidValveRenderer extends KineticTileEntityRenderer { @Override protected void renderSafe(KineticTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay) { + + if (FastRenderDispatcher.available(te.getWorld())) return; + super.renderSafe(te, partialTicks, ms, buffer, light, overlay); BlockState blockState = te.getBlockState(); SuperByteBuffer pointer = AllBlockPartials.FLUID_VALVE_POINTER.renderOn(blockState); diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltInstance.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltInstance.java index c318d18ed..ed4794e76 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltInstance.java @@ -1,29 +1,24 @@ package com.simibubi.create.content.contraptions.relays.belt; import java.util.ArrayList; -import java.util.function.Consumer; import java.util.function.Supplier; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.AllBlocks; +import com.simibubi.create.content.contraptions.base.KineticData; import com.simibubi.create.content.contraptions.base.KineticTileInstance; import com.simibubi.create.content.contraptions.base.RotatingData; import com.simibubi.create.foundation.block.render.SpriteShiftEntry; import com.simibubi.create.foundation.render.backend.instancing.InstanceKey; import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; -import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderRegistry; import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.MatrixStacker; import net.minecraft.item.DyeColor; -import net.minecraft.tileentity.TileEntityType; import net.minecraft.util.Direction; -import net.minecraft.util.math.BlockPos; import net.minecraft.world.LightType; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.fml.DistExecutor; public class BeltInstance extends KineticTileInstance { @@ -103,9 +98,9 @@ public class BeltInstance extends KineticTileInstance { @Override public void updateLight() { - keys.forEach(this::relight); + relight(pos, keys.stream().map(InstanceKey::getInstance)); - if (pulleyKey != null) relight(pulleyKey); + if (pulleyKey != null) relight(pos, pulleyKey.getInstance()); } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/SplitShaftInstance.java b/src/main/java/com/simibubi/create/content/contraptions/relays/encased/SplitShaftInstance.java index 8547400b6..641d72a68 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/SplitShaftInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/encased/SplitShaftInstance.java @@ -4,19 +4,16 @@ import java.util.ArrayList; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.content.contraptions.base.IRotate; +import com.simibubi.create.content.contraptions.base.KineticData; import com.simibubi.create.content.contraptions.base.KineticTileInstance; import com.simibubi.create.content.contraptions.base.RotatingData; import com.simibubi.create.foundation.render.backend.instancing.InstanceKey; import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; -import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderRegistry; import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; import com.simibubi.create.foundation.utility.Iterate; import net.minecraft.block.Block; -import net.minecraft.tileentity.TileEntityType; import net.minecraft.util.Direction; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.fml.DistExecutor; public class SplitShaftInstance extends KineticTileInstance { @@ -59,7 +56,7 @@ public class SplitShaftInstance extends KineticTileInstance relight(pos, ((InstanceKey>) key).getInstance())); } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/GaugeInstance.java b/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/GaugeInstance.java new file mode 100644 index 000000000..b7352809b --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/GaugeInstance.java @@ -0,0 +1,173 @@ +package com.simibubi.create.content.contraptions.relays.gauge; + +import com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.AllBlockPartials; +import com.simibubi.create.content.contraptions.base.KineticTileEntity; +import com.simibubi.create.content.contraptions.relays.encased.ShaftInstance; +import com.simibubi.create.foundation.render.backend.RenderMaterials; +import com.simibubi.create.foundation.render.backend.instancing.ITickableInstance; +import com.simibubi.create.foundation.render.backend.instancing.InstanceKey; +import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; +import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; +import com.simibubi.create.foundation.render.backend.instancing.impl.ModelData; +import com.simibubi.create.foundation.utility.*; +import net.minecraft.util.Direction; +import net.minecraft.util.math.MathHelper; + +import java.util.ArrayList; + +public abstract class GaugeInstance extends ShaftInstance implements ITickableInstance { + + protected ArrayList faces; + + protected MatrixStack ms; + + protected GaugeInstance(InstancedTileRenderer dispatcher, KineticTileEntity tile) { + super(dispatcher, tile); + } + + @Override + protected void init() { + super.init(); + + faces = new ArrayList<>(2); + + GaugeTileEntity gaugeTile = (GaugeTileEntity) tile; + GaugeBlock gaugeBlock = (GaugeBlock) lastState.getBlock(); + + InstancedModel dialModel = modelManager.getMaterial(RenderMaterials.MODELS).getModel(AllBlockPartials.GAUGE_DIAL, lastState); + InstancedModel headModel = getHeadModel(); + + ms = new MatrixStack(); + MatrixStacker msr = MatrixStacker.of(ms); + msr.translate(getFloatingPos()); + + float progress = MathHelper.lerp(AnimationTickHolder.getPartialTicks(), gaugeTile.prevDialState, gaugeTile.dialState); + + for (Direction facing : Iterate.directions) { + if (!gaugeBlock.shouldRenderHeadOnFace(world, pos, lastState, facing)) + continue; + + DialFace face = makeFace(facing, dialModel, headModel); + + faces.add(face); + + face.setupTransform(msr, progress); + } + + updateLight(); + } + + private DialFace makeFace(Direction face, InstancedModel dialModel, InstancedModel headModel) { + return new DialFace(face, dialModel.createInstance(), headModel.createInstance()); + } + + @Override + public void tick() { + GaugeTileEntity gaugeTile = (GaugeTileEntity) tile; + + if (MathHelper.epsilonEquals(gaugeTile.prevDialState, gaugeTile.dialState)) + return; + + float progress = MathHelper.lerp(AnimationTickHolder.getPartialTicks(), gaugeTile.prevDialState, gaugeTile.dialState); + + MatrixStacker msr = MatrixStacker.of(ms); + + for (DialFace faceEntry : faces) { + faceEntry.updateTransform(msr, progress); + } + } + + @Override + public void updateLight() { + super.updateLight(); + + relight(pos, faces.stream() + .flatMap(Couple::stream) + .map(InstanceKey::getInstance)); + } + + @Override + public void remove() { + super.remove(); + + faces.forEach(DialFace::delete); + } + + protected abstract InstancedModel getHeadModel(); + + private class DialFace extends Couple> { + + Direction face; + + public DialFace(Direction face, InstanceKey first, InstanceKey second) { + super(first, second); + this.face = face; + } + + private void setupTransform(MatrixStacker msr, float progress) { + float dialPivot = 5.75f / 16; + + ms.push(); + rotateToFace(msr); + + getSecond().getInstance().setTransform(ms); + + msr.translate(0, dialPivot, dialPivot) + .rotate(Direction.EAST, (float) (Math.PI / 2 * -progress)) + .translate(0, -dialPivot, -dialPivot); + + getFirst().getInstance().setTransform(ms); + + ms.pop(); + } + + private void updateTransform(MatrixStacker msr, float progress) { + float dialPivot = 5.75f / 16; + + ms.push(); + + rotateToFace(msr) + .translate(0, dialPivot, dialPivot) + .rotate(Direction.EAST, (float) (Math.PI / 2 * -progress)) + .translate(0, -dialPivot, -dialPivot); + + getFirst().getInstance().setTransform(ms); + + ms.pop(); + } + + protected MatrixStacker rotateToFace(MatrixStacker msr) { + return msr.centre() + .rotate(Direction.UP, (float) ((-face.getHorizontalAngle() - 90) / 180 * Math.PI)) + .unCentre(); + } + + private void delete() { + getFirst().delete(); + getSecond().delete(); + } + } + + public static class Speed extends GaugeInstance { + public Speed(InstancedTileRenderer dispatcher, KineticTileEntity tile) { + super(dispatcher, tile); + } + + @Override + protected InstancedModel getHeadModel() { + return modelManager.getMaterial(RenderMaterials.MODELS).getModel(AllBlockPartials.GAUGE_HEAD_SPEED, lastState); + } + } + + public static class Stress extends GaugeInstance { + public Stress(InstancedTileRenderer dispatcher, KineticTileEntity tile) { + super(dispatcher, tile); + } + + @Override + protected InstancedModel getHeadModel() { + return modelManager.getMaterial(RenderMaterials.MODELS).getModel(AllBlockPartials.GAUGE_HEAD_STRESS, lastState); + } + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/GaugeRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/GaugeRenderer.java index 3085dae58..bc89519bb 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/GaugeRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/GaugeRenderer.java @@ -7,6 +7,7 @@ import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.content.contraptions.relays.gauge.GaugeBlock.Type; import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; import com.simibubi.create.foundation.utility.Iterate; import net.minecraft.block.BlockState; @@ -37,6 +38,8 @@ public class GaugeRenderer extends KineticTileEntityRenderer { @Override protected void renderSafe(KineticTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay) { + if (FastRenderDispatcher.available(te.getWorld())) return; + super.renderSafe(te, partialTicks, ms, buffer, light, overlay); BlockState gaugeState = te.getBlockState(); GaugeTileEntity gaugeTE = (GaugeTileEntity) te; @@ -47,14 +50,14 @@ public class GaugeRenderer extends KineticTileEntityRenderer { .renderOn(gaugeState); SuperByteBuffer dialBuffer = AllBlockPartials.GAUGE_DIAL.renderOn(gaugeState); + float dialPivot = 5.75f / 16; + float progress = MathHelper.lerp(partialTicks, gaugeTE.prevDialState, gaugeTE.dialState); + for (Direction facing : Iterate.directions) { if (!((GaugeBlock) gaugeState.getBlock()).shouldRenderHeadOnFace(te.getWorld(), te.getPos(), gaugeState, facing)) continue; - float dialPivot = 5.75f / 16; - float progress = MathHelper.lerp(partialTicks, gaugeTE.prevDialState, gaugeTE.dialState); - IVertexBuilder vb = buffer.getBuffer(RenderType.getSolid()); rotateBufferTowards(dialBuffer, facing).translate(0, dialPivot, dialPivot) .rotate(Direction.EAST, (float) (Math.PI / 2 * -progress)) diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/gearbox/GearboxInstance.java b/src/main/java/com/simibubi/create/content/contraptions/relays/gearbox/GearboxInstance.java index 60c4ec81f..ec75b02a6 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/gearbox/GearboxInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/gearbox/GearboxInstance.java @@ -99,14 +99,7 @@ public class GearboxInstance extends KineticTileInstance { @Override public void updateLight() { - int blockLight = tile.getWorld().getLightLevel(LightType.BLOCK, pos); - int skyLight = tile.getWorld().getLightLevel(LightType.SKY, pos); - - for (InstanceKey key : keys.values()) { - key.getInstance() - .setBlockLight(blockLight) - .setSkyLight(skyLight); - } + relight(pos, keys.values().stream().map(InstanceKey::getInstance)); } @Override diff --git a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInstance.java b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInstance.java index c8a527490..7a504c7b1 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInstance.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInstance.java @@ -73,7 +73,7 @@ public class ArmInstance extends SingleRotatingInstance implements ITickableInst public void tick() { ArmTileEntity arm = (ArmTileEntity) tile; - boolean settled = Stream.of(arm.baseAngle, arm.lowerArmAngle, arm.upperArmAngle, arm.headAngle).allMatch(InterpolatedValue::settled); + boolean settled = arm.baseAngle.settled() && arm.lowerArmAngle.settled() && arm.upperArmAngle.settled() && arm.headAngle.settled(); boolean rave = arm.phase == ArmTileEntity.Phase.DANCING; if (!settled || rave || firstTick) @@ -154,13 +154,8 @@ public class ArmInstance extends SingleRotatingInstance implements ITickableInst @Override public void updateLight() { super.updateLight(); - int block = world.getLightLevel(LightType.BLOCK, pos); - int sky = world.getLightLevel(LightType.SKY, pos); - - models.stream() - .map(InstanceKey::getInstance) - .forEach(data -> data.setSkyLight(sky).setBlockLight(block)); + relight(pos, models.stream().map(InstanceKey::getInstance)); } @Override diff --git a/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonInstance.java b/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonInstance.java index 307a8e6b1..97f27b930 100644 --- a/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonInstance.java +++ b/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonInstance.java @@ -81,15 +81,6 @@ public class SchematicannonInstance extends TileEntityInstance extends BufferedMod protected int minIndexChanged = -1; protected int maxIndexChanged = -1; + protected boolean anyToRemove; + public InstancedModel(InstancedTileRenderer renderer, BufferBuilder buf) { super(buf); this.renderer = renderer; @@ -73,6 +75,8 @@ public abstract class InstancedModel extends BufferedMod verifyKey(key); key.invalidate(); + + anyToRemove = true; } public D getInstance(InstanceKey key) { @@ -161,6 +165,8 @@ public abstract class InstancedModel extends BufferedMod // copied from ArrayList#removeIf protected boolean doRemoval() { + if (!anyToRemove) return false; + // figure out which elements are to be removed // any exception thrown from the filter predicate at this stage // will leave the collection unmodified @@ -198,6 +204,8 @@ public abstract class InstancedModel extends BufferedMod maxIndexChanged = newSize - 1; } + this.anyToRemove = false; + return anyToRemove; } diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/InstancedTileRenderer.java b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/InstancedTileRenderer.java index 21131fe32..5871c5d8e 100644 --- a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/InstancedTileRenderer.java +++ b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/InstancedTileRenderer.java @@ -6,8 +6,10 @@ import javax.annotation.Nullable; import com.simibubi.create.foundation.ponder.PonderWorld; import com.simibubi.create.foundation.render.backend.Backend; +import com.simibubi.create.foundation.render.backend.RenderMaterials; import com.simibubi.create.foundation.render.backend.gl.BasicProgram; import com.simibubi.create.foundation.render.backend.gl.shader.ShaderCallback; +import com.simibubi.create.foundation.render.backend.instancing.impl.ModelData; import com.simibubi.create.foundation.utility.AnimationTickHolder; import net.minecraft.client.Minecraft; @@ -67,6 +69,10 @@ public abstract class InstancedTileRenderer

{ return (RenderMaterial) materials.get(materialType); } + public RenderMaterial> basicMaterial() { + return getMaterial(RenderMaterials.MODELS); + } + @Nullable public TileEntityInstance getInstance(T tile) { return getInstance(tile, true); diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/TileEntityInstance.java b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/TileEntityInstance.java index 4e029f184..b5241999c 100644 --- a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/TileEntityInstance.java +++ b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/TileEntityInstance.java @@ -1,5 +1,6 @@ package com.simibubi.create.foundation.render.backend.instancing; +import com.simibubi.create.foundation.render.backend.instancing.impl.IFlatLight; import com.simibubi.create.foundation.render.backend.instancing.impl.ModelData; import net.minecraft.block.BlockState; import net.minecraft.tileentity.TileEntity; @@ -7,6 +8,9 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.world.LightType; import net.minecraft.world.World; +import java.util.Arrays; +import java.util.stream.Stream; + public abstract class TileEntityInstance { protected final InstancedTileRenderer modelManager; @@ -60,13 +64,19 @@ public abstract class TileEntityInstance { return pos.subtract(modelManager.getOriginCoordinate()); } - protected void relight(BlockPos pos, ModelData... models) { + protected > void relight(BlockPos pos, IFlatLight... models) { relight(world.getLightLevel(LightType.BLOCK, pos), world.getLightLevel(LightType.SKY, pos), models); } - protected void relight(int block, int sky, ModelData... models) { - for (ModelData model : models) { - model.setBlockLight(block).setSkyLight(sky); - } + protected > void relight(BlockPos pos, Stream> models) { + relight(world.getLightLevel(LightType.BLOCK, pos), world.getLightLevel(LightType.SKY, pos), models); + } + + protected > void relight(int block, int sky, IFlatLight... models) { + relight(block, sky, Arrays.stream(models)); + } + + protected > void relight(int block, int sky, Stream> models) { + models.forEach(model -> model.setBlockLight(block).setSkyLight(sky)); } } diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/IFlatLight.java b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/IFlatLight.java new file mode 100644 index 000000000..7dea998b1 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/IFlatLight.java @@ -0,0 +1,26 @@ +package com.simibubi.create.foundation.render.backend.instancing.impl; + +import com.simibubi.create.foundation.render.backend.instancing.InstanceData; + +/** + * An interface that implementors of {@link InstanceData} should also implement + * if they wish to make use of Flywheel's provided light update methods. + * + * This only covers flat lighting, smooth lighting is still TODO. + * @param The name of the class that implements this interface. + */ +public interface IFlatLight> { + /** + * @param blockLight An integer in the range [0, 15] representing the + * amount of block light this instance should receive. + * @return this + */ + D setBlockLight(int blockLight); + + /** + * @param skyLight An integer in the range [0, 15] representing the + * amount of sky light this instance should receive. + * @return this + */ + D setSkyLight(int skyLight); +} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/ModelData.java b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/ModelData.java index 350c8e4ad..4b0a93a9a 100644 --- a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/ModelData.java +++ b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/ModelData.java @@ -9,7 +9,7 @@ import net.minecraft.client.renderer.Matrix4f; import java.nio.ByteBuffer; -public class ModelData extends InstanceData { +public class ModelData extends InstanceData implements IFlatLight { private static final Matrix4f IDENT4 = new Matrix4f(); private static final Matrix3f IDENT3 = new Matrix3f(); static { @@ -54,11 +54,13 @@ public class ModelData extends InstanceData { return this; } + @Override public ModelData setBlockLight(int blockLight) { this.blockLight = (byte) (blockLight << 4); return this; } + @Override public ModelData setSkyLight(int skyLight) { this.skyLight = (byte) (skyLight << 4); return this; diff --git a/src/main/java/com/simibubi/create/foundation/utility/Couple.java b/src/main/java/com/simibubi/create/foundation/utility/Couple.java index 9c36c903f..1c0cf6153 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/Couple.java +++ b/src/main/java/com/simibubi/create/foundation/utility/Couple.java @@ -6,6 +6,7 @@ import java.util.function.BiConsumer; import java.util.function.BiFunction; import java.util.function.Consumer; import java.util.function.Function; +import java.util.stream.Stream; import com.google.common.base.Supplier; import com.google.common.collect.ImmutableList; @@ -104,6 +105,10 @@ public class Couple extends Pair implements Iterable { return new Couplerator<>(this); } + public Stream stream() { + return Stream.of(first, second); + } + private static class Couplerator implements Iterator { int state; diff --git a/src/main/java/com/simibubi/create/foundation/utility/MatrixStacker.java b/src/main/java/com/simibubi/create/foundation/utility/MatrixStacker.java index 0323a1ebb..8ebc71b26 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/MatrixStacker.java +++ b/src/main/java/com/simibubi/create/foundation/utility/MatrixStacker.java @@ -24,6 +24,15 @@ public class MatrixStacker { return instance; } + public MatrixStacker restoreIdentity() { + MatrixStack.Entry entry = ms.peek(); + + entry.getModel().loadIdentity(); + entry.getNormal().loadIdentity(); + + return this; + } + public MatrixStacker rotate(Direction axis, float radians) { if (radians == 0) return this; diff --git a/src/main/java/com/simibubi/create/foundation/utility/animation/LerpedFloat.java b/src/main/java/com/simibubi/create/foundation/utility/animation/LerpedFloat.java index b0f22f545..7e99e39cb 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/animation/LerpedFloat.java +++ b/src/main/java/com/simibubi/create/foundation/utility/animation/LerpedFloat.java @@ -81,6 +81,10 @@ public class LerpedFloat { return MathHelper.lerp(partialTicks, previousValue, value); } + public boolean settled() { + return MathHelper.epsilonEquals(previousValue, value); + } + public float getChaseTarget() { return chaseTarget; }