Angle aligned rotation

This commit is contained in:
grimmauld 2021-04-17 23:05:24 +02:00
parent 53e1f0f416
commit ff6b80ee9f
6 changed files with 117 additions and 59 deletions

View File

@ -2,6 +2,7 @@ package com.simibubi.create.content.optics;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import net.minecraft.util.LazyValue;
import net.minecraft.util.math.vector.Vector3d; import net.minecraft.util.math.vector.Vector3d;
public class BeamSegment { public class BeamSegment {
@ -9,12 +10,14 @@ public class BeamSegment {
private final Vector3d direction; private final Vector3d direction;
private final Vector3d start; private final Vector3d start;
private int length; private int length;
private final LazyValue<Vector3d> normalized;
public BeamSegment(@Nonnull float[] color, Vector3d start, Vector3d direction) { public BeamSegment(@Nonnull float[] color, Vector3d start, Vector3d direction) {
this.colors = color; this.colors = color;
this.direction = direction; this.direction = direction;
this.start = start; this.start = start;
this.length = 1; this.length = 1;
this.normalized = new LazyValue<>(direction::normalize);
} }
public void incrementLength() { public void incrementLength() {
@ -36,4 +39,8 @@ public class BeamSegment {
public Vector3d getStart() { public Vector3d getStart() {
return start; return start;
} }
public Vector3d getNormalized() {
return normalized.getValue();
}
} }

View File

@ -1,34 +1,77 @@
package com.simibubi.create.content.optics; package com.simibubi.create.content.optics;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import javax.annotation.Nullable;
import com.simibubi.create.foundation.utility.BeaconHelper;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.item.DyeColor;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.RayTraceContext;
import net.minecraft.util.math.vector.Vector3d; import net.minecraft.util.math.vector.Vector3d;
import net.minecraft.util.math.vector.Vector3f;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
public interface ILightHandler<T extends TileEntity & ILightHandler<T>> { public interface ILightHandler<T extends TileEntity & ILightHandler<T>> {
Vector3d getBeamDirection(); Vector3d getBeamDirection();
default double getBeamLenght() { default Collection<BeamSegment> constructOutBeam(Vector3d beamDirection) {
T te = getTile(); ArrayList<BeamSegment> beam = new ArrayList<>();
World world = te.getWorld(); float[] segmentColor = getSegmentStartColor();
BlockPos pos = te.getPos(); World world = getTile().getWorld();
if (pos == BlockPos.ZERO || world == null) if (world == null)
return 0; return beam;
Vector3d direction = VecHelper.step(beamDirection);
Vector3d testPos = VecHelper.getCenterOf(getTile().getPos());
Vector3d direction = getBeamDirection(); BeamSegment segment = new BeamSegment(segmentColor, testPos, direction);
BlockRayTraceResult raytrace = world beam.add(segment);
.rayTraceBlocks(new RayTraceContext(Vector3d.of(pos).add(direction),
direction.normalize()
.scale(128)
.add(Vector3d.of(pos)),
RayTraceContext.BlockMode.OUTLINE, RayTraceContext.FluidMode.NONE, null));
return Vector3d.of(raytrace.getPos() for (int i = 0; i < 128; i++) {
.subtract(pos)) testPos = testPos.add(direction); // check next block
.length(); BlockPos testBlockPos = new BlockPos(testPos.x, testPos.y, testPos.z);
BlockState testState = world.getBlockState(testBlockPos);
float[] newColor = BeaconHelper.getBeaconColorAt(testState.getBlock());
if (newColor == null) {
TileEntity te = testState.hasTileEntity() ? world.getTileEntity(testBlockPos) : null;
if (testState.getOpacity(world, testBlockPos) >= 15 && testState.getBlock() != Blocks.BEDROCK || te instanceof ILightHandler) {
if (te instanceof ILightHandler) {
((ILightHandler<?>) te).setColor(segmentColor);
}
break;
}
} else if (!Arrays.equals(segmentColor, newColor)) {
segmentColor = new float[]{(segment.colors[0] + newColor[0]) / 2.0F, (segment.colors[1] + newColor[1]) / 2.0F, (segment.colors[2] + newColor[2]) / 2.0F};
segment = new BeamSegment(newColor, testPos, direction);
beam.add(segment);
continue;
}
segment.incrementLength();
}
return beam;
} }
T getTile(); T getTile();
default void setColor(float[] segmentColor) {
}
default float[] getSegmentStartColor() {
return DyeColor.WHITE.getColorComponentValues();
}
@Nullable
@OnlyIn(Dist.CLIENT)
default Vector3f getBeamRotationAround() {
return null;
}
} }

View File

@ -1,5 +1,6 @@
package com.simibubi.create.content.optics.mirror; package com.simibubi.create.content.optics.mirror;
import static com.simibubi.create.foundation.utility.VecHelper.UP;
import static net.minecraft.client.renderer.tileentity.BeaconTileEntityRenderer.TEXTURE_BEACON_BEAM; import static net.minecraft.client.renderer.tileentity.BeaconTileEntityRenderer.TEXTURE_BEACON_BEAM;
import javax.annotation.ParametersAreNonnullByDefault; import javax.annotation.ParametersAreNonnullByDefault;
@ -67,16 +68,16 @@ public class MirrorRenderer extends KineticTileEntityRenderer {
MirrorTileEntity mirrorTe = (MirrorTileEntity) te; MirrorTileEntity mirrorTe = (MirrorTileEntity) te;
renderMirror(mirrorTe, partialTicks, ms, buffer, light); renderMirror(mirrorTe, partialTicks, ms, buffer, light);
renderOutBeam(mirrorTe, partialTicks, ms, buffer, light); renderOutBeam(mirrorTe, partialTicks, ms, buffer);
} }
private void renderOutBeam(MirrorTileEntity mirrorTe, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer, int light) { private void renderOutBeam(MirrorTileEntity mirrorTe, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer) {
int start = 0; int start = 0;
for (int k = 0; k < mirrorTe.beam.size(); k++) { for (int k = 0; k < mirrorTe.beam.size(); k++) {
BeamSegment beamSegment = mirrorTe.beam.get(k); BeamSegment beamSegment = mirrorTe.beam.get(k);
renderSegment(beamSegment, ms, buffer, partialTicks, mirrorTe.getWorld() renderSegment(mirrorTe, beamSegment, ms, buffer, partialTicks, mirrorTe.getWorld()
.getGameTime(), .getGameTime(),
beamSegment.getDirection() beamSegment.getDirection()
.scale(start + beamSegment.getLength()) .scale(start + beamSegment.getLength())
@ -85,9 +86,15 @@ public class MirrorRenderer extends KineticTileEntityRenderer {
} }
} }
private void renderSegment(BeamSegment beamSegment, MatrixStack ms, IRenderTypeBuffer buffer, float partialTicks, long gameTime, double length) { private void renderSegment(MirrorTileEntity mirrorTe, BeamSegment beamSegment, MatrixStack ms, IRenderTypeBuffer buffer, float partialTicks, long gameTime, double length) {
float adjustedGameTime = (float) Math.floorMod(gameTime, 40L) + partialTicks; float adjustedGameTime = (float) Math.floorMod(gameTime, 40L) + partialTicks;
ms.push(); ms.push();
ms.translate(0, 0.5D, 0.5D);
ms.multiply(mirrorTe.getBeamRotationAround()
.getRadialQuaternion((float) Math.acos(beamSegment.getNormalized()
.dotProduct(UP))));
ms.translate(0, -0.5D, -0.5D);
ms.push();
ms.translate(0.5D, 0.0D, 0.5D); ms.translate(0.5D, 0.0D, 0.5D);
ms.push(); ms.push();
ms.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(adjustedGameTime * 2.25F - 45.0F)); ms.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(adjustedGameTime * 2.25F - 45.0F));
@ -97,6 +104,7 @@ public class MirrorRenderer extends KineticTileEntityRenderer {
method_22741(ms, buffer.getBuffer(RenderType.getBeaconBeam(TEXTURE_BEACON_BEAM, true)), beamSegment.colors, 1F, MathHelper.floor(length - beamSegment.getLength()), MathHelper.floor(length), 0F, 0.2F, .2F, 0F, -.2f, 0f, 0f, -.2f, 0f, 1f, f16, f15); method_22741(ms, buffer.getBuffer(RenderType.getBeaconBeam(TEXTURE_BEACON_BEAM, true)), beamSegment.colors, 1F, MathHelper.floor(length - beamSegment.getLength()), MathHelper.floor(length), 0F, 0.2F, .2F, 0F, -.2f, 0f, 0f, -.2f, 0f, 1f, f16, f15);
ms.pop(); ms.pop();
ms.pop(); ms.pop();
ms.pop();
} }
private void renderMirror(MirrorTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer, int light) { private void renderMirror(MirrorTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer, int light) {

View File

@ -1,10 +1,11 @@
package com.simibubi.create.content.optics.mirror; package com.simibubi.create.content.optics.mirror;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import javax.annotation.Nonnull;
import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.content.optics.BeamSegment; import com.simibubi.create.content.optics.BeamSegment;
import com.simibubi.create.content.optics.ILightHandler; import com.simibubi.create.content.optics.ILightHandler;
@ -15,19 +16,23 @@ import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.item.DyeColor; import net.minecraft.item.DyeColor;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.tileentity.BeaconTileEntity; import net.minecraft.tileentity.BeaconTileEntity;
import net.minecraft.tileentity.TileEntityType; import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.vector.Vector3d; import net.minecraft.util.math.vector.Vector3d;
import net.minecraft.util.math.vector.Vector3f;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
public class MirrorTileEntity extends KineticTileEntity implements ILightHandler<MirrorTileEntity> { public class MirrorTileEntity extends KineticTileEntity implements ILightHandler<MirrorTileEntity> {
public final List<BeamSegment> beam; public final List<BeamSegment> beam;
protected float angle; protected float angle;
protected float clientAngleDiff; protected float clientAngleDiff;
private float prevAngle; private float prevAngle;
private double length;
private Optional<BeaconTileEntity> beacon; private Optional<BeaconTileEntity> beacon;
private float[] initialColor = DyeColor.WHITE.getColorComponentValues();
public MirrorTileEntity(TileEntityType<?> typeIn) { public MirrorTileEntity(TileEntityType<?> typeIn) {
super(typeIn); super(typeIn);
@ -44,10 +49,7 @@ public class MirrorTileEntity extends KineticTileEntity implements ILightHandler
@Override @Override
protected void fromTag(BlockState state, CompoundNBT compound, boolean clientPacket) { protected void fromTag(BlockState state, CompoundNBT compound, boolean clientPacket) {
if (wasMoved) {
super.fromTag(state, compound, clientPacket); super.fromTag(state, compound, clientPacket);
return;
}
angle = compound.getFloat("Angle"); angle = compound.getFloat("Angle");
super.fromTag(state, compound, clientPacket); super.fromTag(state, compound, clientPacket);
@ -87,29 +89,8 @@ public class MirrorTileEntity extends KineticTileEntity implements ILightHandler
public void lazyTick() { public void lazyTick() {
super.lazyTick(); super.lazyTick();
beacon = BeaconHelper.getBeaconTE(pos, world); beacon = BeaconHelper.getBeaconTE(pos, world);
length = getBeamLenght();
if (length < 1)
return;
Vector3d direction = VecHelper.step(getBeamDirection());
Vector3d startPos = VecHelper.getCenterOf(getPos());
beam.clear(); beam.clear();
beam.addAll(constructOutBeam(getBeamDirection()));
float[] startColor = DyeColor.WHITE.getColorComponentValues(); // TODO: Add mirroring of color
BeamSegment segment = new BeamSegment(startColor, startPos, direction);
for (int i = 0; i < length; i++) {
startPos = startPos.add(direction); // check next block
float[] newColor = BeaconHelper.getBeaconColorAt(startPos, world);
if (newColor != null && !Arrays.equals(startColor, newColor)) {
beam.add(segment);
startColor = new float[]{(segment.colors[0] + newColor[0]) / 2.0F, (segment.colors[1] + newColor[1]) / 2.0F, (segment.colors[2] + newColor[2]) / 2.0F};
segment = new BeamSegment(newColor, startPos, direction);
} else {
segment.incrementLength();
}
}
beam.add(segment);
} }
@Override @Override
@ -117,10 +98,6 @@ public class MirrorTileEntity extends KineticTileEntity implements ILightHandler
return true; return true;
} }
public void setAngle(float forcedAngle) {
angle = forcedAngle;
}
@Override @Override
public Vector3d getBeamDirection() { public Vector3d getBeamDirection() {
// TODO: Implement properly // TODO: Implement properly
@ -131,4 +108,30 @@ public class MirrorTileEntity extends KineticTileEntity implements ILightHandler
public MirrorTileEntity getTile() { public MirrorTileEntity getTile() {
return this; return this;
} }
@Override
public void setColor(float[] initialColor) {
this.initialColor = initialColor;
}
@Override
public float[] getSegmentStartColor() {
return initialColor;
}
@Nonnull
@OnlyIn(Dist.CLIENT)
@Override
public Vector3f getBeamRotationAround() {
return Direction.getFacingFromAxisDirection(getBlockState().get(BlockStateProperties.AXIS), Direction.AxisDirection.POSITIVE)
.getUnitVector();
}
public float getAngle() {
return angle;
}
public void setAngle(float forcedAngle) {
angle = forcedAngle;
}
} }

View File

@ -53,11 +53,7 @@ public class BeaconHelper {
} }
@Nullable @Nullable
public static float[] getBeaconColorAt(Vector3d pos, @Nullable IBlockReader world) { public static float[] getBeaconColorAt(Block block) {
if (world == null)
return null;
Block block = world.getBlockState(new BlockPos(pos.x, pos.y, pos.z))
.getBlock();
if (!(block instanceof IBeaconBeamColorProvider)) if (!(block instanceof IBeaconBeamColorProvider))
return null; return null;
return ((IBeaconBeamColorProvider) block).getColor() return ((IBeaconBeamColorProvider) block).getColor()

View File

@ -22,6 +22,7 @@ import net.minecraft.util.math.vector.Vector3i;
public class VecHelper { public class VecHelper {
public static final Vector3d CENTER_OF_ORIGIN = new Vector3d(.5, .5, .5); public static final Vector3d CENTER_OF_ORIGIN = new Vector3d(.5, .5, .5);
public static final Vector3d UP = new Vector3d(0, 1, 0);
public static Vector3d rotate(Vector3d vec, Vector3d rotationVec) { public static Vector3d rotate(Vector3d vec, Vector3d rotationVec) {
return rotate(vec, rotationVec.x, rotationVec.y, rotationVec.z); return rotate(vec, rotationVec.x, rotationVec.y, rotationVec.z);