From 68716b67953485c1110a6f11d229cfc72a0ec97e Mon Sep 17 00:00:00 2001 From: Aaron Franke Date: Wed, 26 Nov 2025 11:08:24 -0800 Subject: [PATCH] Allow converting from Mesh to ImporterMesh --- doc/classes/ImporterMesh.xml | 7 +++ modules/gltf/gltf_document.cpp | 72 ++-------------------------- scene/resources/3d/importer_mesh.cpp | 43 ++++++++++++++++- scene/resources/3d/importer_mesh.h | 3 +- 4 files changed, 53 insertions(+), 72 deletions(-) diff --git a/doc/classes/ImporterMesh.xml b/doc/classes/ImporterMesh.xml index 3714f0fcbeb..8d4bc028a0d 100644 --- a/doc/classes/ImporterMesh.xml +++ b/doc/classes/ImporterMesh.xml @@ -42,6 +42,13 @@ Removes all surfaces and blend shapes from this [ImporterMesh]. + + + + + Converts the given [Mesh] into an [ImporterMesh] by copying all its surfaces, blend shapes, materials, and metadata into a new [ImporterMesh] object. + + diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp index 652ffdbd168..f5342d2c1b0 100644 --- a/modules/gltf/gltf_document.cpp +++ b/modules/gltf/gltf_document.cpp @@ -99,49 +99,6 @@ static void _attach_meta_to_extras(Ref p_node, Dictionary &p_json) { } } -static Ref _mesh_to_importer_mesh(Ref p_mesh) { - Ref importer_mesh; - importer_mesh.instantiate(); - if (p_mesh.is_null()) { - return importer_mesh; - } - - Ref array_mesh = p_mesh; - if (p_mesh->get_blend_shape_count()) { - ArrayMesh::BlendShapeMode shape_mode = ArrayMesh::BLEND_SHAPE_MODE_NORMALIZED; - if (array_mesh.is_valid()) { - shape_mode = array_mesh->get_blend_shape_mode(); - } - importer_mesh->set_blend_shape_mode(shape_mode); - for (int morph_i = 0; morph_i < p_mesh->get_blend_shape_count(); morph_i++) { - importer_mesh->add_blend_shape(p_mesh->get_blend_shape_name(morph_i)); - } - } - for (int32_t surface_i = 0; surface_i < p_mesh->get_surface_count(); surface_i++) { - Array array = p_mesh->surface_get_arrays(surface_i); - Ref mat = p_mesh->surface_get_material(surface_i); - const String surface_name = array_mesh.is_valid() ? array_mesh->surface_get_name(surface_i) : String(); - String mat_name; - if (mat.is_valid()) { - mat_name = mat->get_name(); - if (mat_name.is_empty()) { - mat_name = surface_name; - } - } else { - mat_name = surface_name; - // Assign default material when no material is assigned. - mat.instantiate(); - mat->set_name(mat_name); - } - importer_mesh->add_surface(p_mesh->surface_get_primitive_type(surface_i), - array, p_mesh->surface_get_blend_shape_arrays(surface_i), p_mesh->surface_get_lods(surface_i), mat, - mat_name, p_mesh->surface_get_format(surface_i)); - } - importer_mesh->merge_meta_from(*p_mesh); - importer_mesh->set_name(p_mesh->get_name()); - return importer_mesh; -} - Error GLTFDocument::_serialize(Ref p_state) { for (Ref ext : document_extensions) { ERR_CONTINUE(ext.is_null()); @@ -4074,7 +4031,6 @@ GLTFMeshIndex GLTFDocument::_convert_mesh_to_gltf(Ref p_state, MeshIn Ref mat = p_mesh_instance->get_active_material(surface_i); instance_materials.append(mat); } - Ref current_mesh = _mesh_to_importer_mesh(mesh_resource); Vector blend_weights; int32_t blend_count = mesh_resource->get_blend_shape_count(); blend_weights.resize(blend_count); @@ -4089,7 +4045,7 @@ GLTFMeshIndex GLTFDocument::_convert_mesh_to_gltf(Ref p_state, MeshIn gltf_mesh->set_name(_gen_unique_name(p_state, mesh_resource->get_name())); } gltf_mesh->set_instance_materials(instance_materials); - gltf_mesh->set_mesh(current_mesh); + gltf_mesh->set_mesh(ImporterMesh::from_mesh(mesh_resource)); gltf_mesh->set_blend_weights(blend_weights); GLTFMeshIndex mesh_i = p_state->meshes.size(); p_state->meshes.push_back(gltf_mesh); @@ -4354,7 +4310,7 @@ void GLTFDocument::_convert_grid_map_to_gltf(GridMap *p_grid_map, GLTFNodeIndex Vector3(cell_location.x, cell_location.y, cell_location.z))); Ref gltf_mesh; gltf_mesh.instantiate(); - gltf_mesh->set_mesh(_mesh_to_importer_mesh(p_grid_map->get_mesh_library()->get_item_mesh(cell))); + gltf_mesh->set_mesh(ImporterMesh::from_mesh(p_grid_map->get_mesh_library()->get_item_mesh(cell))); gltf_mesh->set_original_name(p_grid_map->get_mesh_library()->get_item_name(cell)); const String unique_name = _gen_unique_name(p_state, p_grid_map->get_mesh_library()->get_item_name(cell)); gltf_mesh->set_name(unique_name); @@ -4385,29 +4341,7 @@ void GLTFDocument::_convert_multi_mesh_instance_to_gltf( } gltf_mesh->set_original_name(multi_mesh->get_name()); gltf_mesh->set_name(multi_mesh->get_name()); - Ref importer_mesh; - importer_mesh.instantiate(); - Ref array_mesh = multi_mesh->get_mesh(); - if (array_mesh.is_valid()) { - importer_mesh->set_blend_shape_mode(array_mesh->get_blend_shape_mode()); - for (int32_t blend_i = 0; blend_i < array_mesh->get_blend_shape_count(); blend_i++) { - importer_mesh->add_blend_shape(array_mesh->get_blend_shape_name(blend_i)); - } - } - for (int32_t surface_i = 0; surface_i < mesh->get_surface_count(); surface_i++) { - Ref mat = mesh->surface_get_material(surface_i); - String material_name; - if (mat.is_valid()) { - material_name = mat->get_name(); - } - Array blend_arrays; - if (array_mesh.is_valid()) { - blend_arrays = array_mesh->surface_get_blend_shape_arrays(surface_i); - } - importer_mesh->add_surface(mesh->surface_get_primitive_type(surface_i), mesh->surface_get_arrays(surface_i), - blend_arrays, mesh->surface_get_lods(surface_i), mat, material_name, mesh->surface_get_format(surface_i)); - } - gltf_mesh->set_mesh(importer_mesh); + gltf_mesh->set_mesh(ImporterMesh::from_mesh(mesh)); GLTFMeshIndex mesh_index = p_state->meshes.size(); p_state->meshes.push_back(gltf_mesh); for (int32_t instance_i = 0; instance_i < multi_mesh->get_instance_count(); diff --git a/scene/resources/3d/importer_mesh.cpp b/scene/resources/3d/importer_mesh.cpp index cb70f09eaf6..cd57606417f 100644 --- a/scene/resources/3d/importer_mesh.cpp +++ b/scene/resources/3d/importer_mesh.cpp @@ -64,13 +64,13 @@ Mesh::BlendShapeMode ImporterMesh::get_blend_shape_mode() const { return blend_shape_mode; } -void ImporterMesh::add_surface(Mesh::PrimitiveType p_primitive, const Array &p_arrays, const TypedArray &p_blend_shapes, const Dictionary &p_lods, const Ref &p_material, const String &p_name, const uint64_t p_flags) { +void ImporterMesh::add_surface(Mesh::PrimitiveType p_primitive, const Array &p_arrays, const TypedArray &p_blend_shapes, const Dictionary &p_lods, const Ref &p_material, const String &p_surface_name, const uint64_t p_flags) { ERR_FAIL_COND(p_blend_shapes.size() != blend_shapes.size()); ERR_FAIL_COND(p_arrays.size() != Mesh::ARRAY_MAX); Surface s; s.primitive = p_primitive; s.arrays = p_arrays; - s.name = p_name; + s.name = p_surface_name; s.flags = p_flags; Vector vertex_array = p_arrays[Mesh::ARRAY_VERTEX]; @@ -627,6 +627,44 @@ Ref ImporterMesh::get_mesh(const Ref &p_base) { return mesh; } +Ref ImporterMesh::from_mesh(const Ref &p_mesh) { + Ref importer_mesh; + importer_mesh.instantiate(); + if (p_mesh.is_null()) { + return importer_mesh; + } + Ref array_mesh = p_mesh; + // Convert blend shape mode and names if any. + if (p_mesh->get_blend_shape_count() > 0) { + ArrayMesh::BlendShapeMode shape_mode = ArrayMesh::BLEND_SHAPE_MODE_NORMALIZED; + if (array_mesh.is_valid()) { + shape_mode = array_mesh->get_blend_shape_mode(); + } + importer_mesh->set_blend_shape_mode(shape_mode); + for (int morph_i = 0; morph_i < p_mesh->get_blend_shape_count(); morph_i++) { + importer_mesh->add_blend_shape(p_mesh->get_blend_shape_name(morph_i)); + } + } + // Add surfaces one by one. + for (int32_t surface_i = 0; surface_i < p_mesh->get_surface_count(); surface_i++) { + Ref mat = p_mesh->surface_get_material(surface_i); + String surface_name; + if (array_mesh.is_valid()) { + surface_name = array_mesh->surface_get_name(surface_i); + } + if (surface_name.is_empty() && mat.is_valid()) { + surface_name = mat->get_name(); + } + importer_mesh->add_surface(p_mesh->surface_get_primitive_type(surface_i), p_mesh->surface_get_arrays(surface_i), + p_mesh->surface_get_blend_shape_arrays(surface_i), p_mesh->surface_get_lods(surface_i), + mat, surface_name, p_mesh->surface_get_format(surface_i)); + } + // Merge metadata. + importer_mesh->merge_meta_from(*p_mesh); + importer_mesh->set_name(p_mesh->get_name()); + return importer_mesh; +} + void ImporterMesh::clear() { surfaces.clear(); blend_shapes.clear(); @@ -1255,6 +1293,7 @@ void ImporterMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("generate_lods", "normal_merge_angle", "normal_split_angle", "bone_transform_array"), &ImporterMesh::_generate_lods_bind); ClassDB::bind_method(D_METHOD("get_mesh", "base_mesh"), &ImporterMesh::get_mesh, DEFVAL(Ref())); + ClassDB::bind_static_method("ImporterMesh", D_METHOD("from_mesh", "mesh"), &ImporterMesh::from_mesh); ClassDB::bind_method(D_METHOD("clear"), &ImporterMesh::clear); ClassDB::bind_method(D_METHOD("_set_data", "data"), &ImporterMesh::_set_data); diff --git a/scene/resources/3d/importer_mesh.h b/scene/resources/3d/importer_mesh.h index 03cc73e627c..665b461f2a9 100644 --- a/scene/resources/3d/importer_mesh.h +++ b/scene/resources/3d/importer_mesh.h @@ -93,7 +93,7 @@ public: static String validate_blend_shape_name(const String &p_name); - void add_surface(Mesh::PrimitiveType p_primitive, const Array &p_arrays, const TypedArray &p_blend_shapes = Array(), const Dictionary &p_lods = Dictionary(), const Ref &p_material = Ref(), const String &p_name = String(), const uint64_t p_flags = 0); + void add_surface(Mesh::PrimitiveType p_primitive, const Array &p_arrays, const TypedArray &p_blend_shapes = Array(), const Dictionary &p_lods = Dictionary(), const Ref &p_material = Ref(), const String &p_surface_name = String(), const uint64_t p_flags = 0); int get_surface_count() const; void set_blend_shape_mode(Mesh::BlendShapeMode p_blend_shape_mode); @@ -133,5 +133,6 @@ public: bool has_mesh() const; Ref get_mesh(const Ref &p_base = Ref()); + static Ref from_mesh(const Ref &p_mesh); void clear(); };