diff --git a/src/main/java/com/jozufozu/flywheel/api/struct/Batched.java b/src/main/java/com/jozufozu/flywheel/api/struct/Batched.java index ddf7e17b8..a61e326fd 100644 --- a/src/main/java/com/jozufozu/flywheel/api/struct/Batched.java +++ b/src/main/java/com/jozufozu/flywheel/api/struct/Batched.java @@ -1,10 +1,8 @@ package com.jozufozu.flywheel.api.struct; -import com.jozufozu.flywheel.core.model.Model; - public interface Batched extends StructType { - BatchingTransformer getTransformer(Model model); + BatchingTransformer getTransformer(); @Override default Batched asBatched() { diff --git a/src/main/java/com/jozufozu/flywheel/api/struct/BatchingTransformer.java b/src/main/java/com/jozufozu/flywheel/api/struct/BatchingTransformer.java index 16280a457..4b7e9f5d7 100644 --- a/src/main/java/com/jozufozu/flywheel/api/struct/BatchingTransformer.java +++ b/src/main/java/com/jozufozu/flywheel/api/struct/BatchingTransformer.java @@ -1,11 +1,9 @@ package com.jozufozu.flywheel.api.struct; -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.VertexConsumer; +import com.jozufozu.flywheel.core.model.SuperByteBuffer; -public abstract class BatchingTransformer { +@FunctionalInterface +public interface BatchingTransformer { - public void draw(S s, PoseStack stack, VertexConsumer consumer) { - - } + void transform(S s, SuperByteBuffer b); } diff --git a/src/main/java/com/jozufozu/flywheel/backend/Backend.java b/src/main/java/com/jozufozu/flywheel/backend/Backend.java index 2a14e44ff..ba02ae599 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/Backend.java +++ b/src/main/java/com/jozufozu/flywheel/backend/Backend.java @@ -17,10 +17,13 @@ import com.jozufozu.flywheel.api.FlywheelWorld; import com.jozufozu.flywheel.api.InstanceData; import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.backend.gl.versioned.GlCompat; +import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; import com.jozufozu.flywheel.config.FlwConfig; +import com.jozufozu.flywheel.config.FlwEngine; import com.jozufozu.flywheel.core.shader.spec.ProgramSpec; import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelAccessor; @@ -29,6 +32,7 @@ public class Backend { public static final Logger log = LogManager.getLogger(Backend.class); protected static final Backend INSTANCE = new Backend(); + private FlwEngine engine; public static Backend getInstance() { return INSTANCE; @@ -57,12 +61,13 @@ public class Backend { * (Meshlet, MDI, GL31 Draw Instanced are planned), this will name which one is in use. */ public String getBackendDescriptor() { - if (canUseInstancing()) { - return "GL33 Instanced Arrays"; - } + if (enabled) { + ClientLevel level = Minecraft.getInstance().level; - if (canUseVBOs()) { - return "VBOs"; + if (level == null) { + return "Invalid"; + } + return InstancedRenderDispatcher.getEngineName(level); } return "Disabled"; @@ -134,8 +139,9 @@ public class Backend { instancedArrays = compat.instancedArraysSupported(); - enabled = FlwConfig.get() - .enabled() && !OptifineHandler.usingShaders(); + FlwConfig config = FlwConfig.get(); + enabled = config.enabled() && !OptifineHandler.usingShaders(); + engine = config.client.engine.get(); } public boolean canUseInstancing(@Nullable Level world) { @@ -188,4 +194,8 @@ public class Backend { public static void init() { } + + public FlwEngine getEngine() { + return engine; + } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/AbstractInstancer.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/AbstractInstancer.java index 11aec327e..b6e85dbdc 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/AbstractInstancer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/AbstractInstancer.java @@ -58,6 +58,14 @@ public abstract class AbstractInstancer implements Insta anyToRemove = true; } + public int getModelVertexCount() { + return modelData.vertexCount(); + } + + public int numInstances() { + return data.size(); + } + protected BitSet getDirtyBitSet() { final int size = data.size(); final BitSet dirtySet = new BitSet(size); diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/Engine.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/Engine.java index 1e33c16db..a72a24a01 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/Engine.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/Engine.java @@ -3,4 +3,5 @@ package com.jozufozu.flywheel.backend.instancing; import com.jozufozu.flywheel.api.MaterialManager; public interface Engine extends RenderDispatcher, MaterialManager { + String getName(); } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceWorld.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceWorld.java index 7f127021f..f2cd13180 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceWorld.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceWorld.java @@ -2,10 +2,12 @@ package com.jozufozu.flywheel.backend.instancing; import com.jozufozu.flywheel.api.instance.IDynamicInstance; import com.jozufozu.flywheel.api.instance.ITickableInstance; +import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.instancing.batching.BatchingEngine; import com.jozufozu.flywheel.backend.instancing.entity.EntityInstanceManager; import com.jozufozu.flywheel.backend.instancing.instancing.InstancingEngine; import com.jozufozu.flywheel.backend.instancing.tile.TileInstanceManager; +import com.jozufozu.flywheel.config.FlwEngine; import com.jozufozu.flywheel.core.Contexts; import com.jozufozu.flywheel.core.shader.WorldProgram; import com.jozufozu.flywheel.event.BeginFrameEvent; @@ -29,12 +31,11 @@ public class InstanceWorld { public InstanceWorld() { - // TODO: finish impl - if (false) { - engine = new BatchingEngine(); - entityInstanceManager = new EntityInstanceManager(engine); - tileEntityInstanceManager = new TileInstanceManager(engine); - } else { + FlwEngine engine = Backend.getInstance() + .getEngine(); + + switch (engine) { + case GL33 -> { InstancingEngine manager = InstancingEngine.builder(Contexts.WORLD) .build(); @@ -43,7 +44,14 @@ public class InstanceWorld { manager.addListener(entityInstanceManager); manager.addListener(tileEntityInstanceManager); - engine = manager; + this.engine = manager; + } + case BATCHING -> { + this.engine = new BatchingEngine(); + entityInstanceManager = new EntityInstanceManager(this.engine); + tileEntityInstanceManager = new TileInstanceManager(this.engine); + } + default -> throw new IllegalArgumentException("Unknown engine type"); } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java index 426ff035b..c07a1d325 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java @@ -41,6 +41,10 @@ public class InstancedRenderDispatcher { getEntities(entity.level).queueUpdate(entity); } + public static String getEngineName(LevelAccessor world) { + return instanceWorlds.get(world).engine.getName(); + } + public static InstanceManager getTiles(LevelAccessor world) { return instanceWorlds.get(world) .getTileEntityInstanceManager(); diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchedMaterial.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchedMaterial.java index 2593c67bf..ad14cba40 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchedMaterial.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchedMaterial.java @@ -28,9 +28,9 @@ public class BatchedMaterial implements Material { return models.computeIfAbsent(key, $ -> new CPUInstancer<>(type, modelSupplier.get())); } - public void render(PoseStack stack, VertexConsumer buffer) { + public void render(PoseStack stack, VertexConsumer buffer, FormatContext context) { for (CPUInstancer instancer : models.values()) { - instancer.drawAll(stack, buffer); + instancer.drawAll(stack, buffer, context); } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchedMaterialGroup.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchedMaterialGroup.java index 7cad92ecb..ea7b65e7c 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchedMaterialGroup.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchedMaterialGroup.java @@ -6,6 +6,8 @@ import java.util.Map; import com.jozufozu.flywheel.api.InstanceData; import com.jozufozu.flywheel.api.MaterialGroup; import com.jozufozu.flywheel.api.struct.StructType; +import com.jozufozu.flywheel.backend.model.DirectBufferBuilder; +import com.jozufozu.flywheel.backend.model.DirectVertexConsumer; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; @@ -31,8 +33,31 @@ public class BatchedMaterialGroup implements MaterialGroup { public void render(PoseStack stack, MultiBufferSource source) { VertexConsumer buffer = source.getBuffer(state); + if (buffer instanceof DirectBufferBuilder direct) { + DirectVertexConsumer consumer = direct.intoDirectConsumer(calculateNeededVertices()); + + renderInto(stack, consumer, new FormatContext(consumer.hasOverlay())); + + direct.updateAfterWriting(consumer); + } else { + renderInto(stack, buffer, FormatContext.defaultContext()); + } + } + + private int calculateNeededVertices() { + int total = 0; + for (BatchedMaterial material : materials.values()) { + for (CPUInstancer instancer : material.models.values()) { + total += instancer.getModelVertexCount() * instancer.numInstances(); + } + } + + return total; + } + + private void renderInto(PoseStack stack, VertexConsumer consumer, FormatContext context) { for (BatchedMaterial value : materials.values()) { - value.render(stack, buffer); + value.render(stack, consumer, context); } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchingEngine.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchingEngine.java index 27535864a..ba915499e 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchingEngine.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchingEngine.java @@ -8,6 +8,7 @@ import com.jozufozu.flywheel.api.MaterialGroup; import com.jozufozu.flywheel.backend.RenderLayer; import com.jozufozu.flywheel.backend.instancing.Engine; import com.jozufozu.flywheel.event.RenderLayerEvent; +import com.mojang.blaze3d.vertex.PoseStack; import net.minecraft.client.Camera; import net.minecraft.client.renderer.MultiBufferSource; @@ -40,15 +41,28 @@ public class BatchingEngine implements Engine { @Override public void render(RenderLayerEvent event, MultiBufferSource buffers) { + PoseStack stack = event.stack; + + stack.pushPose(); + + stack.translate(-event.camX, -event.camY, -event.camZ); + for (Map.Entry entry : layers.get(event.getLayer()).entrySet()) { BatchedMaterialGroup group = entry.getValue(); - group.render(event.stack, buffers); + group.render(stack, buffers); } + + stack.popPose(); } @Override public void beginFrame(Camera info) { } + + @Override + public String getName() { + return "Batching"; + } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/CPUInstancer.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/CPUInstancer.java index 955c52a1c..38c5a7510 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/CPUInstancer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/CPUInstancer.java @@ -5,18 +5,23 @@ import com.jozufozu.flywheel.api.struct.BatchingTransformer; import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.backend.instancing.AbstractInstancer; import com.jozufozu.flywheel.core.model.Model; +import com.jozufozu.flywheel.core.model.SuperByteBuffer; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; +import com.mojang.blaze3d.vertex.VertexFormat; public class CPUInstancer extends AbstractInstancer { - private final BatchingTransformer renderer; + private final BatchingTransformer transform; + + private final SuperByteBuffer sbb; public CPUInstancer(StructType type, Model modelData) { super(type, modelData); - renderer = type.asBatched() - .getTransformer(modelData); + sbb = new SuperByteBuffer(modelData); + transform = type.asBatched() + .getTransformer(); } @Override @@ -24,15 +29,19 @@ public class CPUInstancer extends AbstractInstancer { // noop } - public void drawAll(PoseStack stack, VertexConsumer buffer) { - if (renderer == null) { + public void drawAll(PoseStack stack, VertexConsumer buffer, FormatContext context) { + if (transform == null) { return; } renderSetup(); for (D d : data) { - renderer.draw(d, stack, buffer); + if (context.usesOverlay()) sbb.entityMode(); + + transform.transform(d, sbb); + + sbb.renderInto(stack, buffer); } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/FormatContext.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/FormatContext.java new file mode 100644 index 000000000..bb0bbd41e --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/FormatContext.java @@ -0,0 +1,8 @@ +package com.jozufozu.flywheel.backend.instancing.batching; + +public record FormatContext(boolean usesOverlay) { + + public static FormatContext defaultContext() { + return new FormatContext(false); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancingEngine.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancingEngine.java index 7d1fa1cbe..1332a4a56 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancingEngine.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancingEngine.java @@ -165,6 +165,11 @@ public class InstancingEngine

implements Engine { } } + @Override + public String getName() { + return "GL33 Instanced Arrays"; + } + @FunctionalInterface public interface OriginShiftListener { void onOriginShift(); diff --git a/src/main/java/com/jozufozu/flywheel/backend/model/DirectBufferBuilder.java b/src/main/java/com/jozufozu/flywheel/backend/model/DirectBufferBuilder.java new file mode 100644 index 000000000..b3f08681a --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/model/DirectBufferBuilder.java @@ -0,0 +1,8 @@ +package com.jozufozu.flywheel.backend.model; + +public interface DirectBufferBuilder { + + DirectVertexConsumer intoDirectConsumer(int neededVerts); + + void updateAfterWriting(DirectVertexConsumer complete); +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/model/DirectVertexConsumer.java b/src/main/java/com/jozufozu/flywheel/backend/model/DirectVertexConsumer.java new file mode 100644 index 000000000..0bea53cb4 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/model/DirectVertexConsumer.java @@ -0,0 +1,136 @@ +package com.jozufozu.flywheel.backend.model; + +import java.nio.ByteBuffer; + +import org.lwjgl.system.MemoryUtil; + +import com.jozufozu.flywheel.util.RenderMath; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.mojang.blaze3d.vertex.VertexFormat; +import com.mojang.blaze3d.vertex.VertexFormatElement; + +public class DirectVertexConsumer implements VertexConsumer { + + public final VertexFormat format; + private final int stride; + public final int startPos; + + private int position = -1; + private int normal = -1; + private int color = -1; + private int uv = -1; + private int uv1 = -1; + private int uv2 = -1; + + private long vertexBase; + private int vertexCount; + + public DirectVertexConsumer(ByteBuffer buffer, VertexFormat format) { + this.format = format; + startPos = buffer.position(); + stride = format.getVertexSize(); + + int offset = 0; + + for (VertexFormatElement element : format.getElements()) { + switch (element.getUsage()) { + case POSITION -> this.position = offset; + case NORMAL -> this.normal = offset; + case COLOR -> this.color = offset; + case UV -> { + switch (element.getIndex()) { + case 0 -> this.uv = offset; + case 1 -> this.uv1 = offset; + case 2 -> this.uv2 = offset; + } + } + } + + offset += element.getByteSize(); + } + + this.vertexBase = MemoryUtil.memAddress(buffer); + } + + public boolean hasOverlay() { + return uv1 >= 0; + } + + @Override + public VertexConsumer vertex(double x, double y, double z) { + if (position < 0) return this; + long base = vertexBase + position; + MemoryUtil.memPutFloat(base, (float) x); + MemoryUtil.memPutFloat(base + 4, (float) y); + MemoryUtil.memPutFloat(base + 8, (float) z); + return this; + } + + @Override + public VertexConsumer color(int r, int g, int b, int a) { + if (color < 0) return this; + long base = vertexBase + color; + MemoryUtil.memPutByte(base, (byte) r); + MemoryUtil.memPutByte(base + 1, (byte) g); + MemoryUtil.memPutByte(base + 2, (byte) b); + MemoryUtil.memPutByte(base + 3, (byte) a); + return this; + } + + @Override + public VertexConsumer uv(float u, float v) { + if (uv < 0) return this; + long base = vertexBase + uv; + MemoryUtil.memPutFloat(base, u); + MemoryUtil.memPutFloat(base + 4, v); + return this; + } + + @Override + public VertexConsumer overlayCoords(int u, int v) { + if (uv1 < 0) return this; + long base = vertexBase + uv1; + MemoryUtil.memPutShort(base, (short) u); + MemoryUtil.memPutShort(base + 2, (short) v); + return this; + } + + @Override + public VertexConsumer uv2(int u, int v) { + if (uv2 < 0) return this; + long base = vertexBase + uv2; + MemoryUtil.memPutShort(base, (short) u); + MemoryUtil.memPutShort(base + 2, (short) v); + return this; + } + + @Override + public VertexConsumer normal(float x, float y, float z) { + if (normal < 0) return this; + long base = vertexBase + normal; + MemoryUtil.memPutByte(base, RenderMath.nb(x)); + MemoryUtil.memPutByte(base + 1, RenderMath.nb(y)); + MemoryUtil.memPutByte(base + 2, RenderMath.nb(z)); + return this; + } + + @Override + public void endVertex() { + vertexBase += stride; + vertexCount++; + } + + @Override + public void defaultColor(int r, int g, int b, int a) { + + } + + @Override + public void unsetDefaultColor() { + + } + + public int getVertexCount() { + return vertexCount; + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/model/package-info.java b/src/main/java/com/jozufozu/flywheel/backend/model/package-info.java new file mode 100644 index 000000000..3109529e1 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/model/package-info.java @@ -0,0 +1,6 @@ +@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault +package com.jozufozu.flywheel.backend.model; + +import javax.annotation.ParametersAreNonnullByDefault; + +import net.minecraft.MethodsReturnNonnullByDefault; diff --git a/src/main/java/com/jozufozu/flywheel/backend/struct/BufferWriter.java b/src/main/java/com/jozufozu/flywheel/backend/struct/BufferWriter.java index d46cbcaed..94f976f22 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/struct/BufferWriter.java +++ b/src/main/java/com/jozufozu/flywheel/backend/struct/BufferWriter.java @@ -18,14 +18,22 @@ public abstract class BufferWriter implements StructWriter { this.stride = this.format.getStride(); } - /** - * Advances the write pointer forward by the stride of one vertex. This should always be called after a - * vertex is written. Implementations which override this should always call invoke the super implementation. - */ - protected void advance() { - + @Override + public final void write(S struct) { + writeInternal(struct); + advance(); } + /** + * Advances the write pointer forward by the stride of one vertex. + * This will always be called after a struct is written, implementors need not call it themselves. + * + * @see #write + */ + protected abstract void advance(); + + protected abstract void writeInternal(S s); + @Override public void seek(int pos) { backingBuffer.position(pos * stride); diff --git a/src/main/java/com/jozufozu/flywheel/backend/struct/UnsafeBufferWriter.java b/src/main/java/com/jozufozu/flywheel/backend/struct/UnsafeBufferWriter.java index d5e97eeb9..b7c74e7f6 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/struct/UnsafeBufferWriter.java +++ b/src/main/java/com/jozufozu/flywheel/backend/struct/UnsafeBufferWriter.java @@ -15,7 +15,7 @@ import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer; */ public abstract class UnsafeBufferWriter extends BufferWriter { /** - * The write pointer into the buffer storage. This is advanced by the vertex stride every time + * The write pointer into the buffer storage. This is advanced by the stride every time * {@link UnsafeBufferWriter#advance()} is called. */ protected long writePointer; @@ -35,8 +35,6 @@ public abstract class UnsafeBufferWriter extends BufferWriter { @Override protected void advance() { this.writePointer += this.stride; - - super.advance(); } private void acquireWritePointer() { diff --git a/src/main/java/com/jozufozu/flywheel/config/EngineConfigCommand.java b/src/main/java/com/jozufozu/flywheel/config/EngineConfigCommand.java new file mode 100644 index 000000000..a5ab057ce --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/config/EngineConfigCommand.java @@ -0,0 +1,32 @@ +package com.jozufozu.flywheel.config; + +import com.mojang.brigadier.Command; +import com.mojang.brigadier.builder.ArgumentBuilder; + +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.commands.Commands; +import net.minecraft.server.level.ServerPlayer; +import net.minecraftforge.network.PacketDistributor; +import net.minecraftforge.server.command.EnumArgument; + +public class EngineConfigCommand { + public ArgumentBuilder register() { + return Commands.literal("engine") + .executes(context -> { + ServerPlayer player = context.getSource() + .getPlayerOrException(); + FlwPackets.channel.send(PacketDistributor.PLAYER.with(() -> player), new SConfigureEnginePacket()); + return Command.SINGLE_SUCCESS; + }) + .then(Commands.argument("type", EnumArgument.enumArgument(FlwEngine.class)) + .executes(context -> { + FlwEngine type = context.getArgument("type", FlwEngine.class); + + ServerPlayer player = context.getSource() + .getPlayerOrException(); + FlwPackets.channel.send(PacketDistributor.PLAYER.with(() -> player), new SConfigureEnginePacket(type)); + + return Command.SINGLE_SUCCESS; + })); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/config/FlwCommands.java b/src/main/java/com/jozufozu/flywheel/config/FlwCommands.java index 31525410c..3cee5f1eb 100644 --- a/src/main/java/com/jozufozu/flywheel/config/FlwCommands.java +++ b/src/main/java/com/jozufozu/flywheel/config/FlwCommands.java @@ -17,6 +17,7 @@ public class FlwCommands { dispatcher.register(Commands.literal("flywheel") .then(new BooleanConfigCommand("backend", BooleanConfig.ENGINE).register()) .then(new BooleanConfigCommand("debugNormals", BooleanConfig.NORMAL_OVERLAY).register()) + .then(new EngineConfigCommand().register()) ); } } diff --git a/src/main/java/com/jozufozu/flywheel/config/FlwConfig.java b/src/main/java/com/jozufozu/flywheel/config/FlwConfig.java index 0fd5a2673..1efdba072 100644 --- a/src/main/java/com/jozufozu/flywheel/config/FlwConfig.java +++ b/src/main/java/com/jozufozu/flywheel/config/FlwConfig.java @@ -39,6 +39,7 @@ public class FlwConfig { public static class ClientConfig { public final BooleanValue enabled; + public final ForgeConfigSpec.EnumValue engine; public final BooleanValue debugNormals; public ClientConfig(ForgeConfigSpec.Builder builder) { @@ -46,6 +47,9 @@ public class FlwConfig { enabled = builder.comment("Enable or disable the entire engine") .define("enabled", true); + engine = builder.comment("Enable or disable the entire engine") + .defineEnum("backend", FlwEngine.GL33); + debugNormals = builder.comment("Enable or disable a debug overlay that colors pixels by their normal") .define("debugNormals", false); } diff --git a/src/main/java/com/jozufozu/flywheel/config/FlwEngine.java b/src/main/java/com/jozufozu/flywheel/config/FlwEngine.java new file mode 100644 index 000000000..45a09fb45 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/config/FlwEngine.java @@ -0,0 +1,57 @@ +package com.jozufozu.flywheel.config; + +import javax.annotation.Nullable; + +import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.backend.OptifineHandler; + +import net.minecraft.ChatFormatting; +import net.minecraft.client.Minecraft; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.TextComponent; + +public enum FlwEngine { + BATCHING(new TextComponent("Batching").withStyle(ChatFormatting.BLUE)), + GL33(new TextComponent("GL 3.3 Instanced Arrays").withStyle(ChatFormatting.GREEN)), + + ; + + private final Component name; + + FlwEngine(Component name) { + this.name = name; + } + + @Nullable + public static FlwEngine decode(FriendlyByteBuf buffer) { + byte b = buffer.readByte(); + + if (b == -1) return null; + + return values()[b]; + } + + public void encode(FriendlyByteBuf buffer) { + buffer.writeByte(this.ordinal()); + } + + public void switchTo() { + LocalPlayer player = Minecraft.getInstance().player; + if (player == null) return; + +// if (state == BooleanDirective.DISPLAY) { +// Component text = new TextComponent("Flywheel renderer is currently: ").append(boolToText(FlwConfig.get().enabled())); +// player.displayClientMessage(text, false); +// return; +// } + + FlwConfig.get().client.engine.set(this); + + Component text = new TextComponent("Using ").withStyle(ChatFormatting.WHITE).append(name); + + player.displayClientMessage(text, false); + Backend.reloadWorldRenderers(); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/config/FlwPackets.java b/src/main/java/com/jozufozu/flywheel/config/FlwPackets.java index 97c4a0e46..eb968aa52 100644 --- a/src/main/java/com/jozufozu/flywheel/config/FlwPackets.java +++ b/src/main/java/com/jozufozu/flywheel/config/FlwPackets.java @@ -24,5 +24,11 @@ public class FlwPackets { .encoder(SConfigureBooleanPacket::encode) .consumer(SConfigureBooleanPacket::execute) .add(); + + channel.messageBuilder(SConfigureEnginePacket.class, 1, NetworkDirection.PLAY_TO_CLIENT) + .decoder(SConfigureEnginePacket::new) + .encoder(SConfigureEnginePacket::encode) + .consumer(SConfigureEnginePacket::execute) + .add(); } } diff --git a/src/main/java/com/jozufozu/flywheel/config/SConfigureEnginePacket.java b/src/main/java/com/jozufozu/flywheel/config/SConfigureEnginePacket.java new file mode 100644 index 000000000..ac7a4c8e9 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/config/SConfigureEnginePacket.java @@ -0,0 +1,38 @@ +package com.jozufozu.flywheel.config; + +import java.util.function.Supplier; + +import net.minecraft.network.FriendlyByteBuf; +import net.minecraftforge.network.NetworkEvent; + +public class SConfigureEnginePacket { + + private final FlwEngine type; + + public SConfigureEnginePacket() { + type = null; + } + + public SConfigureEnginePacket(FlwEngine type) { + this.type = type; + } + + public SConfigureEnginePacket(FriendlyByteBuf buffer) { + type = FlwEngine.decode(buffer); + } + + public void encode(FriendlyByteBuf buffer) { + if (type != null) + type.encode(buffer); + else + buffer.writeByte(-1); + } + + public void execute(Supplier ctx) { + if (type != null) { + type.switchTo(); + } + ctx.get() + .setPacketHandled(true); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/core/materials/BasicData.java b/src/main/java/com/jozufozu/flywheel/core/materials/BasicData.java index 1b34a856e..955aba918 100644 --- a/src/main/java/com/jozufozu/flywheel/core/materials/BasicData.java +++ b/src/main/java/com/jozufozu/flywheel/core/materials/BasicData.java @@ -2,6 +2,8 @@ package com.jozufozu.flywheel.core.materials; import com.jozufozu.flywheel.api.InstanceData; +import net.minecraft.client.renderer.LightTexture; + public abstract class BasicData extends InstanceData implements FlatLit { public byte blockLight; @@ -14,18 +16,23 @@ public abstract class BasicData extends InstanceData implements FlatLit> { * @return this */ D setSkyLight(int skyLight); + + int getPackedLight(); } diff --git a/src/main/java/com/jozufozu/flywheel/core/materials/UnsafeBasicWriter.java b/src/main/java/com/jozufozu/flywheel/core/materials/UnsafeBasicWriter.java new file mode 100644 index 000000000..5b36599e0 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/core/materials/UnsafeBasicWriter.java @@ -0,0 +1,25 @@ +package com.jozufozu.flywheel.core.materials; + +import org.lwjgl.system.MemoryUtil; + +import com.jozufozu.flywheel.api.struct.StructType; +import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer; +import com.jozufozu.flywheel.backend.struct.UnsafeBufferWriter; + +public abstract class UnsafeBasicWriter extends UnsafeBufferWriter { + + public UnsafeBasicWriter(VecBuffer backingBuffer, StructType vertexType) { + super(backingBuffer, vertexType); + } + + @Override + protected void writeInternal(D d) { + long addr = writePointer; + MemoryUtil.memPutByte(addr, (byte) (d.blockLight << 4)); + MemoryUtil.memPutByte(addr + 1, (byte) (d.skyLight << 4)); + MemoryUtil.memPutByte(addr + 2, d.r); + MemoryUtil.memPutByte(addr + 3, d.g); + MemoryUtil.memPutByte(addr + 4, d.b); + MemoryUtil.memPutByte(addr + 5, d.a); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/core/materials/model/ModelTransformer.java b/src/main/java/com/jozufozu/flywheel/core/materials/model/ModelTransformer.java deleted file mode 100644 index 0851fbcc4..000000000 --- a/src/main/java/com/jozufozu/flywheel/core/materials/model/ModelTransformer.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.jozufozu.flywheel.core.materials.model; - -import com.jozufozu.flywheel.api.struct.BatchingTransformer; -import com.jozufozu.flywheel.core.model.Model; - -public class ModelTransformer extends BatchingTransformer { - public ModelTransformer(Model model) { - - - //model.buffer(); - } -} diff --git a/src/main/java/com/jozufozu/flywheel/core/materials/model/ModelType.java b/src/main/java/com/jozufozu/flywheel/core/materials/model/ModelType.java index c815df2f9..9527cbb1f 100644 --- a/src/main/java/com/jozufozu/flywheel/core/materials/model/ModelType.java +++ b/src/main/java/com/jozufozu/flywheel/core/materials/model/ModelType.java @@ -8,8 +8,6 @@ import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat; import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer; import com.jozufozu.flywheel.core.Formats; import com.jozufozu.flywheel.core.Programs; -import com.jozufozu.flywheel.core.materials.model.writer.UnsafeModelWriter; -import com.jozufozu.flywheel.core.model.Model; import net.minecraft.resources.ResourceLocation; @@ -36,7 +34,11 @@ public class ModelType implements Instanced, Batched { } @Override - public BatchingTransformer getTransformer(Model model) { - return null; + public BatchingTransformer getTransformer() { + return (d, b) -> { + b.transform(d.model, d.normal) + .color(d.r, d.g, d.b, d.a) + .light(d.getPackedLight()); + }; } } diff --git a/src/main/java/com/jozufozu/flywheel/core/materials/model/UnsafeModelWriter.java b/src/main/java/com/jozufozu/flywheel/core/materials/model/UnsafeModelWriter.java new file mode 100644 index 000000000..9d041df58 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/core/materials/model/UnsafeModelWriter.java @@ -0,0 +1,23 @@ +package com.jozufozu.flywheel.core.materials.model; + +import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer; +import com.jozufozu.flywheel.api.struct.StructType; +import com.jozufozu.flywheel.core.materials.UnsafeBasicWriter; +import com.jozufozu.flywheel.util.WriteUnsafe; + +public class UnsafeModelWriter extends UnsafeBasicWriter { + + public UnsafeModelWriter(VecBuffer backingBuffer, StructType vertexType) { + super(backingBuffer, vertexType); + } + + @Override + protected void writeInternal(ModelData d) { + super.writeInternal(d); + long addr = writePointer + 6; + + ((WriteUnsafe) (Object) d.model).writeUnsafe(addr); + addr += 4 * 16; + ((WriteUnsafe) (Object) d.normal).writeUnsafe(addr); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/core/materials/model/writer/UnsafeModelWriter.java b/src/main/java/com/jozufozu/flywheel/core/materials/model/writer/UnsafeModelWriter.java deleted file mode 100644 index 9b04a8534..000000000 --- a/src/main/java/com/jozufozu/flywheel/core/materials/model/writer/UnsafeModelWriter.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.jozufozu.flywheel.core.materials.model.writer; - -import org.lwjgl.system.MemoryUtil; - -import com.jozufozu.flywheel.api.struct.StructType; -import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer; -import com.jozufozu.flywheel.backend.struct.UnsafeBufferWriter; -import com.jozufozu.flywheel.core.materials.model.ModelData; -import com.jozufozu.flywheel.util.WriteUnsafe; - -public class UnsafeModelWriter extends UnsafeBufferWriter { - - public UnsafeModelWriter(VecBuffer backingBuffer, StructType vertexType) { - super(backingBuffer, vertexType); - } - - @Override - public void write(ModelData d) { - long addr = writePointer; - MemoryUtil.memPutByte(addr, d.blockLight); - MemoryUtil.memPutByte(addr + 1, d.skyLight); - MemoryUtil.memPutByte(addr + 2, d.r); - MemoryUtil.memPutByte(addr + 3, d.g); - MemoryUtil.memPutByte(addr + 4, d.b); - MemoryUtil.memPutByte(addr + 5, d.a); - - addr += 6; - - ((WriteUnsafe) (Object) d.model).writeUnsafe(addr); - addr += 4 * 16; - ((WriteUnsafe) (Object) d.normal).writeUnsafe(addr); - - advance(); - } -} diff --git a/src/main/java/com/jozufozu/flywheel/core/materials/oriented/OrientedType.java b/src/main/java/com/jozufozu/flywheel/core/materials/oriented/OrientedType.java index 55f0097f4..c5625bca0 100644 --- a/src/main/java/com/jozufozu/flywheel/core/materials/oriented/OrientedType.java +++ b/src/main/java/com/jozufozu/flywheel/core/materials/oriented/OrientedType.java @@ -8,8 +8,7 @@ import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat; import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer; import com.jozufozu.flywheel.core.Formats; import com.jozufozu.flywheel.core.Programs; -import com.jozufozu.flywheel.core.materials.oriented.writer.UnsafeOrientedWriter; -import com.jozufozu.flywheel.core.model.Model; +import com.mojang.math.Quaternion; import net.minecraft.resources.ResourceLocation; @@ -36,7 +35,13 @@ public class OrientedType implements Instanced, Batched getTransformer(Model model) { - return null; + public BatchingTransformer getTransformer() { + return (d, sbb) -> { + sbb.light(d.getPackedLight()) + .color(d.r, d.g, d.b, d.a) + .translate(d.posX + d.pivotX, d.posY + d.pivotY, d.posZ + d.pivotZ) + .multiply(new Quaternion(d.qX, d.qY, d.qZ, d.qW)) + .translate(-d.pivotX, -d.pivotY, -d.pivotZ); + }; } } diff --git a/src/main/java/com/jozufozu/flywheel/core/materials/oriented/writer/UnsafeOrientedWriter.java b/src/main/java/com/jozufozu/flywheel/core/materials/oriented/UnsafeOrientedWriter.java similarity index 57% rename from src/main/java/com/jozufozu/flywheel/core/materials/oriented/writer/UnsafeOrientedWriter.java rename to src/main/java/com/jozufozu/flywheel/core/materials/oriented/UnsafeOrientedWriter.java index 3818985e0..c617e6396 100644 --- a/src/main/java/com/jozufozu/flywheel/core/materials/oriented/writer/UnsafeOrientedWriter.java +++ b/src/main/java/com/jozufozu/flywheel/core/materials/oriented/UnsafeOrientedWriter.java @@ -1,26 +1,20 @@ -package com.jozufozu.flywheel.core.materials.oriented.writer; +package com.jozufozu.flywheel.core.materials.oriented; import org.lwjgl.system.MemoryUtil; -import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer; -import com.jozufozu.flywheel.backend.struct.UnsafeBufferWriter; -import com.jozufozu.flywheel.core.materials.oriented.OrientedData; +import com.jozufozu.flywheel.api.struct.StructType; +import com.jozufozu.flywheel.core.materials.UnsafeBasicWriter; -public class UnsafeOrientedWriter extends UnsafeBufferWriter { +public class UnsafeOrientedWriter extends UnsafeBasicWriter { public UnsafeOrientedWriter(VecBuffer backingBuffer, StructType vertexType) { super(backingBuffer, vertexType); } @Override - public void write(OrientedData d) { + protected void writeInternal(OrientedData d) { long addr = writePointer; - MemoryUtil.memPutByte(addr, d.blockLight); - MemoryUtil.memPutByte(addr + 1, d.skyLight); - MemoryUtil.memPutByte(addr + 2, d.r); - MemoryUtil.memPutByte(addr + 3, d.g); - MemoryUtil.memPutByte(addr + 4, d.b); - MemoryUtil.memPutByte(addr + 5, d.a); + super.writeInternal(d); MemoryUtil.memPutFloat(addr + 6, d.posX); MemoryUtil.memPutFloat(addr + 10, d.posY); @@ -32,7 +26,5 @@ public class UnsafeOrientedWriter extends UnsafeBufferWriter { MemoryUtil.memPutFloat(addr + 34, d.qY); MemoryUtil.memPutFloat(addr + 38, d.qZ); MemoryUtil.memPutFloat(addr + 42, d.qW); - - advance(); } } diff --git a/src/main/java/com/jozufozu/flywheel/core/materials/package-info.java b/src/main/java/com/jozufozu/flywheel/core/materials/package-info.java new file mode 100644 index 000000000..09622d998 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/core/materials/package-info.java @@ -0,0 +1,6 @@ +@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault +package com.jozufozu.flywheel.core.materials; + +import javax.annotation.ParametersAreNonnullByDefault; + +import net.minecraft.MethodsReturnNonnullByDefault; diff --git a/src/main/java/com/jozufozu/flywheel/core/model/BakedModelModel.java b/src/main/java/com/jozufozu/flywheel/core/model/BakedModelModel.java deleted file mode 100644 index a972704fb..000000000 --- a/src/main/java/com/jozufozu/flywheel/core/model/BakedModelModel.java +++ /dev/null @@ -1,138 +0,0 @@ -package com.jozufozu.flywheel.core.model; - -import java.nio.Buffer; -import java.nio.ByteBuffer; -import java.nio.IntBuffer; -import java.util.Arrays; -import java.util.List; -import java.util.Random; - -import org.lwjgl.system.MemoryStack; - -import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat; -import com.jozufozu.flywheel.core.Formats; -import com.jozufozu.flywheel.util.VirtualEmptyModelData; -import com.mojang.blaze3d.vertex.DefaultVertexFormat; -import com.mojang.blaze3d.vertex.VertexConsumer; -import com.mojang.math.Vector3f; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.color.item.ItemColors; -import net.minecraft.client.renderer.block.model.BakedQuad; -import net.minecraft.client.resources.model.BakedModel; -import net.minecraft.core.Direction; -import net.minecraft.core.Vec3i; - -public class BakedModelModel implements Model { - // DOWN, UP, NORTH, SOUTH, WEST, EAST, null - private static final Direction[] dirs; - - static { - Direction[] directions = Direction.values(); - - dirs = Arrays.copyOf(directions, directions.length + 1); - } - - - public final BakedModel model; - private final int numQuads; - - public BakedModelModel(BakedModel model) { - this.model = model; - - Random random = new Random(); - - int numQuads = 0; - - for (Direction dir : dirs) { - random.setSeed(42); - List quads = model.getQuads(null, dir, random, VirtualEmptyModelData.INSTANCE); - - numQuads += quads.size(); - } - - this.numQuads = numQuads; - } - - @Override - public String name() { - return model.toString(); - } - - @Override - public void buffer(VertexConsumer buffer) { - - Minecraft mc = Minecraft.getInstance(); - - ItemColors itemColors = mc.getItemColors(); - - Random random = new Random(); - - for (Direction dir : dirs) { - random.setSeed(42); - List quads = model.getQuads(null, dir, random, VirtualEmptyModelData.INSTANCE); - - for (BakedQuad bakedQuad : quads) { -// int i = -1; -// if (!itemStack.isEmpty() && bakedQuad.isTinted()) { -// i = itemColors.getColor(itemStack, bakedQuad.getTintIndex()); -// } -// -// byte red = (byte)(i >> 16 & 255); -// byte green = (byte)(i >> 8 & 255); -// byte blue = (byte)(i & 255); - - int[] aint = bakedQuad.getVertices(); - Vec3i faceNormal = bakedQuad.getDirection().getNormal(); - Vector3f normal = new Vector3f((float)faceNormal.getX(), (float)faceNormal.getY(), (float)faceNormal.getZ()); - int intSize = DefaultVertexFormat.BLOCK.getIntegerSize(); - int vertexCount = aint.length / intSize; - - try (MemoryStack memorystack = MemoryStack.stackPush()) { - ByteBuffer bytebuffer = memorystack.malloc(DefaultVertexFormat.BLOCK.getVertexSize()); - IntBuffer intbuffer = bytebuffer.asIntBuffer(); - - for(int j = 0; j < vertexCount; ++j) { - ((Buffer)intbuffer).clear(); - intbuffer.put(aint, j * 8, 8); - float f = bytebuffer.getFloat(0); - float f1 = bytebuffer.getFloat(4); - float f2 = bytebuffer.getFloat(8); -// float cr; -// float cg; -// float cb; -// float ca; -// { -// float r = (float)(bytebuffer.get(12) & 255) / 255.0F; -// float g = (float)(bytebuffer.get(13) & 255) / 255.0F; -// float b = (float)(bytebuffer.get(14) & 255) / 255.0F; -// float a = (float)(bytebuffer.get(15) & 255) / 255.0F; -// cr = r * red; -// cg = g * green; -// cb = b * blue; -// ca = a; -// } - - float u = bytebuffer.getFloat(16); - float v = bytebuffer.getFloat(20); - - buffer.vertex(f, f1, f2); - buffer.normal(normal.x(), normal.y(), normal.z()); - buffer.uv(u, v); - buffer.endVertex(); - } - } - } - } - } - - @Override - public int vertexCount() { - return numQuads * 4; - } - - @Override - public VertexFormat format() { - return Formats.UNLIT_MODEL; - } -} diff --git a/src/main/java/com/jozufozu/flywheel/core/model/BlockModel.java b/src/main/java/com/jozufozu/flywheel/core/model/BlockModel.java index 44d81c899..0d3ae3dfb 100644 --- a/src/main/java/com/jozufozu/flywheel/core/model/BlockModel.java +++ b/src/main/java/com/jozufozu/flywheel/core/model/BlockModel.java @@ -5,6 +5,7 @@ import java.util.Arrays; import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat; import com.jozufozu.flywheel.core.Formats; import com.jozufozu.flywheel.util.BufferBuilderReader; +import com.jozufozu.flywheel.util.ModelReader; import com.jozufozu.flywheel.util.RenderMath; import com.jozufozu.flywheel.util.VirtualEmptyModelData; import com.mojang.blaze3d.vertex.BufferBuilder; @@ -27,7 +28,7 @@ import net.minecraft.world.level.block.state.BlockState; public class BlockModel implements Model { private static final PoseStack IDENTITY = new PoseStack(); - private final BufferBuilderReader reader; + private final ModelReader reader; private final String name; @@ -69,7 +70,7 @@ public class BlockModel implements Model { for (int i = 0; i < vertexCount; i++) { buffer.vertex(reader.getX(i), reader.getY(i), reader.getZ(i)); - buffer.normal(RenderMath.f(reader.getNX(i)), RenderMath.f(reader.getNY(i)), RenderMath.f(reader.getNZ(i))); + buffer.normal(reader.getNX(i), reader.getNY(i), reader.getNZ(i)); buffer.uv(reader.getU(i), reader.getV(i)); @@ -77,6 +78,11 @@ public class BlockModel implements Model { } } + @Override + public ModelReader getReader() { + return reader; + } + public static BufferBuilder getBufferBuilder(BakedModel model, BlockState referenceState, PoseStack ms) { Minecraft mc = Minecraft.getInstance(); BlockRenderDispatcher dispatcher = mc.getBlockRenderer(); @@ -96,12 +102,4 @@ public class BlockModel implements Model { return builder; } - // DOWN, UP, NORTH, SOUTH, WEST, EAST, null - private static final Direction[] dirs; - - static { - Direction[] directions = Direction.values(); - - dirs = Arrays.copyOf(directions, directions.length + 1); - } } diff --git a/src/main/java/com/jozufozu/flywheel/core/model/Model.java b/src/main/java/com/jozufozu/flywheel/core/model/Model.java index fb8704742..863cef816 100644 --- a/src/main/java/com/jozufozu/flywheel/core/model/Model.java +++ b/src/main/java/com/jozufozu/flywheel/core/model/Model.java @@ -3,6 +3,7 @@ package com.jozufozu.flywheel.core.model; import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat; import com.jozufozu.flywheel.backend.model.ElementBuffer; import com.jozufozu.flywheel.core.QuadConverter; +import com.jozufozu.flywheel.util.ModelReader; import com.mojang.blaze3d.vertex.VertexConsumer; /** @@ -76,4 +77,6 @@ public interface Model { default boolean empty() { return vertexCount() == 0; } + + ModelReader getReader(); } diff --git a/src/main/java/com/jozufozu/flywheel/core/model/ModelPart.java b/src/main/java/com/jozufozu/flywheel/core/model/ModelPart.java index bf4498090..0b87087fb 100644 --- a/src/main/java/com/jozufozu/flywheel/core/model/ModelPart.java +++ b/src/main/java/com/jozufozu/flywheel/core/model/ModelPart.java @@ -1,10 +1,15 @@ package com.jozufozu.flywheel.core.model; +import java.nio.ByteBuffer; import java.util.List; import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat; +import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer; import com.jozufozu.flywheel.core.Formats; +import com.jozufozu.flywheel.util.ModelReader; +import com.jozufozu.flywheel.util.RenderMath; import com.mojang.blaze3d.vertex.VertexConsumer; +import com.mojang.math.Vector3f; public class ModelPart implements Model { @@ -48,4 +53,95 @@ public class ModelPart implements Model { public VertexFormat format() { return Formats.UNLIT_MODEL; } + + @Override + public ModelReader getReader() { + return new PartReader(this); + } + + private class PartReader implements ModelReader { + + private final ByteBuffer buffer; + + private PartReader(ModelPart part) { + this.buffer = ByteBuffer.allocate(part.size()); + VecBufferWriter writer = new VecBufferWriter(this.buffer); + + buffer(writer); + } + + private int vertIdx(int vertexIndex) { + return vertexIndex * format().getStride(); + } + + @Override + public float getX(int index) { + return buffer.getFloat(vertIdx(index)); + } + + @Override + public float getY(int index) { + return buffer.getFloat(vertIdx(index) + 4); + } + + @Override + public float getZ(int index) { + return buffer.getFloat(vertIdx(index) + 8); + } + + @Override + public byte getR(int index) { + return (byte) 0xFF; + } + + @Override + public byte getG(int index) { + return (byte) 0xFF; + } + + @Override + public byte getB(int index) { + return (byte) 0xFF; + } + + @Override + public byte getA(int index) { + return (byte) 0xFF; + } + + @Override + public float getU(int index) { + return buffer.getFloat(vertIdx(index) + 15); + } + + @Override + public float getV(int index) { + return buffer.getFloat(vertIdx(index) + 19); + } + + @Override + public int getLight(int index) { + return 0; + } + + @Override + public float getNX(int index) { + return RenderMath.f(buffer.get(vertIdx(index) + 12)); + } + + @Override + public float getNY(int index) { + return RenderMath.f(buffer.get(vertIdx(index) + 13)); + } + + @Override + public float getNZ(int index) { + return RenderMath.f(buffer.get(vertIdx(index) + 14)); + } + + @Override + public int getVertexCount() { + return vertices; + } + } } diff --git a/src/main/java/com/jozufozu/flywheel/core/model/RecordingVertexConsumer.java b/src/main/java/com/jozufozu/flywheel/core/model/RecordingVertexConsumer.java deleted file mode 100644 index 127604939..000000000 --- a/src/main/java/com/jozufozu/flywheel/core/model/RecordingVertexConsumer.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.jozufozu.flywheel.core.model; - -import java.util.ArrayList; -import java.util.List; -import java.util.function.Consumer; - -import com.google.common.collect.ImmutableList; -import com.mojang.blaze3d.vertex.VertexConsumer; - -public class RecordingVertexConsumer implements VertexConsumer { - - List> replay = new ArrayList<>(); - - @Override - public VertexConsumer vertex(double x, double y, double z) { - replay.add(v -> v.vertex(x, y, z)); - return this; - } - - @Override - public VertexConsumer color(int r, int g, int b, int a) { - replay.add(v -> v.color(r, g, b, a)); - return this; - } - - @Override - public VertexConsumer uv(float u, float v) { - replay.add(vc -> vc.uv(u, v)); - return this; - } - - @Override - public VertexConsumer overlayCoords(int u, int v) { - replay.add(vc -> vc.overlayCoords(u, v)); - return this; - } - - @Override - public VertexConsumer uv2(int u, int v) { - replay.add(vc -> vc.uv2(u, v)); - return this; - } - - @Override - public VertexConsumer normal(float x, float y, float z) { - replay.add(v -> v.normal(x, y, z)); - return this; - } - - @Override - public void endVertex() { - replay.add(VertexConsumer::endVertex); - } - - @Override - public void defaultColor(int r, int g, int b, int a) { - replay.add(vc -> vc.defaultColor(r, g, b, a)); - } - - @Override - public void unsetDefaultColor() { - replay.add(VertexConsumer::unsetDefaultColor); - } - - public VertexRecording saveRecording() { - VertexRecording out = new VertexRecording(ImmutableList.copyOf(replay)); - replay.clear(); - return out; - } -} diff --git a/src/main/java/com/jozufozu/flywheel/core/model/SuperByteBuffer.java b/src/main/java/com/jozufozu/flywheel/core/model/SuperByteBuffer.java new file mode 100644 index 000000000..4d3aa6561 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/core/model/SuperByteBuffer.java @@ -0,0 +1,468 @@ +package com.jozufozu.flywheel.core.model; + +import com.jozufozu.flywheel.util.ModelReader; +import com.jozufozu.flywheel.util.transform.Rotate; +import com.jozufozu.flywheel.util.transform.Scale; +import com.jozufozu.flywheel.util.transform.TStack; +import com.jozufozu.flywheel.util.transform.Translate; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.mojang.math.*; + +import it.unimi.dsi.fastutil.longs.Long2IntMap; +import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.LevelRenderer; +import net.minecraft.client.renderer.LightTexture; +import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.util.Mth; +import net.minecraft.world.level.Level; +import net.minecraftforge.client.model.pipeline.LightUtil; + +public class SuperByteBuffer implements Scale, Translate, Rotate, TStack { + + private final Model model; + private final ModelReader template; + + // Vertex Position + private final PoseStack transforms; + + private final Params defaultParams = Params.defaultParams(); + private final Params params = defaultParams.copy(); + + // Temporary + private static final Long2IntMap WORLD_LIGHT_CACHE = new Long2IntOpenHashMap(); + private final Vector4f pos = new Vector4f(); + private final Vector3f normal = new Vector3f(); + private final Vector4f lightPos = new Vector4f(); + + public SuperByteBuffer(Model model) { + this.model = model; + template = model.getReader(); + + transforms = new PoseStack(); + transforms.pushPose(); + } + + public void renderInto(PoseStack input, VertexConsumer builder) { + if (isEmpty()) + return; + + Matrix4f modelMat = input.last() + .pose() + .copy(); + Matrix4f localTransforms = transforms.last() + .pose(); + modelMat.multiply(localTransforms); + + Matrix3f normalMat; + + if (params.fullNormalTransform) { + normalMat = input.last().normal().copy(); + normalMat.mul(transforms.last().normal()); + } else { + normalMat = transforms.last().normal().copy(); + } + + if (params.useWorldLight) { + WORLD_LIGHT_CACHE.clear(); + } + + float f = .5f; + int vertexCount = template.getVertexCount(); + for (int i = 0; i < vertexCount; i++) { + float x = template.getX(i); + float y = template.getY(i); + float z = template.getZ(i); + pos.set(x, y, z, 1F); + pos.transform(modelMat); + builder.vertex(pos.x(), pos.y(), pos.z()); + + float normalX = template.getNX(i); + float normalY = template.getNY(i); + float normalZ = template.getNZ(i); + + normal.set(normalX, normalY, normalZ); + normal.transform(normalMat); + normal.normalize(); + float nx = normal.x(); + float ny = normal.y(); + float nz = normal.z(); + + float instanceDiffuse = LightUtil.diffuseLight(nx, ny, nz); + + switch (params.colorMode) { + case MODEL_ONLY -> builder.color(template.getR(i), template.getG(i), template.getB(i), template.getA(i)); + case DIFFUSE_ONLY -> builder.color(instanceDiffuse, instanceDiffuse, instanceDiffuse, 1f); + case MODEL_DIFFUSE -> { + int r = Byte.toUnsignedInt(template.getR(i)); + int g = Byte.toUnsignedInt(template.getG(i)); + int b = Byte.toUnsignedInt(template.getB(i)); + int a = Byte.toUnsignedInt(template.getA(i)); + + float diffuse = switch (params.diffuseMode) { + case NONE -> 1f; + case INSTANCE -> instanceDiffuse; + case ONE_OVER_STATIC -> 1 / LightUtil.diffuseLight(normalX, normalY, normalZ); + case INSTANCE_OVER_STATIC -> instanceDiffuse / LightUtil.diffuseLight(normalX, normalY, normalZ); + }; + + if (diffuse != 1) { + r = transformColor(r, diffuse); + g = transformColor(g, diffuse); + b = transformColor(b, diffuse); + } + + builder.color(r, g, b, a); + } + case RECOLOR -> { + if (params.diffuseMode == DiffuseMode.NONE) { + builder.color(params.r, params.g, params.b, params.a); + } else { + int colorR = transformColor(params.r, instanceDiffuse); + int colorG = transformColor(params.g, instanceDiffuse); + int colorB = transformColor(params.b, instanceDiffuse); + builder.color(colorR, colorG, colorB, params.a); + } + } + } + + //builder.color(Math.max(0, (int) (nx * 255)), Math.max(0, (int) (ny * 255)), Math.max(0, (int) (nz * 255)), 0xFF); + //builder.color(Math.max(0, (int) (normalX * 255)), Math.max(0, (int) (normalY * 255)), Math.max(0, (int) (normalZ * 255)), 0xFF); + + float u = template.getU(i); + float v = template.getV(i); + if (params.spriteShiftFunc != null) { + params.spriteShiftFunc.shift(builder, u, v); + } else { + builder.uv(u, v); + } + + if (params.hasOverlay) { + builder.overlayCoords(params.overlay); + } + + int light; + if (params.useWorldLight) { + lightPos.set(((x - f) * 15 / 16f) + f, (y - f) * 15 / 16f + f, (z - f) * 15 / 16f + f, 1F); + lightPos.transform(localTransforms); + if (params.lightTransform != null) { + lightPos.transform(params.lightTransform); + } + + light = getLight(Minecraft.getInstance().level, lightPos); + if (params.hasCustomLight) { + light = maxLight(light, params.packedLightCoords); + } + } else if (params.hasCustomLight) { + light = params.packedLightCoords; + } else { + light = template.getLight(i); + } + + if (params.hybridLight) { + builder.uv2(maxLight(light, template.getLight(i))); + } else { + builder.uv2(light); + } + + builder.normal(nx, ny, nz); + + builder.endVertex(); + } + + reset(); + } + + public SuperByteBuffer reset() { + while (!transforms.clear()) + transforms.popPose(); + transforms.pushPose(); + + params.load(defaultParams); + + return this; + } + + @Override + public SuperByteBuffer translate(double x, double y, double z) { + transforms.translate(x, y, z); + return this; + } + + @Override + public SuperByteBuffer multiply(Quaternion quaternion) { + transforms.mulPose(quaternion); + return this; + } + + public SuperByteBuffer transform(PoseStack stack) { + PoseStack.Pose last = stack.last(); + return transform(last.pose(), last.normal()); + } + + public SuperByteBuffer transform(Matrix4f pose, Matrix3f normal) { + transforms.last() + .pose() + .multiply(pose); + transforms.last() + .normal() + .mul(normal); + return this; + } + + public SuperByteBuffer rotateCentered(Direction axis, float radians) { + translate(.5f, .5f, .5f).rotate(axis, radians) + .translate(-.5f, -.5f, -.5f); + return this; + } + + public SuperByteBuffer rotateCentered(Quaternion q) { + translate(.5f, .5f, .5f).multiply(q) + .translate(-.5f, -.5f, -.5f); + return this; + } + + public SuperByteBuffer color(int r, int g, int b, int a) { + params.colorMode = ColorMode.RECOLOR; + params.r = r; + params.g = g; + params.b = b; + params.a = a; + return this; + } + + public SuperByteBuffer color(byte r, byte g, byte b, byte a) { + params.colorMode = ColorMode.RECOLOR; + params.r = Byte.toUnsignedInt(r); + params.g = Byte.toUnsignedInt(g); + params.b = Byte.toUnsignedInt(b); + params.a = Byte.toUnsignedInt(a); + return this; + } + + public SuperByteBuffer color(int color) { + params.colorMode = ColorMode.RECOLOR; + params.r = ((color >> 16) & 0xFF); + params.g = ((color >> 8) & 0xFF); + params.b = (color & 0xFF); + params.a = 255; + return this; + } + + public SuperByteBuffer shiftUV(SpriteShiftFunc entry) { + params.spriteShiftFunc = entry; + return this; + } + + public SuperByteBuffer overlay() { + params.hasOverlay = true; + return this; + } + + public SuperByteBuffer overlay(int overlay) { + params.hasOverlay = true; + params.overlay = overlay; + return this; + } + + /** + * Transforms normals not only by the local matrix stack, but also by the passed matrix stack. + */ + public SuperByteBuffer entityMode() { + params.hasOverlay = true; + params.fullNormalTransform = true; + params.diffuseMode = DiffuseMode.NONE; + params.colorMode = ColorMode.RECOLOR; + return this; + } + + public SuperByteBuffer light() { + params.useWorldLight = true; + return this; + } + + public SuperByteBuffer light(Matrix4f lightTransform) { + params.useWorldLight = true; + params.lightTransform = lightTransform; + return this; + } + + public SuperByteBuffer light(int packedLightCoords) { + params.hasCustomLight = true; + params.packedLightCoords = packedLightCoords; + return this; + } + + public SuperByteBuffer light(Matrix4f lightTransform, int packedLightCoords) { + light(lightTransform); + light(packedLightCoords); + return this; + } + + /** + * Uses max light from calculated light (world light or custom light) and vertex light for the final light value. + * Ineffective if any other light method was not called. + */ + public SuperByteBuffer hybridLight() { + params.hybridLight = true; + return this; + } + + public boolean isEmpty() { + return template.isEmpty(); + } + + @Override + public SuperByteBuffer scale(float factorX, float factorY, float factorZ) { + transforms.scale(factorX, factorY, factorZ); + return this; + } + + @Override + public SuperByteBuffer pushPose() { + transforms.pushPose(); + return this; + } + + @Override + public SuperByteBuffer popPose() { + transforms.popPose(); + return this; + } + + @Override + public String toString() { + return "SuperByteBuffer[" + model + ']'; + } + + public static int transformColor(int component, float scale) { + return Mth.clamp((int) (component * scale), 0, 255); + } + + public static int maxLight(int packedLight1, int packedLight2) { + int blockLight1 = LightTexture.block(packedLight1); + int skyLight1 = LightTexture.sky(packedLight1); + int blockLight2 = LightTexture.block(packedLight2); + int skyLight2 = LightTexture.sky(packedLight2); + return LightTexture.pack(Math.max(blockLight1, blockLight2), Math.max(skyLight1, skyLight2)); + } + + private static int getLight(Level world, Vector4f lightPos) { + BlockPos pos = new BlockPos(lightPos.x(), lightPos.y(), lightPos.z()); + return WORLD_LIGHT_CACHE.computeIfAbsent(pos.asLong(), $ -> LevelRenderer.getLightColor(world, pos)); + } + + @FunctionalInterface + public interface SpriteShiftFunc { + void shift(VertexConsumer builder, float u, float v); + } + + public enum ColorMode { + MODEL_ONLY, + MODEL_DIFFUSE, + DIFFUSE_ONLY, + RECOLOR + } + + public enum DiffuseMode { + NONE, + INSTANCE, + ONE_OVER_STATIC, + INSTANCE_OVER_STATIC, + } + + public static class Params { + // Vertex Coloring + public ColorMode colorMode = ColorMode.DIFFUSE_ONLY; + public DiffuseMode diffuseMode = DiffuseMode.INSTANCE; + public int r; + public int g; + public int b; + public int a; + + // Vertex Texture Coords + public SpriteShiftFunc spriteShiftFunc; + + // Vertex Overlay Color + public boolean hasOverlay; + public int overlay = OverlayTexture.NO_OVERLAY; + + // Vertex Lighting + public boolean useWorldLight; + public Matrix4f lightTransform; + public boolean hasCustomLight; + public int packedLightCoords; + public boolean hybridLight; + + // Vertex Normals + public boolean fullNormalTransform; + + public void load(Params from) { + colorMode = from.colorMode; + diffuseMode = from.diffuseMode; + r = from.r; + g = from.g; + b = from.b; + a = from.a; + spriteShiftFunc = from.spriteShiftFunc; + hasOverlay = from.hasOverlay; + overlay = from.overlay; + useWorldLight = from.useWorldLight; + lightTransform = from.lightTransform; + hasCustomLight = from.hasCustomLight; + packedLightCoords = from.packedLightCoords; + hybridLight = from.hybridLight; + fullNormalTransform = from.fullNormalTransform; + } + + public Params copy() { + Params params = new Params(); + params.load(this); + return params; + } + + public static Params defaultParams() { + Params out = new Params(); + out.colorMode = ColorMode.DIFFUSE_ONLY; + out.diffuseMode = DiffuseMode.INSTANCE; + out.r = 0xFF; + out.g = 0xFF; + out.b = 0xFF; + out.a = 0xFF; + out.spriteShiftFunc = null; + out.hasOverlay = false; + out.overlay = OverlayTexture.NO_OVERLAY; + out.useWorldLight = false; + out.lightTransform = null; + out.hasCustomLight = false; + out.packedLightCoords = 0; + out.hybridLight = false; + out.fullNormalTransform = false; + return out; + } + + public static Params newEntityParams() { + Params out = new Params(); + out.colorMode = ColorMode.RECOLOR; + out.diffuseMode = DiffuseMode.NONE; + out.r = 0xFF; + out.g = 0xFF; + out.b = 0xFF; + out.a = 0xFF; + out.spriteShiftFunc = null; + out.hasOverlay = true; + out.overlay = OverlayTexture.NO_OVERLAY; + out.useWorldLight = false; + out.lightTransform = null; + out.hasCustomLight = false; + out.packedLightCoords = 0; + out.hybridLight = false; + out.fullNormalTransform = true; + return out; + } + } +} diff --git a/src/main/java/com/jozufozu/flywheel/core/model/VecBufferWriter.java b/src/main/java/com/jozufozu/flywheel/core/model/VecBufferWriter.java index fefc5cf80..c1ea4957c 100644 --- a/src/main/java/com/jozufozu/flywheel/core/model/VecBufferWriter.java +++ b/src/main/java/com/jozufozu/flywheel/core/model/VecBufferWriter.java @@ -2,6 +2,8 @@ package com.jozufozu.flywheel.core.model; import static com.jozufozu.flywheel.util.RenderMath.nb; +import java.nio.ByteBuffer; + import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer; import com.mojang.blaze3d.vertex.VertexConsumer; @@ -9,6 +11,10 @@ public class VecBufferWriter implements VertexConsumer { private final VecBuffer buffer; + public VecBufferWriter(ByteBuffer buffer) { + this.buffer = new VecBuffer(buffer); + } + public VecBufferWriter(VecBuffer buffer) { this.buffer = buffer; } diff --git a/src/main/java/com/jozufozu/flywheel/core/model/VertexRecording.java b/src/main/java/com/jozufozu/flywheel/core/model/VertexRecording.java deleted file mode 100644 index 82df180ff..000000000 --- a/src/main/java/com/jozufozu/flywheel/core/model/VertexRecording.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.jozufozu.flywheel.core.model; - -import java.util.function.Consumer; - -import com.google.common.collect.ImmutableList; -import com.mojang.blaze3d.vertex.VertexConsumer; - -public record VertexRecording(ImmutableList> recording) { - - public void replay(VertexConsumer vc) { - for (Consumer consumer : recording) { - consumer.accept(vc); - } - } -} diff --git a/src/main/java/com/jozufozu/flywheel/core/model/WorldModel.java b/src/main/java/com/jozufozu/flywheel/core/model/WorldModel.java index c9c355c05..c5f5dff2e 100644 --- a/src/main/java/com/jozufozu/flywheel/core/model/WorldModel.java +++ b/src/main/java/com/jozufozu/flywheel/core/model/WorldModel.java @@ -5,6 +5,7 @@ import java.util.Collection; import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat; import com.jozufozu.flywheel.core.Formats; import com.jozufozu.flywheel.util.BufferBuilderReader; +import com.jozufozu.flywheel.util.ModelReader; import com.jozufozu.flywheel.util.RenderMath; import com.mojang.blaze3d.vertex.VertexConsumer; @@ -15,7 +16,7 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemp public class WorldModel implements Model { - private final BufferBuilderReader reader; + private final ModelReader reader; private final String name; public WorldModel(BlockAndTintGetter renderWorld, RenderType layer, Collection blocks, String name) { @@ -33,7 +34,7 @@ public class WorldModel implements Model { for (int i = 0; i < vertexCount(); i++) { vertices.vertex(reader.getX(i), reader.getY(i), reader.getZ(i)); - vertices.normal(RenderMath.f(reader.getNX(i)), RenderMath.f(reader.getNY(i)), RenderMath.f(reader.getNZ(i))); + vertices.normal(reader.getNX(i), reader.getNY(i), reader.getNZ(i)); vertices.uv(reader.getU(i), reader.getV(i)); @@ -60,4 +61,8 @@ public class WorldModel implements Model { return Formats.COLORED_LIT_MODEL; } + @Override + public ModelReader getReader() { + return reader; + } } diff --git a/src/main/java/com/jozufozu/flywheel/mixin/BufferBuilderMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/BufferBuilderMixin.java new file mode 100644 index 000000000..a22223d2f --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/mixin/BufferBuilderMixin.java @@ -0,0 +1,58 @@ +package com.jozufozu.flywheel.mixin; + +import java.nio.ByteBuffer; + +import javax.annotation.Nullable; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import com.jozufozu.flywheel.backend.model.DirectVertexConsumer; +import com.jozufozu.flywheel.backend.model.DirectBufferBuilder; +import com.mojang.blaze3d.vertex.BufferBuilder; +import com.mojang.blaze3d.vertex.VertexFormat; +import com.mojang.blaze3d.vertex.VertexFormatElement; + +@Mixin(BufferBuilder.class) +public abstract class BufferBuilderMixin implements DirectBufferBuilder { + @Shadow + private ByteBuffer buffer; + + @Shadow + private VertexFormat format; + + @Shadow + protected abstract void ensureCapacity(int p_85723_); + + @Shadow + private int vertices; + + @Shadow + @Nullable + private VertexFormatElement currentElement; + + @Shadow + private int elementIndex; + + @Shadow + private int nextElementByte; + + @Override + public DirectVertexConsumer intoDirectConsumer(int neededVerts) { + ensureCapacity(neededVerts * this.format.getVertexSize()); + return new DirectVertexConsumer(this.buffer, this.format); + } + + @Override + public void updateAfterWriting(DirectVertexConsumer complete) { + int vertexCount = complete.getVertexCount(); + int totalWrittenBytes = vertexCount * format.getVertexSize(); + + this.vertices += vertexCount; + this.currentElement = format.getElements() + .get(0); + this.elementIndex = 0; + this.nextElementByte += totalWrittenBytes; + this.buffer.position(complete.startPos + totalWrittenBytes); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/util/BufferBuilderReader.java b/src/main/java/com/jozufozu/flywheel/util/BufferBuilderReader.java index 640506bb6..eecf24e1b 100644 --- a/src/main/java/com/jozufozu/flywheel/util/BufferBuilderReader.java +++ b/src/main/java/com/jozufozu/flywheel/util/BufferBuilderReader.java @@ -6,7 +6,7 @@ import com.mojang.blaze3d.vertex.BufferBuilder; import com.mojang.blaze3d.vertex.VertexFormat; import com.mojang.datafixers.util.Pair; -public class BufferBuilderReader { +public class BufferBuilderReader implements ModelReader { private final ByteBuffer buffer; private final int vertexCount; @@ -35,66 +35,81 @@ public class BufferBuilderReader { // } } + @Override public boolean isEmpty() { return vertexCount == 0; } - public int vertIdx(int vertexIndex) { + private int vertIdx(int vertexIndex) { return vertexIndex * formatSize; } + @Override public float getX(int index) { return buffer.getFloat(vertIdx(index)); } + @Override public float getY(int index) { return buffer.getFloat(vertIdx(index) + 4); } + @Override public float getZ(int index) { return buffer.getFloat(vertIdx(index) + 8); } + @Override public byte getR(int index) { return buffer.get(vertIdx(index) + 12); } + @Override public byte getG(int index) { return buffer.get(vertIdx(index) + 13); } + @Override public byte getB(int index) { return buffer.get(vertIdx(index) + 14); } + @Override public byte getA(int index) { return buffer.get(vertIdx(index) + 15); } + @Override public float getU(int index) { return buffer.getFloat(vertIdx(index) + 16); } + @Override public float getV(int index) { return buffer.getFloat(vertIdx(index) + 20); } + @Override public int getLight(int index) { return buffer.getInt(vertIdx(index) + 24); } - public byte getNX(int index) { - return buffer.get(vertIdx(index) + 28); + @Override + public float getNX(int index) { + return RenderMath.f(buffer.get(vertIdx(index) + 28)); } - public byte getNY(int index) { - return buffer.get(vertIdx(index) + 29); + @Override + public float getNY(int index) { + return RenderMath.f(buffer.get(vertIdx(index) + 29)); } - public byte getNZ(int index) { - return buffer.get(vertIdx(index) + 30); + @Override + public float getNZ(int index) { + return RenderMath.f(buffer.get(vertIdx(index) + 30)); } + @Override public int getVertexCount() { return vertexCount; } diff --git a/src/main/java/com/jozufozu/flywheel/util/ModelReader.java b/src/main/java/com/jozufozu/flywheel/util/ModelReader.java new file mode 100644 index 000000000..c1dda5f8b --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/util/ModelReader.java @@ -0,0 +1,35 @@ +package com.jozufozu.flywheel.util; + +public interface ModelReader { + float getX(int index); + + float getY(int index); + + float getZ(int index); + + byte getR(int index); + + byte getG(int index); + + byte getB(int index); + + byte getA(int index); + + float getU(int index); + + float getV(int index); + + int getLight(int index); + + float getNX(int index); + + float getNY(int index); + + float getNZ(int index); + + int getVertexCount(); + + default boolean isEmpty() { + return getVertexCount() == 0; + } +} diff --git a/src/main/resources/flywheel.mixins.json b/src/main/resources/flywheel.mixins.json index 537f77cd1..7bdf36429 100644 --- a/src/main/resources/flywheel.mixins.json +++ b/src/main/resources/flywheel.mixins.json @@ -5,6 +5,7 @@ "compatibilityLevel": "JAVA_17", "refmap": "flywheel.refmap.json", "client": [ + "BufferBuilderMixin", "CancelEntityRenderMixin", "ChunkRebuildHooksMixin", "FixFabulousDepthMixin",