From b9f6a3b94e055aa8e78c144515c613ba04ed9ec6 Mon Sep 17 00:00:00 2001 From: JozsefA Date: Wed, 31 Mar 2021 16:19:58 -0700 Subject: [PATCH] Instanced bearings --- .../com/simibubi/create/AllTileEntities.java | 11 +-- .../NonStationaryLighter.java | 9 --- .../bearing/BearingInstance.java | 77 +++++++++++++++++++ .../bearing/BearingRenderer.java | 4 + .../bearing/StabilizedBearingInstance.java | 51 ++++++++++++ .../StabilizedBearingMovementBehaviour.java | 58 ++++++++++---- .../foundation/render/SuperByteBuffer.java | 10 +++ 7 files changed, 189 insertions(+), 31 deletions(-) create mode 100644 src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BearingInstance.java create mode 100644 src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/StabilizedBearingInstance.java diff --git a/src/main/java/com/simibubi/create/AllTileEntities.java b/src/main/java/com/simibubi/create/AllTileEntities.java index 9a6671797..219269b08 100644 --- a/src/main/java/com/simibubi/create/AllTileEntities.java +++ b/src/main/java/com/simibubi/create/AllTileEntities.java @@ -50,10 +50,7 @@ import com.simibubi.create.content.contraptions.components.press.PressInstance; import com.simibubi.create.content.contraptions.components.saw.SawInstance; import com.simibubi.create.content.contraptions.components.saw.SawRenderer; import com.simibubi.create.content.contraptions.components.saw.SawTileEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.bearing.BearingRenderer; -import com.simibubi.create.content.contraptions.components.structureMovement.bearing.ClockworkBearingTileEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.bearing.MechanicalBearingTileEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.bearing.WindmillBearingTileEntity; +import com.simibubi.create.content.contraptions.components.structureMovement.bearing.*; import com.simibubi.create.content.contraptions.components.structureMovement.chassis.ChassisTileEntity; import com.simibubi.create.content.contraptions.components.structureMovement.chassis.StickerInstance; import com.simibubi.create.content.contraptions.components.structureMovement.chassis.StickerRenderer; @@ -380,21 +377,21 @@ public class AllTileEntities { public static final TileEntityEntry WINDMILL_BEARING = Create.registrate() .tileEntity("windmill_bearing", WindmillBearingTileEntity::new) - .instance(() -> BackHalfShaftInstance::new) + .instance(() -> BearingInstance::new) .validBlocks(AllBlocks.WINDMILL_BEARING) .renderer(() -> BearingRenderer::new) .register(); public static final TileEntityEntry MECHANICAL_BEARING = Create.registrate() .tileEntity("mechanical_bearing", MechanicalBearingTileEntity::new) - .instance(() -> BackHalfShaftInstance::new) + .instance(() -> BearingInstance::new) .validBlocks(AllBlocks.MECHANICAL_BEARING) .renderer(() -> BearingRenderer::new) .register(); public static final TileEntityEntry CLOCKWORK_BEARING = Create.registrate() .tileEntity("clockwork_bearing", ClockworkBearingTileEntity::new) - .instance(() -> BackHalfShaftInstance::new) + .instance(() -> BearingInstance::new) .validBlocks(AllBlocks.CLOCKWORK_BEARING) .renderer(() -> BearingRenderer::new) .register(); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/NonStationaryLighter.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/NonStationaryLighter.java index c20a34145..6474b583c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/NonStationaryLighter.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/NonStationaryLighter.java @@ -8,15 +8,6 @@ public class NonStationaryLighter extends ContraptionLigh super(contraption); } - @Override - protected GridAlignedBB contraptionBoundsToVolume(GridAlignedBB bounds) { - bounds.grow(2); // so we have at least enough data on the edges to avoid artifacts and have smooth lighting - bounds.minY = Math.max(bounds.minY, 0); - bounds.maxY = Math.min(bounds.maxY, 255); - - return bounds; - } - @Override public void tick(RenderedContraption owner) { super.tick(owner); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BearingInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BearingInstance.java new file mode 100644 index 000000000..cb8177452 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BearingInstance.java @@ -0,0 +1,77 @@ +package com.simibubi.create.content.contraptions.components.structureMovement.bearing; + +import net.minecraft.client.renderer.Quaternion; +import net.minecraft.client.renderer.Vector3f; +import net.minecraft.state.properties.BlockStateProperties; +import net.minecraft.util.Direction; + +import com.simibubi.create.AllBlockPartials; +import com.simibubi.create.content.contraptions.base.BackHalfShaftInstance; +import com.simibubi.create.content.contraptions.base.KineticTileEntity; +import com.simibubi.create.foundation.render.backend.core.OrientedData; +import com.simibubi.create.foundation.render.backend.instancing.IDynamicInstance; +import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; +import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.AnimationTickHolder; + +public class BearingInstance extends BackHalfShaftInstance implements IDynamicInstance { + final B bearing; + + final OrientedData topInstance; + + final Vector3f rotationAxis; + final Quaternion blockOrientation; + + public BearingInstance(InstancedTileRenderer modelManager, B tile) { + super(modelManager, tile); + this.bearing = tile; + + Direction facing = blockState.get(BlockStateProperties.FACING); + rotationAxis = Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, axis).getUnitVector(); + + blockOrientation = getBlockStateOrientation(facing); + + AllBlockPartials top = + bearing.isWoodenTop() ? AllBlockPartials.BEARING_TOP_WOODEN : AllBlockPartials.BEARING_TOP; + + topInstance = getOrientedMaterial().getModel(top, blockState).createInstance(); + + topInstance.setPosition(getInstancePosition()).setRotation(blockOrientation); + } + + @Override + public void beginFrame() { + + float interpolatedAngle = bearing.getInterpolatedAngle(AnimationTickHolder.getPartialTicks() - 1); + Quaternion rot = rotationAxis.getDegreesQuaternion(interpolatedAngle); + + rot.multiply(blockOrientation); + + topInstance.setRotation(rot); + } + + @Override + public void updateLight() { + super.updateLight(); + relight(pos, topInstance); + } + + @Override + public void remove() { + super.remove(); + topInstance.delete(); + } + + static Quaternion getBlockStateOrientation(Direction facing) { + Quaternion orientation; + + if (facing.getAxis().isHorizontal()) { + orientation = Vector3f.POSITIVE_Y.getDegreesQuaternion(AngleHelper.horizontalAngle(facing.getOpposite())); + } else { + orientation = Quaternion.IDENTITY.copy(); + } + + orientation.multiply(Vector3f.POSITIVE_X.getDegreesQuaternion(-90 - AngleHelper.verticalAngle(facing))); + return orientation; + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BearingRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BearingRenderer.java index f94d29e89..6a81320bd 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BearingRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BearingRenderer.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 net.minecraft.client.renderer.IRenderTypeBuffer; @@ -22,6 +23,9 @@ public class BearingRenderer 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); IBearingTileEntity bearingTe = (IBearingTileEntity) te; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/StabilizedBearingInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/StabilizedBearingInstance.java new file mode 100644 index 000000000..90d4b9bd5 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/StabilizedBearingInstance.java @@ -0,0 +1,51 @@ +package com.simibubi.create.content.contraptions.components.structureMovement.bearing; + +import net.minecraft.block.BlockState; +import net.minecraft.client.renderer.Quaternion; +import net.minecraft.client.renderer.Vector3f; +import net.minecraft.state.properties.BlockStateProperties; +import net.minecraft.util.Direction; + +import com.simibubi.create.AllBlockPartials; +import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; +import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance; +import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionKineticRenderer; +import com.simibubi.create.foundation.render.backend.core.OrientedData; +import com.simibubi.create.foundation.utility.AnimationTickHolder; + +public class StabilizedBearingInstance extends ActorInstance { + + final OrientedData topInstance; + + final Direction facing; + final Vector3f rotationAxis; + final Quaternion blockOrientation; + + public StabilizedBearingInstance(ContraptionKineticRenderer modelManager, MovementContext context) { + super(modelManager, context); + + BlockState blockState = context.state; + + facing = blockState.get(BlockStateProperties.FACING); + rotationAxis = Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, facing.getAxis()).getUnitVector(); + + blockOrientation = BearingInstance.getBlockStateOrientation(facing); + + topInstance = modelManager.getOrientedMaterial().getModel(AllBlockPartials.BEARING_TOP, blockState).createInstance(); + + topInstance.setPosition(context.localPos) + .setRotation(blockOrientation) + .setBlockLight(localBlockLight()); + } + + @Override + public void beginFrame() { + float counterRotationAngle = StabilizedBearingMovementBehaviour.getCounterRotationAngle(context, facing, AnimationTickHolder.getPartialTicks()); + + Quaternion rotation = rotationAxis.getDegreesQuaternion(counterRotationAngle); + + rotation.multiply(blockOrientation); + + topInstance.setRotation(rotation); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/StabilizedBearingMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/StabilizedBearingMovementBehaviour.java index b2a517625..fda46bb8d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/StabilizedBearingMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/StabilizedBearingMovementBehaviour.java @@ -7,12 +7,16 @@ import com.simibubi.create.content.contraptions.components.structureMovement.Con import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; import com.simibubi.create.content.contraptions.components.structureMovement.OrientedContraptionEntity; +import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance; +import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionKineticRenderer; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; 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.AnimationTickHolder; import net.minecraft.client.renderer.IRenderTypeBuffer; +import net.minecraft.client.renderer.Quaternion; import net.minecraft.client.renderer.RenderType; import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.util.Direction; @@ -20,28 +24,57 @@ import net.minecraft.util.Direction.Axis; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; +import javax.annotation.Nullable; + public class StabilizedBearingMovementBehaviour extends MovementBehaviour { @Override @OnlyIn(Dist.CLIENT) public void renderInContraption(MovementContext context, MatrixStack ms, MatrixStack msLocal, IRenderTypeBuffer buffer) { + if (FastRenderDispatcher.available()) return; + Direction facing = context.state.get(BlockStateProperties.FACING); AllBlockPartials top = AllBlockPartials.BEARING_TOP; SuperByteBuffer superBuffer = top.renderOn(context.state); float renderPartialTicks = AnimationTickHolder.getPartialTicks(); // rotate to match blockstate - Axis axis = facing.getAxis(); - if (axis.isHorizontal()) - superBuffer.rotateCentered(Direction.UP, - AngleHelper.rad(AngleHelper.horizontalAngle(facing.getOpposite()))); - superBuffer.rotateCentered(Direction.EAST, AngleHelper.rad(-90 - AngleHelper.verticalAngle(facing))); + Quaternion orientation = BearingInstance.getBlockStateOrientation(facing); // rotate against parent + float angle = getCounterRotationAngle(context, facing, renderPartialTicks) * facing.getAxisDirection().getOffset(); + + Quaternion rotation = facing.getUnitVector().getDegreesQuaternion(angle); + + rotation.multiply(orientation); + + orientation = rotation; + + superBuffer.rotateCentered(orientation); + + // render + superBuffer.light(msLocal.peek() + .getModel(), ContraptionRenderDispatcher.getLightOnContraption(context)); + superBuffer.renderInto(ms, buffer.getBuffer(RenderType.getSolid())); + } + + @Override + public boolean hasSpecialInstancedRendering() { + return true; + } + + @Nullable + @Override + public ActorInstance createInstance(ContraptionKineticRenderer kr, MovementContext context) { + return new StabilizedBearingInstance(kr, context); + } + + static float getCounterRotationAngle(MovementContext context, Direction facing, float renderPartialTicks) { float offset = 0; - int offsetMultiplier = facing.getAxisDirection().getOffset(); - + + Axis axis = facing.getAxis(); + AbstractContraptionEntity entity = context.contraption.entity; if (entity instanceof ControlledContraptionEntity) { ControlledContraptionEntity controlledCE = (ControlledContraptionEntity) entity; @@ -54,17 +87,12 @@ public class StabilizedBearingMovementBehaviour extends MovementBehaviour { offset = -orientedCE.getYaw(renderPartialTicks); else { if (orientedCE.isInitialOrientationPresent() && orientedCE.getInitialOrientation() - .getAxis() == axis) + .getAxis() == axis) offset = -orientedCE.getPitch(renderPartialTicks); } } - if (offset != 0) - superBuffer.rotateCentered(Direction.UP, AngleHelper.rad(offset * offsetMultiplier)); - - // render - superBuffer.light(msLocal.peek() - .getModel(), ContraptionRenderDispatcher.getLightOnContraption(context)); - superBuffer.renderInto(ms, buffer.getBuffer(RenderType.getSolid())); + return offset; } + } diff --git a/src/main/java/com/simibubi/create/foundation/render/SuperByteBuffer.java b/src/main/java/com/simibubi/create/foundation/render/SuperByteBuffer.java index 840f5f0f0..e0e13802f 100644 --- a/src/main/java/com/simibubi/create/foundation/render/SuperByteBuffer.java +++ b/src/main/java/com/simibubi/create/foundation/render/SuperByteBuffer.java @@ -196,11 +196,21 @@ public class SuperByteBuffer extends TemplateBuffer { return this; } + public SuperByteBuffer rotate(Quaternion q) { + transforms.multiply(q); + return this; + } + public SuperByteBuffer rotateCentered(Direction axis, float radians) { return translate(.5f, .5f, .5f).rotate(axis, radians) .translate(-.5f, -.5f, -.5f); } + public SuperByteBuffer rotateCentered(Quaternion q) { + return translate(.5f, .5f, .5f).rotate(q) + .translate(-.5f, -.5f, -.5f); + } + public SuperByteBuffer shiftUV(SpriteShiftEntry entry) { this.spriteShiftFunc = (builder, u, v) -> { float targetU = entry.getTarget().getInterpolatedU((getUnInterpolatedU(entry.getOriginal(), u)));