diff options
Diffstat (limited to 'modules/gltf/gltf_document.cpp')
-rw-r--r-- | modules/gltf/gltf_document.cpp | 238 |
1 files changed, 181 insertions, 57 deletions
diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp index 8d2e37be3a..6700b6de0a 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) { @@ -465,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) { @@ -489,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) { @@ -529,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) { @@ -2584,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]; @@ -2818,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)); } } @@ -3028,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; @@ -3041,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); } @@ -3219,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; @@ -3240,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(); @@ -3254,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; @@ -3268,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++) { @@ -3299,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; @@ -3429,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; @@ -3484,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) { @@ -3507,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) { @@ -3566,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(); @@ -3614,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")) { @@ -4301,14 +4418,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); @@ -4839,12 +4956,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++) { @@ -5707,15 +5824,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); @@ -5938,7 +6055,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) { @@ -6477,8 +6594,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; } @@ -6834,6 +6953,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); |