Instanced bearings

This commit is contained in:
JozsefA 2021-03-31 16:19:58 -07:00
parent b743e00978
commit b9f6a3b94e
7 changed files with 189 additions and 31 deletions

View file

@ -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<WindmillBearingTileEntity> 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<MechanicalBearingTileEntity> 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<ClockworkBearingTileEntity> CLOCKWORK_BEARING = Create.registrate()
.tileEntity("clockwork_bearing", ClockworkBearingTileEntity::new)
.instance(() -> BackHalfShaftInstance::new)
.instance(() -> BearingInstance::new)
.validBlocks(AllBlocks.CLOCKWORK_BEARING)
.renderer(() -> BearingRenderer::new)
.register();

View file

@ -8,15 +8,6 @@ public class NonStationaryLighter<C extends Contraption> 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);

View file

@ -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<B extends KineticTileEntity & IBearingTileEntity> 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;
}
}

View file

@ -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;

View file

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

View file

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

View file

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