From 5f81bc559fc76fe28219608b5c6560c83345c204 Mon Sep 17 00:00:00 2001 From: Jozufozu Date: Wed, 29 Nov 2023 20:09:28 -0800 Subject: [PATCH] Spheres your cubes - Use sphere-frustum intersection tests in visuals. - Seems to be ~20x faster. --- .../jozufozu/flywheel/lib/math/MoreMath.java | 5 ++++ .../lib/visual/AbstractBlockEntityVisual.java | 6 ++++- .../lib/visual/AbstractEntityVisual.java | 2 +- .../lib/visual/EntityVisibilityTester.java | 27 +++++++++++++------ 4 files changed, 30 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/jozufozu/flywheel/lib/math/MoreMath.java b/src/main/java/com/jozufozu/flywheel/lib/math/MoreMath.java index 340dbac9e..2e7ed44a2 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/math/MoreMath.java +++ b/src/main/java/com/jozufozu/flywheel/lib/math/MoreMath.java @@ -4,6 +4,11 @@ public final class MoreMath { private MoreMath() { } + /** + * The circumsphere of a cube has a radius of sqrt(3) / 2 * sideLength. + */ + public static final float SQRT_3_OVER_2 = (float) (Math.sqrt(3.0) / 2.0); + public static int align16(int numToRound) { return (numToRound + 16 - 1) & -16; } diff --git a/src/main/java/com/jozufozu/flywheel/lib/visual/AbstractBlockEntityVisual.java b/src/main/java/com/jozufozu/flywheel/lib/visual/AbstractBlockEntityVisual.java index 7501263b4..3669e70cf 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/visual/AbstractBlockEntityVisual.java +++ b/src/main/java/com/jozufozu/flywheel/lib/visual/AbstractBlockEntityVisual.java @@ -10,6 +10,7 @@ import com.jozufozu.flywheel.api.visualization.VisualManager; import com.jozufozu.flywheel.api.visualization.VisualizationContext; import com.jozufozu.flywheel.lib.box.Box; import com.jozufozu.flywheel.lib.box.MutableBox; +import com.jozufozu.flywheel.lib.math.MoreMath; import net.minecraft.core.BlockPos; import net.minecraft.world.level.block.entity.BlockEntity; @@ -73,7 +74,10 @@ public abstract class AbstractBlockEntityVisual extends A * @return {@code true} if this visual within the given frustum. */ public boolean isVisible(FrustumIntersection frustum) { - return frustum.testAab(visualPos.getX(), visualPos.getY(), visualPos.getZ(), visualPos.getX() + 1, visualPos.getY() + 1, visualPos.getZ() + 1); + float x = visualPos.getX() + 0.5f; + float y = visualPos.getY() + 0.5f; + float z = visualPos.getZ() + 0.5f; + return frustum.testSphere(x, y, z, MoreMath.SQRT_3_OVER_2); } /** 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 cb26bf352..b55fcd410 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/visual/AbstractEntityVisual.java +++ b/src/main/java/com/jozufozu/flywheel/lib/visual/AbstractEntityVisual.java @@ -41,7 +41,7 @@ public abstract class AbstractEntityVisual extends AbstractVis super(ctx, entity.level()); this.entity = entity; bounds = MutableBox.from(entity.getBoundingBox()); - visibilityTester = new EntityVisibilityTester(entity, ctx.renderOrigin()); + visibilityTester = new EntityVisibilityTester(entity, ctx.renderOrigin(), 1.5f); } /** diff --git a/src/main/java/com/jozufozu/flywheel/lib/visual/EntityVisibilityTester.java b/src/main/java/com/jozufozu/flywheel/lib/visual/EntityVisibilityTester.java index 806dfeb97..3262a6c31 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/visual/EntityVisibilityTester.java +++ b/src/main/java/com/jozufozu/flywheel/lib/visual/EntityVisibilityTester.java @@ -3,7 +3,10 @@ package com.jozufozu.flywheel.lib.visual; import org.jetbrains.annotations.Nullable; import org.joml.FrustumIntersection; +import com.jozufozu.flywheel.lib.math.MoreMath; + import net.minecraft.core.Vec3i; +import net.minecraft.util.Mth; import net.minecraft.world.entity.Entity; import net.minecraft.world.phys.AABB; @@ -15,12 +18,22 @@ import net.minecraft.world.phys.AABB; public class EntityVisibilityTester { private final Entity entity; private final Vec3i renderOrigin; + private final float scale; @Nullable private AABB lastVisibleAABB; - public EntityVisibilityTester(Entity entity, Vec3i renderOrigin) { + /** + * Create a new EntityVisibilityTester. + * + * @param entity The Entity to test. + * @param renderOrigin The render origin according to the VisualizationContext. + * @param scale Multiplier for the Entity's size, can be used to adjust for when + * an entity's model is larger than its hitbox. + */ + public EntityVisibilityTester(Entity entity, Vec3i renderOrigin, float scale) { this.entity = entity; this.renderOrigin = renderOrigin; + this.scale = scale; } /** @@ -47,12 +60,10 @@ public class EntityVisibilityTester { } 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); + float x = (float) Mth.lerp(0.5D, aabb.minX, aabb.maxX) - renderOrigin.getX(); + float y = (float) Mth.lerp(0.5D, aabb.minY, aabb.maxY) - renderOrigin.getY(); + float z = (float) Mth.lerp(0.5D, aabb.minZ, aabb.maxZ) - renderOrigin.getZ(); + float maxSize = (float) Math.max(aabb.getXsize(), Math.max(aabb.getYsize(), aabb.getZsize())); + return frustum.testSphere(x, y, z, maxSize * MoreMath.SQRT_3_OVER_2 * scale); } }