diff options
Diffstat (limited to 'modules/gltf/gltf_document.cpp')
-rw-r--r-- | modules/gltf/gltf_document.cpp | 175 |
1 files changed, 98 insertions, 77 deletions
diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp index 2c42879bd3..281f62c4ad 100644 --- a/modules/gltf/gltf_document.cpp +++ b/modules/gltf/gltf_document.cpp @@ -58,7 +58,6 @@ #include "core/variant/variant.h" #include "core/version.h" #include "drivers/png/png_driver_common.h" -#include "editor/import/resource_importer_scene.h" #include "scene/2d/node_2d.h" #include "scene/3d/camera_3d.h" #include "scene/3d/mesh_instance_3d.h" @@ -66,6 +65,7 @@ #include "scene/3d/node_3d.h" #include "scene/animation/animation_player.h" #include "scene/resources/importer_mesh.h" +#include "scene/resources/material.h" #include "scene/resources/mesh.h" #include "scene/resources/multimesh.h" #include "scene/resources/surface_tool.h" @@ -79,6 +79,10 @@ #include "modules/gridmap/grid_map.h" #endif // MODULE_GRIDMAP_ENABLED +// FIXME: Hardcoded to avoid editor dependency. +#define GLTF_IMPORT_USE_NAMED_SKIN_BINDS 16 +#define GLTF_IMPORT_DISCARD_MESHES_AND_MATERIALS 32 + #include <stdio.h> #include <stdlib.h> #include <cstdint> @@ -254,8 +258,8 @@ Error GLTFDocument::_serialize_scenes(Ref<GLTFState> state) { Error GLTFDocument::_parse_json(const String &p_path, Ref<GLTFState> state) { Error err; - FileAccessRef f = FileAccess::open(p_path, FileAccess::READ, &err); - if (!f) { + Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ, &err); + if (f.is_null()) { return err; } @@ -276,7 +280,7 @@ Error GLTFDocument::_parse_json(const String &p_path, Ref<GLTFState> state) { return OK; } -Error GLTFDocument::_parse_glb(FileAccess *f, Ref<GLTFState> state) { +Error GLTFDocument::_parse_glb(Ref<FileAccess> f, Ref<GLTFState> state) { ERR_FAIL_NULL_V(f, ERR_INVALID_PARAMETER); ERR_FAIL_NULL_V(state, ERR_INVALID_PARAMETER); ERR_FAIL_COND_V(f->get_position() != 0, ERR_FILE_CANT_READ); @@ -694,8 +698,8 @@ Error GLTFDocument::_encode_buffer_glb(Ref<GLTFState> state, const String &p_pat String filename = p_path.get_basename().get_file() + itos(i) + ".bin"; String path = p_path.get_base_dir() + "/" + filename; Error err; - FileAccessRef f = FileAccess::open(path, FileAccess::WRITE, &err); - if (!f) { + Ref<FileAccess> f = FileAccess::open(path, FileAccess::WRITE, &err); + if (f.is_null()) { return err; } if (buffer_data.size() == 0) { @@ -703,7 +707,6 @@ Error GLTFDocument::_encode_buffer_glb(Ref<GLTFState> state, const String &p_pat } f->create(FileAccess::ACCESS_RESOURCES); f->store_buffer(buffer_data.ptr(), buffer_data.size()); - f->close(); gltf_buffer["uri"] = filename; gltf_buffer["byteLength"] = buffer_data.size(); buffers.push_back(gltf_buffer); @@ -727,8 +730,8 @@ Error GLTFDocument::_encode_buffer_bins(Ref<GLTFState> state, const String &p_pa String filename = p_path.get_basename().get_file() + itos(i) + ".bin"; String path = p_path.get_base_dir() + "/" + filename; Error err; - FileAccessRef f = FileAccess::open(path, FileAccess::WRITE, &err); - if (!f) { + Ref<FileAccess> f = FileAccess::open(path, FileAccess::WRITE, &err); + if (f.is_null()) { return err; } if (buffer_data.size() == 0) { @@ -736,7 +739,6 @@ Error GLTFDocument::_encode_buffer_bins(Ref<GLTFState> state, const String &p_pa } f->create(FileAccess::ACCESS_RESOURCES); f->store_buffer(buffer_data.ptr(), buffer_data.size()); - f->close(); gltf_buffer["uri"] = filename; gltf_buffer["byteLength"] = buffer_data.size(); buffers.push_back(gltf_buffer); @@ -2907,34 +2909,43 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) { } array_copy = blend_surface_tool->commit_to_arrays(); + // Enforce blend shape mask array format + for (int l = 0; l < Mesh::ARRAY_MAX; l++) { + if (!(Mesh::ARRAY_FORMAT_BLEND_SHAPE_MASK & (1 << l))) { + array_copy[l] = Variant(); + } + } + morphs.push_back(array_copy); } } - //just add it - Ref<BaseMaterial3D> mat; - if (p.has("material")) { - const int material = p["material"]; - ERR_FAIL_INDEX_V(material, state->materials.size(), ERR_FILE_CORRUPT); - Ref<BaseMaterial3D> mat3d = state->materials[material]; - ERR_FAIL_NULL_V(mat3d, ERR_FILE_CORRUPT); - if (has_vertex_color) { - mat3d->set_flag(BaseMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); - } - mat = mat3d; + String mat_name; + if (!state->discard_meshes_and_materials) { + if (p.has("material")) { + const int material = p["material"]; + ERR_FAIL_INDEX_V(material, state->materials.size(), ERR_FILE_CORRUPT); + Ref<BaseMaterial3D> mat3d = state->materials[material]; + ERR_FAIL_NULL_V(mat3d, ERR_FILE_CORRUPT); + if (has_vertex_color) { + mat3d->set_flag(BaseMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); + } + mat = mat3d; - } else { - Ref<StandardMaterial3D> mat3d; - mat3d.instantiate(); - if (has_vertex_color) { - mat3d->set_flag(BaseMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); + } else { + Ref<StandardMaterial3D> mat3d; + mat3d.instantiate(); + if (has_vertex_color) { + mat3d->set_flag(BaseMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); + } + mat = mat3d; } - mat = mat3d; + ERR_FAIL_NULL_V(mat, ERR_FILE_CORRUPT); + mat_name = mat->get_name(); } - ERR_FAIL_NULL_V(mat, ERR_FILE_CORRUPT); import_mesh->add_surface(primitive, array, morphs, - Dictionary(), mat, mat->get_name(), flags); + Dictionary(), mat, mat_name, flags); } Vector<float> blend_weights; @@ -3012,7 +3023,7 @@ Error GLTFDocument::_serialize_images(Ref<GLTFState> state, const String &p_path String texture_dir = "textures"; String path = p_path.get_base_dir(); String new_texture_dir = path + "/" + texture_dir; - DirAccessRef da = DirAccess::open(path); + Ref<DirAccess> da = DirAccess::open(path); if (!da->dir_exists(new_texture_dir)) { da->make_dir(new_texture_dir); } @@ -3265,7 +3276,7 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) { Dictionary mr; { Array arr; - const Color c = material->get_albedo().to_linear(); + const Color c = material->get_albedo().srgb_to_linear(); arr.push_back(c.r); arr.push_back(c.g); arr.push_back(c.b); @@ -3466,7 +3477,7 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) { } if (material->get_feature(BaseMaterial3D::FEATURE_EMISSION)) { - const Color c = material->get_emission().to_srgb(); + const Color c = material->get_emission().linear_to_srgb(); Array arr; arr.push_back(c.r); arr.push_back(c.g); @@ -3548,7 +3559,7 @@ Error GLTFDocument::_parse_materials(Ref<GLTFState> state) { if (sgm.has("diffuseFactor")) { const Array &arr = sgm["diffuseFactor"]; ERR_FAIL_COND_V(arr.size() != 4, ERR_PARSE_ERROR); - const Color c = Color(arr[0], arr[1], arr[2], arr[3]).to_srgb(); + const Color c = Color(arr[0], arr[1], arr[2], arr[3]).linear_to_srgb(); spec_gloss->diffuse_factor = c; material->set_albedo(spec_gloss->diffuse_factor); } @@ -3579,7 +3590,7 @@ Error GLTFDocument::_parse_materials(Ref<GLTFState> state) { if (mr.has("baseColorFactor")) { const Array &arr = mr["baseColorFactor"]; ERR_FAIL_COND_V(arr.size() != 4, ERR_PARSE_ERROR); - const Color c = Color(arr[0], arr[1], arr[2], arr[3]).to_srgb(); + const Color c = Color(arr[0], arr[1], arr[2], arr[3]).linear_to_srgb(); material->set_albedo(c); } @@ -3646,7 +3657,7 @@ Error GLTFDocument::_parse_materials(Ref<GLTFState> state) { if (d.has("emissiveFactor")) { const Array &arr = d["emissiveFactor"]; ERR_FAIL_COND_V(arr.size() != 3, ERR_PARSE_ERROR); - const Color c = Color(arr[0], arr[1], arr[2]).to_srgb(); + const Color c = Color(arr[0], arr[1], arr[2]).linear_to_srgb(); material->set_feature(BaseMaterial3D::FEATURE_EMISSION, true); material->set_emission(c); @@ -3730,11 +3741,11 @@ void GLTFDocument::spec_gloss_to_rough_metal(Ref<GLTFSpecGloss> r_spec_gloss, Re } for (int32_t y = 0; y < r_spec_gloss->spec_gloss_img->get_height(); y++) { for (int32_t x = 0; x < r_spec_gloss->spec_gloss_img->get_width(); x++) { - const Color specular_pixel = r_spec_gloss->spec_gloss_img->get_pixel(x, y).to_linear(); + const Color specular_pixel = r_spec_gloss->spec_gloss_img->get_pixel(x, y).srgb_to_linear(); Color specular = Color(specular_pixel.r, specular_pixel.g, specular_pixel.b); specular *= r_spec_gloss->specular_factor; Color diffuse = Color(1.0f, 1.0f, 1.0f); - diffuse *= r_spec_gloss->diffuse_img->get_pixel(x, y).to_linear(); + diffuse *= r_spec_gloss->diffuse_img->get_pixel(x, y).srgb_to_linear(); float metallic = 0.0f; Color base_color; spec_gloss_to_metal_base_color(specular, diffuse, base_color, metallic); @@ -3751,7 +3762,7 @@ void GLTFDocument::spec_gloss_to_rough_metal(Ref<GLTFSpecGloss> r_spec_gloss, Re mr.g = 1.0f - mr.g; rm_img->set_pixel(x, y, mr); if (r_spec_gloss->diffuse_img.is_valid()) { - r_spec_gloss->diffuse_img->set_pixel(x, y, base_color.to_srgb()); + r_spec_gloss->diffuse_img->set_pixel(x, y, base_color.linear_to_srgb()); } } } @@ -4619,7 +4630,7 @@ Error GLTFDocument::_parse_lights(Ref<GLTFState> state) { if (d.has("color")) { const Array &arr = d["color"]; ERR_FAIL_COND_V(arr.size() != 3, ERR_PARSE_ERROR); - const Color c = Color(arr[0], arr[1], arr[2]).to_srgb(); + const Color c = Color(arr[0], arr[1], arr[2]).linear_to_srgb(); light->color = c; } if (d.has("intensity")) { @@ -5741,7 +5752,7 @@ void GLTFDocument::_generate_skeleton_bone_node(Ref<GLTFState> state, Node *scen } template <class T> -struct EditorSceneFormatImporterGLTFInterpolate { +struct SceneFormatImporterGLTFInterpolate { T lerp(const T &a, const T &b, float c) const { return a + (b - a) * c; } @@ -5767,7 +5778,7 @@ struct EditorSceneFormatImporterGLTFInterpolate { // thank you for existing, partial specialization template <> -struct EditorSceneFormatImporterGLTFInterpolate<Quaternion> { +struct SceneFormatImporterGLTFInterpolate<Quaternion> { Quaternion lerp(const Quaternion &a, const Quaternion &b, const float c) const { ERR_FAIL_COND_V_MSG(!a.is_normalized(), Quaternion(), "The quaternion \"a\" must be normalized."); ERR_FAIL_COND_V_MSG(!b.is_normalized(), Quaternion(), "The quaternion \"b\" must be normalized."); @@ -5806,7 +5817,7 @@ T GLTFDocument::_interpolate_track(const Vector<real_t> &p_times, const Vector<T idx++; } - EditorSceneFormatImporterGLTFInterpolate<T> interp; + SceneFormatImporterGLTFInterpolate<T> interp; switch (p_interp) { case GLTFAnimation::INTERP_LINEAR: { @@ -6088,7 +6099,14 @@ void GLTFDocument::_import_animation(Ref<GLTFState> state, AnimationPlayer *ap, animation->set_length(length); - ap->add_animation(name, animation); + Ref<AnimationLibrary> library; + if (!ap->has_animation_library("")) { + library.instantiate(); + ap->add_animation_library("", library); + } else { + library = ap->get_animation_library(""); + } + library->add_animation(name, animation); } void GLTFDocument::_convert_mesh_instances(Ref<GLTFState> state) { @@ -6470,8 +6488,8 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap, gltf_animation->get_tracks().insert(transform_track_i.key, track); } } - } else if (String(orig_track_path).contains(":blend_shapes/")) { - const Vector<String> node_suffix = String(orig_track_path).split(":blend_shapes/"); + } else if (String(orig_track_path).contains(":") && animation->track_get_type(track_i) == Animation::TYPE_BLEND_SHAPE) { + const Vector<String> node_suffix = String(orig_track_path).split(":"); const NodePath path = node_suffix[0]; const String suffix = node_suffix[1]; Node *node = ap->get_parent()->get_node_or_null(path); @@ -6579,9 +6597,9 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap, } } -Error GLTFDocument::_parse(Ref<GLTFState> state, String p_path, FileAccess *f, int p_bake_fps) { +Error GLTFDocument::_parse(Ref<GLTFState> state, String p_path, Ref<FileAccess> f, int p_bake_fps) { Error err; - if (!f) { + if (f.is_null()) { return FAILED; } f->seek(0); @@ -6605,7 +6623,6 @@ Error GLTFDocument::_parse(Ref<GLTFState> state, String p_path, FileAccess *f, i ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); state->json = json.get_data(); } - f->close(); if (!state->json.has("asset")) { return ERR_PARSE_ERROR; @@ -6694,8 +6711,8 @@ Error GLTFDocument::_serialize_file(Ref<GLTFState> state, const String p_path) { if (p_path.to_lower().ends_with("glb")) { err = _encode_buffer_glb(state, p_path); ERR_FAIL_COND_V(err != OK, err); - FileAccessRef f = FileAccess::open(p_path, FileAccess::WRITE, &err); - ERR_FAIL_COND_V(!f, FAILED); + Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::WRITE, &err); + ERR_FAIL_COND_V(f.is_null(), FAILED); String json = Variant(state->json).to_json_string(); @@ -6732,25 +6749,22 @@ Error GLTFDocument::_serialize_file(Ref<GLTFState> state, const String p_path) { for (uint32_t pad_i = binary_data_length; pad_i < binary_chunk_length; pad_i++) { f->store_8(0); } - - f->close(); } else { err = _encode_buffer_bins(state, p_path); ERR_FAIL_COND_V(err != OK, err); - FileAccessRef f = FileAccess::open(p_path, FileAccess::WRITE, &err); - ERR_FAIL_COND_V(!f, FAILED); + Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::WRITE, &err); + ERR_FAIL_COND_V(f.is_null(), FAILED); f->create(FileAccess::ACCESS_RESOURCES); String json = Variant(state->json).to_json_string(); f->store_string(json); - f->close(); } return err; } void GLTFDocument::_bind_methods() { - ClassDB::bind_method(D_METHOD("append_from_file", "path", "state", "flags", "bake_fps"), - &GLTFDocument::append_from_file, DEFVAL(0), DEFVAL(30)); + ClassDB::bind_method(D_METHOD("append_from_file", "path", "state", "flags", "bake_fps", "base_path"), + &GLTFDocument::append_from_file, DEFVAL(0), DEFVAL(30), DEFVAL(String())); ClassDB::bind_method(D_METHOD("append_from_buffer", "bytes", "base_path", "state", "flags", "bake_fps"), &GLTFDocument::append_from_buffer, DEFVAL(0), DEFVAL(30)); ClassDB::bind_method(D_METHOD("append_from_scene", "node", "state", "flags", "bake_fps"), @@ -6898,8 +6912,8 @@ Node *GLTFDocument::generate_scene(Ref<GLTFState> state, int32_t p_bake_fps) { Error GLTFDocument::append_from_scene(Node *p_node, Ref<GLTFState> state, uint32_t p_flags, int32_t p_bake_fps) { ERR_FAIL_COND_V(state.is_null(), FAILED); - state->use_named_skin_binds = - p_flags & EditorSceneFormatImporter::IMPORT_USE_NAMED_SKIN_BINDS; + state->use_named_skin_binds = p_flags & GLTF_IMPORT_USE_NAMED_SKIN_BINDS; + state->discard_meshes_and_materials = p_flags & GLTF_IMPORT_DISCARD_MESHES_AND_MATERIALS; _convert_scene_node(state, p_node, -1, -1); if (!state->buffers.size()) { @@ -6918,9 +6932,11 @@ Error GLTFDocument::append_from_buffer(PackedByteArray p_bytes, String p_base_pa ERR_FAIL_COND_V(state.is_null(), FAILED); // TODO Add missing texture and missing .bin file paths to r_missing_deps 2021-09-10 fire Error err = FAILED; - state->use_named_skin_binds = - p_flags & EditorSceneFormatImporter::IMPORT_USE_NAMED_SKIN_BINDS; - FileAccessMemory *file_access = memnew(FileAccessMemory); + state->use_named_skin_binds = p_flags & GLTF_IMPORT_USE_NAMED_SKIN_BINDS; + state->discard_meshes_and_materials = p_flags & GLTF_IMPORT_DISCARD_MESHES_AND_MATERIALS; + + Ref<FileAccessMemory> file_access; + file_access.instantiate(); file_access->open_custom(p_bytes.ptr(), p_bytes.size()); err = _parse(state, p_base_path.get_base_dir(), file_access, p_bake_fps); ERR_FAIL_COND_V(err != OK, FAILED); @@ -6957,20 +6973,22 @@ Error GLTFDocument::_parse_gltf_state(Ref<GLTFState> state, const String &p_sear ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); - /* PARSE IMAGES */ - err = _parse_images(state, p_search_path); + if (!state->discard_meshes_and_materials) { + /* PARSE IMAGES */ + err = _parse_images(state, p_search_path); - ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); + ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); - /* PARSE TEXTURES */ - err = _parse_textures(state); + /* PARSE TEXTURES */ + err = _parse_textures(state); - ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); + ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); - /* PARSE TEXTURES */ - err = _parse_materials(state); + /* PARSE TEXTURES */ + err = _parse_materials(state); - ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); + ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); + } /* PARSE SKINS */ err = _parse_skins(state); @@ -7015,20 +7033,23 @@ Error GLTFDocument::_parse_gltf_state(Ref<GLTFState> state, const String &p_sear return OK; } -Error GLTFDocument::append_from_file(String p_path, Ref<GLTFState> r_state, uint32_t p_flags, int32_t p_bake_fps) { +Error GLTFDocument::append_from_file(String p_path, Ref<GLTFState> r_state, uint32_t p_flags, int32_t p_bake_fps, String p_base_path) { // TODO Add missing texture and missing .bin file paths to r_missing_deps 2021-09-10 fire if (r_state == Ref<GLTFState>()) { r_state.instantiate(); } r_state->filename = p_path.get_file().get_basename(); - r_state->use_named_skin_binds = - p_flags & EditorSceneFormatImporter::IMPORT_USE_NAMED_SKIN_BINDS; + r_state->use_named_skin_binds = p_flags & GLTF_IMPORT_USE_NAMED_SKIN_BINDS; + r_state->discard_meshes_and_materials = p_flags & GLTF_IMPORT_DISCARD_MESHES_AND_MATERIALS; Error err; - FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err); + Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ, &err); ERR_FAIL_COND_V(err != OK, ERR_FILE_CANT_OPEN); ERR_FAIL_NULL_V(f, ERR_FILE_CANT_OPEN); - - err = _parse(r_state, p_path.get_base_dir(), f, p_bake_fps); + String base_path = p_base_path; + if (base_path.is_empty()) { + base_path = p_path.get_base_dir(); + } + err = _parse(r_state, base_path, f, p_bake_fps); ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR); return err; } |