From b4bb71e1cbaad61750b54652691bfd292e6e9df2 Mon Sep 17 00:00:00 2001 From: marian Date: Thu, 26 Feb 2026 00:49:33 +0100 Subject: [PATCH 1/3] add check to catch unsupported transforms on armature (or any skin ancestor) --- tools/gltf_importer/src/parser.cpp | 32 ++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/tools/gltf_importer/src/parser.cpp b/tools/gltf_importer/src/parser.cpp index d5ba41a..fc79c9d 100644 --- a/tools/gltf_importer/src/parser.cpp +++ b/tools/gltf_importer/src/parser.cpp @@ -71,6 +71,38 @@ T3DM::T3DMData T3DM::parseGLTF(const char *gltfPath) continue; } + bool ancestorHasTransforms = false; + cgltf_node* p = bone->parent; + while (p != nullptr) { + if (p->has_translation || p->has_rotation || p->has_scale || p->has_matrix) { + ancestorHasTransforms = true; + printf("Ancestor '%s' of skin armature/root bone '%s' has transforms: t:%d r:%d s:%d m:%d\n", p->name, bone->name, p->has_translation, p->has_rotation, p->has_scale, p->has_matrix); + if(config.verbose) { + if (p->has_translation) { + printf("t: %f %f %f\n", p->translation[0], p->translation[1], p->translation[2]); + } + if (p->has_rotation) { + printf("r: %f %f %f %f\n", p->rotation[0], p->rotation[1], p->rotation[2], p->rotation[3]); + } + if (p->has_scale) { + printf("s: %f %f %f\n", p->scale[0], p->scale[1], p->scale[2]); + } + if (p->has_matrix) { + printf("m: %f %f %f %f\n %f %f %f %f\n %f %f %f %f\n %f %f %f %f\n", + p->matrix[0], p->matrix[1], p->matrix[2], p->matrix[3], + p->matrix[4], p->matrix[5], p->matrix[6], p->matrix[7], + p->matrix[8], p->matrix[9], p->matrix[10], p->matrix[11], + p->matrix[12], p->matrix[13], p->matrix[14], p->matrix[15] + ); + } + } + } + p = p->parent; + } + if (ancestorHasTransforms) { + throw std::runtime_error("At least one ancestor of armature/skin root bone has transforms!"); + } + Bone armature = parseBoneTree(bone, nullptr, boneCount); //printBoneTree(armature, 0); From 590b76863811f20b0a01b680a6f8277a8a30a896 Mon Sep 17 00:00:00 2001 From: marian Date: Sun, 1 Mar 2026 09:55:08 +0100 Subject: [PATCH 2/3] compare transforms to an epsilon to avoid false positives --- tools/gltf_importer/src/parser.cpp | 49 +++++++++++++++++++----------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/tools/gltf_importer/src/parser.cpp b/tools/gltf_importer/src/parser.cpp index fc79c9d..5b361d8 100644 --- a/tools/gltf_importer/src/parser.cpp +++ b/tools/gltf_importer/src/parser.cpp @@ -71,36 +71,51 @@ T3DM::T3DMData T3DM::parseGLTF(const char *gltfPath) continue; } + constexpr auto EPSILON = 0.0001; bool ancestorHasTransforms = false; cgltf_node* p = bone->parent; while (p != nullptr) { if (p->has_translation || p->has_rotation || p->has_scale || p->has_matrix) { - ancestorHasTransforms = true; - printf("Ancestor '%s' of skin armature/root bone '%s' has transforms: t:%d r:%d s:%d m:%d\n", p->name, bone->name, p->has_translation, p->has_rotation, p->has_scale, p->has_matrix); - if(config.verbose) { - if (p->has_translation) { - printf("t: %f %f %f\n", p->translation[0], p->translation[1], p->translation[2]); + if(config.verbose) printf("Ancestor '%s' of skin armature/root bone '%s' has transforms: t:%d r:%d s:%d m:%d\n", p->name, bone->name, p->has_translation, p->has_rotation, p->has_scale, p->has_matrix); + if (p->has_translation) { + if (fabs(p->translation[0]) > EPSILON || fabs(p->translation[1]) > EPSILON || fabs(p->translation[2]) > EPSILON) { + ancestorHasTransforms = true; } - if (p->has_rotation) { - printf("r: %f %f %f %f\n", p->rotation[0], p->rotation[1], p->rotation[2], p->rotation[3]); + if(config.verbose) printf("t: %f %f %f\n", p->translation[0], p->translation[1], p->translation[2]); + } + if (p->has_rotation) { + if (fabs(p->rotation[0]) > EPSILON || fabs(p->rotation[1]) > EPSILON || fabs(p->rotation[2]) > EPSILON || fabs(p->rotation[3] - 1) > EPSILON) { + ancestorHasTransforms = true; } - if (p->has_scale) { - printf("s: %f %f %f\n", p->scale[0], p->scale[1], p->scale[2]); + if(config.verbose) printf("r: %f %f %f %f\n", p->rotation[0], p->rotation[1], p->rotation[2], p->rotation[3]); + } + if (p->has_scale) { + if (fabs(p->scale[0] - 1) > EPSILON || fabs(p->scale[1] - 1) > EPSILON || fabs(p->scale[2] - 1) > EPSILON) { + ancestorHasTransforms = true; } - if (p->has_matrix) { - printf("m: %f %f %f %f\n %f %f %f %f\n %f %f %f %f\n %f %f %f %f\n", - p->matrix[0], p->matrix[1], p->matrix[2], p->matrix[3], - p->matrix[4], p->matrix[5], p->matrix[6], p->matrix[7], - p->matrix[8], p->matrix[9], p->matrix[10], p->matrix[11], - p->matrix[12], p->matrix[13], p->matrix[14], p->matrix[15] - ); + if(config.verbose) printf("s: %f %f %f\n", p->scale[0], p->scale[1], p->scale[2]); + } + if (p->has_matrix) { + for (int y=0; y<4; y++) { + for (int x=0; x<4; x++) { + float reference = x==y ? 1 : 0; + if (fabs(p->matrix[y*4+x] - reference) > EPSILON) { + ancestorHasTransforms = true; + } + } } + if(config.verbose) printf("m: %f %f %f %f\n %f %f %f %f\n %f %f %f %f\n %f %f %f %f\n", + p->matrix[0], p->matrix[1], p->matrix[2], p->matrix[3], + p->matrix[4], p->matrix[5], p->matrix[6], p->matrix[7], + p->matrix[8], p->matrix[9], p->matrix[10], p->matrix[11], + p->matrix[12], p->matrix[13], p->matrix[14], p->matrix[15] + ); } } p = p->parent; } if (ancestorHasTransforms) { - throw std::runtime_error("At least one ancestor of armature/skin root bone has transforms!"); + throw std::runtime_error("At least one ancestor of armature/skin root bone has significant transforms! (in file: " + std::string(gltfPath) + ")"); } Bone armature = parseBoneTree(bone, nullptr, boneCount); From 8455e3e192c8712ae2a1e8b06a9012664a0054f7 Mon Sep 17 00:00:00 2001 From: marian Date: Mon, 2 Mar 2026 09:24:23 +0100 Subject: [PATCH 3/3] fix matrix order --- tools/gltf_importer/src/parser.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/gltf_importer/src/parser.cpp b/tools/gltf_importer/src/parser.cpp index 5b361d8..1226049 100644 --- a/tools/gltf_importer/src/parser.cpp +++ b/tools/gltf_importer/src/parser.cpp @@ -99,16 +99,16 @@ T3DM::T3DMData T3DM::parseGLTF(const char *gltfPath) for (int y=0; y<4; y++) { for (int x=0; x<4; x++) { float reference = x==y ? 1 : 0; - if (fabs(p->matrix[y*4+x] - reference) > EPSILON) { + if (fabs(p->matrix[y+x*4] - reference) > EPSILON) { ancestorHasTransforms = true; } } } if(config.verbose) printf("m: %f %f %f %f\n %f %f %f %f\n %f %f %f %f\n %f %f %f %f\n", - p->matrix[0], p->matrix[1], p->matrix[2], p->matrix[3], - p->matrix[4], p->matrix[5], p->matrix[6], p->matrix[7], - p->matrix[8], p->matrix[9], p->matrix[10], p->matrix[11], - p->matrix[12], p->matrix[13], p->matrix[14], p->matrix[15] + p->matrix[0], p->matrix[4], p->matrix[8], p->matrix[12], + p->matrix[1], p->matrix[5], p->matrix[9], p->matrix[13], + p->matrix[2], p->matrix[6], p->matrix[10], p->matrix[14], + p->matrix[3], p->matrix[7], p->matrix[11], p->matrix[15] ); } }