Disable normal raycaster for LOD generation by default
Normal raycaster makes LOD generation process >2x slower and often generates normals that look significantly worse compared to what the simplifier comes up with by default. This was likely different before last meshoptimizer upgrade, as the attribute metric was not functioning properly, but now it looks like it's doing more harm than good. This change makes it disabled by default but keeps an easy option to re-enable it per mesh using LOD parameters for now until we get more confidence and can remove the code outright. Because the long term plan would be to disable this feature entirely, the scripting API isn't changed, and it's just off-by-default there with no way to re-enable.
This commit is contained in:
parent
cae2f853dc
commit
a13a64eacd
3 changed files with 31 additions and 12 deletions
|
@ -2009,6 +2009,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));
|
||||
|
@ -2436,6 +2437,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;
|
||||
|
@ -2490,6 +2492,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()) {
|
||||
|
@ -2536,7 +2542,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) {
|
||||
|
|
|
@ -269,7 +269,7 @@ void ImporterMesh::set_surface_material(int p_surface, const Ref<Material> &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;
|
||||
}
|
||||
|
@ -429,6 +429,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<Vector3> split_vertex_normals;
|
||||
LocalVector<int> split_vertex_indices;
|
||||
|
@ -438,7 +439,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<StaticRaycaster> raycaster = StaticRaycaster::create();
|
||||
Ref<StaticRaycaster> raycaster = p_raycast_normals ? StaticRaycaster::create() : Ref<StaticRaycaster>();
|
||||
if (raycaster.is_valid()) {
|
||||
raycaster->add_mesh(vertices, indices, 0);
|
||||
raycaster->commit();
|
||||
|
@ -485,19 +486,22 @@ void ImporterMesh::generate_lods(float p_normal_merge_angle, float p_normal_spli
|
|||
}
|
||||
|
||||
new_indices.resize(new_index_count);
|
||||
|
||||
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++) {
|
||||
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<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));
|
||||
const float ray_bias = 0.05;
|
||||
float ray_length = ray_bias + mesh_error * scale * 3.0f;
|
||||
|
@ -668,7 +672,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>();
|
||||
|
||||
for (int j = 0; j < surfaces.write[i].lods.size(); j++) {
|
||||
|
@ -679,6 +686,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();
|
||||
}
|
||||
|
@ -1364,7 +1375,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<ArrayMesh>()));
|
||||
ClassDB::bind_method(D_METHOD("clear"), &ImporterMesh::clear);
|
||||
|
||||
|
|
|
@ -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<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();
|
||||
Ref<ImporterMesh> get_shadow_mesh() const;
|
||||
|
|
Loading…
Reference in a new issue