Prechádzať zdrojové kódy

Merge pull request #93727 from zeux/raycast-opt

Disable normal raycaster for LOD generation by default
Rémi Verschelde 1 rok pred
rodič
commit
e58a7530aa

+ 7 - 1
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::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_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::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;
 		} break;
 		case INTERNAL_IMPORT_CATEGORY_MATERIAL: {
 		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));
 			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;
 				bool generate_lods = p_generate_lods;
 				float split_angle = 25.0f;
 				float split_angle = 25.0f;
 				float merge_angle = 60.0f;
 				float merge_angle = 60.0f;
+				bool raycast_normals = false;
 				bool create_shadow_meshes = p_create_shadow_meshes;
 				bool create_shadow_meshes = p_create_shadow_meshes;
 				bool bake_lightmaps = p_light_bake_mode == LIGHT_BAKE_STATIC_LIGHTMAPS;
 				bool bake_lightmaps = p_light_bake_mode == LIGHT_BAKE_STATIC_LIGHTMAPS;
 				String save_to_file;
 				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"];
 						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))) {
 					if (bool(mesh_settings.get("save_to_file/enabled", false))) {
 						save_to_file = mesh_settings.get("save_to_file/path", String());
 						save_to_file = mesh_settings.get("save_to_file/path", String());
 						if (!save_to_file.is_resource_file()) {
 						if (!save_to_file.is_resource_file()) {
@@ -2540,7 +2546,7 @@ Node *ResourceImporterScene::_generate_meshes(Node *p_node, const Dictionary &p_
 
 
 				if (generate_lods) {
 				if (generate_lods) {
 					Array skin_pose_transform_array = _get_skinned_pose_transforms(src_mesh_node);
 					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) {
 				if (create_shadow_meshes) {

+ 21 - 10
scene/resources/3d/importer_mesh.cpp

@@ -269,7 +269,7 @@ void ImporterMesh::set_surface_material(int p_surface, const Ref<Material> &p_ma
 	}                                                                                                              \
 	}                                                                                                              \
 	write_array[vert_idx] = transformed_vert;
 	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) {
 	if (!SurfaceTool::simplify_scale_func) {
 		return;
 		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 index_target = 12; // Start with the smallest target, 4 triangles
 		unsigned int last_index_count = 0;
 		unsigned int last_index_count = 0;
 
 
+		// Only used for normal raycasting
 		int split_vertex_count = vertex_count;
 		int split_vertex_count = vertex_count;
 		LocalVector<Vector3> split_vertex_normals;
 		LocalVector<Vector3> split_vertex_normals;
 		LocalVector<int> split_vertex_indices;
 		LocalVector<int> split_vertex_indices;
@@ -441,7 +442,7 @@ void ImporterMesh::generate_lods(float p_normal_merge_angle, float p_normal_spli
 		RandomPCG pcg;
 		RandomPCG pcg;
 		pcg.seed(123456789); // Keep seed constant across imports
 		pcg.seed(123456789); // Keep seed constant across imports
 
 
-		Ref<StaticRaycaster> raycaster = StaticRaycaster::create();
+		Ref<StaticRaycaster> raycaster = p_raycast_normals ? StaticRaycaster::create() : Ref<StaticRaycaster>();
 		if (raycaster.is_valid()) {
 		if (raycaster.is_valid()) {
 			raycaster->add_mesh(vertices, indices, 0);
 			raycaster->add_mesh(vertices, indices, 0);
 			raycaster->commit();
 			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);
 			new_indices.resize(new_index_count);
-
-			LocalVector<LocalVector<int>> vertex_corners;
-			vertex_corners.resize(vertex_count);
 			{
 			{
 				int *ptrw = new_indices.ptrw();
 				int *ptrw = new_indices.ptrw();
 				for (unsigned int j = 0; j < new_index_count; j++) {
 				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()) {
 			if (raycaster.is_valid()) {
+				LocalVector<LocalVector<int>> 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));
 				float error_factor = 1.0f / (scale * MAX(mesh_error, 0.15));
 				const float ray_bias = 0.05;
 				const float ray_bias = 0.05;
 				float ray_length = ray_bias + mesh_error * scale * 3.0f;
 				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<Surface::LODComparator>();
 		surfaces.write[i].lods.sort_custom<Surface::LODComparator>();
 
 
 		for (int j = 0; j < surfaces.write[i].lods.size(); j++) {
 		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 {
 bool ImporterMesh::has_mesh() const {
 	return mesh.is_valid();
 	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_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("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<ArrayMesh>()));
 	ClassDB::bind_method(D_METHOD("get_mesh", "base_mesh"), &ImporterMesh::get_mesh, DEFVAL(Ref<ArrayMesh>()));
 	ClassDB::bind_method(D_METHOD("clear"), &ImporterMesh::clear);
 	ClassDB::bind_method(D_METHOD("clear"), &ImporterMesh::clear);
 
 

+ 3 - 1
scene/resources/3d/importer_mesh.h

@@ -86,6 +86,8 @@ protected:
 	void _set_data(const Dictionary &p_data);
 	void _set_data(const Dictionary &p_data);
 	Dictionary _get_data() const;
 	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();
 	static void _bind_methods();
 
 
 public:
 public:
@@ -112,7 +114,7 @@ public:
 
 
 	void set_surface_material(int p_surface, const Ref<Material> &p_material);
 	void set_surface_material(int p_surface, const Ref<Material> &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();
 	void create_shadow_mesh();
 	Ref<ImporterMesh> get_shadow_mesh() const;
 	Ref<ImporterMesh> get_shadow_mesh() const;