diff --git a/src/main/java/com/jozufozu/flywheel/Flywheel.java b/src/main/java/com/jozufozu/flywheel/Flywheel.java index d1d7a51f7..a7d057b1e 100644 --- a/src/main/java/com/jozufozu/flywheel/Flywheel.java +++ b/src/main/java/com/jozufozu/flywheel/Flywheel.java @@ -3,7 +3,9 @@ package com.jozufozu.flywheel; import org.apache.maven.artifact.versioning.ArtifactVersion; import org.slf4j.Logger; +import com.jozufozu.flywheel.backend.Backends; import com.jozufozu.flywheel.backend.Loader; +import com.jozufozu.flywheel.backend.Pipelines; import com.jozufozu.flywheel.backend.engine.batching.DrawBuffer; import com.jozufozu.flywheel.config.BackendArgument; import com.jozufozu.flywheel.config.FlwCommands; @@ -14,14 +16,12 @@ import com.jozufozu.flywheel.impl.BackendManagerImpl; import com.jozufozu.flywheel.impl.IdRegistryImpl; import com.jozufozu.flywheel.impl.RegistryImpl; import com.jozufozu.flywheel.impl.instancing.InstancedRenderDispatcher; -import com.jozufozu.flywheel.lib.backend.Backends; import com.jozufozu.flywheel.lib.context.Contexts; import com.jozufozu.flywheel.lib.format.Formats; import com.jozufozu.flywheel.lib.material.MaterialIndices; import com.jozufozu.flywheel.lib.material.Materials; import com.jozufozu.flywheel.lib.model.Models; import com.jozufozu.flywheel.lib.model.PartialModel; -import com.jozufozu.flywheel.lib.pipeline.Pipelines; import com.jozufozu.flywheel.lib.struct.StructTypes; import com.jozufozu.flywheel.lib.util.QuadConverter; import com.jozufozu.flywheel.lib.util.ShadersModHandler; @@ -36,7 +36,6 @@ import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.eventbus.api.EventPriority; import net.minecraftforge.eventbus.api.IEventBus; -import net.minecraftforge.fml.CrashReportCallables; import net.minecraftforge.fml.DistExecutor; import net.minecraftforge.fml.IExtensionPoint; import net.minecraftforge.fml.ModLoadingContext; @@ -47,7 +46,6 @@ import net.minecraftforge.network.NetworkConstants; @Mod(Flywheel.ID) public class Flywheel { - public static final String ID = "flywheel"; public static final Logger LOGGER = LogUtils.getLogger(); private static ArtifactVersion version; @@ -78,11 +76,12 @@ public class Flywheel { private static void clientInit(IEventBus forgeEventBus, IEventBus modEventBus) { forgeEventBus.addListener(FlwCommands::registerClientCommands); + forgeEventBus.addListener(BackendManagerImpl::onReloadRenderers); + forgeEventBus.addListener(EventPriority.HIGHEST, QuadConverter::onReloadRenderers); forgeEventBus.addListener(Models::onReloadRenderers); forgeEventBus.addListener(DrawBuffer::onReloadRenderers); - forgeEventBus.addListener(InstancedRenderDispatcher::onReloadRenderers); forgeEventBus.addListener(InstancedRenderDispatcher::onRenderStage); forgeEventBus.addListener(InstancedRenderDispatcher::onBeginFrame); forgeEventBus.addListener(InstancedRenderDispatcher::tick); @@ -100,23 +99,23 @@ public class Flywheel { // forgeEventBus.addListener(ExampleEffect::tick); // forgeEventBus.addListener(ExampleEffect::onReload); - ShadersModHandler.init(); + BackendManagerImpl.init(); + Pipelines.init(); Backends.init(); Loader.init(); + ShadersModHandler.init(); + Formats.init(); StructTypes.init(); Materials.init(); Contexts.init(); - Pipelines.init(); MaterialIndices.init(); VanillaInstances.init(); - CrashReportCallables.registerCrashCallable("Flywheel Backend", BackendManagerImpl::getBackendNameForCrashReport); - // https://github.com/Jozufozu/Flywheel/issues/69 // Weird issue with accessor loading. // Only thing I've seen that's close to a fix is to force the class to load before trying to use it. diff --git a/src/main/java/com/jozufozu/flywheel/api/backend/BackendManager.java b/src/main/java/com/jozufozu/flywheel/api/backend/BackendManager.java index 5819bea8e..50b0042ae 100644 --- a/src/main/java/com/jozufozu/flywheel/api/backend/BackendManager.java +++ b/src/main/java/com/jozufozu/flywheel/api/backend/BackendManager.java @@ -17,9 +17,8 @@ public final class BackendManager { return BackendManagerImpl.isOn(); } - // TODO: definitively sort existing calls to this method into API (include behavior in javadoc) or default backend code - public static void refresh() { - BackendManagerImpl.refresh(); + public static Backend getOffBackend() { + return BackendManagerImpl.getOffBackend(); } public static Backend getDefaultBackend() { diff --git a/src/main/java/com/jozufozu/flywheel/api/event/RenderContext.java b/src/main/java/com/jozufozu/flywheel/api/event/RenderContext.java index a3cd89d06..58bed0d54 100644 --- a/src/main/java/com/jozufozu/flywheel/api/event/RenderContext.java +++ b/src/main/java/com/jozufozu/flywheel/api/event/RenderContext.java @@ -3,7 +3,7 @@ package com.jozufozu.flywheel.api.event; import org.jetbrains.annotations.NotNull; import org.joml.FrustumIntersection; -import com.jozufozu.flywheel.util.MatrixUtil; +import com.jozufozu.flywheel.lib.math.MatrixUtil; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.math.Matrix4f; diff --git a/src/main/java/com/jozufozu/flywheel/api/instance/BlockEntityInstance.java b/src/main/java/com/jozufozu/flywheel/api/instance/BlockEntityInstance.java index 0fb3a750e..b5c13a03a 100644 --- a/src/main/java/com/jozufozu/flywheel/api/instance/BlockEntityInstance.java +++ b/src/main/java/com/jozufozu/flywheel/api/instance/BlockEntityInstance.java @@ -2,7 +2,7 @@ package com.jozufozu.flywheel.api.instance; import java.util.List; -import com.jozufozu.flywheel.api.instancer.InstancePart; +import com.jozufozu.flywheel.api.struct.InstancePart; import net.minecraft.world.level.block.entity.BlockEntity; diff --git a/src/main/java/com/jozufozu/flywheel/api/instance/DynamicInstance.java b/src/main/java/com/jozufozu/flywheel/api/instance/DynamicInstance.java index 4f9835cb3..ea8c22f79 100644 --- a/src/main/java/com/jozufozu/flywheel/api/instance/DynamicInstance.java +++ b/src/main/java/com/jozufozu/flywheel/api/instance/DynamicInstance.java @@ -2,8 +2,8 @@ package com.jozufozu.flywheel.api.instance; import org.joml.FrustumIntersection; -import com.jozufozu.flywheel.api.instancer.InstancePart; import com.jozufozu.flywheel.api.instancer.Instancer; +import com.jozufozu.flywheel.api.struct.InstancePart; /** * An interface giving {@link Instance}s a hook to have a function called at diff --git a/src/main/java/com/jozufozu/flywheel/api/instance/TickableInstance.java b/src/main/java/com/jozufozu/flywheel/api/instance/TickableInstance.java index e0c8fd77d..d7b0afb8d 100644 --- a/src/main/java/com/jozufozu/flywheel/api/instance/TickableInstance.java +++ b/src/main/java/com/jozufozu/flywheel/api/instance/TickableInstance.java @@ -1,7 +1,7 @@ package com.jozufozu.flywheel.api.instance; -import com.jozufozu.flywheel.api.instancer.InstancePart; import com.jozufozu.flywheel.api.instancer.Instancer; +import com.jozufozu.flywheel.api.struct.InstancePart; /** * An interface giving {@link Instance}s a hook to have a function called at diff --git a/src/main/java/com/jozufozu/flywheel/api/instancer/Instancer.java b/src/main/java/com/jozufozu/flywheel/api/instancer/Instancer.java index 9be9e5633..8e9b01dba 100644 --- a/src/main/java/com/jozufozu/flywheel/api/instancer/Instancer.java +++ b/src/main/java/com/jozufozu/flywheel/api/instancer/Instancer.java @@ -1,5 +1,7 @@ package com.jozufozu.flywheel.api.instancer; +import com.jozufozu.flywheel.api.struct.InstancePart; + /** * An instancer is how you interact with an instanced model. *

diff --git a/src/main/java/com/jozufozu/flywheel/api/instancer/InstancerProvider.java b/src/main/java/com/jozufozu/flywheel/api/instancer/InstancerProvider.java index 21ea65f18..13c52909d 100644 --- a/src/main/java/com/jozufozu/flywheel/api/instancer/InstancerProvider.java +++ b/src/main/java/com/jozufozu/flywheel/api/instancer/InstancerProvider.java @@ -2,6 +2,7 @@ package com.jozufozu.flywheel.api.instancer; import com.jozufozu.flywheel.api.event.RenderStage; import com.jozufozu.flywheel.api.model.Model; +import com.jozufozu.flywheel.api.struct.InstancePart; import com.jozufozu.flywheel.api.struct.StructType; public interface InstancerProvider { diff --git a/src/main/java/com/jozufozu/flywheel/api/material/Material.java b/src/main/java/com/jozufozu/flywheel/api/material/Material.java index 224ded5ef..5a666eaff 100644 --- a/src/main/java/com/jozufozu/flywheel/api/material/Material.java +++ b/src/main/java/com/jozufozu/flywheel/api/material/Material.java @@ -1,10 +1,8 @@ package com.jozufozu.flywheel.api.material; import com.jozufozu.flywheel.api.registry.Registry; -import com.jozufozu.flywheel.api.vertex.MutableVertexList; import com.jozufozu.flywheel.impl.RegistryImpl; -import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.renderer.RenderType; import net.minecraft.resources.ResourceLocation; @@ -21,9 +19,5 @@ public interface Material { RenderType getBatchingRenderType(); - VertexTransformer getVertexTransformer(); - - interface VertexTransformer { - void transform(MutableVertexList vertexList, ClientLevel level); - } + MaterialVertexTransformer getVertexTransformer(); } diff --git a/src/main/java/com/jozufozu/flywheel/api/material/MaterialVertexTransformer.java b/src/main/java/com/jozufozu/flywheel/api/material/MaterialVertexTransformer.java new file mode 100644 index 000000000..223bd5cd9 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/api/material/MaterialVertexTransformer.java @@ -0,0 +1,9 @@ +package com.jozufozu.flywheel.api.material; + +import com.jozufozu.flywheel.api.vertex.MutableVertexList; + +import net.minecraft.client.multiplayer.ClientLevel; + +public interface MaterialVertexTransformer { + void transform(MutableVertexList vertexList, ClientLevel level); +} diff --git a/src/main/java/com/jozufozu/flywheel/api/model/Mesh.java b/src/main/java/com/jozufozu/flywheel/api/model/Mesh.java index 0d637caa4..ef8494a89 100644 --- a/src/main/java/com/jozufozu/flywheel/api/model/Mesh.java +++ b/src/main/java/com/jozufozu/flywheel/api/model/Mesh.java @@ -5,13 +5,11 @@ import org.joml.Vector4fc; import com.jozufozu.flywheel.api.vertex.MutableVertexList; import com.jozufozu.flywheel.api.vertex.VertexType; import com.jozufozu.flywheel.gl.buffer.ElementBuffer; -import com.jozufozu.flywheel.lib.util.QuadConverter; /** * A holder for arbitrary vertex data that can be written to memory or a vertex list. */ public interface Mesh { - VertexType getVertexType(); /** @@ -50,18 +48,9 @@ public interface Mesh { /** * Create an element buffer object that indexes the vertices of this mesh. - * - *

- * Very often models in minecraft are made up of sequential quads, which is a very predictable pattern. - * The default implementation accommodates this, however this can be overridden to change the behavior and - * support more complex models. - *

* @return an element buffer object indexing this model's vertices. */ - default ElementBuffer createEBO() { - return QuadConverter.getInstance() - .quads2Tris(getVertexCount() / 4); - } + ElementBuffer createEBO(); Vector4fc getBoundingSphere(); diff --git a/src/main/java/com/jozufozu/flywheel/api/instancer/Handle.java b/src/main/java/com/jozufozu/flywheel/api/struct/Handle.java similarity index 60% rename from src/main/java/com/jozufozu/flywheel/api/instancer/Handle.java rename to src/main/java/com/jozufozu/flywheel/api/struct/Handle.java index 208c73673..e688163ad 100644 --- a/src/main/java/com/jozufozu/flywheel/api/instancer/Handle.java +++ b/src/main/java/com/jozufozu/flywheel/api/struct/Handle.java @@ -1,7 +1,6 @@ -package com.jozufozu.flywheel.api.instancer; +package com.jozufozu.flywheel.api.struct; public interface Handle { - void setChanged(); void setDeleted(); diff --git a/src/main/java/com/jozufozu/flywheel/api/instancer/InstancePart.java b/src/main/java/com/jozufozu/flywheel/api/struct/InstancePart.java similarity index 52% rename from src/main/java/com/jozufozu/flywheel/api/instancer/InstancePart.java rename to src/main/java/com/jozufozu/flywheel/api/struct/InstancePart.java index ba6144f49..a59824584 100644 --- a/src/main/java/com/jozufozu/flywheel/api/instancer/InstancePart.java +++ b/src/main/java/com/jozufozu/flywheel/api/struct/InstancePart.java @@ -1,6 +1,4 @@ -package com.jozufozu.flywheel.api.instancer; - -import com.jozufozu.flywheel.api.struct.StructType; +package com.jozufozu.flywheel.api.struct; public interface InstancePart { StructType type(); diff --git a/src/main/java/com/jozufozu/flywheel/api/struct/StructType.java b/src/main/java/com/jozufozu/flywheel/api/struct/StructType.java index c0a0bf002..1d734e5fc 100644 --- a/src/main/java/com/jozufozu/flywheel/api/struct/StructType.java +++ b/src/main/java/com/jozufozu/flywheel/api/struct/StructType.java @@ -1,13 +1,9 @@ package com.jozufozu.flywheel.api.struct; -import com.jozufozu.flywheel.api.instancer.Handle; -import com.jozufozu.flywheel.api.instancer.InstancePart; import com.jozufozu.flywheel.api.layout.BufferLayout; import com.jozufozu.flywheel.api.registry.Registry; -import com.jozufozu.flywheel.api.vertex.MutableVertexList; import com.jozufozu.flywheel.impl.RegistryImpl; -import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.resources.ResourceLocation; /** @@ -33,10 +29,5 @@ public interface StructType

{ ResourceLocation instanceShader(); - VertexTransformer

getVertexTransformer(); - - interface VertexTransformer

{ - void transform(MutableVertexList vertexList, P struct, ClientLevel level); - } - + StructVertexTransformer

getVertexTransformer(); } diff --git a/src/main/java/com/jozufozu/flywheel/api/struct/StructVertexTransformer.java b/src/main/java/com/jozufozu/flywheel/api/struct/StructVertexTransformer.java new file mode 100644 index 000000000..b76e87bfa --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/api/struct/StructVertexTransformer.java @@ -0,0 +1,9 @@ +package com.jozufozu.flywheel.api.struct; + +import com.jozufozu.flywheel.api.vertex.MutableVertexList; + +import net.minecraft.client.multiplayer.ClientLevel; + +public interface StructVertexTransformer

{ + void transform(MutableVertexList vertexList, P struct, ClientLevel level); +} diff --git a/src/main/java/com/jozufozu/flywheel/api/struct/StructWriter.java b/src/main/java/com/jozufozu/flywheel/api/struct/StructWriter.java index 55468838f..5c8aed15d 100644 --- a/src/main/java/com/jozufozu/flywheel/api/struct/StructWriter.java +++ b/src/main/java/com/jozufozu/flywheel/api/struct/StructWriter.java @@ -1,14 +1,11 @@ package com.jozufozu.flywheel.api.struct; -import com.jozufozu.flywheel.api.instancer.InstancePart; - /** - * StructWriters can quickly consume many instances of S and write them to some memory address. + * StructWriters can quickly consume many instances and write them to some memory address. */ public interface StructWriter

{ /** * Write the given struct to the given memory address. */ void write(final long ptr, final P struct); - } diff --git a/src/main/java/com/jozufozu/flywheel/api/vertex/VertexList.java b/src/main/java/com/jozufozu/flywheel/api/vertex/VertexList.java index 1b5070534..78f1a3ab9 100644 --- a/src/main/java/com/jozufozu/flywheel/api/vertex/VertexList.java +++ b/src/main/java/com/jozufozu/flywheel/api/vertex/VertexList.java @@ -7,7 +7,6 @@ package com.jozufozu.flywheel.api.vertex; * VertexList assumes nothing about the layout of the vertices. Implementations should feel free to return constants * for values that are unused in their layout. *

- * TODO: more flexible elements? */ public interface VertexList { float x(int index); diff --git a/src/main/java/com/jozufozu/flywheel/backend/BackendUtil.java b/src/main/java/com/jozufozu/flywheel/backend/BackendUtil.java deleted file mode 100644 index 15fc3e3e6..000000000 --- a/src/main/java/com/jozufozu/flywheel/backend/BackendUtil.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.jozufozu.flywheel.backend; - -import org.jetbrains.annotations.Contract; -import org.jetbrains.annotations.Nullable; - -import com.jozufozu.flywheel.api.FlywheelLevel; -import com.jozufozu.flywheel.api.backend.BackendManager; -import com.jozufozu.flywheel.backend.task.ParallelTaskExecutor; - -import net.minecraft.client.Minecraft; -import net.minecraft.world.level.LevelAccessor; - -public class BackendUtil { - private static ParallelTaskExecutor executor; - - /** - * Get a thread pool for running Flywheel related work in parallel. - * @return A global Flywheel thread pool. - */ - public static ParallelTaskExecutor getTaskExecutor() { - if (executor == null) { - executor = new ParallelTaskExecutor("Flywheel"); - executor.startWorkers(); - } - - return executor; - } - - @Contract("null -> false") - public static boolean canUseInstancing(@Nullable LevelAccessor level) { - return BackendManager.isOn() && isFlywheelLevel(level); - } - - /** - * Used to avoid calling Flywheel functions on (fake) levels that don't specifically support it. - */ - public static boolean isFlywheelLevel(@Nullable LevelAccessor level) { - if (level == null) { - return false; - } - - if (!level.isClientSide()) { - return false; - } - - if (level instanceof FlywheelLevel flywheelLevel && flywheelLevel.supportsFlywheel()) { - return true; - } - - return level == Minecraft.getInstance().level; - } - - public static boolean isGameActive() { - return !(Minecraft.getInstance().level == null || Minecraft.getInstance().player == null); - } -} diff --git a/src/main/java/com/jozufozu/flywheel/lib/backend/Backends.java b/src/main/java/com/jozufozu/flywheel/backend/Backends.java similarity index 80% rename from src/main/java/com/jozufozu/flywheel/lib/backend/Backends.java rename to src/main/java/com/jozufozu/flywheel/backend/Backends.java index 4535ab1fe..3cee46d2a 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/backend/Backends.java +++ b/src/main/java/com/jozufozu/flywheel/backend/Backends.java @@ -1,4 +1,4 @@ -package com.jozufozu.flywheel.lib.backend; +package com.jozufozu.flywheel.backend; import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.api.backend.Backend; @@ -6,30 +6,20 @@ import com.jozufozu.flywheel.backend.engine.batching.BatchingEngine; import com.jozufozu.flywheel.backend.engine.indirect.IndirectEngine; import com.jozufozu.flywheel.backend.engine.instancing.InstancingEngine; import com.jozufozu.flywheel.gl.versioned.GlCompat; +import com.jozufozu.flywheel.lib.backend.SimpleBackend; import com.jozufozu.flywheel.lib.context.Contexts; -import com.jozufozu.flywheel.lib.pipeline.Pipelines; import com.jozufozu.flywheel.lib.util.ShadersModHandler; import net.minecraft.ChatFormatting; import net.minecraft.network.chat.TextComponent; public class Backends { - public static final Backend OFF = SimpleBackend.builder() - .engineMessage(new TextComponent("Disabled Flywheel").withStyle(ChatFormatting.RED)) - .engineFactory(level -> { - throw new IllegalStateException("Cannot create engine when backend is off."); - }) - .fallback(() -> Backends.OFF) - .supported(() -> true) - .register(Flywheel.rl("off")); - /** * Use a thread pool to buffer instances in parallel on the CPU. */ public static final Backend BATCHING = SimpleBackend.builder() .engineMessage(new TextComponent("Using Batching Engine").withStyle(ChatFormatting.GREEN)) .engineFactory(level -> new BatchingEngine()) - .fallback(() -> Backends.OFF) .supported(() -> !ShadersModHandler.isShaderPackInUse()) .register(Flywheel.rl("batching")); diff --git a/src/main/java/com/jozufozu/flywheel/backend/Loader.java b/src/main/java/com/jozufozu/flywheel/backend/Loader.java index 69f72dbbe..362c401ec 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/Loader.java +++ b/src/main/java/com/jozufozu/flywheel/backend/Loader.java @@ -1,13 +1,11 @@ package com.jozufozu.flywheel.backend; -import com.jozufozu.flywheel.api.backend.BackendManager; import com.jozufozu.flywheel.backend.compile.FlwCompiler; import com.jozufozu.flywheel.glsl.ShaderSources; import com.jozufozu.flywheel.glsl.error.ErrorReporter; -import com.jozufozu.flywheel.impl.instancing.InstancedRenderDispatcher; +import com.jozufozu.flywheel.impl.BackendManagerImpl; import net.minecraft.client.Minecraft; -import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.server.packs.resources.ReloadableResourceManager; import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.server.packs.resources.ResourceManagerReloadListener; @@ -27,8 +25,6 @@ public class Loader implements ResourceManagerReloadListener { @Override public void onResourceManagerReload(ResourceManager manager) { - BackendManager.refresh(); - var errorReporter = new ErrorReporter(); ShaderSources sources = new ShaderSources(errorReporter, manager); @@ -38,14 +34,12 @@ public class Loader implements ResourceManagerReloadListener { FlwCompiler.INSTANCE = new FlwCompiler(sources); - ClientLevel level = Minecraft.getInstance().level; - if (level != null) { - InstancedRenderDispatcher.resetInstanceWorld(level); - } + // TODO: Move this to the impl package + BackendManagerImpl.refresh(Minecraft.getInstance().level); } public static void init() { - // Can be null when running datagenerators due to the unfortunate time we call this + // Can be null when running data generators due to the unfortunate time we call this Minecraft minecraft = Minecraft.getInstance(); if (minecraft == null) { return; diff --git a/src/main/java/com/jozufozu/flywheel/lib/pipeline/Pipelines.java b/src/main/java/com/jozufozu/flywheel/backend/Pipelines.java similarity index 93% rename from src/main/java/com/jozufozu/flywheel/lib/pipeline/Pipelines.java rename to src/main/java/com/jozufozu/flywheel/backend/Pipelines.java index f21a568cb..37b123de3 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/pipeline/Pipelines.java +++ b/src/main/java/com/jozufozu/flywheel/backend/Pipelines.java @@ -1,9 +1,10 @@ -package com.jozufozu.flywheel.lib.pipeline; +package com.jozufozu.flywheel.backend; import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.backend.engine.indirect.IndirectComponent; import com.jozufozu.flywheel.backend.engine.instancing.InstancedArraysComponent; import com.jozufozu.flywheel.gl.GLSLVersion; +import com.jozufozu.flywheel.lib.pipeline.SimplePipeline; import net.minecraft.resources.ResourceLocation; @@ -22,7 +23,6 @@ public class Pipelines { .build(); public static void init() { - // noop } public static class Files { diff --git a/src/main/java/com/jozufozu/flywheel/backend/compile/FlwCompiler.java b/src/main/java/com/jozufozu/flywheel/backend/compile/FlwCompiler.java index 910942501..2101a59c8 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/compile/FlwCompiler.java +++ b/src/main/java/com/jozufozu/flywheel/backend/compile/FlwCompiler.java @@ -17,6 +17,7 @@ import com.jozufozu.flywheel.api.pipeline.Pipeline; import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.api.uniform.ShaderUniforms; import com.jozufozu.flywheel.api.vertex.VertexType; +import com.jozufozu.flywheel.backend.Pipelines; import com.jozufozu.flywheel.backend.engine.indirect.IndirectComponent; import com.jozufozu.flywheel.gl.GLSLVersion; import com.jozufozu.flywheel.gl.shader.GlProgram; @@ -27,7 +28,6 @@ import com.jozufozu.flywheel.glsl.SourceComponent; import com.jozufozu.flywheel.glsl.generate.FnSignature; import com.jozufozu.flywheel.glsl.generate.GlslExpr; import com.jozufozu.flywheel.lib.material.MaterialIndices; -import com.jozufozu.flywheel.lib.pipeline.Pipelines; import com.jozufozu.flywheel.util.StringUtil; public class FlwCompiler { diff --git a/src/main/java/com/jozufozu/flywheel/backend/compile/ShaderCompiler.java b/src/main/java/com/jozufozu/flywheel/backend/compile/ShaderCompiler.java index 81622bc32..0326dbfb5 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/compile/ShaderCompiler.java +++ b/src/main/java/com/jozufozu/flywheel/backend/compile/ShaderCompiler.java @@ -13,7 +13,6 @@ import com.jozufozu.flywheel.gl.GLSLVersion; import com.jozufozu.flywheel.gl.shader.GlShader; import com.jozufozu.flywheel.gl.shader.ShaderType; import com.jozufozu.flywheel.glsl.SourceComponent; -import com.jozufozu.flywheel.util.FlwUtil; public class ShaderCompiler { private final Map shaderCache = new HashMap<>(); @@ -87,7 +86,7 @@ public class ShaderCompiler { } public static class Builder { - private Consumer errorConsumer = FlwUtil::noop; + private Consumer errorConsumer = error -> {}; private CompilationFactory factory = Compilation::new; private Includer includer = RecursiveIncluder.INSTANCE; diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/AbstractInstancer.java b/src/main/java/com/jozufozu/flywheel/backend/engine/AbstractInstancer.java index 6ec625409..8b43f4d82 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/AbstractInstancer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/AbstractInstancer.java @@ -2,14 +2,12 @@ package com.jozufozu.flywheel.backend.engine; import java.util.ArrayList; import java.util.BitSet; -import java.util.List; -import com.jozufozu.flywheel.api.instancer.InstancePart; import com.jozufozu.flywheel.api.instancer.Instancer; +import com.jozufozu.flywheel.api.struct.InstancePart; import com.jozufozu.flywheel.api.struct.StructType; public abstract class AbstractInstancer

implements Instancer

{ - public final StructType

type; // Lock for all instance data, only needs to be used in methods that may run on the TaskExecutor. @@ -42,30 +40,33 @@ public abstract class AbstractInstancer

implements Insta } } - /** - * Clear all instance data without freeing resources. - */ - public void clear() { - handles.forEach(HandleImpl::clear); - data.clear(); - handles.clear(); - changed.clear(); - deleted.clear(); - } - public int getInstanceCount() { return data.size(); } - public List

getRange(int start, int end) { - return data.subList(start, end); + public void notifyDirty(int index) { + if (index < 0 || index >= getInstanceCount()) { + return; + } + synchronized (lock) { + changed.set(index); + } } - public List

getAll() { - return data; + public void notifyRemoval(int index) { + if (index < 0 || index >= getInstanceCount()) { + return; + } + synchronized (lock) { + deleted.set(index); + } } protected void removeDeletedInstances() { + if (deleted.isEmpty()) { + return; + } + // Figure out which elements are to be removed. final int oldSize = this.data.size(); int removeCount = deleted.cardinality(); @@ -95,26 +96,19 @@ public abstract class AbstractInstancer

implements Insta .clear(); } + /** + * Clear all instance data without freeing resources. + */ + public void clear() { + handles.forEach(HandleImpl::clear); + data.clear(); + handles.clear(); + changed.clear(); + deleted.clear(); + } + @Override public String toString() { - return "Instancer[" + getInstanceCount() + ']'; - } - - public void notifyDirty(int index) { - if (index < 0 || index >= getInstanceCount()) { - return; - } - synchronized (lock) { - changed.set(index); - } - } - - public void notifyRemoval(int index) { - if (index < 0 || index >= getInstanceCount()) { - return; - } - synchronized (lock) { - deleted.set(index); - } + return "AbstractInstancer[" + getInstanceCount() + ']'; } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/HandleImpl.java b/src/main/java/com/jozufozu/flywheel/backend/engine/HandleImpl.java index 915ef8249..28ebebcda 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/HandleImpl.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/HandleImpl.java @@ -1,9 +1,8 @@ package com.jozufozu.flywheel.backend.engine; -import com.jozufozu.flywheel.api.instancer.Handle; +import com.jozufozu.flywheel.api.struct.Handle; public class HandleImpl implements Handle { - private final AbstractInstancer instancer; private int index; diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/InstancerKey.java b/src/main/java/com/jozufozu/flywheel/backend/engine/InstancerKey.java index 39fa9840a..3cbf4458a 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/InstancerKey.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/InstancerKey.java @@ -1,8 +1,8 @@ package com.jozufozu.flywheel.backend.engine; import com.jozufozu.flywheel.api.event.RenderStage; -import com.jozufozu.flywheel.api.instancer.InstancePart; import com.jozufozu.flywheel.api.model.Model; +import com.jozufozu.flywheel.api.struct.InstancePart; import com.jozufozu.flywheel.api.struct.StructType; public record InstancerKey

(StructType

type, Model model, RenderStage stage) { diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/UniformBuffer.java b/src/main/java/com/jozufozu/flywheel/backend/engine/UniformBuffer.java index 747bfcfd9..ee7497703 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/UniformBuffer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/UniformBuffer.java @@ -10,9 +10,9 @@ import com.jozufozu.flywheel.api.uniform.ShaderUniforms; import com.jozufozu.flywheel.gl.buffer.GlBuffer; import com.jozufozu.flywheel.gl.buffer.GlBufferType; import com.jozufozu.flywheel.gl.shader.GlProgram; +import com.jozufozu.flywheel.lib.math.MoreMath; +import com.jozufozu.flywheel.lib.math.RenderMath; import com.jozufozu.flywheel.lib.memory.MemoryBlock; -import com.jozufozu.flywheel.util.FlwUtil; -import com.jozufozu.flywheel.util.RenderMath; public class UniformBuffer { @@ -93,7 +93,7 @@ public class UniformBuffer { var builder = ImmutableList.builder(); int totalBytes = 0; for (ShaderUniforms provider : providers) { - int size = FlwUtil.align16(provider.byteSize()); + int size = MoreMath.align16(provider.byteSize()); builder.add(new LiveProvider(provider, totalBytes, size)); diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/batching/BatchedMeshPool.java b/src/main/java/com/jozufozu/flywheel/backend/engine/batching/BatchedMeshPool.java index 5bddbf1af..1dde158b4 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/batching/BatchedMeshPool.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/batching/BatchedMeshPool.java @@ -39,6 +39,10 @@ public class BatchedMeshPool { growthMargin = vertexFormat.getVertexSize() * 32; } + public VertexFormat getVertexFormat() { + return vertexFormat; + } + /** * Allocate a mesh in the arena. * @@ -139,10 +143,6 @@ public class BatchedMeshPool { pendingUpload.clear(); } - public VertexFormat getVertexFormat() { - return vertexFormat; - } - @Override public String toString() { return "BatchedMeshPool{" + "vertexFormat=" + vertexFormat + ", byteSize=" + byteSize + ", meshCount=" + meshes.size() + '}'; diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/batching/BatchingEngine.java b/src/main/java/com/jozufozu/flywheel/backend/engine/batching/BatchingEngine.java index 3e62c61ff..fc5a58870 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/batching/BatchingEngine.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/batching/BatchingEngine.java @@ -5,9 +5,9 @@ import java.util.List; import com.jozufozu.flywheel.api.backend.Engine; import com.jozufozu.flywheel.api.event.RenderContext; import com.jozufozu.flywheel.api.event.RenderStage; -import com.jozufozu.flywheel.api.instancer.InstancePart; import com.jozufozu.flywheel.api.instancer.Instancer; import com.jozufozu.flywheel.api.model.Model; +import com.jozufozu.flywheel.api.struct.InstancePart; import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.api.task.TaskExecutor; import com.jozufozu.flywheel.util.FlwUtil; diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/batching/BatchingTransformManager.java b/src/main/java/com/jozufozu/flywheel/backend/engine/batching/BatchingTransformManager.java index b07d78952..214a6c2c4 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/batching/BatchingTransformManager.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/batching/BatchingTransformManager.java @@ -15,10 +15,10 @@ import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ImmutableListMultimap; import com.google.common.collect.ListMultimap; import com.jozufozu.flywheel.api.event.RenderStage; -import com.jozufozu.flywheel.api.instancer.InstancePart; import com.jozufozu.flywheel.api.instancer.Instancer; import com.jozufozu.flywheel.api.model.Mesh; import com.jozufozu.flywheel.api.model.Model; +import com.jozufozu.flywheel.api.struct.InstancePart; import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.backend.engine.InstancerKey; import com.mojang.blaze3d.vertex.VertexFormat; @@ -83,7 +83,7 @@ public class BatchingTransformManager { var meshes = model.getMeshes(); for (var entry : meshes.entrySet()) { var material = entry.getKey(); - var renderType = material.getBatchingRenderType(); + RenderType renderType = material.getBatchingRenderType(); TransformCall transformCall = new TransformCall<>(instancer, material, alloc(entry.getValue(), renderType.format())); transformSet.put(renderType, transformCall); } diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/batching/CPUInstancer.java b/src/main/java/com/jozufozu/flywheel/backend/engine/batching/CPUInstancer.java index 99306a267..6ac7aad78 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/batching/CPUInstancer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/batching/CPUInstancer.java @@ -1,18 +1,25 @@ package com.jozufozu.flywheel.backend.engine.batching; -import com.jozufozu.flywheel.api.instancer.InstancePart; +import java.util.List; + +import com.jozufozu.flywheel.api.struct.InstancePart; import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.backend.engine.AbstractInstancer; public class CPUInstancer

extends AbstractInstancer

{ - public CPUInstancer(StructType

type) { super(type); } - void update() { - if (!deleted.isEmpty()) { - removeDeletedInstances(); - } + public List

getRange(int start, int end) { + return data.subList(start, end); + } + + public List

getAll() { + return data; + } + + public void update() { + removeDeletedInstances(); } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/batching/DrawBuffer.java b/src/main/java/com/jozufozu/flywheel/backend/engine/batching/DrawBuffer.java index aabe7de76..7d5318750 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/batching/DrawBuffer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/batching/DrawBuffer.java @@ -32,7 +32,7 @@ public class DrawBuffer { private boolean prepared; private int vertexCount; - DrawBuffer(RenderType renderType, VertexFormat format, int stride, VertexListProvider provider) { + public DrawBuffer(RenderType renderType, VertexFormat format, int stride, VertexListProvider provider) { this.renderType = renderType; this.format = format; this.stride = stride; diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/batching/DrawBufferSet.java b/src/main/java/com/jozufozu/flywheel/backend/engine/batching/DrawBufferSet.java index c4c15093f..884435ab8 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/batching/DrawBufferSet.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/batching/DrawBufferSet.java @@ -3,8 +3,6 @@ package com.jozufozu.flywheel.backend.engine.batching; import java.util.EnumMap; import java.util.Map; -import org.jetbrains.annotations.ApiStatus; - import com.jozufozu.flywheel.api.event.RenderStage; import com.jozufozu.flywheel.api.vertex.VertexListProvider; import com.jozufozu.flywheel.api.vertex.VertexListProviderRegistry; @@ -20,7 +18,6 @@ public class DrawBufferSet { private final Map buffers = new EnumMap<>(RenderStage.class); - @ApiStatus.Internal public DrawBufferSet(RenderType renderType) { this.renderType = renderType; format = renderType.format(); diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/batching/TransformCall.java b/src/main/java/com/jozufozu/flywheel/backend/engine/batching/TransformCall.java index 003337564..61f1c61ba 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/batching/TransformCall.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/batching/TransformCall.java @@ -2,17 +2,16 @@ package com.jozufozu.flywheel.backend.engine.batching; import java.util.List; -import com.jozufozu.flywheel.api.instancer.InstancePart; import com.jozufozu.flywheel.api.material.Material; -import com.jozufozu.flywheel.api.struct.StructType; +import com.jozufozu.flywheel.api.struct.InstancePart; +import com.jozufozu.flywheel.api.struct.StructVertexTransformer; import com.jozufozu.flywheel.api.task.TaskExecutor; import com.jozufozu.flywheel.api.vertex.MutableVertexList; import com.jozufozu.flywheel.api.vertex.ReusableVertexList; +import com.jozufozu.flywheel.lib.vertex.VertexTransformations; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.math.Matrix3f; import com.mojang.math.Matrix4f; -import com.mojang.math.Vector3f; -import com.mojang.math.Vector4f; import net.minecraft.client.multiplayer.ClientLevel; @@ -37,11 +36,11 @@ public class TransformCall

{ return meshVertexCount * instancer.getInstanceCount(); } - void setup() { + public void setup() { instancer.update(); } - void submitTasks(TaskExecutor executor, DrawBuffer buffer, int startVertex, PoseStack.Pose matrices, ClientLevel level) { + public void submitTasks(TaskExecutor executor, DrawBuffer buffer, int startVertex, PoseStack.Pose matrices, ClientLevel level) { int instances = instancer.getInstanceCount(); while (instances > 0) { @@ -57,21 +56,21 @@ public class TransformCall

{ } } - private void transformRange(ReusableVertexList vertexList, int from, int to, PoseStack.Pose matrices, ClientLevel level) { + public void transformRange(ReusableVertexList vertexList, int from, int to, PoseStack.Pose matrices, ClientLevel level) { transformList(vertexList, instancer.getRange(from, to), matrices, level); } - void transformAll(ReusableVertexList vertexList, PoseStack.Pose matrices, ClientLevel level) { + public void transformAll(ReusableVertexList vertexList, PoseStack.Pose matrices, ClientLevel level) { transformList(vertexList, instancer.getAll(), matrices, level); } - private void transformList(ReusableVertexList vertexList, List

parts, PoseStack.Pose matrices, ClientLevel level) { + public void transformList(ReusableVertexList vertexList, List

parts, PoseStack.Pose matrices, ClientLevel level) { long anchorPtr = vertexList.ptr(); int totalVertexCount = vertexList.vertexCount(); vertexList.vertexCount(meshVertexCount); - StructType.VertexTransformer

structVertexTransformer = instancer.type.getVertexTransformer(); + StructVertexTransformer

structVertexTransformer = instancer.type.getVertexTransformer(); for (P p : parts) { mesh.copyTo(vertexList.ptr()); @@ -88,34 +87,12 @@ public class TransformCall

{ } private static void applyMatrices(MutableVertexList vertexList, PoseStack.Pose matrices) { - Vector4f pos = new Vector4f(); - Vector3f normal = new Vector3f(); - Matrix4f modelMatrix = matrices.pose(); Matrix3f normalMatrix = matrices.normal(); for (int i = 0; i < vertexList.vertexCount(); i++) { - pos.set( - vertexList.x(i), - vertexList.y(i), - vertexList.z(i), - 1f - ); - pos.transform(modelMatrix); - vertexList.x(i, pos.x()); - vertexList.y(i, pos.y()); - vertexList.z(i, pos.z()); - - normal.set( - vertexList.normalX(i), - vertexList.normalY(i), - vertexList.normalZ(i) - ); - normal.transform(normalMatrix); - normal.normalize(); - vertexList.normalX(i, normal.x()); - vertexList.normalY(i, normal.y()); - vertexList.normalZ(i, normal.z()); + VertexTransformations.transformPos(vertexList, i, modelMatrix); + VertexTransformations.transformNormal(vertexList, i, normalMatrix); } } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectComponent.java b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectComponent.java index f82f04f41..ecdabd46e 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectComponent.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectComponent.java @@ -8,6 +8,7 @@ import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.api.layout.LayoutItem; import com.jozufozu.flywheel.api.pipeline.Pipeline; import com.jozufozu.flywheel.api.struct.StructType; +import com.jozufozu.flywheel.backend.Pipelines; import com.jozufozu.flywheel.glsl.ShaderSources; import com.jozufozu.flywheel.glsl.SourceComponent; import com.jozufozu.flywheel.glsl.SourceFile; @@ -15,7 +16,6 @@ import com.jozufozu.flywheel.glsl.generate.FnSignature; import com.jozufozu.flywheel.glsl.generate.GlslBlock; import com.jozufozu.flywheel.glsl.generate.GlslBuilder; import com.jozufozu.flywheel.glsl.generate.GlslExpr; -import com.jozufozu.flywheel.lib.pipeline.Pipelines; import net.minecraft.resources.ResourceLocation; diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectCullingGroup.java b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectCullingGroup.java index b5f9bed66..9636b512b 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectCullingGroup.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectCullingGroup.java @@ -12,14 +12,14 @@ import static org.lwjgl.opengl.GL45.glVertexArrayElementBuffer; import static org.lwjgl.opengl.GL45.glVertexArrayVertexBuffer; import com.jozufozu.flywheel.api.event.RenderStage; -import com.jozufozu.flywheel.api.instancer.InstancePart; +import com.jozufozu.flywheel.api.struct.InstancePart; import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.api.vertex.VertexType; +import com.jozufozu.flywheel.backend.Pipelines; import com.jozufozu.flywheel.backend.compile.FlwCompiler; import com.jozufozu.flywheel.backend.engine.UniformBuffer; import com.jozufozu.flywheel.gl.shader.GlProgram; import com.jozufozu.flywheel.lib.context.Contexts; -import com.jozufozu.flywheel.lib.pipeline.Pipelines; import com.jozufozu.flywheel.lib.util.QuadConverter; public class IndirectCullingGroup

{ @@ -109,7 +109,7 @@ public class IndirectCullingGroup

{ } buffers.updateCounts(instanceCountThisFrame, drawSet.size()); - meshPool.uploadAll(); + meshPool.flush(); uploadInstanceData(); uploadIndirectCommands(); @@ -174,7 +174,7 @@ public class IndirectCullingGroup

{ int baseInstance = 0; for (var batch : drawSet.indirectDraws) { batch.prepare(baseInstance); - baseInstance += batch.instancer().instanceCount; + baseInstance += batch.instancer().getInstanceCount(); } return baseInstance; } diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectDraw.java b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectDraw.java index bbc352f4c..d9a18a032 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectDraw.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectDraw.java @@ -3,32 +3,48 @@ package com.jozufozu.flywheel.backend.engine.indirect; import org.lwjgl.system.MemoryUtil; import com.jozufozu.flywheel.api.event.RenderStage; -import com.jozufozu.flywheel.api.instancer.InstancePart; import com.jozufozu.flywheel.api.material.Material; +import com.jozufozu.flywheel.api.struct.InstancePart; import com.jozufozu.flywheel.lib.material.MaterialIndices; -public final class IndirectDraw

{ +public class IndirectDraw

{ private final IndirectInstancer

instancer; private final IndirectMeshPool.BufferedMesh mesh; private final Material material; private final RenderStage stage; - int baseInstance = -1; - final int vertexMaterialID; - final int fragmentMaterialID; + private final int vertexMaterialID; + private final int fragmentMaterialID; - boolean needsFullWrite = true; + private int baseInstance = -1; + private boolean needsFullWrite = true; - IndirectDraw(IndirectInstancer

instancer, Material material, RenderStage stage, IndirectMeshPool.BufferedMesh mesh) { + public IndirectDraw(IndirectInstancer

instancer, Material material, IndirectMeshPool.BufferedMesh mesh, RenderStage stage) { this.instancer = instancer; this.material = material; - this.stage = stage; this.mesh = mesh; + this.stage = stage; this.vertexMaterialID = MaterialIndices.getVertexShaderIndex(material); this.fragmentMaterialID = MaterialIndices.getFragmentShaderIndex(material); } + public IndirectInstancer

instancer() { + return instancer; + } + + public Material material() { + return material; + } + + public IndirectMeshPool.BufferedMesh mesh() { + return mesh; + } + + public RenderStage stage() { + return stage; + } + public void prepare(int baseInstance) { instancer.update(); if (baseInstance == this.baseInstance) { @@ -39,7 +55,7 @@ public final class IndirectDraw

{ needsFullWrite = true; } - void writeObjects(long objectPtr, long batchIDPtr, int batchID) { + public void writeObjects(long objectPtr, long batchIDPtr, int batchID) { if (needsFullWrite) { instancer.writeFull(objectPtr, batchIDPtr, batchID); } else { @@ -48,7 +64,7 @@ public final class IndirectDraw

{ } public void writeIndirectCommand(long ptr) { - var boundingSphere = mesh.mesh.getBoundingSphere(); + var boundingSphere = mesh.getMesh().getBoundingSphere(); MemoryUtil.memPutInt(ptr, mesh.getIndexCount()); // count MemoryUtil.memPutInt(ptr + 4, 0); // instanceCount - to be incremented by the compute shader @@ -59,22 +75,5 @@ public final class IndirectDraw

{ boundingSphere.getToAddress(ptr + 20); // boundingSphere MemoryUtil.memPutInt(ptr + 36, vertexMaterialID); // vertexMaterialID MemoryUtil.memPutInt(ptr + 40, fragmentMaterialID); // fragmentMaterialID - - } - - public IndirectInstancer

instancer() { - return instancer; - } - - public IndirectMeshPool.BufferedMesh mesh() { - return mesh; - } - - public Material material() { - return material; - } - - public RenderStage stage() { - return stage; } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectDrawManager.java b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectDrawManager.java index 73eb23973..49ab8402c 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectDrawManager.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectDrawManager.java @@ -6,16 +6,15 @@ import java.util.List; import java.util.Map; import com.jozufozu.flywheel.api.event.RenderStage; -import com.jozufozu.flywheel.api.instancer.InstancePart; import com.jozufozu.flywheel.api.instancer.Instancer; import com.jozufozu.flywheel.api.model.Model; +import com.jozufozu.flywheel.api.struct.InstancePart; import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.api.vertex.VertexType; import com.jozufozu.flywheel.backend.engine.InstancerKey; import com.jozufozu.flywheel.util.Pair; public class IndirectDrawManager { - private final Map, IndirectInstancer> instancers = new HashMap<>(); private final List uninitializedInstancers = new ArrayList<>(); private final List> initializedInstancers = new ArrayList<>(); diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectDrawSet.java b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectDrawSet.java index 8fe598553..7f0080794 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectDrawSet.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectDrawSet.java @@ -11,10 +11,9 @@ import java.util.List; import java.util.Map; import com.jozufozu.flywheel.api.event.RenderStage; -import com.jozufozu.flywheel.api.instancer.InstancePart; import com.jozufozu.flywheel.api.material.Material; +import com.jozufozu.flywheel.api.struct.InstancePart; import com.jozufozu.flywheel.lib.material.MaterialIndices; -import com.jozufozu.flywheel.util.Textures; public class IndirectDrawSet

{ @@ -31,7 +30,7 @@ public class IndirectDrawSet

{ } public void add(IndirectInstancer

instancer, Material material, RenderStage stage, IndirectMeshPool.BufferedMesh bufferedMesh) { - indirectDraws.add(new IndirectDraw<>(instancer, material, stage, bufferedMesh)); + indirectDraws.add(new IndirectDraw<>(instancer, material, bufferedMesh, stage)); determineMultiDraws(); } diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectEngine.java b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectEngine.java index be3e9bb30..5c53a2261 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectEngine.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectEngine.java @@ -7,9 +7,9 @@ import org.lwjgl.opengl.GL32; import com.jozufozu.flywheel.api.backend.Engine; import com.jozufozu.flywheel.api.event.RenderContext; import com.jozufozu.flywheel.api.event.RenderStage; -import com.jozufozu.flywheel.api.instancer.InstancePart; import com.jozufozu.flywheel.api.instancer.Instancer; import com.jozufozu.flywheel.api.model.Model; +import com.jozufozu.flywheel.api.struct.InstancePart; import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.api.task.TaskExecutor; import com.jozufozu.flywheel.gl.GlStateTracker; diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectInstancer.java b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectInstancer.java index 4d50bafc5..e5f6282fa 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectInstancer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectInstancer.java @@ -2,52 +2,43 @@ package com.jozufozu.flywheel.backend.engine.indirect; import org.lwjgl.system.MemoryUtil; -import com.jozufozu.flywheel.api.instancer.InstancePart; +import com.jozufozu.flywheel.api.struct.InstancePart; import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.api.struct.StructWriter; import com.jozufozu.flywheel.backend.engine.AbstractInstancer; public class IndirectInstancer

extends AbstractInstancer

{ - - private final long objectStride; - private final StructWriter

writer; - int instanceCount = 0; + private final long instanceStride; public IndirectInstancer(StructType

type) { super(type); - this.objectStride = type.getLayout() + this.instanceStride = type.getLayout() .getStride(); - writer = type.getWriter(); } - public boolean isEmpty() { - return changed.isEmpty() && deleted.isEmpty() && instanceCount == 0; - } - - void update() { - if (!deleted.isEmpty()) { - removeDeletedInstances(); - } - - instanceCount = data.size(); + public void update() { + removeDeletedInstances(); } public void writeSparse(long objectPtr, long batchIDPtr, int batchID) { - final int size = data.size(); + int count = data.size(); + StructWriter

writer = type.getWriter(); + for (int i = changed.nextSetBit(0); i >= 0 && i < count; i = changed.nextSetBit(i + 1)) { + // write object + writer.write(objectPtr + instanceStride * i, data.get(i)); - for (int i = changed.nextSetBit(0); i >= 0 && i < size; i = changed.nextSetBit(i + 1)) { - writer.write(objectPtr + i * objectStride, data.get(i)); - - MemoryUtil.memPutInt(batchIDPtr + i * IndirectBuffers.INT_SIZE, batchID); + // write batchID + MemoryUtil.memPutInt(batchIDPtr + IndirectBuffers.INT_SIZE * i, batchID); } changed.clear(); } public void writeFull(long objectPtr, long batchIDPtr, int batchID) { + StructWriter

writer = type.getWriter(); for (var object : data) { // write object writer.write(objectPtr, object); - objectPtr += objectStride; + objectPtr += instanceStride; // write batchID MemoryUtil.memPutInt(batchIDPtr, batchID); diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectMeshPool.java b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectMeshPool.java index f7da98d36..c966ab56b 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectMeshPool.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectMeshPool.java @@ -39,6 +39,10 @@ public class IndirectMeshPool { clientStorage = MemoryBlock.malloc(byteCapacity); } + public VertexType getVertexType() { + return vertexType; + } + /** * Allocate a model in the arena. * @@ -60,24 +64,26 @@ public class IndirectMeshPool { return meshes.get(mesh); } - void uploadAll() { - if (!dirty) { - return; + public void flush() { + if (dirty) { + uploadAll(); + dirty = false; } - dirty = false; + } + private void uploadAll() { final long ptr = clientStorage.ptr(); int byteIndex = 0; int baseVertex = 0; - for (BufferedMesh model : meshList) { - model.byteIndex = byteIndex; - model.baseVertex = baseVertex; + for (BufferedMesh mesh : meshList) { + mesh.byteIndex = byteIndex; + mesh.baseVertex = baseVertex; - model.buffer(ptr); + mesh.buffer(ptr); - byteIndex += model.size(); - baseVertex += model.mesh.getVertexCount(); + byteIndex += mesh.size(); + baseVertex += mesh.mesh.getVertexCount(); } nglNamedBufferSubData(vbo, 0, byteIndex, ptr); @@ -90,26 +96,18 @@ public class IndirectMeshPool { meshList.clear(); } - public VertexType getVertexType() { - return vertexType; - } - public class BufferedMesh { - public final Mesh mesh; + private final Mesh mesh; private final int vertexCount; + private long byteIndex; private int baseVertex; private BufferedMesh(Mesh mesh) { this.mesh = mesh; - vertexCount = mesh.getVertexCount(); } - private void buffer(long ptr) { - mesh.write(ptr + byteIndex); - } - public Mesh getMesh() { return mesh; } @@ -129,5 +127,9 @@ public class IndirectMeshPool { public VertexType getVertexType() { return vertexType; } + + private void buffer(long ptr) { + mesh.write(ptr + byteIndex); + } } } diff --git a/src/main/java/com/jozufozu/flywheel/util/Textures.java b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/Textures.java similarity index 89% rename from src/main/java/com/jozufozu/flywheel/util/Textures.java rename to src/main/java/com/jozufozu/flywheel/backend/engine/indirect/Textures.java index f6292e966..7cc18e82e 100644 --- a/src/main/java/com/jozufozu/flywheel/util/Textures.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/Textures.java @@ -1,4 +1,4 @@ -package com.jozufozu.flywheel.util; +package com.jozufozu.flywheel.backend.engine.indirect; import org.lwjgl.opengl.GL32; diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/DrawCall.java b/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/DrawCall.java index 7c86e5f3e..9f152f392 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/DrawCall.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/DrawCall.java @@ -1,86 +1,50 @@ package com.jozufozu.flywheel.backend.engine.instancing; -import com.jozufozu.flywheel.api.material.Material; -import com.jozufozu.flywheel.api.vertex.VertexType; import com.jozufozu.flywheel.gl.GlStateTracker; import com.jozufozu.flywheel.gl.array.GlVertexArray; public class DrawCall { + private final GPUInstancer instancer; + private final InstancedMeshPool.BufferedMesh mesh; - final GPUInstancer instancer; - final Material material; private final int meshAttributes; - InstancedMeshPool.BufferedMesh bufferedMesh; - GlVertexArray vao; + private GlVertexArray vao; - DrawCall(GPUInstancer instancer, Material material, InstancedMeshPool.BufferedMesh mesh) { + public DrawCall(GPUInstancer instancer, InstancedMeshPool.BufferedMesh mesh) { this.instancer = instancer; - this.material = material; - this.vao = new GlVertexArray(); - this.bufferedMesh = mesh; - this.meshAttributes = this.bufferedMesh.getAttributeCount(); - this.vao.enableArrays(this.meshAttributes + instancer.instanceFormat.getAttributeCount()); + this.mesh = mesh; + + meshAttributes = this.mesh.getAttributeCount(); + vao = new GlVertexArray(); + vao.enableArrays(meshAttributes + this.instancer.getAttributeCount()); } - public Material getMaterial() { - return material; - } - - public VertexType getVertexType() { - return bufferedMesh.getVertexType(); + public boolean isInvalid() { + return instancer.isInvalid() || vao == null; } public void render() { - if (invalid()) { + if (isInvalid()) { return; } try (var ignored = GlStateTracker.getRestoreState()) { + instancer.update(); - this.instancer.update(); + instancer.bindToVAO(vao, meshAttributes); - bindInstancerToVAO(); - - if (this.instancer.glInstanceCount > 0) { - bufferedMesh.drawInstances(vao, this.instancer.glInstanceCount); + if (instancer.getInstanceCount() > 0) { + mesh.drawInstances(vao, instancer.getInstanceCount()); } } } - public boolean shouldRemove() { - return invalid(); - } - - /** - * Only {@code true} if the InstancedModel has been destroyed. - */ - private boolean invalid() { - return this.instancer.vbo == null || bufferedMesh == null || vao == null; - } - - private void bindInstancerToVAO() { - if (!this.instancer.boundTo.add(vao)) { - return; - } - - var instanceFormat = this.instancer.instanceFormat; - - vao.bindAttributes(this.instancer.vbo, this.meshAttributes, instanceFormat, 0L); - - for (int i = 0; i < instanceFormat.getAttributeCount(); i++) { - vao.setAttributeDivisor(this.meshAttributes + i, 1); - } - } - public void delete() { - if (invalid()) { + if (vao == null) { return; } vao.delete(); - bufferedMesh.delete(); - vao = null; - bufferedMesh = null; } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/GPUInstancer.java b/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/GPUInstancer.java index 55b48a75c..dbd5040c1 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/GPUInstancer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/GPUInstancer.java @@ -4,8 +4,8 @@ import java.util.HashSet; import java.util.Set; import com.jozufozu.flywheel.Flywheel; -import com.jozufozu.flywheel.api.instancer.InstancePart; import com.jozufozu.flywheel.api.layout.BufferLayout; +import com.jozufozu.flywheel.api.struct.InstancePart; import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.api.struct.StructWriter; import com.jozufozu.flywheel.backend.engine.AbstractInstancer; @@ -16,17 +16,24 @@ import com.jozufozu.flywheel.gl.buffer.GlBufferUsage; import com.jozufozu.flywheel.gl.buffer.MappedBuffer; public class GPUInstancer

extends AbstractInstancer

{ + private final BufferLayout instanceFormat; + private final int instanceStride; - final BufferLayout instanceFormat; - final Set boundTo = new HashSet<>(); - GlBuffer vbo; - int glInstanceCount = 0; - - boolean anyToUpdate; + private final Set boundTo = new HashSet<>(); + private GlBuffer vbo; public GPUInstancer(StructType

type) { super(type); - this.instanceFormat = type.getLayout(); + instanceFormat = type.getLayout(); + instanceStride = instanceFormat.getStride(); + } + + public int getAttributeCount() { + return instanceFormat.getAttributeCount(); + } + + public boolean isInvalid() { + return vbo == null; } public void init() { @@ -35,63 +42,59 @@ public class GPUInstancer

extends AbstractInstancer

{ } vbo = new GlBuffer(GlBufferType.ARRAY_BUFFER, GlBufferUsage.DYNAMIC_DRAW); - vbo.setGrowthMargin(instanceFormat.getStride() * 16); + vbo.setGrowthMargin(instanceStride * 16); } - public boolean isEmpty() { - return deleted.isEmpty() && changed.isEmpty() && glInstanceCount == 0; + public void update() { + removeDeletedInstances(); + ensureBufferCapacity(); + updateBuffer(); } - void update() { - if (!deleted.isEmpty()) { - removeDeletedInstances(); - } - - if (checkAndGrowBuffer()) { - // The instance vbo has moved, so we need to re-bind attributes + private void ensureBufferCapacity() { + int count = data.size(); + int byteSize = instanceStride * count; + if (vbo.ensureCapacity(byteSize)) { + // The vbo has moved, so we need to re-bind attributes boundTo.clear(); } - - if (!changed.isEmpty()) { - clearAndUpdateBuffer(); - } - - glInstanceCount = data.size(); } - private void clearAndUpdateBuffer() { - final int size = data.size(); - final long clearStart = (long) size * instanceFormat.getStride(); - final long clearLength = vbo.getSize() - clearStart; + private void updateBuffer() { + if (changed.isEmpty()) { + return; + } + + int count = data.size(); + long clearStart = instanceStride * (long) count; + long clearLength = vbo.getSize() - clearStart; try (MappedBuffer buf = vbo.map()) { buf.clear(clearStart, clearLength); - if (size > 0) { - final long ptr = buf.getPtr(); - final long stride = type.getLayout() - .getStride(); - final StructWriter

writer = type.getWriter(); + long ptr = buf.getPtr(); + StructWriter

writer = type.getWriter(); - for (int i = changed.nextSetBit(0); i >= 0 && i < size; i = changed.nextSetBit(i + 1)) { - writer.write(ptr + i * stride, data.get(i)); - } - changed.clear(); + for (int i = changed.nextSetBit(0); i >= 0 && i < count; i = changed.nextSetBit(i + 1)) { + writer.write(ptr + instanceStride * i, data.get(i)); } + + changed.clear(); } catch (Exception e) { Flywheel.LOGGER.error("Error updating GPUInstancer:", e); } } - /** - * @return {@code true} if the buffer moved. - */ - private boolean checkAndGrowBuffer() { - int size = this.data.size(); - int stride = instanceFormat.getStride(); - int requiredSize = size * stride; + public void bindToVAO(GlVertexArray vao, int attributeOffset) { + if (!boundTo.add(vao)) { + return; + } - return vbo.ensureCapacity(requiredSize); + vao.bindAttributes(vbo, attributeOffset, instanceFormat, 0L); + + for (int i = 0; i < instanceFormat.getAttributeCount(); i++) { + vao.setAttributeDivisor(attributeOffset + i, 1); + } } public void delete() { diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancedMeshPool.java b/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancedMeshPool.java index e9f9320c2..603b7bce8 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancedMeshPool.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancedMeshPool.java @@ -39,9 +39,12 @@ public class InstancedMeshPool { public InstancedMeshPool(VertexType vertexType) { this.vertexType = vertexType; int stride = vertexType.getLayout().getStride(); - this.vbo = new GlBuffer(GlBufferType.ARRAY_BUFFER); + vbo = new GlBuffer(GlBufferType.ARRAY_BUFFER); + vbo.setGrowthMargin(stride * 32); + } - this.vbo.setGrowthMargin(stride * 32); + public VertexType getVertexType() { + return vertexType; } /** @@ -161,10 +164,6 @@ public class InstancedMeshPool { pendingUpload.clear(); } - public VertexType getVertexType() { - return vertexType; - } - @Override public String toString() { return "InstancedMeshPool{" + "vertexType=" + vertexType + ", byteSize=" + byteSize + ", meshCount=" + meshes.size() + '}'; @@ -210,10 +209,6 @@ public class InstancedMeshPool { boundTo.clear(); } - public void drawCall(GlVertexArray vao) { - drawInstances(vao, 1); - } - public void drawInstances(GlVertexArray vao, int instanceCount) { if (isEmpty()) { return; diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancingDrawManager.java b/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancingDrawManager.java index 10c3fd563..d6165ddb8 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancingDrawManager.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancingDrawManager.java @@ -14,16 +14,15 @@ import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ImmutableListMultimap; import com.google.common.collect.ListMultimap; import com.jozufozu.flywheel.api.event.RenderStage; -import com.jozufozu.flywheel.api.instancer.InstancePart; import com.jozufozu.flywheel.api.instancer.Instancer; import com.jozufozu.flywheel.api.model.Mesh; import com.jozufozu.flywheel.api.model.Model; +import com.jozufozu.flywheel.api.struct.InstancePart; import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.api.vertex.VertexType; import com.jozufozu.flywheel.backend.engine.InstancerKey; public class InstancingDrawManager { - private final Map, GPUInstancer> instancers = new HashMap<>(); private final List uninitializedInstancers = new ArrayList<>(); private final List> initializedInstancers = new ArrayList<>(); @@ -48,9 +47,6 @@ public class InstancingDrawManager { public void flush() { for (var instancer : uninitializedInstancers) { - instancer.instancer() - .init(); - add(instancer.instancer(), instancer.model(), instancer.stage()); } uninitializedInstancers.clear(); @@ -80,11 +76,13 @@ public class InstancingDrawManager { } private void add(GPUInstancer instancer, Model model, RenderStage stage) { + instancer.init(); DrawSet drawSet = drawSets.computeIfAbsent(stage, DrawSet::new); var meshes = model.getMeshes(); for (var entry : meshes.entrySet()) { - DrawCall drawCall = new DrawCall(instancer, entry.getKey(), alloc(entry.getValue())); - var shaderState = new ShaderState(drawCall.getMaterial(), drawCall.getVertexType(), drawCall.instancer.type); + var mesh = alloc(entry.getValue()); + ShaderState shaderState = new ShaderState(entry.getKey(), mesh.getVertexType(), instancer.type); + DrawCall drawCall = new DrawCall(instancer, mesh); drawSet.put(shaderState, drawCall); } initializedInstancers.add(instancer); @@ -96,7 +94,6 @@ public class InstancingDrawManager { } public static class DrawSet implements Iterable>> { - public static final DrawSet EMPTY = new DrawSet(ImmutableListMultimap.of()); private final ListMultimap drawCalls; diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancingEngine.java b/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancingEngine.java index 8cfbb174b..80e0a6b3a 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancingEngine.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancingEngine.java @@ -8,17 +8,17 @@ import com.jozufozu.flywheel.api.backend.Engine; import com.jozufozu.flywheel.api.context.Context; import com.jozufozu.flywheel.api.event.RenderContext; import com.jozufozu.flywheel.api.event.RenderStage; -import com.jozufozu.flywheel.api.instancer.InstancePart; import com.jozufozu.flywheel.api.instancer.Instancer; import com.jozufozu.flywheel.api.model.Model; +import com.jozufozu.flywheel.api.struct.InstancePart; import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.api.task.TaskExecutor; +import com.jozufozu.flywheel.backend.Pipelines; import com.jozufozu.flywheel.backend.compile.FlwCompiler; import com.jozufozu.flywheel.backend.engine.UniformBuffer; import com.jozufozu.flywheel.gl.GlStateTracker; import com.jozufozu.flywheel.gl.GlTextureUnit; import com.jozufozu.flywheel.lib.material.MaterialIndices; -import com.jozufozu.flywheel.lib.pipeline.Pipelines; import com.mojang.blaze3d.systems.RenderSystem; import net.minecraft.client.Camera; @@ -47,7 +47,7 @@ public class InstancingEngine implements Engine { @Override public void beginFrame(TaskExecutor executor, RenderContext context) { - try (var restoreState = GlStateTracker.getRestoreState()) { + try (var state = GlStateTracker.getRestoreState()) { drawManager.flush(); } } @@ -60,7 +60,7 @@ public class InstancingEngine implements Engine { return; } - try (var restoreState = GlStateTracker.getRestoreState()) { + try (var state = GlStateTracker.getRestoreState()) { setup(); render(drawSet); @@ -83,7 +83,7 @@ public class InstancingEngine implements Engine { var shader = entry.getKey(); var drawCalls = entry.getValue(); - drawCalls.removeIf(DrawCall::shouldRemove); + drawCalls.removeIf(DrawCall::isInvalid); if (drawCalls.isEmpty()) { continue; @@ -102,9 +102,9 @@ public class InstancingEngine implements Engine { } private void setup(ShaderState desc) { - var vertexType = desc.vertex(); - var structType = desc.instance(); var material = desc.material(); + var vertexType = desc.vertexType(); + var structType = desc.instanceType(); var program = FlwCompiler.INSTANCE.getPipelineProgram(vertexType, structType, context, Pipelines.INSTANCED_ARRAYS); UniformBuffer.syncAndBind(program); diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/ShaderState.java b/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/ShaderState.java index c38be8946..420cfac1b 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/ShaderState.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/ShaderState.java @@ -4,5 +4,5 @@ import com.jozufozu.flywheel.api.material.Material; import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.api.vertex.VertexType; -public record ShaderState(Material material, VertexType vertex, StructType instance) { +public record ShaderState(Material material, VertexType vertexType, StructType instanceType) { } diff --git a/src/main/java/com/jozufozu/flywheel/backend/task/FlwTaskExecutor.java b/src/main/java/com/jozufozu/flywheel/backend/task/FlwTaskExecutor.java new file mode 100644 index 000000000..b88a1be76 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/task/FlwTaskExecutor.java @@ -0,0 +1,18 @@ +package com.jozufozu.flywheel.backend.task; + +public class FlwTaskExecutor { + private static ParallelTaskExecutor executor; + + /** + * Get a thread pool for running Flywheel related work in parallel. + * @return A global Flywheel thread pool. + */ + public static ParallelTaskExecutor get() { + if (executor == null) { + executor = new ParallelTaskExecutor("Flywheel"); + executor.startWorkers(); + } + + return executor; + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/task/ParallelTaskExecutor.java b/src/main/java/com/jozufozu/flywheel/backend/task/ParallelTaskExecutor.java index e8917fcad..351b3d8b9 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/task/ParallelTaskExecutor.java +++ b/src/main/java/com/jozufozu/flywheel/backend/task/ParallelTaskExecutor.java @@ -146,6 +146,28 @@ public class ParallelTaskExecutor implements TaskExecutor { } } + public void discardAndAwait() { + // Discard everyone else's work... + while (taskQueue.pollLast() != null) { + synchronized (tasksCompletedNotifier) { + if (--incompleteTaskCounter == 0) { + tasksCompletedNotifier.notifyAll(); + } + } + } + + // and wait for any stragglers. + synchronized (tasksCompletedNotifier) { + while (incompleteTaskCounter > 0) { + try { + tasksCompletedNotifier.wait(); + } catch (InterruptedException e) { + // + } + } + } + } + @Nullable private Runnable getNextTask() { Runnable task = taskQueue.pollFirst(); diff --git a/src/main/java/com/jozufozu/flywheel/config/BackendArgument.java b/src/main/java/com/jozufozu/flywheel/config/BackendArgument.java index 64e2bd23d..35e783735 100644 --- a/src/main/java/com/jozufozu/flywheel/config/BackendArgument.java +++ b/src/main/java/com/jozufozu/flywheel/config/BackendArgument.java @@ -9,20 +9,19 @@ import com.mojang.brigadier.StringReader; import com.mojang.brigadier.arguments.ArgumentType; import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.exceptions.CommandSyntaxException; -import com.mojang.brigadier.exceptions.Dynamic2CommandExceptionType; +import com.mojang.brigadier.exceptions.DynamicCommandExceptionType; import com.mojang.brigadier.suggestion.Suggestions; import com.mojang.brigadier.suggestion.SuggestionsBuilder; import net.minecraft.commands.SharedSuggestionProvider; -import net.minecraft.network.chat.TranslatableComponent; +import net.minecraft.network.chat.TextComponent; import net.minecraft.resources.ResourceLocation; public class BackendArgument implements ArgumentType { private static final List STRING_IDS = Backend.REGISTRY.getAllIds().stream().map(ResourceLocation::toString).toList(); - private static final Dynamic2CommandExceptionType INVALID = new Dynamic2CommandExceptionType((found, constants) -> { - // TODO: don't steal lang - return new TranslatableComponent("commands.forge.arguments.enum.invalid", constants, found); + public static final DynamicCommandExceptionType ERROR_UNKNOWN_BACKEND = new DynamicCommandExceptionType(arg -> { + return new TextComponent("Unknown backend '" + arg + "'"); }); public static final BackendArgument INSTANCE = new BackendArgument(); @@ -33,7 +32,7 @@ public class BackendArgument implements ArgumentType { Backend backend = Backend.REGISTRY.get(id); if (backend == null) { - throw INVALID.createWithContext(reader, id.toString(), STRING_IDS); + throw ERROR_UNKNOWN_BACKEND.createWithContext(reader, id.toString()); } return backend; diff --git a/src/main/java/com/jozufozu/flywheel/glsl/error/ErrorReporter.java b/src/main/java/com/jozufozu/flywheel/glsl/error/ErrorReporter.java index 9d534c029..084c1f707 100644 --- a/src/main/java/com/jozufozu/flywheel/glsl/error/ErrorReporter.java +++ b/src/main/java/com/jozufozu/flywheel/glsl/error/ErrorReporter.java @@ -9,7 +9,7 @@ import org.slf4j.Logger; import com.jozufozu.flywheel.glsl.ShaderLoadingException; import com.jozufozu.flywheel.glsl.SourceFile; import com.jozufozu.flywheel.glsl.span.Span; -import com.jozufozu.flywheel.util.FlwUtil; +import com.jozufozu.flywheel.lib.math.MoreMath; import com.jozufozu.flywheel.util.StringUtil; import com.mojang.logging.LogUtils; @@ -97,14 +97,14 @@ public class ErrorReporter { int size = lines.size(); - int maxWidth = FlwUtil.numDigits(size) + 1; + int maxWidth = MoreMath.numDigits(size) + 1; StringBuilder builder = new StringBuilder().append('\n'); for (int i = 0; i < size; i++) { builder.append(i) - .append(StringUtil.repeatChar(' ', maxWidth - FlwUtil.numDigits(i))) + .append(StringUtil.repeatChar(' ', maxWidth - MoreMath.numDigits(i))) .append("| ") .append(lines.get(i)) .append('\n'); diff --git a/src/main/java/com/jozufozu/flywheel/handler/EntityWorldHandler.java b/src/main/java/com/jozufozu/flywheel/handler/EntityWorldHandler.java index fd4895fda..9cefeb4a3 100644 --- a/src/main/java/com/jozufozu/flywheel/handler/EntityWorldHandler.java +++ b/src/main/java/com/jozufozu/flywheel/handler/EntityWorldHandler.java @@ -1,7 +1,7 @@ package com.jozufozu.flywheel.handler; -import com.jozufozu.flywheel.backend.BackendUtil; import com.jozufozu.flywheel.impl.instancing.InstancedRenderDispatcher; +import com.jozufozu.flywheel.util.FlwUtil; import net.minecraft.world.level.Level; import net.minecraftforge.event.entity.EntityJoinWorldEvent; @@ -14,7 +14,7 @@ public class EntityWorldHandler { return; } - if (BackendUtil.canUseInstancing(level)) { + if (FlwUtil.canUseInstancing(level)) { InstancedRenderDispatcher.getEntities(level) .queueAdd(event.getEntity()); } @@ -26,7 +26,7 @@ public class EntityWorldHandler { return; } - if (BackendUtil.canUseInstancing(level)) { + if (FlwUtil.canUseInstancing(level)) { InstancedRenderDispatcher.getEntities(level) .remove(event.getEntity()); } diff --git a/src/main/java/com/jozufozu/flywheel/handler/ForgeEvents.java b/src/main/java/com/jozufozu/flywheel/handler/ForgeEvents.java index 61e78fdc1..af04a70ed 100644 --- a/src/main/java/com/jozufozu/flywheel/handler/ForgeEvents.java +++ b/src/main/java/com/jozufozu/flywheel/handler/ForgeEvents.java @@ -3,10 +3,10 @@ package com.jozufozu.flywheel.handler; import java.util.ArrayList; import com.jozufozu.flywheel.Flywheel; -import com.jozufozu.flywheel.backend.BackendUtil; import com.jozufozu.flywheel.impl.instancing.InstancedRenderDispatcher; import com.jozufozu.flywheel.lib.light.LightUpdater; import com.jozufozu.flywheel.lib.memory.FlwMemoryTracker; +import com.jozufozu.flywheel.util.FlwUtil; import com.jozufozu.flywheel.util.StringUtil; import com.jozufozu.flywheel.util.WorldAttached; @@ -33,7 +33,7 @@ public class ForgeEvents { } public static void tickLight(TickEvent.ClientTickEvent event) { - if (event.phase == TickEvent.Phase.END && BackendUtil.isGameActive()) { + if (event.phase == TickEvent.Phase.END && FlwUtil.isGameActive()) { LightUpdater.get(Minecraft.getInstance().level) .tick(); } diff --git a/src/main/java/com/jozufozu/flywheel/impl/BackendManagerImpl.java b/src/main/java/com/jozufozu/flywheel/impl/BackendManagerImpl.java index c7a573b22..c2e4c73d8 100644 --- a/src/main/java/com/jozufozu/flywheel/impl/BackendManagerImpl.java +++ b/src/main/java/com/jozufozu/flywheel/impl/BackendManagerImpl.java @@ -3,14 +3,33 @@ package com.jozufozu.flywheel.impl; import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; +import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.api.backend.Backend; +import com.jozufozu.flywheel.api.event.ReloadRenderersEvent; +import com.jozufozu.flywheel.backend.Backends; import com.jozufozu.flywheel.config.FlwConfig; -import com.jozufozu.flywheel.lib.backend.Backends; +import com.jozufozu.flywheel.impl.instancing.InstancedRenderDispatcher; +import com.jozufozu.flywheel.lib.backend.SimpleBackend; import com.mojang.logging.LogUtils; +import net.minecraft.ChatFormatting; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.network.chat.TextComponent; +import net.minecraftforge.fml.CrashReportCallables; + public final class BackendManagerImpl { private static final Logger LOGGER = LogUtils.getLogger(); + + private static final Backend OFF_BACKEND = SimpleBackend.builder() + .engineMessage(new TextComponent("Disabled Flywheel").withStyle(ChatFormatting.RED)) + .engineFactory(level -> { + throw new IllegalStateException("Cannot create engine when backend is off."); + }) + .supported(() -> true) + .register(Flywheel.rl("off")); + private static final Backend DEFAULT_BACKEND = findDefaultBackend(); + private static Backend backend; @Nullable @@ -19,17 +38,35 @@ public final class BackendManagerImpl { } public static boolean isOn() { - return backend != null && backend != Backends.OFF; + return backend != null && backend != OFF_BACKEND; } - public static void refresh() { - backend = chooseBackend(); + public static Backend getOffBackend() { + return OFF_BACKEND; } public static Backend getDefaultBackend() { return DEFAULT_BACKEND; } + private static Backend findDefaultBackend() { + // TODO: Automatically select the best default config based on the user's driver + // TODO: Figure out how this will work if custom backends are registered and without hardcoding the default backends + return Backends.INDIRECT; + } + + public static void onReloadRenderers(ReloadRenderersEvent event) { + refresh(event.getLevel()); + } + + public static void refresh(@Nullable ClientLevel level) { + backend = chooseBackend(); + + if (level != null) { + InstancedRenderDispatcher.resetInstanceWorld(level); + } + } + private static Backend chooseBackend() { var preferred = FlwConfig.get().getBackend(); var actual = preferred.findFallback(); @@ -41,21 +78,17 @@ public final class BackendManagerImpl { return actual; } - private static Backend findDefaultBackend() { - // TODO: Automatically select the best default config based on the user's driver - // TODO: Figure out how this will work if custom backends are registered - return Backends.INDIRECT; - } - - public static String getBackendNameForCrashReport() { - if (backend == null) { - return "Uninitialized"; - } - var backendId = Backend.REGISTRY.getId(backend); - if (backendId == null) { - return "Unregistered"; - } - return backendId.toString(); + public static void init() { + CrashReportCallables.registerCrashCallable("Flywheel Backend", () -> { + if (backend == null) { + return "Uninitialized"; + } + var backendId = Backend.REGISTRY.getId(backend); + if (backendId == null) { + return "Unregistered"; + } + return backendId.toString(); + }); } private BackendManagerImpl() { diff --git a/src/main/java/com/jozufozu/flywheel/impl/instancing/InstanceWorld.java b/src/main/java/com/jozufozu/flywheel/impl/instancing/InstanceWorld.java index 635fff41d..e974d0b69 100644 --- a/src/main/java/com/jozufozu/flywheel/impl/instancing/InstanceWorld.java +++ b/src/main/java/com/jozufozu/flywheel/impl/instancing/InstanceWorld.java @@ -11,8 +11,8 @@ import com.jozufozu.flywheel.api.event.RenderStage; import com.jozufozu.flywheel.api.instance.DynamicInstance; import com.jozufozu.flywheel.api.instance.TickableInstance; import com.jozufozu.flywheel.api.instance.effect.Effect; -import com.jozufozu.flywheel.api.task.TaskExecutor; -import com.jozufozu.flywheel.backend.BackendUtil; +import com.jozufozu.flywheel.backend.task.FlwTaskExecutor; +import com.jozufozu.flywheel.backend.task.ParallelTaskExecutor; import com.jozufozu.flywheel.config.FlwCommands; import com.jozufozu.flywheel.config.FlwConfig; import com.jozufozu.flywheel.impl.instancing.manager.BlockEntityInstanceManager; @@ -27,9 +27,10 @@ import net.minecraft.world.level.block.entity.BlockEntity; /** * A manager class for a single world where instancing is supported. */ -public class InstanceWorld { +// AutoCloseable is implemented to prevent leaking this object from WorldAttached +public class InstanceWorld implements AutoCloseable { private final Engine engine; - private final TaskExecutor taskExecutor; + private final ParallelTaskExecutor taskExecutor; private final InstanceManager blockEntities; private final InstanceManager entities; @@ -37,7 +38,7 @@ public class InstanceWorld { public InstanceWorld(LevelAccessor level) { engine = BackendManager.getBackend().createEngine(level); - taskExecutor = BackendUtil.getTaskExecutor(); + taskExecutor = FlwTaskExecutor.get(); blockEntities = new BlockEntityInstanceManager(engine); entities = new EntityInstanceManager(engine); @@ -127,9 +128,15 @@ public class InstanceWorld { * Free all acquired resources and invalidate this instance world. */ public void delete() { + taskExecutor.discardAndAwait(); blockEntities.invalidate(); entities.invalidate(); effects.invalidate(); engine.delete(); } + + @Override + public void close() { + delete(); + } } diff --git a/src/main/java/com/jozufozu/flywheel/impl/instancing/InstancedRenderDispatcher.java b/src/main/java/com/jozufozu/flywheel/impl/instancing/InstancedRenderDispatcher.java index b44513e12..11aaaabd3 100644 --- a/src/main/java/com/jozufozu/flywheel/impl/instancing/InstancedRenderDispatcher.java +++ b/src/main/java/com/jozufozu/flywheel/impl/instancing/InstancedRenderDispatcher.java @@ -3,14 +3,13 @@ package com.jozufozu.flywheel.impl.instancing; import java.util.List; import com.jozufozu.flywheel.api.event.BeginFrameEvent; -import com.jozufozu.flywheel.api.event.ReloadRenderersEvent; import com.jozufozu.flywheel.api.event.RenderStageEvent; import com.jozufozu.flywheel.api.instance.Instance; import com.jozufozu.flywheel.api.instance.effect.Effect; -import com.jozufozu.flywheel.backend.BackendUtil; import com.jozufozu.flywheel.extension.ClientLevelExtension; import com.jozufozu.flywheel.impl.instancing.manager.InstanceManager; -import com.jozufozu.flywheel.util.AnimationTickHolder; +import com.jozufozu.flywheel.lib.util.AnimationTickHolder; +import com.jozufozu.flywheel.util.FlwUtil; import com.jozufozu.flywheel.util.WorldAttached; import net.minecraft.client.Minecraft; @@ -34,7 +33,7 @@ public class InstancedRenderDispatcher { return; } - if (!BackendUtil.canUseInstancing(level)) { + if (!FlwUtil.canUseInstancing(level)) { return; } @@ -49,7 +48,7 @@ public class InstancedRenderDispatcher { */ public static void queueUpdate(Entity entity) { Level level = entity.level; - if (!BackendUtil.canUseInstancing(level)) { + if (!FlwUtil.canUseInstancing(level)) { return; } @@ -63,7 +62,7 @@ public class InstancedRenderDispatcher { * @param effect The effect whose instance you want to update. */ public static void queueUpdate(LevelAccessor level, Effect effect) { - if (!BackendUtil.canUseInstancing(level)) { + if (!FlwUtil.canUseInstancing(level)) { return; } @@ -77,7 +76,7 @@ public class InstancedRenderDispatcher { * @throws IllegalStateException if the backend is off */ private static InstanceWorld getInstanceWorld(LevelAccessor level) { - if (!BackendUtil.canUseInstancing(level)) { + if (!FlwUtil.canUseInstancing(level)) { throw new IllegalStateException("Cannot retrieve instance world when backend is off!"); } return INSTANCE_WORLDS.get(level); @@ -100,7 +99,7 @@ public class InstancedRenderDispatcher { } public static void tick(TickEvent.ClientTickEvent event) { - if (!BackendUtil.isGameActive() || event.phase == TickEvent.Phase.START) { + if (!FlwUtil.isGameActive() || event.phase == TickEvent.Phase.START) { return; } @@ -117,7 +116,7 @@ public class InstancedRenderDispatcher { } Level level = cameraEntity.level; - if (!BackendUtil.canUseInstancing(level)) { + if (!FlwUtil.canUseInstancing(level)) { return; } @@ -129,12 +128,12 @@ public class InstancedRenderDispatcher { } public static void onBeginFrame(BeginFrameEvent event) { - if (!BackendUtil.isGameActive()) { + if (!FlwUtil.isGameActive()) { return; } ClientLevel level = event.getContext().level(); - if (!BackendUtil.canUseInstancing(level)) { + if (!FlwUtil.canUseInstancing(level)) { return; } @@ -143,26 +142,17 @@ public class InstancedRenderDispatcher { public static void onRenderStage(RenderStageEvent event) { ClientLevel level = event.getContext().level(); - if (!BackendUtil.canUseInstancing(level)) { + if (!FlwUtil.canUseInstancing(level)) { return; } INSTANCE_WORLDS.get(level).renderStage(event.getContext(), event.getStage()); } - public static void onReloadRenderers(ReloadRenderersEvent event) { - ClientLevel level = event.getLevel(); - if (level == null) { - return; - } - - resetInstanceWorld(level); - } - public static void resetInstanceWorld(ClientLevel level) { INSTANCE_WORLDS.remove(level, InstanceWorld::delete); - if (!BackendUtil.canUseInstancing(level)) { + if (!FlwUtil.canUseInstancing(level)) { return; } @@ -175,7 +165,7 @@ public class InstancedRenderDispatcher { public static void addDebugInfo(List info) { ClientLevel level = Minecraft.getInstance().level; - if (BackendUtil.canUseInstancing(level)) { + if (FlwUtil.canUseInstancing(level)) { INSTANCE_WORLDS.get(level).addDebugInfo(info); } else { info.add("Disabled"); diff --git a/src/main/java/com/jozufozu/flywheel/impl/instancing/manager/BlockEntityInstanceManager.java b/src/main/java/com/jozufozu/flywheel/impl/instancing/manager/BlockEntityInstanceManager.java index e43961527..cf4a7ba84 100644 --- a/src/main/java/com/jozufozu/flywheel/impl/instancing/manager/BlockEntityInstanceManager.java +++ b/src/main/java/com/jozufozu/flywheel/impl/instancing/manager/BlockEntityInstanceManager.java @@ -8,10 +8,10 @@ import com.jozufozu.flywheel.api.backend.Engine; import com.jozufozu.flywheel.api.instance.BlockEntityInstance; import com.jozufozu.flywheel.api.instance.Instance; import com.jozufozu.flywheel.api.instance.controller.InstanceContext; -import com.jozufozu.flywheel.backend.BackendUtil; import com.jozufozu.flywheel.impl.instancing.InstancingControllerHelper; import com.jozufozu.flywheel.impl.instancing.storage.One2OneStorage; import com.jozufozu.flywheel.impl.instancing.storage.Storage; +import com.jozufozu.flywheel.util.FlwUtil; import it.unimi.dsi.fastutil.longs.Long2ObjectMap; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; @@ -66,7 +66,7 @@ public class BlockEntityInstanceManager extends InstanceManager { return false; } - if (BackendUtil.isFlywheelLevel(level)) { + if (FlwUtil.isFlywheelLevel(level)) { BlockPos pos = blockEntity.getBlockPos(); BlockGetter existingChunk = level.getChunkForCollisions(pos.getX() >> 4, pos.getZ() >> 4); diff --git a/src/main/java/com/jozufozu/flywheel/impl/instancing/manager/EntityInstanceManager.java b/src/main/java/com/jozufozu/flywheel/impl/instancing/manager/EntityInstanceManager.java index b76c1966d..5e1474f55 100644 --- a/src/main/java/com/jozufozu/flywheel/impl/instancing/manager/EntityInstanceManager.java +++ b/src/main/java/com/jozufozu/flywheel/impl/instancing/manager/EntityInstanceManager.java @@ -5,10 +5,10 @@ import org.jetbrains.annotations.Nullable; import com.jozufozu.flywheel.api.backend.Engine; import com.jozufozu.flywheel.api.instance.Instance; import com.jozufozu.flywheel.api.instance.controller.InstanceContext; -import com.jozufozu.flywheel.backend.BackendUtil; import com.jozufozu.flywheel.impl.instancing.InstancingControllerHelper; import com.jozufozu.flywheel.impl.instancing.storage.One2OneStorage; import com.jozufozu.flywheel.impl.instancing.storage.Storage; +import com.jozufozu.flywheel.util.FlwUtil; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.Level; @@ -53,7 +53,7 @@ public class EntityInstanceManager extends InstanceManager { Level level = entity.level; - return BackendUtil.isFlywheelLevel(level); + return FlwUtil.isFlywheelLevel(level); } } } diff --git a/src/main/java/com/jozufozu/flywheel/impl/instancing/manager/InstanceManager.java b/src/main/java/com/jozufozu/flywheel/impl/instancing/manager/InstanceManager.java index 05a90f292..ff0c5535d 100644 --- a/src/main/java/com/jozufozu/flywheel/impl/instancing/manager/InstanceManager.java +++ b/src/main/java/com/jozufozu/flywheel/impl/instancing/manager/InstanceManager.java @@ -64,6 +64,14 @@ public abstract class InstanceManager { queue.add(Transaction.add(obj)); } + public void remove(T obj) { + getStorage().remove(obj); + } + + public void queueRemove(T obj) { + queue.add(Transaction.remove(obj)); + } + /** * Update the instance associated with an object. * @@ -91,10 +99,6 @@ public abstract class InstanceManager { queue.add(Transaction.update(obj)); } - public void remove(T obj) { - getStorage().remove(obj); - } - public void recreateAll() { getStorage().recreateAll(); } diff --git a/src/main/java/com/jozufozu/flywheel/impl/vertex/InferredVertexListImpl.java b/src/main/java/com/jozufozu/flywheel/impl/vertex/InferredVertexListImpl.java index 125143446..3f541d157 100644 --- a/src/main/java/com/jozufozu/flywheel/impl/vertex/InferredVertexListImpl.java +++ b/src/main/java/com/jozufozu/flywheel/impl/vertex/InferredVertexListImpl.java @@ -4,7 +4,7 @@ import org.lwjgl.system.MemoryUtil; import com.jozufozu.flywheel.api.vertex.ReusableVertexList; import com.jozufozu.flywheel.lib.format.AbstractVertexList; -import com.jozufozu.flywheel.util.RenderMath; +import com.jozufozu.flywheel.lib.math.RenderMath; import com.mojang.blaze3d.vertex.VertexFormat; import net.minecraft.client.renderer.LightTexture; diff --git a/src/main/java/com/jozufozu/flywheel/lib/backend/SimpleBackend.java b/src/main/java/com/jozufozu/flywheel/lib/backend/SimpleBackend.java index 07aff3df7..8f1f80703 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/backend/SimpleBackend.java +++ b/src/main/java/com/jozufozu/flywheel/lib/backend/SimpleBackend.java @@ -7,6 +7,7 @@ import java.util.function.Supplier; import org.jetbrains.annotations.Nullable; import com.jozufozu.flywheel.api.backend.Backend; +import com.jozufozu.flywheel.api.backend.BackendManager; import com.jozufozu.flywheel.api.backend.Engine; import com.jozufozu.flywheel.api.pipeline.Pipeline; @@ -66,7 +67,7 @@ public class SimpleBackend implements Backend { public static class Builder { private Component engineMessage; private Function engineFactory; - private Supplier fallback; + private Supplier fallback = BackendManager::getOffBackend; private BooleanSupplier isSupported; private Pipeline pipelineShader; diff --git a/src/main/java/com/jozufozu/flywheel/lib/box/ImmutableBox.java b/src/main/java/com/jozufozu/flywheel/lib/box/ImmutableBox.java index e6cfc46dc..0ed8fbc22 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/box/ImmutableBox.java +++ b/src/main/java/com/jozufozu/flywheel/lib/box/ImmutableBox.java @@ -1,6 +1,6 @@ package com.jozufozu.flywheel.lib.box; -import static com.jozufozu.flywheel.util.RenderMath.isPowerOf2; +import static com.jozufozu.flywheel.lib.math.RenderMath.isPowerOf2; import net.minecraft.world.phys.AABB; diff --git a/src/main/java/com/jozufozu/flywheel/lib/box/MutableBox.java b/src/main/java/com/jozufozu/flywheel/lib/box/MutableBox.java index f052647c8..e8300bcb6 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/box/MutableBox.java +++ b/src/main/java/com/jozufozu/flywheel/lib/box/MutableBox.java @@ -2,7 +2,7 @@ package com.jozufozu.flywheel.lib.box; import java.util.Collection; -import com.jozufozu.flywheel.util.RenderMath; +import com.jozufozu.flywheel.lib.math.RenderMath; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -19,7 +19,6 @@ public class MutableBox implements ImmutableBox { private int maxZ; public MutableBox() { - } public MutableBox(int minX, int minY, int minZ, int maxX, int maxY, int maxZ) { diff --git a/src/main/java/com/jozufozu/flywheel/lib/context/Contexts.java b/src/main/java/com/jozufozu/flywheel/lib/context/Contexts.java index a234f276c..89207df19 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/context/Contexts.java +++ b/src/main/java/com/jozufozu/flywheel/lib/context/Contexts.java @@ -1,27 +1,29 @@ package com.jozufozu.flywheel.lib.context; +import org.jetbrains.annotations.ApiStatus; + import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.api.context.Context; import com.jozufozu.flywheel.util.ResourceUtil; import net.minecraft.resources.ResourceLocation; -public class Contexts { +public final class Contexts { public static final SimpleContext WORLD = Context.REGISTRY.registerAndGet(new SimpleContext(Files.WORLD_VERTEX, Files.WORLD_FRAGMENT)); public static final SimpleContext CRUMBLING = Context.REGISTRY.registerAndGet(new SimpleContext(Files.WORLD_VERTEX, Files.CRUMBLING_FRAGMENT)); + @ApiStatus.Internal public static void init() { - // noop } - public static class Files { + public static final class Files { public static final ResourceLocation WORLD_VERTEX = ResourceUtil.subPath(Names.WORLD, ".vert"); public static final ResourceLocation WORLD_FRAGMENT = ResourceUtil.subPath(Names.WORLD, ".frag"); public static final ResourceLocation CRUMBLING_VERTEX = ResourceUtil.subPath(Names.CRUMBLING, ".vert"); public static final ResourceLocation CRUMBLING_FRAGMENT = ResourceUtil.subPath(Names.CRUMBLING, ".frag"); } - public static class Names { + public static final class Names { public static final ResourceLocation WORLD = Flywheel.rl("context/world"); public static final ResourceLocation CRUMBLING = Flywheel.rl("context/crumbling"); } diff --git a/src/main/java/com/jozufozu/flywheel/lib/format/BlockVertexList.java b/src/main/java/com/jozufozu/flywheel/lib/format/BlockVertexList.java index 903f4bff7..45b56f035 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/format/BlockVertexList.java +++ b/src/main/java/com/jozufozu/flywheel/lib/format/BlockVertexList.java @@ -3,7 +3,7 @@ package com.jozufozu.flywheel.lib.format; import org.lwjgl.system.MemoryUtil; import com.jozufozu.flywheel.api.vertex.MutableVertexList; -import com.jozufozu.flywheel.util.RenderMath; +import com.jozufozu.flywheel.lib.math.RenderMath; import net.minecraft.client.renderer.texture.OverlayTexture; diff --git a/src/main/java/com/jozufozu/flywheel/lib/format/Formats.java b/src/main/java/com/jozufozu/flywheel/lib/format/Formats.java index d48980171..7955bbb15 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/format/Formats.java +++ b/src/main/java/com/jozufozu/flywheel/lib/format/Formats.java @@ -1,25 +1,27 @@ package com.jozufozu.flywheel.lib.format; +import org.jetbrains.annotations.ApiStatus; + import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.api.vertex.VertexType; import com.jozufozu.flywheel.util.ResourceUtil; import net.minecraft.resources.ResourceLocation; -public class Formats { +public final class Formats { public static final BlockVertex BLOCK = VertexType.REGISTRY.registerAndGet(new BlockVertex()); public static final PosTexNormalVertex POS_TEX_NORMAL = VertexType.REGISTRY.registerAndGet(new PosTexNormalVertex()); + @ApiStatus.Internal public static void init() { - // noop } - public static class Files { + public static final class Files { public static final ResourceLocation BLOCK_LAYOUT = ResourceUtil.subPath(Names.BLOCK, ".vert"); public static final ResourceLocation POS_TEX_NORMAL_LAYOUT = ResourceUtil.subPath(Names.POS_TEX_NORMAL, ".vert"); } - public static class Names { + public static final class Names { public static final ResourceLocation BLOCK = Flywheel.rl("layout/block"); public static final ResourceLocation POS_TEX_NORMAL = Flywheel.rl("layout/pos_tex_normal"); } diff --git a/src/main/java/com/jozufozu/flywheel/lib/format/PosTexNormalVertexList.java b/src/main/java/com/jozufozu/flywheel/lib/format/PosTexNormalVertexList.java index 6e69bf9a9..5581d5844 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/format/PosTexNormalVertexList.java +++ b/src/main/java/com/jozufozu/flywheel/lib/format/PosTexNormalVertexList.java @@ -3,7 +3,7 @@ package com.jozufozu.flywheel.lib.format; import org.lwjgl.system.MemoryUtil; import com.jozufozu.flywheel.api.vertex.MutableVertexList; -import com.jozufozu.flywheel.util.RenderMath; +import com.jozufozu.flywheel.lib.math.RenderMath; import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.texture.OverlayTexture; diff --git a/src/main/java/com/jozufozu/flywheel/lib/layout/CommonItems.java b/src/main/java/com/jozufozu/flywheel/lib/layout/CommonItems.java index 3f289300a..bd6165595 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/layout/CommonItems.java +++ b/src/main/java/com/jozufozu/flywheel/lib/layout/CommonItems.java @@ -5,7 +5,6 @@ import com.jozufozu.flywheel.gl.array.VertexAttributeF; import com.jozufozu.flywheel.gl.array.VertexAttributeI; public class CommonItems { - private static final String VEC2_TYPE = "vec2"; private static final String VEC3_TYPE = "vec3"; private static final String VEC4_TYPE = "vec4"; @@ -16,6 +15,7 @@ public class CommonItems { private static final String FLOAT_TYPE = "float"; private static final String UINT_TYPE = "uint"; private static final String LIGHT_COORD_TYPE = "LightCoord"; + public static final VecInput LIGHT_COORD = VecInput.builder() .vertexAttribute(new VertexAttributeI(GlNumericType.USHORT, 2)) .typeName(IVEC2_TYPE) @@ -69,8 +69,4 @@ public class CommonItems { public static final MatInput MAT3 = new MatInput(3, 3, "mat3", "Mat3F", "unpackMat3F"); public static final MatInput MAT4 = new MatInput(4, 4, "mat4", "Mat4F", "unpackMat4F"); - - private static class Unpacking { - - } } diff --git a/src/main/java/com/jozufozu/flywheel/lib/light/LightUpdater.java b/src/main/java/com/jozufozu/flywheel/lib/light/LightUpdater.java index 52bba12df..3bd003cd6 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/light/LightUpdater.java +++ b/src/main/java/com/jozufozu/flywheel/lib/light/LightUpdater.java @@ -5,7 +5,7 @@ import java.util.Set; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.stream.Stream; -import com.jozufozu.flywheel.backend.BackendUtil; +import com.jozufozu.flywheel.backend.task.FlwTaskExecutor; import com.jozufozu.flywheel.lib.box.ImmutableBox; import com.jozufozu.flywheel.lib.task.WorkGroup; import com.jozufozu.flywheel.util.FlwUtil; @@ -23,7 +23,6 @@ import net.minecraft.world.level.LightLayer; * {@link LightUpdated} for LightUpdater to work with them. */ public class LightUpdater { - private static final WorldAttached LEVELS = new WorldAttached<>(LightUpdater::new); private final LevelAccessor level; @@ -68,7 +67,7 @@ public class LightUpdater { } }) .onComplete(() -> listeners.forEach(this::addListener)) - .execute(BackendUtil.getTaskExecutor()); + .execute(FlwTaskExecutor.get()); } /** diff --git a/src/main/java/com/jozufozu/flywheel/lib/material/MaterialIndices.java b/src/main/java/com/jozufozu/flywheel/lib/material/MaterialIndices.java index 78a619dda..61baac3a7 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/material/MaterialIndices.java +++ b/src/main/java/com/jozufozu/flywheel/lib/material/MaterialIndices.java @@ -21,7 +21,7 @@ import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap; import net.minecraft.resources.ResourceLocation; // TODO: add messages to exceptions -public class MaterialIndices { +public final class MaterialIndices { private static Reference2IntMap materialIndices; private static Object2IntMap vertexShaderIndices; private static Object2IntMap fragmentShaderIndices; diff --git a/src/main/java/com/jozufozu/flywheel/lib/material/Materials.java b/src/main/java/com/jozufozu/flywheel/lib/material/Materials.java index 1053a0014..6178eab54 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/material/Materials.java +++ b/src/main/java/com/jozufozu/flywheel/lib/material/Materials.java @@ -1,11 +1,14 @@ package com.jozufozu.flywheel.lib.material; +import org.jetbrains.annotations.ApiStatus; + import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.api.material.Material; +import com.jozufozu.flywheel.api.material.MaterialVertexTransformer; import com.jozufozu.flywheel.gl.GlTextureUnit; import com.jozufozu.flywheel.lib.material.SimpleMaterial.GlStateShard; +import com.jozufozu.flywheel.lib.math.DiffuseLightCalculator; import com.jozufozu.flywheel.lib.util.ShadersModHandler; -import com.jozufozu.flywheel.util.DiffuseLightCalculator; import com.jozufozu.flywheel.util.ResourceUtil; import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.systems.RenderSystem; @@ -18,7 +21,7 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.world.inventory.InventoryMenu; public final class Materials { - public static final Material.VertexTransformer SHADING_TRANSFORMER = (vertexList, level) -> { + public static final MaterialVertexTransformer SHADING_TRANSFORMER = (vertexList, level) -> { if (ShadersModHandler.isShaderPackInUse()) { return; } @@ -131,8 +134,8 @@ public final class Materials { .batchingRenderType(RenderType.entitySolid(MINECART_LOCATION)) .register(); + @ApiStatus.Internal public static void init() { - // noop } public static final class Shards { @@ -173,14 +176,14 @@ public final class Materials { } } - public static class Files { + public static final class Files { public static final ResourceLocation DEFAULT_VERTEX = ResourceUtil.subPath(Names.DEFAULT, ".vert"); public static final ResourceLocation SHADED_VERTEX = ResourceUtil.subPath(Names.SHADED, ".vert"); public static final ResourceLocation DEFAULT_FRAGMENT = ResourceUtil.subPath(Names.DEFAULT, ".frag"); public static final ResourceLocation CUTOUT_FRAGMENT = ResourceUtil.subPath(Names.CUTOUT, ".frag"); } - public static class Names { + public static final class Names { public static final ResourceLocation DEFAULT = Flywheel.rl("material/default"); public static final ResourceLocation CUTOUT = Flywheel.rl("material/cutout"); public static final ResourceLocation SHADED = Flywheel.rl("material/shaded"); diff --git a/src/main/java/com/jozufozu/flywheel/lib/material/SimpleMaterial.java b/src/main/java/com/jozufozu/flywheel/lib/material/SimpleMaterial.java index f21a809c2..e25cb070a 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/material/SimpleMaterial.java +++ b/src/main/java/com/jozufozu/flywheel/lib/material/SimpleMaterial.java @@ -1,6 +1,7 @@ package com.jozufozu.flywheel.lib.material; import com.jozufozu.flywheel.api.material.Material; +import com.jozufozu.flywheel.api.material.MaterialVertexTransformer; import net.minecraft.client.renderer.RenderStateShard; import net.minecraft.client.renderer.RenderType; @@ -12,9 +13,9 @@ public class SimpleMaterial implements Material { protected final Runnable setup; protected final Runnable clear; protected final RenderType batchingRenderType; - protected final VertexTransformer vertexTransformer; + protected final MaterialVertexTransformer vertexTransformer; - public SimpleMaterial(ResourceLocation vertexShader, ResourceLocation fragmentShader, Runnable setup, Runnable clear, RenderType batchingRenderType, VertexTransformer vertexTransformer) { + public SimpleMaterial(ResourceLocation vertexShader, ResourceLocation fragmentShader, Runnable setup, Runnable clear, RenderType batchingRenderType, MaterialVertexTransformer vertexTransformer) { this.vertexShader = vertexShader; this.fragmentShader = fragmentShader; this.setup = setup; @@ -53,7 +54,7 @@ public class SimpleMaterial implements Material { } @Override - public VertexTransformer getVertexTransformer() { + public MaterialVertexTransformer getVertexTransformer() { return vertexTransformer; } @@ -63,8 +64,7 @@ public class SimpleMaterial implements Material { protected Runnable setup = () -> {}; protected Runnable clear = () -> {}; protected RenderType batchingRenderType = RenderType.solid(); - protected VertexTransformer vertexTransformer = (vertexList, level) -> { - }; + protected MaterialVertexTransformer vertexTransformer = (vertexList, level) -> {}; public Builder() { } @@ -100,7 +100,7 @@ public class SimpleMaterial implements Material { return this; } - public Builder vertexTransformer(VertexTransformer vertexTransformer) { + public Builder vertexTransformer(MaterialVertexTransformer vertexTransformer) { this.vertexTransformer = vertexTransformer; return this; } diff --git a/src/main/java/com/jozufozu/flywheel/util/DiffuseLightCalculator.java b/src/main/java/com/jozufozu/flywheel/lib/math/DiffuseLightCalculator.java similarity index 91% rename from src/main/java/com/jozufozu/flywheel/util/DiffuseLightCalculator.java rename to src/main/java/com/jozufozu/flywheel/lib/math/DiffuseLightCalculator.java index 2fcf6161e..9ec8414bd 100644 --- a/src/main/java/com/jozufozu/flywheel/util/DiffuseLightCalculator.java +++ b/src/main/java/com/jozufozu/flywheel/lib/math/DiffuseLightCalculator.java @@ -1,4 +1,4 @@ -package com.jozufozu.flywheel.util; +package com.jozufozu.flywheel.lib.math; import net.minecraft.client.multiplayer.ClientLevel; diff --git a/src/main/java/com/jozufozu/flywheel/util/MatrixUtil.java b/src/main/java/com/jozufozu/flywheel/lib/math/MatrixUtil.java similarity index 74% rename from src/main/java/com/jozufozu/flywheel/util/MatrixUtil.java rename to src/main/java/com/jozufozu/flywheel/lib/math/MatrixUtil.java index 57b96de79..8a1a25321 100644 --- a/src/main/java/com/jozufozu/flywheel/util/MatrixUtil.java +++ b/src/main/java/com/jozufozu/flywheel/lib/math/MatrixUtil.java @@ -1,4 +1,4 @@ -package com.jozufozu.flywheel.util; +package com.jozufozu.flywheel.lib.math; import java.nio.ByteBuffer; @@ -9,7 +9,37 @@ import com.jozufozu.flywheel.mixin.matrix.Matrix4fAccessor; import com.mojang.math.Matrix3f; import com.mojang.math.Matrix4f; -public class MatrixUtil { +public final class MatrixUtil { + public static float transformPositionX(Matrix4f matrix, float x, float y, float z) { + Matrix4fAccessor m = (Matrix4fAccessor) (Object) matrix; + return (m.flywheel$m00() * x) + (m.flywheel$m01() * y) + (m.flywheel$m02() * z) + m.flywheel$m03(); + } + + public static float transformPositionY(Matrix4f matrix, float x, float y, float z) { + Matrix4fAccessor m = (Matrix4fAccessor) (Object) matrix; + return (m.flywheel$m10() * x) + (m.flywheel$m11() * y) + (m.flywheel$m12() * z) + m.flywheel$m13(); + } + + public static float transformPositionZ(Matrix4f matrix, float x, float y, float z) { + Matrix4fAccessor m = (Matrix4fAccessor) (Object) matrix; + return (m.flywheel$m20() * x) + (m.flywheel$m21() * y) + (m.flywheel$m22() * z) + m.flywheel$m23(); + } + + public static float transformNormalX(Matrix3f matrix, float x, float y, float z) { + Matrix3fAccessor m = (Matrix3fAccessor) (Object) matrix; + return (m.flywheel$m00() * x) + (m.flywheel$m01() * y) + (m.flywheel$m02() * z); + } + + public static float transformNormalY(Matrix3f matrix, float x, float y, float z) { + Matrix3fAccessor m = (Matrix3fAccessor) (Object) matrix; + return (m.flywheel$m10() * x) + (m.flywheel$m11() * y) + (m.flywheel$m12() * z); + } + + public static float transformNormalZ(Matrix3f matrix, float x, float y, float z) { + Matrix3fAccessor m = (Matrix3fAccessor) (Object) matrix; + return (m.flywheel$m20() * x) + (m.flywheel$m21() * y) + (m.flywheel$m22() * z); + } + public static void write(Matrix4f matrix, ByteBuffer buf) { Matrix4fAccessor m = (Matrix4fAccessor) (Object) matrix; buf.putFloat(m.flywheel$m00()); diff --git a/src/main/java/com/jozufozu/flywheel/lib/math/MoreMath.java b/src/main/java/com/jozufozu/flywheel/lib/math/MoreMath.java new file mode 100644 index 000000000..b06678d00 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/lib/math/MoreMath.java @@ -0,0 +1,166 @@ +package com.jozufozu.flywheel.lib.math; + +import org.joml.Math; +import org.joml.Matrix4f; +import org.lwjgl.system.MemoryUtil; + +public final class MoreMath { + public static int align16(int numToRound) { + return (numToRound + 16 - 1) & -16; + } + + 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; + } + } + } + } + } + + /** + * 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/src/main/java/com/jozufozu/flywheel/util/RenderMath.java b/src/main/java/com/jozufozu/flywheel/lib/math/RenderMath.java similarity index 95% rename from src/main/java/com/jozufozu/flywheel/util/RenderMath.java rename to src/main/java/com/jozufozu/flywheel/lib/math/RenderMath.java index 213cc2819..d7d015161 100644 --- a/src/main/java/com/jozufozu/flywheel/util/RenderMath.java +++ b/src/main/java/com/jozufozu/flywheel/lib/math/RenderMath.java @@ -1,9 +1,8 @@ -package com.jozufozu.flywheel.util; +package com.jozufozu.flywheel.lib.math; import net.minecraftforge.client.model.pipeline.LightUtil; -public class RenderMath { - +public final class RenderMath { /** * Convert a signed byte into a signed, normalized float. */ diff --git a/src/main/java/com/jozufozu/flywheel/lib/memory/FlwMemoryTracker.java b/src/main/java/com/jozufozu/flywheel/lib/memory/FlwMemoryTracker.java index c66e852a9..6aec1b3e3 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/memory/FlwMemoryTracker.java +++ b/src/main/java/com/jozufozu/flywheel/lib/memory/FlwMemoryTracker.java @@ -7,7 +7,7 @@ import org.lwjgl.system.MemoryUtil; import com.jozufozu.flywheel.util.StringUtil; -public class FlwMemoryTracker { +public final class FlwMemoryTracker { public static final boolean DEBUG_MEMORY_SAFETY = System.getProperty("flw.debugMemorySafety") != null; static final Cleaner CLEANER = Cleaner.create(); diff --git a/src/main/java/com/jozufozu/flywheel/lib/model/ModelUtil.java b/src/main/java/com/jozufozu/flywheel/lib/model/ModelUtil.java index 654d5ef9f..aa930bbda 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/model/ModelUtil.java +++ b/src/main/java/com/jozufozu/flywheel/lib/model/ModelUtil.java @@ -6,21 +6,21 @@ import java.nio.ByteBuffer; import org.jetbrains.annotations.Nullable; import org.joml.Vector4f; import org.lwjgl.system.MemoryUtil; +import org.slf4j.Logger; import com.dreizak.miniball.highdim.Miniball; import com.dreizak.miniball.model.PointSet; -import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.api.material.Material; import com.jozufozu.flywheel.api.vertex.ReusableVertexList; import com.jozufozu.flywheel.api.vertex.VertexList; import com.jozufozu.flywheel.api.vertex.VertexListProviderRegistry; import com.jozufozu.flywheel.api.vertex.VertexType; -import com.jozufozu.flywheel.lib.format.Formats; import com.jozufozu.flywheel.lib.material.Materials; import com.jozufozu.flywheel.lib.memory.MemoryBlock; import com.mojang.blaze3d.vertex.BufferBuilder.DrawState; import com.mojang.blaze3d.vertex.VertexFormat; import com.mojang.datafixers.util.Pair; +import com.mojang.logging.LogUtils; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.RenderType; @@ -28,7 +28,9 @@ import net.minecraft.client.renderer.block.BlockRenderDispatcher; import net.minecraft.client.renderer.block.ModelBlockRenderer; import net.minecraftforge.fml.util.ObfuscationReflectionHelper; -public class ModelUtil { +public final class ModelUtil { + private static final Logger LOGGER = LogUtils.getLogger(); + /** * An alternative BlockRenderDispatcher that circumvents the Forge rendering pipeline to ensure consistency. * Meant to be used for virtual rendering. @@ -45,25 +47,24 @@ public class ModelUtil { } ObfuscationReflectionHelper.setPrivateValue(BlockRenderDispatcher.class, dispatcher, new ModelBlockRenderer(Minecraft.getInstance().getBlockColors()), "f_110900_"); } catch (Exception e) { - Flywheel.LOGGER.error("Failed to initialize vanilla BlockRenderDispatcher!", e); + LOGGER.error("Failed to initialize vanilla BlockRenderDispatcher!", e); return defaultDispatcher; } return dispatcher; } - public static Pair convertBlockBuffer(Pair pair) { + public static MemoryBlock convertVanillaBuffer(Pair pair, VertexType vertexType) { DrawState drawState = pair.getFirst(); int vertexCount = drawState.vertexCount(); VertexFormat srcFormat = drawState.format(); - VertexType dstVertexType = Formats.BLOCK; ByteBuffer src = pair.getSecond(); - MemoryBlock dst = MemoryBlock.malloc(vertexCount * dstVertexType.getLayout().getStride()); + MemoryBlock dst = MemoryBlock.malloc(vertexCount * vertexType.getLayout().getStride()); long srcPtr = MemoryUtil.memAddress(src); long dstPtr = dst.ptr(); ReusableVertexList srcList = VertexListProviderRegistry.getProvider(srcFormat).createVertexList(); - ReusableVertexList dstList = dstVertexType.createVertexList(); + ReusableVertexList dstList = vertexType.createVertexList(); srcList.ptr(srcPtr); dstList.ptr(dstPtr); srcList.vertexCount(vertexCount); @@ -71,7 +72,7 @@ public class ModelUtil { srcList.writeAll(dstList); - return Pair.of(dstVertexType, dst); + return dst; } @Nullable diff --git a/src/main/java/com/jozufozu/flywheel/lib/model/Models.java b/src/main/java/com/jozufozu/flywheel/lib/model/Models.java index 8caf445e8..fe55c0147 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/model/Models.java +++ b/src/main/java/com/jozufozu/flywheel/lib/model/Models.java @@ -15,7 +15,7 @@ import com.mojang.blaze3d.vertex.PoseStack; import net.minecraft.core.Direction; import net.minecraft.world.level.block.state.BlockState; -public class Models { +public final class Models { private static final Map BLOCK_STATE = new HashMap<>(); private static final Map PARTIAL = new HashMap<>(); private static final Map, Model> PARTIAL_DIR = new HashMap<>(); diff --git a/src/main/java/com/jozufozu/flywheel/lib/model/QuadMesh.java b/src/main/java/com/jozufozu/flywheel/lib/model/QuadMesh.java new file mode 100644 index 000000000..2c46b040f --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/lib/model/QuadMesh.java @@ -0,0 +1,23 @@ +package com.jozufozu.flywheel.lib.model; + +import com.jozufozu.flywheel.api.model.Mesh; +import com.jozufozu.flywheel.gl.buffer.ElementBuffer; +import com.jozufozu.flywheel.lib.util.QuadConverter; + +public interface QuadMesh extends Mesh { + /** + * Create an element buffer object that indexes the vertices of this mesh. + * + *

+ * Very often models in minecraft are made up of sequential quads, which is a very predictable pattern. + * The default implementation accommodates this, however this can be overridden to change the behavior and + * support more complex models. + *

+ * @return an element buffer object indexing this model's vertices. + */ + @Override + default ElementBuffer createEBO() { + return QuadConverter.getInstance() + .quads2Tris(getVertexCount() / 4); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/lib/model/SimpleMesh.java b/src/main/java/com/jozufozu/flywheel/lib/model/SimpleMesh.java index 7d4724d63..197b6ee7f 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/model/SimpleMesh.java +++ b/src/main/java/com/jozufozu/flywheel/lib/model/SimpleMesh.java @@ -3,13 +3,12 @@ package com.jozufozu.flywheel.lib.model; import org.joml.Vector4f; import org.joml.Vector4fc; -import com.jozufozu.flywheel.api.model.Mesh; import com.jozufozu.flywheel.api.vertex.MutableVertexList; import com.jozufozu.flywheel.api.vertex.ReusableVertexList; import com.jozufozu.flywheel.api.vertex.VertexType; import com.jozufozu.flywheel.lib.memory.MemoryBlock; -public class SimpleMesh implements Mesh { +public class SimpleMesh implements QuadMesh { private final VertexType vertexType; private final int vertexCount; private final MemoryBlock contents; diff --git a/src/main/java/com/jozufozu/flywheel/lib/model/buffering/BakedModelBuilder.java b/src/main/java/com/jozufozu/flywheel/lib/model/buffering/BakedModelBuilder.java index 48b99319a..cfc6640fb 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/model/buffering/BakedModelBuilder.java +++ b/src/main/java/com/jozufozu/flywheel/lib/model/buffering/BakedModelBuilder.java @@ -5,7 +5,7 @@ import java.util.function.BiFunction; import com.google.common.collect.ImmutableMap; import com.jozufozu.flywheel.api.material.Material; import com.jozufozu.flywheel.api.model.Mesh; -import com.jozufozu.flywheel.api.vertex.VertexType; +import com.jozufozu.flywheel.lib.format.Formats; import com.jozufozu.flywheel.lib.memory.MemoryBlock; import com.jozufozu.flywheel.lib.model.ModelUtil; import com.jozufozu.flywheel.lib.model.SimpleMesh; @@ -20,7 +20,6 @@ import com.mojang.blaze3d.vertex.BufferBuilder; import com.mojang.blaze3d.vertex.DefaultVertexFormat; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexFormat; -import com.mojang.datafixers.util.Pair; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.resources.model.BakedModel; @@ -106,8 +105,8 @@ public class BakedModelBuilder { buffer.end(); Material material = materialFunc.apply(renderType, shaded); if (material != null) { - Pair pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer()); - meshMapBuilder.put(material, new SimpleMesh(pair.getFirst(), pair.getSecond(), "bakedModel=" + bakedModel.toString() + ",renderType=" + renderType.toString() + ",shaded=" + shaded)); + MemoryBlock data = ModelUtil.convertVanillaBuffer(buffer.popNextBuffer(), Formats.BLOCK); + meshMapBuilder.put(material, new SimpleMesh(Formats.BLOCK, data, "bakedModel=" + bakedModel.toString() + ",renderType=" + renderType.toString() + ",shaded=" + shaded)); } }; ModelBufferingUtil.bufferSingleShadeSeparated(ModelUtil.VANILLA_RENDERER.getModelRenderer(), renderWorld, bakedModel, blockState, poseStack, bufferFactory, objects.shadeSeparatingBufferWrapper, objects.random, modelData, resultConsumer); @@ -121,8 +120,8 @@ public class BakedModelBuilder { buffer.end(); Material material = materialFunc.apply(renderType, false); if (material != null) { - Pair pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer()); - meshMapBuilder.put(material, new SimpleMesh(pair.getFirst(), pair.getSecond(), "bakedModel=" + bakedModel.toString() + ",renderType=" + renderType.toString())); + MemoryBlock data = ModelUtil.convertVanillaBuffer(buffer.popNextBuffer(), Formats.BLOCK); + meshMapBuilder.put(material, new SimpleMesh(Formats.BLOCK, data, "bakedModel=" + bakedModel.toString() + ",renderType=" + renderType.toString())); } }; ModelBufferingUtil.bufferSingle(ModelUtil.VANILLA_RENDERER.getModelRenderer(), renderWorld, bakedModel, blockState, poseStack, bufferFactory, objects.bufferWrapper, objects.random, modelData, resultConsumer); diff --git a/src/main/java/com/jozufozu/flywheel/lib/model/buffering/BlockModelBuilder.java b/src/main/java/com/jozufozu/flywheel/lib/model/buffering/BlockModelBuilder.java index dd4a54dc1..e5372f7d3 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/model/buffering/BlockModelBuilder.java +++ b/src/main/java/com/jozufozu/flywheel/lib/model/buffering/BlockModelBuilder.java @@ -5,7 +5,7 @@ import java.util.function.BiFunction; import com.google.common.collect.ImmutableMap; import com.jozufozu.flywheel.api.material.Material; import com.jozufozu.flywheel.api.model.Mesh; -import com.jozufozu.flywheel.api.vertex.VertexType; +import com.jozufozu.flywheel.lib.format.Formats; import com.jozufozu.flywheel.lib.memory.MemoryBlock; import com.jozufozu.flywheel.lib.model.ModelUtil; import com.jozufozu.flywheel.lib.model.SimpleMesh; @@ -20,7 +20,6 @@ import com.mojang.blaze3d.vertex.BufferBuilder; import com.mojang.blaze3d.vertex.DefaultVertexFormat; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexFormat; -import com.mojang.datafixers.util.Pair; import net.minecraft.client.renderer.RenderType; import net.minecraft.world.level.BlockAndTintGetter; @@ -95,8 +94,8 @@ public class BlockModelBuilder { buffer.end(); Material material = materialFunc.apply(renderType, shaded); if (material != null) { - Pair pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer()); - meshMapBuilder.put(material, new SimpleMesh(pair.getFirst(), pair.getSecond(), "state=" + state.toString() + ",renderType=" + renderType.toString() + ",shaded=" + shaded)); + MemoryBlock data = ModelUtil.convertVanillaBuffer(buffer.popNextBuffer(), Formats.BLOCK); + meshMapBuilder.put(material, new SimpleMesh(Formats.BLOCK, data, "state=" + state.toString() + ",renderType=" + renderType.toString() + ",shaded=" + shaded)); } }; ModelBufferingUtil.bufferBlockShadeSeparated(ModelUtil.VANILLA_RENDERER, renderWorld, state, poseStack, bufferFactory, objects.shadeSeparatingBufferWrapper, objects.random, modelData, resultConsumer); @@ -110,8 +109,8 @@ public class BlockModelBuilder { buffer.end(); Material material = materialFunc.apply(renderType, false); if (material != null) { - Pair pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer()); - meshMapBuilder.put(material, new SimpleMesh(pair.getFirst(), pair.getSecond(), "state=" + state.toString() + ",renderType=" + renderType.toString())); + MemoryBlock data = ModelUtil.convertVanillaBuffer(buffer.popNextBuffer(), Formats.BLOCK); + meshMapBuilder.put(material, new SimpleMesh(Formats.BLOCK, data, "state=" + state.toString() + ",renderType=" + renderType.toString())); } }; ModelBufferingUtil.bufferBlock(ModelUtil.VANILLA_RENDERER, renderWorld, state, poseStack, bufferFactory, objects.bufferWrapper, objects.random, modelData, resultConsumer); diff --git a/src/main/java/com/jozufozu/flywheel/lib/model/buffering/MultiBlockModelBuilder.java b/src/main/java/com/jozufozu/flywheel/lib/model/buffering/MultiBlockModelBuilder.java index 6f0581624..888e07405 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/model/buffering/MultiBlockModelBuilder.java +++ b/src/main/java/com/jozufozu/flywheel/lib/model/buffering/MultiBlockModelBuilder.java @@ -8,7 +8,7 @@ import java.util.function.BiFunction; import com.google.common.collect.ImmutableMap; import com.jozufozu.flywheel.api.material.Material; import com.jozufozu.flywheel.api.model.Mesh; -import com.jozufozu.flywheel.api.vertex.VertexType; +import com.jozufozu.flywheel.lib.format.Formats; import com.jozufozu.flywheel.lib.memory.MemoryBlock; import com.jozufozu.flywheel.lib.model.ModelUtil; import com.jozufozu.flywheel.lib.model.SimpleMesh; @@ -22,7 +22,6 @@ import com.mojang.blaze3d.vertex.BufferBuilder; import com.mojang.blaze3d.vertex.DefaultVertexFormat; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexFormat; -import com.mojang.datafixers.util.Pair; import net.minecraft.client.renderer.RenderType; import net.minecraft.core.BlockPos; @@ -102,8 +101,8 @@ public class MultiBlockModelBuilder { buffer.end(); Material material = materialFunc.apply(renderType, shaded); if (material != null) { - Pair pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer()); - meshMapBuilder.put(material, new SimpleMesh(pair.getFirst(), pair.getSecond(), "renderType=" + renderType.toString() + ",shaded=" + shaded)); + MemoryBlock data = ModelUtil.convertVanillaBuffer(buffer.popNextBuffer(), Formats.BLOCK); + meshMapBuilder.put(material, new SimpleMesh(Formats.BLOCK, data, "renderType=" + renderType.toString() + ",shaded=" + shaded)); } }; ModelBufferingUtil.bufferMultiBlockShadeSeparated(blocks, ModelUtil.VANILLA_RENDERER, renderWorld, poseStack, bufferFactory, objects.shadeSeparatingBufferWrapper, objects.random, modelDataMap, resultConsumer); @@ -117,8 +116,8 @@ public class MultiBlockModelBuilder { buffer.end(); Material material = materialFunc.apply(renderType, false); if (material != null) { - Pair pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer()); - meshMapBuilder.put(material, new SimpleMesh(pair.getFirst(), pair.getSecond(), "renderType=" + renderType.toString())); + MemoryBlock data = ModelUtil.convertVanillaBuffer(buffer.popNextBuffer(), Formats.BLOCK); + meshMapBuilder.put(material, new SimpleMesh(Formats.BLOCK, data, "renderType=" + renderType.toString())); } }; ModelBufferingUtil.bufferMultiBlock(blocks, ModelUtil.VANILLA_RENDERER, renderWorld, poseStack, bufferFactory, objects.bufferWrapper, objects.random, modelDataMap, resultConsumer); diff --git a/src/main/java/com/jozufozu/flywheel/lib/modelpart/ModelPart.java b/src/main/java/com/jozufozu/flywheel/lib/modelpart/ModelPart.java index dfadcc10a..7a56cef2d 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/modelpart/ModelPart.java +++ b/src/main/java/com/jozufozu/flywheel/lib/modelpart/ModelPart.java @@ -5,22 +5,22 @@ import java.util.List; import org.joml.Vector4f; import org.joml.Vector4fc; -import com.jozufozu.flywheel.api.model.Mesh; import com.jozufozu.flywheel.api.vertex.MutableVertexList; import com.jozufozu.flywheel.api.vertex.ReusableVertexList; import com.jozufozu.flywheel.lib.format.Formats; import com.jozufozu.flywheel.lib.format.PosTexNormalVertex; import com.jozufozu.flywheel.lib.memory.MemoryBlock; import com.jozufozu.flywheel.lib.model.ModelUtil; +import com.jozufozu.flywheel.lib.model.QuadMesh; -public class ModelPart implements Mesh { +public class ModelPart implements QuadMesh { private final int vertexCount; private final MemoryBlock contents; private final ReusableVertexList vertexList; private final Vector4f boundingSphere; private final String name; - public ModelPart(List cuboids, String name) { + public ModelPart(List cuboids, String name) { this.name = name; this.vertexCount = countVertices(cuboids); @@ -28,7 +28,7 @@ public class ModelPart implements Mesh { contents = MemoryBlock.malloc(size()); long ptr = contents.ptr(); VertexWriter writer = new VertexWriterImpl(ptr); - for (PartBuilder.CuboidBuilder cuboid : cuboids) { + for (ModelPartBuilder.CuboidBuilder cuboid : cuboids) { cuboid.write(writer); } @@ -39,8 +39,8 @@ public class ModelPart implements Mesh { boundingSphere = ModelUtil.computeBoundingSphere(vertexList); } - public static PartBuilder builder(String name, int sizeU, int sizeV) { - return new PartBuilder(name, sizeU, sizeV); + public static ModelPartBuilder builder(String name, int sizeU, int sizeV) { + return new ModelPartBuilder(name, sizeU, sizeV); } @Override @@ -78,9 +78,9 @@ public class ModelPart implements Mesh { return name; } - private static int countVertices(List cuboids) { + private static int countVertices(List cuboids) { int vertices = 0; - for (PartBuilder.CuboidBuilder cuboid : cuboids) { + for (ModelPartBuilder.CuboidBuilder cuboid : cuboids) { vertices += cuboid.vertices(); } return vertices; diff --git a/src/main/java/com/jozufozu/flywheel/lib/modelpart/PartBuilder.java b/src/main/java/com/jozufozu/flywheel/lib/modelpart/ModelPartBuilder.java similarity index 89% rename from src/main/java/com/jozufozu/flywheel/lib/modelpart/PartBuilder.java rename to src/main/java/com/jozufozu/flywheel/lib/modelpart/ModelPartBuilder.java index f3b4d6200..84f8aa830 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/modelpart/PartBuilder.java +++ b/src/main/java/com/jozufozu/flywheel/lib/modelpart/ModelPartBuilder.java @@ -12,8 +12,7 @@ import com.mojang.math.Vector3f; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.core.Direction; -public class PartBuilder { - +public class ModelPartBuilder { private final float sizeU; private final float sizeV; @@ -22,13 +21,13 @@ public class PartBuilder { private final List cuboids = new ArrayList<>(); private final String name; - public PartBuilder(String name, int sizeU, int sizeV) { + public ModelPartBuilder(String name, int sizeU, int sizeV) { this.name = name; this.sizeU = (float) sizeU; this.sizeV = (float) sizeV; } - public PartBuilder sprite(TextureAtlasSprite sprite) { + public ModelPartBuilder sprite(TextureAtlasSprite sprite) { this.sprite = sprite; return this; } @@ -41,36 +40,35 @@ public class PartBuilder { return new ModelPart(cuboids, name); } - private PartBuilder addCuboid(CuboidBuilder builder) { + private ModelPartBuilder addCuboid(CuboidBuilder builder) { cuboids.add(builder); return this; } public static class CuboidBuilder { + private TextureAtlasSprite sprite; - TextureAtlasSprite sprite; + private Set visibleFaces = EnumSet.allOf(Direction.class); + private int textureOffsetU; + private int textureOffsetV; - Set visibleFaces = EnumSet.allOf(Direction.class); - int textureOffsetU; - int textureOffsetV; + private float posX1; + private float posY1; + private float posZ1; + private float posX2; + private float posY2; + private float posZ2; - float posX1; - float posY1; - float posZ1; - float posX2; - float posY2; - float posZ2; + private boolean invertYZ; - boolean invertYZ; + private boolean useRotation; + private float rotationX; + private float rotationY; + private float rotationZ; - boolean useRotation; - float rotationX; - float rotationY; - float rotationZ; + private final ModelPartBuilder partBuilder; - final PartBuilder partBuilder; - - CuboidBuilder(PartBuilder partBuilder) { + private CuboidBuilder(ModelPartBuilder partBuilder) { this.partBuilder = partBuilder; this.sprite = partBuilder.sprite; } @@ -151,7 +149,7 @@ public class PartBuilder { return this; } - public PartBuilder endCuboid() { + public ModelPartBuilder endCuboid() { return partBuilder.addCuboid(this); } @@ -254,5 +252,4 @@ public class PartBuilder { return v / partBuilder.sizeV; } } - } diff --git a/src/main/java/com/jozufozu/flywheel/lib/modelpart/VertexWriterImpl.java b/src/main/java/com/jozufozu/flywheel/lib/modelpart/VertexWriterImpl.java index 53fb8ee96..125e7526b 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/modelpart/VertexWriterImpl.java +++ b/src/main/java/com/jozufozu/flywheel/lib/modelpart/VertexWriterImpl.java @@ -2,7 +2,7 @@ package com.jozufozu.flywheel.lib.modelpart; import org.lwjgl.system.MemoryUtil; -import com.jozufozu.flywheel.util.RenderMath; +import com.jozufozu.flywheel.lib.math.RenderMath; public class VertexWriterImpl implements VertexWriter { private long ptr; diff --git a/src/main/java/com/jozufozu/flywheel/lib/struct/AbstractInstancePart.java b/src/main/java/com/jozufozu/flywheel/lib/struct/AbstractInstancePart.java index 71b55fc4d..fde6ab5b5 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/struct/AbstractInstancePart.java +++ b/src/main/java/com/jozufozu/flywheel/lib/struct/AbstractInstancePart.java @@ -1,12 +1,11 @@ package com.jozufozu.flywheel.lib.struct; -import com.jozufozu.flywheel.api.instancer.Handle; -import com.jozufozu.flywheel.api.instancer.InstancePart; +import com.jozufozu.flywheel.api.struct.Handle; +import com.jozufozu.flywheel.api.struct.InstancePart; import com.jozufozu.flywheel.api.struct.StructType; public abstract class AbstractInstancePart implements InstancePart { - - public final StructType type; + protected final StructType type; protected final Handle handle; protected AbstractInstancePart(StructType type, Handle handle) { diff --git a/src/main/java/com/jozufozu/flywheel/lib/struct/ColoredLitPart.java b/src/main/java/com/jozufozu/flywheel/lib/struct/ColoredLitPart.java index a6339f577..b92815f7e 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/struct/ColoredLitPart.java +++ b/src/main/java/com/jozufozu/flywheel/lib/struct/ColoredLitPart.java @@ -1,12 +1,11 @@ package com.jozufozu.flywheel.lib.struct; -import com.jozufozu.flywheel.api.instancer.Handle; +import com.jozufozu.flywheel.api.struct.Handle; import com.jozufozu.flywheel.api.struct.StructType; import net.minecraft.client.renderer.LightTexture; public abstract class ColoredLitPart extends AbstractInstancePart implements FlatLit { - public byte blockLight; public byte skyLight; @@ -15,7 +14,7 @@ public abstract class ColoredLitPart extends AbstractInstancePart implements Fla public byte b = (byte) 0xFF; public byte a = (byte) 0xFF; - public ColoredLitPart(StructType type, Handle handle) { + public ColoredLitPart(StructType type, Handle handle) { super(type, handle); } @@ -35,7 +34,7 @@ public abstract class ColoredLitPart extends AbstractInstancePart implements Fla @Override public int getPackedLight() { - return LightTexture.pack(this.blockLight, this.skyLight); + return LightTexture.pack(blockLight, skyLight); } public ColoredLitPart setColor(int color) { diff --git a/src/main/java/com/jozufozu/flywheel/lib/struct/FlatLit.java b/src/main/java/com/jozufozu/flywheel/lib/struct/FlatLit.java index 19d95bcf5..ae23de706 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/struct/FlatLit.java +++ b/src/main/java/com/jozufozu/flywheel/lib/struct/FlatLit.java @@ -1,6 +1,6 @@ package com.jozufozu.flywheel.lib.struct; -import com.jozufozu.flywheel.api.instancer.InstancePart; +import com.jozufozu.flywheel.api.struct.InstancePart; import net.minecraft.core.BlockPos; import net.minecraft.world.level.BlockAndTintGetter; diff --git a/src/main/java/com/jozufozu/flywheel/lib/struct/OrientedPart.java b/src/main/java/com/jozufozu/flywheel/lib/struct/OrientedPart.java index 2f00ab4f2..c8589fd3b 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/struct/OrientedPart.java +++ b/src/main/java/com/jozufozu/flywheel/lib/struct/OrientedPart.java @@ -1,13 +1,13 @@ package com.jozufozu.flywheel.lib.struct; -import com.jozufozu.flywheel.api.instancer.Handle; +import com.jozufozu.flywheel.api.struct.Handle; +import com.jozufozu.flywheel.api.struct.StructType; import com.mojang.math.Quaternion; import com.mojang.math.Vector3f; import net.minecraft.core.BlockPos; public class OrientedPart extends ColoredLitPart { - public float posX; public float posY; public float posZ; @@ -19,8 +19,8 @@ public class OrientedPart extends ColoredLitPart { public float qZ; public float qW = 1; - public OrientedPart(Handle handle) { - super(StructTypes.ORIENTED, handle); + public OrientedPart(StructType type, Handle handle) { + super(type, handle); } public OrientedPart setPosition(BlockPos pos) { @@ -87,7 +87,7 @@ public class OrientedPart extends ColoredLitPart { @Override public OrientedPart copy(Handle handle) { - var out = new OrientedPart(handle); + var out = StructTypes.ORIENTED.create(handle); out.posX = this.posX; out.posY = this.posY; out.posZ = this.posZ; diff --git a/src/main/java/com/jozufozu/flywheel/lib/struct/OrientedType.java b/src/main/java/com/jozufozu/flywheel/lib/struct/OrientedType.java index 6185819d6..ae0317fbd 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/struct/OrientedType.java +++ b/src/main/java/com/jozufozu/flywheel/lib/struct/OrientedType.java @@ -1,21 +1,20 @@ package com.jozufozu.flywheel.lib.struct; -import com.jozufozu.flywheel.api.instancer.Handle; import com.jozufozu.flywheel.api.layout.BufferLayout; +import com.jozufozu.flywheel.api.struct.Handle; import com.jozufozu.flywheel.api.struct.StructType; +import com.jozufozu.flywheel.api.struct.StructVertexTransformer; import com.jozufozu.flywheel.api.struct.StructWriter; import com.jozufozu.flywheel.lib.layout.CommonItems; -import com.jozufozu.flywheel.util.RenderMath; +import com.jozufozu.flywheel.lib.math.RenderMath; +import com.jozufozu.flywheel.lib.vertex.VertexTransformations; import com.mojang.math.Matrix3f; import com.mojang.math.Matrix4f; import com.mojang.math.Quaternion; -import com.mojang.math.Vector3f; -import com.mojang.math.Vector4f; import net.minecraft.resources.ResourceLocation; public class OrientedType implements StructType { - public static final BufferLayout FORMAT = BufferLayout.builder() .addItem(CommonItems.LIGHT_COORD, "light") .addItem(CommonItems.UNORM_4x8, "color") @@ -26,7 +25,7 @@ public class OrientedType implements StructType { @Override public OrientedPart create(Handle handle) { - return new OrientedPart(handle); + return new OrientedPart(this, handle); } @Override @@ -45,11 +44,8 @@ public class OrientedType implements StructType { } @Override - public VertexTransformer getVertexTransformer() { + public StructVertexTransformer getVertexTransformer() { return (vertexList, struct, level) -> { - Vector4f pos = new Vector4f(); - Vector3f normal = new Vector3f(); - Quaternion q = new Quaternion(struct.qX, struct.qY, struct.qZ, struct.qW); Matrix4f modelMatrix = new Matrix4f(); @@ -67,27 +63,8 @@ public class OrientedType implements StructType { int light = struct.getPackedLight(); for (int i = 0; i < vertexList.vertexCount(); i++) { - pos.set( - vertexList.x(i), - vertexList.y(i), - vertexList.z(i), - 1f - ); - pos.transform(modelMatrix); - vertexList.x(i, pos.x()); - vertexList.y(i, pos.y()); - vertexList.z(i, pos.z()); - - normal.set( - vertexList.normalX(i), - vertexList.normalY(i), - vertexList.normalZ(i) - ); - normal.transform(normalMatrix); - normal.normalize(); - vertexList.normalX(i, normal.x()); - vertexList.normalY(i, normal.y()); - vertexList.normalZ(i, normal.z()); + VertexTransformations.transformPos(vertexList, i, modelMatrix); + VertexTransformations.transformNormal(vertexList, i, normalMatrix); vertexList.r(i, r); vertexList.g(i, g); diff --git a/src/main/java/com/jozufozu/flywheel/lib/struct/StructTypes.java b/src/main/java/com/jozufozu/flywheel/lib/struct/StructTypes.java index fddeb37c9..f42b02b9f 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/struct/StructTypes.java +++ b/src/main/java/com/jozufozu/flywheel/lib/struct/StructTypes.java @@ -1,25 +1,27 @@ package com.jozufozu.flywheel.lib.struct; +import org.jetbrains.annotations.ApiStatus; + import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.util.ResourceUtil; import net.minecraft.resources.ResourceLocation; -public class StructTypes { +public final class StructTypes { public static final StructType TRANSFORMED = StructType.REGISTRY.registerAndGet(new TransformedType()); public static final StructType ORIENTED = StructType.REGISTRY.registerAndGet(new OrientedType()); + @ApiStatus.Internal public static void init() { - // noop } - public static class Files { + public static final class Files { public static final ResourceLocation TRANSFORMED = ResourceUtil.subPath(Names.TRANSFORMED, ".vert"); public static final ResourceLocation ORIENTED = ResourceUtil.subPath(Names.ORIENTED, ".vert"); } - public static class Names { + public static final class Names { public static final ResourceLocation TRANSFORMED = Flywheel.rl("instance/transformed"); public static final ResourceLocation ORIENTED = Flywheel.rl("instance/oriented"); } diff --git a/src/main/java/com/jozufozu/flywheel/lib/struct/TransformedPart.java b/src/main/java/com/jozufozu/flywheel/lib/struct/TransformedPart.java index 16a19233d..90f1bb519 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/struct/TransformedPart.java +++ b/src/main/java/com/jozufozu/flywheel/lib/struct/TransformedPart.java @@ -1,6 +1,7 @@ package com.jozufozu.flywheel.lib.struct; -import com.jozufozu.flywheel.api.instancer.Handle; +import com.jozufozu.flywheel.api.struct.Handle; +import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.lib.transform.Transform; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.math.Matrix3f; @@ -16,8 +17,8 @@ public class TransformedPart extends ColoredLitPart implements Transform type, Handle handle) { + super(type, handle); } public TransformedPart setTransform(PoseStack stack) { @@ -106,7 +107,7 @@ public class TransformedPart extends ColoredLitPart implements Transform { - public static final BufferLayout FORMAT = BufferLayout.builder() .addItem(CommonItems.LIGHT_COORD, "light") .addItem(CommonItems.UNORM_4x8, "color") @@ -22,7 +21,7 @@ public class TransformedType implements StructType { @Override public TransformedPart create(Handle handle) { - return new TransformedPart(handle); + return new TransformedPart(this, handle); } @Override @@ -41,11 +40,8 @@ public class TransformedType implements StructType { } @Override - public VertexTransformer getVertexTransformer() { + public StructVertexTransformer getVertexTransformer() { return (vertexList, struct, level) -> { - Vector4f pos = new Vector4f(); - Vector3f normal = new Vector3f(); - float r = RenderMath.uf(struct.r); float g = RenderMath.uf(struct.g); float b = RenderMath.uf(struct.b); @@ -53,27 +49,8 @@ public class TransformedType implements StructType { int light = struct.getPackedLight(); for (int i = 0; i < vertexList.vertexCount(); i++) { - pos.set( - vertexList.x(i), - vertexList.y(i), - vertexList.z(i), - 1f - ); - pos.transform(struct.model); - vertexList.x(i, pos.x()); - vertexList.y(i, pos.y()); - vertexList.z(i, pos.z()); - - normal.set( - vertexList.normalX(i), - vertexList.normalY(i), - vertexList.normalZ(i) - ); - normal.transform(struct.normal); - normal.normalize(); - vertexList.normalX(i, normal.x()); - vertexList.normalY(i, normal.y()); - vertexList.normalZ(i, normal.z()); + VertexTransformations.transformPos(vertexList, i, struct.model); + VertexTransformations.transformNormal(vertexList, i, struct.normal); vertexList.r(i, r); vertexList.g(i, g); diff --git a/src/main/java/com/jozufozu/flywheel/lib/struct/TransformedWriter.java b/src/main/java/com/jozufozu/flywheel/lib/struct/TransformedWriter.java index bb69dcb6c..e18d14f9c 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/struct/TransformedWriter.java +++ b/src/main/java/com/jozufozu/flywheel/lib/struct/TransformedWriter.java @@ -1,6 +1,6 @@ package com.jozufozu.flywheel.lib.struct; -import com.jozufozu.flywheel.util.MatrixUtil; +import com.jozufozu.flywheel.lib.math.MatrixUtil; public class TransformedWriter extends ColoredLitWriter { public static final TransformedWriter INSTANCE = new TransformedWriter(); diff --git a/src/main/java/com/jozufozu/flywheel/lib/task/WorkGroup.java b/src/main/java/com/jozufozu/flywheel/lib/task/WorkGroup.java index 82dee6bee..8de35d7b5 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/task/WorkGroup.java +++ b/src/main/java/com/jozufozu/flywheel/lib/task/WorkGroup.java @@ -8,7 +8,7 @@ import java.util.stream.Stream; import org.jetbrains.annotations.Nullable; -public class WorkGroup { +public final class WorkGroup { public static void run(Iterator tasks, Executor executor) { tasks.forEachRemaining(executor::execute); } diff --git a/src/main/java/com/jozufozu/flywheel/lib/uniform/FlwShaderUniforms.java b/src/main/java/com/jozufozu/flywheel/lib/uniform/FlwShaderUniforms.java index a967fadfb..4f88499ac 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/uniform/FlwShaderUniforms.java +++ b/src/main/java/com/jozufozu/flywheel/lib/uniform/FlwShaderUniforms.java @@ -9,8 +9,8 @@ import com.jozufozu.flywheel.api.event.BeginFrameEvent; import com.jozufozu.flywheel.api.event.RenderContext; import com.jozufozu.flywheel.api.uniform.ShaderUniforms; import com.jozufozu.flywheel.impl.instancing.InstancedRenderDispatcher; -import com.jozufozu.flywheel.util.FlwUtil; -import com.jozufozu.flywheel.util.MatrixUtil; +import com.jozufozu.flywheel.lib.math.MatrixUtil; +import com.jozufozu.flywheel.lib.math.MoreMath; import com.mojang.blaze3d.systems.RenderSystem; import net.minecraft.core.Vec3i; @@ -134,7 +134,7 @@ public class FlwShaderUniforms implements ShaderUniforms { var projection = MatrixUtil.toJoml(context.viewProjection()); projection.translate(-camX, -camY, -camZ); - FlwUtil.writePackedFrustumPlanes(ptr + 128, projection); + MoreMath.writePackedFrustumPlanes(ptr + 128, projection); FRUSTUM_CAPTURE = false; } diff --git a/src/main/java/com/jozufozu/flywheel/util/AnimationTickHolder.java b/src/main/java/com/jozufozu/flywheel/lib/util/AnimationTickHolder.java similarity index 93% rename from src/main/java/com/jozufozu/flywheel/util/AnimationTickHolder.java rename to src/main/java/com/jozufozu/flywheel/lib/util/AnimationTickHolder.java index 20ed918df..3c2fbaff6 100644 --- a/src/main/java/com/jozufozu/flywheel/util/AnimationTickHolder.java +++ b/src/main/java/com/jozufozu/flywheel/lib/util/AnimationTickHolder.java @@ -1,4 +1,4 @@ -package com.jozufozu.flywheel.util; +package com.jozufozu.flywheel.lib.util; import com.jozufozu.flywheel.mixin.PausedPartialTickAccessor; @@ -7,8 +7,7 @@ import net.minecraft.client.Minecraft; /** * Static access to tick-count and partialTick time, accounting for pausing. */ -public class AnimationTickHolder { - +public final class AnimationTickHolder { // Wrap around every 24 hours to maintain floating point accuracy. private static final int wrappingInterval = 1_728_000; private static int ticks; diff --git a/src/main/java/com/jozufozu/flywheel/lib/util/QuadConverter.java b/src/main/java/com/jozufozu/flywheel/lib/util/QuadConverter.java index 95ec577e9..3dd415bf8 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/util/QuadConverter.java +++ b/src/main/java/com/jozufozu/flywheel/lib/util/QuadConverter.java @@ -20,7 +20,6 @@ import it.unimi.dsi.fastutil.ints.Int2ReferenceMap; * A class to manage EBOs that index quads as triangles. */ public class QuadConverter { - private static QuadConverter INSTANCE; @NotNull diff --git a/src/main/java/com/jozufozu/flywheel/lib/util/ShadersModHandler.java b/src/main/java/com/jozufozu/flywheel/lib/util/ShadersModHandler.java index 0d4546980..9b1435663 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/util/ShadersModHandler.java +++ b/src/main/java/com/jozufozu/flywheel/lib/util/ShadersModHandler.java @@ -6,6 +6,7 @@ import java.util.function.BooleanSupplier; import javax.annotation.Nullable; +import org.jetbrains.annotations.ApiStatus; import org.slf4j.Logger; import com.mojang.logging.LogUtils; @@ -19,53 +20,53 @@ public final class ShadersModHandler { private static final Logger LOGGER = LogUtils.getLogger(); public static final String OPTIFINE_ROOT_PACKAGE = "net.optifine"; - public static final String SHADER_PACKAGE = "net.optifine.shaders"; + public static final String OPTIFINE_SHADER_PACKAGE = "net.optifine.shaders"; - private static final boolean isOculusLoaded; - private static final boolean isOptifineInstalled; - private static final InternalHandler internalHandler; + private static final boolean IS_OCULUS_LOADED; + private static final boolean IS_OPTIFINE_INSTALLED; + private static final InternalHandler INTERNAL_HANDLER; static { Package optifinePackage = Package.getPackage(OPTIFINE_ROOT_PACKAGE); - isOptifineInstalled = optifinePackage != null; - isOculusLoaded = ModList.get() + IS_OPTIFINE_INSTALLED = optifinePackage != null; + IS_OCULUS_LOADED = ModList.get() .isLoaded("oculus"); // optfine and oculus are assumed to be mutually exclusive - if (isOptifineInstalled) { + if (IS_OPTIFINE_INSTALLED) { LOGGER.info("Optifine detected."); - internalHandler = new Optifine(); - } else if (isOculusLoaded) { + INTERNAL_HANDLER = new Optifine(); + } else if (IS_OCULUS_LOADED) { LOGGER.info("Oculus detected."); - internalHandler = new Oculus(); + INTERNAL_HANDLER = new Oculus(); } else { LOGGER.info("No shaders mod detected."); - internalHandler = new InternalHandler() {}; + INTERNAL_HANDLER = new InternalHandler() {}; } } - private ShadersModHandler() { - } - - public static void init() { - // noop, load statics + public static boolean isOculusLoaded() { + return IS_OCULUS_LOADED; } public static boolean isOptifineInstalled() { - return isOptifineInstalled; - } - - public static boolean isOculusLoaded() { - return isOculusLoaded; + return IS_OPTIFINE_INSTALLED; } public static boolean isShaderPackInUse() { - return internalHandler.isShaderPackInUse(); + return INTERNAL_HANDLER.isShaderPackInUse(); } public static boolean isRenderingShadowPass() { - return internalHandler.isRenderingShadowPass(); + return INTERNAL_HANDLER.isRenderingShadowPass(); + } + + @ApiStatus.Internal + public static void init() { + } + + private ShadersModHandler() { } private interface InternalHandler { diff --git a/src/main/java/com/jozufozu/flywheel/lib/vertex/VertexTransformations.java b/src/main/java/com/jozufozu/flywheel/lib/vertex/VertexTransformations.java new file mode 100644 index 000000000..4e37aff40 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/lib/vertex/VertexTransformations.java @@ -0,0 +1,36 @@ +package com.jozufozu.flywheel.lib.vertex; + +import com.jozufozu.flywheel.api.vertex.MutableVertexList; +import com.jozufozu.flywheel.lib.math.MatrixUtil; +import com.mojang.math.Matrix3f; +import com.mojang.math.Matrix4f; + +public final class VertexTransformations { + public static void transformPos(MutableVertexList vertexList, int index, Matrix4f matrix) { + float x = vertexList.x(index); + float y = vertexList.y(index); + float z = vertexList.z(index); + vertexList.x(index, MatrixUtil.transformPositionX(matrix, x, y, z)); + vertexList.y(index, MatrixUtil.transformPositionY(matrix, x, y, z)); + vertexList.z(index, MatrixUtil.transformPositionZ(matrix, x, y, z)); + } + + public static void transformNormal(MutableVertexList vertexList, int index, Matrix3f matrix) { + float nx = vertexList.normalX(index); + float ny = vertexList.normalY(index); + float nz = vertexList.normalZ(index); + float tnx = MatrixUtil.transformNormalX(matrix, nx, ny, nz); + float tny = MatrixUtil.transformNormalY(matrix, nx, ny, nz); + float tnz = MatrixUtil.transformNormalZ(matrix, nx, ny, nz); + float sqrLength = tnx * tnx + tny * tny + tnz * tnz; + if (sqrLength != 0) { + float f = 1 / (float) Math.sqrt(sqrLength); + tnx *= f; + tny *= f; + tnz *= f; + } + vertexList.normalX(index, tnx); + vertexList.normalY(index, tny); + vertexList.normalZ(index, tnz); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/mixin/ClientLevelMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/ClientLevelMixin.java index 0740b96f0..5e459f9f1 100644 --- a/src/main/java/com/jozufozu/flywheel/mixin/ClientLevelMixin.java +++ b/src/main/java/com/jozufozu/flywheel/mixin/ClientLevelMixin.java @@ -9,9 +9,9 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import com.google.common.collect.Lists; -import com.jozufozu.flywheel.backend.BackendUtil; import com.jozufozu.flywheel.extension.ClientLevelExtension; import com.jozufozu.flywheel.impl.instancing.InstancingControllerHelper; +import com.jozufozu.flywheel.util.FlwUtil; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.world.entity.Entity; @@ -29,7 +29,7 @@ public abstract class ClientLevelMixin implements ClientLevelExtension { @Inject(method = "entitiesForRendering", at = @At("RETURN"), cancellable = true) private void flywheel$filterEntities(CallbackInfoReturnable> cir) { - if (BackendUtil.canUseInstancing((ClientLevel) (Object) this)) { + if (FlwUtil.canUseInstancing((ClientLevel) (Object) this)) { Iterable entities = cir.getReturnValue(); ArrayList filtered = Lists.newArrayList(entities); diff --git a/src/main/java/com/jozufozu/flywheel/mixin/LevelRendererMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/LevelRendererMixin.java index 0da661d5e..f0642e61c 100644 --- a/src/main/java/com/jozufozu/flywheel/mixin/LevelRendererMixin.java +++ b/src/main/java/com/jozufozu/flywheel/mixin/LevelRendererMixin.java @@ -10,7 +10,6 @@ import org.spongepowered.asm.mixin.injection.At.Shift; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import com.jozufozu.flywheel.api.backend.BackendManager; import com.jozufozu.flywheel.api.event.BeginFrameEvent; import com.jozufozu.flywheel.api.event.ReloadRenderersEvent; import com.jozufozu.flywheel.api.event.RenderContext; @@ -56,8 +55,6 @@ public class LevelRendererMixin { @Inject(at = @At("TAIL"), method = "allChanged") private void flywheel$refresh(CallbackInfo ci) { - BackendManager.refresh(); - MinecraftForge.EVENT_BUS.post(new ReloadRenderersEvent(level)); } diff --git a/src/main/java/com/jozufozu/flywheel/mixin/instancemanage/ChunkRebuildHooksMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/instancemanage/ChunkRebuildHooksMixin.java index 48c90075b..324114960 100644 --- a/src/main/java/com/jozufozu/flywheel/mixin/instancemanage/ChunkRebuildHooksMixin.java +++ b/src/main/java/com/jozufozu/flywheel/mixin/instancemanage/ChunkRebuildHooksMixin.java @@ -7,9 +7,9 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import com.jozufozu.flywheel.backend.BackendUtil; import com.jozufozu.flywheel.impl.instancing.InstancedRenderDispatcher; import com.jozufozu.flywheel.impl.instancing.InstancingControllerHelper; +import com.jozufozu.flywheel.util.FlwUtil; import net.minecraft.client.renderer.chunk.ChunkRenderDispatcher; import net.minecraft.world.level.block.entity.BlockEntity; @@ -18,7 +18,7 @@ import net.minecraft.world.level.block.entity.BlockEntity; public class ChunkRebuildHooksMixin { @Inject(method = "handleBlockEntity", at = @At("HEAD"), cancellable = true) private void flywheel$addAndFilterBEs(ChunkRenderDispatcher.CompiledChunk compiledChunk, Set set, E be, CallbackInfo ci) { - if (BackendUtil.canUseInstancing(be.getLevel())) { + if (FlwUtil.canUseInstancing(be.getLevel())) { if (InstancingControllerHelper.canInstance(be)) InstancedRenderDispatcher.getBlockEntities(be.getLevel()).queueAdd(be); diff --git a/src/main/java/com/jozufozu/flywheel/mixin/instancemanage/InstanceAddMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/instancemanage/InstanceAddMixin.java index dcbcd7203..601bb9b72 100644 --- a/src/main/java/com/jozufozu/flywheel/mixin/instancemanage/InstanceAddMixin.java +++ b/src/main/java/com/jozufozu/flywheel/mixin/instancemanage/InstanceAddMixin.java @@ -7,8 +7,8 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import com.jozufozu.flywheel.backend.BackendUtil; import com.jozufozu.flywheel.impl.instancing.InstancedRenderDispatcher; +import com.jozufozu.flywheel.util.FlwUtil; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; @@ -23,7 +23,7 @@ public class InstanceAddMixin { @Inject(method = "setBlockEntity", at = @At(value = "INVOKE_ASSIGN", target = "Ljava/util/Map;put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;")) private void flywheel$onBlockEntityAdded(BlockEntity blockEntity, CallbackInfo ci) { - if (level.isClientSide && BackendUtil.canUseInstancing(level)) { + if (level.isClientSide && FlwUtil.canUseInstancing(level)) { InstancedRenderDispatcher.getBlockEntities(level) .add(blockEntity); } diff --git a/src/main/java/com/jozufozu/flywheel/mixin/instancemanage/InstanceRemoveMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/instancemanage/InstanceRemoveMixin.java index 4b4bce61b..4a6df32db 100644 --- a/src/main/java/com/jozufozu/flywheel/mixin/instancemanage/InstanceRemoveMixin.java +++ b/src/main/java/com/jozufozu/flywheel/mixin/instancemanage/InstanceRemoveMixin.java @@ -7,8 +7,8 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import com.jozufozu.flywheel.backend.BackendUtil; import com.jozufozu.flywheel.impl.instancing.InstancedRenderDispatcher; +import com.jozufozu.flywheel.util.FlwUtil; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.world.level.Level; @@ -22,7 +22,7 @@ public class InstanceRemoveMixin { @Inject(at = @At("TAIL"), method = "setRemoved") private void flywheel$removeInstance(CallbackInfo ci) { - if (level instanceof ClientLevel && BackendUtil.canUseInstancing(level)) { + if (level instanceof ClientLevel && FlwUtil.canUseInstancing(level)) { InstancedRenderDispatcher.getBlockEntities(level) .remove((BlockEntity) (Object) this); } diff --git a/src/main/java/com/jozufozu/flywheel/mixin/instancemanage/InstanceUpdateMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/instancemanage/InstanceUpdateMixin.java index 17b11ceab..363e1dc0e 100644 --- a/src/main/java/com/jozufozu/flywheel/mixin/instancemanage/InstanceUpdateMixin.java +++ b/src/main/java/com/jozufozu/flywheel/mixin/instancemanage/InstanceUpdateMixin.java @@ -6,8 +6,8 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import com.jozufozu.flywheel.backend.BackendUtil; import com.jozufozu.flywheel.impl.instancing.InstancedRenderDispatcher; +import com.jozufozu.flywheel.util.FlwUtil; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.renderer.LevelRenderer; @@ -25,7 +25,7 @@ public class InstanceUpdateMixin { */ @Inject(at = @At("TAIL"), method = "setBlockDirty(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/block/state/BlockState;)V") private void flywheel$checkUpdate(BlockPos pos, BlockState lastState, BlockState newState, CallbackInfo ci) { - if (!BackendUtil.canUseInstancing(level)) { + if (!FlwUtil.canUseInstancing(level)) { return; } BlockEntity blockEntity = level.getBlockEntity(pos); diff --git a/src/main/java/com/jozufozu/flywheel/util/CodecUtil.java b/src/main/java/com/jozufozu/flywheel/util/CodecUtil.java deleted file mode 100644 index 8263ce501..000000000 --- a/src/main/java/com/jozufozu/flywheel/util/CodecUtil.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.jozufozu.flywheel.util; - -import java.util.Collections; -import java.util.List; - -import com.mojang.datafixers.util.Either; -import com.mojang.serialization.Codec; - -public class CodecUtil { - - /** - * Creates a list codec that can be parsed from either a single element or a complete list. - */ - public static Codec> oneOrMore(Codec codec) { - return Codec.either(codec.listOf(), codec) - .xmap(either -> either.map(l -> l, Collections::singletonList), list -> { - if (list.size() == 1) { - return Either.right(list.get(0)); - } else { - return Either.left(list); - } - }); - } -} diff --git a/src/main/java/com/jozufozu/flywheel/util/FlwUtil.java b/src/main/java/com/jozufozu/flywheel/util/FlwUtil.java index a1d8ec095..ecef7d85e 100644 --- a/src/main/java/com/jozufozu/flywheel/util/FlwUtil.java +++ b/src/main/java/com/jozufozu/flywheel/util/FlwUtil.java @@ -1,18 +1,51 @@ package com.jozufozu.flywheel.util; import java.util.Collections; -import java.util.Map; import java.util.Set; import java.util.WeakHashMap; -import java.util.stream.Stream; -import org.joml.Math; -import org.joml.Matrix4f; -import org.lwjgl.system.MemoryUtil; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.Nullable; +import com.jozufozu.flywheel.api.FlywheelLevel; +import com.jozufozu.flywheel.api.backend.BackendManager; import com.mojang.blaze3d.vertex.PoseStack; -public class FlwUtil { +import net.minecraft.client.Minecraft; +import net.minecraft.world.level.LevelAccessor; + +public final class FlwUtil { + public static boolean isGameActive() { + return !(Minecraft.getInstance().level == null || Minecraft.getInstance().player == null); + } + + @Contract("null -> false") + public static boolean canUseInstancing(@Nullable LevelAccessor level) { + return BackendManager.isOn() && isFlywheelLevel(level); + } + + /** + * Used to avoid calling Flywheel functions on (fake) levels that don't specifically support it. + */ + public static boolean isFlywheelLevel(@Nullable LevelAccessor level) { + if (level == null) { + return false; + } + + if (!level.isClientSide()) { + return false; + } + + if (level instanceof FlywheelLevel flywheelLevel && flywheelLevel.supportsFlywheel()) { + return true; + } + + return level == Minecraft.getInstance().level; + } + + public static Set createWeakHashSet() { + return Collections.newSetFromMap(new WeakHashMap<>()); + } public static PoseStack copyPoseStack(PoseStack stack) { PoseStack copy = new PoseStack(); @@ -20,176 +53,4 @@ public class FlwUtil { copy.last().normal().load(stack.last().normal()); return copy; } - - 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 Stream mapValues(Map map) { - return map.values() - .stream(); - } - - public static void noop(T object) { - // noop - } - - public static int align16(int numToRound) { - return (numToRound + 16 - 1) & -16; - } - - public static Set createWeakHashSet() { - return Collections.newSetFromMap(new WeakHashMap<>()); - } - - /** - * 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/src/main/java/com/jozufozu/flywheel/vanilla/BellInstance.java b/src/main/java/com/jozufozu/flywheel/vanilla/BellInstance.java index 971f24d1c..aa9526224 100644 --- a/src/main/java/com/jozufozu/flywheel/vanilla/BellInstance.java +++ b/src/main/java/com/jozufozu/flywheel/vanilla/BellInstance.java @@ -7,14 +7,14 @@ import org.jetbrains.annotations.NotNull; import com.jozufozu.flywheel.api.event.RenderStage; import com.jozufozu.flywheel.api.instance.DynamicInstance; import com.jozufozu.flywheel.api.instance.controller.InstanceContext; -import com.jozufozu.flywheel.api.instancer.InstancePart; +import com.jozufozu.flywheel.api.struct.InstancePart; import com.jozufozu.flywheel.lib.instance.AbstractBlockEntityInstance; import com.jozufozu.flywheel.lib.material.Materials; import com.jozufozu.flywheel.lib.model.SimpleLazyModel; import com.jozufozu.flywheel.lib.modelpart.ModelPart; import com.jozufozu.flywheel.lib.struct.OrientedPart; import com.jozufozu.flywheel.lib.struct.StructTypes; -import com.jozufozu.flywheel.util.AnimationTickHolder; +import com.jozufozu.flywheel.lib.util.AnimationTickHolder; import com.mojang.math.Quaternion; import com.mojang.math.Vector3f; diff --git a/src/main/java/com/jozufozu/flywheel/vanilla/ChestInstance.java b/src/main/java/com/jozufozu/flywheel/vanilla/ChestInstance.java index 4b95610ca..4e862a238 100644 --- a/src/main/java/com/jozufozu/flywheel/vanilla/ChestInstance.java +++ b/src/main/java/com/jozufozu/flywheel/vanilla/ChestInstance.java @@ -7,7 +7,7 @@ import java.util.function.BiFunction; import com.jozufozu.flywheel.api.event.RenderStage; import com.jozufozu.flywheel.api.instance.DynamicInstance; import com.jozufozu.flywheel.api.instance.controller.InstanceContext; -import com.jozufozu.flywheel.api.instancer.InstancePart; +import com.jozufozu.flywheel.api.struct.InstancePart; import com.jozufozu.flywheel.lib.instance.AbstractBlockEntityInstance; import com.jozufozu.flywheel.lib.material.Materials; import com.jozufozu.flywheel.lib.model.SimpleLazyModel; @@ -15,7 +15,7 @@ import com.jozufozu.flywheel.lib.modelpart.ModelPart; import com.jozufozu.flywheel.lib.struct.OrientedPart; import com.jozufozu.flywheel.lib.struct.StructTypes; import com.jozufozu.flywheel.lib.struct.TransformedPart; -import com.jozufozu.flywheel.util.AnimationTickHolder; +import com.jozufozu.flywheel.lib.util.AnimationTickHolder; import com.mojang.math.Quaternion; import com.mojang.math.Vector3f; diff --git a/src/main/java/com/jozufozu/flywheel/vanilla/MinecartInstance.java b/src/main/java/com/jozufozu/flywheel/vanilla/MinecartInstance.java index d4b3bd9da..1e1cc638f 100644 --- a/src/main/java/com/jozufozu/flywheel/vanilla/MinecartInstance.java +++ b/src/main/java/com/jozufozu/flywheel/vanilla/MinecartInstance.java @@ -15,7 +15,7 @@ import com.jozufozu.flywheel.lib.modelpart.ModelPart; import com.jozufozu.flywheel.lib.struct.StructTypes; import com.jozufozu.flywheel.lib.struct.TransformedPart; import com.jozufozu.flywheel.lib.transform.TransformStack; -import com.jozufozu.flywheel.util.AnimationTickHolder; +import com.jozufozu.flywheel.lib.util.AnimationTickHolder; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.math.Vector3f; diff --git a/src/main/java/com/jozufozu/flywheel/vanilla/ShulkerBoxInstance.java b/src/main/java/com/jozufozu/flywheel/vanilla/ShulkerBoxInstance.java index 3cee8063a..da5c1eb84 100644 --- a/src/main/java/com/jozufozu/flywheel/vanilla/ShulkerBoxInstance.java +++ b/src/main/java/com/jozufozu/flywheel/vanilla/ShulkerBoxInstance.java @@ -6,7 +6,7 @@ import java.util.function.Function; import com.jozufozu.flywheel.api.event.RenderStage; import com.jozufozu.flywheel.api.instance.DynamicInstance; import com.jozufozu.flywheel.api.instance.controller.InstanceContext; -import com.jozufozu.flywheel.api.instancer.InstancePart; +import com.jozufozu.flywheel.api.struct.InstancePart; import com.jozufozu.flywheel.lib.instance.AbstractBlockEntityInstance; import com.jozufozu.flywheel.lib.material.Materials; import com.jozufozu.flywheel.lib.model.SimpleLazyModel; @@ -14,7 +14,7 @@ import com.jozufozu.flywheel.lib.modelpart.ModelPart; import com.jozufozu.flywheel.lib.struct.StructTypes; import com.jozufozu.flywheel.lib.struct.TransformedPart; import com.jozufozu.flywheel.lib.transform.TransformStack; -import com.jozufozu.flywheel.util.AnimationTickHolder; +import com.jozufozu.flywheel.lib.util.AnimationTickHolder; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.math.Quaternion; import com.mojang.math.Vector3f; diff --git a/src/main/java/com/jozufozu/flywheel/vanilla/VanillaInstances.java b/src/main/java/com/jozufozu/flywheel/vanilla/VanillaInstances.java index 5eef3079d..d372d4906 100644 --- a/src/main/java/com/jozufozu/flywheel/vanilla/VanillaInstances.java +++ b/src/main/java/com/jozufozu/flywheel/vanilla/VanillaInstances.java @@ -27,7 +27,6 @@ import net.minecraft.world.level.block.entity.BlockEntityType; * */ public class VanillaInstances { - public static void init() { configure(BlockEntityType.CHEST) .alwaysSkipRender() diff --git a/src/main/java/com/jozufozu/flywheel/vanilla/effect/ExampleEffect.java b/src/main/java/com/jozufozu/flywheel/vanilla/effect/ExampleEffect.java index fb6a8453e..c149585c4 100644 --- a/src/main/java/com/jozufozu/flywheel/vanilla/effect/ExampleEffect.java +++ b/src/main/java/com/jozufozu/flywheel/vanilla/effect/ExampleEffect.java @@ -22,7 +22,7 @@ import com.jozufozu.flywheel.lib.instance.AbstractInstance; import com.jozufozu.flywheel.lib.model.Models; import com.jozufozu.flywheel.lib.struct.StructTypes; import com.jozufozu.flywheel.lib.struct.TransformedPart; -import com.jozufozu.flywheel.util.AnimationTickHolder; +import com.jozufozu.flywheel.lib.util.AnimationTickHolder; import net.minecraft.client.Minecraft; import net.minecraft.core.BlockPos;