From d667786ee08e95690856fc5b3607a2973a3f4568 Mon Sep 17 00:00:00 2001 From: MoePus <547007249@qq.com> Date: Wed, 5 Mar 2025 00:06:20 +0900 Subject: [PATCH 1/6] fix wrong mips applied to super long chain # Conflicts: # src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorRenderer.java --- .../chainConveyor/ChainConveyorRenderer.java | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorRenderer.java b/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorRenderer.java index d3faea6d23..8ad2b59ded 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorRenderer.java +++ b/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorRenderer.java @@ -40,7 +40,7 @@ public class ChainConveyorRenderer extends KineticBlockEntityRenderer { public static final ResourceLocation CHAIN_LOCATION = ResourceLocation.withDefaultNamespace("textures/block/chain.png"); - public static final int MIP_DISTANCE = 48; + public static final int MIP_DISTANCE_SQR = 48 * 48; public ChainConveyorRenderer(Context context) { super(context); @@ -131,6 +131,15 @@ private void renderBox(ChainConveyorBlockEntity be, PoseStack ms, MultiBufferSou } } + private static Vec3 getClosestPointOnChain(Vec3 cam, Vec3 start, Vec3 end) { + Vec3 seg = end.subtract(start); + Vec3 start2cam = cam.subtract(start); + + double t = Mth.clamp(start2cam.dot(seg) / seg.lengthSqr(), 0.0, 1.0); + + return start.add(seg.scale(t)); + } + private void renderChains(ChainConveyorBlockEntity be, PoseStack ms, MultiBufferSource buffer, int light, int overlay) { float time = AnimationTickHolder.getRenderTime(be.getLevel()) / (360f / Math.abs(be.getSpeed())); @@ -183,10 +192,14 @@ private void renderChains(ChainConveyorBlockEntity be, PoseStack ms, MultiBuffer int light2 = LightTexture.pack(level.getBrightness(LightLayer.BLOCK, tilePos.offset(blockPos)), level.getBrightness(LightLayer.SKY, tilePos.offset(blockPos))); - boolean far = Minecraft.getInstance().level == be.getLevel() && !Minecraft.getInstance() - .getBlockEntityRenderDispatcher().camera.getPosition() - .closerThan(Vec3.atCenterOf(tilePos) - .add(blockPos.getX() / 2f, blockPos.getY() / 2f, blockPos.getZ() / 2f), MIP_DISTANCE); + boolean far = false; + if (Minecraft.getInstance().level == be.getLevel()) { + Vec3 camPos = Minecraft.getInstance() + .getBlockEntityRenderDispatcher().camera.getPosition(); + Vec3 closest = getClosestPointOnChain(camPos, stats.start(), stats.end()); + if (closest.distanceToSqr(camPos) > MIP_DISTANCE_SQR) + far = true; + } renderChain(ms, buffer, animation, stats.chainLength(), light1, light2, far); From 5dddc5a5e00f09ee5613abaf42a1d5b577cfde3b Mon Sep 17 00:00:00 2001 From: MoePus <547007249@qq.com> Date: Wed, 5 Mar 2025 00:14:25 +0900 Subject: [PATCH 2/6] accurate culling # Conflicts: # src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorBlockEntity.java # src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorRenderer.java # src/main/resources/create.mixins.json --- .../ChainConveyorBlockEntity.java | 2 +- .../chainConveyor/ChainConveyorRenderer.java | 38 +++++++++++++------ .../renderer/SafeBlockEntityRenderer.java | 17 +++++++-- .../mixin/accessor/FrustumAccessor.java | 13 +++++++ src/main/resources/create.mixins.json | 1 + 5 files changed, 54 insertions(+), 17 deletions(-) create mode 100644 src/main/java/com/simibubi/create/foundation/mixin/accessor/FrustumAccessor.java diff --git a/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorBlockEntity.java index e675b02ca1..921a39e2af 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorBlockEntity.java @@ -88,7 +88,7 @@ public ChainConveyorBlockEntity(BlockEntityType typeIn, BlockPos pos, BlockSt @Override protected AABB createRenderBoundingBox() { - return new AABB(worldPosition).inflate(connections.isEmpty() ? 3 : 64); + return AABB.INFINITE; } @Override diff --git a/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorRenderer.java b/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorRenderer.java index 8ad2b59ded..910323f5b7 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorRenderer.java +++ b/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorRenderer.java @@ -3,6 +3,7 @@ import java.util.List; import java.util.Map.Entry; +import org.joml.FrustumIntersection; import org.joml.Matrix4f; import com.mojang.blaze3d.vertex.PoseStack; @@ -52,25 +53,33 @@ protected void renderSafe(ChainConveyorBlockEntity be, float partialTicks, PoseS super.renderSafe(be, partialTicks, ms, buffer, light, overlay); BlockPos pos = be.getBlockPos(); - renderChains(be, ms, buffer, light, overlay); + FrustumIntersection frustum = null; + Vec3 camPos = null; + if(Minecraft.getInstance().level == be.getLevel()) + { + frustum = getFrustumIntersection(); + camPos = Minecraft.getInstance().gameRenderer.getMainCamera().getPosition(); + } + renderChains(be, ms, buffer, light, overlay, frustum, camPos); if (VisualizationManager.supportsVisualization(be.getLevel())) return; - CachedBuffers.partial(AllPartialModels.CHAIN_CONVEYOR_WHEEL, be.getBlockState()) - .light(light) - .overlay(overlay) - .renderInto(ms, buffer.getBuffer(RenderType.cutoutMipped())); + if (frustum != null && frustum.testAab(pos.getX() - 2 - (float) camPos.x, pos.getY() - (float) camPos.y, pos.getZ() - 2 - (float) camPos.z, pos.getX() + 2 - (float) camPos.x, pos.getY() + 1 - (float) camPos.y, pos.getZ() + 2 - (float) camPos.z)) + CachedBuffers.partial(AllPartialModels.CHAIN_CONVEYOR_WHEEL, be.getBlockState()) + .light(light) + .overlay(overlay) + .renderInto(ms, buffer.getBuffer(RenderType.cutoutMipped())); for (ChainConveyorPackage box : be.loopingPackages) - renderBox(be, ms, buffer, overlay, pos, box, partialTicks); + renderBox(be, ms, buffer, overlay, pos, box, partialTicks, frustum, camPos); for (Entry> entry : be.travellingPackages.entrySet()) for (ChainConveyorPackage box : entry.getValue()) - renderBox(be, ms, buffer, overlay, pos, box, partialTicks); + renderBox(be, ms, buffer, overlay, pos, box, partialTicks, frustum, camPos); } private void renderBox(ChainConveyorBlockEntity be, PoseStack ms, MultiBufferSource buffer, int overlay, - BlockPos pos, ChainConveyorPackage box, float partialTicks) { + BlockPos pos, ChainConveyorPackage box, float partialTicks, FrustumIntersection frustum, Vec3 camPos) { if (box.worldPosition == null) return; if (box.item == null || box.item.isEmpty()) @@ -82,6 +91,9 @@ private void renderBox(ChainConveyorBlockEntity be, PoseStack ms, MultiBufferSou Vec3 position = physicsData.prevPos.lerp(physicsData.pos, partialTicks); Vec3 targetPosition = physicsData.prevTargetPos.lerp(physicsData.targetPos, partialTicks); + if (frustum != null && !frustum.testSphere((float) (targetPosition.x - camPos.x), (float) (targetPosition.y - camPos.y), (float) (targetPosition.z - camPos.z), 1)) + return; + float yaw = AngleHelper.angleLerp(partialTicks, physicsData.prevYaw, physicsData.yaw); Vec3 offset = new Vec3(targetPosition.x - pos.getX(), targetPosition.y - pos.getY(), targetPosition.z - pos.getZ()); @@ -141,7 +153,7 @@ private static Vec3 getClosestPointOnChain(Vec3 cam, Vec3 start, Vec3 end) { } private void renderChains(ChainConveyorBlockEntity be, PoseStack ms, MultiBufferSource buffer, int light, - int overlay) { + int overlay, FrustumIntersection frustum, Vec3 camPos) { float time = AnimationTickHolder.getRenderTime(be.getLevel()) / (360f / Math.abs(be.getSpeed())); time %= 1; if (time < 0) @@ -154,6 +166,10 @@ private void renderChains(ChainConveyorBlockEntity be, PoseStack ms, MultiBuffer if (stats == null) continue; + if (frustum != null && !frustum.testLineSegment((float) (stats.start().x - camPos.x), (float) (stats.start().y - camPos.y), (float) (stats.start().z - camPos.z), + (float) (stats.end().x - camPos.x), (float) (stats.end().y - camPos.y), (float) (stats.end().z - camPos.z))) { + continue; + } Vec3 diff = stats.end() .subtract(stats.start()); double yaw = (float) Mth.RAD_TO_DEG * Mth.atan2(diff.x, diff.z); @@ -193,9 +209,7 @@ private void renderChains(ChainConveyorBlockEntity be, PoseStack ms, MultiBuffer level.getBrightness(LightLayer.SKY, tilePos.offset(blockPos))); boolean far = false; - if (Minecraft.getInstance().level == be.getLevel()) { - Vec3 camPos = Minecraft.getInstance() - .getBlockEntityRenderDispatcher().camera.getPosition(); + if (frustum != null) { Vec3 closest = getClosestPointOnChain(camPos, stats.start(), stats.end()); if (closest.distanceToSqr(camPos) > MIP_DISTANCE_SQR) far = true; diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/renderer/SafeBlockEntityRenderer.java b/src/main/java/com/simibubi/create/foundation/blockEntity/renderer/SafeBlockEntityRenderer.java index e727d488a1..99f15c3b91 100644 --- a/src/main/java/com/simibubi/create/foundation/blockEntity/renderer/SafeBlockEntityRenderer.java +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/renderer/SafeBlockEntityRenderer.java @@ -6,6 +6,7 @@ import com.simibubi.create.foundation.blockEntity.CachedRenderBBBlockEntity; import com.simibubi.create.foundation.mixin.accessor.LevelRendererAccessor; +import com.simibubi.create.foundation.mixin.accessor.FrustumAccessor; import com.simibubi.create.foundation.mixin.accessor.LevelRendererAccessor; import net.createmod.ponder.api.level.PonderLevel; @@ -19,6 +20,8 @@ import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; +import org.joml.FrustumIntersection; + public abstract class SafeBlockEntityRenderer implements BlockEntityRenderer { @Override public final void render(T be, float partialTicks, PoseStack ms, MultiBufferSource bufferSource, int light, @@ -36,14 +39,20 @@ public boolean isInvalid(T be) { .getBlock() == Blocks.AIR; } + public Frustum getFrustum() { + LevelRendererAccessor accessor = (LevelRendererAccessor) Minecraft.getInstance().levelRenderer; + return accessor.create$getCapturedFrustum() != null ? accessor.create$getCapturedFrustum() : accessor.create$getCullingFrustum(); + } + + public FrustumIntersection getFrustumIntersection() { + return ((FrustumAccessor) getFrustum()).create$getFrustumIntersection(); + } + public boolean shouldCullItem(Vec3 itemPos, Level level) { if (level instanceof PonderLevel) return false; - LevelRendererAccessor accessor = (LevelRendererAccessor) Minecraft.getInstance().levelRenderer; - Frustum frustum = accessor.create$getCapturedFrustum() != null ? - accessor.create$getCapturedFrustum() : - accessor.create$getCullingFrustum(); + Frustum frustum = getFrustum(); AABB itemBB = new AABB( itemPos.x - 0.25, diff --git a/src/main/java/com/simibubi/create/foundation/mixin/accessor/FrustumAccessor.java b/src/main/java/com/simibubi/create/foundation/mixin/accessor/FrustumAccessor.java new file mode 100644 index 0000000000..8844f9c185 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/mixin/accessor/FrustumAccessor.java @@ -0,0 +1,13 @@ +package com.simibubi.create.foundation.mixin.accessor; + +import net.minecraft.client.renderer.culling.Frustum; + +import org.joml.FrustumIntersection; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(Frustum.class) +public interface FrustumAccessor { + @Accessor("intersection") + FrustumIntersection create$getFrustumIntersection(); +} diff --git a/src/main/resources/create.mixins.json b/src/main/resources/create.mixins.json index 1e5591747b..0b003539ea 100644 --- a/src/main/resources/create.mixins.json +++ b/src/main/resources/create.mixins.json @@ -53,6 +53,7 @@ "accessor.AgeableListModelAccessor", "accessor.EntityRenderDispatcherAccessor", "accessor.FontAccessor", + "accessor.FrustumAccessor", "accessor.GuiAccessor", "accessor.HumanoidArmorLayerAccessor", "accessor.LevelRendererAccessor", From 08a848a521e4c75828a9daa1c4841ec2e8856918 Mon Sep 17 00:00:00 2001 From: MoePus <547007249@qq.com> Date: Wed, 5 Mar 2025 00:54:44 +0900 Subject: [PATCH 3/6] fix guard been culled in some angle --- .../chainConveyor/ChainConveyorRenderer.java | 33 ++++++++++--------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorRenderer.java b/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorRenderer.java index 910323f5b7..361e60ee0f 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorRenderer.java +++ b/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorRenderer.java @@ -60,12 +60,13 @@ protected void renderSafe(ChainConveyorBlockEntity be, float partialTicks, PoseS frustum = getFrustumIntersection(); camPos = Minecraft.getInstance().gameRenderer.getMainCamera().getPosition(); } - renderChains(be, ms, buffer, light, overlay, frustum, camPos); + boolean renderCentre = frustum != null && frustum.testAab(pos.getX() - 2 - (float) camPos.x, pos.getY() - (float) camPos.y, pos.getZ() - 2 - (float) camPos.z, pos.getX() + 2 - (float) camPos.x, pos.getY() + 1 - (float) camPos.y, pos.getZ() + 2 - (float) camPos.z); + renderChains(be, ms, buffer, light, overlay, frustum, camPos, renderCentre); if (VisualizationManager.supportsVisualization(be.getLevel())) return; - if (frustum != null && frustum.testAab(pos.getX() - 2 - (float) camPos.x, pos.getY() - (float) camPos.y, pos.getZ() - 2 - (float) camPos.z, pos.getX() + 2 - (float) camPos.x, pos.getY() + 1 - (float) camPos.y, pos.getZ() + 2 - (float) camPos.z)) + if (renderCentre) CachedBuffers.partial(AllPartialModels.CHAIN_CONVEYOR_WHEEL, be.getBlockState()) .light(light) .overlay(overlay) @@ -153,7 +154,7 @@ private static Vec3 getClosestPointOnChain(Vec3 cam, Vec3 start, Vec3 end) { } private void renderChains(ChainConveyorBlockEntity be, PoseStack ms, MultiBufferSource buffer, int light, - int overlay, FrustumIntersection frustum, Vec3 camPos) { + int overlay, FrustumIntersection frustum, Vec3 camPos, boolean renderCentre) { float time = AnimationTickHolder.getRenderTime(be.getLevel()) / (360f / Math.abs(be.getSpeed())); time %= 1; if (time < 0) @@ -166,22 +167,10 @@ private void renderChains(ChainConveyorBlockEntity be, PoseStack ms, MultiBuffer if (stats == null) continue; - if (frustum != null && !frustum.testLineSegment((float) (stats.start().x - camPos.x), (float) (stats.start().y - camPos.y), (float) (stats.start().z - camPos.z), - (float) (stats.end().x - camPos.x), (float) (stats.end().y - camPos.y), (float) (stats.end().z - camPos.z))) { - continue; - } Vec3 diff = stats.end() .subtract(stats.start()); double yaw = (float) Mth.RAD_TO_DEG * Mth.atan2(diff.x, diff.z); - double pitch = (float) Mth.RAD_TO_DEG * Mth.atan2(diff.y, diff.multiply(1, 0, 1) - .length()); - - Level level = be.getLevel(); - BlockPos tilePos = be.getBlockPos(); - Vec3 startOffset = stats.start() - .subtract(Vec3.atCenterOf(tilePos)); - - if (!VisualizationManager.supportsVisualization(be.getLevel())) { + if (!VisualizationManager.supportsVisualization(be.getLevel()) && renderCentre) { SuperByteBuffer guard = CachedBuffers.partial(AllPartialModels.CHAIN_CONVEYOR_GUARD, be.getBlockState()); guard.center(); @@ -192,6 +181,18 @@ private void renderChains(ChainConveyorBlockEntity be, PoseStack ms, MultiBuffer .overlay(overlay) .renderInto(ms, buffer.getBuffer(RenderType.cutoutMipped())); } + if (frustum != null && !frustum.testLineSegment((float) (stats.start().x - camPos.x), (float) (stats.start().y - camPos.y), (float) (stats.start().z - camPos.z), + (float) (stats.end().x - camPos.x), (float) (stats.end().y - camPos.y), (float) (stats.end().z - camPos.z))) { + continue; + } + + double pitch = (float) Mth.RAD_TO_DEG * Mth.atan2(diff.y, diff.multiply(1, 0, 1) + .length()); + + Level level = be.getLevel(); + BlockPos tilePos = be.getBlockPos(); + Vec3 startOffset = stats.start() + .subtract(Vec3.atCenterOf(tilePos)); ms.pushPose(); var chain = TransformStack.of(ms); From 06a0261649463c81a04fac90a45f5ed907425525 Mon Sep 17 00:00:00 2001 From: MoePus <547007249@qq.com> Date: Wed, 12 Mar 2025 02:20:14 +0900 Subject: [PATCH 4/6] fix render glitch in ponder --- .../content/kinetics/chainConveyor/ChainConveyorRenderer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorRenderer.java b/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorRenderer.java index 361e60ee0f..a8c234525e 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorRenderer.java +++ b/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorRenderer.java @@ -60,7 +60,7 @@ protected void renderSafe(ChainConveyorBlockEntity be, float partialTicks, PoseS frustum = getFrustumIntersection(); camPos = Minecraft.getInstance().gameRenderer.getMainCamera().getPosition(); } - boolean renderCentre = frustum != null && frustum.testAab(pos.getX() - 2 - (float) camPos.x, pos.getY() - (float) camPos.y, pos.getZ() - 2 - (float) camPos.z, pos.getX() + 2 - (float) camPos.x, pos.getY() + 1 - (float) camPos.y, pos.getZ() + 2 - (float) camPos.z); + boolean renderCentre = frustum == null || frustum.testAab(pos.getX() - 2 - (float) camPos.x, pos.getY() - (float) camPos.y, pos.getZ() - 2 - (float) camPos.z, pos.getX() + 2 - (float) camPos.x, pos.getY() + 1 - (float) camPos.y, pos.getZ() + 2 - (float) camPos.z); renderChains(be, ms, buffer, light, overlay, frustum, camPos, renderCentre); if (VisualizationManager.supportsVisualization(be.getLevel())) From accee4aa28576653c06a5bca70e6f11b715c3f25 Mon Sep 17 00:00:00 2001 From: MoePus <547007249@qq.com> Date: Fri, 4 Apr 2025 20:57:28 +0900 Subject: [PATCH 5/6] Update to lastest chain renderer --- .../ChainConveyorBlockEntity.java | 33 ++++- .../chainConveyor/ChainConveyorRenderer.java | 126 ++++++++++++++---- 2 files changed, 129 insertions(+), 30 deletions(-) diff --git a/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorBlockEntity.java index 921a39e2af..1c1bd84d7c 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorBlockEntity.java @@ -10,7 +10,7 @@ import java.util.Set; import java.util.function.Consumer; -import org.jetbrains.annotations.Nullable; +import javax.annotation.Nullable; import com.simibubi.create.api.contraption.transformable.TransformableBlockEntity; import com.simibubi.create.content.contraptions.StructureTransform; @@ -88,7 +88,30 @@ public ChainConveyorBlockEntity(BlockEntityType typeIn, BlockPos pos, BlockSt @Override protected AABB createRenderBoundingBox() { - return AABB.INFINITE; + if (connections.isEmpty()) { + return new AABB(worldPosition).inflate(3); + } else { + Vec3 mid = Vec3.atLowerCornerOf(worldPosition); + double minX = mid.x; + double minY = mid.y; + double minZ = mid.z; + double maxX = mid.x; + double maxY = mid.y; + double maxZ = mid.z; + + for (BlockPos connection : connections) { + ConnectionStats stats = connectionStats.get(connection); + if (stats == null) + continue; + minX = Math.min(minX, Math.min(stats.start.x, stats.end.x)); + minY = Math.min(minY, Math.min(stats.start.y, stats.end.y)); + minZ = Math.min(minZ, Math.min(stats.start.z, stats.end.z)); + maxX = Math.max(maxX, Math.max(stats.start.x, stats.end.x)); + maxY = Math.max(maxY, Math.max(stats.start.y, stats.end.y)); + maxZ = Math.max(maxZ, Math.max(stats.start.z, stats.end.z)); + } + return new AABB(minX, minY, minZ, maxX, maxY, maxZ).inflate(3); + } } @Override @@ -668,7 +691,7 @@ public float propagateRotationTo(KineticBlockEntity target, BlockState stateFrom @Override public void writeSafe(CompoundTag tag, HolderLookup.Provider registries) { super.writeSafe(tag, registries); - tag.put("Connections", CatnipCodecUtils.encode(CatnipCodecs.set(BlockPos.CODEC), registries, connections).orElseThrow()); + tag.put("Connections", CatnipCodecUtils.encode(CatnipCodecs.set(BlockPos.CODEC), connections).orElseThrow()); } @Override @@ -679,7 +702,7 @@ protected void write(CompoundTag compound, HolderLookup.Provider registries, boo chainDestroyedEffectToSend = null; } - compound.put("Connections", CatnipCodecUtils.encode(CatnipCodecs.set(BlockPos.CODEC), registries, connections).orElseThrow()); + compound.put("Connections", CatnipCodecUtils.encode(CatnipCodecs.set(BlockPos.CODEC), connections).orElseThrow()); compound.put("TravellingPackages", NBTHelper.writeCompoundList(travellingPackages.entrySet(), entry -> { CompoundTag compoundTag = new CompoundTag(); compoundTag.put("Target", NbtUtils.writeBlockPos(entry.getKey())); @@ -699,7 +722,7 @@ protected void read(CompoundTag compound, HolderLookup.Provider registries, bool int sizeBefore = connections.size(); connections.clear(); - CatnipCodecUtils.decode(CatnipCodecs.set(BlockPos.CODEC), registries, compound.get("Connections")).ifPresent(connections::addAll); + CatnipCodecUtils.decode(CatnipCodecs.set(BlockPos.CODEC), compound.get("Connections")).ifPresent(connections::addAll); travellingPackages.clear(); NBTHelper.iterateCompoundList(compound.getList("TravellingPackages", Tag.TAG_COMPOUND), c -> travellingPackages.put(NBTHelper.readBlockPos(c, "Target"), diff --git a/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorRenderer.java b/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorRenderer.java index a8c234525e..57cf8e3aea 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorRenderer.java +++ b/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorRenderer.java @@ -38,6 +38,8 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.Vec3; +import org.joml.Vector3f; + public class ChainConveyorRenderer extends KineticBlockEntityRenderer { public static final ResourceLocation CHAIN_LOCATION = ResourceLocation.withDefaultNamespace("textures/block/chain.png"); @@ -55,10 +57,9 @@ protected void renderSafe(ChainConveyorBlockEntity be, float partialTicks, PoseS FrustumIntersection frustum = null; Vec3 camPos = null; - if(Minecraft.getInstance().level == be.getLevel()) - { + if (Minecraft.getInstance().level == be.getLevel()) { frustum = getFrustumIntersection(); - camPos = Minecraft.getInstance().gameRenderer.getMainCamera().getPosition(); + camPos = Minecraft.getInstance().getBlockEntityRenderDispatcher().camera.getPosition(); } boolean renderCentre = frustum == null || frustum.testAab(pos.getX() - 2 - (float) camPos.x, pos.getY() - (float) camPos.y, pos.getZ() - 2 - (float) camPos.z, pos.getX() + 2 - (float) camPos.x, pos.getY() + 1 - (float) camPos.y, pos.getZ() + 2 - (float) camPos.z); renderChains(be, ms, buffer, light, overlay, frustum, camPos, renderCentre); @@ -144,13 +145,79 @@ private void renderBox(ChainConveyorBlockEntity be, PoseStack ms, MultiBufferSou } } - private static Vec3 getClosestPointOnChain(Vec3 cam, Vec3 start, Vec3 end) { - Vec3 seg = end.subtract(start); - Vec3 start2cam = cam.subtract(start); + /** + * Calculate the intersection points between a line segment and a circle centered at cameraPos with radius LODDistance. + * The intersections array is used to store up to 2 intersection points. + * Returns the number of intersection points (0, 1, or 2). + */ + private static int calculateLineCircleIntersection(Vec3 start, Vec3 end, Vec3 cameraPos, Vec3[] intersections) { + Vec3 ab = end.subtract(start); + Vec3 ac = start.subtract(cameraPos); + float a = (float) ab.lengthSqr(); + float b = 2 * (float) ac.dot(ab); + float c = (float) ac.lengthSqr() - MIP_DISTANCE_SQR; + float discriminant = b * b - 4 * a * c; + + if (discriminant < 0) { + return 0; // No intersection + } - double t = Mth.clamp(start2cam.dot(seg) / seg.lengthSqr(), 0.0, 1.0); + float sqrtDisc = Mth.sqrt(discriminant); + float t1 = (-b - sqrtDisc) / (2 * a); + float t2 = (-b + sqrtDisc) / (2 * a); + int count = 0; + if (t1 >= 0 && t1 <= 1) { + intersections[count++] = start.add(ab.scale(t1)); + } + // Avoid duplicate calculations (when t1 and t2 are almost equal) + if (t2 >= 0 && t2 <= 1 && Math.abs(t2 - t1) > 1e-6f) { + intersections[count++] = start.add(ab.scale(t2)); + } + return count; + } - return start.add(seg.scale(t)); + /** + * Cut the line segment based on the intersection points with the circle centered at the camera position. + * The output Vector3f contains: + * x: The distance from the start of the line segment to the intersection point (outside the LOD); + * y: The length of the part of the line segment LOD0; + * z: The distance from the intersection point to the end of the line segment (outside the LOD). + */ + public static Vector3f calculateLODCut(Vec3 start, Vec3 end, Vec3 cameraPos) { + Vec3[] intersections = new Vec3[2]; + int intersectionCount = calculateLineCircleIntersection(start, end, cameraPos, intersections); + float totalLength = (float) start.distanceTo(end); + float x = 0, y = 0, z = 0; + + if (intersectionCount == 0) { + // No intersection: Determine if the line segment is entirely inside or outside the circle + if (start.distanceToSqr(cameraPos) < MIP_DISTANCE_SQR && end.distanceToSqr(cameraPos) < MIP_DISTANCE_SQR) { + // Both ends are inside the circle + y = totalLength; + } else { + // The line segment is entirely outside the circle + x = totalLength; + } + } else if (intersectionCount == 1) { + // Only one intersection point, determine which end is inside the circle + // one end must be inside and the other outside + boolean endInside = end.distanceToSqr(cameraPos) < MIP_DISTANCE_SQR; + if (endInside) { + x = (float) start.distanceTo(intersections[0]); + y = (float) intersections[0].distanceTo(end); + z = 0; + } else { + x = 0; + y = (float) start.distanceTo(intersections[0]); + z = (float) intersections[0].distanceTo(end); + } + } else if (intersectionCount == 2) { + x = (float) start.distanceTo(intersections[0]); + y = (float) intersections[0].distanceTo(intersections[1]); + z = (float) end.distanceTo(intersections[1]); + } + + return new Vector3f(x, y, z); } private void renderChains(ChainConveyorBlockEntity be, PoseStack ms, MultiBufferSource buffer, int light, @@ -191,8 +258,13 @@ private void renderChains(ChainConveyorBlockEntity be, PoseStack ms, MultiBuffer Level level = be.getLevel(); BlockPos tilePos = be.getBlockPos(); - Vec3 startOffset = stats.start() - .subtract(Vec3.atCenterOf(tilePos)); + + int light1 = LightTexture.pack(level.getBrightness(LightLayer.BLOCK, tilePos), + level.getBrightness(LightLayer.SKY, tilePos)); + int light2 = LightTexture.pack(level.getBrightness(LightLayer.BLOCK, tilePos.offset(blockPos)), + level.getBrightness(LightLayer.SKY, tilePos.offset(blockPos))); + + Vec3 startOffset = stats.start().subtract(Vec3.atCenterOf(tilePos)); ms.pushPose(); var chain = TransformStack.of(ms); @@ -204,29 +276,34 @@ private void renderChains(ChainConveyorBlockEntity be, PoseStack ms, MultiBuffer chain.translate(0, 8 / 16f, 0); chain.uncenter(); - int light1 = LightTexture.pack(level.getBrightness(LightLayer.BLOCK, tilePos), - level.getBrightness(LightLayer.SKY, tilePos)); - int light2 = LightTexture.pack(level.getBrightness(LightLayer.BLOCK, tilePos.offset(blockPos)), - level.getBrightness(LightLayer.SKY, tilePos.offset(blockPos))); - - boolean far = false; if (frustum != null) { - Vec3 closest = getClosestPointOnChain(camPos, stats.start(), stats.end()); - if (closest.distanceToSqr(camPos) > MIP_DISTANCE_SQR) - far = true; + Vector3f length = calculateLODCut(stats.start(), stats.end(), camPos); + if (length.x > 1e-6f) { + renderChain(ms, buffer, animation, 0, length.x, light1, light2, true); + } + + if (length.y > 1e-6f) { + chain.translate(0, length.x, 0); + renderChain(ms, buffer, animation, length.x, length.y, light1, light2, false); + } + + if (length.z > 1e-6f) { + chain.translate(0, length.y, 0); + renderChain(ms, buffer, animation, 0, length.z, light1, light2, true); + } + } else { + renderChain(ms, buffer, animation, 0, stats.chainLength(), light1, light2, false); } - renderChain(ms, buffer, animation, stats.chainLength(), light1, light2, far); - ms.popPose(); } } - public static void renderChain(PoseStack ms, MultiBufferSource buffer, float animation, float length, int light1, + public static void renderChain(PoseStack ms, MultiBufferSource buffer, float animation, float start, float length, int light1, int light2, boolean far) { float radius = far ? 1f / 16f : 1.5f / 16f; - float minV = far ? 0 : animation; - float maxV = far ? 1 / 16f : length + minV; + float maxV = far ? 0 : animation - start; + float minV = far ? 1 / 16f : maxV - length; float minU = far ? 3 / 16f : 0; float maxU = far ? 4 / 16f : 3 / 16f; @@ -236,7 +313,6 @@ public static void renderChain(PoseStack ms, MultiBufferSource buffer, float ani VertexConsumer vc = buffer.getBuffer(RenderTypes.chain(CHAIN_LOCATION)); renderPart(ms, vc, length, 0.0F, radius, radius, 0.0F, -radius, 0.0F, 0.0F, -radius, minU, maxU, minV, maxV, light1, light2, far); - ms.popPose(); } From b596b22399e7b40859485f80accca98fe4dbb5f7 Mon Sep 17 00:00:00 2001 From: MoePus <547007249@qq.com> Date: Sun, 26 Oct 2025 22:17:26 +0900 Subject: [PATCH 6/6] render chain even if the other side is out of render distance --- .../ChainConveyorBlockEntity.java | 12 +- .../chainConveyor/ChainConveyorRenderer.java | 171 ++++++++++++------ 2 files changed, 125 insertions(+), 58 deletions(-) diff --git a/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorBlockEntity.java index 1c1bd84d7c..3d6e047833 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorBlockEntity.java @@ -509,8 +509,7 @@ private void tickBoxVisuals(ChainConveyorPackage box) { physicsData.yaw = AngleHelper.angleLerp(.25, physicsData.yaw, box.yaw); } - private void calculateConnectionStats(BlockPos connection) { - boolean reversed = getSpeed() < 0; + public static ConnectionStats calculateConnectionStats(BlockPos connection, BlockPos worldPosition, boolean reversed) { float offBranchDistance = 35f; float direction = Mth.RAD_TO_DEG * (float) Mth.atan2(connection.getX(), connection.getZ()); float angle = wrapAngle(direction - offBranchDistance * (reversed ? -1 : 1)); @@ -525,7 +524,12 @@ private void calculateConnectionStats(BlockPos connection) { .add(0, 6 / 16f, 0); float length = (float) start.distanceTo(end); - connectionStats.put(connection, new ConnectionStats(angle, length, start, end)); + return new ConnectionStats(angle, length, start, end); + } + + private void calculateConnectionStats(BlockPos connection) { + boolean reversed = getSpeed() < 0; + connectionStats.put(connection, calculateConnectionStats(connection, worldPosition, reversed)); } public boolean addConnectionTo(BlockPos target) { @@ -737,7 +741,7 @@ protected void read(CompoundTag compound, HolderLookup.Provider registries, bool invalidateRenderBoundingBox(); } - public float wrapAngle(float angle) { + public static float wrapAngle(float angle) { angle %= 360; if (angle < 0) angle += 360; diff --git a/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorRenderer.java b/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorRenderer.java index 57cf8e3aea..9cdae93e1d 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorRenderer.java +++ b/src/main/java/com/simibubi/create/content/kinetics/chainConveyor/ChainConveyorRenderer.java @@ -3,6 +3,13 @@ import java.util.List; import java.util.Map.Entry; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.core.SectionPos; +import net.minecraft.world.level.chunk.ChunkAccess; + +import net.minecraft.world.level.chunk.LevelChunk; +import net.minecraft.world.level.chunk.status.ChunkStatus; + import org.joml.FrustumIntersection; import org.joml.Matrix4f; @@ -51,7 +58,7 @@ public ChainConveyorRenderer(Context context) { @Override protected void renderSafe(ChainConveyorBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, - int light, int overlay) { + int light, int overlay) { super.renderSafe(be, partialTicks, ms, buffer, light, overlay); BlockPos pos = be.getBlockPos(); @@ -81,7 +88,7 @@ protected void renderSafe(ChainConveyorBlockEntity be, float partialTicks, PoseS } private void renderBox(ChainConveyorBlockEntity be, PoseStack ms, MultiBufferSource buffer, int overlay, - BlockPos pos, ChainConveyorPackage box, float partialTicks, FrustumIntersection frustum, Vec3 camPos) { + BlockPos pos, ChainConveyorPackage box, float partialTicks, FrustumIntersection frustum, Vec3 camPos) { if (box.worldPosition == null) return; if (box.item == null || box.item.isEmpty()) @@ -93,7 +100,10 @@ private void renderBox(ChainConveyorBlockEntity be, PoseStack ms, MultiBufferSou Vec3 position = physicsData.prevPos.lerp(physicsData.pos, partialTicks); Vec3 targetPosition = physicsData.prevTargetPos.lerp(physicsData.targetPos, partialTicks); - if (frustum != null && !frustum.testSphere((float) (targetPosition.x - camPos.x), (float) (targetPosition.y - camPos.y), (float) (targetPosition.z - camPos.z), 1)) + if (frustum != null && !frustum.testSphere( + (float) (targetPosition.x - camPos.x), + (float) (targetPosition.y - camPos.y), + (float) (targetPosition.z - camPos.z), 1)) return; float yaw = AngleHelper.angleLerp(partialTicks, physicsData.prevYaw, physicsData.yaw); @@ -125,7 +135,7 @@ private void renderBox(ChainConveyorBlockEntity be, PoseStack ms, MultiBufferSou zRot = Mth.clamp(zRot, -25, 25); xRot = Mth.clamp(xRot, -25, 25); - for (SuperByteBuffer buf : new SuperByteBuffer[] { rigBuffer, boxBuffer }) { + for (SuperByteBuffer buf : new SuperByteBuffer[]{rigBuffer, boxBuffer}) { buf.translate(offset); buf.translate(0, 10 / 16f, 0); buf.rotateYDegrees(yaw); @@ -221,7 +231,12 @@ public static Vector3f calculateLODCut(Vec3 start, Vec3 end, Vec3 cameraPos) { } private void renderChains(ChainConveyorBlockEntity be, PoseStack ms, MultiBufferSource buffer, int light, - int overlay, FrustumIntersection frustum, Vec3 camPos, boolean renderCentre) { + int overlay, FrustumIntersection frustum, Vec3 camPos, boolean renderCentre) { + if (frustum != null) { + float renderDistance = Minecraft.getInstance().gameRenderer.getRenderDistance(); + if (camPos.distanceToSqr(be.getBlockPos().getCenter()) > renderDistance * renderDistance) + return; + } float time = AnimationTickHolder.getRenderTime(be.getLevel()) / (360f / Math.abs(be.getSpeed())); time %= 1; if (time < 0) @@ -234,8 +249,15 @@ private void renderChains(ChainConveyorBlockEntity be, PoseStack ms, MultiBuffer if (stats == null) continue; - Vec3 diff = stats.end() - .subtract(stats.start()); + Level level = be.getLevel(); + BlockPos tilePos = be.getBlockPos(); + BlockPos targetPos = tilePos.offset(blockPos); + + Vec3 start = stats.start(); + Vec3 end = stats.end(); + + Vec3 diff = end + .subtract(start); double yaw = (float) Mth.RAD_TO_DEG * Mth.atan2(diff.x, diff.z); if (!VisualizationManager.supportsVisualization(be.getLevel()) && renderCentre) { SuperByteBuffer guard = @@ -248,59 +270,100 @@ private void renderChains(ChainConveyorBlockEntity be, PoseStack ms, MultiBuffer .overlay(overlay) .renderInto(ms, buffer.getBuffer(RenderType.cutoutMipped())); } - if (frustum != null && !frustum.testLineSegment((float) (stats.start().x - camPos.x), (float) (stats.start().y - camPos.y), (float) (stats.start().z - camPos.z), - (float) (stats.end().x - camPos.x), (float) (stats.end().y - camPos.y), (float) (stats.end().z - camPos.z))) { - continue; + if (frustum == null || frustum.testLineSegment((float) (start.x - camPos.x), (float) (start.y - camPos.y), (float) (start.z - camPos.z), + (float) (end.x - camPos.x), (float) (end.y - camPos.y), (float) (end.z - camPos.z))) { + double pitch = (float) Mth.RAD_TO_DEG * Mth.atan2(diff.y, diff.multiply(1, 0, 1) + .length()); + + int light1 = LightTexture.pack(level.getBrightness(LightLayer.BLOCK, tilePos), + level.getBrightness(LightLayer.SKY, tilePos)); + int light2 = LightTexture.pack(level.getBrightness(LightLayer.BLOCK, targetPos), + level.getBrightness(LightLayer.SKY, targetPos)); + + Vec3 startOffset = start.subtract(Vec3.atCenterOf(tilePos)); + + ms.pushPose(); + var chain = TransformStack.of(ms); + chain.center(); + chain.translate(startOffset); + chain.rotateYDegrees((float) yaw); + chain.rotateXDegrees(90 - (float) pitch); + chain.rotateYDegrees(45); + chain.translate(0, 8 / 16f, 0); + chain.uncenter(); + + if (frustum != null) { + renderChainWithLod(ms, buffer, animation, light1, light2, camPos, start, end, chain); + } else { + renderChain(ms, buffer, animation, 0, stats.chainLength(), light1, light2, false); + } + ms.popPose(); } - double pitch = (float) Mth.RAD_TO_DEG * Mth.atan2(diff.y, diff.multiply(1, 0, 1) - .length()); + if (frustum == null) + continue; - Level level = be.getLevel(); - BlockPos tilePos = be.getBlockPos(); + float renderDistance = Minecraft.getInstance().gameRenderer.getRenderDistance(); + if (camPos.distanceToSqr(targetPos.getCenter()) <= renderDistance * renderDistance) + continue; - int light1 = LightTexture.pack(level.getBrightness(LightLayer.BLOCK, tilePos), - level.getBrightness(LightLayer.SKY, tilePos)); - int light2 = LightTexture.pack(level.getBrightness(LightLayer.BLOCK, tilePos.offset(blockPos)), - level.getBrightness(LightLayer.SKY, tilePos.offset(blockPos))); - - Vec3 startOffset = stats.start().subtract(Vec3.atCenterOf(tilePos)); - - ms.pushPose(); - var chain = TransformStack.of(ms); - chain.center(); - chain.translate(startOffset); - chain.rotateYDegrees((float) yaw); - chain.rotateXDegrees(90 - (float) pitch); - chain.rotateYDegrees(45); - chain.translate(0, 8 / 16f, 0); - chain.uncenter(); - - if (frustum != null) { - Vector3f length = calculateLODCut(stats.start(), stats.end(), camPos); - if (length.x > 1e-6f) { - renderChain(ms, buffer, animation, 0, length.x, light1, light2, true); - } + boolean reversed = be.getSpeed() < 0; + ConnectionStats virtualStats = ChainConveyorBlockEntity.calculateConnectionStats( + blockPos.multiply(-1), + targetPos, + reversed + ); + + start = virtualStats.start(); + end = virtualStats.end(); + + if (frustum.testLineSegment((float) (start.x - camPos.x), (float) (start.y - camPos.y), (float) (start.z - camPos.z), + (float) (end.x - camPos.x), (float) (end.y - camPos.y), (float) (end.z - camPos.z))) { + diff = end.subtract(start); + yaw = (float) Mth.RAD_TO_DEG * Mth.atan2(diff.x, diff.z); + double pitch = (float) Mth.RAD_TO_DEG * Mth.atan2(diff.y, diff.multiply(1, 0, 1).length()); + Vec3 startOffset = start.subtract(Vec3.atCenterOf(tilePos)); + + ms.pushPose(); + var chain = TransformStack.of(ms); + chain.center(); + chain.translate(startOffset); + chain.rotateYDegrees((float) yaw); + chain.rotateXDegrees(90 - (float) pitch); + chain.rotateYDegrees(45); + chain.translate(0, 8 / 16f, 0); + chain.uncenter(); + + int light1 = LightTexture.pack(level.getBrightness(LightLayer.BLOCK, tilePos), + level.getBrightness(LightLayer.SKY, tilePos)); + + renderChainWithLod(ms, buffer, animation, light1, light1, camPos, start, end, chain); + ms.popPose(); + } - if (length.y > 1e-6f) { - chain.translate(0, length.x, 0); - renderChain(ms, buffer, animation, length.x, length.y, light1, light2, false); - } + } + } - if (length.z > 1e-6f) { - chain.translate(0, length.y, 0); - renderChain(ms, buffer, animation, 0, length.z, light1, light2, true); - } - } else { - renderChain(ms, buffer, animation, 0, stats.chainLength(), light1, light2, false); - } + public static void renderChainWithLod(PoseStack ms, MultiBufferSource buffer, float animation, int light1, + int light2, Vec3 camPos, Vec3 chainStart, Vec3 chainEnd, TransformStack chain) { + Vector3f length = calculateLODCut(chainStart, chainEnd, camPos); + if (length.x > 1e-6f) { + renderChain(ms, buffer, animation, 0, length.x, light1, light2, true); + } + + if (length.y > 1e-6f) { + chain.translate(0, length.x, 0); + renderChain(ms, buffer, animation, length.x, length.y, light1, light2, false); + } - ms.popPose(); + if (length.z > 1e-6f) { + chain.translate(0, length.y, 0); + renderChain(ms, buffer, animation, 0, length.z, light1, light2, true); } } public static void renderChain(PoseStack ms, MultiBufferSource buffer, float animation, float start, float length, int light1, - int light2, boolean far) { + int light2, boolean far) { float radius = far ? 1f / 16f : 1.5f / 16f; float maxV = far ? 0 : animation - start; float minV = far ? 1 / 16f : maxV - length; @@ -317,8 +380,8 @@ public static void renderChain(PoseStack ms, MultiBufferSource buffer, float ani } private static void renderPart(PoseStack pPoseStack, VertexConsumer pConsumer, float pMaxY, float pX0, float pZ0, - float pX1, float pZ1, float pX2, float pZ2, float pX3, float pZ3, float pMinU, float pMaxU, float pMinV, - float pMaxV, int light1, int light2, boolean far) { + float pX1, float pZ1, float pX2, float pZ2, float pX3, float pZ3, float pMinU, float pMaxU, float pMinV, + float pMaxV, int light1, int light2, boolean far) { PoseStack.Pose posestack$pose = pPoseStack.last(); Matrix4f matrix4f = posestack$pose.pose(); @@ -334,8 +397,8 @@ private static void renderPart(PoseStack pPoseStack, VertexConsumer pConsumer, f } private static void renderQuad(Matrix4f pPose, PoseStack.Pose pNormal, VertexConsumer pConsumer, float pMinY, float pMaxY, - float pMinX, float pMinZ, float pMaxX, float pMaxZ, float pMinU, float pMaxU, float pMinV, float pMaxV, - int light1, int light2) { + float pMinX, float pMinZ, float pMaxX, float pMaxZ, float pMinU, float pMaxU, float pMinV, float pMaxV, + int light1, int light2) { addVertex(pPose, pNormal, pConsumer, pMaxY, pMinX, pMinZ, pMaxU, pMinV, light2); addVertex(pPose, pNormal, pConsumer, pMinY, pMinX, pMinZ, pMaxU, pMaxV, light1); addVertex(pPose, pNormal, pConsumer, pMinY, pMaxX, pMaxZ, pMinU, pMaxV, light1); @@ -343,7 +406,7 @@ private static void renderQuad(Matrix4f pPose, PoseStack.Pose pNormal, VertexCon } private static void addVertex(Matrix4f pPose, PoseStack.Pose pNormal, VertexConsumer pConsumer, float pY, float pX, - float pZ, float pU, float pV, int light) { + float pZ, float pU, float pV, int light) { pConsumer.addVertex(pPose, pX, pY, pZ) .setColor(1.0f, 1.0f, 1.0f, 1.0f) .setUv(pU, pV)