Spheres your cubes

- Use sphere-frustum intersection tests in visuals.
- Seems to be ~20x faster.
This commit is contained in:
Jozufozu 2023-11-29 20:09:28 -08:00
parent bf6401a867
commit 5f81bc559f
4 changed files with 30 additions and 10 deletions

View file

@ -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;
}

View file

@ -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<T extends BlockEntity> 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);
}
/**

View file

@ -41,7 +41,7 @@ public abstract class AbstractEntityVisual<T extends Entity> 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);
}
/**

View file

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