From d59817336c9144cff83c6a93f1613602945a6ac1 Mon Sep 17 00:00:00 2001 From: hackermdch <58121864+hackermdch@users.noreply.github.com> Date: Sat, 25 May 2024 17:55:28 +0800 Subject: [PATCH] Update render with indices --- build.gradle | 3 +- gradle.properties | 4 +- .../interfaces/BufferBuilderExt.kt | 9 ++++ .../advancedfmk/mixin/BufferBuilderMixin.java | 43 ++++++++++++++++ .../advancedfmk/mixin/VertexBufferMixin.java | 50 +++++++++++++++++++ .../advancedfmk/mmd/PMXModel.java | 28 +++++++++-- .../advancedfmk/mmd/SabaNative.java | 11 ++-- .../mmd/renderer/EntityRenderWrapper.kt | 3 ++ .../advancedfmk/mmd/renderer/Renderer.kt | 6 +-- .../advancedfmk.mmdrenderer.mixins.json | 4 +- mmdrenderer/src/main/resources/natives | 2 +- 11 files changed, 146 insertions(+), 17 deletions(-) create mode 100644 mmdrenderer/src/main/java/com/primogemstudio/advancedfmk/mixin/VertexBufferMixin.java diff --git a/build.gradle b/build.gradle index bd4a185a..dde73369 100644 --- a/build.gradle +++ b/build.gradle @@ -84,7 +84,8 @@ dependencies { implementation "org.apiguardian:apiguardian-api:${project.apiguardian_api_version}" modRuntimeOnly "com.terraformersmc:modmenu:${project.modmenu_version}" - // modRuntimeOnly "maven.modrinth:iris:${project.iris_version}" + modRuntimeOnly "maven.modrinth:fpsdisplay:${project.fpsdisplay_version}" +// modRuntimeOnly "maven.modrinth:iris:${project.iris_version}" runtimeOnly "org.anarres:jcpp:${project.jcpp_version}" runtimeOnly "io.github.douira:glsl-transformer:${project.glsl_transformer_version}" runtimeOnly "org.antlr:antlr4-runtime:${project.antlr4_runtime_version}" diff --git a/gradle.properties b/gradle.properties index 8ec1958e..dee8fb60 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,7 +2,7 @@ org.gradle.jvmargs=-Xmx4G fabric.loom.multiProjectOptimisation=true minecraft_version=1.20.6 loader_version=0.15.10 -mod_version=0.5.1 +mod_version=0.5.2 maven_group=io.github.primogemstudio archives_base_name=advancedfmk fabric_version=0.97.8+1.20.6 @@ -13,7 +13,7 @@ kotlin_version=1.9.20 satin_version=1.17.0 sodium_version=mc1.20.6-0.5.8 modmenu_version=10.0.0-beta.1 -fpsdisplay_version=4.0.0+1.20.4 +fpsdisplay_version=4.1.0+1.20.5 joml_version=1.10.5 luaj_version=3.0.1 bcel_version=6.8.2 diff --git a/mmdrenderer/src/main/java/com/primogemstudio/advancedfmk/interfaces/BufferBuilderExt.kt b/mmdrenderer/src/main/java/com/primogemstudio/advancedfmk/interfaces/BufferBuilderExt.kt index 983b3d9b..c134ea7c 100644 --- a/mmdrenderer/src/main/java/com/primogemstudio/advancedfmk/interfaces/BufferBuilderExt.kt +++ b/mmdrenderer/src/main/java/com/primogemstudio/advancedfmk/interfaces/BufferBuilderExt.kt @@ -1,5 +1,7 @@ package com.primogemstudio.advancedfmk.interfaces +import com.primogemstudio.advancedfmk.mmd.PMXModel + interface BufferBuilderExt { fun fullFormat(): Boolean fun bumpNxt(d: Int) @@ -7,4 +9,11 @@ interface BufferBuilderExt { fun resize() fun padding(): Int fun setPtr(ptr: Int) + fun getPMXModel(): PMXModel? + fun setPMXModel(model: PMXModel?) +} + +interface RenderedBufferExt { + fun getPMXModel(): PMXModel? + fun setPMXModel(model: PMXModel?) } \ No newline at end of file diff --git a/mmdrenderer/src/main/java/com/primogemstudio/advancedfmk/mixin/BufferBuilderMixin.java b/mmdrenderer/src/main/java/com/primogemstudio/advancedfmk/mixin/BufferBuilderMixin.java index 8406e0a6..91aa31e6 100644 --- a/mmdrenderer/src/main/java/com/primogemstudio/advancedfmk/mixin/BufferBuilderMixin.java +++ b/mmdrenderer/src/main/java/com/primogemstudio/advancedfmk/mixin/BufferBuilderMixin.java @@ -1,13 +1,19 @@ package com.primogemstudio.advancedfmk.mixin; +import com.llamalad7.mixinextras.injector.ModifyReturnValue; import com.mojang.blaze3d.platform.MemoryTracker; import com.mojang.blaze3d.vertex.BufferBuilder; import com.mojang.blaze3d.vertex.BufferVertexConsumer; import com.mojang.blaze3d.vertex.DefaultedVertexConsumer; import com.mojang.blaze3d.vertex.VertexFormat; import com.primogemstudio.advancedfmk.interfaces.BufferBuilderExt; +import com.primogemstudio.advancedfmk.interfaces.RenderedBufferExt; +import com.primogemstudio.advancedfmk.mmd.PMXModel; +import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; import java.nio.ByteBuffer; @@ -28,6 +34,9 @@ public abstract class BufferBuilderMixin extends DefaultedVertexConsumer impleme @Shadow public ByteBuffer buffer; + @Unique + private PMXModel model; + @Override public boolean fullFormat() { return fullFormat; @@ -61,4 +70,38 @@ public void resize() { buffer.rewind(); } } + + @Nullable + @Override + public PMXModel getPMXModel() { + return model; + } + + @Override + public void setPMXModel(@Nullable PMXModel model) { + this.model = model; + } + + @ModifyReturnValue(method = "storeRenderedBuffer", at = @At("RETURN")) + private BufferBuilder.RenderedBuffer storeRenderedBuffer(BufferBuilder.RenderedBuffer original) { + ((RenderedBufferExt) original).setPMXModel(model); + model = null; + return original; + } + + @Mixin(BufferBuilder.RenderedBuffer.class) + public static class RenderedBufferMixin implements RenderedBufferExt { + @Unique + private PMXModel model; + + @Override + public PMXModel getPMXModel() { + return model; + } + + @Override + public void setPMXModel(@Nullable PMXModel model) { + this.model = model; + } + } } diff --git a/mmdrenderer/src/main/java/com/primogemstudio/advancedfmk/mixin/VertexBufferMixin.java b/mmdrenderer/src/main/java/com/primogemstudio/advancedfmk/mixin/VertexBufferMixin.java new file mode 100644 index 00000000..2b31731b --- /dev/null +++ b/mmdrenderer/src/main/java/com/primogemstudio/advancedfmk/mixin/VertexBufferMixin.java @@ -0,0 +1,50 @@ +package com.primogemstudio.advancedfmk.mixin; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.BufferBuilder; +import com.mojang.blaze3d.vertex.VertexBuffer; +import com.mojang.blaze3d.vertex.VertexFormat; +import com.primogemstudio.advancedfmk.interfaces.RenderedBufferExt; +import com.primogemstudio.advancedfmk.mmd.PMXModel; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +import java.nio.ByteBuffer; + +@Mixin(VertexBuffer.class) +public abstract class VertexBufferMixin { + @Shadow + @Nullable + protected abstract RenderSystem.AutoStorageIndexBuffer uploadIndexBuffer(BufferBuilder.DrawState drawState, @Nullable ByteBuffer buffer); + + @Unique + private PMXModel getModel(BufferBuilder.RenderedBuffer buffer) { + return ((RenderedBufferExt) buffer).getPMXModel(); + } + + @Redirect(method = "upload", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/vertex/BufferBuilder$DrawState;indexCount()I")) + private int indexCount(BufferBuilder.DrawState instance, BufferBuilder.RenderedBuffer buffer) { + var model = getModel(buffer); + return model != null ? model.indexCount : instance.indexCount(); + } + + @Redirect(method = "upload", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/vertex/BufferBuilder$DrawState;indexType()Lcom/mojang/blaze3d/vertex/VertexFormat$IndexType;")) + private VertexFormat.IndexType indexType(BufferBuilder.DrawState instance, BufferBuilder.RenderedBuffer buffer) { + var model = getModel(buffer); + return model != null ? VertexFormat.IndexType.INT : instance.indexType(); + } + + @Redirect(method = "upload", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/vertex/VertexBuffer;uploadIndexBuffer(Lcom/mojang/blaze3d/vertex/BufferBuilder$DrawState;Ljava/nio/ByteBuffer;)Lcom/mojang/blaze3d/systems/RenderSystem$AutoStorageIndexBuffer;")) + private RenderSystem.AutoStorageIndexBuffer uploadIndexBuffer(VertexBuffer instance, BufferBuilder.DrawState drawState, ByteBuffer buffer, BufferBuilder.RenderedBuffer buff) { + var model = getModel(buff); + if (model != null) { + model.bindIndices(); + return null; + } + return uploadIndexBuffer(drawState, buffer); + } +} diff --git a/mmdrenderer/src/main/java/com/primogemstudio/advancedfmk/mmd/PMXModel.java b/mmdrenderer/src/main/java/com/primogemstudio/advancedfmk/mmd/PMXModel.java index c615af84..2fcee030 100644 --- a/mmdrenderer/src/main/java/com/primogemstudio/advancedfmk/mmd/PMXModel.java +++ b/mmdrenderer/src/main/java/com/primogemstudio/advancedfmk/mmd/PMXModel.java @@ -1,8 +1,11 @@ package com.primogemstudio.advancedfmk.mmd; +import com.mojang.blaze3d.platform.GlStateManager; +import com.mojang.blaze3d.systems.RenderSystem; import com.primogemstudio.advancedfmk.interfaces.AccessFromNative; import com.primogemstudio.advancedfmk.mmd.renderer.MMDTextureAtlas; import com.primogemstudio.advancedfmk.mmd.renderer.TextureManager; +import org.lwjgl.opengl.GL32; import java.io.File; import java.lang.ref.Cleaner; @@ -10,33 +13,42 @@ import java.util.ArrayList; import java.util.List; +import static org.lwjgl.opengl.GL15.GL_ELEMENT_ARRAY_BUFFER; + public class PMXModel implements AutoCloseable { @AccessFromNative private long ptr; @AccessFromNative - private Cleaner.Cleanable cleaner; + private final Cleaner.Cleanable cleaner; private static int ID = 0; private final int id = ++ID; private final String texture = "mmd_texture" + id; @AccessFromNative private final MMDTextureAtlas atlas; public final TextureManager textureManager; - public final int vertexCount; + public final int vertexCount, indexCount; public final Animation animation; + private final int ibo; public PMXModel(File file) { load(file); vertexCount = getVertexCount(); + indexCount = getIndexCount(); atlas = Loader.createAtlas(getTextures()); textureManager = new TextureManager(atlas); animation = new Animation(this); textureManager.register(texture); mappingVertices(); + ibo = GlStateManager._glGenBuffers(); + GlStateManager._glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); + RenderSystem.glBufferData(GL_ELEMENT_ARRAY_BUFFER, getIndices(), GL32.GL_STATIC_DRAW); var p = ptr; var tm = textureManager; + var t_ibo = ibo; cleaner = SabaNative.cleaner.register(this, () -> { - SabaNative.release(PMXModel.class, p); + release(p); tm.release(); + RenderSystem.glDeleteBuffers(t_ibo); }); } @@ -44,12 +56,22 @@ public PMXModel(File file) { public native void render(ByteBuffer buff, ByteBuffer constants); + private native ByteBuffer getIndices(); + private native int getVertexCount(); + private native int getIndexCount(); + private native List getTextures(); private native void mappingVertices(); + private static native void release(long ptr); + + public void bindIndices() { + GlStateManager._glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); + } + private float lastTime = System.nanoTime() / 1000000000f; @AccessFromNative private float animationTime = 0; diff --git a/mmdrenderer/src/main/java/com/primogemstudio/advancedfmk/mmd/SabaNative.java b/mmdrenderer/src/main/java/com/primogemstudio/advancedfmk/mmd/SabaNative.java index 7667699c..9e3b81ce 100644 --- a/mmdrenderer/src/main/java/com/primogemstudio/advancedfmk/mmd/SabaNative.java +++ b/mmdrenderer/src/main/java/com/primogemstudio/advancedfmk/mmd/SabaNative.java @@ -10,8 +10,13 @@ public final class SabaNative { var path = ""; var os = System.getProperty("os.name"); var name = ""; - if (arch.equals("aarch64")) path = "/natives/arm/"; - else if (arch.equals("amd64")) path = "/natives/"; + if (arch.equals("aarch64")) { + if (os.contains("Windows")) throw new RuntimeException("Unsupported Windows on ARM"); + path = "/natives/arm/"; + } else if (arch.equals("amd64")) { + if (os.contains("Mac OS")) throw new RuntimeException("Unsupported Mac OS on x86"); + path = "/natives/"; + } if (path.isEmpty()) throw new RuntimeException("Unsupported CPU architecture: " + arch); if (os.contains("Windows")) path += name = "saba-native.dll"; else if (os.contains("Linux")) path += name = "libsaba-native.so"; @@ -30,8 +35,6 @@ public final class SabaNative { static final Cleaner cleaner = Cleaner.create(); - static native void release(Class cls, long ptr); - public static void init() { } } diff --git a/mmdrenderer/src/main/java/com/primogemstudio/advancedfmk/mmd/renderer/EntityRenderWrapper.kt b/mmdrenderer/src/main/java/com/primogemstudio/advancedfmk/mmd/renderer/EntityRenderWrapper.kt index a9c02418..ca7ce523 100644 --- a/mmdrenderer/src/main/java/com/primogemstudio/advancedfmk/mmd/renderer/EntityRenderWrapper.kt +++ b/mmdrenderer/src/main/java/com/primogemstudio/advancedfmk/mmd/renderer/EntityRenderWrapper.kt @@ -11,6 +11,7 @@ import net.minecraft.client.renderer.MultiBufferSource import net.minecraft.client.renderer.RenderType import net.minecraft.client.renderer.texture.OverlayTexture import org.joml.Vector2i +import org.lwjgl.opengl.GL32 import java.nio.ByteBuffer import java.nio.ByteOrder @@ -25,6 +26,7 @@ class EntityRenderWrapper(val model: PMXModel) { fun render( entityYaw: Float, poseStack: PoseStack, buffer: MultiBufferSource, packedLight: Int ) { + GL32.GL_INT val vc = buffer.getBuffer(renderType) val buf = try { if (vc is SodiumBufferBuilder) vc.originalBufferBuilder @@ -33,6 +35,7 @@ class EntityRenderWrapper(val model: PMXModel) { vc as BufferBuilder } buf as BufferBuilderExt + buf.setPMXModel(model) poseStack.pushPose() poseStack.scale(0.1f, 0.1f, 0.1f) poseStack.mulPose(Axis.YN.rotationDegrees(entityYaw)) diff --git a/mmdrenderer/src/main/java/com/primogemstudio/advancedfmk/mmd/renderer/Renderer.kt b/mmdrenderer/src/main/java/com/primogemstudio/advancedfmk/mmd/renderer/Renderer.kt index 59001f85..1bfd3537 100644 --- a/mmdrenderer/src/main/java/com/primogemstudio/advancedfmk/mmd/renderer/Renderer.kt +++ b/mmdrenderer/src/main/java/com/primogemstudio/advancedfmk/mmd/renderer/Renderer.kt @@ -16,7 +16,6 @@ import net.minecraft.resources.ResourceLocation import net.minecraft.server.packs.resources.ResourceManager import net.minecraft.util.Mth import java.nio.ByteBuffer -import java.nio.ByteOrder import kotlin.math.ceil import kotlin.math.sqrt @@ -145,10 +144,7 @@ class MMDTextureAtlas(tes: List) : AbstractTexture() { } @AccessFromNative - private val buff = ByteBuffer.allocateDirect(8).order(ByteOrder.nativeOrder()) - - @AccessFromNative - fun mapping(ti: Int) { + fun mapping(ti: Int, buff: ByteBuffer) { val r = map[ti]!! val x = buff.getFloat(0).toDouble() val y = buff.getFloat(4).toDouble() diff --git a/mmdrenderer/src/main/resources/advancedfmk.mmdrenderer.mixins.json b/mmdrenderer/src/main/resources/advancedfmk.mmdrenderer.mixins.json index dd0c15f6..7a4f0675 100644 --- a/mmdrenderer/src/main/resources/advancedfmk.mmdrenderer.mixins.json +++ b/mmdrenderer/src/main/resources/advancedfmk.mmdrenderer.mixins.json @@ -5,7 +5,9 @@ "compatibilityLevel": "JAVA_21", "client": [ "BufferBuilderMixin", - "NativeImageMixin" + "BufferBuilderMixin$RenderedBufferMixin", + "NativeImageMixin", + "VertexBufferMixin" ], "injectors": { "defaultRequire": 1 diff --git a/mmdrenderer/src/main/resources/natives b/mmdrenderer/src/main/resources/natives index adda16f2..12d25129 160000 --- a/mmdrenderer/src/main/resources/natives +++ b/mmdrenderer/src/main/resources/natives @@ -1 +1 @@ -Subproject commit adda16f2c715d72ca68ba46c3c739bf67ad88456 +Subproject commit 12d25129d9b32b94808b9b4cec1f107775ed627a