diff --git a/src/main/java/org/saturnclient/cosmetics/hat/HatFeatureRenderer.java b/src/main/java/org/saturnclient/cosmetics/hat/HatFeatureRenderer.java index 3656803..3d03d98 100644 --- a/src/main/java/org/saturnclient/cosmetics/hat/HatFeatureRenderer.java +++ b/src/main/java/org/saturnclient/cosmetics/hat/HatFeatureRenderer.java @@ -1,9 +1,11 @@ package org.saturnclient.cosmetics.hat; import java.io.IOException; +import java.util.Map; import org.saturnclient.cosmetics.obj.ObjRenderer; +import de.javagl.obj.Mtl; import de.javagl.obj.Obj; import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.entity.feature.FeatureRenderer; @@ -15,12 +17,15 @@ import net.minecraft.util.Identifier; public class HatFeatureRenderer extends FeatureRenderer { static Identifier HAT = Identifier.of("saturnclient", "models/item/horns/horns.obj"); + static Identifier BLACK_MTL = Identifier.of("saturnclient", "models/item/black.mtl"); Obj obj; + Map mtl; public HatFeatureRenderer(FeatureRendererContext context) { super(context); try { this.obj = ObjRenderer.loadObj(HAT); + this.mtl = ObjRenderer.loadMtl(BLACK_MTL); } catch (IOException e) { e.printStackTrace(); } @@ -29,6 +34,6 @@ public class HatFeatureRenderer extends FeatureRenderer loadMtl(Identifier mtlId) throws IOException { + try (InputStream is = MinecraftClient.getInstance().getResourceManager() + .getResource(mtlId).get().getInputStream()) { + List mtlList = MtlReader.read(is); + Map mtlMap = new java.util.LinkedHashMap<>(); + for (Mtl mtl : mtlList) { + mtlMap.put(mtl.getName(), mtl); + } + return mtlMap; + } + } + + public static void renderObj(Obj obj, Map mtlMap, MatrixStack matrices, + VertexConsumerProvider vertexConsumers, int light, int overlay) { MatrixStack.Entry entry = matrices.peek(); - int faces = obj.getNumFaces(); + Map materialGroups = ObjSplitting.splitByMaterialGroups(obj); - System.out.println("Faces " + faces + ", vertices " + obj.getNumVertices()); + for (Map.Entry group : materialGroups.entrySet()) { + String materialName = group.getKey(); + Obj groupObj = group.getValue(); - for (int f = 0; f < faces; f++) { - ObjFace face = obj.getFace(f); - int vertices = face.getNumVertices(); + Mtl mtl = mtlMap != null ? mtlMap.get(materialName) : null; - // Reverse winding order: OBJ is CCW, Minecraft expects CW - for (int i = vertices - 1; i >= 0; i--) { - writeVertex(obj, face, i, consumer, entry, light, overlay); + // Resolve texture identifier using same logic as ObjUnbakedModelModel + Identifier texture = Identifier.of("minecraft:textures/misc/white.png"); + + if (mtl != null) { + String mapKd = mtl.getMapKd(); + if (mapKd != null) { + // "#key" references are not resolvable at runtime without a texture map, + // so we only support direct resource location strings here + if (!mapKd.startsWith("#")) { + texture = Identifier.of(mapKd); + } + } + } + + // Diffuse color (Kd) + float r = 1f, g = 1f, b = 1f; + if (mtl != null) { + FloatTuple kd = mtl.getKd(); + if (kd != null) { + r = kd.getX(); + g = kd.getY(); + b = kd.getZ(); + } + } + + VertexConsumer consumer = vertexConsumers.getBuffer(RenderLayer.getEntityAlpha(texture)); + + int faces = groupObj.getNumFaces(); + final float fr = r, fg = g, fb = b; + + for (int f = 0; f < faces; f++) { + ObjFace face = groupObj.getFace(f); + int verts = face.getNumVertices(); + + // Your original winding order logic, untouched + for (int i = verts - 1; i >= 0; i--) { + writeVertex(groupObj, face, i, consumer, entry, light, overlay, fr, fg, fb); + } } } } - /** Write a single vertex to the VertexConsumer using the OBJ FloatTuple */ - private static void writeVertex(Obj obj, ObjFace face, int index, VertexConsumer consumer, MatrixStack.Entry matrix, - int light, int overlay) { + private static void writeVertex(Obj obj, ObjFace face, int index, VertexConsumer consumer, + MatrixStack.Entry matrix, int light, int overlay, + float r, float g, float b) { + FloatTuple pos = obj.getVertex(face.getVertexIndex(index)); float x = pos.getX(); float y = pos.getY(); float z = pos.getZ(); - // Default normal - float nx = 0f; - float ny = 1f; - float nz = 0f; - - // Use OBJ normal if available + float nx = 0f, ny = 1f, nz = 0f; int normalIndex = face.getNormalIndex(index); if (normalIndex >= 0) { FloatTuple n = obj.getNormal(normalIndex); @@ -67,9 +108,17 @@ public class ObjRenderer { nz = n.getZ(); } + float u = 0f, v = 0f; + int texIndex = face.getTexCoordIndex(index); + if (texIndex >= 0) { + FloatTuple tc = obj.getTexCoord(texIndex); + u = tc.getX(); + v = 1f - tc.getY(); // Flip V: OBJ bottom-left origin -> Minecraft top-left + } + consumer.vertex(matrix, x, y, z) - .color(255, 255, 255, 255) - .texture(0f, 0f) + .color(r, g, b, 1f) + .texture(u, v) .overlay(overlay) .light(light) .normal(matrix, nx, ny, nz); diff --git a/src/main/resources/assets/saturnclient/models/item/black.mtl b/src/main/resources/assets/saturnclient/models/item/black.mtl index 6670390..3661766 100644 --- a/src/main/resources/assets/saturnclient/models/item/black.mtl +++ b/src/main/resources/assets/saturnclient/models/item/black.mtl @@ -10,4 +10,4 @@ Ke 0.000000 0.000000 0.000000 Ni 1.450000 d 1.000000 illum 2 -map_Kd saturnclient:item/halo_black +map_Kd saturnclient:textures/item/halo_black.png diff --git a/src/main/resources/assets/saturnclient/models/item/white.mtl b/src/main/resources/assets/saturnclient/models/item/white.mtl index f273f55..9c0dc53 100644 --- a/src/main/resources/assets/saturnclient/models/item/white.mtl +++ b/src/main/resources/assets/saturnclient/models/item/white.mtl @@ -10,4 +10,4 @@ Ke 0.000000 0.000000 0.000000 Ni 1.450000 d 1.000000 illum 2 -map_Kd saturnclient:item/halo +map_Kd saturnclient:textures/item/halo.png