feat(gltf): accept custom bones — remove 11-bone filter, simplify joint remap
This commit is contained in:
@@ -103,10 +103,8 @@ public final class GlbParser {
|
|||||||
JsonObject skin = skins.get(0).getAsJsonObject();
|
JsonObject skin = skins.get(0).getAsJsonObject();
|
||||||
JsonArray skinJoints = skin.getAsJsonArray("joints");
|
JsonArray skinJoints = skin.getAsJsonArray("joints");
|
||||||
|
|
||||||
// Filter skin joints to only include known deforming bones
|
// Accept all skin joints (no filtering — custom bones are supported)
|
||||||
List<Integer> filteredJointNodes = new ArrayList<>();
|
List<Integer> allJointNodes = new ArrayList<>();
|
||||||
int[] skinJointRemap = new int[skinJoints.size()]; // old skin index -> new filtered index
|
|
||||||
java.util.Arrays.fill(skinJointRemap, -1);
|
|
||||||
for (int j = 0; j < skinJoints.size(); j++) {
|
for (int j = 0; j < skinJoints.size(); j++) {
|
||||||
int nodeIdx = skinJoints.get(j).getAsInt();
|
int nodeIdx = skinJoints.get(j).getAsInt();
|
||||||
JsonObject node = nodes.get(nodeIdx).getAsJsonObject();
|
JsonObject node = nodes.get(nodeIdx).getAsJsonObject();
|
||||||
@@ -117,19 +115,25 @@ public final class GlbParser {
|
|||||||
if (name.contains("|")) {
|
if (name.contains("|")) {
|
||||||
name = name.substring(name.lastIndexOf('|') + 1);
|
name = name.substring(name.lastIndexOf('|') + 1);
|
||||||
}
|
}
|
||||||
if (GltfBoneMapper.isKnownBone(name)) {
|
// Log info for non-MC bones
|
||||||
skinJointRemap[j] = filteredJointNodes.size();
|
if (!GltfBoneMapper.isKnownBone(name)) {
|
||||||
filteredJointNodes.add(nodeIdx);
|
String suggestion = GltfBoneMapper.suggestBoneName(name);
|
||||||
} else {
|
if (suggestion != null) {
|
||||||
LOGGER.debug(
|
LOGGER.warn(
|
||||||
"[GltfPipeline] Skipping non-deforming bone: '{}' (node {})",
|
"[GltfPipeline] Unknown bone '{}' in {} — did you mean '{}'? (treated as custom bone)",
|
||||||
name,
|
name, debugName, suggestion
|
||||||
nodeIdx
|
);
|
||||||
);
|
} else {
|
||||||
|
LOGGER.info(
|
||||||
|
"[GltfPipeline] Custom bone '{}' in {} (will follow parent hierarchy in rest pose)",
|
||||||
|
name, debugName
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
allJointNodes.add(nodeIdx);
|
||||||
}
|
}
|
||||||
|
|
||||||
int jointCount = filteredJointNodes.size();
|
int jointCount = allJointNodes.size();
|
||||||
String[] jointNames = new String[jointCount];
|
String[] jointNames = new String[jointCount];
|
||||||
int[] parentJointIndices = new int[jointCount];
|
int[] parentJointIndices = new int[jointCount];
|
||||||
Quaternionf[] restRotations = new Quaternionf[jointCount];
|
Quaternionf[] restRotations = new Quaternionf[jointCount];
|
||||||
@@ -139,14 +143,14 @@ public final class GlbParser {
|
|||||||
int[] nodeToJoint = new int[nodes.size()];
|
int[] nodeToJoint = new int[nodes.size()];
|
||||||
java.util.Arrays.fill(nodeToJoint, -1);
|
java.util.Arrays.fill(nodeToJoint, -1);
|
||||||
for (int j = 0; j < jointCount; j++) {
|
for (int j = 0; j < jointCount; j++) {
|
||||||
int nodeIdx = filteredJointNodes.get(j);
|
int nodeIdx = allJointNodes.get(j);
|
||||||
nodeToJoint[nodeIdx] = j;
|
nodeToJoint[nodeIdx] = j;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read joint names, rest pose, and build parent mapping
|
// Read joint names, rest pose, and build parent mapping
|
||||||
java.util.Arrays.fill(parentJointIndices, -1);
|
java.util.Arrays.fill(parentJointIndices, -1);
|
||||||
for (int j = 0; j < jointCount; j++) {
|
for (int j = 0; j < jointCount; j++) {
|
||||||
int nodeIdx = filteredJointNodes.get(j);
|
int nodeIdx = allJointNodes.get(j);
|
||||||
JsonObject node = nodes.get(nodeIdx).getAsJsonObject();
|
JsonObject node = nodes.get(nodeIdx).getAsJsonObject();
|
||||||
|
|
||||||
String rawName = node.has("name")
|
String rawName = node.has("name")
|
||||||
@@ -200,7 +204,6 @@ public final class GlbParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// -- Inverse Bind Matrices --
|
// -- Inverse Bind Matrices --
|
||||||
// IBM accessor is indexed by original skin joint order, so we pick the filtered entries
|
|
||||||
Matrix4f[] inverseBindMatrices = new Matrix4f[jointCount];
|
Matrix4f[] inverseBindMatrices = new Matrix4f[jointCount];
|
||||||
if (skin.has("inverseBindMatrices")) {
|
if (skin.has("inverseBindMatrices")) {
|
||||||
int ibmAccessor = skin.get("inverseBindMatrices").getAsInt();
|
int ibmAccessor = skin.get("inverseBindMatrices").getAsInt();
|
||||||
@@ -210,12 +213,9 @@ public final class GlbParser {
|
|||||||
binData,
|
binData,
|
||||||
ibmAccessor
|
ibmAccessor
|
||||||
);
|
);
|
||||||
for (int origJ = 0; origJ < skinJoints.size(); origJ++) {
|
for (int j = 0; j < jointCount; j++) {
|
||||||
int newJ = skinJointRemap[origJ];
|
inverseBindMatrices[j] = new Matrix4f();
|
||||||
if (newJ >= 0) {
|
inverseBindMatrices[j].set(ibmData, j * 16);
|
||||||
inverseBindMatrices[newJ] = new Matrix4f();
|
|
||||||
inverseBindMatrices[newJ].set(ibmData, origJ * 16);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (int j = 0; j < jointCount; j++) {
|
for (int j = 0; j < jointCount; j++) {
|
||||||
@@ -344,15 +344,10 @@ public final class GlbParser {
|
|||||||
binData,
|
binData,
|
||||||
attributes.get("JOINTS_0").getAsInt()
|
attributes.get("JOINTS_0").getAsInt()
|
||||||
);
|
);
|
||||||
// Remap vertex joint indices from original skin order to filtered order
|
// No remap needed — all joints are kept, indices match directly.
|
||||||
|
// Guard against out-of-range joint indices.
|
||||||
for (int i = 0; i < primJoints.length; i++) {
|
for (int i = 0; i < primJoints.length; i++) {
|
||||||
int origIdx = primJoints[i];
|
if (primJoints[i] < 0 || primJoints[i] >= jointCount) {
|
||||||
if (origIdx >= 0 && origIdx < skinJointRemap.length) {
|
|
||||||
primJoints[i] =
|
|
||||||
skinJointRemap[origIdx] >= 0
|
|
||||||
? skinJointRemap[origIdx]
|
|
||||||
: 0;
|
|
||||||
} else {
|
|
||||||
primJoints[i] = 0;
|
primJoints[i] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user