diff --git a/common/src/api/java/dev/engine_room/flywheel/api/event/RenderContext.java b/common/src/api/java/dev/engine_room/flywheel/api/RenderContext.java similarity index 68% rename from common/src/api/java/dev/engine_room/flywheel/api/event/RenderContext.java rename to common/src/api/java/dev/engine_room/flywheel/api/RenderContext.java index ef27d4169..5fc9f68b5 100644 --- a/common/src/api/java/dev/engine_room/flywheel/api/event/RenderContext.java +++ b/common/src/api/java/dev/engine_room/flywheel/api/RenderContext.java @@ -1,7 +1,6 @@ -package dev.engine_room.flywheel.api.event; +package dev.engine_room.flywheel.api; -import org.jetbrains.annotations.ApiStatus; -import org.joml.Matrix4f; +import org.joml.Matrix4fc; import com.mojang.blaze3d.vertex.PoseStack; @@ -10,7 +9,6 @@ import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.renderer.LevelRenderer; import net.minecraft.client.renderer.RenderBuffers; -@ApiStatus.NonExtendable public interface RenderContext { LevelRenderer renderer(); @@ -20,9 +18,9 @@ public interface RenderContext { PoseStack stack(); - Matrix4f projection(); + Matrix4fc projection(); - Matrix4f viewProjection(); + Matrix4fc viewProjection(); Camera camera(); diff --git a/common/src/api/java/dev/engine_room/flywheel/api/backend/Backend.java b/common/src/api/java/dev/engine_room/flywheel/api/backend/Backend.java index f7b5cebe7..ca63659c7 100644 --- a/common/src/api/java/dev/engine_room/flywheel/api/backend/Backend.java +++ b/common/src/api/java/dev/engine_room/flywheel/api/backend/Backend.java @@ -1,13 +1,12 @@ package dev.engine_room.flywheel.api.backend; -import dev.engine_room.flywheel.api.BackendImplemented; import dev.engine_room.flywheel.api.internal.FlwApiLink; import dev.engine_room.flywheel.api.registry.IdRegistry; import net.minecraft.world.level.LevelAccessor; @BackendImplemented public interface Backend { - static IdRegistry REGISTRY = FlwApiLink.INSTANCE.createIdRegistry(); + IdRegistry REGISTRY = FlwApiLink.INSTANCE.createIdRegistry(); /** * Create a new engine instance. diff --git a/common/src/api/java/dev/engine_room/flywheel/api/BackendImplemented.java b/common/src/api/java/dev/engine_room/flywheel/api/backend/BackendImplemented.java similarity index 95% rename from common/src/api/java/dev/engine_room/flywheel/api/BackendImplemented.java rename to common/src/api/java/dev/engine_room/flywheel/api/backend/BackendImplemented.java index 6a5fbba4d..69765d6cf 100644 --- a/common/src/api/java/dev/engine_room/flywheel/api/BackendImplemented.java +++ b/common/src/api/java/dev/engine_room/flywheel/api/backend/BackendImplemented.java @@ -1,4 +1,4 @@ -package dev.engine_room.flywheel.api; +package dev.engine_room.flywheel.api.backend; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; diff --git a/common/src/api/java/dev/engine_room/flywheel/api/backend/BackendManager.java b/common/src/api/java/dev/engine_room/flywheel/api/backend/BackendManager.java index 876700a4d..039b2a528 100644 --- a/common/src/api/java/dev/engine_room/flywheel/api/backend/BackendManager.java +++ b/common/src/api/java/dev/engine_room/flywheel/api/backend/BackendManager.java @@ -9,19 +9,19 @@ public final class BackendManager { /** * Get the current backend. */ - public static Backend getBackend() { - return FlwApiLink.INSTANCE.getBackend(); + public static Backend currentBackend() { + return FlwApiLink.INSTANCE.getCurrentBackend(); } public static boolean isBackendOn() { return FlwApiLink.INSTANCE.isBackendOn(); } - public static Backend getOffBackend() { + public static Backend offBackend() { return FlwApiLink.INSTANCE.getOffBackend(); } - public static Backend getDefaultBackend() { + public static Backend defaultBackend() { return FlwApiLink.INSTANCE.getDefaultBackend(); } } diff --git a/common/src/api/java/dev/engine_room/flywheel/api/backend/Engine.java b/common/src/api/java/dev/engine_room/flywheel/api/backend/Engine.java index b6b7baa25..8c65ec5a1 100644 --- a/common/src/api/java/dev/engine_room/flywheel/api/backend/Engine.java +++ b/common/src/api/java/dev/engine_room/flywheel/api/backend/Engine.java @@ -2,52 +2,43 @@ package dev.engine_room.flywheel.api.backend; import java.util.List; -import dev.engine_room.flywheel.api.BackendImplemented; -import dev.engine_room.flywheel.api.event.RenderContext; -import dev.engine_room.flywheel.api.event.RenderStage; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Range; + +import dev.engine_room.flywheel.api.RenderContext; import dev.engine_room.flywheel.api.instance.Instance; import dev.engine_room.flywheel.api.task.Plan; -import dev.engine_room.flywheel.api.task.TaskExecutor; +import dev.engine_room.flywheel.api.visualization.VisualType; import dev.engine_room.flywheel.api.visualization.VisualizationContext; import it.unimi.dsi.fastutil.longs.LongSet; import net.minecraft.client.Camera; import net.minecraft.core.BlockPos; +import net.minecraft.core.SectionPos; import net.minecraft.core.Vec3i; +import net.minecraft.world.level.LightLayer; @BackendImplemented public interface Engine { /** - * Create a visualization context that will render to the given stage. + * Create a visualization context that will be used to create visuals of the given type. * - * @param stage The stage to render to. + * @param visualType The type of visual. * @return A new visualization context. */ - VisualizationContext createVisualizationContext(RenderStage stage); + VisualizationContext createVisualizationContext(VisualType visualType); /** - * Create a plan that will be executed every frame. + * Create a plan that will start execution after the start of the level render and + * finish execution before {@link #setupRender} is called. + * * @return A new plan. */ Plan createFramePlan(); /** - * Render all instances necessary for the given stage. - * @param executor The task executor running the frame plan. - * @param context The render context for this frame. - * @param stage The stage to render. + * @return The current render origin. */ - void renderStage(TaskExecutor executor, RenderContext context, RenderStage stage); - - /** - * Render the given instances as a crumbling overlay. - *
- * This is guaranteed to be called between the first and last calls to {@link #renderStage} for the current frame. - * - * @param executor The task executor running the frame plan. - * @param context The render context for this frame. - * @param crumblingBlocks The instances to render. This list is never empty. - */ - void renderCrumbling(TaskExecutor executor, RenderContext context, List crumblingBlocks); + Vec3i renderOrigin(); /** * Maintain the render origin to be within a certain distance from the camera in all directions, @@ -57,11 +48,6 @@ public interface Engine { */ boolean updateRenderOrigin(Camera camera); - /** - * @return The current render origin. - */ - Vec3i renderOrigin(); - /** * Assign the set of sections that visuals have requested GPU light for. * @@ -71,19 +57,70 @@ public interface Engine { */ void lightSections(LongSet sections); + void onLightUpdate(SectionPos sectionPos, LightLayer layer); + + /** + * Set up rendering for the current level render. + * + *

This method is guaranteed to be called after + * {@linkplain #createFramePlan() the frame plan} has finished execution and before + * {@link #render} and {@link #renderCrumbling} are called. This method is guaranteed to + * be called on the render thread. + * + * @param context The context for the current level render. + */ + void setupRender(RenderContext context); + + /** + * Render all instances necessary for the given visual type. + * + *

This method is guaranteed to be called after {@link #setupRender} for the current + * level render. This method is guaranteed to be called on the render thread. + * + * @param context The context for the current level render. + * @param visualType The type of visual. + */ + void render(RenderContext context, VisualType visualType); + + /** + * Render the given instances as a crumbling overlay. + * + *

This method is guaranteed to be called after {@link #setupRender} for the current + * level render. This method is guaranteed to be called on the render thread. + * + * @param context The context for the current level render. + * @param crumblingBlocks The instances to render. This list is never empty. + */ + void renderCrumbling(RenderContext context, List crumblingBlocks); + /** * Free all resources associated with this engine. - *
- * This engine will not be used again after this method is called. + * + *

This engine will not be used again after this method is called. + * + *

This method is guaranteed to be called on the render thread. */ void delete(); /** * A block to be rendered as a crumbling overlay. - * @param progress The progress of the crumbling animation in the range [0, 10). - * @param pos The position of the block. - * @param instances The instances associated with the BE at this position. */ - record CrumblingBlock(int progress, BlockPos pos, List instances) { + @ApiStatus.NonExtendable + interface CrumblingBlock { + /** + * The position of the block. + */ + BlockPos pos(); + + /** + * The progress of the crumbling animation in the range [0, 10). + */ + @Range(from = 0, to = 9) + int progress(); + + /** + * The instances associated with the block entity visual at this position. + */ + List instances(); } } diff --git a/common/src/api/java/dev/engine_room/flywheel/api/event/RenderStage.java b/common/src/api/java/dev/engine_room/flywheel/api/event/RenderStage.java deleted file mode 100644 index 27183b586..000000000 --- a/common/src/api/java/dev/engine_room/flywheel/api/event/RenderStage.java +++ /dev/null @@ -1,27 +0,0 @@ -package dev.engine_room.flywheel.api.event; - -public enum RenderStage { - AFTER_ENTITIES, - AFTER_BLOCK_ENTITIES, - AFTER_TRANSLUCENT_TERRAIN, - AFTER_PARTICLES, - AFTER_WEATHER; - - /** - * Is this stage the last one to be rendered in the frame? - * - * @return {@code true} if no other RenderStages will be dispatched this frame. - */ - public boolean isLast() { - return this == values()[values().length - 1]; - } - - /** - * Is this stage the first one to be rendered in the frame? - * - * @return {@code true} if this is the first RenderStage to be dispatched this frame. - */ - public boolean isFirst() { - return this == values()[0]; - } -} diff --git a/common/src/api/java/dev/engine_room/flywheel/api/instance/Instance.java b/common/src/api/java/dev/engine_room/flywheel/api/instance/Instance.java index 19748e9ab..9d86d018c 100644 --- a/common/src/api/java/dev/engine_room/flywheel/api/instance/Instance.java +++ b/common/src/api/java/dev/engine_room/flywheel/api/instance/Instance.java @@ -5,11 +5,11 @@ public interface Instance { InstanceHandle handle(); - default void delete() { - handle().setDeleted(); - } - default void setChanged() { handle().setChanged(); } + + default void delete() { + handle().setDeleted(); + } } diff --git a/common/src/api/java/dev/engine_room/flywheel/api/instance/InstanceHandle.java b/common/src/api/java/dev/engine_room/flywheel/api/instance/InstanceHandle.java index f0847058e..ea2065dd0 100644 --- a/common/src/api/java/dev/engine_room/flywheel/api/instance/InstanceHandle.java +++ b/common/src/api/java/dev/engine_room/flywheel/api/instance/InstanceHandle.java @@ -1,6 +1,6 @@ package dev.engine_room.flywheel.api.instance; -import dev.engine_room.flywheel.api.BackendImplemented; +import dev.engine_room.flywheel.api.backend.BackendImplemented; @BackendImplemented public interface InstanceHandle { diff --git a/common/src/api/java/dev/engine_room/flywheel/api/instance/InstanceType.java b/common/src/api/java/dev/engine_room/flywheel/api/instance/InstanceType.java index d5e1fbb3e..887bb6cda 100644 --- a/common/src/api/java/dev/engine_room/flywheel/api/instance/InstanceType.java +++ b/common/src/api/java/dev/engine_room/flywheel/api/instance/InstanceType.java @@ -11,7 +11,7 @@ import net.minecraft.resources.ResourceLocation; * @param The java representation of the instance. */ public interface InstanceType { - static Registry> REGISTRY = FlwApiLink.INSTANCE.createRegistry(); + Registry> REGISTRY = FlwApiLink.INSTANCE.createRegistry(); /** * @param handle A handle that allows you to mark the instance as dirty or deleted. diff --git a/common/src/api/java/dev/engine_room/flywheel/api/instance/Instancer.java b/common/src/api/java/dev/engine_room/flywheel/api/instance/Instancer.java index c0b0a5679..704f0a9b4 100644 --- a/common/src/api/java/dev/engine_room/flywheel/api/instance/Instancer.java +++ b/common/src/api/java/dev/engine_room/flywheel/api/instance/Instancer.java @@ -2,7 +2,7 @@ package dev.engine_room.flywheel.api.instance; import org.jetbrains.annotations.Nullable; -import dev.engine_room.flywheel.api.BackendImplemented; +import dev.engine_room.flywheel.api.backend.BackendImplemented; /** * An instancer is how you interact with an instanced model. @@ -29,6 +29,17 @@ public interface Instancer { */ I createInstance(); + /** + * Populate arr with new instances of this model. + * + * @param arr An array to fill. + */ + default void createInstances(I[] arr) { + for (int i = 0; i < arr.length; i++) { + arr[i] = createInstance(); + } + } + /** * Steal an instance from another instancer. *
@@ -43,15 +54,4 @@ public interface Instancer { * @param instance The instance to steal. */ void stealInstance(@Nullable I instance); - - /** - * Populate arr with new instances of this model. - * - * @param arr An array to fill. - */ - default void createInstances(I[] arr) { - for (int i = 0; i < arr.length; i++) { - arr[i] = createInstance(); - } - } } diff --git a/common/src/api/java/dev/engine_room/flywheel/api/instance/InstancerProvider.java b/common/src/api/java/dev/engine_room/flywheel/api/instance/InstancerProvider.java index 97196d5fd..8feb72ca3 100644 --- a/common/src/api/java/dev/engine_room/flywheel/api/instance/InstancerProvider.java +++ b/common/src/api/java/dev/engine_room/flywheel/api/instance/InstancerProvider.java @@ -1,6 +1,6 @@ package dev.engine_room.flywheel.api.instance; -import dev.engine_room.flywheel.api.BackendImplemented; +import dev.engine_room.flywheel.api.backend.BackendImplemented; import dev.engine_room.flywheel.api.model.Model; @BackendImplemented diff --git a/common/src/api/java/dev/engine_room/flywheel/api/internal/FlwApiLink.java b/common/src/api/java/dev/engine_room/flywheel/api/internal/FlwApiLink.java index 2fe8537cc..b60a52fe4 100644 --- a/common/src/api/java/dev/engine_room/flywheel/api/internal/FlwApiLink.java +++ b/common/src/api/java/dev/engine_room/flywheel/api/internal/FlwApiLink.java @@ -22,7 +22,7 @@ public interface FlwApiLink { IdRegistry createIdRegistry(); - Backend getBackend(); + Backend getCurrentBackend(); boolean isBackendOn(); diff --git a/common/src/api/java/dev/engine_room/flywheel/api/material/CutoutShader.java b/common/src/api/java/dev/engine_room/flywheel/api/material/CutoutShader.java index d3e54294a..4798cece4 100644 --- a/common/src/api/java/dev/engine_room/flywheel/api/material/CutoutShader.java +++ b/common/src/api/java/dev/engine_room/flywheel/api/material/CutoutShader.java @@ -5,7 +5,7 @@ import dev.engine_room.flywheel.api.registry.Registry; import net.minecraft.resources.ResourceLocation; public interface CutoutShader { - static Registry REGISTRY = FlwApiLink.INSTANCE.createRegistry(); + Registry REGISTRY = FlwApiLink.INSTANCE.createRegistry(); ResourceLocation source(); } diff --git a/common/src/api/java/dev/engine_room/flywheel/api/material/FogShader.java b/common/src/api/java/dev/engine_room/flywheel/api/material/FogShader.java index 4309d53a7..91ef5f90b 100644 --- a/common/src/api/java/dev/engine_room/flywheel/api/material/FogShader.java +++ b/common/src/api/java/dev/engine_room/flywheel/api/material/FogShader.java @@ -5,7 +5,7 @@ import dev.engine_room.flywheel.api.registry.Registry; import net.minecraft.resources.ResourceLocation; public interface FogShader { - static Registry REGISTRY = FlwApiLink.INSTANCE.createRegistry(); + Registry REGISTRY = FlwApiLink.INSTANCE.createRegistry(); ResourceLocation source(); } diff --git a/common/src/api/java/dev/engine_room/flywheel/api/material/MaterialShaders.java b/common/src/api/java/dev/engine_room/flywheel/api/material/MaterialShaders.java index a8f83b1f1..0ef2c1ab6 100644 --- a/common/src/api/java/dev/engine_room/flywheel/api/material/MaterialShaders.java +++ b/common/src/api/java/dev/engine_room/flywheel/api/material/MaterialShaders.java @@ -5,9 +5,9 @@ import dev.engine_room.flywheel.api.registry.Registry; import net.minecraft.resources.ResourceLocation; public interface MaterialShaders { - static Registry REGISTRY = FlwApiLink.INSTANCE.createRegistry(); + Registry REGISTRY = FlwApiLink.INSTANCE.createRegistry(); - ResourceLocation vertexShader(); + ResourceLocation vertexSource(); - ResourceLocation fragmentShader(); + ResourceLocation fragmentSource(); } diff --git a/common/src/api/java/dev/engine_room/flywheel/api/model/Mesh.java b/common/src/api/java/dev/engine_room/flywheel/api/model/Mesh.java index 803d11d19..1072d3956 100644 --- a/common/src/api/java/dev/engine_room/flywheel/api/model/Mesh.java +++ b/common/src/api/java/dev/engine_room/flywheel/api/model/Mesh.java @@ -31,9 +31,4 @@ public interface Mesh { * @return A vec4 view. */ Vector4fc boundingSphere(); - - /** - * Free this mesh's resources, memory, etc. - */ - void delete(); } diff --git a/common/src/api/java/dev/engine_room/flywheel/api/model/Model.java b/common/src/api/java/dev/engine_room/flywheel/api/model/Model.java index 4f97f2076..64b240d4b 100644 --- a/common/src/api/java/dev/engine_room/flywheel/api/model/Model.java +++ b/common/src/api/java/dev/engine_room/flywheel/api/model/Model.java @@ -27,8 +27,6 @@ public interface Model { */ Vector4fc boundingSphere(); - void delete(); - record ConfiguredMesh(Material material, Mesh mesh) { } } diff --git a/common/src/api/java/dev/engine_room/flywheel/api/registry/IdRegistry.java b/common/src/api/java/dev/engine_room/flywheel/api/registry/IdRegistry.java index 2add5a59b..a2528ce03 100644 --- a/common/src/api/java/dev/engine_room/flywheel/api/registry/IdRegistry.java +++ b/common/src/api/java/dev/engine_room/flywheel/api/registry/IdRegistry.java @@ -2,11 +2,10 @@ package dev.engine_room.flywheel.api.registry; import java.util.Collection; import java.util.Set; -import java.util.function.Consumer; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; -import org.jetbrains.annotations.Unmodifiable; +import org.jetbrains.annotations.UnmodifiableView; import net.minecraft.resources.ResourceLocation; @@ -26,13 +25,11 @@ public interface IdRegistry extends Iterable { ResourceLocation getIdOrThrow(T object); - @Unmodifiable + @UnmodifiableView Set getAllIds(); - @Unmodifiable + @UnmodifiableView Collection getAll(); - void addFreezeCallback(Consumer> callback); - boolean isFrozen(); } diff --git a/common/src/api/java/dev/engine_room/flywheel/api/registry/Registry.java b/common/src/api/java/dev/engine_room/flywheel/api/registry/Registry.java index 7f14eda04..7cb7edb56 100644 --- a/common/src/api/java/dev/engine_room/flywheel/api/registry/Registry.java +++ b/common/src/api/java/dev/engine_room/flywheel/api/registry/Registry.java @@ -1,10 +1,9 @@ package dev.engine_room.flywheel.api.registry; import java.util.Set; -import java.util.function.Consumer; import org.jetbrains.annotations.ApiStatus; -import org.jetbrains.annotations.Unmodifiable; +import org.jetbrains.annotations.UnmodifiableView; @ApiStatus.NonExtendable public interface Registry extends Iterable { @@ -12,10 +11,8 @@ public interface Registry extends Iterable { S registerAndGet(S object); - @Unmodifiable + @UnmodifiableView Set getAll(); - void addFreezeCallback(Consumer> callback); - boolean isFrozen(); } diff --git a/common/src/api/java/dev/engine_room/flywheel/api/task/TaskExecutor.java b/common/src/api/java/dev/engine_room/flywheel/api/task/TaskExecutor.java index 0ec30f038..f8fd35cb2 100644 --- a/common/src/api/java/dev/engine_room/flywheel/api/task/TaskExecutor.java +++ b/common/src/api/java/dev/engine_room/flywheel/api/task/TaskExecutor.java @@ -1,64 +1,11 @@ package dev.engine_room.flywheel.api.task; import java.util.concurrent.Executor; -import java.util.function.BooleanSupplier; import org.jetbrains.annotations.ApiStatus; @ApiStatus.NonExtendable public interface TaskExecutor extends Executor { - /** - * Wait for all running tasks to finish. - *
- * This is useful as a nuclear option, but most of the time you should - * try to use {@link #syncUntil(BooleanSupplier) syncUntil}. - */ - void syncPoint(); - - /** - * Wait for running tasks, until the given condition is met - * ({@link BooleanSupplier#getAsBoolean()} returns {@code true}). - *
- * This method is equivalent to {@code syncWhile(() -> !cond.getAsBoolean())}. - * - * @param cond The condition to wait for. - * @return {@code true} if the condition is met. {@code false} if - * this executor runs out of tasks before the condition is met. - */ - boolean syncUntil(BooleanSupplier cond); - - /** - * Wait for running tasks, so long as the given condition is met - * ({@link BooleanSupplier#getAsBoolean()} returns {@code true}). - *
- * If this method is called on the - *
- * This method is equivalent to {@code syncUntil(() -> !cond.getAsBoolean())}. - * - * @param cond The condition sync on. - * @return {@code true} if the condition is no longer met. {@code false} if - * this executor runs out of tasks while the condition is still met. - */ - boolean syncWhile(BooleanSupplier cond); - - /** - * Schedule a task to be run on the main thread. - *
- * This method may be called from any thread (including the main thread), - * but the runnable will only be executed once somebody calls - * either {@link #syncPoint()} or {@link #syncUntil(BooleanSupplier)} - * on this task executor's main thread. - * @param runnable The task to run. - */ - void scheduleForMainThread(Runnable runnable); - - /** - * Check whether the current thread is this task executor's main thread. - * - * @return {@code true} if the current thread is the main thread. - */ - boolean isMainThread(); - /** * Check for the number of threads this executor uses. *
diff --git a/common/src/api/java/dev/engine_room/flywheel/api/vertex/VertexView.java b/common/src/api/java/dev/engine_room/flywheel/api/vertex/VertexView.java deleted file mode 100644 index 1abfda114..000000000 --- a/common/src/api/java/dev/engine_room/flywheel/api/vertex/VertexView.java +++ /dev/null @@ -1,11 +0,0 @@ -package dev.engine_room.flywheel.api.vertex; - -public interface VertexView extends MutableVertexList { - long ptr(); - - void ptr(long ptr); - - void vertexCount(int vertexCount); - - long stride(); -} diff --git a/common/src/api/java/dev/engine_room/flywheel/api/visual/Effect.java b/common/src/api/java/dev/engine_room/flywheel/api/visual/Effect.java index 446038942..fdf65bc27 100644 --- a/common/src/api/java/dev/engine_room/flywheel/api/visual/Effect.java +++ b/common/src/api/java/dev/engine_room/flywheel/api/visual/Effect.java @@ -1,6 +1,7 @@ package dev.engine_room.flywheel.api.visual; import dev.engine_room.flywheel.api.visualization.VisualizationContext; +import net.minecraft.world.level.LevelAccessor; /** * An effect is not attached to any formal game object, but allows you to hook into @@ -8,6 +9,8 @@ import dev.engine_room.flywheel.api.visualization.VisualizationContext; * without any built in support for networking. */ public interface Effect { + LevelAccessor level(); + /** * Create a visual that will be keyed by this effect object. * diff --git a/common/src/api/java/dev/engine_room/flywheel/api/visual/SectionTrackedVisual.java b/common/src/api/java/dev/engine_room/flywheel/api/visual/SectionTrackedVisual.java index a2189357a..653ec3b73 100644 --- a/common/src/api/java/dev/engine_room/flywheel/api/visual/SectionTrackedVisual.java +++ b/common/src/api/java/dev/engine_room/flywheel/api/visual/SectionTrackedVisual.java @@ -4,7 +4,7 @@ import org.jetbrains.annotations.ApiStatus; import it.unimi.dsi.fastutil.longs.LongSet; -public sealed interface SectionTrackedVisual extends Visual permits ShaderLightVisual, LightUpdatedVisual { +public sealed interface SectionTrackedVisual extends Visual permits LightUpdatedVisual, ShaderLightVisual { /** * Set the section collector object. * diff --git a/common/src/api/java/dev/engine_room/flywheel/api/visualization/VisualEmbedding.java b/common/src/api/java/dev/engine_room/flywheel/api/visualization/VisualEmbedding.java index baf35844c..f479602b4 100644 --- a/common/src/api/java/dev/engine_room/flywheel/api/visualization/VisualEmbedding.java +++ b/common/src/api/java/dev/engine_room/flywheel/api/visualization/VisualEmbedding.java @@ -3,7 +3,7 @@ package dev.engine_room.flywheel.api.visualization; import org.joml.Matrix3fc; import org.joml.Matrix4fc; -import dev.engine_room.flywheel.api.BackendImplemented; +import dev.engine_room.flywheel.api.backend.BackendImplemented; @BackendImplemented public interface VisualEmbedding extends VisualizationContext { diff --git a/common/src/api/java/dev/engine_room/flywheel/api/visualization/VisualManager.java b/common/src/api/java/dev/engine_room/flywheel/api/visualization/VisualManager.java index 10d9abdfc..b25bd9947 100644 --- a/common/src/api/java/dev/engine_room/flywheel/api/visualization/VisualManager.java +++ b/common/src/api/java/dev/engine_room/flywheel/api/visualization/VisualManager.java @@ -9,7 +9,7 @@ public interface VisualManager { * * @return The visual count. */ - int getVisualCount(); + int visualCount(); void queueAdd(T obj); diff --git a/common/src/api/java/dev/engine_room/flywheel/api/visualization/VisualType.java b/common/src/api/java/dev/engine_room/flywheel/api/visualization/VisualType.java new file mode 100644 index 000000000..486eaa532 --- /dev/null +++ b/common/src/api/java/dev/engine_room/flywheel/api/visualization/VisualType.java @@ -0,0 +1,7 @@ +package dev.engine_room.flywheel.api.visualization; + +public enum VisualType { + BLOCK_ENTITY, + ENTITY, + EFFECT; +} diff --git a/common/src/api/java/dev/engine_room/flywheel/api/visualization/VisualizationContext.java b/common/src/api/java/dev/engine_room/flywheel/api/visualization/VisualizationContext.java index 4d5088214..a45422667 100644 --- a/common/src/api/java/dev/engine_room/flywheel/api/visualization/VisualizationContext.java +++ b/common/src/api/java/dev/engine_room/flywheel/api/visualization/VisualizationContext.java @@ -1,6 +1,6 @@ package dev.engine_room.flywheel.api.visualization; -import dev.engine_room.flywheel.api.BackendImplemented; +import dev.engine_room.flywheel.api.backend.BackendImplemented; import dev.engine_room.flywheel.api.instance.InstancerProvider; import net.minecraft.core.Vec3i; diff --git a/common/src/api/java/dev/engine_room/flywheel/api/visualization/VisualizationManager.java b/common/src/api/java/dev/engine_room/flywheel/api/visualization/VisualizationManager.java index 0cd976d15..2579d5f86 100644 --- a/common/src/api/java/dev/engine_room/flywheel/api/visualization/VisualizationManager.java +++ b/common/src/api/java/dev/engine_room/flywheel/api/visualization/VisualizationManager.java @@ -1,14 +1,17 @@ package dev.engine_room.flywheel.api.visualization; +import java.util.SortedSet; + import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; +import dev.engine_room.flywheel.api.RenderContext; import dev.engine_room.flywheel.api.internal.FlwApiLink; import dev.engine_room.flywheel.api.visual.Effect; -import dev.engine_room.flywheel.api.visual.Visual; +import it.unimi.dsi.fastutil.longs.Long2ObjectMap; import net.minecraft.core.Vec3i; +import net.minecraft.server.level.BlockDestructionProgress; import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.entity.BlockEntity; @@ -27,52 +30,31 @@ public interface VisualizationManager { return FlwApiLink.INSTANCE.getVisualizationManagerOrThrow(level); } - /** - * Call this when you want to run {@link Visual#update}. - * @param blockEntity The block entity whose visual you want to update. - */ - static void queueUpdate(BlockEntity blockEntity) { - Level level = blockEntity.getLevel(); - VisualizationManager manager = get(level); - if (manager == null) { - return; - } + Vec3i renderOrigin(); - manager.getBlockEntities().queueUpdate(blockEntity); - } + VisualManager blockEntities(); + + VisualManager entities(); + + VisualManager effects(); /** - * Call this when you want to run {@link Visual#update}. - * @param entity The entity whose visual you want to update. + * Get the render dispatcher, which can be used to invoke rendering. + * This should only be used by mods which heavily rewrite rendering to restore compatibility with Flywheel + * without mixins. */ - static void queueUpdate(Entity entity) { - Level level = entity.level(); - VisualizationManager manager = get(level); - if (manager == null) { - return; - } + RenderDispatcher renderDispatcher(); - manager.getEntities().queueUpdate(entity); + @ApiStatus.NonExtendable + interface RenderDispatcher { + void onStartLevelRender(RenderContext ctx); + + void afterBlockEntities(RenderContext ctx); + + void afterEntities(RenderContext ctx); + + void beforeCrumbling(RenderContext ctx, Long2ObjectMap> destructionProgress); + + void afterParticles(RenderContext ctx); } - - /** - * Call this when you want to run {@link Visual#update}. - * @param effect The effect whose visual you want to update. - */ - static void queueUpdate(LevelAccessor level, Effect effect) { - VisualizationManager manager = get(level); - if (manager == null) { - return; - } - - manager.getEffects().queueUpdate(effect); - } - - Vec3i getRenderOrigin(); - - VisualManager getBlockEntities(); - - VisualManager getEntities(); - - VisualManager getEffects(); } diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/FlwBackend.java b/common/src/backend/java/dev/engine_room/flywheel/backend/FlwBackend.java index 36fc3b920..a51878268 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/FlwBackend.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/FlwBackend.java @@ -12,7 +12,6 @@ public final class FlwBackend { } public static void init() { - ShaderIndices.init(); Backends.init(); } } diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/InternalVertex.java b/common/src/backend/java/dev/engine_room/flywheel/backend/InternalVertex.java index 85d1dc055..524e5a0b4 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/InternalVertex.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/InternalVertex.java @@ -6,9 +6,9 @@ import dev.engine_room.flywheel.api.Flywheel; import dev.engine_room.flywheel.api.layout.FloatRepr; import dev.engine_room.flywheel.api.layout.Layout; import dev.engine_room.flywheel.api.layout.LayoutBuilder; -import dev.engine_room.flywheel.api.vertex.VertexView; import dev.engine_room.flywheel.backend.gl.array.VertexAttribute; import dev.engine_room.flywheel.lib.vertex.FullVertexView; +import dev.engine_room.flywheel.lib.vertex.VertexView; import net.minecraft.resources.ResourceLocation; public final class InternalVertex { diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/LightUpdateHolder.java b/common/src/backend/java/dev/engine_room/flywheel/backend/LightUpdateHolder.java deleted file mode 100644 index e6f9e856d..000000000 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/LightUpdateHolder.java +++ /dev/null @@ -1,37 +0,0 @@ -package dev.engine_room.flywheel.backend; - -import dev.engine_room.flywheel.lib.util.LevelAttached; -import it.unimi.dsi.fastutil.longs.LongArraySet; -import it.unimi.dsi.fastutil.longs.LongOpenHashSet; -import it.unimi.dsi.fastutil.longs.LongSet; -import net.minecraft.world.level.LevelAccessor; - -/** - * Stores the set of updates light sections for LightStorage to poll in its frame plan. - */ -public class LightUpdateHolder { - private static final LevelAttached HOLDERS = new LevelAttached<>(level -> new LightUpdateHolder()); - - private final LongSet updatedSections = new LongOpenHashSet(); - - private LightUpdateHolder() { - } - - public static LightUpdateHolder get(LevelAccessor level) { - return HOLDERS.get(level); - } - - public LongSet getAndClearUpdatedSections() { - if (updatedSections.isEmpty()) { - return LongSet.of(); - } - - var out = new LongArraySet(updatedSections); - updatedSections.clear(); - return out; - } - - public void add(long section) { - updatedSections.add(section); - } -} diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/MaterialShaderIndices.java b/common/src/backend/java/dev/engine_room/flywheel/backend/MaterialShaderIndices.java new file mode 100644 index 000000000..8592a9e65 --- /dev/null +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/MaterialShaderIndices.java @@ -0,0 +1,135 @@ +package dev.engine_room.flywheel.backend; + +import java.util.List; +import java.util.function.Function; + +import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.Unmodifiable; + +import dev.engine_room.flywheel.api.material.CutoutShader; +import dev.engine_room.flywheel.api.material.FogShader; +import dev.engine_room.flywheel.api.material.MaterialShaders; +import dev.engine_room.flywheel.api.registry.Registry; +import it.unimi.dsi.fastutil.objects.Object2IntMap; +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import it.unimi.dsi.fastutil.objects.ObjectList; +import net.minecraft.resources.ResourceLocation; + +public final class MaterialShaderIndices { + @Nullable + private static Index vertexSources; + @Nullable + private static Index fragmentSources; + @Nullable + private static Index fogSources; + @Nullable + private static Index cutoutSources; + + private MaterialShaderIndices() { + } + + public static Index vertexSources() { + if (vertexSources == null) { + vertexSources = indexFromRegistry(MaterialShaders.REGISTRY, MaterialShaders::vertexSource); + } + return vertexSources; + } + + public static Index fragmentSources() { + if (fragmentSources == null) { + fragmentSources = indexFromRegistry(MaterialShaders.REGISTRY, MaterialShaders::fragmentSource); + } + return fragmentSources; + } + + public static Index fogSources() { + if (fogSources == null) { + fogSources = indexFromRegistry(FogShader.REGISTRY, FogShader::source); + } + return fogSources; + } + + public static Index cutoutSources() { + if (cutoutSources == null) { + cutoutSources = indexFromRegistry(CutoutShader.REGISTRY, CutoutShader::source); + } + return cutoutSources; + } + + public static int vertexIndex(MaterialShaders shaders) { + return vertexSources().index(shaders.vertexSource()); + } + + public static int fragmentIndex(MaterialShaders shaders) { + return fragmentSources().index(shaders.fragmentSource()); + } + + public static int fogIndex(FogShader fogShader) { + return fogSources().index(fogShader.source()); + } + + public static int cutoutIndex(CutoutShader cutoutShader) { + return cutoutSources().index(cutoutShader.source()); + } + + private static Index indexFromRegistry(Registry registry, Function sourceFunc) { + if (!registry.isFrozen()) { + throw new IllegalStateException("Cannot create index from registry that is not frozen!"); + } + + var builder = new IndexBuilder(); + + for (T object : registry) { + builder.add(sourceFunc.apply(object)); + } + + return builder.build(); + } + + public static class Index { + private final Object2IntMap sources2Index; + private final ObjectList sources; + + private Index(IndexBuilder builder) { + this.sources2Index = new Object2IntOpenHashMap<>(builder.sources2Index); + this.sources = new ObjectArrayList<>(builder.sources); + } + + public int index(ResourceLocation source) { + return sources2Index.getInt(source); + } + + public ResourceLocation get(int index) { + return sources.get(index); + } + + @Unmodifiable + public List all() { + return sources; + } + } + + private static class IndexBuilder { + private final Object2IntMap sources2Index; + private final ObjectList sources; + private int index = 0; + + public IndexBuilder() { + sources2Index = new Object2IntOpenHashMap<>(); + sources2Index.defaultReturnValue(-1); + sources = new ObjectArrayList<>(); + } + + public void add(ResourceLocation source) { + if (sources2Index.putIfAbsent(source, index) == -1) { + sources.add(source); + index++; + } + } + + public Index build() { + return new Index(this); + } + } +} diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/ShaderIndices.java b/common/src/backend/java/dev/engine_room/flywheel/backend/ShaderIndices.java deleted file mode 100644 index 7905fa694..000000000 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/ShaderIndices.java +++ /dev/null @@ -1,170 +0,0 @@ -package dev.engine_room.flywheel.backend; - -import java.util.List; - -import org.jetbrains.annotations.Nullable; -import org.jetbrains.annotations.Unmodifiable; - -import dev.engine_room.flywheel.api.material.CutoutShader; -import dev.engine_room.flywheel.api.material.FogShader; -import dev.engine_room.flywheel.api.material.MaterialShaders; -import dev.engine_room.flywheel.api.registry.Registry; -import it.unimi.dsi.fastutil.objects.Object2IntMap; -import it.unimi.dsi.fastutil.objects.Object2IntMaps; -import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; -import it.unimi.dsi.fastutil.objects.ObjectArrayList; -import it.unimi.dsi.fastutil.objects.ObjectList; -import it.unimi.dsi.fastutil.objects.ObjectLists; -import net.minecraft.resources.ResourceLocation; - -public final class ShaderIndices { - @Nullable - private static Index vertexShaders; - @Nullable - private static Index fragmentShaders; - @Nullable - private static Index fogShaders; - @Nullable - private static Index cutoutShaders; - - private ShaderIndices() { - } - - public static Index materialVertex() { - if (vertexShaders == null) { - throw new IllegalStateException("Not initialized!"); - } - return vertexShaders; - } - - public static Index materialFragment() { - if (fragmentShaders == null) { - throw new IllegalStateException("Not initialized!"); - } - return fragmentShaders; - } - - public static Index fog() { - if (fogShaders == null) { - throw new IllegalStateException("Not initialized!"); - } - return fogShaders; - } - - public static Index cutout() { - if (cutoutShaders == null) { - throw new IllegalStateException("Not initialized!"); - } - return cutoutShaders; - } - - public static int getVertexShaderIndex(MaterialShaders shaders) { - return materialVertex().index(shaders.vertexShader()); - } - - public static int getFragmentShaderIndex(MaterialShaders shaders) { - return materialFragment().index(shaders.fragmentShader()); - } - - public static int getFogShaderIndex(FogShader fogShader) { - return fog().index(fogShader.source()); - } - - public static int getCutoutShaderIndex(CutoutShader cutoutShader) { - return cutout().index(cutoutShader.source()); - } - - private static void initMaterialShaders(Registry registry) { - int amount = registry.getAll() - .size(); - - var vertexShaders = new IndexBuilder(amount); - var fragmentShaders = new IndexBuilder(amount); - - for (MaterialShaders shaders : registry) { - vertexShaders.add(shaders.vertexShader()); - fragmentShaders.add(shaders.fragmentShader()); - } - - ShaderIndices.vertexShaders = vertexShaders.build(); - ShaderIndices.fragmentShaders = fragmentShaders.build(); - } - - private static void initFogShaders(Registry registry) { - int amount = registry.getAll() - .size(); - - var fog = new IndexBuilder(amount); - - for (FogShader shaders : registry) { - fog.add(shaders.source()); - } - - ShaderIndices.fogShaders = fog.build(); - } - - private static void initCutoutShaders(Registry registry) { - int amount = registry.getAll() - .size(); - - var cutout = new IndexBuilder(amount); - - for (CutoutShader shaders : registry) { - cutout.add(shaders.source()); - } - - ShaderIndices.cutoutShaders = cutout.build(); - } - - public static void init() { - MaterialShaders.REGISTRY.addFreezeCallback(ShaderIndices::initMaterialShaders); - FogShader.REGISTRY.addFreezeCallback(ShaderIndices::initFogShaders); - CutoutShader.REGISTRY.addFreezeCallback(ShaderIndices::initCutoutShaders); - } - - public static class Index { - private final Object2IntMap shaders2Index; - private final ObjectList shaders; - - private Index(IndexBuilder builder) { - this.shaders2Index = Object2IntMaps.unmodifiable(builder.shaders2Index); - this.shaders = ObjectLists.unmodifiable(builder.shaders); - } - - public int index(ResourceLocation shader) { - return shaders2Index.getInt(shader); - } - - @Unmodifiable - public List all() { - return shaders; - } - - public ResourceLocation get(int index) { - return shaders.get(index); - } - } - - private static class IndexBuilder { - private int index; - private final Object2IntMap shaders2Index; - private final ObjectList shaders; - - public IndexBuilder(int amount) { - shaders2Index = new Object2IntOpenHashMap<>(); - shaders2Index.defaultReturnValue(-1); - shaders = new ObjectArrayList<>(amount); - } - - public void add(ResourceLocation shader) { - if (shaders2Index.putIfAbsent(shader, index) == -1) { - shaders.add(shader); - index++; - } - } - - public Index build() { - return new Index(this); - } - } -} diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/compile/FlwPrograms.java b/common/src/backend/java/dev/engine_room/flywheel/backend/compile/FlwPrograms.java index f457d5bf4..5a8f47086 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/compile/FlwPrograms.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/compile/FlwPrograms.java @@ -10,7 +10,7 @@ import com.google.common.collect.ImmutableList; import dev.engine_room.flywheel.api.Flywheel; import dev.engine_room.flywheel.api.instance.InstanceType; -import dev.engine_room.flywheel.backend.ShaderIndices; +import dev.engine_room.flywheel.backend.MaterialShaderIndices; import dev.engine_room.flywheel.backend.compile.component.UberShaderComponent; import dev.engine_room.flywheel.backend.compile.core.CompilerStats; import dev.engine_room.flywheel.backend.compile.core.SourceLoader; @@ -74,7 +74,7 @@ public final class FlwPrograms { @Nullable private static UberShaderComponent createVertexMaterialComponent(SourceLoader loader) { return UberShaderComponent.builder(Flywheel.rl("material_vertex")) - .materialSources(ShaderIndices.materialVertex() + .materialSources(MaterialShaderIndices.vertexSources() .all()) .adapt(FnSignature.ofVoid("flw_materialVertex")) .switchOn(GlslExpr.variable("_flw_uberMaterialVertexIndex")) @@ -84,7 +84,7 @@ public final class FlwPrograms { @Nullable private static UberShaderComponent createFragmentMaterialComponent(SourceLoader loader) { return UberShaderComponent.builder(Flywheel.rl("material_fragment")) - .materialSources(ShaderIndices.materialFragment() + .materialSources(MaterialShaderIndices.fragmentSources() .all()) .adapt(FnSignature.ofVoid("flw_materialFragment")) .switchOn(GlslExpr.variable("_flw_uberMaterialFragmentIndex")) @@ -94,7 +94,7 @@ public final class FlwPrograms { @Nullable private static UberShaderComponent createFogComponent(SourceLoader loader) { return UberShaderComponent.builder(Flywheel.rl("fog")) - .materialSources(ShaderIndices.fog() + .materialSources(MaterialShaderIndices.fogSources() .all()) .adapt(FnSignature.create() .returnType("vec4") @@ -108,7 +108,7 @@ public final class FlwPrograms { @Nullable private static UberShaderComponent createCutoutComponent(SourceLoader loader) { return UberShaderComponent.builder(Flywheel.rl("cutout")) - .materialSources(ShaderIndices.cutout() + .materialSources(MaterialShaderIndices.cutoutSources() .all()) .adapt(FnSignature.create() .returnType("bool") diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/AbstractInstancer.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/AbstractInstancer.java index 6cbadf9c9..73f8c1714 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/AbstractInstancer.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/AbstractInstancer.java @@ -8,7 +8,7 @@ import dev.engine_room.flywheel.api.instance.Instance; import dev.engine_room.flywheel.api.instance.InstanceType; import dev.engine_room.flywheel.api.instance.Instancer; import dev.engine_room.flywheel.backend.engine.embed.Environment; -import dev.engine_room.flywheel.lib.util.AtomicBitSet; +import dev.engine_room.flywheel.backend.util.AtomicBitSet; public abstract class AbstractInstancer implements Instancer { public final InstanceType type; diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/DrawManager.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/DrawManager.java index 8b78be928..4f74b1fc1 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/DrawManager.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/DrawManager.java @@ -9,11 +9,11 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; import dev.engine_room.flywheel.api.backend.Engine; -import dev.engine_room.flywheel.api.event.RenderStage; import dev.engine_room.flywheel.api.instance.Instance; import dev.engine_room.flywheel.api.instance.InstanceType; import dev.engine_room.flywheel.api.instance.Instancer; import dev.engine_room.flywheel.api.model.Model; +import dev.engine_room.flywheel.api.visualization.VisualType; import dev.engine_room.flywheel.backend.FlwBackend; import dev.engine_room.flywheel.backend.engine.embed.Environment; import dev.engine_room.flywheel.lib.util.Pair; @@ -36,13 +36,8 @@ public abstract class DrawManager> { protected final Queue> initializationQueue = new ConcurrentLinkedQueue<>(); @SuppressWarnings("unchecked") - public Instancer getInstancer(Environment environment, InstanceType type, Model model, RenderStage stage) { - return (Instancer) instancers.computeIfAbsent(new InstancerKey<>(environment, type, model, stage), this::createAndDeferInit); - } - - public void delete() { - instancers.clear(); - initializationQueue.clear(); + public Instancer getInstancer(Environment environment, InstanceType type, Model model, VisualType visualType) { + return (Instancer) instancers.computeIfAbsent(new InstancerKey<>(environment, type, model, visualType), this::createAndDeferInit); } public void flush(LightStorage lightStorage) { @@ -59,9 +54,9 @@ public abstract class DrawManager> { .forEach(AbstractInstancer::clear); } - public abstract void renderCrumbling(List crumblingBlocks); + public abstract void render(VisualType visualType); - public abstract void renderStage(RenderStage stage); + public abstract void renderCrumbling(List crumblingBlocks); protected abstract N create(InstancerKey type); @@ -80,10 +75,6 @@ public abstract class DrawManager> { return out; } - protected record UninitializedInstancer(InstancerKey key, N instancer) { - - } - private static boolean checkAndWarnEmptyModel(Model model) { if (!model.meshes().isEmpty()) { return true; @@ -133,4 +124,12 @@ public abstract class DrawManager> { } return byType; } + + public void delete() { + instancers.clear(); + initializationQueue.clear(); + } + + protected record UninitializedInstancer(InstancerKey key, N instancer) { + } } diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/EngineImpl.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/EngineImpl.java index 46e66c007..f3a644883 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/EngineImpl.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/EngineImpl.java @@ -2,37 +2,34 @@ package dev.engine_room.flywheel.backend.engine; import java.util.List; +import dev.engine_room.flywheel.api.RenderContext; import dev.engine_room.flywheel.api.backend.Engine; -import dev.engine_room.flywheel.api.event.RenderContext; -import dev.engine_room.flywheel.api.event.RenderStage; import dev.engine_room.flywheel.api.instance.Instance; import dev.engine_room.flywheel.api.instance.InstanceType; import dev.engine_room.flywheel.api.instance.Instancer; import dev.engine_room.flywheel.api.instance.InstancerProvider; import dev.engine_room.flywheel.api.model.Model; import dev.engine_room.flywheel.api.task.Plan; -import dev.engine_room.flywheel.api.task.TaskExecutor; import dev.engine_room.flywheel.api.visualization.VisualEmbedding; +import dev.engine_room.flywheel.api.visualization.VisualType; import dev.engine_room.flywheel.api.visualization.VisualizationContext; import dev.engine_room.flywheel.backend.engine.embed.EmbeddedEnvironment; import dev.engine_room.flywheel.backend.engine.embed.Environment; import dev.engine_room.flywheel.backend.engine.embed.EnvironmentStorage; import dev.engine_room.flywheel.backend.engine.uniform.Uniforms; import dev.engine_room.flywheel.backend.gl.GlStateTracker; -import dev.engine_room.flywheel.lib.task.Flag; -import dev.engine_room.flywheel.lib.task.NamedFlag; -import dev.engine_room.flywheel.lib.task.SyncedPlan; import it.unimi.dsi.fastutil.longs.LongSet; import net.minecraft.client.Camera; import net.minecraft.core.BlockPos; +import net.minecraft.core.SectionPos; import net.minecraft.core.Vec3i; import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.LightLayer; import net.minecraft.world.phys.Vec3; public class EngineImpl implements Engine { private final DrawManager> drawManager; private final int sqrMaxOriginDistance; - private final Flag flushFlag = new NamedFlag("flushed"); private final EnvironmentStorage environmentStorage; private final LightStorage lightStorage; @@ -46,32 +43,18 @@ public class EngineImpl implements Engine { } @Override - public VisualizationContext createVisualizationContext(RenderStage stage) { - return new VisualizationContextImpl(stage); + public VisualizationContext createVisualizationContext(VisualType visualType) { + return new VisualizationContextImpl(visualType); } @Override public Plan createFramePlan() { - return lightStorage.createFramePlan() - .then(SyncedPlan.of(this::flush)); + return lightStorage.createFramePlan(); } @Override - public void renderStage(TaskExecutor executor, RenderContext context, RenderStage stage) { - executor.syncUntil(flushFlag::isRaised); - if (stage.isLast()) { - flushFlag.lower(); - } - - drawManager.renderStage(stage); - } - - @Override - public void renderCrumbling(TaskExecutor executor, RenderContext context, List crumblingBlocks) { - // Need to wait for flush before we can inspect instancer state. - executor.syncUntil(flushFlag::isRaised); - - drawManager.renderCrumbling(crumblingBlocks); + public Vec3i renderOrigin() { + return renderOrigin; } @Override @@ -92,13 +75,32 @@ public class EngineImpl implements Engine { } @Override - public Vec3i renderOrigin() { - return renderOrigin; + public void lightSections(LongSet sections) { + lightStorage.sections(sections); } @Override - public void lightSections(LongSet sections) { - lightStorage.sections(sections); + public void onLightUpdate(SectionPos sectionPos, LightLayer layer) { + lightStorage.onLightUpdate(sectionPos.asLong()); + } + + @Override + public void setupRender(RenderContext context) { + try (var state = GlStateTracker.getRestoreState()) { + Uniforms.update(context); + environmentStorage.flush(); + drawManager.flush(lightStorage); + } + } + + @Override + public void render(RenderContext context, VisualType visualType) { + drawManager.render(visualType); + } + + @Override + public void renderCrumbling(RenderContext context, List crumblingBlocks) { + drawManager.renderCrumbling(crumblingBlocks); } @Override @@ -107,18 +109,8 @@ public class EngineImpl implements Engine { lightStorage.delete(); } - public Instancer instancer(Environment environment, InstanceType type, Model model, RenderStage stage) { - return drawManager.getInstancer(environment, type, model, stage); - } - - private void flush(RenderContext ctx) { - try (var state = GlStateTracker.getRestoreState()) { - Uniforms.update(ctx); - environmentStorage.flush(); - drawManager.flush(lightStorage); - } - - flushFlag.raise(); + public Instancer instancer(Environment environment, InstanceType type, Model model, VisualType visualType) { + return drawManager.getInstancer(environment, type, model, visualType); } public EnvironmentStorage environmentStorage() { @@ -131,11 +123,11 @@ public class EngineImpl implements Engine { private class VisualizationContextImpl implements VisualizationContext { private final InstancerProviderImpl instancerProvider; - private final RenderStage stage; + private final VisualType visualType; - public VisualizationContextImpl(RenderStage stage) { - instancerProvider = new InstancerProviderImpl(EngineImpl.this, stage); - this.stage = stage; + public VisualizationContextImpl(VisualType visualType) { + instancerProvider = new InstancerProviderImpl(EngineImpl.this, visualType); + this.visualType = visualType; } @Override @@ -150,7 +142,7 @@ public class EngineImpl implements Engine { @Override public VisualEmbedding createEmbedding() { - var out = new EmbeddedEnvironment(EngineImpl.this, stage); + var out = new EmbeddedEnvironment(EngineImpl.this, visualType); environmentStorage.track(out); return out; } diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/InstancerKey.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/InstancerKey.java index 7dc10f079..ecdbc29e2 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/InstancerKey.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/InstancerKey.java @@ -1,11 +1,11 @@ package dev.engine_room.flywheel.backend.engine; -import dev.engine_room.flywheel.api.event.RenderStage; import dev.engine_room.flywheel.api.instance.Instance; import dev.engine_room.flywheel.api.instance.InstanceType; import dev.engine_room.flywheel.api.model.Model; +import dev.engine_room.flywheel.api.visualization.VisualType; import dev.engine_room.flywheel.backend.engine.embed.Environment; public record InstancerKey(Environment environment, InstanceType type, Model model, - RenderStage stage) { + VisualType visualType) { } diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/InstancerProviderImpl.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/InstancerProviderImpl.java index 5913df280..3a297b76a 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/InstancerProviderImpl.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/InstancerProviderImpl.java @@ -1,16 +1,16 @@ package dev.engine_room.flywheel.backend.engine; -import dev.engine_room.flywheel.api.event.RenderStage; import dev.engine_room.flywheel.api.instance.Instance; import dev.engine_room.flywheel.api.instance.InstanceType; import dev.engine_room.flywheel.api.instance.Instancer; import dev.engine_room.flywheel.api.instance.InstancerProvider; import dev.engine_room.flywheel.api.model.Model; +import dev.engine_room.flywheel.api.visualization.VisualType; import dev.engine_room.flywheel.backend.engine.embed.GlobalEnvironment; -public record InstancerProviderImpl(EngineImpl engine, RenderStage renderStage) implements InstancerProvider { +public record InstancerProviderImpl(EngineImpl engine, VisualType visualType) implements InstancerProvider { @Override public Instancer instancer(InstanceType type, Model model) { - return engine.instancer(GlobalEnvironment.INSTANCE, type, model, renderStage); + return engine.instancer(GlobalEnvironment.INSTANCE, type, model, visualType); } } diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/LightStorage.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/LightStorage.java index 909dbdb95..ba8d2ce5b 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/LightStorage.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/LightStorage.java @@ -5,16 +5,14 @@ import java.util.BitSet; import org.jetbrains.annotations.Nullable; import org.lwjgl.system.MemoryUtil; -import dev.engine_room.flywheel.api.event.RenderContext; import dev.engine_room.flywheel.api.task.Plan; -import dev.engine_room.flywheel.backend.LightUpdateHolder; import dev.engine_room.flywheel.backend.engine.indirect.StagingBuffer; import dev.engine_room.flywheel.backend.gl.buffer.GlBuffer; import dev.engine_room.flywheel.lib.task.SimplePlan; import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.longs.Long2IntMap; import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; -import it.unimi.dsi.fastutil.longs.LongArraySet; +import it.unimi.dsi.fastutil.longs.LongOpenHashSet; import it.unimi.dsi.fastutil.longs.LongSet; import net.minecraft.core.BlockPos; import net.minecraft.core.SectionPos; @@ -53,6 +51,7 @@ public class LightStorage { private final BitSet changed = new BitSet(); private boolean needsLutRebuild = false; + private final LongSet updatedSections = new LongOpenHashSet(); @Nullable private LongSet requestedSections; @@ -72,11 +71,12 @@ public class LightStorage { requestedSections = sections; } - public Plan createFramePlan() { - return SimplePlan.of(() -> { - var updatedSections = LightUpdateHolder.get(level) - .getAndClearUpdatedSections(); + public void onLightUpdate(long section) { + updatedSections.add(section); + } + public Plan createFramePlan() { + return SimplePlan.of(() -> { if (updatedSections.isEmpty() && requestedSections == null) { return; } @@ -87,15 +87,15 @@ public class LightStorage { LongSet sectionsToCollect; if (requestedSections == null) { // If none were requested, then we need to collect all sections that received updates. - sectionsToCollect = new LongArraySet(); + sectionsToCollect = new LongOpenHashSet(); } else { // If we did receive a new set of requested sections, we only // need to collect the sections that weren't yet tracked. - sectionsToCollect = requestedSections; + sectionsToCollect = new LongOpenHashSet(requestedSections); sectionsToCollect.removeAll(section2ArenaIndex.keySet()); } - // updatedSections contains all sections than received light updates, + // updatedSections contains all sections that received light updates, // but we only care about its intersection with our tracked sections. for (long updatedSection : updatedSections) { // Since sections contain the border light of their neighbors, we need to collect the neighbors as well. @@ -115,6 +115,7 @@ public class LightStorage { // TODO: Should this be done in parallel? sectionsToCollect.forEach(this::collectSection); + updatedSections.clear(); requestedSections = null; }); } @@ -130,7 +131,7 @@ public class LightStorage { var entry = it.next(); var section = entry.getLongKey(); - if (!this.requestedSections.contains(section)) { + if (!requestedSections.contains(section)) { arena.free(entry.getIntValue()); needsLutRebuild = true; it.remove(); diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/MaterialEncoder.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/MaterialEncoder.java index faef1cc6a..feef64c8d 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/MaterialEncoder.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/MaterialEncoder.java @@ -4,7 +4,7 @@ import dev.engine_room.flywheel.api.material.DepthTest; import dev.engine_room.flywheel.api.material.Material; import dev.engine_room.flywheel.api.material.Transparency; import dev.engine_room.flywheel.api.material.WriteMask; -import dev.engine_room.flywheel.backend.ShaderIndices; +import dev.engine_room.flywheel.backend.MaterialShaderIndices; import net.minecraft.util.Mth; // Materials are unpacked in "flywheel:flywheel/internal/packed_material.glsl" @@ -53,13 +53,8 @@ public final class MaterialEncoder { } public static int packFogAndCutout(Material material) { - var fog = ShaderIndices.fog() - .index(material.fog() - .source()); - var cutout = ShaderIndices.cutout() - .index(material.cutout() - .source()); - + var fog = MaterialShaderIndices.fogIndex(material.fog()); + var cutout = MaterialShaderIndices.cutoutIndex(material.cutout()); return fog & 0xFFFF | (cutout & 0xFFFF) << 16; } diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/MeshPool.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/MeshPool.java index cbc195a3d..5a41c1068 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/MeshPool.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/MeshPool.java @@ -9,13 +9,13 @@ import org.jetbrains.annotations.Nullable; import org.lwjgl.opengl.GL32; import dev.engine_room.flywheel.api.model.Mesh; -import dev.engine_room.flywheel.api.vertex.VertexView; import dev.engine_room.flywheel.backend.InternalVertex; import dev.engine_room.flywheel.backend.gl.GlPrimitive; import dev.engine_room.flywheel.backend.gl.array.GlVertexArray; import dev.engine_room.flywheel.backend.gl.buffer.GlBuffer; import dev.engine_room.flywheel.backend.util.ReferenceCounted; import dev.engine_room.flywheel.lib.memory.MemoryBlock; +import dev.engine_room.flywheel.lib.vertex.VertexView; public class MeshPool { private final VertexView vertexView; diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/embed/EmbeddedEnvironment.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/embed/EmbeddedEnvironment.java index fef623172..42deacf6a 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/embed/EmbeddedEnvironment.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/embed/EmbeddedEnvironment.java @@ -6,13 +6,13 @@ import org.joml.Matrix3fc; import org.joml.Matrix4f; import org.joml.Matrix4fc; -import dev.engine_room.flywheel.api.event.RenderStage; import dev.engine_room.flywheel.api.instance.Instance; import dev.engine_room.flywheel.api.instance.InstanceType; import dev.engine_room.flywheel.api.instance.Instancer; import dev.engine_room.flywheel.api.instance.InstancerProvider; import dev.engine_room.flywheel.api.model.Model; import dev.engine_room.flywheel.api.visualization.VisualEmbedding; +import dev.engine_room.flywheel.api.visualization.VisualType; import dev.engine_room.flywheel.backend.compile.ContextShader; import dev.engine_room.flywheel.backend.engine.EngineImpl; import dev.engine_room.flywheel.backend.gl.shader.GlProgram; @@ -20,7 +20,7 @@ import net.minecraft.core.Vec3i; public class EmbeddedEnvironment implements VisualEmbedding, Environment { private final EngineImpl engine; - private final RenderStage renderStage; + private final VisualType visualType; @Nullable private final EmbeddedEnvironment parent; private final InstancerProvider instancerProvider; @@ -32,22 +32,22 @@ public class EmbeddedEnvironment implements VisualEmbedding, Environment { private boolean deleted = false; - public EmbeddedEnvironment(EngineImpl engine, RenderStage renderStage, @Nullable EmbeddedEnvironment parent) { + public EmbeddedEnvironment(EngineImpl engine, VisualType visualType, @Nullable EmbeddedEnvironment parent) { this.engine = engine; - this.renderStage = renderStage; + this.visualType = visualType; this.parent = parent; instancerProvider = new InstancerProvider() { @Override public Instancer instancer(InstanceType type, Model model) { // Kinda cursed usage of anonymous classes here, but it does the job. - return engine.instancer(EmbeddedEnvironment.this, type, model, renderStage); + return engine.instancer(EmbeddedEnvironment.this, type, model, visualType); } }; } - public EmbeddedEnvironment(EngineImpl engine, RenderStage renderStage) { - this(engine, renderStage, null); + public EmbeddedEnvironment(EngineImpl engine, VisualType visualType) { + this(engine, visualType, null); } @Override @@ -68,7 +68,7 @@ public class EmbeddedEnvironment implements VisualEmbedding, Environment { @Override public VisualEmbedding createEmbedding() { - var out = new EmbeddedEnvironment(engine, renderStage, this); + var out = new EmbeddedEnvironment(engine, visualType, this); engine.environmentStorage() .track(out); return out; diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/IndirectCullingGroup.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/IndirectCullingGroup.java index 2bd19e776..5cc8702c9 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/IndirectCullingGroup.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/IndirectCullingGroup.java @@ -14,11 +14,11 @@ import java.util.EnumMap; import java.util.List; import java.util.Map; -import dev.engine_room.flywheel.api.event.RenderStage; import dev.engine_room.flywheel.api.instance.Instance; import dev.engine_room.flywheel.api.instance.InstanceType; import dev.engine_room.flywheel.api.material.Material; import dev.engine_room.flywheel.api.model.Model; +import dev.engine_room.flywheel.api.visualization.VisualType; import dev.engine_room.flywheel.backend.compile.ContextShader; import dev.engine_room.flywheel.backend.compile.IndirectPrograms; import dev.engine_room.flywheel.backend.engine.MaterialRenderState; @@ -30,7 +30,7 @@ import dev.engine_room.flywheel.backend.gl.shader.GlProgram; import dev.engine_room.flywheel.lib.math.MoreMath; public class IndirectCullingGroup { - private static final Comparator DRAW_COMPARATOR = Comparator.comparing(IndirectDraw::stage) + private static final Comparator DRAW_COMPARATOR = Comparator.comparing(IndirectDraw::visualType) .thenComparing(IndirectDraw::indexOfMeshInModel) .thenComparing(IndirectDraw::material, MaterialRenderState.COMPARATOR); @@ -42,7 +42,7 @@ public class IndirectCullingGroup { private final IndirectBuffers buffers; private final List> instancers = new ArrayList<>(); private final List indirectDraws = new ArrayList<>(); - private final Map> multiDraws = new EnumMap<>(RenderStage.class); + private final Map> multiDraws = new EnumMap<>(VisualType.class); private final IndirectPrograms programs; private final GlProgram cullProgram; @@ -145,36 +145,36 @@ public class IndirectCullingGroup { return indirectDraws.isEmpty() || instanceCountThisFrame == 0; } - private boolean nothingToDo(RenderStage stage) { - return nothingToDo() || !multiDraws.containsKey(stage); + private boolean nothingToDo(VisualType visualType) { + return nothingToDo() || !multiDraws.containsKey(visualType); } private void sortDraws() { multiDraws.clear(); - // sort by stage, then material + // sort by visual type, then material indirectDraws.sort(DRAW_COMPARATOR); for (int start = 0, i = 0; i < indirectDraws.size(); i++) { var draw1 = indirectDraws.get(i); var material1 = draw1.material(); - var stage1 = draw1.stage(); + var visualType1 = draw1.visualType(); - // if the next draw call has a different RenderStage or Material, start a new MultiDraw - if (i == indirectDraws.size() - 1 || stage1 != indirectDraws.get(i + 1) - .stage() || !material1.equals(indirectDraws.get(i + 1) + // if the next draw call has a different VisualType or Material, start a new MultiDraw + if (i == indirectDraws.size() - 1 || visualType1 != indirectDraws.get(i + 1) + .visualType() || !material1.equals(indirectDraws.get(i + 1) .material())) { - multiDraws.computeIfAbsent(stage1, s -> new ArrayList<>()) + multiDraws.computeIfAbsent(visualType1, s -> new ArrayList<>()) .add(new MultiDraw(material1, start, i + 1)); start = i + 1; } } } - public boolean hasStage(RenderStage stage) { - return multiDraws.containsKey(stage); + public boolean hasVisualType(VisualType visualType) { + return multiDraws.containsKey(visualType); } - public void add(IndirectInstancer instancer, Model model, RenderStage stage, MeshPool meshPool) { + public void add(IndirectInstancer instancer, Model model, VisualType visualType, MeshPool meshPool) { instancer.modelIndex = instancers.size(); instancers.add(instancer); @@ -183,7 +183,7 @@ public class IndirectCullingGroup { var entry = meshes.get(i); MeshPool.PooledMesh mesh = meshPool.alloc(entry.mesh()); - var draw = new IndirectDraw(instancer, entry.material(), mesh, stage, i); + var draw = new IndirectDraw(instancer, entry.material(), mesh, visualType, i); indirectDraws.add(draw); instancer.addDraw(draw); } @@ -191,8 +191,8 @@ public class IndirectCullingGroup { needsDrawSort = true; } - public void submit(RenderStage stage) { - if (nothingToDo(stage)) { + public void submit(VisualType visualType) { + if (nothingToDo(visualType)) { return; } @@ -205,7 +205,7 @@ public class IndirectCullingGroup { var flwBaseDraw = drawProgram.getUniformLocation("_flw_baseDraw"); - for (var multiDraw : multiDraws.get(stage)) { + for (var multiDraw : multiDraws.get(visualType)) { glUniform1ui(flwBaseDraw, multiDraw.start); MaterialRenderState.setup(multiDraw.material); diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/IndirectDraw.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/IndirectDraw.java index df0069206..2ad217f1a 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/IndirectDraw.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/IndirectDraw.java @@ -2,9 +2,9 @@ package dev.engine_room.flywheel.backend.engine.indirect; import org.lwjgl.system.MemoryUtil; -import dev.engine_room.flywheel.api.event.RenderStage; import dev.engine_room.flywheel.api.material.Material; -import dev.engine_room.flywheel.backend.ShaderIndices; +import dev.engine_room.flywheel.api.visualization.VisualType; +import dev.engine_room.flywheel.backend.MaterialShaderIndices; import dev.engine_room.flywheel.backend.engine.MaterialEncoder; import dev.engine_room.flywheel.backend.engine.MeshPool; @@ -12,7 +12,7 @@ public class IndirectDraw { private final IndirectInstancer instancer; private final Material material; private final MeshPool.PooledMesh mesh; - private final RenderStage stage; + private final VisualType visualType; private final int indexOfMeshInModel; private final int materialVertexIndex; @@ -21,17 +21,17 @@ public class IndirectDraw { private final int packedMaterialProperties; private boolean deleted; - public IndirectDraw(IndirectInstancer instancer, Material material, MeshPool.PooledMesh mesh, RenderStage stage, int indexOfMeshInModel) { + public IndirectDraw(IndirectInstancer instancer, Material material, MeshPool.PooledMesh mesh, VisualType visualType, int indexOfMeshInModel) { this.instancer = instancer; this.material = material; this.mesh = mesh; - this.stage = stage; + this.visualType = visualType; this.indexOfMeshInModel = indexOfMeshInModel; mesh.acquire(); - this.materialVertexIndex = ShaderIndices.getVertexShaderIndex(material.shaders()); - this.materialFragmentIndex = ShaderIndices.getFragmentShaderIndex(material.shaders()); + this.materialVertexIndex = MaterialShaderIndices.vertexIndex(material.shaders()); + this.materialFragmentIndex = MaterialShaderIndices.fragmentIndex(material.shaders()); this.packedFogAndCutout = MaterialEncoder.packFogAndCutout(material); this.packedMaterialProperties = MaterialEncoder.packProperties(material); } @@ -48,8 +48,8 @@ public class IndirectDraw { return mesh; } - public RenderStage stage() { - return stage; + public VisualType visualType() { + return visualType; } public int indexOfMeshInModel() { @@ -80,8 +80,8 @@ public class IndirectDraw { MemoryUtil.memPutInt(ptr + 20, instancer.modelIndex); // modelIndex - MemoryUtil.memPutInt(ptr + 24, ShaderIndices.getVertexShaderIndex(materialOverride.shaders())); // materialVertexIndex - MemoryUtil.memPutInt(ptr + 28, ShaderIndices.getFragmentShaderIndex(materialOverride.shaders())); // materialFragmentIndex + MemoryUtil.memPutInt(ptr + 24, MaterialShaderIndices.vertexIndex(materialOverride.shaders())); // materialVertexIndex + MemoryUtil.memPutInt(ptr + 28, MaterialShaderIndices.fragmentIndex(materialOverride.shaders())); // materialFragmentIndex MemoryUtil.memPutInt(ptr + 32, MaterialEncoder.packFogAndCutout(materialOverride)); // packedFogAndCutout MemoryUtil.memPutInt(ptr + 36, MaterialEncoder.packProperties(materialOverride)); // packedMaterialProperties } diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/IndirectDrawManager.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/IndirectDrawManager.java index d9ef2254a..204da6bb2 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/IndirectDrawManager.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/IndirectDrawManager.java @@ -11,8 +11,8 @@ import java.util.List; import java.util.Map; import dev.engine_room.flywheel.api.backend.Engine; -import dev.engine_room.flywheel.api.event.RenderStage; import dev.engine_room.flywheel.api.instance.Instance; +import dev.engine_room.flywheel.api.visualization.VisualType; import dev.engine_room.flywheel.backend.Samplers; import dev.engine_room.flywheel.backend.compile.ContextShader; import dev.engine_room.flywheel.backend.compile.IndirectPrograms; @@ -63,24 +63,24 @@ public class IndirectDrawManager extends DrawManager> { protected void initialize(InstancerKey key, IndirectInstancer instancer) { var groupKey = new GroupKey<>(key.type(), key.environment()); var group = (IndirectCullingGroup) cullingGroups.computeIfAbsent(groupKey, t -> new IndirectCullingGroup<>(t.instanceType(), t.environment(), programs)); - group.add((IndirectInstancer) instancer, key.model(), key.stage(), meshPool); + group.add((IndirectInstancer) instancer, key.model(), key.visualType(), meshPool); } - public boolean hasStage(RenderStage stage) { + public boolean hasVisualType(VisualType visualType) { for (var group : cullingGroups.values()) { - if (group.hasStage(stage)) { + if (group.hasVisualType(visualType)) { return true; } } return false; } - public void renderStage(RenderStage stage) { - if (!hasStage(stage)) { + public void render(VisualType visualType) { + if (!hasVisualType(visualType)) { return; } - try (var restoreState = GlStateTracker.getRestoreState()) { + try (var state = GlStateTracker.getRestoreState()) { TextureBinder.bindLightAndOverlay(); vertexArray.bindForDraw(); @@ -88,7 +88,7 @@ public class IndirectDrawManager extends DrawManager> { Uniforms.bindAll(); for (var group : cullingGroups.values()) { - group.submit(stage); + group.submit(visualType); } MaterialRenderState.reset(); diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/ResizableStorageBuffer.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/ResizableStorageBuffer.java index 2a4320704..05aa0d722 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/ResizableStorageBuffer.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/ResizableStorageBuffer.java @@ -25,7 +25,7 @@ public class ResizableStorageBuffer extends GlObject { } public void ensureCapacity(long capacity) { - FlwMemoryTracker._freeGPUMemory(this.capacity); + FlwMemoryTracker._freeGpuMemory(this.capacity); if (this.capacity > 0) { int oldHandle = handle(); @@ -42,7 +42,7 @@ public class ResizableStorageBuffer extends GlObject { glNamedBufferStorage(handle(), capacity, 0); } this.capacity = capacity; - FlwMemoryTracker._allocGPUMemory(this.capacity); + FlwMemoryTracker._allocGpuMemory(this.capacity); } @Override @@ -53,6 +53,6 @@ public class ResizableStorageBuffer extends GlObject { @Override public void delete() { super.delete(); - FlwMemoryTracker._freeGPUMemory(capacity); + FlwMemoryTracker._freeGpuMemory(capacity); } } diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/StagingBuffer.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/StagingBuffer.java index dc60c5cda..c976dcfce 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/StagingBuffer.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/indirect/StagingBuffer.java @@ -77,7 +77,7 @@ public class StagingBuffer { totalAvailable = capacity; - FlwMemoryTracker._allocCPUMemory(capacity); + FlwMemoryTracker._allocCpuMemory(capacity); scatterProgram = programs.getScatterProgram(); } @@ -220,7 +220,7 @@ public class StagingBuffer { transfers.delete(); scatterList.delete(); - FlwMemoryTracker._freeCPUMemory(capacity); + FlwMemoryTracker._freeCpuMemory(capacity); } private MemoryBlock getScratch(long size) { diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/instancing/InstancedDrawManager.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/instancing/InstancedDrawManager.java index ae231de0b..549463c37 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/instancing/InstancedDrawManager.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/instancing/InstancedDrawManager.java @@ -7,11 +7,11 @@ import java.util.Map; import org.lwjgl.opengl.GL32; import dev.engine_room.flywheel.api.backend.Engine; -import dev.engine_room.flywheel.api.event.RenderStage; import dev.engine_room.flywheel.api.instance.Instance; import dev.engine_room.flywheel.api.material.Material; +import dev.engine_room.flywheel.api.visualization.VisualType; +import dev.engine_room.flywheel.backend.MaterialShaderIndices; import dev.engine_room.flywheel.backend.Samplers; -import dev.engine_room.flywheel.backend.ShaderIndices; import dev.engine_room.flywheel.backend.compile.ContextShader; import dev.engine_room.flywheel.backend.compile.InstancingPrograms; import dev.engine_room.flywheel.backend.engine.CommonCrumbling; @@ -33,9 +33,9 @@ import net.minecraft.client.resources.model.ModelBakery; public class InstancedDrawManager extends DrawManager> { /** - * The set of draw calls to make in each {@link RenderStage}. + * The set of draw calls to make for each {@link VisualType}. */ - private final Map stages = new EnumMap<>(RenderStage.class); + private final Map stages = new EnumMap<>(VisualType.class); private final InstancingPrograms programs; /** * A map of vertex types to their mesh pools. @@ -74,9 +74,9 @@ public class InstancedDrawManager extends DrawManager> { } }); - for (InstancedRenderStage instancedRenderStage : stages.values()) { + for (InstancedRenderStage stage : stages.values()) { // Remove the draw calls for any instancers we deleted. - instancedRenderStage.flush(); + stage.flush(); } meshPool.flush(); @@ -85,10 +85,10 @@ public class InstancedDrawManager extends DrawManager> { } @Override - public void renderStage(RenderStage stage) { - var drawSet = stages.get(stage); + public void render(VisualType visualType) { + var stage = stages.get(visualType); - if (drawSet == null || drawSet.isEmpty()) { + if (stage == null || stage.isEmpty()) { return; } @@ -98,7 +98,7 @@ public class InstancedDrawManager extends DrawManager> { TextureBinder.bindLightAndOverlay(); light.bind(); - drawSet.draw(instanceTexture, programs); + stage.draw(instanceTexture, programs); MaterialRenderState.reset(); TextureBinder.resetLightAndOverlay(); @@ -133,7 +133,7 @@ public class InstancedDrawManager extends DrawManager> { protected void initialize(InstancerKey key, InstancedInstancer instancer) { instancer.init(); - InstancedRenderStage instancedRenderStage = stages.computeIfAbsent(key.stage(), $ -> new InstancedRenderStage()); + InstancedRenderStage stage = stages.computeIfAbsent(key.visualType(), $ -> new InstancedRenderStage()); var meshes = key.model() .meshes(); @@ -144,7 +144,7 @@ public class InstancedDrawManager extends DrawManager> { GroupKey groupKey = new GroupKey<>(key.type(), key.environment()); InstancedDraw instancedDraw = new InstancedDraw(instancer, mesh, groupKey, entry.material(), i); - instancedRenderStage.put(groupKey, instancedDraw); + stage.put(groupKey, instancedDraw); instancer.addDrawCall(instancedDraw); } } @@ -204,8 +204,8 @@ public class InstancedDrawManager extends DrawManager> { public static void uploadMaterialUniform(GlProgram program, Material material) { int uniformLocation = program.getUniformLocation("_flw_packedMaterial"); - int vertexIndex = ShaderIndices.getVertexShaderIndex(material.shaders()); - int fragmentIndex = ShaderIndices.getFragmentShaderIndex(material.shaders()); + int vertexIndex = MaterialShaderIndices.vertexIndex(material.shaders()); + int fragmentIndex = MaterialShaderIndices.fragmentIndex(material.shaders()); int packedFogAndCutout = MaterialEncoder.packFogAndCutout(material); int packedMaterialProperties = MaterialEncoder.packProperties(material); GL32.glUniform4ui(uniformLocation, vertexIndex, fragmentIndex, packedFogAndCutout, packedMaterialProperties); diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/uniform/FrameUniforms.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/uniform/FrameUniforms.java index 3ae15cb5b..e85b71356 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/uniform/FrameUniforms.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/uniform/FrameUniforms.java @@ -1,13 +1,14 @@ package dev.engine_room.flywheel.backend.engine.uniform; +import org.joml.Math; import org.joml.Matrix4f; import org.joml.Vector2f; import org.joml.Vector3f; +import org.lwjgl.system.MemoryUtil; -import dev.engine_room.flywheel.api.event.RenderContext; +import dev.engine_room.flywheel.api.RenderContext; import dev.engine_room.flywheel.api.visualization.VisualizationManager; import dev.engine_room.flywheel.backend.mixin.LevelRendererAccessor; -import dev.engine_room.flywheel.lib.math.MatrixMath; import net.minecraft.client.Camera; import net.minecraft.client.Minecraft; import net.minecraft.core.BlockPos; @@ -63,7 +64,7 @@ public final class FrameUniforms extends UniformWriter { setPrev(); Vec3i renderOrigin = VisualizationManager.getOrThrow(context.level()) - .getRenderOrigin(); + .renderOrigin(); var camera = context.camera(); Vec3 cameraPos = camera.getPosition(); var camX = (float) (cameraPos.x - renderOrigin.getX()); @@ -85,7 +86,7 @@ public final class FrameUniforms extends UniformWriter { } if (firstWrite || !frustumPaused || frustumCapture) { - MatrixMath.writePackedFrustumPlanes(ptr, VIEW_PROJECTION); + writePackedFrustumPlanes(ptr, VIEW_PROJECTION); frustumCapture = false; } @@ -170,4 +171,118 @@ public final class FrameUniforms extends UniformWriter { Vec3 cameraPos = camera.getPosition(); return writeInFluidAndBlock(ptr, level, blockPos, cameraPos); } + + /** + * Writes the frustum planes of the given projection matrix to the given buffer.

+ * Uses a different format that is friendly towards an optimized instruction-parallel + * implementation of sphere-frustum intersection.

+ * The format is as follows:

+ * {@code vec4(nxX, pxX, nyX, pyX)}
+ * {@code vec4(nxY, pxY, nyY, pyY)}
+ * {@code vec4(nxZ, pxZ, nyZ, pyZ)}
+ * {@code vec4(nxW, pxW, nyW, pyW)}
+ * {@code vec2(nzX, pzX)}
+ * {@code vec2(nzY, pzY)}
+ * {@code vec2(nzZ, pzZ)}
+ * {@code vec2(nzW, pzW)}
+ *

+ * Writes 96 bytes to the buffer. + * + * @param ptr The buffer to write the planes to. + * @param m The projection matrix to compute the frustum planes for. + */ + private static void writePackedFrustumPlanes(long ptr, Matrix4f m) { + float nxX, nxY, nxZ, nxW; + float pxX, pxY, pxZ, pxW; + float nyX, nyY, nyZ, nyW; + float pyX, pyY, pyZ, pyW; + float nzX, nzY, nzZ, nzW; + float pzX, pzY, pzZ, pzW; + + float invl; + nxX = m.m03() + m.m00(); + nxY = m.m13() + m.m10(); + nxZ = m.m23() + m.m20(); + nxW = m.m33() + m.m30(); + invl = Math.invsqrt(nxX * nxX + nxY * nxY + nxZ * nxZ); + nxX *= invl; + nxY *= invl; + nxZ *= invl; + nxW *= invl; + + pxX = m.m03() - m.m00(); + pxY = m.m13() - m.m10(); + pxZ = m.m23() - m.m20(); + pxW = m.m33() - m.m30(); + invl = Math.invsqrt(pxX * pxX + pxY * pxY + pxZ * pxZ); + pxX *= invl; + pxY *= invl; + pxZ *= invl; + pxW *= invl; + + nyX = m.m03() + m.m01(); + nyY = m.m13() + m.m11(); + nyZ = m.m23() + m.m21(); + nyW = m.m33() + m.m31(); + invl = Math.invsqrt(nyX * nyX + nyY * nyY + nyZ * nyZ); + nyX *= invl; + nyY *= invl; + nyZ *= invl; + nyW *= invl; + + pyX = m.m03() - m.m01(); + pyY = m.m13() - m.m11(); + pyZ = m.m23() - m.m21(); + pyW = m.m33() - m.m31(); + invl = Math.invsqrt(pyX * pyX + pyY * pyY + pyZ * pyZ); + pyX *= invl; + pyY *= invl; + pyZ *= invl; + pyW *= invl; + + nzX = m.m03() + m.m02(); + nzY = m.m13() + m.m12(); + nzZ = m.m23() + m.m22(); + nzW = m.m33() + m.m32(); + invl = Math.invsqrt(nzX * nzX + nzY * nzY + nzZ * nzZ); + nzX *= invl; + nzY *= invl; + nzZ *= invl; + nzW *= invl; + + pzX = m.m03() - m.m02(); + pzY = m.m13() - m.m12(); + pzZ = m.m23() - m.m22(); + pzW = m.m33() - m.m32(); + invl = Math.invsqrt(pzX * pzX + pzY * pzY + pzZ * pzZ); + pzX *= invl; + pzY *= invl; + pzZ *= invl; + pzW *= invl; + + MemoryUtil.memPutFloat(ptr, nxX); + MemoryUtil.memPutFloat(ptr + 4, pxX); + MemoryUtil.memPutFloat(ptr + 8, nyX); + MemoryUtil.memPutFloat(ptr + 12, pyX); + MemoryUtil.memPutFloat(ptr + 16, nxY); + MemoryUtil.memPutFloat(ptr + 20, pxY); + MemoryUtil.memPutFloat(ptr + 24, nyY); + MemoryUtil.memPutFloat(ptr + 28, pyY); + MemoryUtil.memPutFloat(ptr + 32, nxZ); + MemoryUtil.memPutFloat(ptr + 36, pxZ); + MemoryUtil.memPutFloat(ptr + 40, nyZ); + MemoryUtil.memPutFloat(ptr + 44, pyZ); + MemoryUtil.memPutFloat(ptr + 48, nxW); + MemoryUtil.memPutFloat(ptr + 52, pxW); + MemoryUtil.memPutFloat(ptr + 56, nyW); + MemoryUtil.memPutFloat(ptr + 60, pyW); + MemoryUtil.memPutFloat(ptr + 64, nzX); + MemoryUtil.memPutFloat(ptr + 68, pzX); + MemoryUtil.memPutFloat(ptr + 72, nzY); + MemoryUtil.memPutFloat(ptr + 76, pzY); + MemoryUtil.memPutFloat(ptr + 80, nzZ); + MemoryUtil.memPutFloat(ptr + 84, pzZ); + MemoryUtil.memPutFloat(ptr + 88, nzW); + MemoryUtil.memPutFloat(ptr + 92, pzW); + } } diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/uniform/LevelUniforms.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/uniform/LevelUniforms.java index ae1422181..978d9ed04 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/uniform/LevelUniforms.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/uniform/LevelUniforms.java @@ -1,6 +1,6 @@ package dev.engine_room.flywheel.backend.engine.uniform; -import dev.engine_room.flywheel.api.event.RenderContext; +import dev.engine_room.flywheel.api.RenderContext; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.resources.ResourceKey; import net.minecraft.world.level.Level; diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/uniform/PlayerUniforms.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/uniform/PlayerUniforms.java index 4df00cc01..8b8f31f85 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/uniform/PlayerUniforms.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/uniform/PlayerUniforms.java @@ -2,7 +2,7 @@ package dev.engine_room.flywheel.backend.engine.uniform; import org.jetbrains.annotations.Nullable; -import dev.engine_room.flywheel.api.event.RenderContext; +import dev.engine_room.flywheel.api.RenderContext; import dev.engine_room.flywheel.backend.FlwBackendXplat; import dev.engine_room.flywheel.backend.mixin.AbstractClientPlayerAccessor; import net.minecraft.client.Minecraft; diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/uniform/Uniforms.java b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/uniform/Uniforms.java index 14539cb60..a0cbf47e5 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/engine/uniform/Uniforms.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/engine/uniform/Uniforms.java @@ -1,6 +1,6 @@ package dev.engine_room.flywheel.backend.engine.uniform; -import dev.engine_room.flywheel.api.event.RenderContext; +import dev.engine_room.flywheel.api.RenderContext; import dev.engine_room.flywheel.backend.gl.shader.GlProgram; public final class Uniforms { diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/gl/buffer/GlBuffer.java b/common/src/backend/java/dev/engine_room/flywheel/backend/gl/buffer/GlBuffer.java index a42d4aa58..af92691ee 100644 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/gl/buffer/GlBuffer.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/gl/buffer/GlBuffer.java @@ -27,10 +27,10 @@ public class GlBuffer extends GlObject { } public void upload(long ptr, long size) { - FlwMemoryTracker._freeGPUMemory(this.size); + FlwMemoryTracker._freeGpuMemory(this.size); Buffer.IMPL.data(handle(), size, ptr, usage.glEnum); this.size = size; - FlwMemoryTracker._allocGPUMemory(this.size); + FlwMemoryTracker._allocGpuMemory(this.size); } public void uploadSpan(long offset, MemoryBlock memoryBlock) { @@ -47,6 +47,6 @@ public class GlBuffer extends GlObject { protected void deleteInternal(int handle) { GlStateManager._glDeleteBuffers(handle); - FlwMemoryTracker._freeGPUMemory(size); + FlwMemoryTracker._freeGpuMemory(size); } } diff --git a/common/src/backend/java/dev/engine_room/flywheel/backend/mixin/ClientChunkCacheMixin.java b/common/src/backend/java/dev/engine_room/flywheel/backend/mixin/ClientChunkCacheMixin.java deleted file mode 100644 index eb8c974ec..000000000 --- a/common/src/backend/java/dev/engine_room/flywheel/backend/mixin/ClientChunkCacheMixin.java +++ /dev/null @@ -1,29 +0,0 @@ -package dev.engine_room.flywheel.backend.mixin; - -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import dev.engine_room.flywheel.backend.LightUpdateHolder; -import net.minecraft.client.multiplayer.ClientChunkCache; -import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.core.SectionPos; -import net.minecraft.world.level.LightLayer; - -@Mixin(ClientChunkCache.class) -abstract class ClientChunkCacheMixin { - @Shadow - @Final - ClientLevel level; - - @Inject(method = "onLightUpdate", at = @At("HEAD")) - private void flywheel$backend$onLightUpdate(LightLayer layer, SectionPos pos, CallbackInfo ci) { - // This is duplicated from code in impl, but I'm not sure that it - // makes sense to be generically passed to backends. - LightUpdateHolder.get(level) - .add(pos.asLong()); - } -} diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/util/AtomicBitSet.java b/common/src/backend/java/dev/engine_room/flywheel/backend/util/AtomicBitSet.java similarity index 99% rename from common/src/lib/java/dev/engine_room/flywheel/lib/util/AtomicBitSet.java rename to common/src/backend/java/dev/engine_room/flywheel/backend/util/AtomicBitSet.java index 28532b70d..334b02732 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/util/AtomicBitSet.java +++ b/common/src/backend/java/dev/engine_room/flywheel/backend/util/AtomicBitSet.java @@ -1,4 +1,4 @@ -package dev.engine_room.flywheel.lib.util; +package dev.engine_room.flywheel.backend.util; import java.util.Arrays; import java.util.BitSet; diff --git a/common/src/backend/resources/flywheel.backend.mixins.json b/common/src/backend/resources/flywheel.backend.mixins.json index e303f7b03..2d924bef0 100644 --- a/common/src/backend/resources/flywheel.backend.mixins.json +++ b/common/src/backend/resources/flywheel.backend.mixins.json @@ -6,7 +6,6 @@ "refmap": "backend-flywheel.refmap.json", "client": [ "AbstractClientPlayerAccessor", - "ClientChunkCacheMixin", "GlStateManagerMixin", "LevelRendererAccessor", "OptionsMixin", diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/backend/SimpleBackend.java b/common/src/lib/java/dev/engine_room/flywheel/lib/backend/SimpleBackend.java index f0d25e873..cdec1433f 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/backend/SimpleBackend.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/backend/SimpleBackend.java @@ -1,5 +1,6 @@ package dev.engine_room.flywheel.lib.backend; +import java.util.Objects; import java.util.function.BooleanSupplier; import java.util.function.Function; import java.util.function.Supplier; @@ -10,7 +11,7 @@ import dev.engine_room.flywheel.api.backend.Engine; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.LevelAccessor; -public class SimpleBackend implements Backend { +public final class SimpleBackend implements Backend { private final Function engineFactory; private final Supplier fallback; private final BooleanSupplier isSupported; @@ -45,9 +46,9 @@ public class SimpleBackend implements Backend { return isSupported.getAsBoolean(); } - public static class Builder { + public static final class Builder { private Function engineFactory; - private Supplier fallback = BackendManager::getOffBackend; + private Supplier fallback = BackendManager::offBackend; private BooleanSupplier isSupported; public Builder engineFactory(Function engineFactory) { @@ -66,6 +67,10 @@ public class SimpleBackend implements Backend { } public Backend register(ResourceLocation id) { + Objects.requireNonNull(engineFactory); + Objects.requireNonNull(fallback); + Objects.requireNonNull(isSupported); + return Backend.REGISTRY.registerAndGet(id, new SimpleBackend(engineFactory, fallback, isSupported)); } } diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/instance/ColoredLitInstance.java b/common/src/lib/java/dev/engine_room/flywheel/lib/instance/ColoredLitInstance.java index ae0260965..6d2f0ed66 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/instance/ColoredLitInstance.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/instance/ColoredLitInstance.java @@ -3,12 +3,13 @@ package dev.engine_room.flywheel.lib.instance; import dev.engine_room.flywheel.api.instance.InstanceHandle; import dev.engine_room.flywheel.api.instance.InstanceType; import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.util.FastColor; public abstract class ColoredLitInstance extends AbstractInstance implements FlatLit { - public byte r = (byte) 0xFF; - public byte g = (byte) 0xFF; - public byte b = (byte) 0xFF; - public byte a = (byte) 0xFF; + public byte red = (byte) 0xFF; + public byte green = (byte) 0xFF; + public byte blue = (byte) 0xFF; + public byte alpha = (byte) 0xFF; public int overlay = OverlayTexture.NO_OVERLAY; public int light = 0; @@ -17,39 +18,34 @@ public abstract class ColoredLitInstance extends AbstractInstance implements Fla super(type, handle); } - public ColoredLitInstance color(int color) { - return color(color, false); + public ColoredLitInstance colorArgb(int argb) { + return color(FastColor.ARGB32.red(argb), FastColor.ARGB32.green(argb), FastColor.ARGB32.blue(argb), FastColor.ARGB32.alpha(argb)); } - public ColoredLitInstance color(int color, boolean alpha) { - byte r = (byte) ((color >> 16) & 0xFF); - byte g = (byte) ((color >> 8) & 0xFF); - byte b = (byte) (color & 0xFF); - - if (alpha) { - byte a = (byte) ((color >> 24) & 0xFF); - return color(r, g, b, a); - } else { - return color(r, g, b); - } + public ColoredLitInstance colorRgb(int rgb) { + return color(FastColor.ARGB32.red(rgb), FastColor.ARGB32.green(rgb), FastColor.ARGB32.blue(rgb)); } - public ColoredLitInstance color(int r, int g, int b) { - return color((byte) r, (byte) g, (byte) b); + public ColoredLitInstance color(int red, int green, int blue, int alpha) { + return color((byte) red, (byte) green, (byte) blue, (byte) alpha); } - public ColoredLitInstance color(byte r, byte g, byte b) { - this.r = r; - this.g = g; - this.b = b; + public ColoredLitInstance color(int red, int green, int blue) { + return color((byte) red, (byte) green, (byte) blue); + } + + public ColoredLitInstance color(byte red, byte green, byte blue, byte alpha) { + this.red = red; + this.green = green; + this.blue = blue; + this.alpha = alpha; return this; } - public ColoredLitInstance color(byte r, byte g, byte b, byte a) { - this.r = r; - this.g = g; - this.b = b; - this.a = a; + public ColoredLitInstance color(byte red, byte green, byte blue) { + this.red = red; + this.green = green; + this.blue = blue; return this; } diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/instance/FlatLit.java b/common/src/lib/java/dev/engine_room/flywheel/lib/instance/FlatLit.java index f9bb8a75e..7cd26dab5 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/instance/FlatLit.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/instance/FlatLit.java @@ -17,15 +17,15 @@ import net.minecraft.client.renderer.LightTexture; public interface FlatLit extends Instance { /** * Set the packed light value for this instance. - * @param packedLight Packed block and sky light per {@link LightTexture#pack(int, int)} + * @param packedLight the packed light per {@link LightTexture#pack(int, int)} * @return {@code this} for chaining */ FlatLit light(int packedLight); /** * Set the block and sky light values for this instance. - * @param blockLight Block light value - * @param skyLight Sky light value + * @param blockLight the block light value + * @param skyLight the sky light value * @return {@code this} for chaining */ default FlatLit light(int blockLight, int skyLight) { diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/instance/InstanceTypes.java b/common/src/lib/java/dev/engine_room/flywheel/lib/instance/InstanceTypes.java index 0ab63f4b6..8cb66a7f0 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/instance/InstanceTypes.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/instance/InstanceTypes.java @@ -20,10 +20,10 @@ public final class InstanceTypes { .matrix("normal", FloatRepr.FLOAT, 3) .build()) .writer((ptr, instance) -> { - MemoryUtil.memPutByte(ptr, instance.r); - MemoryUtil.memPutByte(ptr + 1, instance.g); - MemoryUtil.memPutByte(ptr + 2, instance.b); - MemoryUtil.memPutByte(ptr + 3, instance.a); + MemoryUtil.memPutByte(ptr, instance.red); + MemoryUtil.memPutByte(ptr + 1, instance.green); + MemoryUtil.memPutByte(ptr + 2, instance.blue); + MemoryUtil.memPutByte(ptr + 3, instance.alpha); ExtraMemoryOps.put2x16(ptr + 4, instance.overlay); ExtraMemoryOps.put2x16(ptr + 8, instance.light); ExtraMemoryOps.putMatrix4f(ptr + 12, instance.model); @@ -43,10 +43,10 @@ public final class InstanceTypes { .vector("rotation", FloatRepr.FLOAT, 4) .build()) .writer((ptr, instance) -> { - MemoryUtil.memPutByte(ptr, instance.r); - MemoryUtil.memPutByte(ptr + 1, instance.g); - MemoryUtil.memPutByte(ptr + 2, instance.b); - MemoryUtil.memPutByte(ptr + 3, instance.a); + MemoryUtil.memPutByte(ptr, instance.red); + MemoryUtil.memPutByte(ptr + 1, instance.green); + MemoryUtil.memPutByte(ptr + 2, instance.blue); + MemoryUtil.memPutByte(ptr + 3, instance.alpha); ExtraMemoryOps.put2x16(ptr + 4, instance.overlay); ExtraMemoryOps.put2x16(ptr + 8, instance.light); MemoryUtil.memPutFloat(ptr + 12, instance.posX); diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/instance/OrientedInstance.java b/common/src/lib/java/dev/engine_room/flywheel/lib/instance/OrientedInstance.java index a8c2402e6..321caf936 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/instance/OrientedInstance.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/instance/OrientedInstance.java @@ -1,7 +1,8 @@ package dev.engine_room.flywheel.lib.instance; import org.joml.Quaternionf; -import org.joml.Vector3f; +import org.joml.Quaternionfc; +import org.joml.Vector3fc; import dev.engine_room.flywheel.api.instance.InstanceHandle; import dev.engine_room.flywheel.api.instance.InstanceType; @@ -22,72 +23,83 @@ public class OrientedInstance extends ColoredLitInstance implements Rotate type, InstanceHandle handle) { + public ShadowInstance(InstanceType type, InstanceHandle handle) { super(type, handle); } } diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/instance/SimpleInstanceType.java b/common/src/lib/java/dev/engine_room/flywheel/lib/instance/SimpleInstanceType.java index 711d6f5d1..b20e1e31e 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/instance/SimpleInstanceType.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/instance/SimpleInstanceType.java @@ -9,7 +9,7 @@ import dev.engine_room.flywheel.api.instance.InstanceWriter; import dev.engine_room.flywheel.api.layout.Layout; import net.minecraft.resources.ResourceLocation; -public class SimpleInstanceType implements InstanceType { +public final class SimpleInstanceType implements InstanceType { private final Factory factory; private final Layout layout; private final InstanceWriter writer; @@ -58,7 +58,7 @@ public class SimpleInstanceType implements InstanceType { I create(InstanceType type, InstanceHandle handle); } - public static class Builder { + public static final class Builder { private final Factory factory; private Layout layout; private InstanceWriter writer; diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/instance/TransformedInstance.java b/common/src/lib/java/dev/engine_room/flywheel/lib/instance/TransformedInstance.java index a581b17ec..13938d201 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/instance/TransformedInstance.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/instance/TransformedInstance.java @@ -1,8 +1,10 @@ package dev.engine_room.flywheel.lib.instance; import org.joml.Matrix3f; +import org.joml.Matrix3fc; import org.joml.Matrix4f; -import org.joml.Quaternionf; +import org.joml.Matrix4fc; +import org.joml.Quaternionfc; import com.mojang.blaze3d.vertex.PoseStack; @@ -12,7 +14,6 @@ import dev.engine_room.flywheel.lib.transform.Transform; import net.minecraft.util.Mth; public class TransformedInstance extends ColoredLitInstance implements Transform { - public final Matrix4f model = new Matrix4f(); public final Matrix3f normal = new Matrix3f(); @@ -21,21 +22,34 @@ public class TransformedInstance extends ColoredLitInstance implements Transform } @Override - public TransformedInstance mulPose(Matrix4f pose) { + public TransformedInstance mulPose(Matrix4fc pose) { this.model.mul(pose); return this; } @Override - public TransformedInstance mulNormal(Matrix3f normal) { + public TransformedInstance mulNormal(Matrix3fc normal) { this.normal.mul(normal); return this; } @Override - public TransformedInstance rotateAround(Quaternionf quaternion, float x, float y, float z) { - this.model.rotateAround(quaternion, x, y, z); - this.normal.rotate(quaternion); + public TransformedInstance rotateAround(Quaternionfc quaternion, float x, float y, float z) { + model.rotateAround(quaternion, x, y, z); + normal.rotate(quaternion); + return this; + } + + @Override + public TransformedInstance translate(float x, float y, float z) { + model.translate(x, y, z); + return this; + } + + @Override + public TransformedInstance rotate(Quaternionfc quaternion) { + model.rotate(quaternion); + normal.rotate(quaternion); return this; } @@ -59,16 +73,9 @@ public class TransformedInstance extends ColoredLitInstance implements Transform return this; } - @Override - public TransformedInstance rotate(Quaternionf quaternion) { - model.rotate(quaternion); - normal.rotate(quaternion); - return this; - } - - @Override - public TransformedInstance translate(double x, double y, double z) { - model.translate((float) x, (float) y, (float) z); + public TransformedInstance setTransform(PoseStack.Pose pose) { + model.set(pose.pose()); + normal.set(pose.normal()); return this; } @@ -76,9 +83,9 @@ public class TransformedInstance extends ColoredLitInstance implements Transform return setTransform(stack.last()); } - public TransformedInstance setTransform(PoseStack.Pose pose) { - this.model.set(pose.pose()); - this.normal.set(pose.normal()); + public TransformedInstance setIdentityTransform() { + model.identity(); + normal.identity(); return this; } @@ -89,15 +96,9 @@ public class TransformedInstance extends ColoredLitInstance implements Transform * This will allow the GPU to quickly discard all geometry for this instance, effectively "turning it off". *

*/ - public TransformedInstance setEmptyTransform() { + public TransformedInstance setZeroTransform() { model.zero(); normal.zero(); return this; } - - public TransformedInstance loadIdentity() { - model.identity(); - normal.identity(); - return this; - } } diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/internal/FlwLibXplat.java b/common/src/lib/java/dev/engine_room/flywheel/lib/internal/FlwLibXplat.java index 0fe92a997..2809537ee 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/internal/FlwLibXplat.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/internal/FlwLibXplat.java @@ -1,6 +1,7 @@ package dev.engine_room.flywheel.lib.internal; import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.UnknownNullability; import dev.engine_room.flywheel.api.internal.DependencyInjection; import dev.engine_room.flywheel.lib.model.baked.BakedModelBuilder; @@ -9,13 +10,18 @@ import dev.engine_room.flywheel.lib.model.baked.MultiBlockModelBuilder; import dev.engine_room.flywheel.lib.util.ShadersModHandler; import net.minecraft.client.renderer.block.BlockRenderDispatcher; import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.client.resources.model.ModelManager; import net.minecraft.core.BlockPos; +import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.BlockAndTintGetter; import net.minecraft.world.level.block.state.BlockState; public interface FlwLibXplat { FlwLibXplat INSTANCE = DependencyInjection.load(FlwLibXplat.class, "dev.engine_room.flywheel.impl.FlwLibXplatImpl"); + @UnknownNullability + BakedModel getBakedModel(ModelManager modelManager, ResourceLocation location); + BlockRenderDispatcher createVanillaBlockRenderDispatcher(); BakedModelBuilder createBakedModelBuilder(BakedModel bakedModel); diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/material/CutoutShaders.java b/common/src/lib/java/dev/engine_room/flywheel/lib/material/CutoutShaders.java index 79b5dd444..fec3b60d9 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/material/CutoutShaders.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/material/CutoutShaders.java @@ -5,7 +5,7 @@ import org.jetbrains.annotations.ApiStatus; import dev.engine_room.flywheel.api.Flywheel; import dev.engine_room.flywheel.api.material.CutoutShader; -public class CutoutShaders { +public final class CutoutShaders { /** * Do not discard any fragments based on alpha. */ diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/material/FogShaders.java b/common/src/lib/java/dev/engine_room/flywheel/lib/material/FogShaders.java index 8c2531696..1dedfdb80 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/material/FogShaders.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/material/FogShaders.java @@ -5,7 +5,7 @@ import org.jetbrains.annotations.ApiStatus; import dev.engine_room.flywheel.api.Flywheel; import dev.engine_room.flywheel.api.material.FogShader; -public class FogShaders { +public final class FogShaders { public static final FogShader NONE = FogShader.REGISTRY.registerAndGet(new SimpleFogShader(Flywheel.rl("fog/none.glsl"))); public static final FogShader LINEAR = FogShader.REGISTRY.registerAndGet(new SimpleFogShader(Flywheel.rl("fog/linear.glsl"))); public static final FogShader LINEAR_FADE = FogShader.REGISTRY.registerAndGet(new SimpleFogShader(Flywheel.rl("fog/linear_fade.glsl"))); diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/material/Materials.java b/common/src/lib/java/dev/engine_room/flywheel/lib/material/Materials.java index 2cab44864..38bbd4ff6 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/material/Materials.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/material/Materials.java @@ -2,73 +2,50 @@ package dev.engine_room.flywheel.lib.material; import dev.engine_room.flywheel.api.material.Material; import dev.engine_room.flywheel.api.material.Transparency; -import net.minecraft.client.renderer.Sheets; -import net.minecraft.resources.ResourceLocation; public final class Materials { - private static final ResourceLocation MINECART_LOCATION = new ResourceLocation("textures/entity/minecart.png"); - - public static final Material CHUNK_SOLID_SHADED = SimpleMaterial.builder() + public static final Material SOLID_BLOCK = SimpleMaterial.builder() .build(); - public static final Material CHUNK_SOLID_UNSHADED = SimpleMaterial.builder() + public static final Material SOLID_UNSHADED_BLOCK = SimpleMaterial.builder() .diffuse(false) .build(); - public static final Material CHUNK_CUTOUT_MIPPED_SHADED = SimpleMaterial.builder() + public static final Material CUTOUT_MIPPED_BLOCK = SimpleMaterial.builder() .cutout(CutoutShaders.HALF) .build(); - public static final Material CHUNK_CUTOUT_MIPPED_UNSHADED = SimpleMaterial.builder() + public static final Material CUTOUT_MIPPED_UNSHADED_BLOCK = SimpleMaterial.builder() .cutout(CutoutShaders.HALF) .diffuse(false) .build(); - public static final Material CHUNK_CUTOUT_SHADED = SimpleMaterial.builder() + public static final Material CUTOUT_BLOCK = SimpleMaterial.builder() .cutout(CutoutShaders.ONE_TENTH) .mipmap(false) .build(); - public static final Material CHUNK_CUTOUT_UNSHADED = SimpleMaterial.builder() + public static final Material CUTOUT_UNSHADED_BLOCK = SimpleMaterial.builder() .cutout(CutoutShaders.ONE_TENTH) .mipmap(false) .diffuse(false) .build(); - public static final Material CHUNK_TRANSLUCENT_SHADED = SimpleMaterial.builder() + public static final Material TRANSLUCENT_BLOCK = SimpleMaterial.builder() .transparency(Transparency.TRANSLUCENT) .build(); - public static final Material CHUNK_TRANSLUCENT_UNSHADED = SimpleMaterial.builder() + public static final Material TRANSLUCENT_UNSHADED_BLOCK = SimpleMaterial.builder() .transparency(Transparency.TRANSLUCENT) .diffuse(false) .build(); - public static final Material CHUNK_TRIPWIRE_SHADED = SimpleMaterial.builder() + public static final Material TRIPWIRE_BLOCK = SimpleMaterial.builder() .cutout(CutoutShaders.ONE_TENTH) .transparency(Transparency.TRANSLUCENT) .build(); - public static final Material CHUNK_TRIPWIRE_UNSHADED = SimpleMaterial.builder() + public static final Material TRIPWIRE_UNSHADED_BLOCK = SimpleMaterial.builder() .cutout(CutoutShaders.ONE_TENTH) .transparency(Transparency.TRANSLUCENT) .diffuse(false) .build(); - public static final Material CHEST = SimpleMaterial.builder() - .cutout(CutoutShaders.ONE_TENTH) - .texture(Sheets.CHEST_SHEET) - .mipmap(false) - .build(); - public static final Material SHULKER = SimpleMaterial.builder() - .cutout(CutoutShaders.ONE_TENTH) - .texture(Sheets.SHULKER_SHEET) - .mipmap(false) - .backfaceCulling(false) - .build(); - public static final Material BELL = SimpleMaterial.builder() - .mipmap(false) - .build(); - public static final Material MINECART = SimpleMaterial.builder() - .texture(MINECART_LOCATION) - .mipmap(false) - .build(); - private Materials() { } } diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/material/SimpleMaterialShaders.java b/common/src/lib/java/dev/engine_room/flywheel/lib/material/SimpleMaterialShaders.java index 35422c805..f39c1f4ea 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/material/SimpleMaterialShaders.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/material/SimpleMaterialShaders.java @@ -3,5 +3,5 @@ package dev.engine_room.flywheel.lib.material; import dev.engine_room.flywheel.api.material.MaterialShaders; import net.minecraft.resources.ResourceLocation; -public record SimpleMaterialShaders(ResourceLocation vertexShader, ResourceLocation fragmentShader) implements MaterialShaders { +public record SimpleMaterialShaders(ResourceLocation vertexSource, ResourceLocation fragmentSource) implements MaterialShaders { } diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/math/DataPacker.java b/common/src/lib/java/dev/engine_room/flywheel/lib/math/DataPacker.java new file mode 100644 index 000000000..6fa5f33fe --- /dev/null +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/math/DataPacker.java @@ -0,0 +1,36 @@ +package dev.engine_room.flywheel.lib.math; + +import net.minecraft.util.Mth; + +public final class DataPacker { + private DataPacker() { + } + + /** + * Pack a float as an unsigned, normalized byte. + */ + public static byte packNormU8(float f) { + return (byte) (int) (Mth.clamp(f, 0.0f, 1.0f) * 255); + } + + /** + * Unpack an unsigned, normalized byte to a float. + */ + public static float unpackNormU8(byte b) { + return (float) (Byte.toUnsignedInt(b)) / 255f; + } + + /** + * Pack a float as a signed, normalized byte. + */ + public static byte packNormI8(float f) { + return (byte) (Mth.clamp(f, -1.0f, 1.0f) * 127); + } + + /** + * Unpack a signed, normalized byte to a float. + */ + public static float unpackNormI8(byte b) { + return (float) b / 127f; + } +} diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/math/MatrixMath.java b/common/src/lib/java/dev/engine_room/flywheel/lib/math/MatrixMath.java index 77a761b58..d0fb5fd0a 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/math/MatrixMath.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/math/MatrixMath.java @@ -2,10 +2,8 @@ package dev.engine_room.flywheel.lib.math; import static org.joml.Math.fma; -import org.joml.Math; import org.joml.Matrix3f; import org.joml.Matrix4f; -import org.lwjgl.system.MemoryUtil; public final class MatrixMath { private MatrixMath() { @@ -34,131 +32,4 @@ public final class MatrixMath { public static float transformNormalZ(Matrix3f matrix, float x, float y, float z) { return fma(matrix.m02(), x, fma(matrix.m12(), y, matrix.m22() * z)); } - - /** - * Extracts the greatest scale factor across all axes from the given matrix. - * - * @param matrix The matrix to extract the scale from. - * @return The greatest scale factor across all axes. - */ - public static float extractScale(Matrix4f matrix) { - float scaleSqrX = matrix.m00() * matrix.m00() + matrix.m01() * matrix.m01() + matrix.m02() * matrix.m02(); - float scaleSqrY = matrix.m10() * matrix.m10() + matrix.m11() * matrix.m11() + matrix.m12() * matrix.m12(); - float scaleSqrZ = matrix.m20() * matrix.m20() + matrix.m21() * matrix.m21() + matrix.m22() * matrix.m22(); - return Math.sqrt(Math.max(Math.max(scaleSqrX, scaleSqrY), scaleSqrZ)); - } - - /** - * Writes the frustum planes of the given projection matrix to the given buffer.

- * Uses a different format that is friendly towards an optimized instruction-parallel - * implementation of sphere-frustum intersection.

- * The format is as follows:

- * {@code vec4(nxX, pxX, nyX, pyX)}
- * {@code vec4(nxY, pxY, nyY, pyY)}
- * {@code vec4(nxZ, pxZ, nyZ, pyZ)}
- * {@code vec4(nxW, pxW, nyW, pyW)}
- * {@code vec2(nzX, pzX)}
- * {@code vec2(nzY, pzY)}
- * {@code vec2(nzZ, pzZ)}
- * {@code vec2(nzW, pzW)}
- *

- * Writes 96 bytes to the buffer. - * - * @param ptr The buffer to write the planes to. - * @param m The projection matrix to compute the frustum planes for. - */ - public static void writePackedFrustumPlanes(long ptr, Matrix4f m) { - float nxX, nxY, nxZ, nxW; - float pxX, pxY, pxZ, pxW; - float nyX, nyY, nyZ, nyW; - float pyX, pyY, pyZ, pyW; - float nzX, nzY, nzZ, nzW; - float pzX, pzY, pzZ, pzW; - - float invl; - nxX = m.m03() + m.m00(); - nxY = m.m13() + m.m10(); - nxZ = m.m23() + m.m20(); - nxW = m.m33() + m.m30(); - invl = Math.invsqrt(nxX * nxX + nxY * nxY + nxZ * nxZ); - nxX *= invl; - nxY *= invl; - nxZ *= invl; - nxW *= invl; - - pxX = m.m03() - m.m00(); - pxY = m.m13() - m.m10(); - pxZ = m.m23() - m.m20(); - pxW = m.m33() - m.m30(); - invl = Math.invsqrt(pxX * pxX + pxY * pxY + pxZ * pxZ); - pxX *= invl; - pxY *= invl; - pxZ *= invl; - pxW *= invl; - - nyX = m.m03() + m.m01(); - nyY = m.m13() + m.m11(); - nyZ = m.m23() + m.m21(); - nyW = m.m33() + m.m31(); - invl = Math.invsqrt(nyX * nyX + nyY * nyY + nyZ * nyZ); - nyX *= invl; - nyY *= invl; - nyZ *= invl; - nyW *= invl; - - pyX = m.m03() - m.m01(); - pyY = m.m13() - m.m11(); - pyZ = m.m23() - m.m21(); - pyW = m.m33() - m.m31(); - invl = Math.invsqrt(pyX * pyX + pyY * pyY + pyZ * pyZ); - pyX *= invl; - pyY *= invl; - pyZ *= invl; - pyW *= invl; - - nzX = m.m03() + m.m02(); - nzY = m.m13() + m.m12(); - nzZ = m.m23() + m.m22(); - nzW = m.m33() + m.m32(); - invl = Math.invsqrt(nzX * nzX + nzY * nzY + nzZ * nzZ); - nzX *= invl; - nzY *= invl; - nzZ *= invl; - nzW *= invl; - - pzX = m.m03() - m.m02(); - pzY = m.m13() - m.m12(); - pzZ = m.m23() - m.m22(); - pzW = m.m33() - m.m32(); - invl = Math.invsqrt(pzX * pzX + pzY * pzY + pzZ * pzZ); - pzX *= invl; - pzY *= invl; - pzZ *= invl; - pzW *= invl; - - MemoryUtil.memPutFloat(ptr, nxX); - MemoryUtil.memPutFloat(ptr + 4, pxX); - MemoryUtil.memPutFloat(ptr + 8, nyX); - MemoryUtil.memPutFloat(ptr + 12, pyX); - MemoryUtil.memPutFloat(ptr + 16, nxY); - MemoryUtil.memPutFloat(ptr + 20, pxY); - MemoryUtil.memPutFloat(ptr + 24, nyY); - MemoryUtil.memPutFloat(ptr + 28, pyY); - MemoryUtil.memPutFloat(ptr + 32, nxZ); - MemoryUtil.memPutFloat(ptr + 36, pxZ); - MemoryUtil.memPutFloat(ptr + 40, nyZ); - MemoryUtil.memPutFloat(ptr + 44, pyZ); - MemoryUtil.memPutFloat(ptr + 48, nxW); - MemoryUtil.memPutFloat(ptr + 52, pxW); - MemoryUtil.memPutFloat(ptr + 56, nyW); - MemoryUtil.memPutFloat(ptr + 60, pyW); - MemoryUtil.memPutFloat(ptr + 64, nzX); - MemoryUtil.memPutFloat(ptr + 68, pzX); - MemoryUtil.memPutFloat(ptr + 72, nzY); - MemoryUtil.memPutFloat(ptr + 76, pzY); - MemoryUtil.memPutFloat(ptr + 80, nzZ); - MemoryUtil.memPutFloat(ptr + 84, pzZ); - MemoryUtil.memPutFloat(ptr + 88, nzW); - MemoryUtil.memPutFloat(ptr + 92, pzW); - } } diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/math/MoreMath.java b/common/src/lib/java/dev/engine_room/flywheel/lib/math/MoreMath.java index feca659c0..944f797e8 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/math/MoreMath.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/math/MoreMath.java @@ -29,47 +29,6 @@ public final class MoreMath { return (numerator + denominator - 1) / denominator; } - public static int numDigits(int number) { - // cursed but allegedly the fastest algorithm, taken from https://www.baeldung.com/java-number-of-digits-in-int - if (number < 100000) { - if (number < 100) { - if (number < 10) { - return 1; - } else { - return 2; - } - } else { - if (number < 1000) { - return 3; - } else { - if (number < 10000) { - return 4; - } else { - return 5; - } - } - } - } else { - if (number < 10000000) { - if (number < 1000000) { - return 6; - } else { - return 7; - } - } else { - if (number < 100000000) { - return 8; - } else { - if (number < 1000000000) { - return 9; - } else { - return 10; - } - } - } - } - } - public static long ceilLong(double d) { return (long) Math.ceil(d); } diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/math/RenderMath.java b/common/src/lib/java/dev/engine_room/flywheel/lib/math/RenderMath.java deleted file mode 100644 index fdcd8285a..000000000 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/math/RenderMath.java +++ /dev/null @@ -1,34 +0,0 @@ -package dev.engine_room.flywheel.lib.math; - -public final class RenderMath { - private RenderMath() { - } - - /** - * Convert a signed byte into a signed, normalized float. - */ - public static float f(byte b) { - return b / 127f; - } - - /** - * Convert a signed, normalized float into a signed byte. - */ - public static byte nb(float f) { - return (byte) (f * 127); - } - - /** - * Convert an unsigned byte into an unsigned, normalized float. - */ - public static float uf(byte b) { - return (float) (Byte.toUnsignedInt(b)) / 255f; - } - - /** - * Convert an unsigned, normalized float into an unsigned byte. - */ - public static byte unb(float f) { - return (byte) (int) (f * 255); - } -} diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/memory/AbstractMemoryBlockImpl.java b/common/src/lib/java/dev/engine_room/flywheel/lib/memory/AbstractMemoryBlockImpl.java index 0b50bf662..0fb5385da 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/memory/AbstractMemoryBlockImpl.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/memory/AbstractMemoryBlockImpl.java @@ -18,13 +18,21 @@ non-sealed abstract class AbstractMemoryBlockImpl implements MemoryBlock { this.size = size; } + void assertAllocated() { + if (freed) { + throw new IllegalStateException("Operation called on freed MemoryBlock!"); + } + } + @Override public long ptr() { + assertAllocated(); return ptr; } @Override public long size() { + assertAllocated(); return size; } @@ -35,27 +43,32 @@ non-sealed abstract class AbstractMemoryBlockImpl implements MemoryBlock { @Override public void copyTo(MemoryBlock block) { + assertAllocated(); long bytes = Math.min(size, block.size()); copyTo(block.ptr(), bytes); } @Override public void copyTo(long ptr, long bytes) { + assertAllocated(); MemoryUtil.memCopy(this.ptr, ptr, bytes); } @Override public void copyTo(long ptr) { + assertAllocated(); copyTo(ptr, size); } @Override public void clear() { + assertAllocated(); MemoryUtil.memSet(ptr, 0, size); } @Override public ByteBuffer asBuffer() { + assertAllocated(); int intSize = (int) size; if (intSize != size) { throw new UnsupportedOperationException("Cannot create buffer with long capacity!"); @@ -64,12 +77,13 @@ non-sealed abstract class AbstractMemoryBlockImpl implements MemoryBlock { } void freeInner() { - FlwMemoryTracker._freeCPUMemory(size); + FlwMemoryTracker._freeCpuMemory(size); freed = true; } @Override public void free() { + assertAllocated(); FlwMemoryTracker.free(ptr); freeInner(); } diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/memory/DebugMemoryBlockImpl.java b/common/src/lib/java/dev/engine_room/flywheel/lib/memory/DebugMemoryBlockImpl.java index 7ff39f3f5..ca1ec7820 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/memory/DebugMemoryBlockImpl.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/memory/DebugMemoryBlockImpl.java @@ -31,8 +31,9 @@ class DebugMemoryBlockImpl extends AbstractMemoryBlockImpl { @Override public MemoryBlock realloc(long size) { + assertAllocated(); MemoryBlock block = new DebugMemoryBlockImpl(FlwMemoryTracker.realloc(ptr, size), size, cleaner, 1); - FlwMemoryTracker._allocCPUMemory(block.size()); + FlwMemoryTracker._allocCpuMemory(block.size()); freeInner(); return block; } @@ -54,13 +55,13 @@ class DebugMemoryBlockImpl extends AbstractMemoryBlockImpl { static MemoryBlock malloc(long size) { MemoryBlock block = new DebugMemoryBlockImpl(FlwMemoryTracker.malloc(size), size, CLEANER, 2); - FlwMemoryTracker._allocCPUMemory(block.size()); + FlwMemoryTracker._allocCpuMemory(block.size()); return block; } static MemoryBlock calloc(long num, long size) { MemoryBlock block = new DebugMemoryBlockImpl(FlwMemoryTracker.calloc(num, size), num * size, CLEANER, 2); - FlwMemoryTracker._allocCPUMemory(block.size()); + FlwMemoryTracker._allocCpuMemory(block.size()); return block; } @@ -94,7 +95,7 @@ class DebugMemoryBlockImpl extends AbstractMemoryBlockImpl { FlwLibLink.INSTANCE.getLogger().warn(builder.toString()); FlwMemoryTracker.free(ptr); - FlwMemoryTracker._freeCPUMemory(size); + FlwMemoryTracker._freeCpuMemory(size); } } } diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/memory/FlwMemoryTracker.java b/common/src/lib/java/dev/engine_room/flywheel/lib/memory/FlwMemoryTracker.java index 0e33b8168..4fa35d71c 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/memory/FlwMemoryTracker.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/memory/FlwMemoryTracker.java @@ -7,8 +7,6 @@ import org.lwjgl.system.MemoryUtil; import dev.engine_room.flywheel.lib.util.StringUtil; public final class FlwMemoryTracker { - public static final boolean DEBUG_MEMORY_SAFETY = System.getProperty("flw.debugMemorySafety") != null; - private static final AtomicLong CPU_MEMORY = new AtomicLong(0); private static final AtomicLong GPU_MEMORY = new AtomicLong(0); @@ -32,38 +30,38 @@ public final class FlwMemoryTracker { } public static long realloc(long ptr, long size) { - ptr = MemoryUtil.nmemRealloc(ptr, size); - if (ptr == MemoryUtil.NULL) { + long newPtr = MemoryUtil.nmemRealloc(ptr, size); + if (newPtr == MemoryUtil.NULL) { throw new OutOfMemoryError("Failed to reallocate " + size + " bytes for address " + StringUtil.formatAddress(ptr)); } - return ptr; + return newPtr; } public static void free(long ptr) { MemoryUtil.nmemFree(ptr); } - public static void _allocCPUMemory(long size) { + public static void _allocCpuMemory(long size) { CPU_MEMORY.getAndAdd(size); } - public static void _freeCPUMemory(long size) { + public static void _freeCpuMemory(long size) { CPU_MEMORY.getAndAdd(-size); } - public static void _allocGPUMemory(long size) { + public static void _allocGpuMemory(long size) { GPU_MEMORY.getAndAdd(size); } - public static void _freeGPUMemory(long size) { + public static void _freeGpuMemory(long size) { GPU_MEMORY.getAndAdd(-size); } - public static long getCPUMemory() { + public static long getCpuMemory() { return CPU_MEMORY.get(); } - public static long getGPUMemory() { + public static long getGpuMemory() { return GPU_MEMORY.get(); } } diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/memory/MemoryBlock.java b/common/src/lib/java/dev/engine_room/flywheel/lib/memory/MemoryBlock.java index 3f68a8b9e..85fa1e0bc 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/memory/MemoryBlock.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/memory/MemoryBlock.java @@ -26,7 +26,7 @@ public sealed interface MemoryBlock permits AbstractMemoryBlockImpl { void free(); static MemoryBlock malloc(long size) { - if (FlwMemoryTracker.DEBUG_MEMORY_SAFETY) { + if (MemoryBlockImpl.DEBUG_MEMORY_SAFETY) { return DebugMemoryBlockImpl.malloc(size); } else { return MemoryBlockImpl.malloc(size); @@ -38,7 +38,7 @@ public sealed interface MemoryBlock permits AbstractMemoryBlockImpl { } static MemoryBlock calloc(long num, long size) { - if (FlwMemoryTracker.DEBUG_MEMORY_SAFETY) { + if (MemoryBlockImpl.DEBUG_MEMORY_SAFETY) { return DebugMemoryBlockImpl.calloc(num, size); } else { return MemoryBlockImpl.calloc(num, size); diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/memory/MemoryBlockImpl.java b/common/src/lib/java/dev/engine_room/flywheel/lib/memory/MemoryBlockImpl.java index f716fb88f..81a72dcaf 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/memory/MemoryBlockImpl.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/memory/MemoryBlockImpl.java @@ -1,6 +1,8 @@ package dev.engine_room.flywheel.lib.memory; class MemoryBlockImpl extends AbstractMemoryBlockImpl { + static final boolean DEBUG_MEMORY_SAFETY = System.getProperty("flw.debugMemorySafety") != null; + MemoryBlockImpl(long ptr, long size) { super(ptr, size); } @@ -12,21 +14,22 @@ class MemoryBlockImpl extends AbstractMemoryBlockImpl { @Override public MemoryBlock realloc(long size) { + assertAllocated(); MemoryBlock block = new MemoryBlockImpl(FlwMemoryTracker.realloc(ptr, size), size); - FlwMemoryTracker._allocCPUMemory(block.size()); + FlwMemoryTracker._allocCpuMemory(block.size()); freeInner(); return block; } static MemoryBlock malloc(long size) { MemoryBlock block = new MemoryBlockImpl(FlwMemoryTracker.malloc(size), size); - FlwMemoryTracker._allocCPUMemory(block.size()); + FlwMemoryTracker._allocCpuMemory(block.size()); return block; } static MemoryBlock calloc(long num, long size) { MemoryBlock block = new MemoryBlockImpl(FlwMemoryTracker.calloc(num, size), num * size); - FlwMemoryTracker._allocCPUMemory(block.size()); + FlwMemoryTracker._allocCpuMemory(block.size()); return block; } } diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/memory/TrackedMemoryBlockImpl.java b/common/src/lib/java/dev/engine_room/flywheel/lib/memory/TrackedMemoryBlockImpl.java index 0d052275e..6346084f7 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/memory/TrackedMemoryBlockImpl.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/memory/TrackedMemoryBlockImpl.java @@ -28,21 +28,22 @@ class TrackedMemoryBlockImpl extends AbstractMemoryBlockImpl { @Override public MemoryBlock realloc(long size) { + assertAllocated(); MemoryBlock block = new TrackedMemoryBlockImpl(FlwMemoryTracker.realloc(ptr, size), size, cleaner); - FlwMemoryTracker._allocCPUMemory(block.size()); + FlwMemoryTracker._allocCpuMemory(block.size()); freeInner(); return block; } static MemoryBlock malloc(long size) { MemoryBlock block = new TrackedMemoryBlockImpl(FlwMemoryTracker.malloc(size), size, CLEANER); - FlwMemoryTracker._allocCPUMemory(block.size()); + FlwMemoryTracker._allocCpuMemory(block.size()); return block; } static MemoryBlock calloc(long num, long size) { MemoryBlock block = new TrackedMemoryBlockImpl(FlwMemoryTracker.calloc(num, size), num * size, CLEANER); - FlwMemoryTracker._allocCPUMemory(block.size()); + FlwMemoryTracker._allocCpuMemory(block.size()); return block; } @@ -61,7 +62,7 @@ class TrackedMemoryBlockImpl extends AbstractMemoryBlockImpl { public void run() { if (!freed) { FlwMemoryTracker.free(ptr); - FlwMemoryTracker._freeCPUMemory(size); + FlwMemoryTracker._freeCpuMemory(size); } } } diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/model/LineModelBuilder.java b/common/src/lib/java/dev/engine_room/flywheel/lib/model/LineModelBuilder.java index 5fdab98de..5e93d92ee 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/model/LineModelBuilder.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/model/LineModelBuilder.java @@ -1,5 +1,6 @@ package dev.engine_room.flywheel.lib.model; +import org.jetbrains.annotations.UnknownNullability; import org.joml.Vector4f; import org.joml.Vector4fc; import org.lwjgl.system.MemoryUtil; @@ -9,32 +10,32 @@ import dev.engine_room.flywheel.api.model.IndexSequence; import dev.engine_room.flywheel.api.model.Mesh; import dev.engine_room.flywheel.api.model.Model; import dev.engine_room.flywheel.api.vertex.MutableVertexList; -import dev.engine_room.flywheel.api.vertex.VertexView; +import dev.engine_room.flywheel.api.vertex.VertexList; import dev.engine_room.flywheel.lib.material.SimpleMaterial; import dev.engine_room.flywheel.lib.material.StandardMaterialShaders; import dev.engine_room.flywheel.lib.memory.MemoryBlock; import dev.engine_room.flywheel.lib.vertex.FullVertexView; +import dev.engine_room.flywheel.lib.vertex.VertexView; import net.minecraft.client.renderer.LightTexture; +import net.minecraft.client.renderer.texture.OverlayTexture; -public class LineModelBuilder { - public static final Material MATERIAL = SimpleMaterial.builder() +public final class LineModelBuilder { + private static final Material MATERIAL = SimpleMaterial.builder() .shaders(StandardMaterialShaders.LINE) .backfaceCulling(false) .diffuse(false) .build(); - private final VertexView vertices; - private MemoryBlock block; + @UnknownNullability + private VertexView vertexView; + @UnknownNullability + private MemoryBlock data; private int vertexCount = 0; - private LineModelBuilder(int segmentCount) { - this.vertices = new FullVertexView(); - this.block = MemoryBlock.malloc(segmentCount * 4 * FullVertexView.STRIDE); - vertices.ptr(block.ptr()); - } - - public static LineModelBuilder withCapacity(int segmentCount) { - return new LineModelBuilder(segmentCount); + public LineModelBuilder(int segmentCount) { + vertexView = new FullVertexView(); + data = MemoryBlock.mallocTracked(segmentCount * 4 * vertexView.stride()); + vertexView.ptr(data.ptr()); } public LineModelBuilder line(float x1, float y1, float z1, float x2, float y2, float z2) { @@ -50,53 +51,61 @@ public class LineModelBuilder { float normalZ = dz / length; for (int i = 0; i < 2; i++) { - vertices.x(vertexCount + i, x1); - vertices.y(vertexCount + i, y1); - vertices.z(vertexCount + i, z1); + vertexView.x(vertexCount + i, x1); + vertexView.y(vertexCount + i, y1); + vertexView.z(vertexCount + i, z1); - vertices.x(vertexCount + 2 + i, x2); - vertices.y(vertexCount + 2 + i, y2); - vertices.z(vertexCount + 2 + i, z2); + vertexView.x(vertexCount + 2 + i, x2); + vertexView.y(vertexCount + 2 + i, y2); + vertexView.z(vertexCount + 2 + i, z2); } for (int i = 0; i < 4; i++) { - vertices.r(vertexCount + i, 1); - vertices.g(vertexCount + i, 1); - vertices.b(vertexCount + i, 1); - vertices.a(vertexCount + i, 1); - vertices.u(vertexCount + i, 0); - vertices.v(vertexCount + i, 0); - vertices.light(vertexCount + i, LightTexture.FULL_BRIGHT); - vertices.normalX(vertexCount + i, normalX); - vertices.normalY(vertexCount + i, normalY); - vertices.normalZ(vertexCount + i, normalZ); + vertexView.r(vertexCount + i, 1); + vertexView.g(vertexCount + i, 1); + vertexView.b(vertexCount + i, 1); + vertexView.a(vertexCount + i, 1); + vertexView.u(vertexCount + i, 0); + vertexView.v(vertexCount + i, 0); + vertexView.overlay(vertexCount + i, OverlayTexture.NO_OVERLAY); + vertexView.light(vertexCount + i, LightTexture.FULL_BRIGHT); + vertexView.normalX(vertexCount + i, normalX); + vertexView.normalY(vertexCount + i, normalY); + vertexView.normalZ(vertexCount + i, normalZ); } vertexCount += 4; - return this; } public Model build() { - vertices.vertexCount(vertexCount); + vertexView.vertexCount(vertexCount); - var boundingSphere = ModelUtil.computeBoundingSphere(vertices); + var boundingSphere = ModelUtil.computeBoundingSphere(vertexView); boundingSphere.w += 0.1f; // make the bounding sphere a little bigger to account for line width + var mesh = new LineMesh(vertexView, boundingSphere); + var model = new SingleMeshModel(mesh, MATERIAL); - var mesh = new LineMesh(vertexCount, vertices, block, boundingSphere); + vertexView = null; + data = null; + vertexCount = 0; - return new SingleMeshModel(mesh, MATERIAL); + return model; } private void ensureCapacity(int vertexCount) { - if (vertexCount * FullVertexView.STRIDE > block.size()) { - this.block = block.realloc(vertexCount * FullVertexView.STRIDE); - vertices.ptr(block.ptr()); + if (data == null) { + vertexView = new FullVertexView(); + data = MemoryBlock.mallocTracked(vertexCount * vertexView.stride()); + vertexView.ptr(data.ptr()); + } else if (vertexCount * vertexView.stride() > data.size()) { + data = data.realloc(vertexCount * vertexView.stride()); + vertexView.ptr(data.ptr()); } } - public static class LineMesh implements Mesh { - public static final IndexSequence INDEX_SEQUENCE = (ptr, count) -> { + private static class LineMesh implements Mesh { + private static final IndexSequence INDEX_SEQUENCE = (ptr, count) -> { int numVertices = 2 * count / 3; int baseVertex = 0; while (baseVertex < numVertices) { @@ -113,26 +122,22 @@ public class LineModelBuilder { ptr += 24; } }; - private final int vertexCount; - private final VertexView vertexView; - private final MemoryBlock data; + private final VertexList vertexList; private final Vector4f boundingSphere; - public LineMesh(int vertexCount, VertexView vertexView, MemoryBlock data, Vector4f boundingSphere) { - this.vertexCount = vertexCount; - this.vertexView = vertexView; - this.data = data; + public LineMesh(VertexList vertexList, Vector4f boundingSphere) { + this.vertexList = vertexList; this.boundingSphere = boundingSphere; } @Override public int vertexCount() { - return vertexCount; + return vertexList.vertexCount(); } @Override public void write(MutableVertexList vertexList) { - vertexView.writeAll(vertexList); + vertexList.writeAll(vertexList); } @Override @@ -142,17 +147,12 @@ public class LineModelBuilder { @Override public int indexCount() { - return vertexCount / 2 * 3; + return vertexCount() / 2 * 3; } @Override public Vector4fc boundingSphere() { return boundingSphere; } - - @Override - public void delete() { - data.free(); - } } } diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/model/ModelCache.java b/common/src/lib/java/dev/engine_room/flywheel/lib/model/ModelCache.java index 7e37ccce0..9cd66069e 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/model/ModelCache.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/model/ModelCache.java @@ -1,17 +1,17 @@ package dev.engine_room.flywheel.lib.model; -import java.util.ArrayList; -import java.util.List; import java.util.Map; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Function; import org.jetbrains.annotations.ApiStatus; import dev.engine_room.flywheel.api.model.Model; +import dev.engine_room.flywheel.lib.util.FlwUtil; -public class ModelCache { - private static final List> ALL = new ArrayList<>(); +public final class ModelCache { + private static final Set> ALL = FlwUtil.createWeakHashSet(); private final Function factory; private final Map map = new ConcurrentHashMap<>(); @@ -28,7 +28,6 @@ public class ModelCache { } public void clear() { - map.values().forEach(Model::delete); map.clear(); } diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/model/ModelHolder.java b/common/src/lib/java/dev/engine_room/flywheel/lib/model/ModelHolder.java index cf3eef535..7ca5f5199 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/model/ModelHolder.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/model/ModelHolder.java @@ -1,16 +1,16 @@ package dev.engine_room.flywheel.lib.model; -import java.util.ArrayList; -import java.util.List; +import java.util.Set; import java.util.function.Supplier; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; import dev.engine_room.flywheel.api.model.Model; +import dev.engine_room.flywheel.lib.util.FlwUtil; -public class ModelHolder { - private static final List ALL = new ArrayList<>(); +public final class ModelHolder { + private static final Set ALL = FlwUtil.createWeakHashSet(); private final Supplier factory; @Nullable private volatile Model model; @@ -45,7 +45,6 @@ public class ModelHolder { synchronized (this) { model = this.model; if (model != null) { - model.delete(); this.model = null; } } diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/model/ModelUtil.java b/common/src/lib/java/dev/engine_room/flywheel/lib/model/ModelUtil.java index 0f9816e7f..4b3bf1d74 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/model/ModelUtil.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/model/ModelUtil.java @@ -31,19 +31,19 @@ public final class ModelUtil { @Nullable public static Material getMaterial(RenderType chunkRenderType, boolean shaded) { if (chunkRenderType == RenderType.solid()) { - return shaded ? Materials.CHUNK_SOLID_SHADED : Materials.CHUNK_SOLID_UNSHADED; + return shaded ? Materials.SOLID_BLOCK : Materials.SOLID_UNSHADED_BLOCK; } if (chunkRenderType == RenderType.cutoutMipped()) { - return shaded ? Materials.CHUNK_CUTOUT_MIPPED_SHADED : Materials.CHUNK_CUTOUT_MIPPED_UNSHADED; + return shaded ? Materials.CUTOUT_MIPPED_BLOCK : Materials.CUTOUT_MIPPED_UNSHADED_BLOCK; } if (chunkRenderType == RenderType.cutout()) { - return shaded ? Materials.CHUNK_CUTOUT_SHADED : Materials.CHUNK_CUTOUT_UNSHADED; + return shaded ? Materials.CUTOUT_BLOCK : Materials.CUTOUT_UNSHADED_BLOCK; } if (chunkRenderType == RenderType.translucent()) { - return shaded ? Materials.CHUNK_TRANSLUCENT_SHADED : Materials.CHUNK_TRANSLUCENT_UNSHADED; + return shaded ? Materials.TRANSLUCENT_BLOCK : Materials.TRANSLUCENT_UNSHADED_BLOCK; } if (chunkRenderType == RenderType.tripwire()) { - return shaded ? Materials.CHUNK_TRIPWIRE_SHADED : Materials.CHUNK_TRIPWIRE_UNSHADED; + return shaded ? Materials.TRIPWIRE_BLOCK : Materials.TRIPWIRE_UNSHADED_BLOCK; } return null; } diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/model/QuadIndexSequence.java b/common/src/lib/java/dev/engine_room/flywheel/lib/model/QuadIndexSequence.java index a59105b0e..0853ed1c2 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/model/QuadIndexSequence.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/model/QuadIndexSequence.java @@ -4,7 +4,7 @@ import org.lwjgl.system.MemoryUtil; import dev.engine_room.flywheel.api.model.IndexSequence; -public class QuadIndexSequence implements IndexSequence { +public final class QuadIndexSequence implements IndexSequence { public static final QuadIndexSequence INSTANCE = new QuadIndexSequence(); private QuadIndexSequence() { diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/model/SimpleMesh.java b/common/src/lib/java/dev/engine_room/flywheel/lib/model/SimpleMesh.java deleted file mode 100644 index ccddea727..000000000 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/model/SimpleMesh.java +++ /dev/null @@ -1,65 +0,0 @@ -package dev.engine_room.flywheel.lib.model; - -import org.jetbrains.annotations.Nullable; -import org.joml.Vector4f; -import org.joml.Vector4fc; - -import dev.engine_room.flywheel.api.vertex.MutableVertexList; -import dev.engine_room.flywheel.api.vertex.VertexView; -import dev.engine_room.flywheel.lib.memory.MemoryBlock; - -public class SimpleMesh implements QuadMesh { - private final int vertexCount; - private final VertexView vertexView; - private final Vector4f boundingSphere; - private final MemoryBlock data; - @Nullable - private final String descriptor; - - public SimpleMesh(VertexView vertexView, MemoryBlock data, @Nullable String descriptor) { - this.vertexView = vertexView; - this.data = data; - this.descriptor = descriptor; - - int bytes = (int) data.size(); - int stride = (int) this.vertexView.stride(); - if (bytes % stride != 0) { - throw new IllegalArgumentException("MemoryBlock contains non-whole amount of vertices!"); - } - vertexCount = bytes / stride; - - this.vertexView.ptr(data.ptr()); - this.vertexView.vertexCount(vertexCount); - - boundingSphere = ModelUtil.computeBoundingSphere(vertexView); - } - - public SimpleMesh(VertexView vertexView, MemoryBlock data) { - this(vertexView, data, null); - } - - @Override - public int vertexCount() { - return vertexCount; - } - - @Override - public void write(MutableVertexList dst) { - vertexView.writeAll(dst); - } - - @Override - public Vector4fc boundingSphere() { - return boundingSphere; - } - - @Override - public void delete() { - data.free(); - } - - @Override - public String toString() { - return "SimpleMesh{" + "vertexCount=" + vertexCount + ",descriptor={" + descriptor + "}" + "}"; - } -} diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/model/SimpleModel.java b/common/src/lib/java/dev/engine_room/flywheel/lib/model/SimpleModel.java index 2d3483a7b..494e06393 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/model/SimpleModel.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/model/SimpleModel.java @@ -24,11 +24,4 @@ public class SimpleModel implements Model { public Vector4fc boundingSphere() { return boundingSphere; } - - @Override - public void delete() { - for (ConfiguredMesh mesh : meshes) { - mesh.mesh().delete(); - } - } } diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/model/SimpleQuadMesh.java b/common/src/lib/java/dev/engine_room/flywheel/lib/model/SimpleQuadMesh.java new file mode 100644 index 000000000..e7ff25a5b --- /dev/null +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/model/SimpleQuadMesh.java @@ -0,0 +1,45 @@ +package dev.engine_room.flywheel.lib.model; + +import org.jetbrains.annotations.Nullable; +import org.joml.Vector4f; +import org.joml.Vector4fc; + +import dev.engine_room.flywheel.api.vertex.MutableVertexList; +import dev.engine_room.flywheel.api.vertex.VertexList; + +public final class SimpleQuadMesh implements QuadMesh { + private final VertexList vertexList; + private final Vector4f boundingSphere; + @Nullable + private final String descriptor; + + public SimpleQuadMesh(VertexList vertexList, @Nullable String descriptor) { + this.vertexList = vertexList; + boundingSphere = ModelUtil.computeBoundingSphere(vertexList); + this.descriptor = descriptor; + } + + public SimpleQuadMesh(VertexList vertexList) { + this(vertexList, null); + } + + @Override + public int vertexCount() { + return vertexList.vertexCount(); + } + + @Override + public void write(MutableVertexList dst) { + vertexList.writeAll(dst); + } + + @Override + public Vector4fc boundingSphere() { + return boundingSphere; + } + + @Override + public String toString() { + return "SimpleQuadMesh{" + "vertexCount=" + vertexCount() + ",descriptor={" + descriptor + "}" + "}"; + } +} diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/model/SingleMeshModel.java b/common/src/lib/java/dev/engine_room/flywheel/lib/model/SingleMeshModel.java index 005e92fe1..84ba0b5a3 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/model/SingleMeshModel.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/model/SingleMeshModel.java @@ -28,9 +28,4 @@ public class SingleMeshModel implements Model { public Vector4fc boundingSphere() { return mesh.boundingSphere(); } - - @Override - public void delete() { - mesh.delete(); - } } diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/model/baked/MeshHelper.java b/common/src/lib/java/dev/engine_room/flywheel/lib/model/baked/MeshHelper.java index e6326600b..257ac4f09 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/model/baked/MeshHelper.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/model/baked/MeshHelper.java @@ -7,16 +7,16 @@ import org.lwjgl.system.MemoryUtil; import com.mojang.blaze3d.vertex.BufferBuilder; -import dev.engine_room.flywheel.api.vertex.VertexView; import dev.engine_room.flywheel.lib.memory.MemoryBlock; -import dev.engine_room.flywheel.lib.model.SimpleMesh; +import dev.engine_room.flywheel.lib.model.SimpleQuadMesh; import dev.engine_room.flywheel.lib.vertex.NoOverlayVertexView; +import dev.engine_room.flywheel.lib.vertex.VertexView; final class MeshHelper { private MeshHelper() { } - public static SimpleMesh blockVerticesToMesh(BufferBuilder.RenderedBuffer buffer, @Nullable String meshDescriptor) { + public static SimpleQuadMesh blockVerticesToMesh(BufferBuilder.RenderedBuffer buffer, @Nullable String meshDescriptor) { BufferBuilder.DrawState drawState = buffer.drawState(); int vertexCount = drawState.vertexCount(); long srcStride = drawState.format().getVertexSize(); @@ -25,7 +25,7 @@ final class MeshHelper { long dstStride = vertexView.stride(); ByteBuffer src = buffer.vertexBuffer(); - MemoryBlock dst = MemoryBlock.malloc((long) vertexCount * dstStride); + MemoryBlock dst = MemoryBlock.mallocTracked((long) vertexCount * dstStride); long srcPtr = MemoryUtil.memAddress(src); long dstPtr = dst.ptr(); // The first 31 bytes of each vertex in a block vertex buffer are guaranteed to contain the same data in the @@ -42,6 +42,6 @@ final class MeshHelper { vertexView.ptr(dstPtr); vertexView.vertexCount(vertexCount); - return new SimpleMesh(vertexView, dst, meshDescriptor); + return new SimpleQuadMesh(vertexView, meshDescriptor); } } diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/model/baked/OriginBlockAndTintGetter.java b/common/src/lib/java/dev/engine_room/flywheel/lib/model/baked/OriginBlockAndTintGetter.java new file mode 100644 index 000000000..9df1dbf4f --- /dev/null +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/model/baked/OriginBlockAndTintGetter.java @@ -0,0 +1,57 @@ +package dev.engine_room.flywheel.lib.model.baked; + +import java.util.function.ToIntFunction; + +import org.jetbrains.annotations.Nullable; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; + +public class OriginBlockAndTintGetter extends VirtualBlockGetter { + @Nullable + protected BlockEntity originBlockEntity; + protected BlockState originBlockState = Blocks.AIR.defaultBlockState(); + + public OriginBlockAndTintGetter(ToIntFunction blockLightFunc, ToIntFunction skyLightFunc) { + super(blockLightFunc, skyLightFunc); + } + + public void originBlockEntity(@Nullable BlockEntity blockEntity) { + originBlockEntity = blockEntity; + } + + public void originBlockState(BlockState state) { + originBlockState = state; + } + + @Override + @Nullable + public BlockEntity getBlockEntity(BlockPos pos) { + if (pos.equals(BlockPos.ZERO)) { + return originBlockEntity; + } + + return null; + } + + @Override + public BlockState getBlockState(BlockPos pos) { + if (pos.equals(BlockPos.ZERO)) { + return originBlockState; + } + + return Blocks.AIR.defaultBlockState(); + } + + @Override + public int getHeight() { + return 1; + } + + @Override + public int getMinBuildHeight() { + return 0; + } +} diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/model/baked/PartialModel.java b/common/src/lib/java/dev/engine_room/flywheel/lib/model/baked/PartialModel.java index ba96c09c0..0b80329e9 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/model/baked/PartialModel.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/model/baked/PartialModel.java @@ -1,8 +1,13 @@ package dev.engine_room.flywheel.lib.model.baked; -import java.util.ArrayList; -import java.util.List; +import java.util.concurrent.ConcurrentMap; +import org.jetbrains.annotations.UnknownNullability; + +import com.google.common.collect.MapMaker; + +import dev.engine_room.flywheel.lib.internal.FlwLibXplat; +import net.minecraft.client.Minecraft; import net.minecraft.client.resources.model.BakedModel; import net.minecraft.resources.ResourceLocation; @@ -10,44 +15,35 @@ import net.minecraft.resources.ResourceLocation; * A helper class for loading and accessing JSON models not directly used by any blocks or items. *
* Creating a PartialModel will make Minecraft automatically load the associated modelLocation. - * PartialModels must be initialized before the initial resource reload, otherwise an error will be thrown. - * It is recommended to do this in the client mod initializer on Fabric and the mod class constructor on Forge. *
* Once Minecraft has finished baking all models, all PartialModels will have their bakedModel fields populated. */ -public class PartialModel { - static final List ALL = new ArrayList<>(); - static boolean tooLate = false; +public final class PartialModel { + static final ConcurrentMap ALL = new MapMaker().weakValues().makeMap(); + static boolean populateOnInit = false; - protected final ResourceLocation modelLocation; - protected BakedModel bakedModel; - - public PartialModel(ResourceLocation modelLocation) { - if (tooLate) { - throw new RuntimeException("Attempted to create PartialModel with location '" + modelLocation + "' after start of initial resource reload!"); - } + private final ResourceLocation modelLocation; + @UnknownNullability + BakedModel bakedModel; + private PartialModel(ResourceLocation modelLocation) { this.modelLocation = modelLocation; - synchronized (ALL) { - ALL.add(this); + if (populateOnInit) { + bakedModel = FlwLibXplat.INSTANCE.getBakedModel(Minecraft.getInstance().getModelManager(), modelLocation); } } - public ResourceLocation getLocation() { - return modelLocation; - } - - public String getName() { - return getLocation() - .toString(); + public static PartialModel of(ResourceLocation modelLocation) { + return ALL.computeIfAbsent(modelLocation, PartialModel::new); } + @UnknownNullability public BakedModel get() { return bakedModel; } - protected void set(BakedModel bakedModel) { - this.bakedModel = bakedModel; + public ResourceLocation modelLocation() { + return modelLocation; } } diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/model/part/ModelPartConverter.java b/common/src/lib/java/dev/engine_room/flywheel/lib/model/part/ModelPartConverter.java index 637c5523e..1e4a17d27 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/model/part/ModelPartConverter.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/model/part/ModelPartConverter.java @@ -7,8 +7,9 @@ import com.mojang.blaze3d.vertex.PoseStack; import dev.engine_room.flywheel.api.model.Mesh; import dev.engine_room.flywheel.lib.memory.MemoryBlock; -import dev.engine_room.flywheel.lib.model.SimpleMesh; +import dev.engine_room.flywheel.lib.model.SimpleQuadMesh; import dev.engine_room.flywheel.lib.vertex.PosTexNormalVertexView; +import dev.engine_room.flywheel.lib.vertex.VertexView; import net.minecraft.client.Minecraft; import net.minecraft.client.model.geom.EntityModelSet; import net.minecraft.client.model.geom.ModelLayerLocation; @@ -29,10 +30,14 @@ public final class ModelPartConverter { poseStack = objects.identityPoseStack; } VertexWriter vertexWriter = objects.vertexWriter; + vertexWriter.setTextureMapper(textureMapper); modelPart.render(poseStack, vertexWriter, LightTexture.FULL_BRIGHT, OverlayTexture.NO_OVERLAY); MemoryBlock data = vertexWriter.copyDataAndReset(); - return new SimpleMesh(new PosTexNormalVertexView(), data, "source=ModelPartConverter"); + + VertexView vertexView = new PosTexNormalVertexView(); + vertexView.load(data); + return new SimpleQuadMesh(vertexView, "source=ModelPartConverter"); } public static Mesh convert(ModelLayerLocation layer, @Nullable TextureAtlasSprite sprite, String... childPath) { diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/model/part/VertexWriter.java b/common/src/lib/java/dev/engine_room/flywheel/lib/model/part/VertexWriter.java index f8b9aa5f6..30855a85e 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/model/part/VertexWriter.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/model/part/VertexWriter.java @@ -6,7 +6,7 @@ import org.lwjgl.system.MemoryUtil; import com.mojang.blaze3d.vertex.VertexConsumer; -import dev.engine_room.flywheel.lib.math.RenderMath; +import dev.engine_room.flywheel.lib.math.DataPacker; import dev.engine_room.flywheel.lib.memory.MemoryBlock; import dev.engine_room.flywheel.lib.model.part.ModelPartConverter.TextureMapper; import dev.engine_room.flywheel.lib.vertex.PosTexNormalVertexView; @@ -85,9 +85,9 @@ class VertexWriter implements VertexConsumer { public VertexConsumer normal(float x, float y, float z) { if (!filledNormal) { long ptr = vertexPtr(); - MemoryUtil.memPutByte(ptr + 20, RenderMath.nb(x)); - MemoryUtil.memPutByte(ptr + 21, RenderMath.nb(y)); - MemoryUtil.memPutByte(ptr + 22, RenderMath.nb(z)); + MemoryUtil.memPutByte(ptr + 20, DataPacker.packNormI8(x)); + MemoryUtil.memPutByte(ptr + 21, DataPacker.packNormI8(y)); + MemoryUtil.memPutByte(ptr + 22, DataPacker.packNormI8(z)); filledNormal = true; } return this; @@ -124,7 +124,7 @@ class VertexWriter implements VertexConsumer { } public MemoryBlock copyDataAndReset() { - MemoryBlock dataCopy = MemoryBlock.malloc(vertexCount * STRIDE); + MemoryBlock dataCopy = MemoryBlock.mallocTracked(vertexCount * STRIDE); data.copyTo(dataCopy); vertexCount = 0; diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/task/BarrierPlan.java b/common/src/lib/java/dev/engine_room/flywheel/lib/task/BarrierPlan.java index a00e35e21..2f641e5d2 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/task/BarrierPlan.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/task/BarrierPlan.java @@ -4,7 +4,7 @@ import dev.engine_room.flywheel.api.task.Plan; import dev.engine_room.flywheel.api.task.TaskExecutor; public record BarrierPlan(Plan first, Plan second) implements SimplyComposedPlan { - public static Plan of(Plan first, Plan second) { + public static BarrierPlan of(Plan first, Plan second) { return new BarrierPlan<>(first, second); } @@ -12,5 +12,4 @@ public record BarrierPlan(Plan first, Plan second) implements SimplyCom public void execute(TaskExecutor taskExecutor, C context, Runnable onCompletion) { first.execute(taskExecutor, context, () -> second.execute(taskExecutor, context, onCompletion)); } - } diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/task/Distribute.java b/common/src/lib/java/dev/engine_room/flywheel/lib/task/Distribute.java index 3b6f6a1b2..592330b47 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/task/Distribute.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/task/Distribute.java @@ -9,6 +9,9 @@ import dev.engine_room.flywheel.api.task.TaskExecutor; import dev.engine_room.flywheel.lib.math.MoreMath; public final class Distribute { + private Distribute() { + } + /** * Distribute the given list of tasks across the threads of the task executor. * @@ -184,7 +187,4 @@ public final class Distribute { public static int sliceSize(TaskExecutor taskExecutor, int totalSize, int denominator) { return MoreMath.ceilingDiv(totalSize, taskExecutor.threadCount() * denominator); } - - private Distribute() { - } } diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/task/DynamicNestedPlan.java b/common/src/lib/java/dev/engine_room/flywheel/lib/task/DynamicNestedPlan.java index 69bf3eed0..ba2727f38 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/task/DynamicNestedPlan.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/task/DynamicNestedPlan.java @@ -14,11 +14,11 @@ import dev.engine_room.flywheel.lib.task.functional.SupplierWithContext; */ public record DynamicNestedPlan( SupplierWithContext>> plans) implements SimplyComposedPlan { - public static Plan of(SupplierWithContext.Ignored>> supplier) { + public static DynamicNestedPlan of(SupplierWithContext.Ignored>> supplier) { return new DynamicNestedPlan<>(supplier); } - public static Plan of(SupplierWithContext>> supplier) { + public static DynamicNestedPlan of(SupplierWithContext>> supplier) { return new DynamicNestedPlan<>(supplier); } diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/task/ForEachPlan.java b/common/src/lib/java/dev/engine_room/flywheel/lib/task/ForEachPlan.java index 986281e2f..3f6ce8ac1 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/task/ForEachPlan.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/task/ForEachPlan.java @@ -2,7 +2,6 @@ package dev.engine_room.flywheel.lib.task; import java.util.List; -import dev.engine_room.flywheel.api.task.Plan; import dev.engine_room.flywheel.api.task.TaskExecutor; import dev.engine_room.flywheel.lib.task.functional.ConsumerWithContext; import dev.engine_room.flywheel.lib.task.functional.SupplierWithContext; @@ -19,19 +18,19 @@ import dev.engine_room.flywheel.lib.task.functional.SupplierWithContext; */ public record ForEachPlan(SupplierWithContext> listSupplier, ConsumerWithContext action) implements SimplyComposedPlan { - public static Plan of(SupplierWithContext> iterable, ConsumerWithContext forEach) { + public static ForEachPlan of(SupplierWithContext> iterable, ConsumerWithContext forEach) { return new ForEachPlan<>(iterable, forEach); } - public static Plan of(SupplierWithContext> iterable, ConsumerWithContext.Ignored forEach) { + public static ForEachPlan of(SupplierWithContext> iterable, ConsumerWithContext.Ignored forEach) { return new ForEachPlan<>(iterable, forEach); } - public static Plan of(SupplierWithContext.Ignored> iterable, ConsumerWithContext forEach) { + public static ForEachPlan of(SupplierWithContext.Ignored> iterable, ConsumerWithContext forEach) { return new ForEachPlan<>(iterable, forEach); } - public static Plan of(SupplierWithContext.Ignored> iterable, ConsumerWithContext.Ignored forEach) { + public static ForEachPlan of(SupplierWithContext.Ignored> iterable, ConsumerWithContext.Ignored forEach) { return new ForEachPlan<>(iterable, forEach); } diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/task/ForEachSlicePlan.java b/common/src/lib/java/dev/engine_room/flywheel/lib/task/ForEachSlicePlan.java index 8f036c4b7..8a677e6de 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/task/ForEachSlicePlan.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/task/ForEachSlicePlan.java @@ -2,7 +2,6 @@ package dev.engine_room.flywheel.lib.task; import java.util.List; -import dev.engine_room.flywheel.api.task.Plan; import dev.engine_room.flywheel.api.task.TaskExecutor; import dev.engine_room.flywheel.lib.task.functional.ConsumerWithContext; import dev.engine_room.flywheel.lib.task.functional.SupplierWithContext; @@ -19,19 +18,19 @@ import dev.engine_room.flywheel.lib.task.functional.SupplierWithContext; */ public record ForEachSlicePlan(SupplierWithContext> listSupplier, ConsumerWithContext, C> action) implements SimplyComposedPlan { - public static Plan of(SupplierWithContext> iterable, ConsumerWithContext, C> forEach) { + public static ForEachSlicePlan of(SupplierWithContext> iterable, ConsumerWithContext, C> forEach) { return new ForEachSlicePlan<>(iterable, forEach); } - public static Plan of(SupplierWithContext> iterable, ConsumerWithContext.Ignored, C> forEach) { + public static ForEachSlicePlan of(SupplierWithContext> iterable, ConsumerWithContext.Ignored, C> forEach) { return new ForEachSlicePlan<>(iterable, forEach); } - public static Plan of(SupplierWithContext.Ignored> iterable, ConsumerWithContext, C> forEach) { + public static ForEachSlicePlan of(SupplierWithContext.Ignored> iterable, ConsumerWithContext, C> forEach) { return new ForEachSlicePlan<>(iterable, forEach); } - public static Plan of(SupplierWithContext.Ignored> iterable, ConsumerWithContext.Ignored, C> forEach) { + public static ForEachSlicePlan of(SupplierWithContext.Ignored> iterable, ConsumerWithContext.Ignored, C> forEach) { return new ForEachSlicePlan<>(iterable, forEach); } diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/task/IfElsePlan.java b/common/src/lib/java/dev/engine_room/flywheel/lib/task/IfElsePlan.java index d7b60c155..dfcefa397 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/task/IfElsePlan.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/task/IfElsePlan.java @@ -30,7 +30,7 @@ public record IfElsePlan(BooleanSupplierWithContext condition, Plan onT } } - public static class Builder { + public static final class Builder { private final BooleanSupplierWithContext condition; private Plan onTrue = UnitPlan.of(); private Plan onFalse = UnitPlan.of(); diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/task/MapContextPlan.java b/common/src/lib/java/dev/engine_room/flywheel/lib/task/MapContextPlan.java index 26b4133ff..d81b026f6 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/task/MapContextPlan.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/task/MapContextPlan.java @@ -19,7 +19,7 @@ public record MapContextPlan(SupplierWithContext map, Plan plan) plan.execute(taskExecutor, newContext, onCompletion); } - public static class Builder { + public static final class Builder { private final SupplierWithContext map; public Builder(SupplierWithContext map) { diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/task/NamedFlag.java b/common/src/lib/java/dev/engine_room/flywheel/lib/task/NamedFlag.java deleted file mode 100644 index b990ba974..000000000 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/task/NamedFlag.java +++ /dev/null @@ -1,21 +0,0 @@ -package dev.engine_room.flywheel.lib.task; - -/** - * A flag with an arbitrary name. - */ -public final class NamedFlag extends Flag { - private final String name; - - /** - * @param name The name of the flag, mainly for debugging purposes. - */ - public NamedFlag(String name) { - this.name = name; - } - - @Override - public String toString() { - return "NamedFlag[" + "name=" + name + ']'; - } - -} diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/task/NestedPlan.java b/common/src/lib/java/dev/engine_room/flywheel/lib/task/NestedPlan.java index a3e4e4097..fea1cc1f5 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/task/NestedPlan.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/task/NestedPlan.java @@ -41,5 +41,4 @@ public record NestedPlan(List> parallelPlans) implements SimplyCompos .add(plan) .build()); } - } diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/task/PlanMap.java b/common/src/lib/java/dev/engine_room/flywheel/lib/task/PlanMap.java index fcc8d7035..8fe000181 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/task/PlanMap.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/task/PlanMap.java @@ -14,7 +14,7 @@ import dev.engine_room.flywheel.api.task.TaskExecutor; * @param The key type * @param The context type */ -public class PlanMap implements SimplyComposedPlan { +public final class PlanMap implements SimplyComposedPlan { private final List keys = new ArrayList<>(); private final List> values = new ArrayList<>(); diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/task/SimplePlan.java b/common/src/lib/java/dev/engine_room/flywheel/lib/task/SimplePlan.java index 0ec04d1f9..c172c5086 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/task/SimplePlan.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/task/SimplePlan.java @@ -43,5 +43,4 @@ public record SimplePlan(List> parallelTasks) implemen } return SimplyComposedPlan.super.and(plan); } - } diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/task/SimplyComposedPlan.java b/common/src/lib/java/dev/engine_room/flywheel/lib/task/SimplyComposedPlan.java index e5556906a..9b968bd6e 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/task/SimplyComposedPlan.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/task/SimplyComposedPlan.java @@ -5,12 +5,11 @@ import dev.engine_room.flywheel.api.task.Plan; public interface SimplyComposedPlan extends Plan { @Override default Plan then(Plan plan) { - return new BarrierPlan<>(this, plan); + return BarrierPlan.of(this, plan); } @Override default Plan and(Plan plan) { return NestedPlan.of(this, plan); } - } diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/task/StageFlag.java b/common/src/lib/java/dev/engine_room/flywheel/lib/task/StageFlag.java deleted file mode 100644 index 34f5db1e8..000000000 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/task/StageFlag.java +++ /dev/null @@ -1,25 +0,0 @@ -package dev.engine_room.flywheel.lib.task; - -import dev.engine_room.flywheel.api.event.RenderStage; - -/** - * A flag that is associated with a render stage. - *
- * Useful for synchronizing tasks for a specific render stage. - */ -public final class StageFlag extends Flag { - private final RenderStage stage; - - /** - * @param stage The render stage this flag is associated with. - */ - public StageFlag(RenderStage stage) { - this.stage = stage; - } - - @Override - public String toString() { - return "StageFlag[" + "stage=" + stage + ']'; - } - -} diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/task/SyncedPlan.java b/common/src/lib/java/dev/engine_room/flywheel/lib/task/SyncedPlan.java deleted file mode 100644 index 3a1e42860..000000000 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/task/SyncedPlan.java +++ /dev/null @@ -1,23 +0,0 @@ -package dev.engine_room.flywheel.lib.task; - -import dev.engine_room.flywheel.api.task.Plan; -import dev.engine_room.flywheel.api.task.TaskExecutor; -import dev.engine_room.flywheel.lib.task.functional.RunnableWithContext; - -public record SyncedPlan(RunnableWithContext task) implements SimplyComposedPlan { - public static Plan of(RunnableWithContext task) { - return new SyncedPlan<>(task); - } - - public static Plan of(RunnableWithContext.Ignored task) { - return new SyncedPlan<>(task); - } - - @Override - public void execute(TaskExecutor taskExecutor, C context, Runnable onCompletion) { - taskExecutor.scheduleForMainThread(() -> { - task.run(context); - onCompletion.run(); - }); - } -} diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/task/Synchronizer.java b/common/src/lib/java/dev/engine_room/flywheel/lib/task/Synchronizer.java index 5039a5cb2..27c015cdb 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/task/Synchronizer.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/task/Synchronizer.java @@ -2,7 +2,7 @@ package dev.engine_room.flywheel.lib.task; import java.util.concurrent.atomic.AtomicInteger; -public class Synchronizer implements Runnable { +public final class Synchronizer implements Runnable { private final AtomicInteger countDown; private final Runnable onCompletion; diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/task/UnitPlan.java b/common/src/lib/java/dev/engine_room/flywheel/lib/task/UnitPlan.java index 9bc20cef7..27b46aa36 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/task/UnitPlan.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/task/UnitPlan.java @@ -3,7 +3,7 @@ package dev.engine_room.flywheel.lib.task; import dev.engine_room.flywheel.api.task.Plan; import dev.engine_room.flywheel.api.task.TaskExecutor; -public class UnitPlan implements Plan { +public final class UnitPlan implements Plan { private static final UnitPlan INSTANCE = new UnitPlan<>(); private UnitPlan() { @@ -28,5 +28,4 @@ public class UnitPlan implements Plan { public Plan and(Plan plan) { return plan; } - } diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/transform/Affine.java b/common/src/lib/java/dev/engine_room/flywheel/lib/transform/Affine.java index e6e80ec32..91d62df57 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/transform/Affine.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/transform/Affine.java @@ -1,27 +1,46 @@ package dev.engine_room.flywheel.lib.transform; import org.joml.Quaternionf; +import org.joml.Quaternionfc; +import org.joml.Vector3fc; import com.mojang.math.Axis; import net.minecraft.core.Direction; public interface Affine> extends Translate, Rotate, Scale { - default Self rotateAround(Quaternionf quaternion, float x, float y, float z) { + default Self rotateAround(Quaternionfc quaternion, float x, float y, float z) { return translate(x, y, z).rotate(quaternion) - .translate(-x, -y, -z); + .translateBack(x, y, z); } - default Self rotateCentered(Quaternionf q) { + default Self rotateAround(Quaternionfc quaternion, Vector3fc vec) { + return translate(vec.x(), vec.y(), vec.z()).rotate(quaternion) + .translateBack(vec.x(), vec.y(), vec.z()); + } + + default Self rotateCentered(Quaternionfc q) { return rotateAround(q, CENTER, CENTER, CENTER); } + default Self rotateCentered(float radians, Vector3fc axis) { + if (radians == 0) { + return self(); + } + return rotateCentered(new Quaternionf().setAngleAxis(radians, axis.x(), axis.y(), axis.z())); + } + default Self rotateCentered(float radians, Axis axis) { + if (radians == 0) { + return self(); + } return rotateCentered(axis.rotation(radians)); } default Self rotateCentered(float radians, Direction axis) { - var step = axis.step(); - return rotateCentered(new Quaternionf().setAngleAxis(radians, step.x(), step.y(), step.z())); + if (radians == 0) { + return self(); + } + return rotateCentered(radians, axis.step()); } } diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/transform/PoseTransformStack.java b/common/src/lib/java/dev/engine_room/flywheel/lib/transform/PoseTransformStack.java index aafaefead..81a9e661f 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/transform/PoseTransformStack.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/transform/PoseTransformStack.java @@ -1,9 +1,9 @@ package dev.engine_room.flywheel.lib.transform; import org.jetbrains.annotations.ApiStatus; -import org.joml.Matrix3f; -import org.joml.Matrix4f; -import org.joml.Quaternionf; +import org.joml.Matrix3fc; +import org.joml.Matrix4fc; +import org.joml.Quaternionfc; import com.mojang.blaze3d.vertex.PoseStack; @@ -15,45 +15,14 @@ import com.mojang.blaze3d.vertex.PoseStack; public final class PoseTransformStack implements TransformStack { private final PoseStack stack; + /** + * Use {@link TransformStack#of(PoseStack)}. + */ @ApiStatus.Internal public PoseTransformStack(PoseStack stack) { this.stack = stack; } - @Override - public PoseTransformStack rotate(Quaternionf quaternion) { - stack.mulPose(quaternion); - return this; - } - - @Override - public PoseTransformStack rotateAround(Quaternionf quaternion, float x, float y, float z) { - stack.rotateAround(quaternion, x, y, z); - return this; - } - - @Override - public PoseTransformStack scale(float factorX, float factorY, float factorZ) { - stack.scale(factorX, factorY, factorZ); - return this; - } - - @Override - public PoseTransformStack mulPose(Matrix4f pose) { - stack.last() - .pose() - .mul(pose); - return this; - } - - @Override - public PoseTransformStack mulNormal(Matrix3f normal) { - stack.last() - .normal() - .mul(normal); - return this; - } - @Override public PoseTransformStack pushPose() { stack.pushPose(); @@ -67,11 +36,49 @@ public final class PoseTransformStack implements TransformStack> { - S rotate(Quaternionf quaternion); +public interface Rotate> { + Self rotate(Quaternionfc quaternion); - default S rotate(AxisAngle4f axisAngle) { + default Self rotate(AxisAngle4f axisAngle) { return rotate(new Quaternionf(axisAngle)); } - default S rotate(float radians, Vector3fc axis) { + default Self rotate(float radians, Vector3fc axis) { if (radians == 0) { return self(); } return rotate(new Quaternionf().setAngleAxis(radians, axis.x(), axis.y(), axis.z())); } - default S rotate(float radians, Axis axis) { + default Self rotate(float radians, Axis axis) { if (radians == 0) { return self(); } return rotate(axis.rotation(radians)); } - default S rotate(float radians, Direction axis) { + default Self rotate(float radians, Direction axis) { if (radians == 0) { return self(); } return rotate(radians, axis.step()); } - default S rotate(float radians, Direction.Axis axis) { + default Self rotate(float radians, Direction.Axis axis) { return switch (axis) { case X -> rotateX(radians); case Y -> rotateY(radians); @@ -44,59 +45,59 @@ public interface Rotate> { }; } - default S rotateDegrees(float degrees, Vector3fc axis) { + default Self rotateDegrees(float degrees, Vector3fc axis) { if (degrees == 0) { return self(); } return rotate((float) Math.toRadians(degrees), axis); } - default S rotateDegrees(float degrees, Axis axis) { + default Self rotateDegrees(float degrees, Axis axis) { if (degrees == 0) { return self(); } return rotate(axis.rotationDegrees(degrees)); } - default S rotateDegrees(float degrees, Direction axis) { + default Self rotateDegrees(float degrees, Direction axis) { if (degrees == 0) { return self(); } return rotate((float) Math.toRadians(degrees), axis); } - default S rotateDegrees(float degrees, Direction.Axis axis) { + default Self rotateDegrees(float degrees, Direction.Axis axis) { if (degrees == 0) { return self(); } return rotate((float) Math.toRadians(degrees), axis); } - default S rotateX(float radians) { + default Self rotateX(float radians) { return rotate(radians, Axis.XP); } - default S rotateY(float radians) { + default Self rotateY(float radians) { return rotate(radians, Axis.YP); } - default S rotateZ(float radians) { + default Self rotateZ(float radians) { return rotate(radians, Axis.ZP); } - default S rotateXDegrees(float degrees) { + default Self rotateXDegrees(float degrees) { return rotateDegrees(degrees, Axis.XP); } - default S rotateYDegrees(float degrees) { + default Self rotateYDegrees(float degrees) { return rotateDegrees(degrees, Axis.YP); } - default S rotateZDegrees(float degrees) { + default Self rotateZDegrees(float degrees) { return rotateDegrees(degrees, Axis.ZP); } - default S rotateToFace(Direction facing) { + default Self rotateToFace(Direction facing) { return switch (facing) { case DOWN -> rotateXDegrees(-90); case UP -> rotateXDegrees(90); @@ -108,7 +109,7 @@ public interface Rotate> { } @SuppressWarnings("unchecked") - default S self() { - return (S) this; + default Self self() { + return (Self) this; } } diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/transform/Scale.java b/common/src/lib/java/dev/engine_room/flywheel/lib/transform/Scale.java index 8ef8cd664..554383e31 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/transform/Scale.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/transform/Scale.java @@ -1,5 +1,7 @@ package dev.engine_room.flywheel.lib.transform; +import org.joml.Vector3fc; + public interface Scale> { Self scale(float factorX, float factorY, float factorZ); @@ -18,4 +20,8 @@ public interface Scale> { default Self scaleZ(float factor) { return scale(1, 1, factor); } + + default Self scale(Vector3fc factors) { + return scale(factors.x(), factors.y(), factors.z()); + } } diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/transform/Transform.java b/common/src/lib/java/dev/engine_room/flywheel/lib/transform/Transform.java index fa7ddc7f7..c9aeb051a 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/transform/Transform.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/transform/Transform.java @@ -1,16 +1,16 @@ package dev.engine_room.flywheel.lib.transform; -import org.joml.Matrix3f; -import org.joml.Matrix4f; +import org.joml.Matrix3fc; +import org.joml.Matrix4fc; import com.mojang.blaze3d.vertex.PoseStack; public interface Transform> extends Affine { - Self mulPose(Matrix4f pose); + Self mulPose(Matrix4fc pose); - Self mulNormal(Matrix3f normal); + Self mulNormal(Matrix3fc normal); - default Self transform(Matrix4f pose, Matrix3f normal) { + default Self transform(Matrix4fc pose, Matrix3fc normal) { return mulPose(pose).mulNormal(normal); } diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/transform/Translate.java b/common/src/lib/java/dev/engine_room/flywheel/lib/transform/Translate.java index 30b43e2ec..cfaa049c2 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/transform/Translate.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/transform/Translate.java @@ -1,6 +1,7 @@ package dev.engine_room.flywheel.lib.transform; -import org.joml.Vector3f; +import org.joml.Vector3fc; +import org.joml.Vector3ic; import net.minecraft.core.Vec3i; import net.minecraft.world.phys.Vec3; @@ -8,21 +9,25 @@ import net.minecraft.world.phys.Vec3; public interface Translate> { float CENTER = 0.5f; - Self translate(double x, double y, double z); + Self translate(float x, float y, float z); - default Self translate(double v) { + default Self translate(double x, double y, double z) { + return translate((float) x, (float) y, (float) z); + } + + default Self translate(float v) { return translate(v, v, v); } - default Self translateX(double x) { + default Self translateX(float x) { return translate(x, 0, 0); } - default Self translateY(double y) { + default Self translateY(float y) { return translate(0, y, 0); } - default Self translateZ(double z) { + default Self translateZ(float z) { return translate(0, 0, z); } @@ -30,7 +35,11 @@ public interface Translate> { return translate(vec.getX(), vec.getY(), vec.getZ()); } - default Self translate(Vector3f vec) { + default Self translate(Vector3ic vec) { + return translate(vec.x(), vec.y(), vec.z()); + } + + default Self translate(Vector3fc vec) { return translate(vec.x(), vec.y(), vec.z()); } @@ -38,11 +47,15 @@ public interface Translate> { return translate(vec.x, vec.y, vec.z); } + default Self translateBack(float x, float y, float z) { + return translate(-x, -y, -z); + } + default Self translateBack(double x, double y, double z) { return translate(-x, -y, -z); } - default Self translateBack(double v) { + default Self translateBack(float v) { return translate(-v); } @@ -50,8 +63,12 @@ public interface Translate> { return translateBack(vec.getX(), vec.getY(), vec.getZ()); } - default Self translateBack(Vector3f vec) { - return translateBack(vec.x, vec.y, vec.z); + default Self translateBack(Vector3ic vec) { + return translateBack(vec.x(), vec.y(), vec.z()); + } + + default Self translateBack(Vector3fc vec) { + return translateBack(vec.x(), vec.y(), vec.z()); } default Self translateBack(Vec3 vec) { diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/util/FlwUtil.java b/common/src/lib/java/dev/engine_room/flywheel/lib/util/FlwUtil.java index 5aa9dd4ea..c00d10d97 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/util/FlwUtil.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/util/FlwUtil.java @@ -5,23 +5,17 @@ import java.util.Collections; import java.util.Set; import java.util.WeakHashMap; -import net.minecraft.client.Minecraft; - public final class FlwUtil { private FlwUtil() { } - public static boolean isGameActive() { - return !(Minecraft.getInstance().level == null || Minecraft.getInstance().player == null); - } - - public static Set createWeakHashSet() { - return Collections.newSetFromMap(new WeakHashMap<>()); - } - public static int[] initArray(int size, int fill) { var out = new int[size]; Arrays.fill(out, fill); return out; } + + public static Set createWeakHashSet() { + return Collections.newSetFromMap(new WeakHashMap<>()); + } } diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/util/SectionUtil.java b/common/src/lib/java/dev/engine_room/flywheel/lib/util/SectionUtil.java deleted file mode 100644 index 3f88675c3..000000000 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/util/SectionUtil.java +++ /dev/null @@ -1,53 +0,0 @@ -package dev.engine_room.flywheel.lib.util; - -import java.util.Collection; -import java.util.function.LongConsumer; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.SectionPos; - -public class SectionUtil { - public static void containingAll(Collection blocks, LongConsumer consumer) { - if (blocks.isEmpty()) { - return; - } - - int minX = Integer.MAX_VALUE; - int minY = Integer.MAX_VALUE; - int minZ = Integer.MAX_VALUE; - int maxX = Integer.MIN_VALUE; - int maxY = Integer.MIN_VALUE; - int maxZ = Integer.MIN_VALUE; - for (BlockPos pos : blocks) { - minX = Math.min(minX, pos.getX()); - minY = Math.min(minY, pos.getY()); - minZ = Math.min(minZ, pos.getZ()); - maxX = Math.max(maxX, pos.getX()); - maxY = Math.max(maxY, pos.getY()); - maxZ = Math.max(maxZ, pos.getZ()); - } - - betweenClosedBlocks(minX, minY, minZ, maxX, maxY, maxZ, consumer); - } - - public static void betweenClosedBox(int x, int y, int z, int sizeX, int sizeY, int sizeZ, LongConsumer consumer) { - betweenClosedBlocks(x, y, z, x + sizeX, y + sizeY, z + sizeZ, consumer); - } - - public static void betweenClosedBlocks(int minX, int minY, int minZ, int maxX, int maxY, int maxZ, LongConsumer consumer) { - int minSectionX = SectionPos.blockToSectionCoord(minX); - int minSectionY = SectionPos.blockToSectionCoord(minY); - int minSectionZ = SectionPos.blockToSectionCoord(minZ); - int maxSectionX = SectionPos.blockToSectionCoord(maxX); - int maxSectionY = SectionPos.blockToSectionCoord(maxY); - int maxSectionZ = SectionPos.blockToSectionCoord(maxZ); - - for (int sectionX = minSectionX; sectionX <= maxSectionX; sectionX++) { - for (int sectionY = minSectionY; sectionY <= maxSectionY; sectionY++) { - for (int sectionZ = minSectionZ; sectionZ <= maxSectionZ; sectionZ++) { - consumer.accept(SectionPos.asLong(sectionX, sectionY, sectionZ)); - } - } - } - } -} diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/vertex/AbstractVertexView.java b/common/src/lib/java/dev/engine_room/flywheel/lib/vertex/AbstractVertexView.java index 19a07ec1d..b6752ee17 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/vertex/AbstractVertexView.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/vertex/AbstractVertexView.java @@ -1,10 +1,5 @@ package dev.engine_room.flywheel.lib.vertex; -import org.lwjgl.system.MemoryUtil; - -import dev.engine_room.flywheel.api.vertex.MutableVertexList; -import dev.engine_room.flywheel.api.vertex.VertexView; - public abstract class AbstractVertexView implements VertexView { protected long ptr; protected int vertexCount; @@ -28,37 +23,4 @@ public abstract class AbstractVertexView implements VertexView { public void vertexCount(int vertexCount) { this.vertexCount = vertexCount; } - - @Override - public void write(MutableVertexList dst, int srcIndex, int dstIndex) { - if (dst.getClass() == getClass()) { - long stride = stride(); - long dstPtr = ((AbstractVertexView) dst).ptr; - MemoryUtil.memCopy(ptr + srcIndex * stride, dstPtr + dstIndex * stride, stride); - } else { - VertexView.super.write(dst, srcIndex, dstIndex); - } - } - - @Override - public void write(MutableVertexList dst, int srcStartIndex, int dstStartIndex, int vertexCount) { - if (dst.getClass() == getClass()) { - long stride = stride(); - long dstPtr = ((AbstractVertexView) dst).ptr; - MemoryUtil.memCopy(ptr + srcStartIndex * stride, dstPtr + dstStartIndex * stride, vertexCount * stride); - } else { - VertexView.super.write(dst, srcStartIndex, dstStartIndex, vertexCount); - } - } - - @Override - public void writeAll(MutableVertexList dst) { - if (dst.getClass() == getClass()) { - long stride = stride(); - long dstPtr = ((AbstractVertexView) dst).ptr; - MemoryUtil.memCopy(ptr, dstPtr, Math.min(vertexCount, dst.vertexCount()) * stride); - } else { - VertexView.super.writeAll(dst); - } - } } diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/vertex/EmptyVertexList.java b/common/src/lib/java/dev/engine_room/flywheel/lib/vertex/DefaultVertexList.java similarity index 96% rename from common/src/lib/java/dev/engine_room/flywheel/lib/vertex/EmptyVertexList.java rename to common/src/lib/java/dev/engine_room/flywheel/lib/vertex/DefaultVertexList.java index 171ad10e6..b6361854b 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/vertex/EmptyVertexList.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/vertex/DefaultVertexList.java @@ -4,7 +4,7 @@ import dev.engine_room.flywheel.api.vertex.MutableVertexList; import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.texture.OverlayTexture; -public interface EmptyVertexList extends MutableVertexList { +public interface DefaultVertexList extends MutableVertexList { @Override default float x(int index) { return 0.0f; diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/vertex/FullVertexView.java b/common/src/lib/java/dev/engine_room/flywheel/lib/vertex/FullVertexView.java index 31aa4efaa..661ff1395 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/vertex/FullVertexView.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/vertex/FullVertexView.java @@ -2,7 +2,7 @@ package dev.engine_room.flywheel.lib.vertex; import org.lwjgl.system.MemoryUtil; -import dev.engine_room.flywheel.lib.math.RenderMath; +import dev.engine_room.flywheel.lib.math.DataPacker; public class FullVertexView extends AbstractVertexView { public static final long STRIDE = 36; @@ -29,22 +29,22 @@ public class FullVertexView extends AbstractVertexView { @Override public float r(int index) { - return RenderMath.uf(MemoryUtil.memGetByte(ptr + index * STRIDE + 12)); + return DataPacker.unpackNormU8(MemoryUtil.memGetByte(ptr + index * STRIDE + 12)); } @Override public float g(int index) { - return RenderMath.uf(MemoryUtil.memGetByte(ptr + index * STRIDE + 13)); + return DataPacker.unpackNormU8(MemoryUtil.memGetByte(ptr + index * STRIDE + 13)); } @Override public float b(int index) { - return RenderMath.uf(MemoryUtil.memGetByte(ptr + index * STRIDE + 14)); + return DataPacker.unpackNormU8(MemoryUtil.memGetByte(ptr + index * STRIDE + 14)); } @Override public float a(int index) { - return RenderMath.uf(MemoryUtil.memGetByte(ptr + index * STRIDE + 15)); + return DataPacker.unpackNormU8(MemoryUtil.memGetByte(ptr + index * STRIDE + 15)); } @Override @@ -69,17 +69,17 @@ public class FullVertexView extends AbstractVertexView { @Override public float normalX(int index) { - return RenderMath.f(MemoryUtil.memGetByte(ptr + index * STRIDE + 32)); + return DataPacker.unpackNormI8(MemoryUtil.memGetByte(ptr + index * STRIDE + 32)); } @Override public float normalY(int index) { - return RenderMath.f(MemoryUtil.memGetByte(ptr + index * STRIDE + 33)); + return DataPacker.unpackNormI8(MemoryUtil.memGetByte(ptr + index * STRIDE + 33)); } @Override public float normalZ(int index) { - return RenderMath.f(MemoryUtil.memGetByte(ptr + index * STRIDE + 34)); + return DataPacker.unpackNormI8(MemoryUtil.memGetByte(ptr + index * STRIDE + 34)); } @Override @@ -99,22 +99,22 @@ public class FullVertexView extends AbstractVertexView { @Override public void r(int index, float r) { - MemoryUtil.memPutByte(ptr + index * STRIDE + 12, RenderMath.unb(r)); + MemoryUtil.memPutByte(ptr + index * STRIDE + 12, DataPacker.packNormU8(r)); } @Override public void g(int index, float g) { - MemoryUtil.memPutByte(ptr + index * STRIDE + 13, RenderMath.unb(g)); + MemoryUtil.memPutByte(ptr + index * STRIDE + 13, DataPacker.packNormU8(g)); } @Override public void b(int index, float b) { - MemoryUtil.memPutByte(ptr + index * STRIDE + 14, RenderMath.unb(b)); + MemoryUtil.memPutByte(ptr + index * STRIDE + 14, DataPacker.packNormU8(b)); } @Override public void a(int index, float a) { - MemoryUtil.memPutByte(ptr + index * STRIDE + 15, RenderMath.unb(a)); + MemoryUtil.memPutByte(ptr + index * STRIDE + 15, DataPacker.packNormU8(a)); } @Override @@ -139,16 +139,16 @@ public class FullVertexView extends AbstractVertexView { @Override public void normalX(int index, float normalX) { - MemoryUtil.memPutByte(ptr + index * STRIDE + 32, RenderMath.nb(normalX)); + MemoryUtil.memPutByte(ptr + index * STRIDE + 32, DataPacker.packNormI8(normalX)); } @Override public void normalY(int index, float normalY) { - MemoryUtil.memPutByte(ptr + index * STRIDE + 33, RenderMath.nb(normalY)); + MemoryUtil.memPutByte(ptr + index * STRIDE + 33, DataPacker.packNormI8(normalY)); } @Override public void normalZ(int index, float normalZ) { - MemoryUtil.memPutByte(ptr + index * STRIDE + 34, RenderMath.nb(normalZ)); + MemoryUtil.memPutByte(ptr + index * STRIDE + 34, DataPacker.packNormI8(normalZ)); } } diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/vertex/NoOverlayVertexView.java b/common/src/lib/java/dev/engine_room/flywheel/lib/vertex/NoOverlayVertexView.java index 6bcdb7201..ed3ac8cd6 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/vertex/NoOverlayVertexView.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/vertex/NoOverlayVertexView.java @@ -2,9 +2,9 @@ package dev.engine_room.flywheel.lib.vertex; import org.lwjgl.system.MemoryUtil; -import dev.engine_room.flywheel.lib.math.RenderMath; +import dev.engine_room.flywheel.lib.math.DataPacker; -public class NoOverlayVertexView extends AbstractVertexView implements EmptyVertexList { +public class NoOverlayVertexView extends AbstractVertexView implements DefaultVertexList { public static final long STRIDE = 31; @Override @@ -29,22 +29,22 @@ public class NoOverlayVertexView extends AbstractVertexView implements EmptyVert @Override public float r(int index) { - return RenderMath.uf(MemoryUtil.memGetByte(ptr + index * STRIDE + 12)); + return DataPacker.unpackNormU8(MemoryUtil.memGetByte(ptr + index * STRIDE + 12)); } @Override public float g(int index) { - return RenderMath.uf(MemoryUtil.memGetByte(ptr + index * STRIDE + 13)); + return DataPacker.unpackNormU8(MemoryUtil.memGetByte(ptr + index * STRIDE + 13)); } @Override public float b(int index) { - return RenderMath.uf(MemoryUtil.memGetByte(ptr + index * STRIDE + 14)); + return DataPacker.unpackNormU8(MemoryUtil.memGetByte(ptr + index * STRIDE + 14)); } @Override public float a(int index) { - return RenderMath.uf(MemoryUtil.memGetByte(ptr + index * STRIDE + 15)); + return DataPacker.unpackNormU8(MemoryUtil.memGetByte(ptr + index * STRIDE + 15)); } @Override @@ -64,17 +64,17 @@ public class NoOverlayVertexView extends AbstractVertexView implements EmptyVert @Override public float normalX(int index) { - return RenderMath.f(MemoryUtil.memGetByte(ptr + index * STRIDE + 28)); + return DataPacker.unpackNormI8(MemoryUtil.memGetByte(ptr + index * STRIDE + 28)); } @Override public float normalY(int index) { - return RenderMath.f(MemoryUtil.memGetByte(ptr + index * STRIDE + 29)); + return DataPacker.unpackNormI8(MemoryUtil.memGetByte(ptr + index * STRIDE + 29)); } @Override public float normalZ(int index) { - return RenderMath.f(MemoryUtil.memGetByte(ptr + index * STRIDE + 30)); + return DataPacker.unpackNormI8(MemoryUtil.memGetByte(ptr + index * STRIDE + 30)); } @Override @@ -94,22 +94,22 @@ public class NoOverlayVertexView extends AbstractVertexView implements EmptyVert @Override public void r(int index, float r) { - MemoryUtil.memPutByte(ptr + index * STRIDE + 12, RenderMath.unb(r)); + MemoryUtil.memPutByte(ptr + index * STRIDE + 12, DataPacker.packNormU8(r)); } @Override public void g(int index, float g) { - MemoryUtil.memPutByte(ptr + index * STRIDE + 13, RenderMath.unb(g)); + MemoryUtil.memPutByte(ptr + index * STRIDE + 13, DataPacker.packNormU8(g)); } @Override public void b(int index, float b) { - MemoryUtil.memPutByte(ptr + index * STRIDE + 14, RenderMath.unb(b)); + MemoryUtil.memPutByte(ptr + index * STRIDE + 14, DataPacker.packNormU8(b)); } @Override public void a(int index, float a) { - MemoryUtil.memPutByte(ptr + index * STRIDE + 15, RenderMath.unb(a)); + MemoryUtil.memPutByte(ptr + index * STRIDE + 15, DataPacker.packNormU8(a)); } @Override @@ -129,16 +129,16 @@ public class NoOverlayVertexView extends AbstractVertexView implements EmptyVert @Override public void normalX(int index, float normalX) { - MemoryUtil.memPutByte(ptr + index * STRIDE + 28, RenderMath.nb(normalX)); + MemoryUtil.memPutByte(ptr + index * STRIDE + 28, DataPacker.packNormI8(normalX)); } @Override public void normalY(int index, float normalY) { - MemoryUtil.memPutByte(ptr + index * STRIDE + 29, RenderMath.nb(normalY)); + MemoryUtil.memPutByte(ptr + index * STRIDE + 29, DataPacker.packNormI8(normalY)); } @Override public void normalZ(int index, float normalZ) { - MemoryUtil.memPutByte(ptr + index * STRIDE + 30, RenderMath.nb(normalZ)); + MemoryUtil.memPutByte(ptr + index * STRIDE + 30, DataPacker.packNormI8(normalZ)); } } diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/vertex/PosTexNormalVertexView.java b/common/src/lib/java/dev/engine_room/flywheel/lib/vertex/PosTexNormalVertexView.java index d864fec06..c50aa8ca1 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/vertex/PosTexNormalVertexView.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/vertex/PosTexNormalVertexView.java @@ -2,9 +2,9 @@ package dev.engine_room.flywheel.lib.vertex; import org.lwjgl.system.MemoryUtil; -import dev.engine_room.flywheel.lib.math.RenderMath; +import dev.engine_room.flywheel.lib.math.DataPacker; -public class PosTexNormalVertexView extends AbstractVertexView implements EmptyVertexList { +public class PosTexNormalVertexView extends AbstractVertexView implements DefaultVertexList { public static final long STRIDE = 23; @Override @@ -39,17 +39,17 @@ public class PosTexNormalVertexView extends AbstractVertexView implements EmptyV @Override public float normalX(int index) { - return RenderMath.f(MemoryUtil.memGetByte(ptr + index * STRIDE + 20)); + return DataPacker.unpackNormI8(MemoryUtil.memGetByte(ptr + index * STRIDE + 20)); } @Override public float normalY(int index) { - return RenderMath.f(MemoryUtil.memGetByte(ptr + index * STRIDE + 21)); + return DataPacker.unpackNormI8(MemoryUtil.memGetByte(ptr + index * STRIDE + 21)); } @Override public float normalZ(int index) { - return RenderMath.f(MemoryUtil.memGetByte(ptr + index * STRIDE + 22)); + return DataPacker.unpackNormI8(MemoryUtil.memGetByte(ptr + index * STRIDE + 22)); } @Override @@ -79,16 +79,16 @@ public class PosTexNormalVertexView extends AbstractVertexView implements EmptyV @Override public void normalX(int index, float normalX) { - MemoryUtil.memPutByte(ptr + index * STRIDE + 20, RenderMath.nb(normalX)); + MemoryUtil.memPutByte(ptr + index * STRIDE + 20, DataPacker.packNormI8(normalX)); } @Override public void normalY(int index, float normalY) { - MemoryUtil.memPutByte(ptr + index * STRIDE + 21, RenderMath.nb(normalY)); + MemoryUtil.memPutByte(ptr + index * STRIDE + 21, DataPacker.packNormI8(normalY)); } @Override public void normalZ(int index, float normalZ) { - MemoryUtil.memPutByte(ptr + index * STRIDE + 22, RenderMath.nb(normalZ)); + MemoryUtil.memPutByte(ptr + index * STRIDE + 22, DataPacker.packNormI8(normalZ)); } } diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/vertex/PosVertexView.java b/common/src/lib/java/dev/engine_room/flywheel/lib/vertex/PosVertexView.java index bdc6aab26..03664cb8f 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/vertex/PosVertexView.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/vertex/PosVertexView.java @@ -2,7 +2,7 @@ package dev.engine_room.flywheel.lib.vertex; import org.lwjgl.system.MemoryUtil; -public class PosVertexView extends AbstractVertexView implements EmptyVertexList { +public class PosVertexView extends AbstractVertexView implements DefaultVertexList { public static final long STRIDE = 12; @Override diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/vertex/VertexView.java b/common/src/lib/java/dev/engine_room/flywheel/lib/vertex/VertexView.java new file mode 100644 index 000000000..1336153cd --- /dev/null +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/vertex/VertexView.java @@ -0,0 +1,61 @@ +package dev.engine_room.flywheel.lib.vertex; + +import org.lwjgl.system.MemoryUtil; + +import dev.engine_room.flywheel.api.vertex.MutableVertexList; +import dev.engine_room.flywheel.lib.memory.MemoryBlock; + +public interface VertexView extends MutableVertexList { + long ptr(); + + void ptr(long ptr); + + void vertexCount(int vertexCount); + + long stride(); + + default void load(MemoryBlock data) { + long bytes = data.size(); + long stride = stride(); + if (bytes % stride != 0) { + throw new IllegalArgumentException("MemoryBlock contains non-whole amount of vertices!"); + } + int vertexCount = (int) (bytes / stride); + + ptr(data.ptr()); + vertexCount(vertexCount); + } + + @Override + default void write(MutableVertexList dst, int srcIndex, int dstIndex) { + if (dst.getClass() == getClass()) { + long stride = stride(); + long dstPtr = ((VertexView) dst).ptr(); + MemoryUtil.memCopy(ptr() + srcIndex * stride, dstPtr + dstIndex * stride, stride); + } else { + MutableVertexList.super.write(dst, srcIndex, dstIndex); + } + } + + @Override + default void write(MutableVertexList dst, int srcStartIndex, int dstStartIndex, int vertexCount) { + if (dst.getClass() == getClass()) { + long stride = stride(); + long dstPtr = ((VertexView) dst).ptr(); + MemoryUtil.memCopy(ptr() + srcStartIndex * stride, dstPtr + dstStartIndex * stride, vertexCount * stride); + } else { + MutableVertexList.super.write(dst, srcStartIndex, dstStartIndex, vertexCount); + } + } + + @Override + default void writeAll(MutableVertexList dst) { + if (dst.getClass() == getClass()) { + long stride = stride(); + long dstPtr = ((VertexView) dst).ptr(); + MemoryUtil.memCopy(ptr(), dstPtr, Math.min(vertexCount(), dst.vertexCount()) * stride); + } else { + MutableVertexList.super.writeAll(dst); + } + } +} diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/visual/AbstractBlockEntityVisual.java b/common/src/lib/java/dev/engine_room/flywheel/lib/visual/AbstractBlockEntityVisual.java index a3fafb59f..a82e08459 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/visual/AbstractBlockEntityVisual.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/visual/AbstractBlockEntityVisual.java @@ -1,6 +1,9 @@ package dev.engine_room.flywheel.lib.visual; +import java.util.Iterator; + import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.UnknownNullability; import org.joml.FrustumIntersection; import dev.engine_room.flywheel.api.visual.BlockEntityVisual; @@ -41,7 +44,7 @@ public abstract class AbstractBlockEntityVisual extends A protected final BlockPos pos; protected final BlockPos visualPos; protected final BlockState blockState; - @Nullable + @UnknownNullability protected SectionCollector lightSections; public AbstractBlockEntityVisual(VisualizationContext ctx, T blockEntity, float partialTick) { @@ -103,4 +106,20 @@ public abstract class AbstractBlockEntityVisual extends A protected void relight(@Nullable FlatLit... instances) { relight(pos, instances); } + + protected void relight(BlockPos pos, Iterator<@Nullable FlatLit> instances) { + FlatLit.relight(LevelRenderer.getLightColor(level, pos), instances); + } + + protected void relight(Iterator<@Nullable FlatLit> instances) { + relight(pos, instances); + } + + protected void relight(BlockPos pos, Iterable<@Nullable FlatLit> instances) { + FlatLit.relight(LevelRenderer.getLightColor(level, pos), instances); + } + + protected void relight(Iterable<@Nullable FlatLit> instances) { + relight(pos, instances); + } } diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/visual/AbstractEntityVisual.java b/common/src/lib/java/dev/engine_room/flywheel/lib/visual/AbstractEntityVisual.java index 0cff1c953..f9aecce1e 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/visual/AbstractEntityVisual.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/visual/AbstractEntityVisual.java @@ -1,10 +1,13 @@ package dev.engine_room.flywheel.lib.visual; +import org.jetbrains.annotations.Nullable; import org.joml.FrustumIntersection; import org.joml.Vector3f; import dev.engine_room.flywheel.api.visual.DynamicVisual; import dev.engine_room.flywheel.api.visual.EntityVisual; +import dev.engine_room.flywheel.api.visual.LightUpdatedVisual; +import dev.engine_room.flywheel.api.visual.ShaderLightVisual; import dev.engine_room.flywheel.api.visual.TickableVisual; import dev.engine_room.flywheel.api.visualization.VisualizationContext; import dev.engine_room.flywheel.api.visualization.VisualizationManager; @@ -23,6 +26,8 @@ import net.minecraft.world.phys.Vec3; *

    *
  • {@link DynamicVisual}
  • *
  • {@link TickableVisual}
  • + *
  • {@link LightUpdatedVisual}
  • + *
  • {@link ShaderLightVisual}
  • *
* See the interfaces' documentation for more information about each one. * @@ -85,7 +90,7 @@ public abstract class AbstractEntityVisual extends AbstractVis return entity.noCulling || visibilityTester.check(frustum); } - protected void relight(float partialTick, FlatLit... instances) { + protected void relight(float partialTick, @Nullable FlatLit... instances) { BlockPos pos = BlockPos.containing(entity.getLightProbePosition(partialTick)); int blockLight = entity.isOnFire() ? 15 : level.getBrightness(LightLayer.BLOCK, pos); int skyLight = level.getBrightness(LightLayer.SKY, pos); diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/visual/SimpleEntityVisual.java b/common/src/lib/java/dev/engine_room/flywheel/lib/visual/ComponentEntityVisual.java similarity index 70% rename from common/src/lib/java/dev/engine_room/flywheel/lib/visual/SimpleEntityVisual.java rename to common/src/lib/java/dev/engine_room/flywheel/lib/visual/ComponentEntityVisual.java index 35bb8b3a5..3d44290c1 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/visual/SimpleEntityVisual.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/visual/ComponentEntityVisual.java @@ -4,12 +4,13 @@ import java.util.ArrayList; import java.util.List; import dev.engine_room.flywheel.api.visualization.VisualizationContext; +import dev.engine_room.flywheel.lib.visual.component.EntityComponent; import net.minecraft.world.entity.Entity; -public class SimpleEntityVisual extends AbstractEntityVisual implements SimpleDynamicVisual { +public class ComponentEntityVisual extends AbstractEntityVisual implements SimpleDynamicVisual { protected final List components = new ArrayList<>(); - public SimpleEntityVisual(VisualizationContext ctx, T entity, float partialTick) { + public ComponentEntityVisual(VisualizationContext ctx, T entity, float partialTick) { super(ctx, entity, partialTick); } diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/visual/EntityComponent.java b/common/src/lib/java/dev/engine_room/flywheel/lib/visual/component/EntityComponent.java similarity index 74% rename from common/src/lib/java/dev/engine_room/flywheel/lib/visual/EntityComponent.java rename to common/src/lib/java/dev/engine_room/flywheel/lib/visual/component/EntityComponent.java index 582ca8b6e..6622393ac 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/visual/EntityComponent.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/visual/component/EntityComponent.java @@ -1,4 +1,4 @@ -package dev.engine_room.flywheel.lib.visual; +package dev.engine_room.flywheel.lib.visual.component; import dev.engine_room.flywheel.api.visual.DynamicVisual; diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/visual/component/FireComponent.java b/common/src/lib/java/dev/engine_room/flywheel/lib/visual/component/FireComponent.java index b80e26a24..13d60a58d 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/visual/component/FireComponent.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/visual/component/FireComponent.java @@ -18,8 +18,7 @@ import dev.engine_room.flywheel.lib.material.SimpleMaterial; import dev.engine_room.flywheel.lib.model.ModelCache; import dev.engine_room.flywheel.lib.model.QuadMesh; import dev.engine_room.flywheel.lib.model.SingleMeshModel; -import dev.engine_room.flywheel.lib.visual.EntityComponent; -import dev.engine_room.flywheel.lib.visual.SmartRecycler; +import dev.engine_room.flywheel.lib.visual.util.SmartRecycler; import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.resources.model.ModelBakery; @@ -29,12 +28,14 @@ import net.minecraft.world.entity.Entity; /** * A component that uses instances to render the fire animation on an entity. */ -public class FireComponent implements EntityComponent { - private static final Material FIRE_MATERIAL = SimpleMaterial.builderOf(Materials.CHUNK_CUTOUT_UNSHADED) +public final class FireComponent implements EntityComponent { + private static final Material FIRE_MATERIAL = SimpleMaterial.builderOf(Materials.CUTOUT_UNSHADED_BLOCK) .backfaceCulling(false) // Disable backface because we want to be able to flip the model. .build(); + // Parameterize by the material instead of the sprite - // because Material#sprite is a surprisingly heavy operation. + // because Material#sprite is a surprisingly heavy operation + // and because sprites are invalidated after a resource reload. private static final ModelCache FIRE_MODELS = new ModelCache<>(texture -> { return new SingleMeshModel(new FireMesh(texture.sprite()), FIRE_MATERIAL); }); @@ -143,15 +144,6 @@ public class FireComponent implements EntityComponent { writeVertex(vertexList, 3, 0.5f, 1.4f, u1, v0); } - @Override - public Vector4fc boundingSphere() { - return BOUNDING_SPHERE; - } - - @Override - public void delete() { - } - // Magic numbers taken from: // net.minecraft.client.renderer.entity.EntityRenderDispatcher#fireVertex private static void writeVertex(MutableVertexList vertexList, int i, float x, float y, float u, float v) { @@ -168,5 +160,10 @@ public class FireComponent implements EntityComponent { vertexList.normalY(i, 1); vertexList.normalZ(i, 0); } + + @Override + public Vector4fc boundingSphere() { + return BOUNDING_SPHERE; + } } } diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/visual/component/HitboxComponent.java b/common/src/lib/java/dev/engine_room/flywheel/lib/visual/component/HitboxComponent.java index 36277dfa9..834410ed5 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/visual/component/HitboxComponent.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/visual/component/HitboxComponent.java @@ -8,16 +8,14 @@ import dev.engine_room.flywheel.api.visualization.VisualizationContext; import dev.engine_room.flywheel.lib.instance.InstanceTypes; import dev.engine_room.flywheel.lib.instance.TransformedInstance; import dev.engine_room.flywheel.lib.model.LineModelBuilder; -import dev.engine_room.flywheel.lib.model.ModelHolder; -import dev.engine_room.flywheel.lib.visual.EntityComponent; -import dev.engine_room.flywheel.lib.visual.SmartRecycler; +import dev.engine_room.flywheel.lib.visual.util.SmartRecycler; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.LightTexture; import net.minecraft.util.Mth; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; -public class HitboxComponent implements EntityComponent { +public final class HitboxComponent implements EntityComponent { // 010------110 // /| /| // / | / | @@ -27,7 +25,7 @@ public class HitboxComponent implements EntityComponent { // | / | / // |/ |/ // 001------101 - private static final ModelHolder BOX = new ModelHolder(() -> LineModelBuilder.withCapacity(12) + private static final Model BOX_MODEL = new LineModelBuilder(12) // Starting from 0, 0, 0 .line(0, 0, 0, 0, 0, 1) .line(0, 0, 0, 0, 1, 0) @@ -44,19 +42,19 @@ public class HitboxComponent implements EntityComponent { .line(1, 1, 0, 1, 1, 1) .line(1, 1, 0, 1, 0, 0) .line(1, 1, 0, 0, 1, 0) - .build()); + .build(); - private static final ModelHolder LINE = new ModelHolder(() -> LineModelBuilder.withCapacity(1) + private static final Model LINE_MODEL = new LineModelBuilder(1) .line(0, 0, 0, 0, 2, 0) - .build()); + .build(); private final VisualizationContext context; private final Entity entity; - private boolean showEyeBox; - private final SmartRecycler recycler; + private boolean showEyeBox; + public HitboxComponent(VisualizationContext context, Entity entity) { this.context = context; this.entity = entity; @@ -74,8 +72,12 @@ public class HitboxComponent implements EntityComponent { return instance; } - public HitboxComponent showEyeBox(boolean renderEyeBox) { - this.showEyeBox = renderEyeBox; + public boolean doesShowEyeBox() { + return showEyeBox; + } + + public HitboxComponent showEyeBox(boolean showEyeBox) { + this.showEyeBox = showEyeBox; return this; } @@ -95,8 +97,8 @@ public class HitboxComponent implements EntityComponent { var bbWidth = entity.getBbWidth(); var bbHeight = entity.getBbHeight(); var bbWidthHalf = bbWidth * 0.5; - recycler.get(BOX.get()) - .loadIdentity() + recycler.get(BOX_MODEL) + .setIdentityTransform() .translate(entityX - bbWidthHalf, entityY, entityZ - bbWidthHalf) .scale(bbWidth, bbHeight, bbWidth) .setChanged(); @@ -105,8 +107,8 @@ public class HitboxComponent implements EntityComponent { // injection for them so we'll need platform specific code. if (showEyeBox) { - recycler.get(BOX.get()) - .loadIdentity() + recycler.get(BOX_MODEL) + .setIdentityTransform() .translate(entityX - bbWidthHalf, entityY + entity.getEyeHeight() - 0.01, entityZ - bbWidthHalf) .scale(bbWidth, 0.02f, bbWidth) .color(255, 0, 0) @@ -115,8 +117,8 @@ public class HitboxComponent implements EntityComponent { var viewVector = entity.getViewVector(context.partialTick()); - recycler.get(LINE.get()) - .loadIdentity() + recycler.get(LINE_MODEL) + .setIdentityTransform() .translate(entityX, entityY + entity.getEyeHeight(), entityZ) .rotate(new Quaternionf().rotateTo(0, 1, 0, (float) viewVector.x, (float) viewVector.y, (float) viewVector.z)) .color(0, 0, 255) diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/visual/component/ShadowComponent.java b/common/src/lib/java/dev/engine_room/flywheel/lib/visual/component/ShadowComponent.java index 337be2128..65a2d8dcd 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/visual/component/ShadowComponent.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/visual/component/ShadowComponent.java @@ -16,8 +16,7 @@ import dev.engine_room.flywheel.lib.instance.ShadowInstance; import dev.engine_room.flywheel.lib.material.SimpleMaterial; import dev.engine_room.flywheel.lib.model.QuadMesh; import dev.engine_room.flywheel.lib.model.SingleMeshModel; -import dev.engine_room.flywheel.lib.visual.EntityComponent; -import dev.engine_room.flywheel.lib.visual.InstanceRecycler; +import dev.engine_room.flywheel.lib.visual.util.InstanceRecycler; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.texture.OverlayTexture; @@ -42,9 +41,10 @@ import net.minecraft.world.phys.shapes.VoxelShape; *
* The shadow will be cast on blocks at most {@code min(radius, 2 * strength)} blocks below the entity.

*/ -public class ShadowComponent implements EntityComponent { +public final class ShadowComponent implements EntityComponent { + private static final ResourceLocation SHADOW_TEXTURE = new ResourceLocation("textures/misc/shadow.png"); private static final Material SHADOW_MATERIAL = SimpleMaterial.builder() - .texture(new ResourceLocation("textures/misc/shadow.png")) + .texture(SHADOW_TEXTURE) .mipmap(false) .polygonOffset(true) // vanilla shadows use "view offset" but this seems to work fine .transparency(Transparency.TRANSLUCENT) @@ -245,15 +245,6 @@ public class ShadowComponent implements EntityComponent { writeVertex(vertexList, 3, 1, 0); } - @Override - public Vector4fc boundingSphere() { - return BOUNDING_SPHERE; - } - - @Override - public void delete() { - } - // Magic numbers taken from: // net.minecraft.client.renderer.entity.EntityRenderDispatcher#shadowVertex private static void writeVertex(MutableVertexList vertexList, int i, float x, float z) { @@ -271,5 +262,10 @@ public class ShadowComponent implements EntityComponent { vertexList.normalY(i, 1); vertexList.normalZ(i, 0); } + + @Override + public Vector4fc boundingSphere() { + return BOUNDING_SPHERE; + } } } diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/visual/InstanceRecycler.java b/common/src/lib/java/dev/engine_room/flywheel/lib/visual/util/InstanceRecycler.java similarity index 94% rename from common/src/lib/java/dev/engine_room/flywheel/lib/visual/InstanceRecycler.java rename to common/src/lib/java/dev/engine_room/flywheel/lib/visual/util/InstanceRecycler.java index cdfa6a4aa..b4cb490aa 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/visual/InstanceRecycler.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/visual/util/InstanceRecycler.java @@ -1,4 +1,4 @@ -package dev.engine_room.flywheel.lib.visual; +package dev.engine_room.flywheel.lib.visual.util; import java.util.ArrayList; import java.util.List; @@ -14,11 +14,9 @@ import dev.engine_room.flywheel.api.instance.Instance; * * @param The type of instance to recycle. */ -public class InstanceRecycler { +public final class InstanceRecycler { private final Supplier factory; - private final List instances = new ArrayList<>(); - private int count; public InstanceRecycler(Supplier factory) { diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/visual/SmartRecycler.java b/common/src/lib/java/dev/engine_room/flywheel/lib/visual/util/SmartRecycler.java similarity index 87% rename from common/src/lib/java/dev/engine_room/flywheel/lib/visual/SmartRecycler.java rename to common/src/lib/java/dev/engine_room/flywheel/lib/visual/util/SmartRecycler.java index 574976b77..f82f2774f 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/visual/SmartRecycler.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/visual/util/SmartRecycler.java @@ -1,4 +1,4 @@ -package dev.engine_room.flywheel.lib.visual; +package dev.engine_room.flywheel.lib.visual.util; import java.util.HashMap; import java.util.Map; @@ -6,7 +6,7 @@ import java.util.function.Function; import dev.engine_room.flywheel.api.instance.Instance; -public class SmartRecycler { +public final class SmartRecycler { private final Function factory; private final Map> recyclers = new HashMap<>(); diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/visual/SimpleBlockEntityVisualizer.java b/common/src/lib/java/dev/engine_room/flywheel/lib/visualization/SimpleBlockEntityVisualizer.java similarity index 88% rename from common/src/lib/java/dev/engine_room/flywheel/lib/visual/SimpleBlockEntityVisualizer.java rename to common/src/lib/java/dev/engine_room/flywheel/lib/visualization/SimpleBlockEntityVisualizer.java index c80d2fbb9..6a82041aa 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/visual/SimpleBlockEntityVisualizer.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/visualization/SimpleBlockEntityVisualizer.java @@ -1,4 +1,4 @@ -package dev.engine_room.flywheel.lib.visual; +package dev.engine_room.flywheel.lib.visualization; import java.util.Objects; import java.util.function.Predicate; @@ -13,9 +13,9 @@ import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; -public class SimpleBlockEntityVisualizer implements BlockEntityVisualizer { - protected Factory visualFactory; - protected Predicate skipVanillaRender; +public final class SimpleBlockEntityVisualizer implements BlockEntityVisualizer { + private final Factory visualFactory; + private final Predicate skipVanillaRender; public SimpleBlockEntityVisualizer(Factory visualFactory, Predicate skipVanillaRender) { this.visualFactory = visualFactory; @@ -53,12 +53,12 @@ public class SimpleBlockEntityVisualizer implements Block * * @param The type of the block entity. */ - public static class Builder { - protected BlockEntityType type; + public static final class Builder { + private final BlockEntityType type; @Nullable - protected Factory visualFactory; + private Factory visualFactory; @Nullable - protected Predicate skipVanillaRender; + private Predicate skipVanillaRender; public Builder(BlockEntityType type) { this.type = type; diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/visual/SimpleEntityVisualizer.java b/common/src/lib/java/dev/engine_room/flywheel/lib/visualization/SimpleEntityVisualizer.java similarity index 88% rename from common/src/lib/java/dev/engine_room/flywheel/lib/visual/SimpleEntityVisualizer.java rename to common/src/lib/java/dev/engine_room/flywheel/lib/visualization/SimpleEntityVisualizer.java index a5bd479ca..86e1832ea 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/visual/SimpleEntityVisualizer.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/visualization/SimpleEntityVisualizer.java @@ -1,4 +1,4 @@ -package dev.engine_room.flywheel.lib.visual; +package dev.engine_room.flywheel.lib.visualization; import java.util.Objects; import java.util.function.Predicate; @@ -13,9 +13,9 @@ import net.minecraft.client.renderer.entity.EntityRenderer; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; -public class SimpleEntityVisualizer implements EntityVisualizer { - protected Factory visualFactory; - protected Predicate skipVanillaRender; +public final class SimpleEntityVisualizer implements EntityVisualizer { + private final Factory visualFactory; + private final Predicate skipVanillaRender; public SimpleEntityVisualizer(Factory visualFactory, Predicate skipVanillaRender) { this.visualFactory = visualFactory; @@ -53,12 +53,12 @@ public class SimpleEntityVisualizer implements EntityVisualize * * @param The type of the entity. */ - public static class Builder { - protected EntityType type; + public static final class Builder { + private final EntityType type; @Nullable - protected Factory visualFactory; + private Factory visualFactory; @Nullable - protected Predicate skipVanillaRender; + private Predicate skipVanillaRender; public Builder(EntityType type) { this.type = type; diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/visual/VisualizationHelper.java b/common/src/lib/java/dev/engine_room/flywheel/lib/visualization/VisualizationHelper.java similarity index 62% rename from common/src/lib/java/dev/engine_room/flywheel/lib/visual/VisualizationHelper.java rename to common/src/lib/java/dev/engine_room/flywheel/lib/visualization/VisualizationHelper.java index b76f3107c..8b8f79860 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/visual/VisualizationHelper.java +++ b/common/src/lib/java/dev/engine_room/flywheel/lib/visualization/VisualizationHelper.java @@ -1,7 +1,9 @@ -package dev.engine_room.flywheel.lib.visual; +package dev.engine_room.flywheel.lib.visualization; import org.jetbrains.annotations.Nullable; +import dev.engine_room.flywheel.api.visual.Effect; +import dev.engine_room.flywheel.api.visual.Visual; import dev.engine_room.flywheel.api.visualization.BlockEntityVisualizer; import dev.engine_room.flywheel.api.visualization.EntityVisualizer; import dev.engine_room.flywheel.api.visualization.VisualizationManager; @@ -16,6 +18,65 @@ public final class VisualizationHelper { private VisualizationHelper() { } + public static void queueAdd(Effect effect) { + VisualizationManager manager = VisualizationManager.get(effect.level()); + if (manager == null) { + return; + } + + manager.effects().queueAdd(effect); + } + + public static void queueRemove(Effect effect) { + VisualizationManager manager = VisualizationManager.get(effect.level()); + if (manager == null) { + return; + } + + manager.effects().queueRemove(effect); + } + + /** + * Call this when you want to run {@link Visual#update}. + * @param blockEntity The block entity whose visual you want to update. + */ + public static void queueUpdate(BlockEntity blockEntity) { + Level level = blockEntity.getLevel(); + VisualizationManager manager = VisualizationManager.get(level); + if (manager == null) { + return; + } + + manager.blockEntities().queueUpdate(blockEntity); + } + + /** + * Call this when you want to run {@link Visual#update}. + * @param entity The entity whose visual you want to update. + */ + public static void queueUpdate(Entity entity) { + Level level = entity.level(); + VisualizationManager manager = VisualizationManager.get(level); + if (manager == null) { + return; + } + + manager.entities().queueUpdate(entity); + } + + /** + * Call this when you want to run {@link Visual#update}. + * @param effect The effect whose visual you want to update. + */ + public static void queueUpdate(Effect effect) { + VisualizationManager manager = VisualizationManager.get(effect.level()); + if (manager == null) { + return; + } + + manager.effects().queueUpdate(effect); + } + @SuppressWarnings("unchecked") @Nullable public static BlockEntityVisualizer getVisualizer(T blockEntity) { @@ -54,7 +115,7 @@ public final class VisualizationHelper { * @param The type of the block entity. * @return {@code true} if the block entity is visualized and should not be rendered normally. */ - public static boolean shouldSkipRender(T blockEntity) { + public static boolean skipVanillaRender(T blockEntity) { BlockEntityVisualizer visualizer = getVisualizer(blockEntity); if (visualizer == null) { return false; @@ -68,7 +129,7 @@ public final class VisualizationHelper { * @param The type of the entity. * @return {@code true} if the entity is visualized and should not be rendered normally. */ - public static boolean shouldSkipRender(T entity) { + public static boolean skipVanillaRender(T entity) { EntityVisualizer visualizer = getVisualizer(entity); if (visualizer == null) { return false; @@ -88,8 +149,7 @@ public final class VisualizationHelper { return false; } - manager.getBlockEntities().queueAdd(blockEntity); - + manager.blockEntities().queueAdd(blockEntity); return visualizer.skipVanillaRender(blockEntity); } } diff --git a/common/src/main/java/dev/engine_room/flywheel/impl/BackendManagerImpl.java b/common/src/main/java/dev/engine_room/flywheel/impl/BackendManagerImpl.java index 012eb01ee..bd2ae4a78 100644 --- a/common/src/main/java/dev/engine_room/flywheel/impl/BackendManagerImpl.java +++ b/common/src/main/java/dev/engine_room/flywheel/impl/BackendManagerImpl.java @@ -1,7 +1,5 @@ package dev.engine_room.flywheel.impl; -import org.jetbrains.annotations.Nullable; - import dev.engine_room.flywheel.api.Flywheel; import dev.engine_room.flywheel.api.backend.Backend; import dev.engine_room.flywheel.backend.Backends; @@ -25,7 +23,7 @@ public final class BackendManagerImpl { private BackendManagerImpl() { } - public static Backend getBackend() { + public static Backend currentBackend() { return backend; } @@ -70,11 +68,8 @@ public final class BackendManagerImpl { VisualizationManagerImpl.resetAll(); } - public static void onReloadLevelRenderer(@Nullable ClientLevel level) { + public static void onReloadLevelRenderer(ClientLevel level) { chooseBackend(); - - if (level != null) { - VisualizationManagerImpl.reset(level); - } + VisualizationManagerImpl.reset(level); } } diff --git a/common/src/main/java/dev/engine_room/flywheel/impl/FlwApiLinkImpl.java b/common/src/main/java/dev/engine_room/flywheel/impl/FlwApiLinkImpl.java index c7e6e8899..297f43fdc 100644 --- a/common/src/main/java/dev/engine_room/flywheel/impl/FlwApiLinkImpl.java +++ b/common/src/main/java/dev/engine_room/flywheel/impl/FlwApiLinkImpl.java @@ -33,8 +33,8 @@ public class FlwApiLinkImpl implements FlwApiLink { } @Override - public Backend getBackend() { - return BackendManagerImpl.getBackend(); + public Backend getCurrentBackend() { + return BackendManagerImpl.currentBackend(); } @Override diff --git a/common/src/main/java/dev/engine_room/flywheel/impl/FlwDebugInfo.java b/common/src/main/java/dev/engine_room/flywheel/impl/FlwDebugInfo.java index 5f4b61c60..86e21d5ea 100644 --- a/common/src/main/java/dev/engine_room/flywheel/impl/FlwDebugInfo.java +++ b/common/src/main/java/dev/engine_room/flywheel/impl/FlwDebugInfo.java @@ -24,13 +24,13 @@ public final class FlwDebugInfo { VisualizationManager manager = VisualizationManager.get(minecraft.level); if (manager != null) { - systemInfo.add("B: " + manager.getBlockEntities().getVisualCount() - + ", E: " + manager.getEntities().getVisualCount() - + ", F: " + manager.getEffects().getVisualCount()); - Vec3i renderOrigin = manager.getRenderOrigin(); + systemInfo.add("B: " + manager.blockEntities().visualCount() + + ", E: " + manager.entities().visualCount() + + ", F: " + manager.effects().visualCount()); + Vec3i renderOrigin = manager.renderOrigin(); systemInfo.add("Origin: " + renderOrigin.getX() + ", " + renderOrigin.getY() + ", " + renderOrigin.getZ()); } - systemInfo.add("Memory Usage: CPU: " + StringUtil.formatBytes(FlwMemoryTracker.getCPUMemory()) + ", GPU: " + StringUtil.formatBytes(FlwMemoryTracker.getGPUMemory())); + systemInfo.add("Memory Usage: CPU: " + StringUtil.formatBytes(FlwMemoryTracker.getCpuMemory()) + ", GPU: " + StringUtil.formatBytes(FlwMemoryTracker.getGpuMemory())); } } diff --git a/common/src/main/java/dev/engine_room/flywheel/impl/FlwImplXplat.java b/common/src/main/java/dev/engine_room/flywheel/impl/FlwImplXplat.java index 3a2a927cb..13675de93 100644 --- a/common/src/main/java/dev/engine_room/flywheel/impl/FlwImplXplat.java +++ b/common/src/main/java/dev/engine_room/flywheel/impl/FlwImplXplat.java @@ -1,20 +1,12 @@ package dev.engine_room.flywheel.impl; -import org.jetbrains.annotations.Nullable; - -import dev.engine_room.flywheel.api.event.RenderContext; -import dev.engine_room.flywheel.api.event.RenderStage; import dev.engine_room.flywheel.api.internal.DependencyInjection; import net.minecraft.client.multiplayer.ClientLevel; public interface FlwImplXplat { FlwImplXplat INSTANCE = DependencyInjection.load(FlwImplXplat.class, "dev.engine_room.flywheel.impl.FlwImplXplatImpl"); - void dispatchBeginFrameEvent(RenderContext context); - - void dispatchReloadLevelRendererEvent(@Nullable ClientLevel level); - - void dispatchRenderStageEvent(RenderContext context, RenderStage stage); + void dispatchReloadLevelRendererEvent(ClientLevel level); String getVersionStr(); diff --git a/common/src/main/java/dev/engine_room/flywheel/impl/event/RenderContextImpl.java b/common/src/main/java/dev/engine_room/flywheel/impl/event/RenderContextImpl.java index a211307ea..1ee538a73 100644 --- a/common/src/main/java/dev/engine_room/flywheel/impl/event/RenderContextImpl.java +++ b/common/src/main/java/dev/engine_room/flywheel/impl/event/RenderContextImpl.java @@ -1,17 +1,18 @@ package dev.engine_room.flywheel.impl.event; import org.joml.Matrix4f; +import org.joml.Matrix4fc; import com.mojang.blaze3d.vertex.PoseStack; -import dev.engine_room.flywheel.api.event.RenderContext; +import dev.engine_room.flywheel.api.RenderContext; import net.minecraft.client.Camera; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.renderer.LevelRenderer; import net.minecraft.client.renderer.RenderBuffers; public record RenderContextImpl(LevelRenderer renderer, ClientLevel level, RenderBuffers buffers, PoseStack stack, - Matrix4f projection, Matrix4f viewProjection, Camera camera, + Matrix4fc projection, Matrix4fc viewProjection, Camera camera, float partialTick) implements RenderContext { public static RenderContextImpl create(LevelRenderer renderer, ClientLevel level, RenderBuffers buffers, PoseStack stack, Matrix4f projection, Camera camera, float partialTick) { Matrix4f viewProjection = new Matrix4f(projection); diff --git a/common/src/main/java/dev/engine_room/flywheel/impl/mixin/ClientChunkCacheMixin.java b/common/src/main/java/dev/engine_room/flywheel/impl/mixin/ClientChunkCacheMixin.java index f55d6d2e9..41bb31c01 100644 --- a/common/src/main/java/dev/engine_room/flywheel/impl/mixin/ClientChunkCacheMixin.java +++ b/common/src/main/java/dev/engine_room/flywheel/impl/mixin/ClientChunkCacheMixin.java @@ -24,7 +24,7 @@ abstract class ClientChunkCacheMixin { var manager = VisualizationManagerImpl.get(level); if (manager != null) { - manager.onLightUpdate(pos.asLong()); + manager.onLightUpdate(pos, layer); } } } diff --git a/common/src/main/java/dev/engine_room/flywheel/impl/mixin/ClientLevelMixin.java b/common/src/main/java/dev/engine_room/flywheel/impl/mixin/ClientLevelMixin.java index 556e4869f..10270b497 100644 --- a/common/src/main/java/dev/engine_room/flywheel/impl/mixin/ClientLevelMixin.java +++ b/common/src/main/java/dev/engine_room/flywheel/impl/mixin/ClientLevelMixin.java @@ -10,7 +10,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import com.google.common.collect.Lists; import dev.engine_room.flywheel.api.visualization.VisualizationManager; -import dev.engine_room.flywheel.lib.visual.VisualizationHelper; +import dev.engine_room.flywheel.lib.visualization.VisualizationHelper; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.world.entity.Entity; @@ -25,7 +25,7 @@ abstract class ClientLevelMixin { Iterable entities = cir.getReturnValue(); ArrayList filtered = Lists.newArrayList(entities); - filtered.removeIf(VisualizationHelper::shouldSkipRender); + filtered.removeIf(VisualizationHelper::skipVanillaRender); cir.setReturnValue(filtered); } diff --git a/common/src/main/java/dev/engine_room/flywheel/impl/mixin/LevelRendererMixin.java b/common/src/main/java/dev/engine_room/flywheel/impl/mixin/LevelRendererMixin.java index 9cbcf2790..2e259c04f 100644 --- a/common/src/main/java/dev/engine_room/flywheel/impl/mixin/LevelRendererMixin.java +++ b/common/src/main/java/dev/engine_room/flywheel/impl/mixin/LevelRendererMixin.java @@ -4,7 +4,6 @@ import java.util.SortedSet; import org.jetbrains.annotations.Nullable; import org.joml.Matrix4f; -import org.objectweb.asm.Opcodes; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -17,10 +16,9 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import com.mojang.blaze3d.vertex.PoseStack; -import dev.engine_room.flywheel.api.event.RenderStage; +import dev.engine_room.flywheel.api.visualization.VisualizationManager; import dev.engine_room.flywheel.impl.FlwImplXplat; import dev.engine_room.flywheel.impl.event.RenderContextImpl; -import dev.engine_room.flywheel.impl.visualization.VisualizationManagerImpl; import it.unimi.dsi.fastutil.longs.Long2ObjectMap; import net.minecraft.client.Camera; import net.minecraft.client.multiplayer.ClientLevel; @@ -53,7 +51,10 @@ abstract class LevelRendererMixin { private void flywheel$beginRender(PoseStack poseStack, float partialTick, long finishNanoTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightTexture lightTexture, Matrix4f projectionMatrix, CallbackInfo ci) { flywheel$renderContext = RenderContextImpl.create((LevelRenderer) (Object) this, level, renderBuffers, poseStack, projectionMatrix, camera, partialTick); - FlwImplXplat.INSTANCE.dispatchBeginFrameEvent(flywheel$renderContext); + VisualizationManager manager = VisualizationManager.get(level); + if (manager != null) { + manager.renderDispatcher().onStartLevelRender(flywheel$renderContext); + } } @Inject(method = "renderLevel", at = @At("RETURN")) @@ -62,65 +63,61 @@ abstract class LevelRendererMixin { } @Inject(method = "allChanged", at = @At("RETURN")) - private void flywheel$refresh(CallbackInfo ci) { - FlwImplXplat.INSTANCE.dispatchReloadLevelRendererEvent(level); - } - - @Inject(method = "renderLevel", at = @At(value = "INVOKE_STRING", target = "Lnet/minecraft/util/profiling/ProfilerFiller;popPush(Ljava/lang/String;)V", args = "ldc=destroyProgress")) - private void flywheel$beforeRenderCrumbling(CallbackInfo ci) { - if (flywheel$renderContext == null) { - return; - } - - var manager = VisualizationManagerImpl.get(level); - if (manager != null) { - manager.renderCrumbling(flywheel$renderContext, destructionProgress); - } - } - - // STAGE DISPATCHING - - @Unique - private void flywheel$dispatch(RenderStage stage) { - if (flywheel$renderContext != null) { - FlwImplXplat.INSTANCE.dispatchRenderStageEvent(flywheel$renderContext, stage); + private void flywheel$reload(CallbackInfo ci) { + if (level != null) { + FlwImplXplat.INSTANCE.dispatchReloadLevelRendererEvent(level); } } @Inject(method = "renderLevel", at = @At(value = "INVOKE_STRING", target = "Lnet/minecraft/util/profiling/ProfilerFiller;popPush(Ljava/lang/String;)V", args = "ldc=blockentities")) - private void flywheel$onStage$beforeBlockEntities(CallbackInfo ci) { - flywheel$dispatch(RenderStage.AFTER_ENTITIES); + private void flywheel$beforeBlockEntities(CallbackInfo ci) { + if (flywheel$renderContext != null) { + VisualizationManager manager = VisualizationManager.get(level); + if (manager != null) { + manager.renderDispatcher().afterEntities(flywheel$renderContext); + } + } } @Inject(method = "renderLevel", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/OutlineBufferSource;endOutlineBatch()V", ordinal = 0)) - private void flywheel$onStage$afterSolidBlockEntities(CallbackInfo ci) { - flywheel$dispatch(RenderStage.AFTER_BLOCK_ENTITIES); + private void flywheel$afterBlockEntities(CallbackInfo ci) { + if (flywheel$renderContext != null) { + VisualizationManager manager = VisualizationManager.get(level); + if (manager != null) { + manager.renderDispatcher().afterBlockEntities(flywheel$renderContext); + } + } } - @Inject(method = "renderLevel", at = @At(value = "FIELD", target = "Lnet/minecraft/client/renderer/LevelRenderer;particlesTarget:Lcom/mojang/blaze3d/pipeline/RenderTarget;", opcode = Opcodes.GETFIELD, ordinal = 0)) - private void flywheel$onStage$afterTranslucentTerrain$fabulous(CallbackInfo ci) { - flywheel$dispatch(RenderStage.AFTER_TRANSLUCENT_TERRAIN); + @Inject(method = "renderLevel", at = @At(value = "INVOKE_STRING", target = "Lnet/minecraft/util/profiling/ProfilerFiller;popPush(Ljava/lang/String;)V", args = "ldc=destroyProgress")) + private void flywheel$beforeRenderCrumbling(CallbackInfo ci) { + if (flywheel$renderContext != null) { + VisualizationManager manager = VisualizationManager.get(level); + if (manager != null) { + manager.renderDispatcher().beforeCrumbling(flywheel$renderContext, destructionProgress); + } + } } - @Inject(method = "renderLevel", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/LevelRenderer;renderChunkLayer(Lnet/minecraft/client/renderer/RenderType;Lcom/mojang/blaze3d/vertex/PoseStack;DDDLorg/joml/Matrix4f;)V", ordinal = 6, shift = Shift.AFTER)) - private void flywheel$onStage$afterTranslucentTerrain(CallbackInfo ci) { - flywheel$dispatch(RenderStage.AFTER_TRANSLUCENT_TERRAIN); - } - - @Group(name = "onStage$afterParticles", min = 2, max = 2) + @Group(name = "afterParticles", min = 2, max = 2) @Inject(method = "renderLevel", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/particle/ParticleEngine;render(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource$BufferSource;Lnet/minecraft/client/renderer/LightTexture;Lnet/minecraft/client/Camera;F)V", shift = Shift.AFTER)) - private void flywheel$onStage$afterParticles$fabric(CallbackInfo ci) { - flywheel$dispatch(RenderStage.AFTER_PARTICLES); + private void flywheel$afterParticles$fabric(CallbackInfo ci) { + if (flywheel$renderContext != null) { + VisualizationManager manager = VisualizationManager.get(level); + if (manager != null) { + manager.renderDispatcher().afterParticles(flywheel$renderContext); + } + } } - @Group(name = "onStage$afterParticles") + @Group(name = "afterParticles") @Inject(method = "renderLevel", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/particle/ParticleEngine;render(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource$BufferSource;Lnet/minecraft/client/renderer/LightTexture;Lnet/minecraft/client/Camera;FLnet/minecraft/client/renderer/culling/Frustum;)V", shift = Shift.AFTER)) - private void flywheel$onStage$afterParticles$forge(CallbackInfo ci) { - flywheel$dispatch(RenderStage.AFTER_PARTICLES); - } - - @Inject(method = "renderLevel", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/LevelRenderer;renderSnowAndRain(Lnet/minecraft/client/renderer/LightTexture;FDDD)V", shift = Shift.AFTER)) - private void flywheel$onStage$afterWeather(CallbackInfo ci) { - flywheel$dispatch(RenderStage.AFTER_WEATHER); + private void flywheel$afterParticles$forge(CallbackInfo ci) { + if (flywheel$renderContext != null) { + VisualizationManager manager = VisualizationManager.get(level); + if (manager != null) { + manager.renderDispatcher().afterParticles(flywheel$renderContext); + } + } } } diff --git a/common/src/main/java/dev/engine_room/flywheel/impl/mixin/visualmanage/BlockEntityMixin.java b/common/src/main/java/dev/engine_room/flywheel/impl/mixin/visualmanage/BlockEntityMixin.java index 0f0945629..5d6ae99ef 100644 --- a/common/src/main/java/dev/engine_room/flywheel/impl/mixin/visualmanage/BlockEntityMixin.java +++ b/common/src/main/java/dev/engine_room/flywheel/impl/mixin/visualmanage/BlockEntityMixin.java @@ -24,6 +24,6 @@ abstract class BlockEntityMixin { return; } - manager.getBlockEntities().queueRemove((BlockEntity) (Object) this); + manager.blockEntities().queueRemove((BlockEntity) (Object) this); } } diff --git a/common/src/main/java/dev/engine_room/flywheel/impl/mixin/visualmanage/LevelChunkMixin.java b/common/src/main/java/dev/engine_room/flywheel/impl/mixin/visualmanage/LevelChunkMixin.java index 8b4c297e6..8fc45f82b 100644 --- a/common/src/main/java/dev/engine_room/flywheel/impl/mixin/visualmanage/LevelChunkMixin.java +++ b/common/src/main/java/dev/engine_room/flywheel/impl/mixin/visualmanage/LevelChunkMixin.java @@ -26,6 +26,6 @@ abstract class LevelChunkMixin { return; } - manager.getBlockEntities().queueAdd(blockEntity); + manager.blockEntities().queueAdd(blockEntity); } } diff --git a/common/src/main/java/dev/engine_room/flywheel/impl/mixin/visualmanage/LevelRendererMixin.java b/common/src/main/java/dev/engine_room/flywheel/impl/mixin/visualmanage/LevelRendererMixin.java index 6ecbbc75f..53f390096 100644 --- a/common/src/main/java/dev/engine_room/flywheel/impl/mixin/visualmanage/LevelRendererMixin.java +++ b/common/src/main/java/dev/engine_room/flywheel/impl/mixin/visualmanage/LevelRendererMixin.java @@ -33,7 +33,7 @@ abstract class LevelRendererMixin { return; } - var blockEntities = manager.getBlockEntities(); + var blockEntities = manager.blockEntities(); if (oldState != newState) { blockEntities.queueRemove(blockEntity); blockEntities.queueAdd(blockEntity); diff --git a/common/src/main/java/dev/engine_room/flywheel/impl/mixin/visualmanage/RebuildTaskMixin.java b/common/src/main/java/dev/engine_room/flywheel/impl/mixin/visualmanage/RebuildTaskMixin.java index c55c532fa..89546e170 100644 --- a/common/src/main/java/dev/engine_room/flywheel/impl/mixin/visualmanage/RebuildTaskMixin.java +++ b/common/src/main/java/dev/engine_room/flywheel/impl/mixin/visualmanage/RebuildTaskMixin.java @@ -6,7 +6,7 @@ import org.spongepowered.asm.mixin.injection.Coerce; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import dev.engine_room.flywheel.lib.visual.VisualizationHelper; +import dev.engine_room.flywheel.lib.visualization.VisualizationHelper; import net.minecraft.world.level.block.entity.BlockEntity; @Mixin(targets = "net.minecraft.client.renderer.chunk.ChunkRenderDispatcher$RenderChunk$RebuildTask") diff --git a/common/src/main/java/dev/engine_room/flywheel/impl/registry/IdRegistryImpl.java b/common/src/main/java/dev/engine_room/flywheel/impl/registry/IdRegistryImpl.java index 528668789..3ea57ea30 100644 --- a/common/src/main/java/dev/engine_room/flywheel/impl/registry/IdRegistryImpl.java +++ b/common/src/main/java/dev/engine_room/flywheel/impl/registry/IdRegistryImpl.java @@ -3,10 +3,9 @@ package dev.engine_room.flywheel.impl.registry; import java.util.Collection; import java.util.Iterator; import java.util.Set; -import java.util.function.Consumer; import org.jetbrains.annotations.Nullable; -import org.jetbrains.annotations.Unmodifiable; +import org.jetbrains.annotations.UnmodifiableView; import dev.engine_room.flywheel.api.registry.IdRegistry; import it.unimi.dsi.fastutil.objects.Object2ReferenceMap; @@ -14,7 +13,6 @@ import it.unimi.dsi.fastutil.objects.Object2ReferenceMaps; import it.unimi.dsi.fastutil.objects.Object2ReferenceOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import it.unimi.dsi.fastutil.objects.ObjectList; -import it.unimi.dsi.fastutil.objects.ObjectLists; import it.unimi.dsi.fastutil.objects.ObjectSet; import it.unimi.dsi.fastutil.objects.ObjectSets; import it.unimi.dsi.fastutil.objects.Reference2ObjectMap; @@ -31,7 +29,6 @@ public class IdRegistryImpl implements IdRegistry { private final Reference2ObjectMap reverseMap = Reference2ObjectMaps.synchronize(new Reference2ObjectOpenHashMap<>()); private final ObjectSet keysView = ObjectSets.unmodifiable(map.keySet()); private final ReferenceCollection valuesView = ReferenceCollections.unmodifiable(map.values()); - private final ObjectList>> freezeCallbacks = ObjectLists.synchronize(new ObjectArrayList<>()); private boolean frozen; public IdRegistryImpl() { @@ -90,25 +87,17 @@ public class IdRegistryImpl implements IdRegistry { } @Override - @Unmodifiable + @UnmodifiableView public Set getAllIds() { return keysView; } @Override - @Unmodifiable + @UnmodifiableView public Collection getAll() { return valuesView; } - @Override - public void addFreezeCallback(Consumer> callback) { - if (frozen) { - throw new IllegalStateException("Cannot add freeze callback to frozen registry!"); - } - freezeCallbacks.add(callback); - } - @Override public boolean isFrozen() { return frozen; @@ -119,12 +108,8 @@ public class IdRegistryImpl implements IdRegistry { return getAll().iterator(); } - public void freeze() { + private void freeze() { frozen = true; - for (var callback : freezeCallbacks) { - callback.accept(this); - } - freezeCallbacks.clear(); } public static void freezeAll() { diff --git a/common/src/main/java/dev/engine_room/flywheel/impl/registry/RegistryImpl.java b/common/src/main/java/dev/engine_room/flywheel/impl/registry/RegistryImpl.java index c6b6db1a2..df9ad6eb9 100644 --- a/common/src/main/java/dev/engine_room/flywheel/impl/registry/RegistryImpl.java +++ b/common/src/main/java/dev/engine_room/flywheel/impl/registry/RegistryImpl.java @@ -2,14 +2,12 @@ package dev.engine_room.flywheel.impl.registry; import java.util.Iterator; import java.util.Set; -import java.util.function.Consumer; -import org.jetbrains.annotations.Unmodifiable; +import org.jetbrains.annotations.UnmodifiableView; import dev.engine_room.flywheel.api.registry.Registry; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import it.unimi.dsi.fastutil.objects.ObjectList; -import it.unimi.dsi.fastutil.objects.ObjectLists; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import it.unimi.dsi.fastutil.objects.ObjectSet; import it.unimi.dsi.fastutil.objects.ObjectSets; @@ -19,7 +17,6 @@ public class RegistryImpl implements Registry { private final ObjectSet set = ObjectSets.synchronize(new ObjectOpenHashSet<>()); private final ObjectSet setView = ObjectSets.unmodifiable(set); - private final ObjectList>> freezeCallbacks = ObjectLists.synchronize(new ObjectArrayList<>()); private boolean frozen; public RegistryImpl() { @@ -44,19 +41,11 @@ public class RegistryImpl implements Registry { } @Override - @Unmodifiable + @UnmodifiableView public Set getAll() { return setView; } - @Override - public void addFreezeCallback(Consumer> callback) { - if (frozen) { - throw new IllegalStateException("Cannot add freeze callback to frozen registry!"); - } - freezeCallbacks.add(callback); - } - @Override public boolean isFrozen() { return frozen; @@ -67,12 +56,8 @@ public class RegistryImpl implements Registry { return getAll().iterator(); } - public void freeze() { + private void freeze() { frozen = true; - for (var callback : freezeCallbacks) { - callback.accept(this); - } - freezeCallbacks.clear(); } public static void freezeAll() { diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/task/Flag.java b/common/src/main/java/dev/engine_room/flywheel/impl/task/Flag.java similarity index 66% rename from common/src/lib/java/dev/engine_room/flywheel/lib/task/Flag.java rename to common/src/main/java/dev/engine_room/flywheel/impl/task/Flag.java index ffbffbebe..e726f84c9 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/task/Flag.java +++ b/common/src/main/java/dev/engine_room/flywheel/impl/task/Flag.java @@ -1,16 +1,26 @@ -package dev.engine_room.flywheel.lib.task; +package dev.engine_room.flywheel.impl.task; import java.util.concurrent.atomic.AtomicBoolean; +import org.jetbrains.annotations.Nullable; + /** * A flag that can be raised and lowered in a thread-safe fashion. *
- * Useful when combined with {@link RaisePlan} and {@link dev.engine_room.flywheel.api.task.TaskExecutor#syncUntil TaskExecutor.syncUntil}. + * Useful when combined with {@link RaisePlan}. */ -public class Flag { - +public final class Flag { private final AtomicBoolean raised = new AtomicBoolean(false); + @Nullable + private final String name; + public Flag(@Nullable String name) { + this.name = name; + } + + public Flag() { + this(null); + } /** * Raise this flag indicating a key point in execution. @@ -47,4 +57,14 @@ public class Flag { public boolean isLowered() { return !isRaised(); } + + @Nullable + public String name() { + return name; + } + + @Override + public String toString() { + return "Flag[" + "name=" + name + ']'; + } } diff --git a/common/src/main/java/dev/engine_room/flywheel/impl/task/FlwTaskExecutor.java b/common/src/main/java/dev/engine_room/flywheel/impl/task/FlwTaskExecutor.java index 491b1f371..6a5cacd25 100644 --- a/common/src/main/java/dev/engine_room/flywheel/impl/task/FlwTaskExecutor.java +++ b/common/src/main/java/dev/engine_room/flywheel/impl/task/FlwTaskExecutor.java @@ -3,9 +3,6 @@ package dev.engine_room.flywheel.impl.task; import org.apache.commons.lang3.concurrent.AtomicSafeInitializer; import org.apache.commons.lang3.concurrent.ConcurrentUtils; -import com.mojang.blaze3d.systems.RenderSystem; - -import dev.engine_room.flywheel.api.task.TaskExecutor; import dev.engine_room.flywheel.impl.FlwConfig; import net.minecraft.util.Mth; @@ -19,7 +16,7 @@ public final class FlwTaskExecutor { * Get a thread pool for running Flywheel related work in parallel. * @return A global Flywheel thread pool. */ - public static TaskExecutor get() { + public static TaskExecutorImpl get() { return ConcurrentUtils.initializeUnchecked(INITIALIZER); } @@ -35,10 +32,9 @@ public final class FlwTaskExecutor { .availableProcessors(); } - - private static class Initializer extends AtomicSafeInitializer { + private static class Initializer extends AtomicSafeInitializer { @Override - protected TaskExecutor initialize() { + protected TaskExecutorImpl initialize() { int threadCount = FlwConfig.INSTANCE .workerThreads(); @@ -50,7 +46,7 @@ public final class FlwTaskExecutor { threadCount = Mth.clamp(threadCount, 1, getMaxThreadCount()); } - ParallelTaskExecutor executor = new ParallelTaskExecutor("Flywheel", threadCount, RenderSystem::isOnRenderThread); + ParallelTaskExecutor executor = new ParallelTaskExecutor("Flywheel", threadCount); executor.startWorkers(); return executor; } diff --git a/common/src/main/java/dev/engine_room/flywheel/impl/task/ParallelTaskExecutor.java b/common/src/main/java/dev/engine_room/flywheel/impl/task/ParallelTaskExecutor.java index 6df75cc2c..6b4e304ed 100644 --- a/common/src/main/java/dev/engine_room/flywheel/impl/task/ParallelTaskExecutor.java +++ b/common/src/main/java/dev/engine_room/flywheel/impl/task/ParallelTaskExecutor.java @@ -3,24 +3,19 @@ package dev.engine_room.flywheel.impl.task; import java.util.ArrayList; import java.util.Deque; import java.util.List; -import java.util.Queue; import java.util.concurrent.ConcurrentLinkedDeque; -import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.BooleanSupplier; -import dev.engine_room.flywheel.api.task.TaskExecutor; import dev.engine_room.flywheel.impl.FlwImpl; import net.minecraft.util.Mth; // https://github.com/CaffeineMC/sodium-fabric/blob/5d364ed5ba63f9067fcf72a078ca310bff4db3e9/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/compile/ChunkBuilder.java // https://stackoverflow.com/questions/29655531 -public class ParallelTaskExecutor implements TaskExecutor { +public class ParallelTaskExecutor implements TaskExecutorImpl { private final String name; private final int threadCount; - private final BooleanSupplier mainThreadQuery; - /** * If set to false, the executor will shut down. */ @@ -28,13 +23,11 @@ public class ParallelTaskExecutor implements TaskExecutor { private final List threads = new ArrayList<>(); private final Deque taskQueue = new ConcurrentLinkedDeque<>(); - private final Queue mainThreadQueue = new ConcurrentLinkedQueue<>(); private final ThreadGroupNotifier taskNotifier = new ThreadGroupNotifier(); private final WaitGroup waitGroup = new WaitGroup(); - public ParallelTaskExecutor(String name, int threadCount, BooleanSupplier mainThreadQuery) { + public ParallelTaskExecutor(String name, int threadCount) { this.name = name; - this.mainThreadQuery = mainThreadQuery; this.threadCount = threadCount; } @@ -94,7 +87,6 @@ public class ParallelTaskExecutor implements TaskExecutor { threads.clear(); taskQueue.clear(); - mainThreadQueue.clear(); waitGroup._reset(); } @@ -110,37 +102,8 @@ public class ParallelTaskExecutor implements TaskExecutor { taskNotifier.postNotification(); } - @Override - public void scheduleForMainThread(Runnable runnable) { - if (!running.get()) { - throw new IllegalStateException("Executor is stopped"); - } - - mainThreadQueue.add(runnable); - } - - @Override - public boolean isMainThread() { - return mainThreadQuery.getAsBoolean(); - } - - /** - * Wait for all running tasks to finish. - */ - @Override - public void syncPoint() { - boolean onMainThread = isMainThread(); - while (true) { - if (syncOneTask(onMainThread)) { - // Done! Nothing left to do. - return; - } - } - } - @Override public boolean syncUntil(BooleanSupplier cond) { - boolean onMainThread = isMainThread(); while (true) { if (cond.getAsBoolean()) { // The condition is already true! @@ -148,7 +111,7 @@ public class ParallelTaskExecutor implements TaskExecutor { return true; } - if (syncOneTask(onMainThread)) { + if (syncOneTask()) { // Out of tasks entirely. // The condition may have flipped though so return its result. return cond.getAsBoolean(); @@ -156,10 +119,8 @@ public class ParallelTaskExecutor implements TaskExecutor { } } - @Override public boolean syncWhile(BooleanSupplier cond) { - boolean onMainThread = isMainThread(); while (true) { if (!cond.getAsBoolean()) { // The condition is already false! @@ -167,7 +128,7 @@ public class ParallelTaskExecutor implements TaskExecutor { return true; } - if (syncOneTask(onMainThread)) { + if (syncOneTask()) { // Out of tasks entirely. // The condition may have flipped though so return its result. return !cond.getAsBoolean(); @@ -175,40 +136,22 @@ public class ParallelTaskExecutor implements TaskExecutor { } } - /** - * Attempt to process a single task. - * - * @param mainThread Whether this is being called from the main thread or not. - * @return {@code true} if the executor has nothing left to do. - */ - private boolean syncOneTask(boolean mainThread) { - return mainThread ? syncOneTaskMainThread() : syncOneTaskOffThread(); - } - - private boolean syncOneTaskMainThread() { - Runnable task; - if ((task = mainThreadQueue.poll()) != null) { - // Prioritize main thread tasks. - processMainThreadTask(task); - - // Check again next loop. - return false; - } else if ((task = taskQueue.pollLast()) != null) { - // Nothing in the mainThreadQueue, work on tasks from the normal queue. - processTask(task); - - // Check again next loop. - return false; - } else { - // Nothing right now, wait for the other threads to finish. - boolean done = waitGroup.await(10_000); - // If we timed-out tasks may have been added to the queue, so check again. - // if they didn't, we're done. - return done && mainThreadQueue.isEmpty(); + @Override + public void syncPoint() { + while (true) { + if (syncOneTask()) { + // Done! Nothing left to do. + return; + } } } - private boolean syncOneTaskOffThread() { + /** + * Attempt to process a single task. + * + * @return {@code true} if the executor has nothing left to do. + */ + private boolean syncOneTask() { Runnable task; if ((task = taskQueue.pollLast()) != null) { // then work on tasks from the queue. @@ -233,14 +176,6 @@ public class ParallelTaskExecutor implements TaskExecutor { } } - private void processMainThreadTask(Runnable task) { - try { - task.run(); - } catch (Exception e) { - FlwImpl.LOGGER.error("Error running main thread task", e); - } - } - private class WorkerThread extends Thread { public WorkerThread(String name) { super(name); diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/task/RaisePlan.java b/common/src/main/java/dev/engine_room/flywheel/impl/task/RaisePlan.java similarity index 77% rename from common/src/lib/java/dev/engine_room/flywheel/lib/task/RaisePlan.java rename to common/src/main/java/dev/engine_room/flywheel/impl/task/RaisePlan.java index b8692200a..0ee995358 100644 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/task/RaisePlan.java +++ b/common/src/main/java/dev/engine_room/flywheel/impl/task/RaisePlan.java @@ -1,6 +1,7 @@ -package dev.engine_room.flywheel.lib.task; +package dev.engine_room.flywheel.impl.task; import dev.engine_room.flywheel.api.task.TaskExecutor; +import dev.engine_room.flywheel.lib.task.SimplyComposedPlan; public record RaisePlan(Flag flag) implements SimplyComposedPlan { public static RaisePlan raise(Flag flag) { diff --git a/common/src/main/java/dev/engine_room/flywheel/impl/task/SerialTaskExecutor.java b/common/src/main/java/dev/engine_room/flywheel/impl/task/SerialTaskExecutor.java index 15fec1462..1eaffdff3 100644 --- a/common/src/main/java/dev/engine_room/flywheel/impl/task/SerialTaskExecutor.java +++ b/common/src/main/java/dev/engine_room/flywheel/impl/task/SerialTaskExecutor.java @@ -2,26 +2,20 @@ package dev.engine_room.flywheel.impl.task; import java.util.function.BooleanSupplier; -import dev.engine_room.flywheel.api.task.TaskExecutor; - -public class SerialTaskExecutor implements TaskExecutor { +public class SerialTaskExecutor implements TaskExecutorImpl { public static final SerialTaskExecutor INSTANCE = new SerialTaskExecutor(); private SerialTaskExecutor() { } @Override - public void execute(Runnable task) { - task.run(); - } - - @Override - public void scheduleForMainThread(Runnable runnable) { + public void execute(Runnable runnable) { runnable.run(); } @Override - public void syncPoint() { + public int threadCount() { + return 1; } @Override @@ -35,12 +29,6 @@ public class SerialTaskExecutor implements TaskExecutor { } @Override - public int threadCount() { - return 1; - } - - @Override - public boolean isMainThread() { - return true; + public void syncPoint() { } } diff --git a/common/src/main/java/dev/engine_room/flywheel/impl/task/TaskExecutorImpl.java b/common/src/main/java/dev/engine_room/flywheel/impl/task/TaskExecutorImpl.java new file mode 100644 index 000000000..99eda8aa4 --- /dev/null +++ b/common/src/main/java/dev/engine_room/flywheel/impl/task/TaskExecutorImpl.java @@ -0,0 +1,41 @@ +package dev.engine_room.flywheel.impl.task; + +import java.util.function.BooleanSupplier; + +import dev.engine_room.flywheel.api.task.TaskExecutor; + +public interface TaskExecutorImpl extends TaskExecutor { + /** + * Wait for running tasks, until the given condition is met + * ({@link BooleanSupplier#getAsBoolean()} returns {@code true}). + *
+ * This method is equivalent to {@code syncWhile(() -> !cond.getAsBoolean())}. + * + * @param cond The condition to wait for. + * @return {@code true} if the condition is met. {@code false} if + * this executor runs out of tasks before the condition is met. + */ + boolean syncUntil(BooleanSupplier cond); + + /** + * Wait for running tasks, so long as the given condition is met + * ({@link BooleanSupplier#getAsBoolean()} returns {@code true}). + *
+ * If this method is called on the + *
+ * This method is equivalent to {@code syncUntil(() -> !cond.getAsBoolean())}. + * + * @param cond The condition sync on. + * @return {@code true} if the condition is no longer met. {@code false} if + * this executor runs out of tasks while the condition is still met. + */ + boolean syncWhile(BooleanSupplier cond); + + /** + * Wait for all running tasks to finish. + *
+ * This is useful as a nuclear option, but most of the time you should + * try to use {@link #syncUntil(BooleanSupplier) syncUntil}. + */ + void syncPoint(); +} diff --git a/common/src/main/java/dev/engine_room/flywheel/impl/visualization/ratelimit/BandedPrimeLimiter.java b/common/src/main/java/dev/engine_room/flywheel/impl/visual/BandedPrimeLimiter.java similarity index 91% rename from common/src/main/java/dev/engine_room/flywheel/impl/visualization/ratelimit/BandedPrimeLimiter.java rename to common/src/main/java/dev/engine_room/flywheel/impl/visual/BandedPrimeLimiter.java index 37678eb00..f52c16f45 100644 --- a/common/src/main/java/dev/engine_room/flywheel/impl/visualization/ratelimit/BandedPrimeLimiter.java +++ b/common/src/main/java/dev/engine_room/flywheel/impl/visual/BandedPrimeLimiter.java @@ -1,4 +1,4 @@ -package dev.engine_room.flywheel.impl.visualization.ratelimit; +package dev.engine_room.flywheel.impl.visual; import net.minecraft.util.Mth; diff --git a/common/src/main/java/dev/engine_room/flywheel/impl/visualization/ratelimit/DistanceUpdateLimiterImpl.java b/common/src/main/java/dev/engine_room/flywheel/impl/visual/DistanceUpdateLimiterImpl.java similarity index 76% rename from common/src/main/java/dev/engine_room/flywheel/impl/visualization/ratelimit/DistanceUpdateLimiterImpl.java rename to common/src/main/java/dev/engine_room/flywheel/impl/visual/DistanceUpdateLimiterImpl.java index f6d43cdb4..6f760ac21 100644 --- a/common/src/main/java/dev/engine_room/flywheel/impl/visualization/ratelimit/DistanceUpdateLimiterImpl.java +++ b/common/src/main/java/dev/engine_room/flywheel/impl/visual/DistanceUpdateLimiterImpl.java @@ -1,4 +1,4 @@ -package dev.engine_room.flywheel.impl.visualization.ratelimit; +package dev.engine_room.flywheel.impl.visual; import dev.engine_room.flywheel.api.visual.DistanceUpdateLimiter; diff --git a/common/src/main/java/dev/engine_room/flywheel/impl/visualization/ratelimit/NonLimiter.java b/common/src/main/java/dev/engine_room/flywheel/impl/visual/NonLimiter.java similarity index 74% rename from common/src/main/java/dev/engine_room/flywheel/impl/visualization/ratelimit/NonLimiter.java rename to common/src/main/java/dev/engine_room/flywheel/impl/visual/NonLimiter.java index 690fe4f09..8450a8c0a 100644 --- a/common/src/main/java/dev/engine_room/flywheel/impl/visualization/ratelimit/NonLimiter.java +++ b/common/src/main/java/dev/engine_room/flywheel/impl/visual/NonLimiter.java @@ -1,4 +1,4 @@ -package dev.engine_room.flywheel.impl.visualization.ratelimit; +package dev.engine_room.flywheel.impl.visual; public class NonLimiter implements DistanceUpdateLimiterImpl { @Override diff --git a/common/src/main/java/dev/engine_room/flywheel/impl/visualization/manager/VisualManagerImpl.java b/common/src/main/java/dev/engine_room/flywheel/impl/visualization/VisualManagerImpl.java similarity index 96% rename from common/src/main/java/dev/engine_room/flywheel/impl/visualization/manager/VisualManagerImpl.java rename to common/src/main/java/dev/engine_room/flywheel/impl/visualization/VisualManagerImpl.java index f0d3420bb..f65e081c1 100644 --- a/common/src/main/java/dev/engine_room/flywheel/impl/visualization/manager/VisualManagerImpl.java +++ b/common/src/main/java/dev/engine_room/flywheel/impl/visualization/VisualManagerImpl.java @@ -1,4 +1,4 @@ -package dev.engine_room.flywheel.impl.visualization.manager; +package dev.engine_room.flywheel.impl.visualization; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; @@ -26,7 +26,7 @@ public class VisualManagerImpl> implements VisualManager } @Override - public int getVisualCount() { + public int visualCount() { return getStorage().getAllVisuals() .size(); } diff --git a/common/src/main/java/dev/engine_room/flywheel/impl/visualization/VisualizationEventHandler.java b/common/src/main/java/dev/engine_room/flywheel/impl/visualization/VisualizationEventHandler.java index 07aa71c67..ab102e6d6 100644 --- a/common/src/main/java/dev/engine_room/flywheel/impl/visualization/VisualizationEventHandler.java +++ b/common/src/main/java/dev/engine_room/flywheel/impl/visualization/VisualizationEventHandler.java @@ -1,10 +1,7 @@ package dev.engine_room.flywheel.impl.visualization; -import dev.engine_room.flywheel.api.event.RenderContext; -import dev.engine_room.flywheel.api.event.RenderStage; import dev.engine_room.flywheel.api.visualization.VisualizationManager; import net.minecraft.client.Minecraft; -import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.Level; @@ -26,33 +23,13 @@ public final class VisualizationEventHandler { manager.tick(); } - public static void onBeginFrame(RenderContext context) { - ClientLevel level = context.level(); - VisualizationManagerImpl manager = VisualizationManagerImpl.get(level); - if (manager == null) { - return; - } - - manager.beginFrame(context); - } - - public static void onRenderStage(RenderContext context, RenderStage stage) { - ClientLevel level = context.level(); - VisualizationManagerImpl manager = VisualizationManagerImpl.get(level); - if (manager == null) { - return; - } - - manager.renderStage(context, stage); - } - public static void onEntityJoinLevel(Level level, Entity entity) { VisualizationManager manager = VisualizationManager.get(level); if (manager == null) { return; } - manager.getEntities().queueAdd(entity); + manager.entities().queueAdd(entity); } public static void onEntityLeaveLevel(Level level, Entity entity) { @@ -61,6 +38,6 @@ public final class VisualizationEventHandler { return; } - manager.getEntities().queueRemove(entity); + manager.entities().queueRemove(entity); } } diff --git a/common/src/main/java/dev/engine_room/flywheel/impl/visualization/VisualizationManagerImpl.java b/common/src/main/java/dev/engine_room/flywheel/impl/visualization/VisualizationManagerImpl.java index ccf69cc0e..2683bcc8d 100644 --- a/common/src/main/java/dev/engine_room/flywheel/impl/visualization/VisualizationManagerImpl.java +++ b/common/src/main/java/dev/engine_room/flywheel/impl/visualization/VisualizationManagerImpl.java @@ -3,55 +3,54 @@ package dev.engine_room.flywheel.impl.visualization; import java.util.ArrayList; import java.util.List; import java.util.SortedSet; -import java.util.function.Supplier; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.Nullable; import org.joml.FrustumIntersection; import org.joml.Matrix4f; +import dev.engine_room.flywheel.api.RenderContext; import dev.engine_room.flywheel.api.backend.BackendManager; import dev.engine_room.flywheel.api.backend.Engine; -import dev.engine_room.flywheel.api.event.RenderContext; -import dev.engine_room.flywheel.api.event.RenderStage; import dev.engine_room.flywheel.api.instance.Instance; import dev.engine_room.flywheel.api.task.Plan; -import dev.engine_room.flywheel.api.task.TaskExecutor; import dev.engine_room.flywheel.api.visual.DynamicVisual; import dev.engine_room.flywheel.api.visual.Effect; import dev.engine_room.flywheel.api.visual.TickableVisual; import dev.engine_room.flywheel.api.visualization.VisualManager; -import dev.engine_room.flywheel.api.visualization.VisualizationContext; +import dev.engine_room.flywheel.api.visualization.VisualType; import dev.engine_room.flywheel.api.visualization.VisualizationLevel; import dev.engine_room.flywheel.api.visualization.VisualizationManager; import dev.engine_room.flywheel.impl.FlwConfig; import dev.engine_room.flywheel.impl.extension.LevelExtension; +import dev.engine_room.flywheel.impl.task.Flag; import dev.engine_room.flywheel.impl.task.FlwTaskExecutor; +import dev.engine_room.flywheel.impl.task.RaisePlan; +import dev.engine_room.flywheel.impl.task.TaskExecutorImpl; +import dev.engine_room.flywheel.impl.visual.BandedPrimeLimiter; +import dev.engine_room.flywheel.impl.visual.DistanceUpdateLimiterImpl; import dev.engine_room.flywheel.impl.visual.DynamicVisualContextImpl; +import dev.engine_room.flywheel.impl.visual.NonLimiter; import dev.engine_room.flywheel.impl.visual.TickableVisualContextImpl; -import dev.engine_room.flywheel.impl.visualization.manager.BlockEntityStorage; -import dev.engine_room.flywheel.impl.visualization.manager.EffectStorage; -import dev.engine_room.flywheel.impl.visualization.manager.EntityStorage; -import dev.engine_room.flywheel.impl.visualization.manager.VisualManagerImpl; -import dev.engine_room.flywheel.impl.visualization.ratelimit.BandedPrimeLimiter; -import dev.engine_room.flywheel.impl.visualization.ratelimit.DistanceUpdateLimiterImpl; -import dev.engine_room.flywheel.impl.visualization.ratelimit.NonLimiter; -import dev.engine_room.flywheel.lib.task.Flag; +import dev.engine_room.flywheel.impl.visualization.storage.BlockEntityStorage; +import dev.engine_room.flywheel.impl.visualization.storage.EffectStorage; +import dev.engine_room.flywheel.impl.visualization.storage.EntityStorage; import dev.engine_room.flywheel.lib.task.IfElsePlan; import dev.engine_room.flywheel.lib.task.MapContextPlan; -import dev.engine_room.flywheel.lib.task.NamedFlag; import dev.engine_room.flywheel.lib.task.NestedPlan; -import dev.engine_room.flywheel.lib.task.RaisePlan; import dev.engine_room.flywheel.lib.task.SimplePlan; import dev.engine_room.flywheel.lib.util.LevelAttached; import it.unimi.dsi.fastutil.longs.Long2ObjectMap; import it.unimi.dsi.fastutil.longs.LongOpenHashSet; import net.minecraft.client.Minecraft; +import net.minecraft.core.BlockPos; +import net.minecraft.core.SectionPos; import net.minecraft.core.Vec3i; import net.minecraft.server.level.BlockDestructionProgress; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.LightLayer; import net.minecraft.world.level.block.entity.BlockEntity; /** @@ -60,40 +59,37 @@ import net.minecraft.world.level.block.entity.BlockEntity; public class VisualizationManagerImpl implements VisualizationManager { private static final LevelAttached MANAGERS = new LevelAttached<>(VisualizationManagerImpl::new, VisualizationManagerImpl::delete); + private final TaskExecutorImpl taskExecutor; private final Engine engine; - private final TaskExecutor taskExecutor; + private final DistanceUpdateLimiterImpl frameLimiter; + private final RenderDispatcherImpl renderDispatcher = new RenderDispatcherImpl(); private final VisualManagerImpl blockEntities; private final VisualManagerImpl entities; private final VisualManagerImpl effects; - private final Plan tickPlan; + private final Flag frameFlag = new Flag("frame"); + private final Flag tickFlag = new Flag("tick"); + private final Plan framePlan; + private final Plan tickPlan; - private final Flag tickFlag = new NamedFlag("tick"); - private final Flag frameVisualsFlag = new NamedFlag("frameVisualUpdates"); - private final Flag frameFlag = new NamedFlag("frameComplete"); - - protected DistanceUpdateLimiterImpl frameLimiter; + private boolean canEngineRender; private VisualizationManagerImpl(LevelAccessor level) { + taskExecutor = FlwTaskExecutor.get(); + engine = BackendManager.currentBackend() + .createEngine(level); frameLimiter = createUpdateLimiter(); - engine = BackendManager.getBackend() - .createEngine(level); - taskExecutor = FlwTaskExecutor.get(); - - var blockEntitiesStorage = new BlockEntityStorage(provider(engine, RenderStage.AFTER_BLOCK_ENTITIES)); - var entitiesStorage = new EntityStorage(provider(engine, RenderStage.AFTER_ENTITIES)); - var effectsStorage = new EffectStorage(provider(engine, RenderStage.AFTER_PARTICLES)); + var blockEntitiesStorage = new BlockEntityStorage(engine.createVisualizationContext(VisualType.BLOCK_ENTITY)); + var entitiesStorage = new EntityStorage(engine.createVisualizationContext(VisualType.ENTITY)); + var effectsStorage = new EffectStorage(engine.createVisualizationContext(VisualType.EFFECT)); blockEntities = new VisualManagerImpl<>(blockEntitiesStorage); entities = new VisualManagerImpl<>(entitiesStorage); effects = new VisualManagerImpl<>(effectsStorage); - tickPlan = NestedPlan.of(blockEntities.tickPlan(), entities.tickPlan(), effects.tickPlan()) - .then(RaisePlan.raise(tickFlag)); - var recreate = SimplePlan.of(context -> blockEntitiesStorage.recreateAll(context.partialTick()), context -> entitiesStorage.recreateAll(context.partialTick()), context -> effectsStorage.recreateAll(context.partialTick())); @@ -114,21 +110,18 @@ public class VisualizationManagerImpl implements VisualizationManager { engine.lightSections(out); } })) - .then(RaisePlan.raise(frameVisualsFlag)) .then(engine.createFramePlan()) .then(RaisePlan.raise(frameFlag)); + tickPlan = NestedPlan.of(blockEntities.tickPlan(), entities.tickPlan(), effects.tickPlan()) + .then(RaisePlan.raise(tickFlag)); + if (level instanceof Level l) { LevelExtension.getAllLoadedEntities(l) .forEach(entities::queueAdd); } } - public static Supplier provider(Engine engine, RenderStage stage) { - var context = engine.createVisualizationContext(stage); - return () -> context; - } - private DynamicVisual.Context createVisualFrameContext(RenderContext ctx) { Vec3i renderOrigin = engine.renderOrigin(); var cameraPos = ctx.camera() @@ -141,7 +134,7 @@ public class VisualizationManagerImpl implements VisualizationManager { return new DynamicVisualContextImpl(ctx.camera(), frustum, ctx.partialTick(), frameLimiter); } - protected DistanceUpdateLimiterImpl createUpdateLimiter() { + private DistanceUpdateLimiterImpl createUpdateLimiter() { if (FlwConfig.INSTANCE .limitUpdates()) { return new BandedPrimeLimiter(); @@ -189,7 +182,7 @@ public class VisualizationManagerImpl implements VisualizationManager { } // TODO: Consider making these reset actions reuse the existing game objects instead of re-adding them - // potentially by keeping the same VisualizationManagerImpl and deleting the engine and visuals but not the game objects + // potentially by keeping the same VisualizationManagerImpl and deleting the engine and visuals but not the game objects public static void reset(LevelAccessor level) { MANAGERS.remove(level); } @@ -199,25 +192,30 @@ public class VisualizationManagerImpl implements VisualizationManager { } @Override - public Vec3i getRenderOrigin() { + public Vec3i renderOrigin() { return engine.renderOrigin(); } @Override - public VisualManager getBlockEntities() { + public VisualManager blockEntities() { return blockEntities; } @Override - public VisualManager getEntities() { + public VisualManager entities() { return entities; } @Override - public VisualManager getEffects() { + public VisualManager effects() { return effects; } + @Override + public RenderDispatcher renderDispatcher() { + return renderDispatcher; + } + /** * Begin execution of the tick plan. */ @@ -235,32 +233,41 @@ public class VisualizationManagerImpl implements VisualizationManager { /** * Begin execution of the frame plan. */ - public void beginFrame(RenderContext context) { + private void beginFrame(RenderContext context) { // Make sure we're done with the last tick. // Note we don't lower here because many frames may happen per tick. taskExecutor.syncUntil(tickFlag::isRaised); - frameVisualsFlag.lower(); frameFlag.lower(); frameLimiter.tick(); + canEngineRender = false; framePlan.execute(taskExecutor, context); } - /** - * Draw all visuals for the given stage. - */ - public void renderStage(RenderContext context, RenderStage stage) { - engine.renderStage(taskExecutor, context, stage); + private void ensureCanRender(RenderContext context) { + taskExecutor.syncUntil(frameFlag::isRaised); + if (!canEngineRender) { + engine.setupRender(context); + canEngineRender = true; + } } - public void renderCrumbling(RenderContext context, Long2ObjectMap> destructionProgress) { + /** + * Draw all visuals of the given type. + */ + private void render(RenderContext context, VisualType visualType) { + ensureCanRender(context); + engine.render(context, visualType); + } + + private void renderCrumbling(RenderContext context, Long2ObjectMap> destructionProgress) { if (destructionProgress.isEmpty()) { return; } - taskExecutor.syncUntil(frameVisualsFlag::isRaised); + ensureCanRender(context); List crumblingBlocks = new ArrayList<>(); @@ -294,24 +301,26 @@ public class VisualizationManagerImpl implements VisualizationManager { var maxDestruction = set.last(); - crumblingBlocks.add(new Engine.CrumblingBlock(maxDestruction.getProgress(), maxDestruction.getPos(), instances)); + crumblingBlocks.add(new CrumblingBlockImpl(maxDestruction.getPos(), maxDestruction.getProgress(), instances)); } if (!crumblingBlocks.isEmpty()) { - engine.renderCrumbling(taskExecutor, context, crumblingBlocks); + engine.renderCrumbling(context, crumblingBlocks); } } - public void onLightUpdate(long section) { - blockEntities.onLightUpdate(section); - entities.onLightUpdate(section); - effects.onLightUpdate(section); + public void onLightUpdate(SectionPos sectionPos, LightLayer layer) { + engine.onLightUpdate(sectionPos, layer); + long longPos = sectionPos.asLong(); + blockEntities.onLightUpdate(longPos); + entities.onLightUpdate(longPos); + effects.onLightUpdate(longPos); } /** * Free all acquired resources and delete this manager. */ - public void delete() { + private void delete() { // Just finish everything. This may include the work of others but that's okay. taskExecutor.syncPoint(); @@ -321,4 +330,34 @@ public class VisualizationManagerImpl implements VisualizationManager { effects.invalidate(); engine.delete(); } + + private class RenderDispatcherImpl implements RenderDispatcher { + @Override + public void onStartLevelRender(RenderContext ctx) { + beginFrame(ctx); + } + + @Override + public void afterBlockEntities(RenderContext ctx) { + render(ctx, VisualType.BLOCK_ENTITY); + } + + @Override + public void afterEntities(RenderContext ctx) { + render(ctx, VisualType.ENTITY); + } + + @Override + public void beforeCrumbling(RenderContext ctx, Long2ObjectMap> destructionProgress) { + renderCrumbling(ctx, destructionProgress); + } + + @Override + public void afterParticles(RenderContext ctx) { + render(ctx, VisualType.EFFECT); + } + } + + private record CrumblingBlockImpl(BlockPos pos, int progress, List instances) implements Engine.CrumblingBlock { + } } diff --git a/common/src/main/java/dev/engine_room/flywheel/impl/visualization/manager/BlockEntityStorage.java b/common/src/main/java/dev/engine_room/flywheel/impl/visualization/storage/BlockEntityStorage.java similarity index 80% rename from common/src/main/java/dev/engine_room/flywheel/impl/visualization/manager/BlockEntityStorage.java rename to common/src/main/java/dev/engine_room/flywheel/impl/visualization/storage/BlockEntityStorage.java index d3d065c5c..fd8d4980f 100644 --- a/common/src/main/java/dev/engine_room/flywheel/impl/visualization/manager/BlockEntityStorage.java +++ b/common/src/main/java/dev/engine_room/flywheel/impl/visualization/storage/BlockEntityStorage.java @@ -1,13 +1,10 @@ -package dev.engine_room.flywheel.impl.visualization.manager; - -import java.util.function.Supplier; +package dev.engine_room.flywheel.impl.visualization.storage; import org.jetbrains.annotations.Nullable; import dev.engine_room.flywheel.api.visual.BlockEntityVisual; import dev.engine_room.flywheel.api.visualization.VisualizationContext; -import dev.engine_room.flywheel.impl.visualization.storage.Storage; -import dev.engine_room.flywheel.lib.visual.VisualizationHelper; +import dev.engine_room.flywheel.lib.visualization.VisualizationHelper; import it.unimi.dsi.fastutil.longs.Long2ObjectMap; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import net.minecraft.core.BlockPos; @@ -18,8 +15,8 @@ import net.minecraft.world.level.block.entity.BlockEntity; public class BlockEntityStorage extends Storage { private final Long2ObjectMap> posLookup = new Long2ObjectOpenHashMap<>(); - public BlockEntityStorage(Supplier visualizationContextSupplier) { - super(visualizationContextSupplier); + public BlockEntityStorage(VisualizationContext visualizationContext) { + super(visualizationContext); } @Nullable @@ -59,7 +56,7 @@ public class BlockEntityStorage extends Storage { return null; } - var visual = visualizer.createVisual(visualizationContextSupplier.get(), obj, partialTick); + var visual = visualizer.createVisual(visualizationContext, obj, partialTick); BlockPos blockPos = obj.getBlockPos(); posLookup.put(blockPos.asLong(), visual); diff --git a/common/src/main/java/dev/engine_room/flywheel/impl/visualization/manager/EffectStorage.java b/common/src/main/java/dev/engine_room/flywheel/impl/visualization/storage/EffectStorage.java similarity index 52% rename from common/src/main/java/dev/engine_room/flywheel/impl/visualization/manager/EffectStorage.java rename to common/src/main/java/dev/engine_room/flywheel/impl/visualization/storage/EffectStorage.java index dbe3e3942..6a8a3c1fd 100644 --- a/common/src/main/java/dev/engine_room/flywheel/impl/visualization/manager/EffectStorage.java +++ b/common/src/main/java/dev/engine_room/flywheel/impl/visualization/storage/EffectStorage.java @@ -1,20 +1,17 @@ -package dev.engine_room.flywheel.impl.visualization.manager; - -import java.util.function.Supplier; +package dev.engine_room.flywheel.impl.visualization.storage; import dev.engine_room.flywheel.api.visual.Effect; import dev.engine_room.flywheel.api.visual.EffectVisual; import dev.engine_room.flywheel.api.visualization.VisualizationContext; -import dev.engine_room.flywheel.impl.visualization.storage.Storage; public class EffectStorage extends Storage { - public EffectStorage(Supplier visualizationContextSupplier) { - super(visualizationContextSupplier); + public EffectStorage(VisualizationContext visualizationContext) { + super(visualizationContext); } @Override protected EffectVisual createRaw(Effect obj, float partialTick) { - return obj.visualize(visualizationContextSupplier.get(), partialTick); + return obj.visualize(visualizationContext, partialTick); } @Override diff --git a/common/src/main/java/dev/engine_room/flywheel/impl/visualization/manager/EntityStorage.java b/common/src/main/java/dev/engine_room/flywheel/impl/visualization/storage/EntityStorage.java similarity index 61% rename from common/src/main/java/dev/engine_room/flywheel/impl/visualization/manager/EntityStorage.java rename to common/src/main/java/dev/engine_room/flywheel/impl/visualization/storage/EntityStorage.java index 5a4cc18e3..56d9446bb 100644 --- a/common/src/main/java/dev/engine_room/flywheel/impl/visualization/manager/EntityStorage.java +++ b/common/src/main/java/dev/engine_room/flywheel/impl/visualization/storage/EntityStorage.java @@ -1,17 +1,14 @@ -package dev.engine_room.flywheel.impl.visualization.manager; - -import java.util.function.Supplier; +package dev.engine_room.flywheel.impl.visualization.storage; import dev.engine_room.flywheel.api.visual.EntityVisual; import dev.engine_room.flywheel.api.visualization.VisualizationContext; -import dev.engine_room.flywheel.impl.visualization.storage.Storage; -import dev.engine_room.flywheel.lib.visual.VisualizationHelper; +import dev.engine_room.flywheel.lib.visualization.VisualizationHelper; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.Level; public class EntityStorage extends Storage { - public EntityStorage(Supplier visualizationContextSupplier) { - super(visualizationContextSupplier); + public EntityStorage(VisualizationContext visualizationContext) { + super(visualizationContext); } @Override @@ -21,7 +18,7 @@ public class EntityStorage extends Storage { return null; } - return visualizer.createVisual(visualizationContextSupplier.get(), obj, partialTick); + return visualizer.createVisual(visualizationContext, obj, partialTick); } @Override diff --git a/common/src/main/java/dev/engine_room/flywheel/impl/visualization/storage/Storage.java b/common/src/main/java/dev/engine_room/flywheel/impl/visualization/storage/Storage.java index bb6fe7fa1..1cc6667a7 100644 --- a/common/src/main/java/dev/engine_room/flywheel/impl/visualization/storage/Storage.java +++ b/common/src/main/java/dev/engine_room/flywheel/impl/visualization/storage/Storage.java @@ -4,7 +4,6 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; -import java.util.function.Supplier; import org.jetbrains.annotations.Nullable; @@ -24,7 +23,7 @@ import dev.engine_room.flywheel.lib.visual.SimpleTickableVisual; import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap; public abstract class Storage { - protected final Supplier visualizationContextSupplier; + protected final VisualizationContext visualizationContext; private final Map visuals = new Reference2ObjectOpenHashMap<>(); protected final PlanMap dynamicVisuals = new PlanMap<>(); @@ -34,8 +33,8 @@ public abstract class Storage { protected final LightUpdatedVisualStorage lightUpdatedVisuals = new LightUpdatedVisualStorage(); protected final ShaderLightVisualStorage shaderLightVisuals = new ShaderLightVisualStorage(); - public Storage(Supplier visualizationContextSupplier) { - this.visualizationContextSupplier = visualizationContextSupplier; + public Storage(VisualizationContext visualizationContext) { + this.visualizationContext = visualizationContext; } public Collection getAllVisuals() { diff --git a/common/src/main/java/dev/engine_room/flywheel/vanilla/BellVisual.java b/common/src/main/java/dev/engine_room/flywheel/vanilla/BellVisual.java index 0b65af807..ad7648c7b 100644 --- a/common/src/main/java/dev/engine_room/flywheel/vanilla/BellVisual.java +++ b/common/src/main/java/dev/engine_room/flywheel/vanilla/BellVisual.java @@ -7,10 +7,11 @@ import org.joml.Quaternionf; import org.joml.Vector3f; import dev.engine_room.flywheel.api.instance.Instance; +import dev.engine_room.flywheel.api.material.Material; import dev.engine_room.flywheel.api.visualization.VisualizationContext; import dev.engine_room.flywheel.lib.instance.InstanceTypes; import dev.engine_room.flywheel.lib.instance.OrientedInstance; -import dev.engine_room.flywheel.lib.material.Materials; +import dev.engine_room.flywheel.lib.material.SimpleMaterial; import dev.engine_room.flywheel.lib.model.ModelHolder; import dev.engine_room.flywheel.lib.model.SingleMeshModel; import dev.engine_room.flywheel.lib.model.part.ModelPartConverter; @@ -22,8 +23,12 @@ import net.minecraft.util.Mth; import net.minecraft.world.level.block.entity.BellBlockEntity; public class BellVisual extends AbstractBlockEntityVisual implements SimpleDynamicVisual { + private static final Material MATERIAL = SimpleMaterial.builder() + .mipmap(false) + .build(); + private static final ModelHolder BELL_MODEL = new ModelHolder(() -> { - return new SingleMeshModel(ModelPartConverter.convert(ModelLayers.BELL, BellRenderer.BELL_RESOURCE_LOCATION.sprite(), "bell_body"), Materials.BELL); + return new SingleMeshModel(ModelPartConverter.convert(ModelLayers.BELL, BellRenderer.BELL_RESOURCE_LOCATION.sprite(), "bell_body"), MATERIAL); }); private final OrientedInstance bell; @@ -33,8 +38,8 @@ public class BellVisual extends AbstractBlockEntityVisual imple public BellVisual(VisualizationContext ctx, BellBlockEntity blockEntity, float partialTick) { super(ctx, blockEntity, partialTick); - bell = createBellInstance().setPivot(0.5f, 0.75f, 0.5f) - .setPosition(getVisualPosition()); + bell = createBellInstance().pivot(0.5f, 0.75f, 0.5f) + .position(getVisualPosition()); bell.setChanged(); updateRotation(partialTick); @@ -62,12 +67,12 @@ public class BellVisual extends AbstractBlockEntityVisual imple Vector3f ringAxis = blockEntity.clickDirection.getCounterClockWise() .step(); - bell.setRotation(new Quaternionf(new AxisAngle4f(angle, ringAxis))) + bell.rotation(new Quaternionf(new AxisAngle4f(angle, ringAxis))) .setChanged(); wasShaking = true; } else if (wasShaking) { - bell.setRotation(new Quaternionf()) + bell.rotation(new Quaternionf()) .setChanged(); wasShaking = false; diff --git a/common/src/main/java/dev/engine_room/flywheel/vanilla/ChestVisual.java b/common/src/main/java/dev/engine_room/flywheel/vanilla/ChestVisual.java index 5745747f5..086a11841 100644 --- a/common/src/main/java/dev/engine_room/flywheel/vanilla/ChestVisual.java +++ b/common/src/main/java/dev/engine_room/flywheel/vanilla/ChestVisual.java @@ -12,7 +12,8 @@ import dev.engine_room.flywheel.api.visualization.VisualizationContext; import dev.engine_room.flywheel.lib.instance.InstanceTypes; import dev.engine_room.flywheel.lib.instance.OrientedInstance; import dev.engine_room.flywheel.lib.instance.TransformedInstance; -import dev.engine_room.flywheel.lib.material.Materials; +import dev.engine_room.flywheel.lib.material.CutoutShaders; +import dev.engine_room.flywheel.lib.material.SimpleMaterial; import dev.engine_room.flywheel.lib.model.ModelCache; import dev.engine_room.flywheel.lib.model.SingleMeshModel; import dev.engine_room.flywheel.lib.model.part.ModelPartConverter; @@ -34,6 +35,12 @@ import net.minecraft.world.level.block.entity.LidBlockEntity; import net.minecraft.world.level.block.state.properties.ChestType; public class ChestVisual extends AbstractBlockEntityVisual implements SimpleDynamicVisual { + public static final dev.engine_room.flywheel.api.material.Material MATERIAL = SimpleMaterial.builder() + .cutout(CutoutShaders.ONE_TENTH) + .texture(Sheets.CHEST_SHEET) + .mipmap(false) + .build(); + private static final Map LAYER_LOCATIONS = new EnumMap<>(ChestType.class); static { LAYER_LOCATIONS.put(ChestType.SINGLE, ModelLayers.CHEST); @@ -42,13 +49,13 @@ public class ChestVisual extends Abstrac } private static final ModelCache> BOTTOM_MODELS = new ModelCache<>(key -> { - return new SingleMeshModel(ModelPartConverter.convert(LAYER_LOCATIONS.get(key.first()), key.second().sprite(), "bottom"), Materials.CHEST); + return new SingleMeshModel(ModelPartConverter.convert(LAYER_LOCATIONS.get(key.first()), key.second().sprite(), "bottom"), MATERIAL); }); private static final ModelCache> LID_MODELS = new ModelCache<>(key -> { - return new SingleMeshModel(ModelPartConverter.convert(LAYER_LOCATIONS.get(key.first()), key.second().sprite(), "lid"), Materials.CHEST); + return new SingleMeshModel(ModelPartConverter.convert(LAYER_LOCATIONS.get(key.first()), key.second().sprite(), "lid"), MATERIAL); }); private static final ModelCache> LOCK_MODELS = new ModelCache<>(key -> { - return new SingleMeshModel(ModelPartConverter.convert(LAYER_LOCATIONS.get(key.first()), key.second().sprite(), "lock"), Materials.CHEST); + return new SingleMeshModel(ModelPartConverter.convert(LAYER_LOCATIONS.get(key.first()), key.second().sprite(), "lock"), MATERIAL); }); private final OrientedInstance bottom; @@ -68,7 +75,7 @@ public class ChestVisual extends Abstrac chestType = blockState.hasProperty(ChestBlock.TYPE) ? blockState.getValue(ChestBlock.TYPE) : ChestType.SINGLE; Material texture = Sheets.chooseMaterial(blockEntity, chestType, isChristmas()); - bottom = createBottomInstance(texture).setPosition(getVisualPosition()); + bottom = createBottomInstance(texture).position(getVisualPosition()); lid = createLidInstance(texture); lock = createLockInstance(texture); @@ -84,7 +91,7 @@ public class ChestVisual extends Abstrac lidProgress = $ -> 0f; } - bottom.setRotation(baseRotation); + bottom.rotation(baseRotation); bottom.setChanged(); applyLidTransform(lidProgress.get(partialTick)); @@ -131,7 +138,7 @@ public class ChestVisual extends Abstrac float angleX = -(progress * ((float) Math.PI / 2F)); - lid.loadIdentity() + lid.setIdentityTransform() .translate(getVisualPosition()) .rotateCentered(baseRotation) .translate(0, 9f / 16f, 1f / 16f) @@ -139,7 +146,7 @@ public class ChestVisual extends Abstrac .translate(0, -9f / 16f, -1f / 16f) .setChanged(); - lock.loadIdentity() + lock.setIdentityTransform() .translate(getVisualPosition()) .rotateCentered(baseRotation) .translate(0, 8f / 16f, 0) diff --git a/common/src/main/java/dev/engine_room/flywheel/vanilla/MinecartVisual.java b/common/src/main/java/dev/engine_room/flywheel/vanilla/MinecartVisual.java index 873ff2bce..bc58879d8 100644 --- a/common/src/main/java/dev/engine_room/flywheel/vanilla/MinecartVisual.java +++ b/common/src/main/java/dev/engine_room/flywheel/vanilla/MinecartVisual.java @@ -5,31 +5,39 @@ import org.jetbrains.annotations.Nullable; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.math.Axis; +import dev.engine_room.flywheel.api.material.Material; import dev.engine_room.flywheel.api.visual.DynamicVisual; import dev.engine_room.flywheel.api.visual.TickableVisual; import dev.engine_room.flywheel.api.visualization.VisualizationContext; import dev.engine_room.flywheel.lib.instance.InstanceTypes; import dev.engine_room.flywheel.lib.instance.TransformedInstance; -import dev.engine_room.flywheel.lib.material.Materials; +import dev.engine_room.flywheel.lib.material.SimpleMaterial; import dev.engine_room.flywheel.lib.model.ModelHolder; import dev.engine_room.flywheel.lib.model.Models; import dev.engine_room.flywheel.lib.model.SingleMeshModel; import dev.engine_room.flywheel.lib.model.part.ModelPartConverter; +import dev.engine_room.flywheel.lib.visual.ComponentEntityVisual; import dev.engine_room.flywheel.lib.visual.SimpleDynamicVisual; -import dev.engine_room.flywheel.lib.visual.SimpleEntityVisual; import dev.engine_room.flywheel.lib.visual.SimpleTickableVisual; import dev.engine_room.flywheel.lib.visual.component.FireComponent; import dev.engine_room.flywheel.lib.visual.component.HitboxComponent; import dev.engine_room.flywheel.lib.visual.component.ShadowComponent; import net.minecraft.client.model.geom.ModelLayerLocation; import net.minecraft.client.model.geom.ModelLayers; +import net.minecraft.resources.ResourceLocation; import net.minecraft.util.Mth; import net.minecraft.world.entity.vehicle.AbstractMinecart; import net.minecraft.world.level.block.RenderShape; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.Vec3; -public class MinecartVisual extends SimpleEntityVisual implements SimpleTickableVisual, SimpleDynamicVisual { +public class MinecartVisual extends ComponentEntityVisual implements SimpleTickableVisual, SimpleDynamicVisual { + private static final ResourceLocation TEXTURE = new ResourceLocation("textures/entity/minecart.png"); + private static final Material MATERIAL = SimpleMaterial.builder() + .texture(TEXTURE) + .mipmap(false) + .build(); + public static final ModelHolder CHEST_BODY_MODEL = createBodyModelHolder(ModelLayers.CHEST_MINECART); public static final ModelHolder COMMAND_BLOCK_BODY_MODEL = createBodyModelHolder(ModelLayers.COMMAND_BLOCK_MINECART); public static final ModelHolder FURNACE_BODY_MODEL = createBodyModelHolder(ModelLayers.FURNACE_MINECART); @@ -68,7 +76,7 @@ public class MinecartVisual extends SimpleEntityVisu private static ModelHolder createBodyModelHolder(ModelLayerLocation layer) { return new ModelHolder(() -> { - return new SingleMeshModel(ModelPartConverter.convert(layer), Materials.MINECART); + return new SingleMeshModel(ModelPartConverter.convert(layer), MATERIAL); }); } @@ -82,7 +90,7 @@ public class MinecartVisual extends SimpleEntityVisu RenderShape shape = blockState.getRenderShape(); if (shape == RenderShape.ENTITYBLOCK_ANIMATED) { - body.setEmptyTransform(); + body.setZeroTransform(); active = false; return null; } diff --git a/common/src/main/java/dev/engine_room/flywheel/vanilla/ShulkerBoxVisual.java b/common/src/main/java/dev/engine_room/flywheel/vanilla/ShulkerBoxVisual.java index 5440c1650..9e9e17925 100644 --- a/common/src/main/java/dev/engine_room/flywheel/vanilla/ShulkerBoxVisual.java +++ b/common/src/main/java/dev/engine_room/flywheel/vanilla/ShulkerBoxVisual.java @@ -11,7 +11,8 @@ import dev.engine_room.flywheel.api.instance.Instance; import dev.engine_room.flywheel.api.visualization.VisualizationContext; import dev.engine_room.flywheel.lib.instance.InstanceTypes; import dev.engine_room.flywheel.lib.instance.TransformedInstance; -import dev.engine_room.flywheel.lib.material.Materials; +import dev.engine_room.flywheel.lib.material.CutoutShaders; +import dev.engine_room.flywheel.lib.material.SimpleMaterial; import dev.engine_room.flywheel.lib.model.ModelCache; import dev.engine_room.flywheel.lib.model.SingleMeshModel; import dev.engine_room.flywheel.lib.model.part.ModelPartConverter; @@ -27,11 +28,18 @@ import net.minecraft.world.level.block.ShulkerBoxBlock; import net.minecraft.world.level.block.entity.ShulkerBoxBlockEntity; public class ShulkerBoxVisual extends AbstractBlockEntityVisual implements SimpleDynamicVisual { + private static final dev.engine_room.flywheel.api.material.Material MATERIAL = SimpleMaterial.builder() + .cutout(CutoutShaders.ONE_TENTH) + .texture(Sheets.SHULKER_SHEET) + .mipmap(false) + .backfaceCulling(false) + .build(); + private static final ModelCache BASE_MODELS = new ModelCache<>(texture -> { - return new SingleMeshModel(ModelPartConverter.convert(ModelLayers.SHULKER, texture.sprite(), "base"), Materials.SHULKER); + return new SingleMeshModel(ModelPartConverter.convert(ModelLayers.SHULKER, texture.sprite(), "base"), MATERIAL); }); private static final ModelCache LID_MODELS = new ModelCache<>(texture -> { - return new SingleMeshModel(ModelPartConverter.convert(ModelLayers.SHULKER, texture.sprite(), "lid"), Materials.SHULKER); + return new SingleMeshModel(ModelPartConverter.convert(ModelLayers.SHULKER, texture.sprite(), "lid"), MATERIAL); }); private final TransformedInstance base; @@ -57,7 +65,7 @@ public class ShulkerBoxVisual extends AbstractBlockEntityVisual currentThread == Thread.currentThread()); + EXECUTOR = new ParallelTaskExecutor("PlanTest", 2); EXECUTOR.startWorkers(); } @@ -187,42 +190,10 @@ class PlanExecutionTest { Assertions.assertEquals(3, counter.get()); } - @Test - void syncedPlanDefersOnMainThread() { - var done = new AtomicBoolean(false); - var plan = SyncedPlan.of(() -> done.set(true)); - - plan.execute(EXECUTOR, Unit.INSTANCE); - - Assertions.assertFalse(done.get()); - - EXECUTOR.syncPoint(); - - Assertions.assertTrue(done.get()); - } - - @Test - void syncedPlanDefersOffThread() { - var done = new AtomicBoolean(false); - - var plan = SyncedPlan.of(() -> { - done.set(true); - }); - - // call execute from within a worker thread - EXECUTOR.execute(() -> plan.execute(EXECUTOR, Unit.INSTANCE)); - - Assertions.assertFalse(done.get()); - - EXECUTOR.syncPoint(); - - Assertions.assertTrue(done.get()); - } - @Test void flagPlan() { - var first = new NamedFlag("ready right away"); - var second = new NamedFlag("ready after we sync"); + var first = new Flag("ready right away"); + var second = new Flag("ready after we sync"); var sync = new Synchronizer(2, second::raise); @@ -240,8 +211,8 @@ class PlanExecutionTest { @Test void longWaitForFlag() { - var first = new NamedFlag("ready right away"); - var second = new NamedFlag("ready after 2s"); + var first = new Flag("ready right away"); + var second = new Flag("ready after 2s"); var plan = RaisePlan.raise(first) .then(SimplePlan.of(() -> { @@ -265,7 +236,7 @@ class PlanExecutionTest { @Test void syncUntilReturnsFlagValue() { - var flag = new NamedFlag("ready right away"); + var flag = new Flag("ready right away"); Assertions.assertFalse(EXECUTOR.syncUntil(flag::isRaised), "Flag should not be raised yet."); diff --git a/common/src/test/java/dev/engine_room/flywheel/lib/task/PlanCompositionTest.java b/common/src/test/java/dev/engine_room/flywheel/lib/task/PlanCompositionTest.java index a7ff0f6f0..2569b5848 100644 --- a/common/src/test/java/dev/engine_room/flywheel/lib/task/PlanCompositionTest.java +++ b/common/src/test/java/dev/engine_room/flywheel/lib/task/PlanCompositionTest.java @@ -7,7 +7,6 @@ import dev.engine_room.flywheel.api.task.Plan; import dev.engine_room.flywheel.lib.util.Unit; public class PlanCompositionTest { - public static final Plan SIMPLE = SimplePlan.of(() -> { }); diff --git a/fabric/src/api/java/dev/engine_room/flywheel/api/event/BeginFrameCallback.java b/fabric/src/api/java/dev/engine_room/flywheel/api/event/BeginFrameCallback.java deleted file mode 100644 index ea044ae39..000000000 --- a/fabric/src/api/java/dev/engine_room/flywheel/api/event/BeginFrameCallback.java +++ /dev/null @@ -1,15 +0,0 @@ -package dev.engine_room.flywheel.api.event; - -import net.fabricmc.fabric.api.event.Event; -import net.fabricmc.fabric.api.event.EventFactory; - -@FunctionalInterface -public interface BeginFrameCallback { - Event EVENT = EventFactory.createArrayBacked(BeginFrameCallback.class, callbacks -> context -> { - for (BeginFrameCallback callback : callbacks) { - callback.onBeginFrame(context); - } - }); - - void onBeginFrame(RenderContext context); -} diff --git a/fabric/src/api/java/dev/engine_room/flywheel/api/event/ReloadLevelRendererCallback.java b/fabric/src/api/java/dev/engine_room/flywheel/api/event/ReloadLevelRendererCallback.java index 7b225e414..dc377da91 100644 --- a/fabric/src/api/java/dev/engine_room/flywheel/api/event/ReloadLevelRendererCallback.java +++ b/fabric/src/api/java/dev/engine_room/flywheel/api/event/ReloadLevelRendererCallback.java @@ -1,7 +1,5 @@ package dev.engine_room.flywheel.api.event; -import org.jetbrains.annotations.Nullable; - import net.fabricmc.fabric.api.event.Event; import net.fabricmc.fabric.api.event.EventFactory; import net.minecraft.client.multiplayer.ClientLevel; @@ -15,5 +13,5 @@ public interface ReloadLevelRendererCallback { } }); - void onReloadLevelRenderer(@Nullable ClientLevel level); + void onReloadLevelRenderer(ClientLevel level); } diff --git a/fabric/src/api/java/dev/engine_room/flywheel/api/event/RenderStageCallback.java b/fabric/src/api/java/dev/engine_room/flywheel/api/event/RenderStageCallback.java deleted file mode 100644 index 8ac881124..000000000 --- a/fabric/src/api/java/dev/engine_room/flywheel/api/event/RenderStageCallback.java +++ /dev/null @@ -1,16 +0,0 @@ -package dev.engine_room.flywheel.api.event; - -import net.fabricmc.fabric.api.event.Event; -import net.fabricmc.fabric.api.event.EventFactory; - -@FunctionalInterface -public interface RenderStageCallback { - Event EVENT = - EventFactory.createArrayBacked(RenderStageCallback.class, callbacks -> (context, stage) -> { - for (RenderStageCallback callback : callbacks) { - callback.onRenderStage(context, stage); - } - }); - - void onRenderStage(RenderContext context, RenderStage stage); -} diff --git a/fabric/src/lib/java/dev/engine_room/flywheel/lib/model/baked/BakedModelBufferer.java b/fabric/src/lib/java/dev/engine_room/flywheel/lib/model/baked/BakedModelBufferer.java index 2f8a09ca6..474e31fbe 100644 --- a/fabric/src/lib/java/dev/engine_room/flywheel/lib/model/baked/BakedModelBufferer.java +++ b/fabric/src/lib/java/dev/engine_room/flywheel/lib/model/baked/BakedModelBufferer.java @@ -18,6 +18,7 @@ import net.minecraft.client.resources.model.BakedModel; import net.minecraft.core.BlockPos; import net.minecraft.util.RandomSource; import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.RenderShape; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.material.FluidState; @@ -31,8 +32,18 @@ final class BakedModelBufferer { private BakedModelBufferer() { } - public static void bufferSingle(ModelBlockRenderer blockRenderer, BlockAndTintGetter level, BakedModel model, BlockState state, @Nullable PoseStack poseStack, ResultConsumer resultConsumer) { + public static void bufferSingle(ModelBlockRenderer blockRenderer, @Nullable BlockAndTintGetter level, BakedModel model, @Nullable BlockState state, @Nullable PoseStack poseStack, ResultConsumer resultConsumer) { ThreadLocalObjects objects = THREAD_LOCAL_OBJECTS.get(); + if (level == null) { + if (state == null) { + state = Blocks.AIR.defaultBlockState(); + } + FabricOriginBlockAndTintGetter originLevel = objects.level; + originLevel.originBlockState(state); + level = originLevel; + } else if (state == null) { + state = level.getBlockState(BlockPos.ZERO); + } if (poseStack == null) { poseStack = objects.identityPoseStack; } @@ -59,7 +70,7 @@ final class BakedModelBufferer { } } - public static void bufferBlock(BlockRenderDispatcher renderDispatcher, BlockAndTintGetter level, BlockState state, @Nullable PoseStack poseStack, ResultConsumer resultConsumer) { + public static void bufferBlock(BlockRenderDispatcher renderDispatcher, @Nullable BlockAndTintGetter level, BlockState state, @Nullable PoseStack poseStack, ResultConsumer resultConsumer) { if (state.getRenderShape() != RenderShape.MODEL) { return; } @@ -133,6 +144,7 @@ final class BakedModelBufferer { } private static class ThreadLocalObjects { + public final FabricOriginBlockAndTintGetter level = new FabricOriginBlockAndTintGetter(p -> 0, p -> 15); public final PoseStack identityPoseStack = new PoseStack(); public final RandomSource random = RandomSource.createNewThreadLocalInstance(); diff --git a/fabric/src/lib/java/dev/engine_room/flywheel/lib/model/baked/FabricBakedModelBuilder.java b/fabric/src/lib/java/dev/engine_room/flywheel/lib/model/baked/FabricBakedModelBuilder.java index 88c3b486f..9f90ba87e 100644 --- a/fabric/src/lib/java/dev/engine_room/flywheel/lib/model/baked/FabricBakedModelBuilder.java +++ b/fabric/src/lib/java/dev/engine_room/flywheel/lib/model/baked/FabricBakedModelBuilder.java @@ -12,7 +12,6 @@ import dev.engine_room.flywheel.lib.model.SimpleModel; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.resources.model.BakedModel; import net.minecraft.world.level.BlockAndTintGetter; -import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.state.BlockState; public final class FabricBakedModelBuilder extends BakedModelBuilder { @@ -46,12 +45,6 @@ public final class FabricBakedModelBuilder extends BakedModelBuilder { @Override public SimpleModel build() { - if (level == null) { - level = VirtualEmptyBlockGetter.INSTANCE; - } - if (blockState == null) { - blockState = Blocks.AIR.defaultBlockState(); - } if (materialFunc == null) { materialFunc = ModelUtil::getMaterial; } diff --git a/fabric/src/lib/java/dev/engine_room/flywheel/lib/model/baked/FabricBlockModelBuilder.java b/fabric/src/lib/java/dev/engine_room/flywheel/lib/model/baked/FabricBlockModelBuilder.java index fecda55b4..58eae7b7d 100644 --- a/fabric/src/lib/java/dev/engine_room/flywheel/lib/model/baked/FabricBlockModelBuilder.java +++ b/fabric/src/lib/java/dev/engine_room/flywheel/lib/model/baked/FabricBlockModelBuilder.java @@ -38,9 +38,6 @@ public final class FabricBlockModelBuilder extends BlockModelBuilder { @Override public SimpleModel build() { - if (level == null) { - level = VirtualEmptyBlockGetter.INSTANCE; - } if (materialFunc == null) { materialFunc = ModelUtil::getMaterial; } diff --git a/fabric/src/lib/java/dev/engine_room/flywheel/lib/model/baked/FabricOriginBlockAndTintGetter.java b/fabric/src/lib/java/dev/engine_room/flywheel/lib/model/baked/FabricOriginBlockAndTintGetter.java new file mode 100644 index 000000000..6ca65bafe --- /dev/null +++ b/fabric/src/lib/java/dev/engine_room/flywheel/lib/model/baked/FabricOriginBlockAndTintGetter.java @@ -0,0 +1,30 @@ +package dev.engine_room.flywheel.lib.model.baked; + +import java.util.function.ToIntFunction; + +import org.jetbrains.annotations.Nullable; + +import net.minecraft.core.BlockPos; + +public class FabricOriginBlockAndTintGetter extends OriginBlockAndTintGetter { + @Nullable + protected Object originRenderData; + + public FabricOriginBlockAndTintGetter(ToIntFunction blockLightFunc, ToIntFunction skyLightFunc) { + super(blockLightFunc, skyLightFunc); + } + + public void originRenderData(@Nullable Object renderData) { + originRenderData = renderData; + } + + @Override + @Nullable + public Object getBlockEntityRenderData(BlockPos pos) { + if (pos.equals(BlockPos.ZERO)) { + return originRenderData; + } + + return super.getBlockEntityRenderData(pos); + } +} diff --git a/fabric/src/lib/java/dev/engine_room/flywheel/lib/model/baked/PartialModelEventHandler.java b/fabric/src/lib/java/dev/engine_room/flywheel/lib/model/baked/PartialModelEventHandler.java index 21f802f07..5b0bc5203 100644 --- a/fabric/src/lib/java/dev/engine_room/flywheel/lib/model/baked/PartialModelEventHandler.java +++ b/fabric/src/lib/java/dev/engine_room/flywheel/lib/model/baked/PartialModelEventHandler.java @@ -18,13 +18,14 @@ public final class PartialModelEventHandler { } public static ResourceLocation[] onRegisterAdditional() { - PartialModel.tooLate = true; - return PartialModel.ALL.stream().map(PartialModel::getLocation).toArray(ResourceLocation[]::new); + return PartialModel.ALL.keySet().toArray(ResourceLocation[]::new); } public static void onBakingCompleted(ModelManager manager) { - for (PartialModel partial : PartialModel.ALL) { - partial.set(manager.getModel(partial.getLocation())); + PartialModel.populateOnInit = true; + + for (PartialModel partial : PartialModel.ALL.values()) { + partial.bakedModel = manager.getModel(partial.modelLocation()); } } diff --git a/fabric/src/main/java/dev/engine_room/flywheel/impl/FabricFlwConfig.java b/fabric/src/main/java/dev/engine_room/flywheel/impl/FabricFlwConfig.java index 9c9554917..173c41102 100644 --- a/fabric/src/main/java/dev/engine_room/flywheel/impl/FabricFlwConfig.java +++ b/fabric/src/main/java/dev/engine_room/flywheel/impl/FabricFlwConfig.java @@ -35,7 +35,7 @@ public class FabricFlwConfig implements FlwConfig { private final File file; - public Backend backend = BackendManager.getDefaultBackend(); + public Backend backend = BackendManager.defaultBackend(); public boolean limitUpdates = LIMIT_UPDATES_DEFAULT; public int workerThreads = WORKER_THREADS_DEFAULT; @@ -81,7 +81,7 @@ public class FabricFlwConfig implements FlwConfig { public void fromJson(JsonElement json) { if (!(json instanceof JsonObject object)) { FlwImpl.CONFIG_LOGGER.warn("Config JSON must be an object"); - backend = BackendManager.getDefaultBackend(); + backend = BackendManager.defaultBackend(); limitUpdates = LIMIT_UPDATES_DEFAULT; workerThreads = WORKER_THREADS_DEFAULT; return; @@ -117,7 +117,7 @@ public class FabricFlwConfig implements FlwConfig { if (msg != null) { FlwImpl.CONFIG_LOGGER.warn(msg); } - backend = BackendManager.getDefaultBackend(); + backend = BackendManager.defaultBackend(); } private void readLimitUpdates(JsonObject object) { diff --git a/fabric/src/main/java/dev/engine_room/flywheel/impl/FlwCommands.java b/fabric/src/main/java/dev/engine_room/flywheel/impl/FlwCommands.java index 010d27806..04bc2af12 100644 --- a/fabric/src/main/java/dev/engine_room/flywheel/impl/FlwCommands.java +++ b/fabric/src/main/java/dev/engine_room/flywheel/impl/FlwCommands.java @@ -29,7 +29,7 @@ public final class FlwCommands { command.then(ClientCommandManager.literal("backend") .executes(context -> { - Backend backend = BackendManager.getBackend(); + Backend backend = BackendManager.currentBackend(); String idStr = Backend.REGISTRY.getIdOrThrow(backend) .toString(); context.getSource().sendFeedback(Component.translatable("command.flywheel.backend.get", idStr)); @@ -44,7 +44,7 @@ public final class FlwCommands { // Reload renderers so we can report the actual backend. Minecraft.getInstance().levelRenderer.allChanged(); - Backend actualBackend = BackendManager.getBackend(); + Backend actualBackend = BackendManager.currentBackend(); if (actualBackend != requestedBackend) { String requestedIdStr = Backend.REGISTRY.getIdOrThrow(requestedBackend) .toString(); diff --git a/fabric/src/main/java/dev/engine_room/flywheel/impl/FlwImplXplatImpl.java b/fabric/src/main/java/dev/engine_room/flywheel/impl/FlwImplXplatImpl.java index 1cb0650b1..4bd60bd7d 100644 --- a/fabric/src/main/java/dev/engine_room/flywheel/impl/FlwImplXplatImpl.java +++ b/fabric/src/main/java/dev/engine_room/flywheel/impl/FlwImplXplatImpl.java @@ -1,30 +1,14 @@ package dev.engine_room.flywheel.impl; -import org.jetbrains.annotations.Nullable; - -import dev.engine_room.flywheel.api.event.BeginFrameCallback; import dev.engine_room.flywheel.api.event.ReloadLevelRendererCallback; -import dev.engine_room.flywheel.api.event.RenderContext; -import dev.engine_room.flywheel.api.event.RenderStage; -import dev.engine_room.flywheel.api.event.RenderStageCallback; import net.minecraft.client.multiplayer.ClientLevel; public class FlwImplXplatImpl implements FlwImplXplat { @Override - public void dispatchBeginFrameEvent(RenderContext context) { - BeginFrameCallback.EVENT.invoker().onBeginFrame(context); - } - - @Override - public void dispatchReloadLevelRendererEvent(@Nullable ClientLevel level) { + public void dispatchReloadLevelRendererEvent(ClientLevel level) { ReloadLevelRendererCallback.EVENT.invoker().onReloadLevelRenderer(level); } - @Override - public void dispatchRenderStageEvent(RenderContext context, RenderStage stage) { - RenderStageCallback.EVENT.invoker().onRenderStage(context, stage); - } - @Override public String getVersionStr() { return FlywheelFabric.version().getFriendlyString(); diff --git a/fabric/src/main/java/dev/engine_room/flywheel/impl/FlwLibXplatImpl.java b/fabric/src/main/java/dev/engine_room/flywheel/impl/FlwLibXplatImpl.java index 8770f0abe..897a7edd7 100644 --- a/fabric/src/main/java/dev/engine_room/flywheel/impl/FlwLibXplatImpl.java +++ b/fabric/src/main/java/dev/engine_room/flywheel/impl/FlwLibXplatImpl.java @@ -1,6 +1,7 @@ package dev.engine_room.flywheel.impl; import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.UnknownNullability; import dev.engine_room.flywheel.lib.internal.FlwLibXplat; import dev.engine_room.flywheel.lib.model.baked.BakedModelBuilder; @@ -15,11 +16,19 @@ import net.irisshaders.iris.api.v0.IrisApi; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.block.BlockRenderDispatcher; import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.client.resources.model.ModelManager; import net.minecraft.core.BlockPos; +import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.BlockAndTintGetter; import net.minecraft.world.level.block.state.BlockState; public class FlwLibXplatImpl implements FlwLibXplat { + @Override + @UnknownNullability + public BakedModel getBakedModel(ModelManager modelManager, ResourceLocation location) { + return modelManager.getModel(location); + } + @Override public BlockRenderDispatcher createVanillaBlockRenderDispatcher() { return Minecraft.getInstance().getBlockRenderer(); diff --git a/fabric/src/main/java/dev/engine_room/flywheel/impl/FlywheelFabric.java b/fabric/src/main/java/dev/engine_room/flywheel/impl/FlywheelFabric.java index d72f235f7..26db5c4f7 100644 --- a/fabric/src/main/java/dev/engine_room/flywheel/impl/FlywheelFabric.java +++ b/fabric/src/main/java/dev/engine_room/flywheel/impl/FlywheelFabric.java @@ -3,10 +3,8 @@ package dev.engine_room.flywheel.impl; import org.jetbrains.annotations.UnknownNullability; import dev.engine_room.flywheel.api.Flywheel; -import dev.engine_room.flywheel.api.event.BeginFrameCallback; import dev.engine_room.flywheel.api.event.EndClientResourceReloadCallback; import dev.engine_room.flywheel.api.event.ReloadLevelRendererCallback; -import dev.engine_room.flywheel.api.event.RenderStageCallback; import dev.engine_room.flywheel.backend.compile.FlwProgramsReloader; import dev.engine_room.flywheel.backend.engine.uniform.Uniforms; import dev.engine_room.flywheel.impl.visualization.VisualizationEventHandler; @@ -54,8 +52,6 @@ public final class FlywheelFabric implements ClientModInitializer { } } }); - BeginFrameCallback.EVENT.register(VisualizationEventHandler::onBeginFrame); - RenderStageCallback.EVENT.register(VisualizationEventHandler::onRenderStage); ClientEntityEvents.ENTITY_LOAD.register((entity, level) -> VisualizationEventHandler.onEntityJoinLevel(level, entity)); ClientEntityEvents.ENTITY_UNLOAD.register((entity, level) -> VisualizationEventHandler.onEntityLeaveLevel(level, entity)); diff --git a/fabric/src/main/java/dev/engine_room/flywheel/impl/mixin/sodium/ChunkBuilderMeshingTaskMixin.java b/fabric/src/main/java/dev/engine_room/flywheel/impl/mixin/sodium/ChunkBuilderMeshingTaskMixin.java index dd03548d3..64e4b31e2 100644 --- a/fabric/src/main/java/dev/engine_room/flywheel/impl/mixin/sodium/ChunkBuilderMeshingTaskMixin.java +++ b/fabric/src/main/java/dev/engine_room/flywheel/impl/mixin/sodium/ChunkBuilderMeshingTaskMixin.java @@ -4,7 +4,7 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; -import dev.engine_room.flywheel.lib.visual.VisualizationHelper; +import dev.engine_room.flywheel.lib.visualization.VisualizationHelper; import me.jellysquid.mods.sodium.client.render.chunk.compile.tasks.ChunkBuilderMeshingTask; import net.minecraft.client.renderer.blockentity.BlockEntityRenderDispatcher; import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; diff --git a/forge/src/api/java/dev/engine_room/flywheel/api/event/BeginFrameEvent.java b/forge/src/api/java/dev/engine_room/flywheel/api/event/BeginFrameEvent.java deleted file mode 100644 index 5da48c419..000000000 --- a/forge/src/api/java/dev/engine_room/flywheel/api/event/BeginFrameEvent.java +++ /dev/null @@ -1,18 +0,0 @@ -package dev.engine_room.flywheel.api.event; - -import net.minecraftforge.eventbus.api.Event; - -/** - * This event is posted to the Forge event bus. - */ -public final class BeginFrameEvent extends Event { - private final RenderContext context; - - public BeginFrameEvent(RenderContext context) { - this.context = context; - } - - public RenderContext context() { - return context; - } -} diff --git a/forge/src/api/java/dev/engine_room/flywheel/api/event/ReloadLevelRendererEvent.java b/forge/src/api/java/dev/engine_room/flywheel/api/event/ReloadLevelRendererEvent.java index e74e792c9..157826619 100644 --- a/forge/src/api/java/dev/engine_room/flywheel/api/event/ReloadLevelRendererEvent.java +++ b/forge/src/api/java/dev/engine_room/flywheel/api/event/ReloadLevelRendererEvent.java @@ -1,7 +1,5 @@ package dev.engine_room.flywheel.api.event; -import org.jetbrains.annotations.Nullable; - import net.minecraft.client.multiplayer.ClientLevel; import net.minecraftforge.eventbus.api.Event; @@ -9,14 +7,12 @@ import net.minecraftforge.eventbus.api.Event; * This event is posted to the Forge event bus. */ public final class ReloadLevelRendererEvent extends Event { - @Nullable private final ClientLevel level; - public ReloadLevelRendererEvent(@Nullable ClientLevel level) { + public ReloadLevelRendererEvent(ClientLevel level) { this.level = level; } - @Nullable public ClientLevel level() { return level; } diff --git a/forge/src/api/java/dev/engine_room/flywheel/api/event/RenderStageEvent.java b/forge/src/api/java/dev/engine_room/flywheel/api/event/RenderStageEvent.java deleted file mode 100644 index 4b0ec8254..000000000 --- a/forge/src/api/java/dev/engine_room/flywheel/api/event/RenderStageEvent.java +++ /dev/null @@ -1,56 +0,0 @@ -package dev.engine_room.flywheel.api.event; - -import org.joml.Matrix4f; - -import com.mojang.blaze3d.vertex.PoseStack; - -import net.minecraft.client.Camera; -import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.client.renderer.RenderBuffers; -import net.minecraftforge.eventbus.api.Event; - -/** - * This event is posted to the Forge event bus. - */ -public final class RenderStageEvent extends Event { - private final RenderContext context; - private final RenderStage stage; - - public RenderStageEvent(RenderContext context, RenderStage stage) { - this.context = context; - this.stage = stage; - } - - public RenderContext context() { - return context; - } - - public RenderStage stage() { - return stage; - } - - public ClientLevel level() { - return context.level(); - } - - public PoseStack stack() { - return context.stack(); - } - - public Matrix4f viewProjection() { - return context.viewProjection(); - } - - public RenderBuffers buffers() { - return context.buffers(); - } - - public Camera camera() { - return context.camera(); - } - - @Override - public String toString() { - return "RenderStageEvent{" + context + "}"; - } -} diff --git a/forge/src/lib/java/dev/engine_room/flywheel/lib/model/baked/BakedModelBufferer.java b/forge/src/lib/java/dev/engine_room/flywheel/lib/model/baked/BakedModelBufferer.java index 50162d4b9..b90004b91 100644 --- a/forge/src/lib/java/dev/engine_room/flywheel/lib/model/baked/BakedModelBufferer.java +++ b/forge/src/lib/java/dev/engine_room/flywheel/lib/model/baked/BakedModelBufferer.java @@ -17,6 +17,7 @@ import net.minecraft.client.resources.model.BakedModel; import net.minecraft.core.BlockPos; import net.minecraft.util.RandomSource; import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.RenderShape; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.material.FluidState; @@ -32,8 +33,18 @@ final class BakedModelBufferer { private BakedModelBufferer() { } - public static void bufferSingle(ModelBlockRenderer blockRenderer, BlockAndTintGetter level, BakedModel model, BlockState state, @Nullable PoseStack poseStack, ModelData modelData, ResultConsumer resultConsumer) { + public static void bufferSingle(ModelBlockRenderer blockRenderer, @Nullable BlockAndTintGetter level, BakedModel model, @Nullable BlockState state, @Nullable PoseStack poseStack, ModelData modelData, ResultConsumer resultConsumer) { ThreadLocalObjects objects = THREAD_LOCAL_OBJECTS.get(); + if (level == null) { + if (state == null) { + state = Blocks.AIR.defaultBlockState(); + } + OriginBlockAndTintGetter originLevel = objects.level; + originLevel.originBlockState(state); + level = originLevel; + } else if (state == null) { + state = level.getBlockState(BlockPos.ZERO); + } if (poseStack == null) { poseStack = objects.identityPoseStack; } @@ -58,7 +69,7 @@ final class BakedModelBufferer { } } - public static void bufferBlock(BlockRenderDispatcher renderDispatcher, BlockAndTintGetter level, BlockState state, @Nullable PoseStack poseStack, ModelData modelData, ResultConsumer resultConsumer) { + public static void bufferBlock(BlockRenderDispatcher renderDispatcher, @Nullable BlockAndTintGetter level, BlockState state, @Nullable PoseStack poseStack, ModelData modelData, ResultConsumer resultConsumer) { if (state.getRenderShape() != RenderShape.MODEL) { return; } @@ -134,6 +145,7 @@ final class BakedModelBufferer { } private static class ThreadLocalObjects { + public final OriginBlockAndTintGetter level = new OriginBlockAndTintGetter(p -> 0, p -> 15); public final PoseStack identityPoseStack = new PoseStack(); public final RandomSource random = RandomSource.createNewThreadLocalInstance(); diff --git a/forge/src/lib/java/dev/engine_room/flywheel/lib/model/baked/ForgeBakedModelBuilder.java b/forge/src/lib/java/dev/engine_room/flywheel/lib/model/baked/ForgeBakedModelBuilder.java index 10714e848..b349a32bf 100644 --- a/forge/src/lib/java/dev/engine_room/flywheel/lib/model/baked/ForgeBakedModelBuilder.java +++ b/forge/src/lib/java/dev/engine_room/flywheel/lib/model/baked/ForgeBakedModelBuilder.java @@ -14,7 +14,6 @@ import dev.engine_room.flywheel.lib.model.SimpleModel; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.resources.model.BakedModel; import net.minecraft.world.level.BlockAndTintGetter; -import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.state.BlockState; import net.minecraftforge.client.model.data.ModelData; @@ -57,12 +56,6 @@ public final class ForgeBakedModelBuilder extends BakedModelBuilder { @Override public SimpleModel build() { - if (level == null) { - level = VirtualEmptyBlockGetter.INSTANCE; - } - if (blockState == null) { - blockState = Blocks.AIR.defaultBlockState(); - } if (materialFunc == null) { materialFunc = ModelUtil::getMaterial; } diff --git a/forge/src/lib/java/dev/engine_room/flywheel/lib/model/baked/ForgeBlockModelBuilder.java b/forge/src/lib/java/dev/engine_room/flywheel/lib/model/baked/ForgeBlockModelBuilder.java index 4e1d9df82..0c0ab4fd0 100644 --- a/forge/src/lib/java/dev/engine_room/flywheel/lib/model/baked/ForgeBlockModelBuilder.java +++ b/forge/src/lib/java/dev/engine_room/flywheel/lib/model/baked/ForgeBlockModelBuilder.java @@ -49,9 +49,6 @@ public final class ForgeBlockModelBuilder extends BlockModelBuilder { @Override public SimpleModel build() { - if (level == null) { - level = VirtualEmptyBlockGetter.INSTANCE; - } if (materialFunc == null) { materialFunc = ModelUtil::getMaterial; } diff --git a/forge/src/lib/java/dev/engine_room/flywheel/lib/model/baked/PartialModelEventHandler.java b/forge/src/lib/java/dev/engine_room/flywheel/lib/model/baked/PartialModelEventHandler.java index 5c490dcd7..d39cb6e92 100644 --- a/forge/src/lib/java/dev/engine_room/flywheel/lib/model/baked/PartialModelEventHandler.java +++ b/forge/src/lib/java/dev/engine_room/flywheel/lib/model/baked/PartialModelEventHandler.java @@ -14,18 +14,17 @@ public final class PartialModelEventHandler { } public static void onRegisterAdditional(ModelEvent.RegisterAdditional event) { - for (PartialModel partial : PartialModel.ALL) { - event.register(partial.getLocation()); + for (ResourceLocation modelLocation : PartialModel.ALL.keySet()) { + event.register(modelLocation); } - - PartialModel.tooLate = true; } public static void onBakingCompleted(ModelEvent.BakingCompleted event) { + PartialModel.populateOnInit = true; Map models = event.getModels(); - for (PartialModel partial : PartialModel.ALL) { - partial.set(models.get(partial.getLocation())); + for (PartialModel partial : PartialModel.ALL.values()) { + partial.bakedModel = models.get(partial.modelLocation()); } } } diff --git a/forge/src/main/java/dev/engine_room/flywheel/impl/FlwCommands.java b/forge/src/main/java/dev/engine_room/flywheel/impl/FlwCommands.java index 227973f4e..8d7ea09b1 100644 --- a/forge/src/main/java/dev/engine_room/flywheel/impl/FlwCommands.java +++ b/forge/src/main/java/dev/engine_room/flywheel/impl/FlwCommands.java @@ -29,7 +29,7 @@ public final class FlwCommands { ConfigValue backendValue = ForgeFlwConfig.INSTANCE.client.backend; command.then(Commands.literal("backend") .executes(context -> { - Backend backend = BackendManager.getBackend(); + Backend backend = BackendManager.currentBackend(); String idStr = Backend.REGISTRY.getIdOrThrow(backend) .toString(); sendMessage(context.getSource(), Component.translatable("command.flywheel.backend.get", idStr)); @@ -45,7 +45,7 @@ public final class FlwCommands { // Reload renderers so we can report the actual backend. Minecraft.getInstance().levelRenderer.allChanged(); - Backend actualBackend = BackendManager.getBackend(); + Backend actualBackend = BackendManager.currentBackend(); if (actualBackend != requestedBackend) { sendFailure(context.getSource(), Component.translatable("command.flywheel.backend.set.unavailable", requestedIdStr)); } diff --git a/forge/src/main/java/dev/engine_room/flywheel/impl/FlwImplXplatImpl.java b/forge/src/main/java/dev/engine_room/flywheel/impl/FlwImplXplatImpl.java index 4ebf4532b..fa4f901e0 100644 --- a/forge/src/main/java/dev/engine_room/flywheel/impl/FlwImplXplatImpl.java +++ b/forge/src/main/java/dev/engine_room/flywheel/impl/FlwImplXplatImpl.java @@ -1,31 +1,15 @@ package dev.engine_room.flywheel.impl; -import org.jetbrains.annotations.Nullable; - -import dev.engine_room.flywheel.api.event.BeginFrameEvent; import dev.engine_room.flywheel.api.event.ReloadLevelRendererEvent; -import dev.engine_room.flywheel.api.event.RenderContext; -import dev.engine_room.flywheel.api.event.RenderStage; -import dev.engine_room.flywheel.api.event.RenderStageEvent; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraftforge.common.MinecraftForge; public class FlwImplXplatImpl implements FlwImplXplat { @Override - public void dispatchBeginFrameEvent(RenderContext context) { - MinecraftForge.EVENT_BUS.post(new BeginFrameEvent(context)); - } - - @Override - public void dispatchReloadLevelRendererEvent(@Nullable ClientLevel level) { + public void dispatchReloadLevelRendererEvent(ClientLevel level) { MinecraftForge.EVENT_BUS.post(new ReloadLevelRendererEvent(level)); } - @Override - public void dispatchRenderStageEvent(RenderContext context, RenderStage stage) { - MinecraftForge.EVENT_BUS.post(new RenderStageEvent(context, stage)); - } - @Override public String getVersionStr() { return FlywheelForge.version().toString(); diff --git a/forge/src/main/java/dev/engine_room/flywheel/impl/FlwLibXplatImpl.java b/forge/src/main/java/dev/engine_room/flywheel/impl/FlwLibXplatImpl.java index 7aa29a9b0..eeed7907a 100644 --- a/forge/src/main/java/dev/engine_room/flywheel/impl/FlwLibXplatImpl.java +++ b/forge/src/main/java/dev/engine_room/flywheel/impl/FlwLibXplatImpl.java @@ -3,6 +3,7 @@ package dev.engine_room.flywheel.impl; import java.lang.reflect.Field; import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.UnknownNullability; import dev.engine_room.flywheel.lib.internal.FlwLibXplat; import dev.engine_room.flywheel.lib.model.baked.BakedModelBuilder; @@ -17,13 +18,21 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.block.BlockRenderDispatcher; import net.minecraft.client.renderer.block.ModelBlockRenderer; import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.client.resources.model.ModelManager; import net.minecraft.core.BlockPos; +import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.BlockAndTintGetter; import net.minecraft.world.level.block.state.BlockState; import net.minecraftforge.fml.ModList; import net.minecraftforge.fml.util.ObfuscationReflectionHelper; public class FlwLibXplatImpl implements FlwLibXplat { + @Override + @UnknownNullability + public BakedModel getBakedModel(ModelManager modelManager, ResourceLocation location) { + return modelManager.getModel(location); + } + @Override public BlockRenderDispatcher createVanillaBlockRenderDispatcher() { BlockRenderDispatcher defaultDispatcher = Minecraft.getInstance().getBlockRenderer(); diff --git a/forge/src/main/java/dev/engine_room/flywheel/impl/FlywheelForge.java b/forge/src/main/java/dev/engine_room/flywheel/impl/FlywheelForge.java index 72e5ada1f..e9271d865 100644 --- a/forge/src/main/java/dev/engine_room/flywheel/impl/FlywheelForge.java +++ b/forge/src/main/java/dev/engine_room/flywheel/impl/FlywheelForge.java @@ -4,10 +4,8 @@ import org.apache.maven.artifact.versioning.ArtifactVersion; import org.jetbrains.annotations.UnknownNullability; import dev.engine_room.flywheel.api.Flywheel; -import dev.engine_room.flywheel.api.event.BeginFrameEvent; import dev.engine_room.flywheel.api.event.EndClientResourceReloadEvent; import dev.engine_room.flywheel.api.event.ReloadLevelRendererEvent; -import dev.engine_room.flywheel.api.event.RenderStageEvent; import dev.engine_room.flywheel.backend.compile.FlwProgramsReloader; import dev.engine_room.flywheel.backend.engine.uniform.Uniforms; import dev.engine_room.flywheel.impl.visualization.VisualizationEventHandler; @@ -76,8 +74,6 @@ public final class FlywheelForge { VisualizationEventHandler.onClientTick(Minecraft.getInstance(), e.level); } }); - forgeEventBus.addListener((BeginFrameEvent e) -> VisualizationEventHandler.onBeginFrame(e.context())); - forgeEventBus.addListener((RenderStageEvent e) -> VisualizationEventHandler.onRenderStage(e.context(), e.stage())); forgeEventBus.addListener((EntityJoinLevelEvent e) -> VisualizationEventHandler.onEntityJoinLevel(e.getLevel(), e.getEntity())); forgeEventBus.addListener((EntityLeaveLevelEvent e) -> VisualizationEventHandler.onEntityLeaveLevel(e.getLevel(), e.getEntity())); diff --git a/forge/src/main/java/dev/engine_room/flywheel/impl/ForgeFlwConfig.java b/forge/src/main/java/dev/engine_room/flywheel/impl/ForgeFlwConfig.java index 69fd054c0..4f24a7f64 100644 --- a/forge/src/main/java/dev/engine_room/flywheel/impl/ForgeFlwConfig.java +++ b/forge/src/main/java/dev/engine_room/flywheel/impl/ForgeFlwConfig.java @@ -27,7 +27,7 @@ public class ForgeFlwConfig implements FlwConfig { public Backend backend() { Backend backend = parseBackend(client.backend.get()); if (backend == null) { - backend = BackendManager.getDefaultBackend(); + backend = BackendManager.defaultBackend(); client.backend.set(Backend.REGISTRY.getIdOrThrow(backend).toString()); } @@ -74,7 +74,7 @@ public class ForgeFlwConfig implements FlwConfig { private ClientConfig(ForgeConfigSpec.Builder builder) { backend = builder.comment("Select the backend to use.") - .define("backend", Backend.REGISTRY.getIdOrThrow(BackendManager.getDefaultBackend()).toString()); + .define("backend", Backend.REGISTRY.getIdOrThrow(BackendManager.defaultBackend()).toString()); limitUpdates = builder.comment("Enable or disable instance update limiting with distance.") .define("limitUpdates", true); diff --git a/forge/src/main/java/dev/engine_room/flywheel/impl/mixin/sodium/ChunkBuilderMeshingTaskMixin.java b/forge/src/main/java/dev/engine_room/flywheel/impl/mixin/sodium/ChunkBuilderMeshingTaskMixin.java index dd03548d3..64e4b31e2 100644 --- a/forge/src/main/java/dev/engine_room/flywheel/impl/mixin/sodium/ChunkBuilderMeshingTaskMixin.java +++ b/forge/src/main/java/dev/engine_room/flywheel/impl/mixin/sodium/ChunkBuilderMeshingTaskMixin.java @@ -4,7 +4,7 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; -import dev.engine_room.flywheel.lib.visual.VisualizationHelper; +import dev.engine_room.flywheel.lib.visualization.VisualizationHelper; import me.jellysquid.mods.sodium.client.render.chunk.compile.tasks.ChunkBuilderMeshingTask; import net.minecraft.client.renderer.blockentity.BlockEntityRenderDispatcher; import net.minecraft.client.renderer.blockentity.BlockEntityRenderer;