From d6535dc9cd6deb9e20d67ddd0270f2e43f506172 Mon Sep 17 00:00:00 2001 From: Jozufozu Date: Sun, 21 May 2023 16:07:46 -0700 Subject: [PATCH] Gone, but not forgotten - Track the last visible AABB within EntityVisuals to prevent entities from freezing when the go offscreen. --- .../lib/visual/AbstractEntityVisual.java | 11 ++-- .../lib/visual/EntityVisibilityTester.java | 53 +++++++++++++++++++ 2 files changed, 56 insertions(+), 8 deletions(-) create mode 100644 src/main/java/com/jozufozu/flywheel/lib/visual/EntityVisibilityTester.java diff --git a/src/main/java/com/jozufozu/flywheel/lib/visual/AbstractEntityVisual.java b/src/main/java/com/jozufozu/flywheel/lib/visual/AbstractEntityVisual.java index 880550a75..4647bf889 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/visual/AbstractEntityVisual.java +++ b/src/main/java/com/jozufozu/flywheel/lib/visual/AbstractEntityVisual.java @@ -35,11 +35,13 @@ import net.minecraft.world.phys.Vec3; public abstract class AbstractEntityVisual extends AbstractVisual implements EntityVisual, TickingLightListener { protected final T entity; protected final MutableBox bounds; + protected final EntityVisibilityTester boxTracker; public AbstractEntityVisual(VisualizationContext ctx, T entity) { super(ctx, entity.level); this.entity = entity; bounds = MutableBox.from(entity.getBoundingBox()); + boxTracker = new EntityVisibilityTester(entity, ctx.renderOrigin()); } @Override @@ -99,13 +101,6 @@ public abstract class AbstractEntityVisual extends AbstractVis if (entity.noCulling) { return true; } - - AABB aabb = entity.getBoundingBoxForCulling(); - return frustum.testAab((float) (aabb.minX - renderOrigin.getX()) - 0.5f, - (float) (aabb.minY - renderOrigin.getY()) - 0.5f, - (float) (aabb.minZ - renderOrigin.getZ()) - 0.5f, - (float) (aabb.maxX - renderOrigin.getX()) + 0.5f, - (float) (aabb.maxY - renderOrigin.getY()) + 0.5f, - (float) (aabb.maxZ - renderOrigin.getZ()) + 0.5f); + return boxTracker.isVisible(frustum); } } diff --git a/src/main/java/com/jozufozu/flywheel/lib/visual/EntityVisibilityTester.java b/src/main/java/com/jozufozu/flywheel/lib/visual/EntityVisibilityTester.java new file mode 100644 index 000000000..649e4edae --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/lib/visual/EntityVisibilityTester.java @@ -0,0 +1,53 @@ +package com.jozufozu.flywheel.lib.visual; + +import org.jetbrains.annotations.Nullable; +import org.joml.FrustumIntersection; + +import net.minecraft.core.Vec3i; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.phys.AABB; + +/** + * A helper class for testing whether an Entity is visible. + *

+ * The last visible AABB is also checked to prevent the Entity from freezing when it goes offscreen. + */ +public class EntityVisibilityTester { + private final Entity entity; + private final Vec3i renderOrigin; + @Nullable + private AABB lastVisibleAABB; + + public EntityVisibilityTester(Entity entity, Vec3i renderOrigin) { + this.entity = entity; + + this.renderOrigin = renderOrigin; + } + + public boolean isVisible(FrustumIntersection frustum) { + AABB aabb = entity.getBoundingBoxForCulling(); + + boolean visible = adjustAndTestAABB(frustum, aabb); + + if (!visible && lastVisibleAABB != null && lastVisibleAABB != aabb) { + // If the entity isn't visible, check the last visible AABB as well. + // This is to avoid Entities freezing when the go offscreen. + visible = adjustAndTestAABB(frustum, lastVisibleAABB); + } + + if (visible) { + lastVisibleAABB = aabb; + } + return visible; + } + + private boolean adjustAndTestAABB(FrustumIntersection frustum, AABB aabb) { + float minX = (float) (aabb.minX - renderOrigin.getX() - 0.5); + float minY = (float) (aabb.minY - renderOrigin.getY() - 0.5); + float minZ = (float) (aabb.minZ - renderOrigin.getZ() - 0.5); + float maxX = (float) (aabb.maxX - renderOrigin.getX() + 0.5); + float maxY = (float) (aabb.maxY - renderOrigin.getY() + 0.5); + float maxZ = (float) (aabb.maxZ - renderOrigin.getZ() + 0.5); + return frustum.testAab(minX, minY, minZ, maxX, maxY, maxZ); + } +}