Gone, but not forgotten

- Track the last visible AABB within EntityVisuals to prevent entities
  from freezing when the go offscreen.
This commit is contained in:
Jozufozu 2023-05-21 16:07:46 -07:00
parent ce6ce841d1
commit d6535dc9cd
2 changed files with 56 additions and 8 deletions

View file

@ -35,11 +35,13 @@ import net.minecraft.world.phys.Vec3;
public abstract class AbstractEntityVisual<T extends Entity> extends AbstractVisual implements EntityVisual<T>, 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<T extends Entity> 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);
}
}

View file

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