mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-06-11 07:09:01 +02:00
153 lines
5.3 KiB
Java
153 lines
5.3 KiB
Java
package com.simibubi.create.content.logistics.trains.track;
|
|
|
|
import static com.simibubi.create.AllBlockPartials.GIRDER_SEGMENT_BOTTOM;
|
|
import static com.simibubi.create.AllBlockPartials.GIRDER_SEGMENT_MIDDLE;
|
|
import static com.simibubi.create.AllBlockPartials.GIRDER_SEGMENT_TOP;
|
|
|
|
import com.jozufozu.flywheel.backend.Backend;
|
|
import com.jozufozu.flywheel.util.transform.TransformStack;
|
|
import com.mojang.blaze3d.vertex.PoseStack;
|
|
import com.mojang.blaze3d.vertex.PoseStack.Pose;
|
|
import com.mojang.blaze3d.vertex.VertexConsumer;
|
|
import com.simibubi.create.content.logistics.trains.BezierConnection;
|
|
import com.simibubi.create.content.logistics.trains.BezierConnection.GirderAngles;
|
|
import com.simibubi.create.content.logistics.trains.BezierConnection.SegmentAngles;
|
|
import com.simibubi.create.content.logistics.trains.TrackMaterial;
|
|
import com.simibubi.create.foundation.render.CachedBufferer;
|
|
import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer;
|
|
import com.simibubi.create.foundation.utility.AngleHelper;
|
|
import com.simibubi.create.foundation.utility.Iterate;
|
|
import com.simibubi.create.foundation.utility.VecHelper;
|
|
|
|
import net.minecraft.client.renderer.LevelRenderer;
|
|
import net.minecraft.client.renderer.MultiBufferSource;
|
|
import net.minecraft.client.renderer.RenderType;
|
|
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
|
|
import net.minecraft.core.BlockPos;
|
|
import net.minecraft.core.Direction.Axis;
|
|
import net.minecraft.util.Mth;
|
|
import net.minecraft.world.level.Level;
|
|
import net.minecraft.world.level.block.Blocks;
|
|
import net.minecraft.world.level.block.state.BlockState;
|
|
import net.minecraft.world.phys.Vec3;
|
|
|
|
public class TrackRenderer extends SafeTileEntityRenderer<TrackTileEntity> {
|
|
|
|
public TrackRenderer(BlockEntityRendererProvider.Context context) {}
|
|
|
|
@Override
|
|
protected void renderSafe(TrackTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, int light,
|
|
int overlay) {
|
|
Level level = te.getLevel();
|
|
if (Backend.canUseInstancing(level))
|
|
return;
|
|
VertexConsumer vb = buffer.getBuffer(RenderType.cutoutMipped());
|
|
te.connections.values()
|
|
.forEach(bc -> renderBezierTurn(level, bc, ms, vb));
|
|
}
|
|
|
|
public static void renderBezierTurn(Level level, BezierConnection bc, PoseStack ms, VertexConsumer vb) {
|
|
if (!bc.isPrimary())
|
|
return;
|
|
|
|
ms.pushPose();
|
|
BlockPos tePosition = bc.tePositions.getFirst();
|
|
BlockState air = Blocks.AIR.defaultBlockState();
|
|
SegmentAngles[] segments = bc.getBakedSegments();
|
|
|
|
TransformStack.cast(ms)
|
|
.nudge((int) tePosition.asLong());
|
|
|
|
renderGirder(level, bc, ms, vb, tePosition);
|
|
|
|
for (int i = 1; i < segments.length; i++) {
|
|
SegmentAngles segment = segments[i];
|
|
int light = LevelRenderer.getLightColor(level, segment.lightPosition.offset(tePosition));
|
|
|
|
TrackMaterial.TrackModelHolder modelHolder = bc.getMaterial().getModelHolder();
|
|
|
|
CachedBufferer.partial(modelHolder.tie(), air)
|
|
.mulPose(segment.tieTransform.pose())
|
|
.mulNormal(segment.tieTransform.normal())
|
|
.light(light)
|
|
.renderInto(ms, vb);
|
|
|
|
for (boolean first : Iterate.trueAndFalse) {
|
|
Pose transform = segment.railTransforms.get(first);
|
|
CachedBufferer.partial(first ? modelHolder.segment_left() : modelHolder.segment_right(), air)
|
|
.mulPose(transform.pose())
|
|
.mulNormal(transform.normal())
|
|
.light(light)
|
|
.renderInto(ms, vb);
|
|
}
|
|
}
|
|
|
|
ms.popPose();
|
|
}
|
|
|
|
private static void renderGirder(Level level, BezierConnection bc, PoseStack ms, VertexConsumer vb,
|
|
BlockPos tePosition) {
|
|
if (!bc.hasGirder)
|
|
return;
|
|
|
|
BlockState air = Blocks.AIR.defaultBlockState();
|
|
GirderAngles[] girders = bc.getBakedGirders();
|
|
|
|
for (int i = 1; i < girders.length; i++) {
|
|
GirderAngles segment = girders[i];
|
|
int light = LevelRenderer.getLightColor(level, segment.lightPosition.offset(tePosition));
|
|
|
|
for (boolean first : Iterate.trueAndFalse) {
|
|
Pose beamTransform = segment.beams.get(first);
|
|
CachedBufferer.partial(GIRDER_SEGMENT_MIDDLE, air)
|
|
.mulPose(beamTransform.pose())
|
|
.mulNormal(beamTransform.normal())
|
|
.light(light)
|
|
.renderInto(ms, vb);
|
|
|
|
for (boolean top : Iterate.trueAndFalse) {
|
|
Pose beamCapTransform = segment.beamCaps.get(top)
|
|
.get(first);
|
|
CachedBufferer.partial(top ? GIRDER_SEGMENT_TOP : GIRDER_SEGMENT_BOTTOM, air)
|
|
.mulPose(beamCapTransform.pose())
|
|
.mulNormal(beamCapTransform.normal())
|
|
.light(light)
|
|
.renderInto(ms, vb);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public static Vec3 getModelAngles(Vec3 normal, Vec3 diff) {
|
|
double diffX = diff.x();
|
|
double diffY = diff.y();
|
|
double diffZ = diff.z();
|
|
double len = Mth.sqrt((float) (diffX * diffX + diffZ * diffZ));
|
|
double yaw = Mth.atan2(diffX, diffZ);
|
|
double pitch = Mth.atan2(len, diffY) - Math.PI * .5;
|
|
|
|
Vec3 yawPitchNormal = VecHelper.rotate(VecHelper.rotate(new Vec3(0, 1, 0), AngleHelper.deg(pitch), Axis.X),
|
|
AngleHelper.deg(yaw), Axis.Y);
|
|
|
|
double signum = Math.signum(yawPitchNormal.dot(normal));
|
|
if (Math.abs(signum) < 0.5f)
|
|
signum = yawPitchNormal.distanceToSqr(normal) < 0.5f ? -1 : 1;
|
|
double dot = diff.cross(normal)
|
|
.normalize()
|
|
.dot(yawPitchNormal);
|
|
double roll = Math.acos(Mth.clamp(dot, -1, 1)) * signum;
|
|
return new Vec3(pitch, yaw, roll);
|
|
}
|
|
|
|
@Override
|
|
public boolean shouldRenderOffScreen(TrackTileEntity pBlockEntity) {
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public int getViewDistance() {
|
|
return 96 * 2;
|
|
}
|
|
|
|
}
|