diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp index f8e30a889c6..6594bba65e8 100644 --- a/modules/gltf/gltf_document.cpp +++ b/modules/gltf/gltf_document.cpp @@ -2894,8 +2894,8 @@ Error GLTFDocument::_parse_meshes(Ref state) { } blend_weights.write[j] = weights[j]; } - mesh->set_blend_weights(blend_weights); } + mesh->set_blend_weights(blend_weights); mesh->set_mesh(import_mesh); state->meshes.push_back(mesh); @@ -4196,80 +4196,10 @@ Error GLTFDocument::_reparent_non_joint_skeleton_subtrees(Ref state, subtree_set.get_members(subtree_nodes, subtree_root); for (int subtree_i = 0; subtree_i < subtree_nodes.size(); ++subtree_i) { - ERR_FAIL_COND_V(_reparent_to_fake_joint(state, skeleton, subtree_nodes[subtree_i]), FAILED); - - // We modified the tree, recompute all the heights - _compute_node_heights(state); - } - } - - return OK; -} - -Error GLTFDocument::_reparent_to_fake_joint(Ref state, Ref skeleton, const GLTFNodeIndex node_index) { - Ref node = state->nodes[node_index]; - - // Can we just "steal" this joint if it is just a spatial node? - if (node->skin < 0 && node->mesh < 0 && node->camera < 0) { - node->joint = true; - // Add the joint to the skeletons joints - skeleton->joints.push_back(node_index); - return OK; - } - - GLTFNode *fake_joint = memnew(GLTFNode); - const GLTFNodeIndex fake_joint_index = state->nodes.size(); - state->nodes.push_back(fake_joint); - - // We better not be a joint, or we messed up in our logic - if (node->joint) - return FAILED; - - fake_joint->translation = node->translation; - fake_joint->rotation = node->rotation; - fake_joint->scale = node->scale; - fake_joint->xform = node->xform; - fake_joint->joint = true; - - // We can use the exact same name here, because the joint will be inside a skeleton and not the scene - fake_joint->set_name(node->get_name()); - - // Clear the nodes transforms, since it will be parented to the fake joint - node->translation = Vector3(0, 0, 0); - node->rotation = Quat(); - node->scale = Vector3(1, 1, 1); - node->xform = Transform(); - - // Transfer the node children to the fake joint - for (int child_i = 0; child_i < node->children.size(); ++child_i) { - Ref child = state->nodes[node->children[child_i]]; - child->parent = fake_joint_index; - } - - fake_joint->children = node->children; - node->children.clear(); - - // add the fake joint to the parent and remove the original joint - if (node->parent >= 0) { - Ref parent = state->nodes[node->parent]; - parent->children.erase(node_index); - parent->children.push_back(fake_joint_index); - fake_joint->parent = node->parent; - } - - // Add the node to the fake joint - fake_joint->children.push_back(node_index); - node->parent = fake_joint_index; - node->fake_joint_parent = fake_joint_index; - - // Add the fake joint to the skeletons joints - skeleton->joints.push_back(fake_joint_index); - - // Replace skin_skeletons with fake joints if we must. - for (GLTFSkinIndex skin_i = 0; skin_i < state->skins.size(); ++skin_i) { - Ref skin = state->skins.write[skin_i]; - if (skin->skin_root == node_index) { - skin->skin_root = fake_joint_index; + Ref node = state->nodes[subtree_nodes[subtree_i]]; + node->joint = true; + // Add the joint to the skeletons joints + skeleton->joints.push_back(subtree_nodes[subtree_i]); } } @@ -5016,9 +4946,9 @@ void GLTFDocument::_assign_scene_names(Ref state) { } } -BoneAttachment *GLTFDocument::_generate_bone_attachment(Ref state, Skeleton *skeleton, const GLTFNodeIndex node_index) { +BoneAttachment *GLTFDocument::_generate_bone_attachment(Ref state, Skeleton *skeleton, const GLTFNodeIndex node_index, const GLTFNodeIndex bone_index) { Ref gltf_node = state->nodes[node_index]; - Ref bone_node = state->nodes[gltf_node->parent]; + Ref bone_node = state->nodes[bone_index]; BoneAttachment *bone_attachment = memnew(BoneAttachment); print_verbose("glTF: Creating bone attachment for: " + gltf_node->get_name()); @@ -5106,7 +5036,7 @@ Spatial *GLTFDocument::_generate_mesh_instance(Ref state, Node *scene return mi; } -Light *GLTFDocument::_generate_light(Ref state, Node *scene_parent, const GLTFNodeIndex node_index) { +Spatial *GLTFDocument::_generate_light(Ref state, Node *scene_parent, const GLTFNodeIndex node_index) { Ref gltf_node = state->nodes[node_index]; ERR_FAIL_INDEX_V(gltf_node->light, state->lights.size(), nullptr); @@ -5155,7 +5085,7 @@ Light *GLTFDocument::_generate_light(Ref state, Node *scene_parent, c light->set_param(SpotLight::PARAM_SPOT_ATTENUATION, angle_attenuation); return light; } - return nullptr; + return memnew(Spatial); } Camera *GLTFDocument::_generate_camera(Ref state, Node *scene_parent, const GLTFNodeIndex node_index) { @@ -5526,32 +5456,102 @@ void GLTFDocument::_convert_mesh_to_gltf(Node *p_scene_parent, Ref st void GLTFDocument::_generate_scene_node(Ref state, Node *scene_parent, Spatial *scene_root, const GLTFNodeIndex node_index) { Ref gltf_node = state->nodes[node_index]; + if (gltf_node->skeleton >= 0) { + _generate_skeleton_bone_node(state, scene_parent, scene_root, node_index); + return; + } + Spatial *current_node = nullptr; // Is our parent a skeleton Skeleton *active_skeleton = Object::cast_to(scene_parent); - if (gltf_node->skeleton >= 0) { - Skeleton *skeleton = state->skeletons[gltf_node->skeleton]->godot_skeleton; - - if (active_skeleton != skeleton) { - ERR_FAIL_COND_MSG(active_skeleton != nullptr, "glTF: Generating scene detected direct parented Skeletons"); - - // Add it to the scene if it has not already been added - if (skeleton->get_parent() == nullptr) { - scene_parent->add_child(skeleton); - skeleton->set_owner(scene_root); - } - } - - active_skeleton = skeleton; - current_node = skeleton; - } + const bool non_bone_parented_to_skeleton = active_skeleton; // If we have an active skeleton, and the node is node skinned, we need to create a bone attachment - if (current_node == nullptr || gltf_node->mesh >= 0 || gltf_node->camera >= 0 || gltf_node->light >= 0) { - if (active_skeleton != nullptr && gltf_node->skin < 0) { - BoneAttachment *bone_attachment = _generate_bone_attachment(state, active_skeleton, node_index); + if (non_bone_parented_to_skeleton && gltf_node->skin < 0) { + // Bone Attachment - Parent Case + BoneAttachment *bone_attachment = _generate_bone_attachment(state, active_skeleton, node_index, gltf_node->parent); + + scene_parent->add_child(bone_attachment); + bone_attachment->set_owner(scene_root); + + // There is no gltf_node that represent this, so just directly create a unique name + bone_attachment->set_name(_gen_unique_name(state, "BoneAttachment")); + + // We change the scene_parent to our bone attachment now. We do not set current_node because we want to make the node + // and attach it to the bone_attachment + scene_parent = bone_attachment; + } + + // We still have not managed to make a node + if (gltf_node->mesh >= 0) { + current_node = _generate_mesh_instance(state, scene_parent, node_index); + } else if (gltf_node->camera >= 0) { + current_node = _generate_camera(state, scene_parent, node_index); + } else if (gltf_node->light >= 0) { + current_node = _generate_light(state, scene_parent, node_index); + } else { + current_node = _generate_spatial(state, scene_parent, node_index); + } + + scene_parent->add_child(current_node); + if (current_node != scene_root) { + current_node->set_owner(scene_root); + } + current_node->set_transform(gltf_node->xform); + current_node->set_name(gltf_node->get_name()); + + state->scene_nodes.insert(node_index, current_node); + + for (int i = 0; i < gltf_node->children.size(); ++i) { + _generate_scene_node(state, current_node, scene_root, gltf_node->children[i]); + } +} + +void GLTFDocument::_generate_skeleton_bone_node(Ref state, Node *scene_parent, Spatial *scene_root, const GLTFNodeIndex node_index) { + Ref gltf_node = state->nodes[node_index]; + + Spatial *current_node = nullptr; + + Skeleton *skeleton = state->skeletons[gltf_node->skeleton]->godot_skeleton; + // In this case, this node is already a bone in skeleton. + const bool is_skinned_mesh = (gltf_node->skin >= 0 && gltf_node->mesh >= 0); + const bool requires_extra_node = (gltf_node->mesh >= 0 || gltf_node->camera >= 0 || gltf_node->light >= 0); + + Skeleton *active_skeleton = Object::cast_to(scene_parent); + if (active_skeleton != skeleton) { + if (active_skeleton) { + // Bone Attachment - Direct Parented Skeleton Case + BoneAttachment *bone_attachment = _generate_bone_attachment(state, active_skeleton, node_index, gltf_node->parent); + + scene_parent->add_child(bone_attachment); + bone_attachment->set_owner(scene_root); + + // There is no gltf_node that represent this, so just directly create a unique name + bone_attachment->set_name(_gen_unique_name(state, "BoneAttachment")); + + // We change the scene_parent to our bone attachment now. We do not set current_node because we want to make the node + // and attach it to the bone_attachment + scene_parent = bone_attachment; + WARN_PRINT(vformat("glTF: Generating scene detected direct parented Skeletons at node %d", node_index)); + } + + // Add it to the scene if it has not already been added + if (skeleton->get_parent() == nullptr) { + scene_parent->add_child(skeleton); + skeleton->set_owner(scene_root); + } + } + + active_skeleton = skeleton; + current_node = skeleton; + + if (requires_extra_node) { + // skinned meshes must not be placed in a bone attachment. + if (!is_skinned_mesh) { + // Bone Attachment - Same Node Case + BoneAttachment *bone_attachment = _generate_bone_attachment(state, active_skeleton, node_index, node_index); scene_parent->add_child(bone_attachment); bone_attachment->set_owner(scene_root); @@ -5573,17 +5573,11 @@ void GLTFDocument::_generate_scene_node(Ref state, Node *scene_parent current_node = _generate_light(state, scene_parent, node_index); } - if (!current_node) { - current_node = _generate_spatial(state, scene_parent, node_index); - } - scene_parent->add_child(current_node); if (current_node != scene_root) { current_node->set_owner(scene_root); } - if (use_xform) { - current_node->set_transform(gltf_node->xform); - } + // Do not set transform here. Transform is already applied to our bone. if (state->use_legacy_names) { current_node->set_name(_legacy_validate_node_name(gltf_node->get_name())); } else { @@ -5594,7 +5588,7 @@ void GLTFDocument::_generate_scene_node(Ref state, Node *scene_parent state->scene_nodes.insert(node_index, current_node); for (int i = 0; i < gltf_node->children.size(); ++i) { - _generate_scene_node(state, current_node, scene_root, gltf_node->children[i]); + _generate_scene_node(state, active_skeleton, scene_root, gltf_node->children[i]); } } @@ -5735,28 +5729,30 @@ void GLTFDocument::_import_animation(Ref state, AnimationPlayer *ap, for (Map::Element *track_i = anim->get_tracks().front(); track_i; track_i = track_i->next()) { const GLTFAnimation::Track &track = track_i->get(); - //need to find the path + //need to find the path: for skeletons, weight tracks will affect the mesh NodePath node_path; + //for skeletons, transform tracks always affect bones + NodePath transform_node_path; GLTFNodeIndex node_index = track_i->key(); - if (state->nodes[node_index]->fake_joint_parent >= 0) { - // Should be same as parent - node_index = state->nodes[node_index]->fake_joint_parent; - } const Ref gltf_node = state->nodes[track_i->key()]; + Node *root = ap->get_parent(); + ERR_FAIL_COND(root == nullptr); + Map::Element *node_element = state->scene_nodes.find(node_index); + ERR_CONTINUE_MSG(node_element == nullptr, vformat("Unable to find node %d for animation", node_index)); + node_path = root->get_path_to(node_element->get()); + if (gltf_node->skeleton >= 0) { const Skeleton *sk = state->skeletons[gltf_node->skeleton]->godot_skeleton; ERR_FAIL_COND(sk == nullptr); const String path = ap->get_parent()->get_path_to(sk); const String bone = gltf_node->get_name(); - node_path = path + ":" + bone; + transform_node_path = path + ":" + bone; } else { - Node *root = ap->get_parent(); - Node *godot_node = state->scene_nodes.find(node_index)->get(); - node_path = root->get_path_to(godot_node); + transform_node_path = node_path; } for (int i = 0; i < track.rotation_track.times.size(); i++) { @@ -5775,11 +5771,13 @@ void GLTFDocument::_import_animation(Ref state, AnimationPlayer *ap, } } - if (track.rotation_track.values.size() || track.translation_track.values.size() || track.scale_track.values.size()) { + // Animated TRS properties will not affect a skinned mesh. + const bool transform_affects_skinned_mesh_instance = gltf_node->skeleton < 0 && gltf_node->skin >= 0; + if ((track.rotation_track.values.size() || track.translation_track.values.size() || track.scale_track.values.size()) && !transform_affects_skinned_mesh_instance) { //make transform track int track_idx = animation->get_track_count(); animation->add_track(Animation::TYPE_TRANSFORM); - animation->track_set_path(track_idx, node_path); + animation->track_set_path(track_idx, transform_node_path); //first determine animation length const double increment = 1.0 / bake_fps; diff --git a/modules/gltf/gltf_document.h b/modules/gltf/gltf_document.h index 993d870be95..31e2324b9bd 100644 --- a/modules/gltf/gltf_document.h +++ b/modules/gltf/gltf_document.h @@ -258,11 +258,12 @@ private: Error _serialize_animations(Ref state); BoneAttachment *_generate_bone_attachment(Ref state, Skeleton *skeleton, - const GLTFNodeIndex node_index); + const GLTFNodeIndex node_index, + const GLTFNodeIndex bone_index); Spatial *_generate_mesh_instance(Ref state, Node *scene_parent, const GLTFNodeIndex node_index); Camera *_generate_camera(Ref state, Node *scene_parent, const GLTFNodeIndex node_index); - Light *_generate_light(Ref state, Node *scene_parent, const GLTFNodeIndex node_index); + Spatial *_generate_light(Ref state, Node *scene_parent, const GLTFNodeIndex node_index); Spatial *_generate_spatial(Ref state, Node *scene_parent, const GLTFNodeIndex node_index); void _assign_scene_names(Ref state); @@ -366,6 +367,7 @@ public: void _generate_scene_node(Ref state, Node *scene_parent, Spatial *scene_root, const GLTFNodeIndex node_index); + void _generate_skeleton_bone_node(Ref state, Node *scene_parent, Spatial *scene_root, const GLTFNodeIndex node_index); void _import_animation(Ref state, AnimationPlayer *ap, const GLTFAnimationIndex index, const int bake_fps); GLTFMeshIndex _convert_mesh_instance(Ref state, diff --git a/modules/gltf/gltf_node.cpp b/modules/gltf/gltf_node.cpp index 0ac0b06510c..2beb2f34d13 100644 --- a/modules/gltf/gltf_node.cpp +++ b/modules/gltf/gltf_node.cpp @@ -55,8 +55,6 @@ void GLTFNode::_bind_methods() { ClassDB::bind_method(D_METHOD("set_scale", "scale"), &GLTFNode::set_scale); ClassDB::bind_method(D_METHOD("get_children"), &GLTFNode::get_children); ClassDB::bind_method(D_METHOD("set_children", "children"), &GLTFNode::set_children); - ClassDB::bind_method(D_METHOD("get_fake_joint_parent"), &GLTFNode::get_fake_joint_parent); - ClassDB::bind_method(D_METHOD("set_fake_joint_parent", "fake_joint_parent"), &GLTFNode::set_fake_joint_parent); ClassDB::bind_method(D_METHOD("get_light"), &GLTFNode::get_light); ClassDB::bind_method(D_METHOD("set_light", "light"), &GLTFNode::set_light); @@ -72,7 +70,6 @@ void GLTFNode::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::QUAT, "rotation"), "set_rotation", "get_rotation"); // Quat ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "scale"), "set_scale", "get_scale"); // Vector3 ADD_PROPERTY(PropertyInfo(Variant::POOL_INT_ARRAY, "children"), "set_children", "get_children"); // Vector - ADD_PROPERTY(PropertyInfo(Variant::INT, "fake_joint_parent"), "set_fake_joint_parent", "get_fake_joint_parent"); // GLTFNodeIndex ADD_PROPERTY(PropertyInfo(Variant::INT, "light"), "set_light", "get_light"); // GLTFLightIndex } @@ -172,14 +169,6 @@ void GLTFNode::set_children(Vector p_children) { children = p_children; } -GLTFNodeIndex GLTFNode::get_fake_joint_parent() { - return fake_joint_parent; -} - -void GLTFNode::set_fake_joint_parent(GLTFNodeIndex p_fake_joint_parent) { - fake_joint_parent = p_fake_joint_parent; -} - GLTFLightIndex GLTFNode::get_light() { return light; } diff --git a/modules/gltf/gltf_node.h b/modules/gltf/gltf_node.h index 32e41d037d9..f292e151ef1 100644 --- a/modules/gltf/gltf_node.h +++ b/modules/gltf/gltf_node.h @@ -53,7 +53,6 @@ private: Quat rotation; Vector3 scale = Vector3(1, 1, 1); Vector children; - GLTFNodeIndex fake_joint_parent = -1; GLTFLightIndex light = -1; protected: @@ -96,9 +95,6 @@ public: Vector get_children(); void set_children(Vector p_children); - GLTFNodeIndex get_fake_joint_parent(); - void set_fake_joint_parent(GLTFNodeIndex p_fake_joint_parent); - GLTFLightIndex get_light(); void set_light(GLTFLightIndex p_light); };