From a8a3d5c8356b96064caa833993e0e1c36bdc8b1f Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Fri, 5 Jan 2018 09:53:07 -0300 Subject: [PATCH] Fixes to GLTF2 importer skeleton positioning, though vertex bone indices still look broken somehow.. --- editor/import/editor_scene_importer_gltf.cpp | 56 +++++++++++++++----- editor/import/editor_scene_importer_gltf.h | 5 +- 2 files changed, 46 insertions(+), 15 deletions(-) diff --git a/editor/import/editor_scene_importer_gltf.cpp b/editor/import/editor_scene_importer_gltf.cpp index cc8ab0a3e0c..1c4617c353d 100644 --- a/editor/import/editor_scene_importer_gltf.cpp +++ b/editor/import/editor_scene_importer_gltf.cpp @@ -910,18 +910,24 @@ Error EditorSceneImporterGLTF::_parse_meshes(GLTFState &state) { { //gltf does not seem to normalize the weights for some reason.. int wc = weights.size(); PoolVector::Write w = weights.write(); - for (int i = 0; i < wc; i += 4) { + + //PoolVector v = array[Mesh::ARRAY_BONES]; + //PoolVector::Read r = v.read(); + + for (int j = 0; j < wc; j += 4) { float total = 0.0; - total += w[i + 0]; - total += w[i + 1]; - total += w[i + 2]; - total += w[i + 3]; + total += w[j + 0]; + total += w[j + 1]; + total += w[j + 2]; + total += w[j + 3]; if (total > 0.0) { - w[i + 0] /= total; - w[i + 1] /= total; - w[i + 2] /= total; - w[i + 3] /= total; + w[j + 0] /= total; + w[j + 1] /= total; + w[j + 2] /= total; + w[j + 3] /= total; } + + //print_line(itos(j / 4) + ": " + itos(r[j + 0]) + ":" + rtos(w[j + 0]) + ", " + itos(r[j + 1]) + ":" + rtos(w[j + 1]) + ", " + itos(r[j + 2]) + ":" + rtos(w[j + 2]) + ", " + itos(r[j + 3]) + ":" + rtos(w[j + 3])); } } array[Mesh::ARRAY_WEIGHTS] = weights; @@ -1368,6 +1374,10 @@ Error EditorSceneImporterGLTF::_parse_skins(GLTFState &state) { //state.nodes[skeleton]->skeleton_skin = state.skins.size(); print_line("setting skeleton skin to" + itos(skeleton)); skin.skeleton = skeleton; + if (!state.skeleton_nodes.has(skeleton)) { + state.skeleton_nodes[skeleton] = Vector(); + } + state.skeleton_nodes[skeleton].push_back(i); } if (d.has("name")) { @@ -1671,7 +1681,8 @@ void EditorSceneImporterGLTF::_generate_node(GLTFState &state, int p_node, Node MeshInstance *mi = Object::cast_to(node); //move skeleton around and place it on node, as the node _is_ a skeleton. Skeleton *s = skeletons[n->skin]; - mi->set_skeleton_path(mi->get_path_to(s)); + state.paths_to_skeleton[mi] = s; + //move it later, as skeleton may be moved around first } #if 0 @@ -1685,16 +1696,27 @@ void EditorSceneImporterGLTF::_generate_node(GLTFState &state, int p_node, Node #endif for (int i = 0; i < n->children.size(); i++) { if (state.nodes[n->children[i]]->joints.size()) { - _generate_bone(state, n->children[i], skeletons, Vector()); + _generate_bone(state, n->children[i], skeletons, Vector(), node); } else { _generate_node(state, n->children[i], node, p_owner, skeletons); } } } -void EditorSceneImporterGLTF::_generate_bone(GLTFState &state, int p_node, Vector &skeletons, const Vector &p_parent_bones) { +void EditorSceneImporterGLTF::_generate_bone(GLTFState &state, int p_node, Vector &skeletons, const Vector &p_parent_bones, Node *p_parent_node) { ERR_FAIL_INDEX(p_node, state.nodes.size()); + if (state.skeleton_nodes.has(p_node)) { + //reparent skeletons to proper place + Vector nodes = state.skeleton_nodes[p_node]; + for (int i = 0; i < nodes.size(); i++) { + Node *owner = skeletons[i]->get_owner(); + skeletons[i]->get_parent()->remove_child(skeletons[i]); + p_parent_node->add_child(skeletons[i]); + skeletons[i]->set_owner(owner); + } + } + GLTFNode *n = state.nodes[p_node]; Vector parent_bones; @@ -1714,7 +1736,7 @@ void EditorSceneImporterGLTF::_generate_bone(GLTFState &state, int p_node, Vecto } for (int i = 0; i < n->children.size(); i++) { - _generate_bone(state, n->children[i], skeletons, parent_bones); + _generate_bone(state, n->children[i], skeletons, parent_bones, p_parent_node); } } @@ -2030,12 +2052,18 @@ Spatial *EditorSceneImporterGLTF::_generate_scene(GLTFState &state, int p_bake_f } for (int i = 0; i < state.root_nodes.size(); i++) { if (state.nodes[state.root_nodes[i]]->joints.size()) { - _generate_bone(state, state.root_nodes[i], skeletons, Vector()); + _generate_bone(state, state.root_nodes[i], skeletons, Vector(), root); } else { _generate_node(state, state.root_nodes[i], root, root, skeletons); } } + for (Map::Element *E = state.paths_to_skeleton.front(); E; E = E->next()) { + MeshInstance *mi = Object::cast_to(E->key()); + ERR_CONTINUE(!mi); + mi->set_skeleton_path(mi->get_path_to(E->get())); + } + for (int i = 0; i < skeletons.size(); i++) { skeletons[i]->localize_rests(); } diff --git a/editor/import/editor_scene_importer_gltf.h b/editor/import/editor_scene_importer_gltf.h index 9d237407796..088036ce75d 100644 --- a/editor/import/editor_scene_importer_gltf.h +++ b/editor/import/editor_scene_importer_gltf.h @@ -274,6 +274,9 @@ class EditorSceneImporterGLTF : public EditorSceneImporter { Vector animations; + Map > skeleton_nodes; + Map paths_to_skeleton; + //Map > skin_users; //cache skin users ~GLTFState() { @@ -308,7 +311,7 @@ class EditorSceneImporterGLTF : public EditorSceneImporter { Vector _decode_accessor_as_basis(GLTFState &state, int p_accessor, bool p_for_vertex); Vector _decode_accessor_as_xform(GLTFState &state, int p_accessor, bool p_for_vertex); - void _generate_bone(GLTFState &state, int p_node, Vector &skeletons, const Vector &p_parent_bones); + void _generate_bone(GLTFState &state, int p_node, Vector &skeletons, const Vector &p_parent_bones, Node *p_parent_node); void _generate_node(GLTFState &state, int p_node, Node *p_parent, Node *p_owner, Vector &skeletons); void _import_animation(GLTFState &state, AnimationPlayer *ap, int index, int bake_fps, Vector skeletons);