From 6dad447c05d2b097c512a904159255eee317a25f Mon Sep 17 00:00:00 2001 From: NotEvil Date: Fri, 17 Apr 2026 01:35:54 +0200 Subject: [PATCH] fix(gltf): select mesh by 'Item' name convention with fallback --- .../tiedup/remake/client/gltf/GlbParser.java | 32 ++++++++++++++++--- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/tiedup/remake/client/gltf/GlbParser.java b/src/main/java/com/tiedup/remake/client/gltf/GlbParser.java index a4df960..28228cf 100644 --- a/src/main/java/com/tiedup/remake/client/gltf/GlbParser.java +++ b/src/main/java/com/tiedup/remake/client/gltf/GlbParser.java @@ -113,6 +113,10 @@ public final class GlbParser { String name = node.has("name") ? node.get("name").getAsString() : "joint_" + j; + // Strip armature prefix (e.g., "MyRig|body" -> "body") + if (name.contains("|")) { + name = name.substring(name.lastIndexOf('|') + 1); + } if (GltfBoneMapper.isKnownBone(name)) { skinJointRemap[j] = filteredJointNodes.size(); filteredJointNodes.add(nodeIdx); @@ -145,9 +149,13 @@ public final class GlbParser { int nodeIdx = filteredJointNodes.get(j); JsonObject node = nodes.get(nodeIdx).getAsJsonObject(); - jointNames[j] = node.has("name") + String rawName = node.has("name") ? node.get("name").getAsString() : "joint_" + j; + // Strip armature prefix consistently + jointNames[j] = rawName.contains("|") + ? rawName.substring(rawName.lastIndexOf('|') + 1) + : rawName; // Rest rotation if (node.has("rotation")) { @@ -215,20 +223,36 @@ public final class GlbParser { } } - // -- Find mesh (ignore "Player" mesh, take LAST non-Player) -- - // WORKAROUND: Takes the LAST non-Player mesh because modelers may leave prototype meshes - // in the .glb. Revert to first non-Player mesh once modeler workflow is standardized. + // -- Find mesh by convention, then fallback -- + // Priority: 1) mesh named "Item", 2) last non-Player mesh int targetMeshIdx = -1; + String selectedMeshName = null; + int nonPlayerCount = 0; if (meshes != null) { for (int mi = 0; mi < meshes.size(); mi++) { JsonObject mesh = meshes.get(mi).getAsJsonObject(); String meshName = mesh.has("name") ? mesh.get("name").getAsString() : ""; + if ("Item".equals(meshName)) { + targetMeshIdx = mi; + selectedMeshName = meshName; + break; // Convention match — use it + } if (!"Player".equals(meshName)) { targetMeshIdx = mi; + selectedMeshName = meshName; + nonPlayerCount++; } } + if (nonPlayerCount > 1 && !"Item".equals(selectedMeshName)) { + LOGGER.warn( + "[GltfPipeline] {} non-Player meshes found in {} — using '{}'. " + + "Name your mesh 'Item' for explicit selection.", + nonPlayerCount, debugName, + selectedMeshName != null ? selectedMeshName : "(unnamed)" + ); + } } // -- Parse root material names (for tint channel detection) --