fix(gltf): select mesh by 'Item' name convention with fallback
This commit is contained in:
@@ -113,6 +113,10 @@ public final class GlbParser {
|
|||||||
String name = node.has("name")
|
String name = node.has("name")
|
||||||
? node.get("name").getAsString()
|
? node.get("name").getAsString()
|
||||||
: "joint_" + j;
|
: "joint_" + j;
|
||||||
|
// Strip armature prefix (e.g., "MyRig|body" -> "body")
|
||||||
|
if (name.contains("|")) {
|
||||||
|
name = name.substring(name.lastIndexOf('|') + 1);
|
||||||
|
}
|
||||||
if (GltfBoneMapper.isKnownBone(name)) {
|
if (GltfBoneMapper.isKnownBone(name)) {
|
||||||
skinJointRemap[j] = filteredJointNodes.size();
|
skinJointRemap[j] = filteredJointNodes.size();
|
||||||
filteredJointNodes.add(nodeIdx);
|
filteredJointNodes.add(nodeIdx);
|
||||||
@@ -145,9 +149,13 @@ public final class GlbParser {
|
|||||||
int nodeIdx = filteredJointNodes.get(j);
|
int nodeIdx = filteredJointNodes.get(j);
|
||||||
JsonObject node = nodes.get(nodeIdx).getAsJsonObject();
|
JsonObject node = nodes.get(nodeIdx).getAsJsonObject();
|
||||||
|
|
||||||
jointNames[j] = node.has("name")
|
String rawName = node.has("name")
|
||||||
? node.get("name").getAsString()
|
? node.get("name").getAsString()
|
||||||
: "joint_" + j;
|
: "joint_" + j;
|
||||||
|
// Strip armature prefix consistently
|
||||||
|
jointNames[j] = rawName.contains("|")
|
||||||
|
? rawName.substring(rawName.lastIndexOf('|') + 1)
|
||||||
|
: rawName;
|
||||||
|
|
||||||
// Rest rotation
|
// Rest rotation
|
||||||
if (node.has("rotation")) {
|
if (node.has("rotation")) {
|
||||||
@@ -215,20 +223,36 @@ public final class GlbParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// -- Find mesh (ignore "Player" mesh, take LAST non-Player) --
|
// -- Find mesh by convention, then fallback --
|
||||||
// WORKAROUND: Takes the LAST non-Player mesh because modelers may leave prototype meshes
|
// Priority: 1) mesh named "Item", 2) last non-Player mesh
|
||||||
// in the .glb. Revert to first non-Player mesh once modeler workflow is standardized.
|
|
||||||
int targetMeshIdx = -1;
|
int targetMeshIdx = -1;
|
||||||
|
String selectedMeshName = null;
|
||||||
|
int nonPlayerCount = 0;
|
||||||
if (meshes != null) {
|
if (meshes != null) {
|
||||||
for (int mi = 0; mi < meshes.size(); mi++) {
|
for (int mi = 0; mi < meshes.size(); mi++) {
|
||||||
JsonObject mesh = meshes.get(mi).getAsJsonObject();
|
JsonObject mesh = meshes.get(mi).getAsJsonObject();
|
||||||
String meshName = mesh.has("name")
|
String meshName = mesh.has("name")
|
||||||
? mesh.get("name").getAsString()
|
? mesh.get("name").getAsString()
|
||||||
: "";
|
: "";
|
||||||
|
if ("Item".equals(meshName)) {
|
||||||
|
targetMeshIdx = mi;
|
||||||
|
selectedMeshName = meshName;
|
||||||
|
break; // Convention match — use it
|
||||||
|
}
|
||||||
if (!"Player".equals(meshName)) {
|
if (!"Player".equals(meshName)) {
|
||||||
targetMeshIdx = mi;
|
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) --
|
// -- Parse root material names (for tint channel detection) --
|
||||||
|
|||||||
Reference in New Issue
Block a user