diff --git a/editor/import/3d/resource_importer_scene.cpp b/editor/import/3d/resource_importer_scene.cpp index df4026195c..27b2af8f77 100644 --- a/editor/import/3d/resource_importer_scene.cpp +++ b/editor/import/3d/resource_importer_scene.cpp @@ -2013,6 +2013,7 @@ void ResourceImporterScene::get_internal_import_options(InternalImportCategory p r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "generate/lods", PROPERTY_HINT_ENUM, "Default,Enable,Disable"), 0)); r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "lods/normal_split_angle", PROPERTY_HINT_RANGE, "0,180,0.1,degrees"), 25.0f)); r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "lods/normal_merge_angle", PROPERTY_HINT_RANGE, "0,180,0.1,degrees"), 60.0f)); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "lods/raycast_normals", PROPERTY_HINT_NONE, ""), false)); } break; case INTERNAL_IMPORT_CATEGORY_MATERIAL: { r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "use_external/enabled", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false)); @@ -2440,6 +2441,7 @@ Node *ResourceImporterScene::_generate_meshes(Node *p_node, const Dictionary &p_ bool generate_lods = p_generate_lods; float split_angle = 25.0f; float merge_angle = 60.0f; + bool raycast_normals = false; bool create_shadow_meshes = p_create_shadow_meshes; bool bake_lightmaps = p_light_bake_mode == LIGHT_BAKE_STATIC_LIGHTMAPS; String save_to_file; @@ -2494,6 +2496,10 @@ Node *ResourceImporterScene::_generate_meshes(Node *p_node, const Dictionary &p_ merge_angle = mesh_settings["lods/normal_merge_angle"]; } + if (mesh_settings.has("lods/raycast_normals")) { + raycast_normals = mesh_settings["lods/raycast_normals"]; + } + if (bool(mesh_settings.get("save_to_file/enabled", false))) { save_to_file = mesh_settings.get("save_to_file/path", String()); if (!save_to_file.is_resource_file()) { @@ -2540,7 +2546,7 @@ Node *ResourceImporterScene::_generate_meshes(Node *p_node, const Dictionary &p_ if (generate_lods) { Array skin_pose_transform_array = _get_skinned_pose_transforms(src_mesh_node); - src_mesh_node->get_mesh()->generate_lods(merge_angle, split_angle, skin_pose_transform_array); + src_mesh_node->get_mesh()->generate_lods(merge_angle, split_angle, skin_pose_transform_array, raycast_normals); } if (create_shadow_meshes) { diff --git a/scene/resources/3d/importer_mesh.cpp b/scene/resources/3d/importer_mesh.cpp index f912d2650d..91531699b4 100644 --- a/scene/resources/3d/importer_mesh.cpp +++ b/scene/resources/3d/importer_mesh.cpp @@ -269,7 +269,7 @@ void ImporterMesh::set_surface_material(int p_surface, const Ref &p_ma } \ write_array[vert_idx] = transformed_vert; -void ImporterMesh::generate_lods(float p_normal_merge_angle, float p_normal_split_angle, Array p_bone_transform_array) { +void ImporterMesh::generate_lods(float p_normal_merge_angle, float p_normal_split_angle, Array p_bone_transform_array, bool p_raycast_normals) { if (!SurfaceTool::simplify_scale_func) { return; } @@ -432,6 +432,7 @@ void ImporterMesh::generate_lods(float p_normal_merge_angle, float p_normal_spli unsigned int index_target = 12; // Start with the smallest target, 4 triangles unsigned int last_index_count = 0; + // Only used for normal raycasting int split_vertex_count = vertex_count; LocalVector split_vertex_normals; LocalVector split_vertex_indices; @@ -441,7 +442,7 @@ void ImporterMesh::generate_lods(float p_normal_merge_angle, float p_normal_spli RandomPCG pcg; pcg.seed(123456789); // Keep seed constant across imports - Ref raycaster = StaticRaycaster::create(); + Ref raycaster = p_raycast_normals ? StaticRaycaster::create() : Ref(); if (raycaster.is_valid()) { raycaster->add_mesh(vertices, indices, 0); raycaster->commit(); @@ -488,19 +489,22 @@ void ImporterMesh::generate_lods(float p_normal_merge_angle, float p_normal_spli } new_indices.resize(new_index_count); - - LocalVector> vertex_corners; - vertex_corners.resize(vertex_count); { int *ptrw = new_indices.ptrw(); for (unsigned int j = 0; j < new_index_count; j++) { - const int &remapped = vertex_inverse_remap[ptrw[j]]; - vertex_corners[remapped].push_back(j); - ptrw[j] = remapped; + ptrw[j] = vertex_inverse_remap[ptrw[j]]; } } if (raycaster.is_valid()) { + LocalVector> vertex_corners; + vertex_corners.resize(vertex_count); + + int *ptrw = new_indices.ptrw(); + for (unsigned int j = 0; j < new_index_count; j++) { + vertex_corners[ptrw[j]].push_back(j); + } + float error_factor = 1.0f / (scale * MAX(mesh_error, 0.15)); const float ray_bias = 0.05; float ray_length = ray_bias + mesh_error * scale * 3.0f; @@ -671,7 +675,10 @@ void ImporterMesh::generate_lods(float p_normal_merge_angle, float p_normal_spli } } - surfaces.write[i].split_normals(split_vertex_indices, split_vertex_normals); + if (raycaster.is_valid()) { + surfaces.write[i].split_normals(split_vertex_indices, split_vertex_normals); + } + surfaces.write[i].lods.sort_custom(); for (int j = 0; j < surfaces.write[i].lods.size(); j++) { @@ -682,6 +689,10 @@ void ImporterMesh::generate_lods(float p_normal_merge_angle, float p_normal_spli } } +void ImporterMesh::_generate_lods_bind(float p_normal_merge_angle, float p_normal_split_angle, Array p_skin_pose_transform_array) { + generate_lods(p_normal_merge_angle, p_normal_split_angle, p_skin_pose_transform_array); +} + bool ImporterMesh::has_mesh() const { return mesh.is_valid(); } @@ -1367,7 +1378,7 @@ void ImporterMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("set_surface_name", "surface_idx", "name"), &ImporterMesh::set_surface_name); ClassDB::bind_method(D_METHOD("set_surface_material", "surface_idx", "material"), &ImporterMesh::set_surface_material); - ClassDB::bind_method(D_METHOD("generate_lods", "normal_merge_angle", "normal_split_angle", "bone_transform_array"), &ImporterMesh::generate_lods); + 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_method(D_METHOD("clear"), &ImporterMesh::clear); diff --git a/scene/resources/3d/importer_mesh.h b/scene/resources/3d/importer_mesh.h index ff8683449b..777f936030 100644 --- a/scene/resources/3d/importer_mesh.h +++ b/scene/resources/3d/importer_mesh.h @@ -86,6 +86,8 @@ protected: void _set_data(const Dictionary &p_data); Dictionary _get_data() const; + void _generate_lods_bind(float p_normal_merge_angle, float p_normal_split_angle, Array p_skin_pose_transform_array); + static void _bind_methods(); public: @@ -112,7 +114,7 @@ public: void set_surface_material(int p_surface, const Ref &p_material); - void generate_lods(float p_normal_merge_angle, float p_normal_split_angle, Array p_skin_pose_transform_array); + void generate_lods(float p_normal_merge_angle, float p_normal_split_angle, Array p_skin_pose_transform_array, bool p_raycast_normals = false); void create_shadow_mesh(); Ref get_shadow_mesh() const;