diff options
Diffstat (limited to 'editor/import')
21 files changed, 735 insertions, 498 deletions
diff --git a/editor/import/collada.cpp b/editor/import/collada.cpp index e38034dd8c..aa9700716d 100644 --- a/editor/import/collada.cpp +++ b/editor/import/collada.cpp @@ -50,8 +50,8 @@ String Collada::Effect::get_texture_path(const String &p_source, Collada &state) return state.state.image_map[image].path; } -Transform Collada::get_root_transform() const { - Transform unit_scale_transform; +Transform3D Collada::get_root_transform() const { + Transform3D unit_scale_transform; #ifndef COLLADA_IMPORT_SCALE_SCENE unit_scale_transform.scale(Vector3(state.unit_scale, state.unit_scale, state.unit_scale)); #endif @@ -74,8 +74,8 @@ static String _uri_to_id(const String &p_uri) { /** HELPER FUNCTIONS **/ -Transform Collada::fix_transform(const Transform &p_transform) { - Transform tr = p_transform; +Transform3D Collada::fix_transform(const Transform3D &p_transform) { + Transform3D tr = p_transform; #ifndef NO_UP_AXIS_SWAP @@ -102,8 +102,8 @@ Transform Collada::fix_transform(const Transform &p_transform) { //return state.matrix_fix * p_transform; } -static Transform _read_transform_from_array(const Vector<float> &array, int ofs = 0) { - Transform tr; +static Transform3D _read_transform_from_array(const Vector<float> &array, int ofs = 0) { + Transform3D tr; // i wonder why collada matrices are transposed, given that's opposed to opengl.. tr.basis.elements[0][0] = array[0 + ofs]; tr.basis.elements[0][1] = array[1 + ofs]; @@ -122,11 +122,11 @@ static Transform _read_transform_from_array(const Vector<float> &array, int ofs /* STRUCTURES */ -Transform Collada::Node::compute_transform(Collada &state) const { - Transform xform; +Transform3D Collada::Node::compute_transform(Collada &state) const { + Transform3D xform; for (int i = 0; i < xform_list.size(); i++) { - Transform xform_step; + Transform3D xform_step; const XForm &xf = xform_list[i]; switch (xf.op) { case XForm::OP_ROTATE: { @@ -165,11 +165,11 @@ Transform Collada::Node::compute_transform(Collada &state) const { return xform; } -Transform Collada::Node::get_transform() const { +Transform3D Collada::Node::get_transform() const { return default_transform; } -Transform Collada::Node::get_global_transform() const { +Transform3D Collada::Node::get_global_transform() const { if (parent) { return parent->get_global_transform() * default_transform; } else { @@ -201,14 +201,14 @@ Vector<float> Collada::AnimationTrack::get_value_at_time(float p_time) const { if (keys[i].data.size() == 16) { //interpolate a matrix - Transform src = _read_transform_from_array(keys[i - 1].data); - Transform dst = _read_transform_from_array(keys[i].data); + Transform3D src = _read_transform_from_array(keys[i - 1].data); + Transform3D dst = _read_transform_from_array(keys[i].data); - Transform interp = c < 0.001 ? src : src.interpolate_with(dst, c); + Transform3D interp = c < 0.001 ? src : src.interpolate_with(dst, c); Vector<float> ret; ret.resize(16); - Transform tr; + Transform3D tr; // i wonder why collada matrices are transposed, given that's opposed to opengl.. ret.write[0] = interp.basis.elements[0][0]; ret.write[1] = interp.basis.elements[0][1]; @@ -410,10 +410,9 @@ Vector<String> Collada::_read_string_array(XMLParser &parser) { return array; } -Transform Collada::_read_transform(XMLParser &parser) { - if (parser.is_empty()) { - return Transform(); - } +Transform3D Collada::_read_transform(XMLParser &parser) { + if (parser.is_empty()) + return Transform3D(); Vector<String> array; while (parser.read() == OK) { @@ -429,7 +428,7 @@ Transform Collada::_read_transform(XMLParser &parser) { } } - ERR_FAIL_COND_V(array.size() != 16, Transform()); + ERR_FAIL_COND_V(array.size() != 16, Transform3D()); Vector<float> farr; farr.resize(16); for (int i = 0; i < 16; i++) { @@ -1197,7 +1196,7 @@ void Collada::_parse_skin_controller(XMLParser &parser, String p_id) { /* STORE REST MATRICES */ - Vector<Transform> rests; + Vector<Transform3D> rests; ERR_FAIL_COND(!skindata.joints.sources.has("JOINT")); ERR_FAIL_COND(!skindata.joints.sources.has("INV_BIND_MATRIX")); @@ -1214,7 +1213,7 @@ void Collada::_parse_skin_controller(XMLParser &parser, String p_id) { for (int i = 0; i < joint_source.sarray.size(); i++) { String name = joint_source.sarray[i]; - Transform xform = _read_transform_from_array(ibm_source.array, i * 16); //<- this is a mistake, it must be applied to vertices + Transform3D xform = _read_transform_from_array(ibm_source.array, i * 16); //<- this is a mistake, it must be applied to vertices xform.affine_invert(); // inverse for rest, because it's an inverse #ifdef COLLADA_IMPORT_SCALE_SCENE xform.origin *= state.unit_scale; @@ -2096,7 +2095,7 @@ void Collada::_merge_skeletons2(VisualScene *p_vscene) { NodeSkeleton *skeleton = nullptr; - for (Map<String, Transform>::Element *F = cd.bone_rest_map.front(); F; F = F->next()) { + for (Map<String, Transform3D>::Element *F = cd.bone_rest_map.front(); F; F = F->next()) { String name; if (!state.sid_to_node_map.has(F->key())) { @@ -2240,11 +2239,11 @@ bool Collada::_move_geometry_to_skeletons(VisualScene *p_vscene, Node *p_node, L //this should be correct ERR_FAIL_COND_V(!state.skin_controller_data_map.has(ng->source), false); SkinControllerData &skin = state.skin_controller_data_map[ng->source]; - Transform skel_inv = sk->get_global_transform().affine_inverse(); + Transform3D skel_inv = sk->get_global_transform().affine_inverse(); p_node->default_transform = skel_inv * (skin.bind_shape /* p_node->get_global_transform()*/); // i honestly have no idea what to do with a previous model xform.. most exporters ignore it //make rests relative to the skeleton (they seem to be always relative to world) - for (Map<String, Transform>::Element *E = skin.bone_rest_map.front(); E; E = E->next()) { + for (Map<String, Transform3D>::Element *E = skin.bone_rest_map.front(); E; E = E->next()) { E->get() = skel_inv * E->get(); //make the bone rest local to the skeleton state.bone_rest_map[E->key()] = E->get(); // make it remember where the bone is globally, now that it's relative } @@ -2252,7 +2251,7 @@ bool Collada::_move_geometry_to_skeletons(VisualScene *p_vscene, Node *p_node, L //but most exporters seem to work only if i do this.. //p_node->default_transform = p_node->get_global_transform(); - //p_node->default_transform=Transform(); //this seems to be correct, because bind shape makes the object local to the skeleton + //p_node->default_transform=Transform3D(); //this seems to be correct, because bind shape makes the object local to the skeleton p_node->ignore_anim = true; // collada may animate this later, if it does, then this is not supported (redo your original asset and don't animate the base mesh) p_node->parent = sk; //sk->children.push_back(0,p_node); //avoid INFINITE loop diff --git a/editor/import/collada.h b/editor/import/collada.h index 2c3f0a3006..5e38637504 100644 --- a/editor/import/collada.h +++ b/editor/import/collada.h @@ -182,7 +182,7 @@ public: String base; bool use_idrefs = false; - Transform bind_shape; + Transform3D bind_shape; struct Source { Vector<String> sarray; //maybe for names @@ -210,7 +210,7 @@ public: int count = 0; } weights; - Map<String, Transform> bone_rest_map; + Map<String, Transform3D> bone_rest_map; SkinControllerData() {} }; @@ -342,15 +342,15 @@ public: String empty_draw_type; bool noname = false; Vector<XForm> xform_list; - Transform default_transform; - Transform post_transform; + Transform3D default_transform; + Transform3D post_transform; Vector<Node *> children; Node *parent = nullptr; - Transform compute_transform(Collada &state) const; - Transform get_global_transform() const; - Transform get_transform() const; + Transform3D compute_transform(Collada &state) const; + Transform3D get_global_transform() const; + Transform3D get_transform() const; bool ignore_anim = false; @@ -497,7 +497,7 @@ public: Map<String, String> sid_to_node_map; //Map<String,NodeJoint*> bone_map; - Map<String, Transform> bone_rest_map; + Map<String, Transform3D> bone_rest_map; String local_path; String root_visual_scene; @@ -517,9 +517,9 @@ public: Collada(); - Transform fix_transform(const Transform &p_transform); + Transform3D fix_transform(const Transform3D &p_transform); - Transform get_root_transform() const; + Transform3D get_root_transform() const; int get_uv_channel(String p_name); @@ -557,7 +557,7 @@ private: // private stuff Variant _parse_param(XMLParser &parser); Vector<float> _read_float_array(XMLParser &parser); Vector<String> _read_string_array(XMLParser &parser); - Transform _read_transform(XMLParser &parser); + Transform3D _read_transform(XMLParser &parser); String _read_empty_draw_type(XMLParser &parser); void _joint_set_owner(Collada::Node *p_node, NodeSkeleton *p_owner); diff --git a/editor/import/editor_import_collada.cpp b/editor/import/editor_import_collada.cpp index d3183e5a8d..54b93edcdd 100644 --- a/editor/import/editor_import_collada.cpp +++ b/editor/import/editor_import_collada.cpp @@ -87,7 +87,7 @@ struct ColladaImport { Error _create_scene(Collada::Node *p_node, Node3D *p_parent); Error _create_resources(Collada::Node *p_node, bool p_use_compression); Error _create_material(const String &p_target); - Error _create_mesh_surfaces(bool p_optimize, Ref<EditorSceneImporterMesh> &p_mesh, const Map<String, Collada::NodeGeometry::Material> &p_material_map, const Collada::MeshData &meshdata, const Transform &p_local_xform, const Vector<int> &bone_remap, const Collada::SkinControllerData *p_skin_controller, const Collada::MorphControllerData *p_morph_data, Vector<Ref<EditorSceneImporterMesh>> p_morph_meshes = Vector<Ref<EditorSceneImporterMesh>>(), bool p_use_compression = false, bool p_use_mesh_material = false); + Error _create_mesh_surfaces(bool p_optimize, Ref<EditorSceneImporterMesh> &p_mesh, const Map<String, Collada::NodeGeometry::Material> &p_material_map, const Collada::MeshData &meshdata, const Transform3D &p_local_xform, const Vector<int> &bone_remap, const Collada::SkinControllerData *p_skin_controller, const Collada::MorphControllerData *p_morph_data, Vector<Ref<EditorSceneImporterMesh>> p_morph_meshes = Vector<Ref<EditorSceneImporterMesh>>(), bool p_use_compression = false, bool p_use_mesh_material = false); Error load(const String &p_path, int p_flags, bool p_force_make_tangents = false, bool p_use_compression = false); void _fix_param_animation_tracks(); void create_animation(int p_clip, bool p_make_tracks_in_all_bones, bool p_import_value_tracks); @@ -300,7 +300,7 @@ Error ColladaImport::_create_scene(Collada::Node *p_node, Node3D *p_parent) { nm.node = node; node_map[p_node->id] = nm; node_name_map[node->get_name()] = p_node->id; - Transform xf = p_node->default_transform; + Transform3D xf = p_node->default_transform; xf = collada.fix_transform(xf) * p_node->post_transform; node->set_transform(xf); @@ -457,7 +457,7 @@ Error ColladaImport::_create_material(const String &p_target) { return OK; } -Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<EditorSceneImporterMesh> &p_mesh, const Map<String, Collada::NodeGeometry::Material> &p_material_map, const Collada::MeshData &meshdata, const Transform &p_local_xform, const Vector<int> &bone_remap, const Collada::SkinControllerData *p_skin_controller, const Collada::MorphControllerData *p_morph_data, Vector<Ref<EditorSceneImporterMesh>> p_morph_meshes, bool p_use_compression, bool p_use_mesh_material) { +Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<EditorSceneImporterMesh> &p_mesh, const Map<String, Collada::NodeGeometry::Material> &p_material_map, const Collada::MeshData &meshdata, const Transform3D &p_local_xform, const Vector<int> &bone_remap, const Collada::SkinControllerData *p_skin_controller, const Collada::MorphControllerData *p_morph_data, Vector<Ref<EditorSceneImporterMesh>> p_morph_meshes, bool p_use_compression, bool p_use_mesh_material) { bool local_xform_mirror = p_local_xform.basis.determinant() < 0; if (p_morph_data) { @@ -811,7 +811,7 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<EditorSceneImpor if (has_weights) { //if skeleton, localize - Transform local_xform = p_local_xform; + Transform3D local_xform = p_local_xform; for (int i = 0; i < vertex_array.size(); i++) { vertex_array.write[i].vertex = local_xform.xform(vertex_array[i].vertex); vertex_array.write[i].normal = local_xform.basis.xform(vertex_array[i].normal).normalized(); @@ -850,7 +850,7 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<EditorSceneImpor } Ref<SurfaceTool> surftool; - surftool.instance(); + surftool.instantiate(); surftool->begin(Mesh::PRIMITIVE_TRIANGLES); for (int k = 0; k < vertex_array.size(); k++) { @@ -894,8 +894,8 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<EditorSceneImpor surftool->add_vertex(vertex_array[k].vertex); } - for (List<int>::Element *E = indices_list.front(); E; E = E->next()) { - surftool->add_index(E->get()); + for (int &E : indices_list) { + surftool->add_index(E); } if (!normal_src) { @@ -1037,7 +1037,7 @@ Error ColladaImport::_create_resources(Collada::Node *p_node, bool p_use_compres Collada::SkinControllerData *skin = nullptr; Collada::MorphControllerData *morph = nullptr; String meshid; - Transform apply_xform; + Transform3D apply_xform; Vector<int> bone_remap; Vector<Ref<EditorSceneImporterMesh>> morphs; @@ -1073,9 +1073,9 @@ Error ColladaImport::_create_resources(Collada::Node *p_node, bool p_use_compres if (apply_mesh_xform_to_vertices) { apply_xform = collada.fix_transform(p_node->default_transform); - node->set_transform(Transform()); + node->set_transform(Transform3D()); } else { - apply_xform = Transform(); + apply_xform = Transform3D(); } ERR_FAIL_COND_V(!skin->weights.sources.has("JOINT"), ERR_INVALID_DATA); @@ -1414,7 +1414,7 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones //animation->set_loop(true); //create animation tracks - Vector<float> base_snapshots; + Vector<real_t> base_snapshots; float f = 0; float snapshot_interval = 1.0 / bake_fps; //should be customizable somewhere... @@ -1461,12 +1461,12 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones continue; } - animation->add_track(Animation::TYPE_TRANSFORM); + animation->add_track(Animation::TYPE_TRANSFORM3D); int track = animation->get_track_count() - 1; animation->track_set_path(track, path); animation->track_set_imported(track, true); //helps merging later - Vector<float> snapshots = base_snapshots; + Vector<real_t> snapshots = base_snapshots; if (nm.anim_tracks.size() == 1) { //use snapshot keys from anim track instead, because this was most likely exported baked @@ -1530,7 +1530,7 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones } } - Transform xform = cn->compute_transform(collada); + Transform3D xform = cn->compute_transform(collada); xform = collada.fix_transform(xform) * cn->post_transform; if (nm.bone >= 0) { @@ -1544,8 +1544,8 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones } Vector3 s = xform.basis.get_scale(); - bool singular_matrix = Math::is_equal_approx(s.x, 0.0f) || Math::is_equal_approx(s.y, 0.0f) || Math::is_equal_approx(s.z, 0.0f); - Quat q = singular_matrix ? Quat() : xform.basis.get_rotation_quat(); + bool singular_matrix = Math::is_zero_approx(s.x) || Math::is_zero_approx(s.y) || Math::is_zero_approx(s.z); + Quaternion q = singular_matrix ? Quaternion() : xform.basis.get_rotation_quaternion(); Vector3 l = xform.origin; animation->transform_track_insert_key(track, snapshots[i], l, q, s); @@ -1584,19 +1584,19 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones continue; } - animation->add_track(Animation::TYPE_TRANSFORM); + animation->add_track(Animation::TYPE_TRANSFORM3D); int track = animation->get_track_count() - 1; animation->track_set_path(track, path); animation->track_set_imported(track, true); //helps merging later - Transform xform = cn->compute_transform(collada); + Transform3D xform = cn->compute_transform(collada); xform = collada.fix_transform(xform) * cn->post_transform; xform = sk->get_bone_rest(nm.bone).affine_inverse() * xform; Vector3 s = xform.basis.get_scale(); - bool singular_matrix = Math::is_equal_approx(s.x, 0.0f) || Math::is_equal_approx(s.y, 0.0f) || Math::is_equal_approx(s.z, 0.0f); - Quat q = singular_matrix ? Quat() : xform.basis.get_rotation_quat(); + bool singular_matrix = Math::is_zero_approx(s.x) || Math::is_zero_approx(s.y) || Math::is_zero_approx(s.z); + Quaternion q = singular_matrix ? Quaternion() : xform.basis.get_rotation_quaternion(); Vector3 l = xform.origin; animation->transform_track_insert_key(track, 0, l, q, s); diff --git a/editor/import/editor_import_plugin.cpp b/editor/import/editor_import_plugin.cpp index 44aff874eb..8660289c40 100644 --- a/editor/import/editor_import_plugin.cpp +++ b/editor/import/editor_import_plugin.cpp @@ -35,63 +35,63 @@ EditorImportPlugin::EditorImportPlugin() { } String EditorImportPlugin::get_importer_name() const { - ERR_FAIL_COND_V(!(get_script_instance() && get_script_instance()->has_method("get_importer_name")), ""); - return get_script_instance()->call("get_importer_name"); + ERR_FAIL_COND_V(!(get_script_instance() && get_script_instance()->has_method("_get_importer_name")), ""); + return get_script_instance()->call("_get_importer_name"); } String EditorImportPlugin::get_visible_name() const { - ERR_FAIL_COND_V(!(get_script_instance() && get_script_instance()->has_method("get_visible_name")), ""); - return get_script_instance()->call("get_visible_name"); + ERR_FAIL_COND_V(!(get_script_instance() && get_script_instance()->has_method("_get_visible_name")), ""); + return get_script_instance()->call("_get_visible_name"); } void EditorImportPlugin::get_recognized_extensions(List<String> *p_extensions) const { - ERR_FAIL_COND(!(get_script_instance() && get_script_instance()->has_method("get_recognized_extensions"))); - Array extensions = get_script_instance()->call("get_recognized_extensions"); + ERR_FAIL_COND(!(get_script_instance() && get_script_instance()->has_method("_get_recognized_extensions"))); + Array extensions = get_script_instance()->call("_get_recognized_extensions"); for (int i = 0; i < extensions.size(); i++) { p_extensions->push_back(extensions[i]); } } String EditorImportPlugin::get_preset_name(int p_idx) const { - ERR_FAIL_COND_V(!(get_script_instance() && get_script_instance()->has_method("get_preset_name")), ""); - return get_script_instance()->call("get_preset_name", p_idx); + ERR_FAIL_COND_V(!(get_script_instance() && get_script_instance()->has_method("_get_preset_name")), ""); + return get_script_instance()->call("_get_preset_name", p_idx); } int EditorImportPlugin::get_preset_count() const { - ERR_FAIL_COND_V(!(get_script_instance() && get_script_instance()->has_method("get_preset_count")), 0); - return get_script_instance()->call("get_preset_count"); + ERR_FAIL_COND_V(!(get_script_instance() && get_script_instance()->has_method("_get_preset_count")), 0); + return get_script_instance()->call("_get_preset_count"); } String EditorImportPlugin::get_save_extension() const { - ERR_FAIL_COND_V(!(get_script_instance() && get_script_instance()->has_method("get_save_extension")), ""); - return get_script_instance()->call("get_save_extension"); + ERR_FAIL_COND_V(!(get_script_instance() && get_script_instance()->has_method("_get_save_extension")), ""); + return get_script_instance()->call("_get_save_extension"); } String EditorImportPlugin::get_resource_type() const { - ERR_FAIL_COND_V(!(get_script_instance() && get_script_instance()->has_method("get_resource_type")), ""); - return get_script_instance()->call("get_resource_type"); + ERR_FAIL_COND_V(!(get_script_instance() && get_script_instance()->has_method("_get_resource_type")), ""); + return get_script_instance()->call("_get_resource_type"); } float EditorImportPlugin::get_priority() const { - if (!(get_script_instance() && get_script_instance()->has_method("get_priority"))) { + if (!(get_script_instance() && get_script_instance()->has_method("_get_priority"))) { return ResourceImporter::get_priority(); } - return get_script_instance()->call("get_priority"); + return get_script_instance()->call("_get_priority"); } int EditorImportPlugin::get_import_order() const { - if (!(get_script_instance() && get_script_instance()->has_method("get_import_order"))) { + if (!(get_script_instance() && get_script_instance()->has_method("_get_import_order"))) { return ResourceImporter::get_import_order(); } - return get_script_instance()->call("get_import_order"); + return get_script_instance()->call("_get_import_order"); } void EditorImportPlugin::get_import_options(List<ResourceImporter::ImportOption> *r_options, int p_preset) const { - ERR_FAIL_COND(!(get_script_instance() && get_script_instance()->has_method("get_import_options"))); + ERR_FAIL_COND(!(get_script_instance() && get_script_instance()->has_method("_get_import_options"))); Array needed; needed.push_back("name"); needed.push_back("default_value"); - Array options = get_script_instance()->call("get_import_options", p_preset); + Array options = get_script_instance()->call("_get_import_options", p_preset); for (int i = 0; i < options.size(); i++) { Dictionary d = options[i]; ERR_FAIL_COND(!d.has_all(needed)); @@ -119,18 +119,18 @@ void EditorImportPlugin::get_import_options(List<ResourceImporter::ImportOption> } bool EditorImportPlugin::get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const { - ERR_FAIL_COND_V(!(get_script_instance() && get_script_instance()->has_method("get_option_visibility")), true); + ERR_FAIL_COND_V(!(get_script_instance() && get_script_instance()->has_method("_get_option_visibility")), true); Dictionary d; Map<StringName, Variant>::Element *E = p_options.front(); while (E) { d[E->key()] = E->get(); E = E->next(); } - return get_script_instance()->call("get_option_visibility", p_option, d); + return get_script_instance()->call("_get_option_visibility", p_option, d); } Error EditorImportPlugin::import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { - ERR_FAIL_COND_V(!(get_script_instance() && get_script_instance()->has_method("import")), ERR_UNAVAILABLE); + ERR_FAIL_COND_V(!(get_script_instance() && get_script_instance()->has_method("_import")), ERR_UNAVAILABLE); Dictionary options; Array platform_variants, gen_files; @@ -139,7 +139,7 @@ Error EditorImportPlugin::import(const String &p_source_file, const String &p_sa options[E->key()] = E->get(); E = E->next(); } - Error err = (Error)get_script_instance()->call("import", p_source_file, p_save_path, options, platform_variants, gen_files).operator int64_t(); + Error err = (Error)get_script_instance()->call("_import", p_source_file, p_save_path, options, platform_variants, gen_files).operator int64_t(); for (int i = 0; i < platform_variants.size(); i++) { r_platform_variants->push_back(platform_variants[i]); @@ -151,16 +151,16 @@ Error EditorImportPlugin::import(const String &p_source_file, const String &p_sa } void EditorImportPlugin::_bind_methods() { - ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::STRING, "get_importer_name")); - ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::STRING, "get_visible_name")); - ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::INT, "get_preset_count")); - ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::STRING, "get_preset_name", PropertyInfo(Variant::INT, "preset"))); - ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::ARRAY, "get_recognized_extensions")); - ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::ARRAY, "get_import_options", PropertyInfo(Variant::INT, "preset"))); - ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::STRING, "get_save_extension")); - ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::STRING, "get_resource_type")); - ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::FLOAT, "get_priority")); - ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::INT, "get_import_order")); - ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "get_option_visibility", PropertyInfo(Variant::STRING, "option"), PropertyInfo(Variant::DICTIONARY, "options"))); - ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::INT, "import", PropertyInfo(Variant::STRING, "source_file"), PropertyInfo(Variant::STRING, "save_path"), PropertyInfo(Variant::DICTIONARY, "options"), PropertyInfo(Variant::ARRAY, "platform_variants"), PropertyInfo(Variant::ARRAY, "gen_files"))); + BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_importer_name")); + BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_visible_name")); + BIND_VMETHOD(MethodInfo(Variant::INT, "_get_preset_count")); + BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_preset_name", PropertyInfo(Variant::INT, "preset"))); + BIND_VMETHOD(MethodInfo(Variant::ARRAY, "_get_recognized_extensions")); + BIND_VMETHOD(MethodInfo(Variant::ARRAY, "_get_import_options", PropertyInfo(Variant::INT, "preset"))); + BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_save_extension")); + BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_resource_type")); + BIND_VMETHOD(MethodInfo(Variant::FLOAT, "_get_priority")); + BIND_VMETHOD(MethodInfo(Variant::INT, "_get_import_order")); + BIND_VMETHOD(MethodInfo(Variant::BOOL, "_get_option_visibility", PropertyInfo(Variant::STRING, "option"), PropertyInfo(Variant::DICTIONARY, "options"))); + BIND_VMETHOD(MethodInfo(Variant::INT, "_import", PropertyInfo(Variant::STRING, "source_file"), PropertyInfo(Variant::STRING, "save_path"), PropertyInfo(Variant::DICTIONARY, "options"), PropertyInfo(Variant::ARRAY, "platform_variants"), PropertyInfo(Variant::ARRAY, "gen_files"))); } diff --git a/editor/import/editor_importer_bake_reset.cpp b/editor/import/editor_importer_bake_reset.cpp new file mode 100644 index 0000000000..00dce6850e --- /dev/null +++ b/editor/import/editor_importer_bake_reset.cpp @@ -0,0 +1,234 @@ +/*************************************************************************/ +/* editor_importer_bake_reset.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "editor/import/editor_importer_bake_reset.h" + +#include "core/error/error_list.h" +#include "core/error/error_macros.h" +#include "core/math/transform_3d.h" +#include "editor/import/scene_importer_mesh_node_3d.h" +#include "resource_importer_scene.h" +#include "scene/3d/mesh_instance_3d.h" +#include "scene/3d/node_3d.h" +#include "scene/3d/skeleton_3d.h" +#include "scene/animation/animation_player.h" + +// Given that an engineering team has made a reference character, one wants ten animators to create animations. +// Currently, a tech artist needs to combine the ten files into one exported gltf2 to import into Godot Engine. +// We bake the RESET animation and then set it to identity, +// so that rigs with corresponding RESET animation can have their animations transferred with ease. +// +// The original algorithm for the code was used to change skeleton bone rolls to be parent to child. +// +// Reference https://github.com/godotengine/godot-proposals/issues/2961 +void BakeReset::_bake_animation_pose(Node *scene, const String &p_bake_anim) { + Map<StringName, BakeResetRestBone> r_rest_bones; + Vector<Node3D *> r_meshes; + List<Node *> queue; + queue.push_back(scene); + while (!queue.is_empty()) { + List<Node *>::Element *E = queue.front(); + Node *node = E->get(); + AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(node); + // Step 1: import scene with animations into the rest bones data structure. + _fetch_reset_animation(ap, r_rest_bones, p_bake_anim); + + int child_count = node->get_child_count(); + for (int i = 0; i < child_count; i++) { + queue.push_back(node->get_child(i)); + } + queue.pop_front(); + } + + queue.push_back(scene); + while (!queue.is_empty()) { + List<Node *>::Element *E = queue.front(); + Node *node = E->get(); + EditorSceneImporterMeshNode3D *editor_mesh_3d = scene->cast_to<EditorSceneImporterMeshNode3D>(node); + MeshInstance3D *mesh_3d = scene->cast_to<MeshInstance3D>(node); + if (scene->cast_to<Skeleton3D>(node)) { + Skeleton3D *skeleton = Object::cast_to<Skeleton3D>(node); + + // Step 2: Bake the RESET animation from the RestBone to the skeleton. + _fix_skeleton(skeleton, r_rest_bones); + } + if (editor_mesh_3d) { + NodePath path = editor_mesh_3d->get_skeleton_path(); + if (!path.is_empty() && editor_mesh_3d->get_node_or_null(path) && Object::cast_to<Skeleton3D>(editor_mesh_3d->get_node_or_null(path))) { + r_meshes.push_back(editor_mesh_3d); + } + } else if (mesh_3d) { + NodePath path = mesh_3d->get_skeleton_path(); + if (!path.is_empty() && mesh_3d->get_node_or_null(path) && Object::cast_to<Skeleton3D>(mesh_3d->get_node_or_null(path))) { + r_meshes.push_back(mesh_3d); + } + } + int child_count = node->get_child_count(); + for (int i = 0; i < child_count; i++) { + queue.push_back(node->get_child(i)); + } + queue.pop_front(); + } + + queue.push_back(scene); + while (!queue.is_empty()) { + List<Node *>::Element *E = queue.front(); + Node *node = E->get(); + AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(node); + if (ap) { + // Step 3: Key all RESET animation frames to identity. + _align_animations(ap, r_rest_bones); + } + + int child_count = node->get_child_count(); + for (int i = 0; i < child_count; i++) { + queue.push_back(node->get_child(i)); + } + queue.pop_front(); + } +} + +void BakeReset::_align_animations(AnimationPlayer *p_ap, const Map<StringName, BakeResetRestBone> &r_rest_bones) { + ERR_FAIL_NULL(p_ap); + List<StringName> anim_names; + p_ap->get_animation_list(&anim_names); + for (List<StringName>::Element *anim_i = anim_names.front(); anim_i; anim_i = anim_i->next()) { + Ref<Animation> a = p_ap->get_animation(anim_i->get()); + ERR_CONTINUE(a.is_null()); + for (Map<StringName, BakeResetRestBone>::Element *rest_bone_i = r_rest_bones.front(); rest_bone_i; rest_bone_i = rest_bone_i->next()) { + int track = a->find_track(NodePath(rest_bone_i->key())); + if (track == -1) { + continue; + } + int new_track = a->add_track(Animation::TYPE_TRANSFORM3D); + NodePath new_path = NodePath(rest_bone_i->key()); + BakeResetRestBone rest_bone = rest_bone_i->get(); + a->track_set_path(new_track, new_path); + for (int key_i = 0; key_i < a->track_get_key_count(track); key_i++) { + Vector3 loc; + Quaternion rot; + Vector3 scale; + Error err = a->transform_track_get_key(track, key_i, &loc, &rot, &scale); + ERR_CONTINUE(err); + real_t time = a->track_get_key_time(track, key_i); + rot.normalize(); + loc = loc - rest_bone.loc; + rot = rest_bone.rest_delta.get_rotation_quaternion().inverse() * rot; + rot.normalize(); + scale = Vector3(1, 1, 1) - (rest_bone.rest_delta.get_scale() - scale); + // Apply the reverse of the rest changes to make the key be close to identity transform. + a->transform_track_insert_key(new_track, time, loc, rot, scale); + } + a->remove_track(track); + } + } +} + +void BakeReset::_fetch_reset_animation(AnimationPlayer *p_ap, Map<StringName, BakeResetRestBone> &r_rest_bones, const String &p_bake_anim) { + if (!p_ap) { + return; + } + List<StringName> anim_names; + p_ap->get_animation_list(&anim_names); + Node *root = p_ap->get_owner(); + ERR_FAIL_NULL(root); + if (!p_ap->has_animation(p_bake_anim)) { + return; + } + Ref<Animation> a = p_ap->get_animation(p_bake_anim); + if (a.is_null()) { + return; + } + for (int32_t track = 0; track < a->get_track_count(); track++) { + NodePath path = a->track_get_path(track); + String string_path = path; + Skeleton3D *skeleton = root->cast_to<Skeleton3D>(root->get_node(string_path.get_slice(":", 0))); + if (!skeleton) { + continue; + } + String bone_name = string_path.get_slice(":", 1); + for (int key_i = 0; key_i < a->track_get_key_count(track); key_i++) { + Vector3 loc; + Quaternion rot; + Vector3 scale; + Error err = a->transform_track_get_key(track, key_i, &loc, &rot, &scale); + if (err != OK) { + ERR_PRINT_ONCE("Reset animation baker can't get key."); + continue; + } + rot.normalize(); + Basis rot_basis = Basis(rot, scale); + BakeResetRestBone rest_bone; + rest_bone.rest_delta = rot_basis; + rest_bone.loc = loc; + // Store the animation into the RestBone. + r_rest_bones[StringName(String(skeleton->get_owner()->get_path_to(skeleton)) + ":" + bone_name)] = rest_bone; + break; + } + } +} + +void BakeReset::_fix_skeleton(Skeleton3D *p_skeleton, Map<StringName, BakeReset::BakeResetRestBone> &r_rest_bones) { + int bone_count = p_skeleton->get_bone_count(); + + // First iterate through all the bones and update the RestBone. + for (int j = 0; j < bone_count; j++) { + StringName final_path = String(p_skeleton->get_owner()->get_path_to(p_skeleton)) + String(":") + p_skeleton->get_bone_name(j); + BakeResetRestBone &rest_bone = r_rest_bones[final_path]; + rest_bone.rest_local = p_skeleton->get_bone_rest(j); + } + for (int i = 0; i < bone_count; i++) { + int parent_bone = p_skeleton->get_bone_parent(i); + String path = p_skeleton->get_owner()->get_path_to(p_skeleton); + StringName final_path = String(path) + String(":") + p_skeleton->get_bone_name(parent_bone); + if (parent_bone >= 0) { + r_rest_bones[path].children.push_back(i); + } + } + + // When we apply transform to a bone, we also have to move all of its children in the opposite direction. + for (int i = 0; i < bone_count; i++) { + StringName final_path = String(p_skeleton->get_owner()->get_path_to(p_skeleton)) + String(":") + p_skeleton->get_bone_name(i); + r_rest_bones[final_path].rest_local = r_rest_bones[final_path].rest_local * Transform3D(r_rest_bones[final_path].rest_delta, r_rest_bones[final_path].loc); + // Iterate through the children and move in the opposite direction. + for (int j = 0; j < r_rest_bones[final_path].children.size(); j++) { + int child_index = r_rest_bones[final_path].children[j]; + StringName children_path = String(p_skeleton->get_name()) + String(":") + p_skeleton->get_bone_name(child_index); + r_rest_bones[children_path].rest_local = Transform3D(r_rest_bones[final_path].rest_delta, r_rest_bones[final_path].loc).affine_inverse() * r_rest_bones[children_path].rest_local; + } + } + + for (int i = 0; i < bone_count; i++) { + StringName final_path = String(p_skeleton->get_owner()->get_path_to(p_skeleton)) + String(":") + p_skeleton->get_bone_name(i); + ERR_CONTINUE(!r_rest_bones.has(final_path)); + Transform3D rest_transform = r_rest_bones[final_path].rest_local; + p_skeleton->set_bone_rest(i, rest_transform); + } +} diff --git a/editor/import/editor_importer_bake_reset.h b/editor/import/editor_importer_bake_reset.h new file mode 100644 index 0000000000..e36ae86181 --- /dev/null +++ b/editor/import/editor_importer_bake_reset.h @@ -0,0 +1,54 @@ +/*************************************************************************/ +/* editor_importer_bake_reset.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef RESOURCE_IMPORTER_BAKE_RESET_H +#define RESOURCE_IMPORTER_BAKE_RESET_H + +#include "scene/main/node.h" + +class Skeleton3D; +class AnimationPlayer; +class BakeReset { + struct BakeResetRestBone { + Transform3D rest_local; + Basis rest_delta; + Vector3 loc; + Vector<int> children; + }; + +public: + void _bake_animation_pose(Node *scene, const String &p_bake_anim); + +private: + void _fix_skeleton(Skeleton3D *p_skeleton, Map<StringName, BakeReset::BakeResetRestBone> &r_rest_bones); + void _align_animations(AnimationPlayer *p_ap, const Map<StringName, BakeResetRestBone> &r_rest_bones); + void _fetch_reset_animation(AnimationPlayer *p_ap, Map<StringName, BakeResetRestBone> &r_rest_bones, const String &p_bake_anim); +}; +#endif diff --git a/editor/import/resource_importer_bitmask.cpp b/editor/import/resource_importer_bitmask.cpp index ffef759c07..7fd9230284 100644 --- a/editor/import/resource_importer_bitmask.cpp +++ b/editor/import/resource_importer_bitmask.cpp @@ -78,7 +78,7 @@ Error ResourceImporterBitMap::import(const String &p_source_file, const String & int create_from = p_options["create_from"]; float threshold = p_options["threshold"]; Ref<Image> image; - image.instance(); + image.instantiate(); Error err = ImageLoader::load_image(p_source_file, image); if (err != OK) { return err; @@ -88,7 +88,7 @@ Error ResourceImporterBitMap::import(const String &p_source_file, const String & int h = image->get_height(); Ref<BitMap> bitmap; - bitmap.instance(); + bitmap.instantiate(); bitmap->create(Size2(w, h)); for (int i = 0; i < h; i++) { diff --git a/editor/import/resource_importer_csv_translation.cpp b/editor/import/resource_importer_csv_translation.cpp index 4a4d9d8f06..07647d8b6a 100644 --- a/editor/import/resource_importer_csv_translation.cpp +++ b/editor/import/resource_importer_csv_translation.cpp @@ -30,8 +30,8 @@ #include "resource_importer_csv_translation.h" +#include "core/io/file_access.h" #include "core/io/resource_saver.h" -#include "core/os/file_access.h" #include "core/string/optimized_translation.h" #include "core/string/translation.h" @@ -104,7 +104,7 @@ Error ResourceImporterCSVTranslation::import(const String &p_source_file, const locales.push_back(locale); Ref<Translation> translation; - translation.instance(); + translation.instantiate(); translation->set_locale(locale); translations.push_back(translation); } diff --git a/editor/import/resource_importer_image.cpp b/editor/import/resource_importer_image.cpp index 26c6a8462b..2dea359188 100644 --- a/editor/import/resource_importer_image.cpp +++ b/editor/import/resource_importer_image.cpp @@ -30,9 +30,9 @@ #include "resource_importer_image.h" +#include "core/io/file_access.h" #include "core/io/image_loader.h" #include "core/io/resource_saver.h" -#include "core/os/file_access.h" #include "scene/resources/texture.h" String ResourceImporterImage::get_importer_name() const { @@ -75,7 +75,7 @@ Error ResourceImporterImage::import(const String &p_source_file, const String &p ERR_FAIL_COND_V_MSG(!f, ERR_CANT_OPEN, "Cannot open file from path '" + p_source_file + "'."); - size_t len = f->get_len(); + uint64_t len = f->get_length(); Vector<uint8_t> data; data.resize(len); diff --git a/editor/import/resource_importer_layered_texture.cpp b/editor/import/resource_importer_layered_texture.cpp index 6d2215c379..2ac8b8bd7d 100644 --- a/editor/import/resource_importer_layered_texture.cpp +++ b/editor/import/resource_importer_layered_texture.cpp @@ -186,7 +186,7 @@ void ResourceImporterLayeredTexture::_save_tex(Vector<Ref<Image>> p_images, cons for (int i = 0; i < mm_d; i++) { Ref<Image> mm; - mm.instance(); + mm.instantiate(); mm->create(mm_w, mm_h, false, p_images[0]->get_format()); Vector3 pos; pos.z = float(i) * float(d) / float(mm_d) + 0.5; @@ -328,7 +328,7 @@ Error ResourceImporterLayeredTexture::import(const String &p_source_file, const } Ref<Image> image; - image.instance(); + image.instantiate(); Error err = ImageLoader::load_image(p_source_file, image, nullptr, false, 1.0); if (err != OK) { return err; diff --git a/editor/import/resource_importer_obj.cpp b/editor/import/resource_importer_obj.cpp index dd62c72d8a..34bc0a7d8d 100644 --- a/editor/import/resource_importer_obj.cpp +++ b/editor/import/resource_importer_obj.cpp @@ -30,8 +30,8 @@ #include "resource_importer_obj.h" +#include "core/io/file_access.h" #include "core/io/resource_saver.h" -#include "core/os/file_access.h" #include "editor/import/scene_importer_mesh.h" #include "editor/import/scene_importer_mesh_node_3d.h" #include "scene/3d/mesh_instance_3d.h" @@ -57,7 +57,7 @@ static Error _parse_material_library(const String &p_path, Map<String, Ref<Stand //vertex current_name = l.replace("newmtl", "").strip_edges(); - current.instance(); + current.instantiate(); current->set_name(current_name); material_map[current_name] = current; } else if (l.begins_with("Ka ")) { @@ -126,7 +126,7 @@ static Error _parse_material_library(const String &p_path, Map<String, Ref<Stand String p = l.replace("map_Kd", "").replace("\\", "/").strip_edges(); String path; - if (p.is_abs_path()) { + if (p.is_absolute_path()) { path = p; } else { path = base_path.plus_file(p); @@ -146,7 +146,7 @@ static Error _parse_material_library(const String &p_path, Map<String, Ref<Stand String p = l.replace("map_Ks", "").replace("\\", "/").strip_edges(); String path; - if (p.is_abs_path()) { + if (p.is_absolute_path()) { path = p; } else { path = base_path.plus_file(p); @@ -166,7 +166,7 @@ static Error _parse_material_library(const String &p_path, Map<String, Ref<Stand String p = l.replace("map_Ns", "").replace("\\", "/").strip_edges(); String path; - if (p.is_abs_path()) { + if (p.is_absolute_path()) { path = p; } else { path = base_path.plus_file(p); @@ -207,7 +207,7 @@ static Error _parse_obj(const String &p_path, List<Ref<Mesh>> &r_meshes, bool p_ ERR_FAIL_COND_V_MSG(!f, ERR_CANT_OPEN, vformat("Couldn't open OBJ file '%s', it may not exist or not be readable.", p_path)); Ref<ArrayMesh> mesh; - mesh.instance(); + mesh.instantiate(); bool generate_tangents = p_generate_tangents; Vector3 scale_mesh = p_scale_mesh; @@ -378,7 +378,7 @@ static Error _parse_obj(const String &p_path, List<Ref<Mesh>> &r_meshes, bool p_ if (!p_single_mesh) { mesh->set_name(name); r_meshes.push_back(mesh); - mesh.instance(); + mesh.instantiate(); current_group = ""; current_material = ""; } @@ -438,17 +438,16 @@ Node *EditorOBJImporter::import_scene(const String &p_path, uint32_t p_flags, in Node3D *scene = memnew(Node3D); - for (List<Ref<Mesh>>::Element *E = meshes.front(); E; E = E->next()) { + for (const Ref<Mesh> &m : meshes) { Ref<EditorSceneImporterMesh> mesh; - mesh.instance(); - Ref<Mesh> m = E->get(); + mesh.instantiate(); for (int i = 0; i < m->get_surface_count(); i++) { mesh->add_surface(m->surface_get_primitive_type(i), m->surface_get_arrays(i), Array(), Dictionary(), m->surface_get_material(i)); } EditorSceneImporterMeshNode3D *mi = memnew(EditorSceneImporterMeshNode3D); mi->set_mesh(mesh); - mi->set_name(E->get()->get_name()); + mi->set_name(m->get_name()); scene->add_child(mi); mi->set_owner(scene); } diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index 4bb56beaeb..492fa3f965 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -32,6 +32,7 @@ #include "core/io/resource_saver.h" #include "editor/editor_node.h" +#include "editor/import/editor_importer_bake_reset.h" #include "editor/import/scene_import_settings.h" #include "editor/import/scene_importer_mesh_node_3d.h" #include "scene/3d/area_3d.h" @@ -44,7 +45,6 @@ #include "scene/resources/animation.h" #include "scene/resources/box_shape_3d.h" #include "scene/resources/packed_scene.h" -#include "scene/resources/ray_shape_3d.h" #include "scene/resources/resource_format_text.h" #include "scene/resources/sphere_shape_3d.h" #include "scene/resources/surface_tool.h" @@ -120,13 +120,13 @@ void EditorSceneImporter::_bind_methods() { ///////////////////////////////// void EditorScenePostImport::_bind_methods() { - BIND_VMETHOD(MethodInfo(Variant::OBJECT, "post_import", PropertyInfo(Variant::OBJECT, "scene"))); + BIND_VMETHOD(MethodInfo(Variant::OBJECT, "_post_import", PropertyInfo(Variant::OBJECT, "scene"))); ClassDB::bind_method(D_METHOD("get_source_file"), &EditorScenePostImport::get_source_file); } Node *EditorScenePostImport::post_import(Node *p_scene) { if (get_script_instance()) { - return get_script_instance()->call("post_import", p_scene); + return get_script_instance()->call("_post_import", p_scene); } return p_scene; @@ -233,21 +233,6 @@ static String _fixstr(const String &p_what, const String &p_str) { return what; } -static void _gen_shape_list(const Ref<Mesh> &mesh, List<Ref<Shape3D>> &r_shape_list, bool p_convex) { - ERR_FAIL_NULL_MSG(mesh, "Cannot generate shape list with null mesh value"); - if (!p_convex) { - Ref<Shape3D> shape = mesh->create_trimesh_shape(); - r_shape_list.push_back(shape); - } else { - Vector<Ref<Shape3D>> cd = mesh->convex_decompose(); - if (cd.size()) { - for (int i = 0; i < cd.size(); i++) { - r_shape_list.push_back(cd[i]); - } - } - } -} - static void _pre_gen_shape_list(const Ref<EditorSceneImporterMesh> &mesh, List<Ref<Shape3D>> &r_shape_list, bool p_convex) { ERR_FAIL_NULL_MSG(mesh, "Cannot generate shape list with null mesh value"); if (!p_convex) { @@ -312,8 +297,8 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<E List<StringName> anims; ap->get_animation_list(&anims); - for (List<StringName>::Element *E = anims.front(); E; E = E->next()) { - Ref<Animation> anim = ap->get_animation(E->get()); + for (const StringName &E : anims) { + Ref<Animation> anim = ap->get_animation(E); ERR_CONTINUE(anim.is_null()); for (int i = 0; i < anim->get_track_count(); i++) { NodePath path = anim->track_get_path(i); @@ -328,14 +313,14 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<E } } - String animname = E->get(); + String animname = E; const int loop_string_count = 3; static const char *loop_strings[loop_string_count] = { "loops", "loop", "cycle" }; for (int i = 0; i < loop_string_count; i++) { if (_teststr(animname, loop_strings[i])) { anim->set_loop(true); animname = _fixstr(animname, loop_strings[i]); - ap->rename_animation(E->get(), animname); + ap->rename_animation(E, animname); } } } @@ -395,11 +380,6 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<E BoxShape3D *boxShape = memnew(BoxShape3D); boxShape->set_size(Vector3(2, 2, 2)); colshape->set_shape(boxShape); - } else if (empty_draw_type == "SINGLE_ARROW") { - RayShape3D *rayShape = memnew(RayShape3D); - rayShape->set_length(1); - colshape->set_shape(rayShape); - Object::cast_to<Node3D>(sb)->rotate_x(Math_PI / 2); } else if (empty_draw_type == "IMAGE") { WorldMarginShape3D *world_margin_shape = memnew(WorldMarginShape3D); colshape->set_shape(world_margin_shape); @@ -425,7 +405,7 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<E if (collision_map.has(mesh)) { shapes = collision_map[mesh]; } else { - _gen_shape_list(mesh, shapes, true); + _pre_gen_shape_list(mesh, shapes, true); } RigidBody3D *rigid_body = memnew(RigidBody3D); @@ -433,7 +413,7 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<E p_node->replace_by(rigid_body); rigid_body->set_transform(mi->get_transform()); p_node = rigid_body; - mi->set_transform(Transform()); + mi->set_transform(Transform3D()); rigid_body->add_child(mi); mi->set_owner(rigid_body->get_owner()); @@ -451,10 +431,10 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<E if (collision_map.has(mesh)) { shapes = collision_map[mesh]; } else if (_teststr(name, "col")) { - _gen_shape_list(mesh, shapes, false); + _pre_gen_shape_list(mesh, shapes, false); collision_map[mesh] = shapes; } else if (_teststr(name, "convcol")) { - _gen_shape_list(mesh, shapes, true); + _pre_gen_shape_list(mesh, shapes, true); collision_map[mesh] = shapes; } @@ -509,11 +489,11 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<E if (collision_map.has(mesh)) { shapes = collision_map[mesh]; } else if (_teststr(mesh->get_name(), "col")) { - _gen_shape_list(mesh, shapes, false); + _pre_gen_shape_list(mesh, shapes, false); collision_map[mesh] = shapes; mesh->set_name(_fixstr(mesh->get_name(), "col")); } else if (_teststr(mesh->get_name(), "convcol")) { - _gen_shape_list(mesh, shapes, true); + _pre_gen_shape_list(mesh, shapes, true); collision_map[mesh] = shapes; mesh->set_name(_fixstr(mesh->get_name(), "convcol")); } @@ -632,7 +612,7 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref< p_node->replace_by(rigid_body); rigid_body->set_transform(mi->get_transform()); p_node = rigid_body; - mi->set_transform(Transform()); + mi->set_transform(Transform3D()); rigid_body->add_child(mi); mi->set_owner(rigid_body->get_owner()); base = rigid_body; @@ -659,9 +639,9 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref< } int idx = 0; - for (List<Ref<Shape3D>>::Element *E = shapes.front(); E; E = E->next()) { + for (const Ref<Shape3D> &E : shapes) { CollisionShape3D *cshape = memnew(CollisionShape3D); - cshape->set_shape(E->get()); + cshape->set_shape(E); base->add_child(cshape); cshape->set_owner(base->get_owner()); @@ -712,9 +692,9 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref< //fill node settings for this node with default values List<ImportOption> iopts; get_internal_import_options(INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE, &iopts); - for (List<ImportOption>::Element *E = iopts.front(); E; E = E->next()) { - if (!node_settings.has(E->get().option.name)) { - node_settings[E->get().option.name] = E->get().default_value; + for (const ImportOption &E : iopts) { + if (!node_settings.has(E.option.name)) { + node_settings[E.option.name] = E.default_value; } } } @@ -756,8 +736,7 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref< } else { List<StringName> anims; ap->get_animation_list(&anims); - for (List<StringName>::Element *E = anims.front(); E; E = E->next()) { - String name = E->get(); + for (const StringName &name : anims) { Ref<Animation> anim = ap->get_animation(name); if (p_animation_data.has(name)) { Dictionary anim_settings = p_animation_data[name]; @@ -765,9 +744,9 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref< //fill with default values List<ImportOption> iopts; get_internal_import_options(INTERNAL_IMPORT_CATEGORY_ANIMATION, &iopts); - for (List<ImportOption>::Element *F = iopts.front(); F; F = F->next()) { - if (!anim_settings.has(F->get().option.name)) { - anim_settings[F->get().option.name] = F->get().default_value; + for (const ImportOption &F : iopts) { + if (!anim_settings.has(F.option.name)) { + anim_settings[F.option.name] = F.default_value; } } } @@ -856,8 +835,8 @@ void ResourceImporterScene::_create_clips(AnimationPlayer *anim, const Array &p_ new_anim->track_set_path(dtrack, default_anim->track_get_path(j)); if (kt > (from + 0.01) && k > 0) { - if (default_anim->track_get_type(j) == Animation::TYPE_TRANSFORM) { - Quat q; + if (default_anim->track_get_type(j) == Animation::TYPE_TRANSFORM3D) { + Quaternion q; Vector3 p; Vector3 s; default_anim->transform_track_interpolate(j, from, &p, &q, &s); @@ -870,8 +849,8 @@ void ResourceImporterScene::_create_clips(AnimationPlayer *anim, const Array &p_ } } - if (default_anim->track_get_type(j) == Animation::TYPE_TRANSFORM) { - Quat q; + if (default_anim->track_get_type(j) == Animation::TYPE_TRANSFORM3D) { + Quaternion q; Vector3 p; Vector3 s; default_anim->transform_track_get_key(j, k, &p, &q, &s); @@ -884,8 +863,8 @@ void ResourceImporterScene::_create_clips(AnimationPlayer *anim, const Array &p_ } if (dtrack != -1 && kt >= to) { - if (default_anim->track_get_type(j) == Animation::TYPE_TRANSFORM) { - Quat q; + if (default_anim->track_get_type(j) == Animation::TYPE_TRANSFORM3D) { + Quaternion q; Vector3 p; Vector3 s; default_anim->transform_track_interpolate(j, to, &p, &q, &s); @@ -902,8 +881,8 @@ void ResourceImporterScene::_create_clips(AnimationPlayer *anim, const Array &p_ new_anim->add_track(default_anim->track_get_type(j)); dtrack = new_anim->get_track_count() - 1; new_anim->track_set_path(dtrack, default_anim->track_get_path(j)); - if (default_anim->track_get_type(j) == Animation::TYPE_TRANSFORM) { - Quat q; + if (default_anim->track_get_type(j) == Animation::TYPE_TRANSFORM3D) { + Quaternion q; Vector3 p; Vector3 s; default_anim->transform_track_interpolate(j, from, &p, &q, &s); @@ -936,8 +915,8 @@ void ResourceImporterScene::_create_clips(AnimationPlayer *anim, const Array &p_ void ResourceImporterScene::_optimize_animations(AnimationPlayer *anim, float p_max_lin_error, float p_max_ang_error, float p_max_angle) { List<StringName> anim_names; anim->get_animation_list(&anim_names); - for (List<StringName>::Element *E = anim_names.front(); E; E = E->next()) { - Ref<Animation> a = anim->get_animation(E->get()); + for (const StringName &E : anim_names) { + Ref<Animation> a = anim->get_animation(E); a->optimize(p_max_lin_error, p_max_ang_error, Math::deg2rad(p_max_angle)); } } @@ -1046,11 +1025,11 @@ void ResourceImporterScene::get_import_options(List<ImportOption> *r_options, in String script_ext_hint; - for (List<String>::Element *E = script_extentions.front(); E; E = E->next()) { + for (const String &E : script_extentions) { if (script_ext_hint != "") { script_ext_hint += ","; } - script_ext_hint += "*." + E->get(); + script_ext_hint += "*." + E; } r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "nodes/root_scale", PROPERTY_HINT_RANGE, "0.001,1000,0.001"), 1.0)); @@ -1061,6 +1040,7 @@ void ResourceImporterScene::get_import_options(List<ImportOption> *r_options, in r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "meshes/lightmap_texel_size", PROPERTY_HINT_RANGE, "0.001,100,0.001"), 0.1)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "skins/use_named_skins"), true)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "animation/import"), true)); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "animation/bake_reset_animation"), true)); r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "animation/fps", PROPERTY_HINT_RANGE, "1,120,1"), 15)); r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "import_script/path", PROPERTY_HINT_FILE, script_ext_hint), "")); @@ -1089,9 +1069,9 @@ Node *ResourceImporterScene::import_scene_from_other_importer(EditorSceneImporte List<String> extensions; E->get()->get_extensions(&extensions); - for (List<String>::Element *F = extensions.front(); F; F = F->next()) { - if (F->get().to_lower() == ext) { - importer = E->get(); + for (const String &F : extensions) { + if (F.to_lower() == ext) { + importer = E; break; } } @@ -1119,9 +1099,9 @@ Ref<Animation> ResourceImporterScene::import_animation_from_other_importer(Edito List<String> extensions; E->get()->get_extensions(&extensions); - for (List<String>::Element *F = extensions.front(); F; F = F->next()) { - if (F->get().to_lower() == ext) { - importer = E->get(); + for (const String &F : extensions) { + if (F.to_lower() == ext) { + importer = E; break; } } @@ -1136,7 +1116,7 @@ Ref<Animation> ResourceImporterScene::import_animation_from_other_importer(Edito return importer->import_animation(p_path, p_flags, p_bake_fps); } -void ResourceImporterScene::_generate_meshes(Node *p_node, const Dictionary &p_mesh_data, bool p_generate_lods, bool p_create_shadow_meshes, LightBakeMode p_light_bake_mode, float p_lightmap_texel_size, const Vector<uint8_t> &p_src_lightmap_cache, Vector<uint8_t> &r_dst_lightmap_cache) { +void ResourceImporterScene::_generate_meshes(Node *p_node, const Dictionary &p_mesh_data, bool p_generate_lods, bool p_create_shadow_meshes, LightBakeMode p_light_bake_mode, float p_lightmap_texel_size, const Vector<uint8_t> &p_src_lightmap_cache, Vector<Vector<uint8_t>> &r_lightmap_caches) { EditorSceneImporterMeshNode3D *src_mesh_node = Object::cast_to<EditorSceneImporterMeshNode3D>(p_node); if (src_mesh_node) { //is mesh @@ -1209,14 +1189,35 @@ void ResourceImporterScene::_generate_meshes(Node *p_node, const Dictionary &p_m } if (bake_lightmaps) { - Transform xf; + Transform3D xf; Node3D *n = src_mesh_node; while (n) { xf = n->get_transform() * xf; - n = n->get_parent_spatial(); + n = n->get_parent_node_3d(); } - //use xf as transform for mesh, and bake it + Vector<uint8_t> lightmap_cache; + src_mesh_node->get_mesh()->lightmap_unwrap_cached(xf, p_lightmap_texel_size, p_src_lightmap_cache, lightmap_cache); + + if (!lightmap_cache.is_empty()) { + if (r_lightmap_caches.is_empty()) { + r_lightmap_caches.push_back(lightmap_cache); + } else { + String new_md5 = String::md5(lightmap_cache.ptr()); // MD5 is stored at the beginning of the cache data + + for (int i = 0; i < r_lightmap_caches.size(); i++) { + String md5 = String::md5(r_lightmap_caches[i].ptr()); + if (new_md5 < md5) { + r_lightmap_caches.insert(i, lightmap_cache); + break; + } + + if (new_md5 == md5) { + break; + } + } + } + } } if (save_to_file != String()) { @@ -1265,14 +1266,14 @@ void ResourceImporterScene::_generate_meshes(Node *p_node, const Dictionary &p_m } for (int i = 0; i < p_node->get_child_count(); i++) { - _generate_meshes(p_node->get_child(i), p_mesh_data, p_generate_lods, p_create_shadow_meshes, p_light_bake_mode, p_lightmap_texel_size, p_src_lightmap_cache, r_dst_lightmap_cache); + _generate_meshes(p_node->get_child(i), p_mesh_data, p_generate_lods, p_create_shadow_meshes, p_light_bake_mode, p_lightmap_texel_size, p_src_lightmap_cache, r_lightmap_caches); } } void ResourceImporterScene::_add_shapes(Node *p_node, const List<Ref<Shape3D>> &p_shapes) { - for (const List<Ref<Shape3D>>::Element *E = p_shapes.front(); E; E = E->next()) { + for (const Ref<Shape3D> &E : p_shapes) { CollisionShape3D *cshape = memnew(CollisionShape3D); - cshape->set_shape(E->get()); + cshape->set_shape(E); p_node->add_child(cshape); cshape->set_owner(p_node->get_owner()); @@ -1290,8 +1291,8 @@ Node *ResourceImporterScene::pre_import(const String &p_source_file) { List<String> extensions; E->get()->get_extensions(&extensions); - for (List<String>::Element *F = extensions.front(); F; F = F->next()) { - if (F->get().to_lower() == ext) { + for (const String &F : extensions) { + if (F.to_lower() == ext) { importer = E->get(); break; } @@ -1330,8 +1331,8 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p List<String> extensions; E->get()->get_extensions(&extensions); - for (List<String>::Element *F = extensions.front(); F; F = F->next()) { - if (F->get().to_lower() == ext) { + for (const String &F : extensions) { + if (F.to_lower() == ext) { importer = E->get(); break; } @@ -1390,6 +1391,11 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p _pre_fix_node(scene, scene, collision_map); _post_fix_node(scene, scene, collision_map, scanned_meshes, node_data, material_data, animation_data, fps); + bool use_bake_reset_animation = p_options["animation/bake_reset_animation"]; + if (use_bake_reset_animation) { + BakeReset bake_reset; + bake_reset._bake_animation_pose(scene, "RESET"); + } String root_type = p_options["nodes/root_type"]; root_type = root_type.split(" ")[0]; // full root_type is "ClassName (filename.gd)" for a script global class. @@ -1401,7 +1407,7 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p } if (root_type != "Node3D") { - Node *base_node = Object::cast_to<Node>(ClassDB::instance(root_type)); + Node *base_node = Object::cast_to<Node>(ClassDB::instantiate(root_type)); if (base_node) { scene->replace_by(base_node); @@ -1433,7 +1439,7 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p float lightmap_texel_size = MAX(0.001, texel_size); Vector<uint8_t> src_lightmap_cache; - Vector<uint8_t> dst_lightmap_cache; + Vector<Vector<uint8_t>> mesh_lightmap_caches; { src_lightmap_cache = FileAccess::get_file_as_array(p_source_file + ".unwrap_cache", &err); @@ -1446,124 +1452,20 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p if (subresources.has("meshes")) { mesh_data = subresources["meshes"]; } - _generate_meshes(scene, mesh_data, gen_lods, create_shadow_meshes, LightBakeMode(light_bake_mode), lightmap_texel_size, src_lightmap_cache, dst_lightmap_cache); + _generate_meshes(scene, mesh_data, gen_lods, create_shadow_meshes, LightBakeMode(light_bake_mode), lightmap_texel_size, src_lightmap_cache, mesh_lightmap_caches); - if (dst_lightmap_cache.size()) { + if (mesh_lightmap_caches.size()) { FileAccessRef f = FileAccess::open(p_source_file + ".unwrap_cache", FileAccess::WRITE); if (f) { - f->store_buffer(dst_lightmap_cache.ptr(), dst_lightmap_cache.size()); - } - } - err = OK; - -#if 0 - if (light_bake_mode == 2 /* || generate LOD */) { - Map<Ref<ArrayMesh>, Transform> meshes; - _find_meshes(scene, meshes); - - String file_id = src_path.get_file(); - String cache_file_path = base_path.plus_file(file_id + ".unwrap_cache"); - - Vector<unsigned char> cache_data; - - if (FileAccess::exists(cache_file_path)) { - Error err2; - FileAccess *file = FileAccess::open(cache_file_path, FileAccess::READ, &err2); - - if (err2) { - if (file) { - memdelete(file); - } - } else { - int cache_size = file->get_len(); - cache_data.resize(cache_size); - file->get_buffer(cache_data.ptrw(), cache_size); - } - } - - Map<String, unsigned int> used_unwraps; - - EditorProgress progress2("gen_lightmaps", TTR("Generating Lightmaps"), meshes.size()); - int step = 0; - for (Map<Ref<ArrayMesh>, Transform>::Element *E = meshes.front(); E; E = E->next()) { - Ref<ArrayMesh> mesh = E->key(); - String name = mesh->get_name(); - if (name == "") { //should not happen but.. - name = "Mesh " + itos(step); - } - - progress2.step(TTR("Generating for Mesh: ") + name + " (" + itos(step) + "/" + itos(meshes.size()) + ")", step); - - int *ret_cache_data = (int *)cache_data.ptrw(); - unsigned int ret_cache_size = cache_data.size(); - bool ret_used_cache = true; // Tell the unwrapper to use the cache - Error err2 = mesh->lightmap_unwrap_cached(ret_cache_data, ret_cache_size, ret_used_cache, E->get(), texel_size); - - if (err2 != OK) { - EditorNode::add_io_error("Mesh '" + name + "' failed lightmap generation. Please fix geometry."); - } else { -` String hash = String::md5((unsigned char *)ret_cache_data); - used_unwraps.insert(hash, ret_cache_size); - - if (!ret_used_cache) { - // Cache was not used, add the generated entry to the current cache - if (cache_data.is_empty()) { - cache_data.resize(4 + ret_cache_size); - int *data = (int *)cache_data.ptrw(); - data[0] = 1; - memcpy(&data[1], ret_cache_data, ret_cache_size); - } else { - int current_size = cache_data.size(); - cache_data.resize(cache_data.size() + ret_cache_size); - unsigned char *ptrw = cache_data.ptrw(); - memcpy(&ptrw[current_size], ret_cache_data, ret_cache_size); - int *data = (int *)ptrw; - data[0] += 1; - } - } + f->store_32(mesh_lightmap_caches.size()); + for (int i = 0; i < mesh_lightmap_caches.size(); i++) { + String md5 = String::md5(mesh_lightmap_caches[i].ptr()); + f->store_buffer(mesh_lightmap_caches[i].ptr(), mesh_lightmap_caches[i].size()); } - step++; - } - - Error err2; - FileAccess *file = FileAccess::open(cache_file_path, FileAccess::WRITE, &err2); - - if (err2) { - if (file) { - memdelete(file); - } - } else { - // Store number of entries - file->store_32(used_unwraps.size()); - - // Store cache entries - const int *cache = (int *)cache_data.ptr(); - unsigned int r_idx = 1; - for (int i = 0; i < cache[0]; ++i) { - unsigned char *entry_start = (unsigned char *)&cache[r_idx]; - String entry_hash = String::md5(entry_start); - if (used_unwraps.has(entry_hash)) { - unsigned int entry_size = used_unwraps[entry_hash]; - file->store_buffer(entry_start, entry_size); - } - - r_idx += 4; // hash - r_idx += 2; // size hint - - int vertex_count = cache[r_idx]; - r_idx += 1; // vertex count - r_idx += vertex_count; // vertex - r_idx += vertex_count * 2; // uvs - - int index_count = cache[r_idx]; - r_idx += 1; // index count - r_idx += index_count; // indices - } - - file->close(); + f->close(); } } -#endif + err = OK; progress.step(TTR("Running Custom Script..."), 2); @@ -1591,7 +1493,7 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p if (!scene) { EditorNode::add_io_error( TTR("Error running post-import script:") + " " + post_import_script_path + "\n" + - TTR("Did you return a Node-derived object in the `post_import()` method?")); + TTR("Did you return a Node-derived object in the `_post_import()` method?")); return err; } } @@ -1640,7 +1542,7 @@ Node *EditorSceneImporterESCN::import_scene(const String &p_path, uint32_t p_fla Ref<PackedScene> ps = ResourceFormatLoaderText::singleton->load(p_path, p_path, &error); ERR_FAIL_COND_V_MSG(!ps.is_valid(), nullptr, "Cannot load scene as text resource from path '" + p_path + "'."); - Node *scene = ps->instance(); + Node *scene = ps->instantiate(); ERR_FAIL_COND_V(!scene, nullptr); return scene; diff --git a/editor/import/resource_importer_scene.h b/editor/import/resource_importer_scene.h index 00039f2ac6..781beff689 100644 --- a/editor/import/resource_importer_scene.h +++ b/editor/import/resource_importer_scene.h @@ -42,8 +42,8 @@ class Material; class AnimationPlayer; class EditorSceneImporterMesh; -class EditorSceneImporter : public Reference { - GDCLASS(EditorSceneImporter, Reference); +class EditorSceneImporter : public RefCounted { + GDCLASS(EditorSceneImporter, RefCounted); protected: static void _bind_methods(); @@ -69,8 +69,8 @@ public: EditorSceneImporter() {} }; -class EditorScenePostImport : public Reference { - GDCLASS(EditorScenePostImport, Reference); +class EditorScenePostImport : public RefCounted { + GDCLASS(EditorScenePostImport, RefCounted); String source_file; @@ -119,7 +119,7 @@ class ResourceImporterScene : public ResourceImporter { }; void _replace_owner(Node *p_node, Node *p_scene, Node *p_new_owner); - void _generate_meshes(Node *p_node, const Dictionary &p_mesh_data, bool p_generate_lods, bool p_create_shadow_meshes, LightBakeMode p_light_bake_mode, float p_lightmap_texel_size, const Vector<uint8_t> &p_src_lightmap_cache, Vector<uint8_t> &r_dst_lightmap_cache); + void _generate_meshes(Node *p_node, const Dictionary &p_mesh_data, bool p_generate_lods, bool p_create_shadow_meshes, LightBakeMode p_light_bake_mode, float p_lightmap_texel_size, const Vector<uint8_t> &p_src_lightmap_cache, Vector<Vector<uint8_t>> &r_lightmap_caches); void _add_shapes(Node *p_node, const List<Ref<Shape3D>> &p_shapes); public: @@ -155,7 +155,8 @@ public: virtual void get_import_options(List<ImportOption> *r_options, int p_preset = 0) const override; virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const override; - virtual int get_import_order() const override { return 100; } //after everything + // Import scenes *after* everything else (such as textures). + virtual int get_import_order() const override { return ResourceImporter::IMPORT_ORDER_SCENE; } Node *_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<EditorSceneImporterMesh>, List<Ref<Shape3D>>> &collision_map); Node *_post_fix_node(Node *p_node, Node *p_root, Map<Ref<EditorSceneImporterMesh>, List<Ref<Shape3D>>> &collision_map, Set<Ref<EditorSceneImporterMesh>> &r_scanned_meshes, const Dictionary &p_node_data, const Dictionary &p_material_data, const Dictionary &p_animation_data, float p_animation_fps); diff --git a/editor/import/resource_importer_shader_file.cpp b/editor/import/resource_importer_shader_file.cpp index f4d20a6296..4d92490675 100644 --- a/editor/import/resource_importer_shader_file.cpp +++ b/editor/import/resource_importer_shader_file.cpp @@ -30,9 +30,9 @@ #include "resource_importer_shader_file.h" +#include "core/io/file_access.h" #include "core/io/marshalls.h" #include "core/io/resource_saver.h" -#include "core/os/file_access.h" #include "editor/editor_node.h" #include "editor/plugins/shader_file_editor_plugin.h" #include "servers/rendering/rendering_device_binds.h" @@ -99,7 +99,7 @@ Error ResourceImporterShaderFile::import(const String &p_source_file, const Stri String file_txt = file->get_as_utf8_string(); Ref<RDShaderFile> shader_file; - shader_file.instance(); + shader_file.instantiate(); String base_path = p_source_file.get_base_dir(); err = shader_file->parse_versions_from_text(file_txt, "", _include_function, &base_path); diff --git a/editor/import/resource_importer_texture.cpp b/editor/import/resource_importer_texture.cpp index de8031af35..daf7b15794 100644 --- a/editor/import/resource_importer_texture.cpp +++ b/editor/import/resource_importer_texture.cpp @@ -88,7 +88,7 @@ void ResourceImporterTexture::update_imports() { for (Map<StringName, MakeInfo>::Element *E = make_flags.front(); E; E = E->next()) { Ref<ConfigFile> cf; - cf.instance(); + cf.instantiate(); String src_path = String(E->key()) + ".import"; Error err = cf->load(src_path); @@ -208,7 +208,7 @@ void ResourceImporterTexture::get_import_options(List<ImportOption> *r_options, r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "roughness/src_normal", PROPERTY_HINT_FILE, "*.bmp,*.dds,*.exr,*.jpeg,*.jpg,*.hdr,*.png,*.svg,*.svgz,*.tga,*.webp"), "")); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "process/fix_alpha_border"), p_preset != PRESET_3D)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "process/premult_alpha"), false)); - r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "process/invert_color"), false)); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "process/normal_map_invert_y"), false)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "process/HDR_as_SRGB"), false)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "process/size_limit", PROPERTY_HINT_RANGE, "0,4096,1"), 0)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "detect_3d/compress_to", PROPERTY_HINT_ENUM, "Disabled,VRAM Compressed,Basis Universal"), (p_preset == PRESET_DETECT) ? 1 : 0)); @@ -218,14 +218,21 @@ void ResourceImporterTexture::get_import_options(List<ImportOption> *r_options, void ResourceImporterTexture::save_to_stex_format(FileAccess *f, const Ref<Image> &p_image, CompressMode p_compress_mode, Image::UsedChannels p_channels, Image::CompressMode p_compress_format, float p_lossy_quality) { switch (p_compress_mode) { case COMPRESS_LOSSLESS: { - f->store_32(StreamTexture2D::DATA_FORMAT_LOSSLESS); + bool lossless_force_png = ProjectSettings::get_singleton()->get("rendering/textures/lossless_compression/force_png"); + bool use_webp = !lossless_force_png && p_image->get_width() <= 16383 && p_image->get_height() <= 16383; // WebP has a size limit + f->store_32(use_webp ? StreamTexture2D::DATA_FORMAT_WEBP : StreamTexture2D::DATA_FORMAT_PNG); f->store_16(p_image->get_width()); f->store_16(p_image->get_height()); f->store_32(p_image->get_mipmap_count()); f->store_32(p_image->get_format()); for (int i = 0; i < p_image->get_mipmap_count() + 1; i++) { - Vector<uint8_t> data = Image::lossless_packer(p_image->get_image_from_mipmap(i)); + Vector<uint8_t> data; + if (use_webp) { + data = Image::webp_lossless_packer(p_image->get_image_from_mipmap(i)); + } else { + data = Image::png_packer(p_image->get_image_from_mipmap(i)); + } int data_len = data.size(); f->store_32(data_len); @@ -235,14 +242,14 @@ void ResourceImporterTexture::save_to_stex_format(FileAccess *f, const Ref<Image } break; case COMPRESS_LOSSY: { - f->store_32(StreamTexture2D::DATA_FORMAT_LOSSY); + f->store_32(StreamTexture2D::DATA_FORMAT_WEBP); f->store_16(p_image->get_width()); f->store_16(p_image->get_height()); f->store_32(p_image->get_mipmap_count()); f->store_32(p_image->get_format()); for (int i = 0; i < p_image->get_mipmap_count() + 1; i++) { - Vector<uint8_t> data = Image::lossy_packer(p_image->get_image_from_mipmap(i), p_lossy_quality); + Vector<uint8_t> data = Image::webp_lossy_packer(p_image->get_image_from_mipmap(i), p_lossy_quality); int data_len = data.size(); f->store_32(data_len); @@ -301,6 +308,7 @@ void ResourceImporterTexture::save_to_stex_format(FileAccess *f, const Ref<Image void ResourceImporterTexture::_save_stex(const Ref<Image> &p_image, const String &p_to_path, CompressMode p_compress_mode, float p_lossy_quality, Image::CompressMode p_vram_compression, bool p_mipmaps, bool p_streamable, bool p_detect_3d, bool p_detect_roughness, bool p_detect_normal, bool p_force_normal, bool p_srgb_friendly, bool p_force_po2_for_compressed, uint32_t p_limit_mipmap, const Ref<Image> &p_normal, Image::RoughnessChannel p_roughness_channel) { FileAccess *f = FileAccess::open(p_to_path, FileAccess::WRITE); + ERR_FAIL_NULL(f); f->store_8('G'); f->store_8('S'); f->store_8('T'); @@ -388,7 +396,7 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String uint32_t mipmap_limit = int(mipmaps ? int(p_options["mipmaps/limit"]) : int(-1)); bool fix_alpha_border = p_options["process/fix_alpha_border"]; bool premult_alpha = p_options["process/premult_alpha"]; - bool invert_color = p_options["process/invert_color"]; + bool normal_map_invert_y = p_options["process/normal_map_invert_y"]; bool stream = p_options["compress/streamed"]; int size_limit = p_options["process/size_limit"]; bool hdr_as_srgb = p_options["process/HDR_as_SRGB"]; @@ -403,13 +411,13 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String Image::RoughnessChannel roughness_channel = Image::ROUGHNESS_CHANNEL_R; if (mipmaps && roughness > 1 && FileAccess::exists(normal_map)) { - normal_image.instance(); + normal_image.instantiate(); if (ImageLoader::load_image(normal_map, normal_image) == OK) { roughness_channel = Image::RoughnessChannel(roughness - 2); } } Ref<Image> image; - image.instance(); + image.instantiate(); Error err = ImageLoader::load_image(p_source_file, image, nullptr, hdr_as_srgb, scale); if (err != OK) { return err; @@ -444,13 +452,18 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String image->premultiply_alpha(); } - if (invert_color) { - int height = image->get_height(); - int width = image->get_width(); + if (normal_map_invert_y) { + // Inverting the green channel can be used to flip a normal map's direction. + // There's no standard when it comes to normal map Y direction, so this is + // sometimes needed when using a normal map exported from another program. + // See <http://wiki.polycount.com/wiki/Normal_Map_Technical_Details#Common_Swizzle_Coordinates>. + const int height = image->get_height(); + const int width = image->get_width(); for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { - image->set_pixel(i, j, image->get_pixel(i, j).inverted()); + const Color color = image->get_pixel(i, j); + image->set_pixel(i, j, Color(color.r, 1 - color.g, color.b)); } } } diff --git a/editor/import/resource_importer_texture.h b/editor/import/resource_importer_texture.h index 0d551a965c..41220009cd 100644 --- a/editor/import/resource_importer_texture.h +++ b/editor/import/resource_importer_texture.h @@ -31,9 +31,9 @@ #ifndef RESOURCEIMPORTTEXTURE_H #define RESOURCEIMPORTTEXTURE_H +#include "core/io/file_access.h" #include "core/io/image.h" #include "core/io/resource_importer.h" -#include "core/os/file_access.h" #include "scene/resources/texture.h" #include "servers/rendering_server.h" diff --git a/editor/import/resource_importer_texture_atlas.cpp b/editor/import/resource_importer_texture_atlas.cpp index 4c3ae59951..dec1466da1 100644 --- a/editor/import/resource_importer_texture_atlas.cpp +++ b/editor/import/resource_importer_texture_atlas.cpp @@ -31,10 +31,10 @@ #include "resource_importer_texture_atlas.h" #include "atlas_import_failed.xpm" +#include "core/io/file_access.h" #include "core/io/image_loader.h" #include "core/io/resource_saver.h" #include "core/math/geometry_2d.h" -#include "core/os/file_access.h" #include "editor/editor_atlas_packer.h" #include "scene/resources/mesh.h" #include "scene/resources/texture.h" @@ -87,7 +87,7 @@ Error ResourceImporterTextureAtlas::import(const String &p_source_file, const St //it's a simple hack Ref<Image> broken = memnew(Image((const char **)atlas_import_failed_xpm)); Ref<ImageTexture> broken_texture; - broken_texture.instance(); + broken_texture.instantiate(); broken_texture->create_from_image(broken); String target_file = p_save_path + ".tex"; @@ -201,7 +201,7 @@ Error ResourceImporterTextureAtlas::import_group_file(const String &p_group_file const Map<StringName, Variant> &options = E->get(); Ref<Image> image; - image.instance(); + image.instantiate(); Error err = ImageLoader::load_image(source, image); ERR_CONTINUE(err != OK); @@ -240,7 +240,7 @@ Error ResourceImporterTextureAtlas::import_group_file(const String &p_group_file pack_data.is_mesh = true; Ref<BitMap> bit_map; - bit_map.instance(); + bit_map.instantiate(); bit_map->create_from_image_alpha(image); Vector<Vector<Vector2>> polygons = bit_map->clip_opaque_to_polygons(Rect2(0, 0, image->get_width(), image->get_height())); @@ -272,7 +272,7 @@ Error ResourceImporterTextureAtlas::import_group_file(const String &p_group_file //blit the atlas Ref<Image> new_atlas; - new_atlas.instance(); + new_atlas.instantiate(); new_atlas->create(atlas_width, atlas_height, false, Image::FORMAT_RGBA8); for (int i = 0; i < pack_data_files.size(); i++) { @@ -303,7 +303,7 @@ Error ResourceImporterTextureAtlas::import_group_file(const String &p_group_file cache.reference_ptr(resptr); } else { Ref<ImageTexture> res_cache; - res_cache.instance(); + res_cache.instantiate(); res_cache->create_from_image(new_atlas); res_cache->set_path(p_group_file); cache = res_cache; @@ -321,7 +321,7 @@ Error ResourceImporterTextureAtlas::import_group_file(const String &p_group_file //region Ref<AtlasTexture> atlas_texture; - atlas_texture.instance(); + atlas_texture.instantiate(); atlas_texture->set_atlas(cache); atlas_texture->set_region(Rect2(offset, pack_data.region.size)); atlas_texture->set_margin(Rect2(pack_data.region.position, Size2(pack_data.image->get_width(), pack_data.image->get_height()) - pack_data.region.size)); @@ -329,7 +329,7 @@ Error ResourceImporterTextureAtlas::import_group_file(const String &p_group_file texture = atlas_texture; } else { Ref<ArrayMesh> mesh; - mesh.instance(); + mesh.instantiate(); for (int i = 0; i < pack_data.chart_pieces.size(); i++) { const EditorAtlasPacker::Chart &chart = charts[pack_data.chart_pieces[i]]; @@ -375,7 +375,7 @@ Error ResourceImporterTextureAtlas::import_group_file(const String &p_group_file } Ref<MeshTexture> mesh_texture; - mesh_texture.instance(); + mesh_texture.instantiate(); mesh_texture->set_base_texture(cache); mesh_texture->set_image_size(pack_data.image->get_size()); mesh_texture->set_mesh(mesh); diff --git a/editor/import/resource_importer_wav.cpp b/editor/import/resource_importer_wav.cpp index bcc55b330b..2db1db9e51 100644 --- a/editor/import/resource_importer_wav.cpp +++ b/editor/import/resource_importer_wav.cpp @@ -30,9 +30,9 @@ #include "resource_importer_wav.h" +#include "core/io/file_access.h" #include "core/io/marshalls.h" #include "core/io/resource_saver.h" -#include "core/os/file_access.h" #include "scene/resources/audio_stream_sample.h" const float TRIM_DB_LIMIT = -50; @@ -78,7 +78,7 @@ void ResourceImporterWAV::get_import_options(List<ImportOption> *r_options, int r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "force/8_bit"), false)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "force/mono"), false)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "force/max_rate", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false)); - r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "force/max_rate_hz", PROPERTY_HINT_EXP_RANGE, "11025,192000,1"), 44100)); + r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "force/max_rate_hz", PROPERTY_HINT_RANGE, "11025,192000,1,exp"), 44100)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "edit/trim"), false)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "edit/normalize"), false)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "edit/loop"), false)); @@ -508,7 +508,7 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s } Ref<AudioStreamSample> sample; - sample.instance(); + sample.instantiate(); sample->set_data(dst_data); sample->set_format(dst_format); sample->set_mix_rate(rate); diff --git a/editor/import/scene_import_settings.cpp b/editor/import/scene_import_settings.cpp index 48340ac242..19a8f209bb 100644 --- a/editor/import/scene_import_settings.cpp +++ b/editor/import/scene_import_settings.cpp @@ -71,9 +71,9 @@ class SceneImportSettingsData : public Object { return false; } void _get_property_list(List<PropertyInfo> *p_list) const { - for (const List<ResourceImporter::ImportOption>::Element *E = options.front(); E; E = E->next()) { - if (ResourceImporterScene::get_singleton()->get_internal_option_visibility(category, E->get().option.name, current)) { - p_list->push_back(E->get().option); + for (const ResourceImporter::ImportOption &E : options) { + if (ResourceImporterScene::get_singleton()->get_internal_option_visibility(category, E.option.name, current)) { + p_list->push_back(E.option); } } } @@ -105,7 +105,7 @@ void SceneImportSettings::_fill_material(Tree *p_tree, const Ref<Material> &p_ma MaterialData &material_data = material_map[import_id]; - Ref<Texture2D> icon = get_theme_icon("StandardMaterial3D", "EditorIcons"); + Ref<Texture2D> icon = get_theme_icon(SNAME("StandardMaterial3D"), SNAME("EditorIcons")); TreeItem *item = p_tree->create_item(p_parent); item->set_text(0, p_material->get_name()); @@ -161,7 +161,7 @@ void SceneImportSettings::_fill_mesh(Tree *p_tree, const Ref<Mesh> &p_mesh, Tree MeshData &mesh_data = mesh_map[import_id]; - Ref<Texture2D> icon = get_theme_icon("Mesh", "EditorIcons"); + Ref<Texture2D> icon = get_theme_icon(SNAME("Mesh"), SNAME("EditorIcons")); TreeItem *item = p_tree->create_item(p_parent); item->set_text(0, p_mesh->get_name()); @@ -211,7 +211,7 @@ void SceneImportSettings::_fill_animation(Tree *p_tree, const Ref<Animation> &p_ AnimationData &animation_data = animation_map[p_name]; - Ref<Texture2D> icon = get_theme_icon("Animation", "EditorIcons"); + Ref<Texture2D> icon = get_theme_icon(SNAME("Animation"), SNAME("EditorIcons")); TreeItem *item = p_tree->create_item(p_parent); item->set_text(0, p_name); @@ -255,17 +255,17 @@ void SceneImportSettings::_fill_scene(Node *p_node, TreeItem *p_parent_item) { String type = p_node->get_class(); - if (!has_theme_icon(type, "EditorIcons")) { + if (!has_theme_icon(type, SNAME("EditorIcons"))) { type = "Node3D"; } - Ref<Texture2D> icon = get_theme_icon(type, "EditorIcons"); + Ref<Texture2D> icon = get_theme_icon(type, SNAME("EditorIcons")); TreeItem *item = scene_tree->create_item(p_parent_item); item->set_text(0, p_node->get_name()); if (p_node == scene) { - icon = get_theme_icon("PackedScene", "EditorIcons"); + icon = get_theme_icon(SNAME("PackedScene"), SNAME("EditorIcons")); item->set_text(0, "Scene"); } @@ -305,8 +305,8 @@ void SceneImportSettings::_fill_scene(Node *p_node, TreeItem *p_parent_item) { if (anim_node) { List<StringName> animations; anim_node->get_animation_list(&animations); - for (List<StringName>::Element *E = animations.front(); E; E = E->next()) { - _fill_animation(scene_tree, anim_node->get_animation(E->get()), E->get(), item); + for (const StringName &E : animations) { + _fill_animation(scene_tree, anim_node->get_animation(E), E, item); } } @@ -317,7 +317,7 @@ void SceneImportSettings::_fill_scene(Node *p_node, TreeItem *p_parent_item) { if (mesh_node && mesh_node->get_mesh().is_valid()) { _fill_mesh(scene_tree, mesh_node->get_mesh(), item); - Transform accum_xform; + Transform3D accum_xform; Node3D *base = mesh_node; while (base) { accum_xform = base->get_transform() * accum_xform; @@ -339,7 +339,7 @@ void SceneImportSettings::_update_scene() { material_tree->clear(); mesh_tree->clear(); - //hiden roots + //hidden roots material_tree->create_item(); mesh_tree->create_item(); @@ -379,7 +379,7 @@ void SceneImportSettings::_update_camera() { camera->set_orthogonal(camera_size * zoom, 0.0001, camera_size * 2); - Transform xf; + Transform3D xf; xf.basis = Basis(Vector3(0, 1, 0), rot_y) * Basis(Vector3(1, 0, 0), rot_x); xf.origin = center; xf.translate(0, 0, camera_size); @@ -394,8 +394,8 @@ void SceneImportSettings::_load_default_subresource_settings(Map<StringName, Var d = d[p_import_id]; List<ResourceImporterScene::ImportOption> options; ResourceImporterScene::get_singleton()->get_internal_import_options(p_category, &options); - for (List<ResourceImporterScene::ImportOption>::Element *E = options.front(); E; E = E->next()) { - String key = E->get().option.name; + for (const ResourceImporterScene::ImportOption &E : options) { + String key = E.option.name; if (d.has(key)) { settings[key] = d[key]; } @@ -435,17 +435,17 @@ void SceneImportSettings::open_settings(const String &p_path) { base_subresource_settings.clear(); Ref<ConfigFile> config; - config.instance(); + config.instantiate(); Error err = config->load(p_path + ".import"); if (err == OK) { List<String> keys; config->get_section_keys("params", &keys); - for (List<String>::Element *E = keys.front(); E; E = E->next()) { - Variant value = config->get_value("params", E->get()); - if (E->get() == "_subresources") { + for (const String &E : keys) { + Variant value = config->get_value("params", E); + if (E == "_subresources") { base_subresource_settings = value; } else { - defaults[E->get()] = value; + defaults[E] = value; } } } @@ -493,7 +493,7 @@ void SceneImportSettings::_select(Tree *p_from, String p_type, String p_id) { Ref<Mesh> base_mesh = mi->get_mesh(); if (base_mesh.is_valid()) { AABB aabb = base_mesh->get_aabb(); - Transform aabb_xf; + Transform3D aabb_xf; aabb_xf.basis.scale(aabb.size); aabb_xf.origin = aabb.position; @@ -605,13 +605,13 @@ void SceneImportSettings::_select(Tree *p_from, String p_type, String p_id) { scene_import_settings_data->defaults.clear(); scene_import_settings_data->current.clear(); - for (List<ResourceImporter::ImportOption>::Element *E = options.front(); E; E = E->next()) { - scene_import_settings_data->defaults[E->get().option.name] = E->get().default_value; + for (const ResourceImporter::ImportOption &E : options) { + scene_import_settings_data->defaults[E.option.name] = E.default_value; //needed for visibility toggling (fails if something is missing) - if (scene_import_settings_data->settings->has(E->get().option.name)) { - scene_import_settings_data->current[E->get().option.name] = (*scene_import_settings_data->settings)[E->get().option.name]; + if (scene_import_settings_data->settings->has(E.option.name)) { + scene_import_settings_data->current[E.option.name] = (*scene_import_settings_data->settings)[E.option.name]; } else { - scene_import_settings_data->current[E->get().option.name] = E->get().default_value; + scene_import_settings_data->current[E.option.name] = E.default_value; } } scene_import_settings_data->options = options; @@ -795,11 +795,11 @@ void SceneImportSettings::_save_path_changed(const String &p_path) { if (FileAccess::exists(p_path)) { save_path_item->set_text(2, "Warning: File exists"); save_path_item->set_tooltip(2, TTR("Existing file with the same name will be replaced.")); - save_path_item->set_icon(2, get_theme_icon("StatusWarning", "EditorIcons")); + save_path_item->set_icon(2, get_theme_icon(SNAME("StatusWarning"), SNAME("EditorIcons"))); } else { save_path_item->set_text(2, "Will create new File"); - save_path_item->set_icon(2, get_theme_icon("StatusSuccess", "EditorIcons")); + save_path_item->set_icon(2, get_theme_icon(SNAME("StatusSuccess"), SNAME("EditorIcons"))); } } @@ -829,7 +829,7 @@ void SceneImportSettings::_save_dir_callback(const String &p_path) { String name = md.material_node->get_text(0); item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK); - item->set_icon(0, get_theme_icon("StandardMaterial3D", "EditorIcons")); + item->set_icon(0, get_theme_icon(SNAME("StandardMaterial3D"), SNAME("EditorIcons"))); item->set_text(0, name); if (md.has_import_id) { @@ -851,20 +851,20 @@ void SceneImportSettings::_save_dir_callback(const String &p_path) { if (FileAccess::exists(path)) { item->set_text(2, "Warning: File exists"); item->set_tooltip(2, TTR("Existing file with the same name will be replaced.")); - item->set_icon(2, get_theme_icon("StatusWarning", "EditorIcons")); + item->set_icon(2, get_theme_icon(SNAME("StatusWarning"), SNAME("EditorIcons"))); } else { item->set_text(2, "Will create new File"); - item->set_icon(2, get_theme_icon("StatusSuccess", "EditorIcons")); + item->set_icon(2, get_theme_icon(SNAME("StatusSuccess"), SNAME("EditorIcons"))); } - item->add_button(1, get_theme_icon("Folder", "EditorIcons")); + item->add_button(1, get_theme_icon(SNAME("Folder"), SNAME("EditorIcons"))); } } else { item->set_text(2, "No import ID"); item->set_tooltip(2, TTR("Material has no name nor any other way to identify on re-import.\nPlease name it or ensure it is exported with an unique ID.")); - item->set_icon(2, get_theme_icon("StatusError", "EditorIcons")); + item->set_icon(2, get_theme_icon(SNAME("StatusError"), SNAME("EditorIcons"))); } save_path_items.push_back(item); @@ -882,7 +882,7 @@ void SceneImportSettings::_save_dir_callback(const String &p_path) { String name = md.mesh_node->get_text(0); item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK); - item->set_icon(0, get_theme_icon("Mesh", "EditorIcons")); + item->set_icon(0, get_theme_icon(SNAME("Mesh"), SNAME("EditorIcons"))); item->set_text(0, name); if (md.has_import_id) { @@ -904,20 +904,20 @@ void SceneImportSettings::_save_dir_callback(const String &p_path) { if (FileAccess::exists(path)) { item->set_text(2, "Warning: File exists"); item->set_tooltip(2, TTR("Existing file with the same name will be replaced on import.")); - item->set_icon(2, get_theme_icon("StatusWarning", "EditorIcons")); + item->set_icon(2, get_theme_icon(SNAME("StatusWarning"), SNAME("EditorIcons"))); } else { item->set_text(2, "Will save to new File"); - item->set_icon(2, get_theme_icon("StatusSuccess", "EditorIcons")); + item->set_icon(2, get_theme_icon(SNAME("StatusSuccess"), SNAME("EditorIcons"))); } - item->add_button(1, get_theme_icon("Folder", "EditorIcons")); + item->add_button(1, get_theme_icon(SNAME("Folder"), SNAME("EditorIcons"))); } } else { item->set_text(2, "No import ID"); item->set_tooltip(2, TTR("Mesh has no name nor any other way to identify on re-import.\nPlease name it or ensure it is exported with an unique ID.")); - item->set_icon(2, get_theme_icon("StatusError", "EditorIcons")); + item->set_icon(2, get_theme_icon(SNAME("StatusError"), SNAME("EditorIcons"))); } save_path_items.push_back(item); @@ -935,7 +935,7 @@ void SceneImportSettings::_save_dir_callback(const String &p_path) { String name = ad.scene_node->get_text(0); item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK); - item->set_icon(0, get_theme_icon("Animation", "EditorIcons")); + item->set_icon(0, get_theme_icon(SNAME("Animation"), SNAME("EditorIcons"))); item->set_text(0, name); if (ad.settings.has("save_to_file/enabled") && bool(ad.settings["save_to_file/enabled"])) { @@ -956,14 +956,14 @@ void SceneImportSettings::_save_dir_callback(const String &p_path) { if (FileAccess::exists(path)) { item->set_text(2, "Warning: File exists"); item->set_tooltip(2, TTR("Existing file with the same name will be replaced on import.")); - item->set_icon(2, get_theme_icon("StatusWarning", "EditorIcons")); + item->set_icon(2, get_theme_icon(SNAME("StatusWarning"), SNAME("EditorIcons"))); } else { item->set_text(2, "Will save to new File"); - item->set_icon(2, get_theme_icon("StatusSuccess", "EditorIcons")); + item->set_icon(2, get_theme_icon(SNAME("StatusSuccess"), SNAME("EditorIcons"))); } - item->add_button(1, get_theme_icon("Folder", "EditorIcons")); + item->add_button(1, get_theme_icon(SNAME("Folder"), SNAME("EditorIcons"))); } save_path_items.push_back(item); @@ -1099,18 +1099,18 @@ SceneImportSettings::SceneImportSettings() { camera->make_current(); light = memnew(DirectionalLight3D); - light->set_transform(Transform().looking_at(Vector3(-1, -2, -0.6), Vector3(0, 1, 0))); + light->set_transform(Transform3D().looking_at(Vector3(-1, -2, -0.6), Vector3(0, 1, 0))); base_viewport->add_child(light); light->set_shadow(true); { Ref<StandardMaterial3D> selection_mat; - selection_mat.instance(); + selection_mat.instantiate(); selection_mat->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); selection_mat->set_albedo(Color(1, 0.8, 1.0)); Ref<SurfaceTool> st; - st.instance(); + st.instantiate(); st->begin(Mesh::PRIMITIVE_LINES); AABB base_aabb; @@ -1126,7 +1126,7 @@ SceneImportSettings::SceneImportSettings() { st->add_vertex(b.lerp(a, 0.2)); } - selection_mesh.instance(); + selection_mesh.instantiate(); st->commit(selection_mesh); selection_mesh->surface_set_material(0, selection_mat); @@ -1141,7 +1141,7 @@ SceneImportSettings::SceneImportSettings() { base_viewport->add_child(mesh_preview); mesh_preview->hide(); - material_preview.instance(); + material_preview.instantiate(); } inspector = memnew(EditorInspector); @@ -1163,13 +1163,13 @@ SceneImportSettings::SceneImportSettings() { external_path_tree->set_columns(3); external_path_tree->set_column_titles_visible(true); external_path_tree->set_column_expand(0, true); - external_path_tree->set_column_min_width(0, 100 * EDSCALE); + external_path_tree->set_column_custom_minimum_width(0, 100 * EDSCALE); external_path_tree->set_column_title(0, TTR("Resource")); external_path_tree->set_column_expand(1, true); - external_path_tree->set_column_min_width(1, 100 * EDSCALE); + external_path_tree->set_column_custom_minimum_width(1, 100 * EDSCALE); external_path_tree->set_column_title(1, TTR("Path")); external_path_tree->set_column_expand(2, false); - external_path_tree->set_column_min_width(2, 200 * EDSCALE); + external_path_tree->set_column_custom_minimum_width(2, 200 * EDSCALE); external_path_tree->set_column_title(2, TTR("Status")); save_path = memnew(EditorFileDialog); save_path->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_DIR); diff --git a/editor/import/scene_importer_mesh.cpp b/editor/import/scene_importer_mesh.cpp index 28fdd4ddbd..0d14347225 100644 --- a/editor/import/scene_importer_mesh.cpp +++ b/editor/import/scene_importer_mesh.cpp @@ -30,6 +30,7 @@ #include "scene_importer_mesh.h" +#include "core/math/math_defs.h" #include "scene/resources/surface_tool.h" void EditorSceneImporterMesh::add_blend_shape(const String &p_name) { @@ -78,11 +79,11 @@ void EditorSceneImporterMesh::add_surface(Mesh::PrimitiveType p_primitive, const List<Variant> lods; p_lods.get_key_list(&lods); - for (List<Variant>::Element *E = lods.front(); E; E = E->next()) { - ERR_CONTINUE(!E->get().is_num()); + for (const Variant &E : lods) { + ERR_CONTINUE(!E.is_num()); Surface::LOD lod; - lod.distance = E->get(); - lod.indices = p_lods[E->get()]; + lod.distance = E; + lod.indices = p_lods[E]; ERR_CONTINUE(lod.indices.size() == 0); s.lods.push_back(lod); } @@ -141,6 +142,18 @@ void EditorSceneImporterMesh::set_surface_material(int p_surface, const Ref<Mate surfaces.write[p_surface].material = p_material; } +Basis EditorSceneImporterMesh::compute_rotation_matrix_from_ortho_6d(Vector3 p_x_raw, Vector3 p_y_raw) { + Vector3 x = p_x_raw.normalized(); + Vector3 z = x.cross(p_y_raw); + z = z.normalized(); + Vector3 y = z.cross(x); + Basis basis; + basis.set_axis(Vector3::AXIS_X, x); + basis.set_axis(Vector3::AXIS_Y, y); + basis.set_axis(Vector3::AXIS_Z, z); + return basis; +} + void EditorSceneImporterMesh::generate_lods() { if (!SurfaceTool::simplify_func) { return; @@ -151,6 +164,9 @@ void EditorSceneImporterMesh::generate_lods() { if (!SurfaceTool::simplify_sloppy_func) { return; } + if (!SurfaceTool::simplify_with_attrib_func) { + return; + } for (int i = 0; i < surfaces.size(); i++) { if (surfaces[i].primitive != Mesh::PRIMITIVE_TRIANGLES) { @@ -163,59 +179,63 @@ void EditorSceneImporterMesh::generate_lods() { if (indices.size() == 0) { continue; //no lods if no indices } + Vector<Vector3> normals = surfaces[i].arrays[RS::ARRAY_NORMAL]; uint32_t vertex_count = vertices.size(); const Vector3 *vertices_ptr = vertices.ptr(); - - int min_indices = 10; - int index_target = indices.size() / 2; - print_line("Total indices: " + itos(indices.size())); - float mesh_scale = SurfaceTool::simplify_scale_func((const float *)vertices_ptr, vertex_count, sizeof(Vector3)); - const float target_error = 1e-3f; - float abs_target_error = target_error / mesh_scale; + Vector<float> attributes; + Vector<float> normal_weights; + int32_t attribute_count = 6; + if (normals.size()) { + attributes.resize(normals.size() * attribute_count); + for (int32_t normal_i = 0; normal_i < normals.size(); normal_i++) { + Basis basis; + basis.set_euler(normals[normal_i]); + Vector3 basis_x = basis.get_axis(0); + Vector3 basis_y = basis.get_axis(1); + basis = compute_rotation_matrix_from_ortho_6d(basis_x, basis_y); + basis_x = basis.get_axis(0); + basis_y = basis.get_axis(1); + attributes.write[normal_i * attribute_count + 0] = basis_x.x; + attributes.write[normal_i * attribute_count + 1] = basis_x.y; + attributes.write[normal_i * attribute_count + 2] = basis_x.z; + attributes.write[normal_i * attribute_count + 3] = basis_y.x; + attributes.write[normal_i * attribute_count + 4] = basis_y.y; + attributes.write[normal_i * attribute_count + 5] = basis_y.z; + } + normal_weights.resize(vertex_count); + for (int32_t weight_i = 0; weight_i < normal_weights.size(); weight_i++) { + normal_weights.write[weight_i] = 1.0; + } + } else { + attribute_count = 0; + } + const int min_indices = 10; + const float error_tolerance = 1.44224'95703; // Cube root of 3 + const float threshold = 1.0 / error_tolerance; + int index_target = indices.size() * threshold; + float max_mesh_error_percentage = 1e0f; + float mesh_error = 0.0f; + float scale = SurfaceTool::simplify_scale_func((const float *)vertices_ptr, vertex_count, sizeof(Vector3)); while (index_target > min_indices) { - float error; Vector<int> new_indices; new_indices.resize(indices.size()); - size_t new_len = SurfaceTool::simplify_func((unsigned int *)new_indices.ptrw(), (const unsigned int *)indices.ptr(), indices.size(), (const float *)vertices_ptr, vertex_count, sizeof(Vector3), index_target, abs_target_error, &error); - if ((int)new_len > (index_target * 120 / 100)) { - // Attribute discontinuities break normals. - bool is_sloppy = false; - if (is_sloppy) { - abs_target_error = target_error / mesh_scale; - index_target = new_len; - while (index_target > min_indices) { - Vector<int> sloppy_new_indices; - sloppy_new_indices.resize(indices.size()); - new_len = SurfaceTool::simplify_sloppy_func((unsigned int *)sloppy_new_indices.ptrw(), (const unsigned int *)indices.ptr(), indices.size(), (const float *)vertices_ptr, vertex_count, sizeof(Vector3), index_target, abs_target_error, &error); - if ((int)new_len > (index_target * 120 / 100)) { - break; // 20 percent tolerance - } - sloppy_new_indices.resize(new_len); - Surface::LOD lod; - lod.distance = error * mesh_scale; - abs_target_error = lod.distance; - if (Math::is_equal_approx(abs_target_error, 0.0f)) { - return; - } - lod.indices = sloppy_new_indices; - print_line("Lod " + itos(surfaces.write[i].lods.size()) + " shoot for " + itos(index_target / 3) + " triangles, got " + itos(new_len / 3) + " triangles. Distance " + rtos(lod.distance) + ". Use simplify sloppy."); - surfaces.write[i].lods.push_back(lod); - index_target /= 2; - } - } - break; // 20 percent tolerance + size_t new_len = SurfaceTool::simplify_with_attrib_func((unsigned int *)new_indices.ptrw(), (const unsigned int *)indices.ptr(), indices.size(), (const float *)vertices_ptr, vertex_count, sizeof(Vector3), index_target, max_mesh_error_percentage, &mesh_error, (float *)attributes.ptrw(), normal_weights.ptrw(), attribute_count); + if ((int)new_len > (index_target * error_tolerance)) { + break; } - new_indices.resize(new_len); Surface::LOD lod; - lod.distance = error * mesh_scale; - abs_target_error = lod.distance; - if (Math::is_equal_approx(abs_target_error, 0.0f)) { - return; + lod.distance = mesh_error * scale; + if (Math::is_zero_approx(mesh_error)) { + break; + } + if (new_len <= 0) { + break; } + new_indices.resize(new_len); lod.indices = new_indices; - print_line("Lod " + itos(surfaces.write[i].lods.size()) + " shoot for " + itos(index_target / 3) + " triangles, got " + itos(new_len / 3) + " triangles. Distance " + rtos(lod.distance)); + print_line("Lod " + itos(surfaces.write[i].lods.size()) + " begin with " + itos(indices.size() / 3) + " triangles and shoot for " + itos(index_target / 3) + " triangles. Got " + itos(new_len / 3) + " triangles. Lod screen ratio " + rtos(lod.distance)); surfaces.write[i].lods.push_back(lod); - index_target /= 2; + index_target *= threshold; } } } @@ -232,7 +252,7 @@ Ref<ArrayMesh> EditorSceneImporterMesh::get_mesh(const Ref<Mesh> &p_base) { mesh = p_base; } if (mesh.is_null()) { - mesh.instance(); + mesh.instantiate(); } mesh->set_name(get_name()); if (has_meta("import_id")) { @@ -301,7 +321,7 @@ void EditorSceneImporterMesh::create_shadow_mesh() { } } - shadow_mesh.instance(); + shadow_mesh.instantiate(); for (int i = 0; i < surfaces.size(); i++) { LocalVector<int> vertex_remap; @@ -486,7 +506,7 @@ Vector<Ref<Shape3D>> EditorSceneImporterMesh::convex_decompose() const { const Vector<Face3> faces = get_faces(); - Vector<Vector<Face3>> decomposed = Mesh::convex_composition_function(faces); + Vector<Vector<Face3>> decomposed = Mesh::convex_composition_function(faces, -1); Vector<Ref<Shape3D>> ret; @@ -509,7 +529,7 @@ Vector<Ref<Shape3D>> EditorSceneImporterMesh::convex_decompose() const { } Ref<ConvexPolygonShape3D> shape; - shape.instance(); + shape.instantiate(); shape->set_points(convex_points); ret.push_back(shape); } @@ -568,7 +588,7 @@ Ref<NavigationMesh> EditorSceneImporterMesh::create_navigation_mesh() { } Ref<NavigationMesh> nm; - nm.instance(); + nm.instantiate(); nm->set_vertices(vertices); Vector<int> v3; @@ -583,7 +603,7 @@ Ref<NavigationMesh> EditorSceneImporterMesh::create_navigation_mesh() { return nm; } -extern bool (*array_mesh_lightmap_unwrap_callback)(float p_texel_size, const float *p_vertices, const float *p_normals, int p_vertex_count, const int *p_indices, int p_index_count, float **r_uv, int **r_vertex, int *r_vertex_count, int **r_index, int *r_index_count, int *r_size_hint_x, int *r_size_hint_y, int *&r_cache_data, unsigned int &r_cache_size, bool &r_used_cache); +extern bool (*array_mesh_lightmap_unwrap_callback)(float p_texel_size, const float *p_vertices, const float *p_normals, int p_vertex_count, const int *p_indices, int p_index_count, const uint8_t *p_cache_data, bool *r_use_cache, uint8_t **r_mesh_cache, int *r_mesh_cache_size, float **r_uv, int **r_vertex, int *r_vertex_count, int **r_index, int *r_index_count, int *r_size_hint_x, int *r_size_hint_y); struct EditorSceneImporterMeshLightmapSurface { Ref<Material> material; @@ -593,22 +613,24 @@ struct EditorSceneImporterMeshLightmapSurface { String name; }; -Error EditorSceneImporterMesh::lightmap_unwrap_cached(int *&r_cache_data, unsigned int &r_cache_size, bool &r_used_cache, const Transform &p_base_transform, float p_texel_size) { +Error EditorSceneImporterMesh::lightmap_unwrap_cached(const Transform3D &p_base_transform, float p_texel_size, const Vector<uint8_t> &p_src_cache, Vector<uint8_t> &r_dst_cache) { ERR_FAIL_COND_V(!array_mesh_lightmap_unwrap_callback, ERR_UNCONFIGURED); ERR_FAIL_COND_V_MSG(blend_shapes.size() != 0, ERR_UNAVAILABLE, "Can't unwrap mesh with blend shapes."); - Vector<float> vertices; - Vector<float> normals; - Vector<int> indices; - Vector<float> uv; - Vector<Pair<int, int>> uv_indices; + LocalVector<float> vertices; + LocalVector<float> normals; + LocalVector<int> indices; + LocalVector<float> uv; + LocalVector<Pair<int, int>> uv_indices; Vector<EditorSceneImporterMeshLightmapSurface> lightmap_surfaces; // Keep only the scale - Transform transform = p_base_transform; - transform.origin = Vector3(); - transform.looking_at(Vector3(1, 0, 0), Vector3(0, 1, 0)); + Basis basis = p_base_transform.get_basis(); + Vector3 scale = Vector3(basis.get_axis(0).length(), basis.get_axis(1).length(), basis.get_axis(2).length()); + + Transform3D transform; + transform.scale(scale); Basis normal_basis = transform.basis.inverse().transposed(); @@ -623,15 +645,10 @@ Error EditorSceneImporterMesh::lightmap_unwrap_cached(int *&r_cache_data, unsign SurfaceTool::create_vertex_array_from_triangle_arrays(arrays, s.vertices, &s.format); - Vector<Vector3> rvertices = arrays[Mesh::ARRAY_VERTEX]; + PackedVector3Array rvertices = arrays[Mesh::ARRAY_VERTEX]; int vc = rvertices.size(); - const Vector3 *r = rvertices.ptr(); - - Vector<Vector3> rnormals = arrays[Mesh::ARRAY_NORMAL]; - ERR_FAIL_COND_V_MSG(rnormals.size() == 0, ERR_UNAVAILABLE, "Normals are required for lightmap unwrap."); - - const Vector3 *rn = rnormals.ptr(); + PackedVector3Array rnormals = arrays[Mesh::ARRAY_NORMAL]; int vertex_ofs = vertices.size() / 3; @@ -640,24 +657,29 @@ Error EditorSceneImporterMesh::lightmap_unwrap_cached(int *&r_cache_data, unsign uv_indices.resize(vertex_ofs + vc); for (int j = 0; j < vc; j++) { - Vector3 v = transform.xform(r[j]); - Vector3 n = normal_basis.xform(rn[j]).normalized(); - - vertices.write[(j + vertex_ofs) * 3 + 0] = v.x; - vertices.write[(j + vertex_ofs) * 3 + 1] = v.y; - vertices.write[(j + vertex_ofs) * 3 + 2] = v.z; - normals.write[(j + vertex_ofs) * 3 + 0] = n.x; - normals.write[(j + vertex_ofs) * 3 + 1] = n.y; - normals.write[(j + vertex_ofs) * 3 + 2] = n.z; - uv_indices.write[j + vertex_ofs] = Pair<int, int>(i, j); + Vector3 v = transform.xform(rvertices[j]); + Vector3 n = normal_basis.xform(rnormals[j]).normalized(); + + vertices[(j + vertex_ofs) * 3 + 0] = v.x; + vertices[(j + vertex_ofs) * 3 + 1] = v.y; + vertices[(j + vertex_ofs) * 3 + 2] = v.z; + normals[(j + vertex_ofs) * 3 + 0] = n.x; + normals[(j + vertex_ofs) * 3 + 1] = n.y; + normals[(j + vertex_ofs) * 3 + 2] = n.z; + uv_indices[j + vertex_ofs] = Pair<int, int>(i, j); } - Vector<int> rindices = arrays[Mesh::ARRAY_INDEX]; + PackedInt32Array rindices = arrays[Mesh::ARRAY_INDEX]; int ic = rindices.size(); + float eps = 1.19209290e-7F; // Taken from xatlas.h if (ic == 0) { for (int j = 0; j < vc / 3; j++) { - if (Face3(r[j * 3 + 0], r[j * 3 + 1], r[j * 3 + 2]).is_degenerate()) { + Vector3 p0 = transform.xform(rvertices[j * 3 + 0]); + Vector3 p1 = transform.xform(rvertices[j * 3 + 1]); + Vector3 p2 = transform.xform(rvertices[j * 3 + 2]); + + if ((p0 - p1).length_squared() < eps || (p1 - p2).length_squared() < eps || (p2 - p0).length_squared() < eps) { continue; } @@ -667,15 +689,18 @@ Error EditorSceneImporterMesh::lightmap_unwrap_cached(int *&r_cache_data, unsign } } else { - const int *ri = rindices.ptr(); - for (int j = 0; j < ic / 3; j++) { - if (Face3(r[ri[j * 3 + 0]], r[ri[j * 3 + 1]], r[ri[j * 3 + 2]]).is_degenerate()) { + Vector3 p0 = transform.xform(rvertices[rindices[j * 3 + 0]]); + Vector3 p1 = transform.xform(rvertices[rindices[j * 3 + 1]]); + Vector3 p2 = transform.xform(rvertices[rindices[j * 3 + 2]]); + + if ((p0 - p1).length_squared() < eps || (p1 - p2).length_squared() < eps || (p2 - p0).length_squared() < eps) { continue; } - indices.push_back(vertex_ofs + ri[j * 3 + 0]); - indices.push_back(vertex_ofs + ri[j * 3 + 1]); - indices.push_back(vertex_ofs + ri[j * 3 + 2]); + + indices.push_back(vertex_ofs + rindices[j * 3 + 0]); + indices.push_back(vertex_ofs + rindices[j * 3 + 1]); + indices.push_back(vertex_ofs + rindices[j * 3 + 2]); } } @@ -684,6 +709,9 @@ Error EditorSceneImporterMesh::lightmap_unwrap_cached(int *&r_cache_data, unsign //unwrap + bool use_cache = true; // Used to request cache generation and to know if cache was used + uint8_t *gen_cache; + int gen_cache_size; float *gen_uvs; int *gen_vertices; int *gen_indices; @@ -692,7 +720,7 @@ Error EditorSceneImporterMesh::lightmap_unwrap_cached(int *&r_cache_data, unsign int size_x; int size_y; - bool ok = array_mesh_lightmap_unwrap_callback(p_texel_size, vertices.ptr(), normals.ptr(), vertices.size() / 3, indices.ptr(), indices.size(), &gen_uvs, &gen_vertices, &gen_vertex_count, &gen_indices, &gen_index_count, &size_x, &size_y, r_cache_data, r_cache_size, r_used_cache); + bool ok = array_mesh_lightmap_unwrap_callback(p_texel_size, vertices.ptr(), normals.ptr(), vertices.size() / 3, indices.ptr(), indices.size(), p_src_cache.ptr(), &use_cache, &gen_cache, &gen_cache_size, &gen_uvs, &gen_vertices, &gen_vertex_count, &gen_indices, &gen_index_count, &size_x, &size_y); if (!ok) { return ERR_CANT_CREATE; @@ -702,11 +730,11 @@ Error EditorSceneImporterMesh::lightmap_unwrap_cached(int *&r_cache_data, unsign clear(); //create surfacetools for each surface.. - Vector<Ref<SurfaceTool>> surfaces_tools; + LocalVector<Ref<SurfaceTool>> surfaces_tools; for (int i = 0; i < lightmap_surfaces.size(); i++) { Ref<SurfaceTool> st; - st.instance(); + st.instantiate(); st->begin(Mesh::PRIMITIVE_TRIANGLES); st->set_material(lightmap_surfaces[i].material); st->set_meta("name", lightmap_surfaces[i].name); @@ -714,11 +742,12 @@ Error EditorSceneImporterMesh::lightmap_unwrap_cached(int *&r_cache_data, unsign } print_verbose("Mesh: Gen indices: " + itos(gen_index_count)); + //go through all indices for (int i = 0; i < gen_index_count; i += 3) { - ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 0]], uv_indices.size(), ERR_BUG); - ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 1]], uv_indices.size(), ERR_BUG); - ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 2]], uv_indices.size(), ERR_BUG); + ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 0]], (int)uv_indices.size(), ERR_BUG); + ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 1]], (int)uv_indices.size(), ERR_BUG); + ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 2]], (int)uv_indices.size(), ERR_BUG); ERR_FAIL_COND_V(uv_indices[gen_vertices[gen_indices[i + 0]]].first != uv_indices[gen_vertices[gen_indices[i + 1]]].first || uv_indices[gen_vertices[gen_indices[i + 0]]].first != uv_indices[gen_vertices[gen_indices[i + 2]]].first, ERR_BUG); @@ -728,49 +757,54 @@ Error EditorSceneImporterMesh::lightmap_unwrap_cached(int *&r_cache_data, unsign SurfaceTool::Vertex v = lightmap_surfaces[surface].vertices[uv_indices[gen_vertices[gen_indices[i + j]]].second]; if (lightmap_surfaces[surface].format & Mesh::ARRAY_FORMAT_COLOR) { - surfaces_tools.write[surface]->set_color(v.color); + surfaces_tools[surface]->set_color(v.color); } if (lightmap_surfaces[surface].format & Mesh::ARRAY_FORMAT_TEX_UV) { - surfaces_tools.write[surface]->set_uv(v.uv); + surfaces_tools[surface]->set_uv(v.uv); } if (lightmap_surfaces[surface].format & Mesh::ARRAY_FORMAT_NORMAL) { - surfaces_tools.write[surface]->set_normal(v.normal); + surfaces_tools[surface]->set_normal(v.normal); } if (lightmap_surfaces[surface].format & Mesh::ARRAY_FORMAT_TANGENT) { Plane t; t.normal = v.tangent; t.d = v.binormal.dot(v.normal.cross(v.tangent)) < 0 ? -1 : 1; - surfaces_tools.write[surface]->set_tangent(t); + surfaces_tools[surface]->set_tangent(t); } if (lightmap_surfaces[surface].format & Mesh::ARRAY_FORMAT_BONES) { - surfaces_tools.write[surface]->set_bones(v.bones); + surfaces_tools[surface]->set_bones(v.bones); } if (lightmap_surfaces[surface].format & Mesh::ARRAY_FORMAT_WEIGHTS) { - surfaces_tools.write[surface]->set_weights(v.weights); + surfaces_tools[surface]->set_weights(v.weights); } Vector2 uv2(gen_uvs[gen_indices[i + j] * 2 + 0], gen_uvs[gen_indices[i + j] * 2 + 1]); - surfaces_tools.write[surface]->set_uv2(uv2); + surfaces_tools[surface]->set_uv2(uv2); - surfaces_tools.write[surface]->add_vertex(v.vertex); + surfaces_tools[surface]->add_vertex(v.vertex); } } //generate surfaces - - for (int i = 0; i < surfaces_tools.size(); i++) { - surfaces_tools.write[i]->index(); - Array arrays = surfaces_tools.write[i]->commit_to_arrays(); - add_surface(surfaces_tools.write[i]->get_primitive(), arrays, Array(), Dictionary(), surfaces_tools.write[i]->get_material(), surfaces_tools.write[i]->get_meta("name")); + for (unsigned int i = 0; i < surfaces_tools.size(); i++) { + surfaces_tools[i]->index(); + Array arrays = surfaces_tools[i]->commit_to_arrays(); + add_surface(surfaces_tools[i]->get_primitive(), arrays, Array(), Dictionary(), surfaces_tools[i]->get_material(), surfaces_tools[i]->get_meta("name")); } set_lightmap_size_hint(Size2(size_x, size_y)); - if (!r_used_cache) { - //free stuff - ::free(gen_vertices); - ::free(gen_indices); - ::free(gen_uvs); + if (gen_cache_size > 0) { + r_dst_cache.resize(gen_cache_size); + memcpy(r_dst_cache.ptrw(), gen_cache, gen_cache_size); + memfree(gen_cache); + } + + if (!use_cache) { + // Cache was not used, free the buffers + memfree(gen_vertices); + memfree(gen_indices); + memfree(gen_uvs); } return OK; diff --git a/editor/import/scene_importer_mesh.h b/editor/import/scene_importer_mesh.h index 3326fab55d..2488de7ed0 100644 --- a/editor/import/scene_importer_mesh.h +++ b/editor/import/scene_importer_mesh.h @@ -67,6 +67,7 @@ class EditorSceneImporterMesh : public Resource { Ref<EditorSceneImporterMesh> shadow_mesh; Size2i lightmap_size_hint; + Basis compute_rotation_matrix_from_ortho_6d(Vector3 p_x_raw, Vector3 y_raw); protected: void _set_data(const Dictionary &p_data); @@ -105,7 +106,7 @@ public: Vector<Ref<Shape3D>> convex_decompose() const; Ref<Shape3D> create_trimesh_shape() const; Ref<NavigationMesh> create_navigation_mesh(); - Error lightmap_unwrap_cached(int *&r_cache_data, unsigned int &r_cache_size, bool &r_used_cache, const Transform &p_base_transform, float p_texel_size); + Error lightmap_unwrap_cached(const Transform3D &p_base_transform, float p_texel_size, const Vector<uint8_t> &p_src_cache, Vector<uint8_t> &r_dst_cache); void set_lightmap_size_hint(const Size2i &p_size); Size2i get_lightmap_size_hint() const; |