diff options
Diffstat (limited to 'modules/gltf/gltf_document.cpp')
-rw-r--r-- | modules/gltf/gltf_document.cpp | 339 |
1 files changed, 242 insertions, 97 deletions
diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp index f5730e7137..cb148463a7 100644 --- a/modules/gltf/gltf_document.cpp +++ b/modules/gltf/gltf_document.cpp @@ -145,6 +145,12 @@ Error GLTFDocument::_serialize(Ref<GLTFState> state, const String &p_path) { return Error::FAILED; } + /* STEP SERIALIZE TEXTURE SAMPLERS */ + err = _serialize_texture_samplers(state); + if (err != OK) { + return Error::FAILED; + } + /* STEP SERIALIZE ANIMATIONS */ err = _serialize_animations(state); if (err != OK) { @@ -191,14 +197,14 @@ Error GLTFDocument::_serialize(Ref<GLTFState> state, const String &p_path) { return Error::FAILED; } - /* STEP SERIALIZE SCENE */ + /* STEP SERIALIZE LIGHTS */ err = _serialize_lights(state); if (err != OK) { return Error::FAILED; } /* STEP SERIALIZE EXTENSIONS */ - err = _serialize_extensions(state); + err = _serialize_gltf_extensions(state); if (err != OK) { return Error::FAILED; } @@ -219,9 +225,9 @@ Error GLTFDocument::_serialize(Ref<GLTFState> state, const String &p_path) { return OK; } -Error GLTFDocument::_serialize_extensions(Ref<GLTFState> state) const { - Array extensions_used; - Array extensions_required; +Error GLTFDocument::_serialize_gltf_extensions(Ref<GLTFState> state) const { + Vector<String> extensions_used = state->extensions_used; + Vector<String> extensions_required = state->extensions_required; if (!state->lights.is_empty()) { extensions_used.push_back("KHR_lights_punctual"); } @@ -230,9 +236,11 @@ Error GLTFDocument::_serialize_extensions(Ref<GLTFState> state) const { extensions_required.push_back("KHR_texture_transform"); } if (!extensions_used.is_empty()) { + extensions_used.sort(); state->json["extensionsUsed"] = extensions_used; } if (!extensions_required.is_empty()) { + extensions_required.sort(); state->json["extensionsRequired"] = extensions_required; } return OK; @@ -401,47 +409,47 @@ Error GLTFDocument::_serialize_nodes(Ref<GLTFState> state) { Array nodes; for (int i = 0; i < state->nodes.size(); i++) { Dictionary node; - Ref<GLTFNode> n = state->nodes[i]; + Ref<GLTFNode> gltf_node = state->nodes[i]; Dictionary extensions; node["extensions"] = extensions; - if (!n->get_name().is_empty()) { - node["name"] = n->get_name(); + if (!gltf_node->get_name().is_empty()) { + node["name"] = gltf_node->get_name(); } - if (n->camera != -1) { - node["camera"] = n->camera; + if (gltf_node->camera != -1) { + node["camera"] = gltf_node->camera; } - if (n->light != -1) { + if (gltf_node->light != -1) { Dictionary lights_punctual; extensions["KHR_lights_punctual"] = lights_punctual; - lights_punctual["light"] = n->light; + lights_punctual["light"] = gltf_node->light; } - if (n->mesh != -1) { - node["mesh"] = n->mesh; + if (gltf_node->mesh != -1) { + node["mesh"] = gltf_node->mesh; } - if (n->skin != -1) { - node["skin"] = n->skin; + if (gltf_node->skin != -1) { + node["skin"] = gltf_node->skin; } - if (n->skeleton != -1 && n->skin < 0) { + if (gltf_node->skeleton != -1 && gltf_node->skin < 0) { } - if (n->xform != Transform3D()) { - node["matrix"] = _xform_to_array(n->xform); + if (gltf_node->xform != Transform3D()) { + node["matrix"] = _xform_to_array(gltf_node->xform); } - if (!n->rotation.is_equal_approx(Quaternion())) { - node["rotation"] = _quaternion_to_array(n->rotation); + if (!gltf_node->rotation.is_equal_approx(Quaternion())) { + node["rotation"] = _quaternion_to_array(gltf_node->rotation); } - if (!n->scale.is_equal_approx(Vector3(1.0f, 1.0f, 1.0f))) { - node["scale"] = _vec3_to_arr(n->scale); + if (!gltf_node->scale.is_equal_approx(Vector3(1.0f, 1.0f, 1.0f))) { + node["scale"] = _vec3_to_arr(gltf_node->scale); } - if (!n->position.is_zero_approx()) { - node["translation"] = _vec3_to_arr(n->position); + if (!gltf_node->position.is_zero_approx()) { + node["translation"] = _vec3_to_arr(gltf_node->position); } - if (n->children.size()) { + if (gltf_node->children.size()) { Array children; - for (int j = 0; j < n->children.size(); j++) { - children.push_back(n->children[j]); + for (int j = 0; j < gltf_node->children.size(); j++) { + children.push_back(gltf_node->children[j]); } node["children"] = children; } @@ -450,7 +458,7 @@ Error GLTFDocument::_serialize_nodes(Ref<GLTFState> state) { Ref<GLTFDocumentExtension> ext = document_extensions[ext_i]; ERR_CONTINUE(ext.is_null()); ERR_CONTINUE(!state->scene_nodes.find(i)); - Error err = ext->export_node(state, n, state->json, state->scene_nodes[i]); + Error err = ext->export_node(state, gltf_node, node, state->scene_nodes[i]); ERR_CONTINUE(err != OK); } @@ -463,23 +471,23 @@ Error GLTFDocument::_serialize_nodes(Ref<GLTFState> state) { String GLTFDocument::_gen_unique_name(Ref<GLTFState> state, const String &p_name) { const String s_name = p_name.validate_node_name(); - String name; + String u_name; int index = 1; while (true) { - name = s_name; + u_name = s_name; if (index > 1) { - name += itos(index); + u_name += itos(index); } - if (!state->unique_names.has(name)) { + if (!state->unique_names.has(u_name)) { break; } index++; } - state->unique_names.insert(name); + state->unique_names.insert(u_name); - return name; + return u_name; } String GLTFDocument::_sanitize_animation_name(const String &p_name) { @@ -487,39 +495,39 @@ String GLTFDocument::_sanitize_animation_name(const String &p_name) { // (See animation/animation_player.cpp::add_animation) // TODO: Consider adding invalid_characters or a validate_animation_name to animation_player to mirror Node. - String name = p_name.validate_node_name(); - name = name.replace(",", ""); - name = name.replace("[", ""); - return name; + String anim_name = p_name.validate_node_name(); + anim_name = anim_name.replace(",", ""); + anim_name = anim_name.replace("[", ""); + return anim_name; } String GLTFDocument::_gen_unique_animation_name(Ref<GLTFState> state, const String &p_name) { const String s_name = _sanitize_animation_name(p_name); - String name; + String u_name; int index = 1; while (true) { - name = s_name; + u_name = s_name; if (index > 1) { - name += itos(index); + u_name += itos(index); } - if (!state->unique_animation_names.has(name)) { + if (!state->unique_animation_names.has(u_name)) { break; } index++; } - state->unique_animation_names.insert(name); + state->unique_animation_names.insert(u_name); - return name; + return u_name; } String GLTFDocument::_sanitize_bone_name(const String &p_name) { - String name = p_name; - name = name.replace(":", "_"); - name = name.replace("/", "_"); - return name; + String bone_name = p_name; + bone_name = bone_name.replace(":", "_"); + bone_name = bone_name.replace("/", "_"); + return bone_name; } String GLTFDocument::_gen_unique_bone_name(Ref<GLTFState> state, const GLTFSkeletonIndex skel_i, const String &p_name) { @@ -527,23 +535,23 @@ String GLTFDocument::_gen_unique_bone_name(Ref<GLTFState> state, const GLTFSkele if (s_name.is_empty()) { s_name = "bone"; } - String name; + String u_name; int index = 1; while (true) { - name = s_name; + u_name = s_name; if (index > 1) { - name += "_" + itos(index); + u_name += "_" + itos(index); } - if (!state->skeletons[skel_i]->unique_names.has(name)) { + if (!state->skeletons[skel_i]->unique_names.has(u_name)) { break; } index++; } - state->skeletons.write[skel_i]->unique_names.insert(name); + state->skeletons.write[skel_i]->unique_names.insert(u_name); - return name; + return u_name; } Error GLTFDocument::_parse_scenes(Ref<GLTFState> state) { @@ -2582,10 +2590,7 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) { Mesh::PRIMITIVE_TRIANGLES, // 4 TRIANGLES Mesh::PRIMITIVE_TRIANGLE_STRIP, // 5 TRIANGLE_STRIP Mesh::PRIMITIVE_TRIANGLES, // 6 TRIANGLE_FAN fan not supported, should be converted -#ifndef _MSC_VER -#warning line loop and triangle fan are not supported and need to be converted to lines and triangles -#endif - + // TODO: Line loop and triangle fan are not supported and need to be converted to lines and triangles. }; primitive = primitives2[mode]; @@ -2816,8 +2821,7 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) { if (j == 0) { const Array &target_names = extras.has("targetNames") ? (Array)extras["targetNames"] : Array(); for (int k = 0; k < targets.size(); k++) { - const String name = k < target_names.size() ? (String)target_names[k] : String("morph_") + itos(k); - import_mesh->add_blend_shape(name); + import_mesh->add_blend_shape(k < target_names.size() ? (String)target_names[k] : String("morph_") + itos(k)); } } @@ -3026,12 +3030,12 @@ Error GLTFDocument::_serialize_images(Ref<GLTFState> state, const String &p_path d["mimeType"] = "image/png"; } else { ERR_FAIL_COND_V(p_path.is_empty(), ERR_INVALID_PARAMETER); - String name = state->images[i]->get_name(); - if (name.is_empty()) { - name = itos(i); + String img_name = state->images[i]->get_name(); + if (img_name.is_empty()) { + img_name = itos(i); } - name = _gen_unique_name(state, name); - name = name.pad_zeros(3) + ".png"; + img_name = _gen_unique_name(state, img_name); + img_name = img_name.pad_zeros(3) + ".png"; String texture_dir = "textures"; String path = p_path.get_base_dir(); String new_texture_dir = path + "/" + texture_dir; @@ -3039,8 +3043,8 @@ Error GLTFDocument::_serialize_images(Ref<GLTFState> state, const String &p_path if (!da->dir_exists(new_texture_dir)) { da->make_dir(new_texture_dir); } - image->save_png(new_texture_dir.path_join(name)); - d["uri"] = texture_dir.path_join(name).uri_encode(); + image->save_png(new_texture_dir.path_join(img_name)); + d["uri"] = texture_dir.path_join(img_name).uri_encode(); } images.push_back(d); } @@ -3217,6 +3221,11 @@ Error GLTFDocument::_serialize_textures(Ref<GLTFState> state) { Ref<GLTFTexture> t = state->textures[i]; ERR_CONTINUE(t->get_src_image() == -1); d["source"] = t->get_src_image(); + + GLTFTextureSamplerIndex sampler_index = t->get_sampler(); + if (sampler_index != -1) { + d["sampler"] = sampler_index; + } textures.push_back(d); } state->json["textures"] = textures; @@ -3238,13 +3247,18 @@ Error GLTFDocument::_parse_textures(Ref<GLTFState> state) { Ref<GLTFTexture> t; t.instantiate(); t->set_src_image(d["source"]); + if (d.has("sampler")) { + t->set_sampler(d["sampler"]); + } else { + t->set_sampler(-1); + } state->textures.push_back(t); } return OK; } -GLTFTextureIndex GLTFDocument::_set_texture(Ref<GLTFState> state, Ref<Texture2D> p_texture) { +GLTFTextureIndex GLTFDocument::_set_texture(Ref<GLTFState> state, Ref<Texture2D> p_texture, StandardMaterial3D::TextureFilter p_filter_mode, bool p_repeats) { ERR_FAIL_COND_V(p_texture.is_null(), -1); Ref<GLTFTexture> gltf_texture; gltf_texture.instantiate(); @@ -3252,6 +3266,7 @@ GLTFTextureIndex GLTFDocument::_set_texture(Ref<GLTFState> state, Ref<Texture2D> GLTFImageIndex gltf_src_image_i = state->images.size(); state->images.push_back(p_texture); gltf_texture->set_src_image(gltf_src_image_i); + gltf_texture->set_sampler(_set_sampler_for_mode(state, p_filter_mode, p_repeats)); GLTFTextureIndex gltf_texture_i = state->textures.size(); state->textures.push_back(gltf_texture); return gltf_texture_i; @@ -3266,6 +3281,102 @@ Ref<Texture2D> GLTFDocument::_get_texture(Ref<GLTFState> state, const GLTFTextur return state->images[image]; } +GLTFTextureSamplerIndex GLTFDocument::_set_sampler_for_mode(Ref<GLTFState> state, StandardMaterial3D::TextureFilter p_filter_mode, bool p_repeats) { + for (int i = 0; i < state->texture_samplers.size(); ++i) { + if (state->texture_samplers[i]->get_filter_mode() == p_filter_mode) { + return i; + } + } + + GLTFTextureSamplerIndex gltf_sampler_i = state->texture_samplers.size(); + Ref<GLTFTextureSampler> gltf_sampler; + gltf_sampler.instantiate(); + gltf_sampler->set_filter_mode(p_filter_mode); + gltf_sampler->set_wrap_mode(p_repeats); + state->texture_samplers.push_back(gltf_sampler); + return gltf_sampler_i; +} + +Ref<GLTFTextureSampler> GLTFDocument::_get_sampler_for_texture(Ref<GLTFState> state, const GLTFTextureIndex p_texture) { + ERR_FAIL_INDEX_V(p_texture, state->textures.size(), Ref<Texture2D>()); + const GLTFTextureSamplerIndex sampler = state->textures[p_texture]->get_sampler(); + + if (sampler == -1) { + return state->default_texture_sampler; + } else { + ERR_FAIL_INDEX_V(sampler, state->texture_samplers.size(), Ref<GLTFTextureSampler>()); + + return state->texture_samplers[sampler]; + } +} + +Error GLTFDocument::_serialize_texture_samplers(Ref<GLTFState> state) { + if (!state->texture_samplers.size()) { + return OK; + } + + Array samplers; + for (int32_t i = 0; i < state->texture_samplers.size(); ++i) { + Dictionary d; + Ref<GLTFTextureSampler> s = state->texture_samplers[i]; + d["magFilter"] = s->get_mag_filter(); + d["minFilter"] = s->get_min_filter(); + d["wrapS"] = s->get_wrap_s(); + d["wrapT"] = s->get_wrap_t(); + samplers.push_back(d); + } + state->json["samplers"] = samplers; + + return OK; +} + +Error GLTFDocument::_parse_texture_samplers(Ref<GLTFState> state) { + state->default_texture_sampler.instantiate(); + state->default_texture_sampler->set_min_filter(GLTFTextureSampler::FilterMode::LINEAR_MIPMAP_LINEAR); + state->default_texture_sampler->set_mag_filter(GLTFTextureSampler::FilterMode::LINEAR); + state->default_texture_sampler->set_wrap_s(GLTFTextureSampler::WrapMode::REPEAT); + state->default_texture_sampler->set_wrap_t(GLTFTextureSampler::WrapMode::REPEAT); + + if (!state->json.has("samplers")) { + return OK; + } + + const Array &samplers = state->json["samplers"]; + for (int i = 0; i < samplers.size(); ++i) { + const Dictionary &d = samplers[i]; + + Ref<GLTFTextureSampler> sampler; + sampler.instantiate(); + + if (d.has("minFilter")) { + sampler->set_min_filter(d["minFilter"]); + } else { + sampler->set_min_filter(GLTFTextureSampler::FilterMode::LINEAR_MIPMAP_LINEAR); + } + if (d.has("magFilter")) { + sampler->set_mag_filter(d["magFilter"]); + } else { + sampler->set_mag_filter(GLTFTextureSampler::FilterMode::LINEAR); + } + + if (d.has("wrapS")) { + sampler->set_wrap_s(d["wrapS"]); + } else { + sampler->set_wrap_s(GLTFTextureSampler::WrapMode::DEFAULT); + } + + if (d.has("wrapT")) { + sampler->set_wrap_t(d["wrapT"]); + } else { + sampler->set_wrap_t(GLTFTextureSampler::WrapMode::DEFAULT); + } + + state->texture_samplers.push_back(sampler); + } + + return OK; +} + Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) { Array materials; for (int32_t i = 0; i < state->materials.size(); i++) { @@ -3297,7 +3408,7 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) { if (albedo_texture.is_valid() && albedo_texture->get_image().is_valid()) { albedo_texture->set_name(material->get_name() + "_albedo"); - gltf_texture_index = _set_texture(state, albedo_texture); + gltf_texture_index = _set_texture(state, albedo_texture, material->get_texture_filter(), material->get_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT)); } if (gltf_texture_index != -1) { bct["index"] = gltf_texture_index; @@ -3373,7 +3484,7 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) { height = albedo_texture->get_height(); width = albedo_texture->get_width(); } - orm_image->create(width, height, false, Image::FORMAT_RGBA8); + orm_image->initialize_data(width, height, false, Image::FORMAT_RGBA8); if (ao_image.is_valid() && ao_image->get_size() != Vector2(width, height)) { ao_image->resize(width, height, Image::INTERPOLATE_LANCZOS); } @@ -3427,7 +3538,7 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) { GLTFTextureIndex orm_texture_index = -1; if (has_ao || has_roughness || has_metalness) { orm_texture->set_name(material->get_name() + "_orm"); - orm_texture_index = _set_texture(state, orm_texture); + orm_texture_index = _set_texture(state, orm_texture, material->get_texture_filter(), material->get_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT)); } if (has_ao) { Dictionary occt; @@ -3482,7 +3593,7 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) { GLTFTextureIndex gltf_texture_index = -1; if (tex.is_valid() && tex->get_image().is_valid()) { tex->set_name(material->get_name() + "_normal"); - gltf_texture_index = _set_texture(state, tex); + gltf_texture_index = _set_texture(state, tex, material->get_texture_filter(), material->get_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT)); } nt["scale"] = material->get_normal_scale(); if (gltf_texture_index != -1) { @@ -3505,7 +3616,7 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) { GLTFTextureIndex gltf_texture_index = -1; if (emission_texture.is_valid() && emission_texture->get_image().is_valid()) { emission_texture->set_name(material->get_name() + "_emission"); - gltf_texture_index = _set_texture(state, emission_texture); + gltf_texture_index = _set_texture(state, emission_texture, material->get_texture_filter(), material->get_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT)); } if (gltf_texture_index != -1) { @@ -3564,6 +3675,11 @@ Error GLTFDocument::_parse_materials(Ref<GLTFState> state) { if (sgm.has("diffuseTexture")) { const Dictionary &diffuse_texture_dict = sgm["diffuseTexture"]; if (diffuse_texture_dict.has("index")) { + Ref<GLTFTextureSampler> diffuse_sampler = _get_sampler_for_texture(state, diffuse_texture_dict["index"]); + if (diffuse_sampler.is_valid()) { + material->set_texture_filter(diffuse_sampler->get_filter_mode()); + material->set_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT, diffuse_sampler->get_wrap_mode()); + } Ref<Texture2D> diffuse_texture = _get_texture(state, diffuse_texture_dict["index"]); if (diffuse_texture.is_valid()) { spec_gloss->diffuse_img = diffuse_texture->get_image(); @@ -3612,6 +3728,9 @@ Error GLTFDocument::_parse_materials(Ref<GLTFState> state) { if (mr.has("baseColorTexture")) { const Dictionary &bct = mr["baseColorTexture"]; if (bct.has("index")) { + Ref<GLTFTextureSampler> bct_sampler = _get_sampler_for_texture(state, bct["index"]); + material->set_texture_filter(bct_sampler->get_filter_mode()); + material->set_flag(BaseMaterial3D::FLAG_USE_TEXTURE_REPEAT, bct_sampler->get_wrap_mode()); material->set_texture(BaseMaterial3D::TEXTURE_ALBEDO, _get_texture(state, bct["index"])); } if (!mr.has("baseColorFactor")) { @@ -3741,13 +3860,11 @@ void GLTFDocument::spec_gloss_to_rough_metal(Ref<GLTFSpecGloss> r_spec_gloss, Re if (r_spec_gloss->diffuse_img.is_null()) { return; } - Ref<Image> rm_img; - rm_img.instantiate(); bool has_roughness = false; bool has_metal = false; p_material->set_roughness(1.0f); p_material->set_metallic(1.0f); - rm_img->create(r_spec_gloss->spec_gloss_img->get_width(), r_spec_gloss->spec_gloss_img->get_height(), false, Image::FORMAT_RGBA8); + Ref<Image> rm_img = Image::create_empty(r_spec_gloss->spec_gloss_img->get_width(), r_spec_gloss->spec_gloss_img->get_height(), false, Image::FORMAT_RGBA8); r_spec_gloss->spec_gloss_img->decompress(); if (r_spec_gloss->diffuse_img.is_valid()) { r_spec_gloss->diffuse_img->decompress(); @@ -4299,14 +4416,14 @@ Error GLTFDocument::_determine_skeleton_roots(Ref<GLTFState> state, const GLTFSk Ref<GLTFSkeleton> skeleton = state->skeletons.write[skel_i]; - Vector<GLTFNodeIndex> owners; - disjoint_set.get_representatives(owners); + Vector<GLTFNodeIndex> representatives; + disjoint_set.get_representatives(representatives); Vector<GLTFNodeIndex> roots; - for (int i = 0; i < owners.size(); ++i) { + for (int i = 0; i < representatives.size(); ++i) { Vector<GLTFNodeIndex> set; - disjoint_set.get_members(set, owners[i]); + disjoint_set.get_members(set, representatives[i]); const GLTFNodeIndex root = _find_highest_node(state, set); ERR_FAIL_COND_V(root < 0, FAILED); roots.push_back(root); @@ -4837,12 +4954,12 @@ Error GLTFDocument::_parse_animations(Ref<GLTFState> state) { Array samplers = d["samplers"]; if (d.has("name")) { - const String name = d["name"]; - const String name_lower = name.to_lower(); - if (name_lower.begins_with("loop") || name_lower.ends_with("loop") || name_lower.begins_with("cycle") || name_lower.ends_with("cycle")) { + const String anim_name = d["name"]; + const String anim_name_lower = anim_name.to_lower(); + if (anim_name_lower.begins_with("loop") || anim_name_lower.ends_with("loop") || anim_name_lower.begins_with("cycle") || anim_name_lower.ends_with("cycle")) { animation->set_loop(true); } - animation->set_name(_gen_unique_animation_name(state, name)); + animation->set_name(_gen_unique_animation_name(state, anim_name)); } for (int j = 0; j < channels.size(); j++) { @@ -5046,7 +5163,7 @@ ImporterMeshInstance3D *GLTFDocument::_generate_mesh_instance(Ref<GLTFState> sta return mi; } -Node3D *GLTFDocument::_generate_light(Ref<GLTFState> state, const GLTFNodeIndex node_index) { +Light3D *GLTFDocument::_generate_light(Ref<GLTFState> state, const GLTFNodeIndex node_index) { Ref<GLTFNode> gltf_node = state->nodes[node_index]; ERR_FAIL_INDEX_V(gltf_node->light, state->lights.size(), nullptr); @@ -5102,6 +5219,7 @@ Node3D *GLTFDocument::_generate_spatial(Ref<GLTFState> state, const GLTFNodeInde return spatial; } + void GLTFDocument::_convert_scene_node(Ref<GLTFState> state, Node *p_current, const GLTFNodeIndex p_gltf_parent, const GLTFNodeIndex p_gltf_root) { bool retflag = true; _check_visibility(p_current, retflag); @@ -5704,15 +5822,15 @@ T GLTFDocument::_interpolate_track(const Vector<real_t> &p_times, const Vector<T void GLTFDocument::_import_animation(Ref<GLTFState> state, AnimationPlayer *ap, const GLTFAnimationIndex index, const int bake_fps) { Ref<GLTFAnimation> anim = state->animations[index]; - String name = anim->get_name(); - if (name.is_empty()) { + String anim_name = anim->get_name(); + if (anim_name.is_empty()) { // No node represent these, and they are not in the hierarchy, so just make a unique name - name = _gen_unique_name(state, "Animation"); + anim_name = _gen_unique_name(state, "Animation"); } Ref<Animation> animation; animation.instantiate(); - animation->set_name(name); + animation->set_name(anim_name); if (anim->get_loop()) { animation->set_loop_mode(Animation::LOOP_LINEAR); @@ -5935,7 +6053,7 @@ void GLTFDocument::_import_animation(Ref<GLTFState> state, AnimationPlayer *ap, } else { library = ap->get_animation_library(""); } - library->add_animation(name, animation); + library->add_animation(anim_name, animation); } void GLTFDocument::_convert_mesh_instances(Ref<GLTFState> state) { @@ -6474,8 +6592,10 @@ Error GLTFDocument::_parse(Ref<GLTFState> state, String p_path, Ref<FileAccess> err = ext->import_preflight(state); ERR_FAIL_COND_V(err != OK, err); } + err = _parse_gltf_state(state, p_path, p_bake_fps); ERR_FAIL_COND_V(err != OK, err); + return OK; } @@ -6831,6 +6951,11 @@ Error GLTFDocument::_parse_gltf_state(Ref<GLTFState> state, const String &p_sear ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); + /* PARSE TEXTURE SAMPLERS */ + err = _parse_texture_samplers(state); + + ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); + /* PARSE TEXTURES */ err = _parse_textures(state); @@ -6916,12 +7041,32 @@ Error GLTFDocument::append_from_file(String p_path, Ref<GLTFState> r_state, uint Error GLTFDocument::_parse_gltf_extensions(Ref<GLTFState> state) { ERR_FAIL_NULL_V(state, ERR_PARSE_ERROR); - if (state->json.has("extensionsRequired") && state->json["extensionsRequired"].get_type() == Variant::ARRAY) { - Array extensions_required = state->json["extensionsRequired"]; - if (extensions_required.find("KHR_draco_mesh_compression") != -1) { - ERR_PRINT("glTF2 extension KHR_draco_mesh_compression is not supported."); - return ERR_UNAVAILABLE; + if (state->json.has("extensionsUsed")) { + Vector<String> ext_array = state->json["extensionsUsed"]; + state->extensions_used = ext_array; + } + if (state->json.has("extensionsRequired")) { + Vector<String> ext_array = state->json["extensionsRequired"]; + state->extensions_required = ext_array; + } + HashSet<String> supported_extensions; + supported_extensions.insert("KHR_lights_punctual"); + supported_extensions.insert("KHR_materials_pbrSpecularGlossiness"); + supported_extensions.insert("KHR_texture_transform"); + for (int ext_i = 0; ext_i < document_extensions.size(); ext_i++) { + Ref<GLTFDocumentExtension> ext = document_extensions[ext_i]; + ERR_CONTINUE(ext.is_null()); + Vector<String> ext_supported_extensions = ext->get_supported_extensions(); + for (int i = 0; i < ext_supported_extensions.size(); ++i) { + supported_extensions.insert(ext_supported_extensions[i]); } } - return OK; + Error ret = Error::OK; + for (int i = 0; i < state->extensions_required.size(); i++) { + if (!supported_extensions.has(state->extensions_required[i])) { + ERR_PRINT("GLTF: Can't import file '" + state->filename + "', required extension '" + String(state->extensions_required[i]) + "' is not supported. Are you missing a GLTFDocumentExtension plugin?"); + ret = ERR_UNAVAILABLE; + } + } + return ret; } |