diff options
author | reduz <reduzio@gmail.com> | 2020-12-17 15:56:59 -0300 |
---|---|---|
committer | Juan Linietsky <reduzio@gmail.com> | 2020-12-18 15:48:03 +0100 |
commit | d2302f53d6ad80943e7f4245ac572003f1681d00 (patch) | |
tree | f1d46d8194f01e56cd3a4d042b9b33ba728c6f62 /editor | |
parent | 36b4e035dc7c410c29cda4446f8daa2e00a31da0 (diff) |
Implement automatic LOD (Level of Detail)
-Happens on import by default for all models
-Just works (tm)
-Biasing can be later adjusted per node or per viewport (as well as globally)
-Disabled AABB.get_support test because its broken
Diffstat (limited to 'editor')
-rw-r--r-- | editor/editor_node.cpp | 3 | ||||
-rw-r--r-- | editor/import/resource_importer_scene.cpp | 71 | ||||
-rw-r--r-- | editor/import/resource_importer_scene.h | 4 | ||||
-rw-r--r-- | editor/plugins/node_3d_editor_plugin.cpp | 7 | ||||
-rw-r--r-- | editor/plugins/node_3d_editor_plugin.h | 1 |
5 files changed, 76 insertions, 10 deletions
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 64b5f50b91..dfe5d64784 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -525,6 +525,9 @@ void EditorNode::_notification(int p_what) { scene_root->set_sdf_oversize(sdf_oversize); Viewport::SDFScale sdf_scale = Viewport::SDFScale(int(GLOBAL_GET("rendering/quality/2d_sdf/scale"))); scene_root->set_sdf_scale(sdf_scale); + + float lod_threshold = GLOBAL_GET("rendering/quality/mesh_lod/threshold_pixels"); + scene_root->set_lod_threshold(lod_threshold); } ResourceImporterTexture::get_singleton()->update_imports(); diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index 5abae339df..d9c8bd9eb3 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -44,6 +44,7 @@ #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" #include "scene/resources/world_margin_shape_3d.h" uint32_t EditorSceneImporter::get_import_flags() const { @@ -217,6 +218,59 @@ Ref<Material> EditorSceneImporterMesh::get_surface_material(int p_surface) const return surfaces[p_surface].material; } +void EditorSceneImporterMesh::generate_lods() { + if (!SurfaceTool::simplify_func) { + return; + } + + for (int i = 0; i < surfaces.size(); i++) { + if (surfaces[i].primitive != Mesh::PRIMITIVE_TRIANGLES) { + continue; + } + + surfaces.write[i].lods.clear(); + Vector<Vector3> vertices = surfaces[i].arrays[RS::ARRAY_VERTEX]; + Vector<int> indices = surfaces[i].arrays[RS::ARRAY_INDEX]; + if (indices.size() == 0) { + continue; //no lods if no indices + } + uint32_t vertex_count = vertices.size(); + const Vector3 *vertices_ptr = vertices.ptr(); + AABB aabb; + { + for (uint32_t j = 0; j < vertex_count; j++) { + if (j == 0) { + aabb.position = vertices_ptr[j]; + } else { + aabb.expand_to(vertices_ptr[j]); + } + } + } + + float longest_axis_size = aabb.get_longest_axis_size(); + + int min_indices = 10; + int index_target = indices.size() / 2; + print_line("total: " + itos(indices.size())); + 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, 1e20, &error); + print_line("shoot for " + itos(index_target) + ", got " + itos(new_len) + " distance " + rtos(error)); + if ((int)new_len > (index_target * 120 / 100)) { + break; // 20 percent tolerance + } + new_indices.resize(new_len); + Surface::LOD lod; + lod.distance = error * longest_axis_size; + lod.indices = new_indices; + surfaces.write[i].lods.push_back(lod); + index_target /= 2; + } + } +} + bool EditorSceneImporterMesh::has_mesh() const { return mesh.is_valid(); } @@ -1422,9 +1476,9 @@ void ResourceImporterScene::get_import_options(List<ImportOption> *r_options, in r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "materials/location", PROPERTY_HINT_ENUM, "Node,Mesh"), (meshes_out || materials_out) ? 1 : 0)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "materials/storage", PROPERTY_HINT_ENUM, "Built-In,Files (.material),Files (.tres)", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), materials_out ? 1 : 0)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "materials/keep_on_reimport"), materials_out)); - r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "meshes/compress"), true)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "meshes/ensure_tangents"), true)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "meshes/storage", PROPERTY_HINT_ENUM, "Built-In,Files (.mesh),Files (.tres)"), meshes_out ? 1 : 0)); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "meshes/generate_lods"), true)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "meshes/light_baking", PROPERTY_HINT_ENUM, "Disabled,Enable,Gen Lightmaps", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), 0)); 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)); @@ -1517,7 +1571,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) { +void ResourceImporterScene::_generate_meshes(Node *p_node, bool p_generate_lods) { EditorSceneImporterMeshNode *src_mesh = Object::cast_to<EditorSceneImporterMeshNode>(p_node); if (src_mesh != nullptr) { //is mesh @@ -1528,6 +1582,9 @@ void ResourceImporterScene::_generate_meshes(Node *p_node) { Ref<ArrayMesh> mesh; if (!src_mesh->get_mesh()->has_mesh()) { + if (p_generate_lods) { + src_mesh->get_mesh()->generate_lods(); + } //do mesh processing } mesh = src_mesh->get_mesh()->get_mesh(); @@ -1542,7 +1599,7 @@ void ResourceImporterScene::_generate_meshes(Node *p_node) { } for (int i = 0; i < p_node->get_child_count(); i++) { - _generate_meshes(p_node->get_child(i)); + _generate_meshes(p_node->get_child(i), p_generate_lods); } } Error ResourceImporterScene::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) { @@ -1583,10 +1640,6 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p import_flags |= EditorSceneImporter::IMPORT_ANIMATION; } - if (int(p_options["meshes/compress"])) { - import_flags |= EditorSceneImporter::IMPORT_USE_COMPRESSION; - } - if (bool(p_options["meshes/ensure_tangents"])) { import_flags |= EditorSceneImporter::IMPORT_GENERATE_TANGENT_ARRAYS; } @@ -1641,7 +1694,9 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p scene->set_name(p_save_path.get_file().get_basename()); } - _generate_meshes(scene); + bool gen_lods = bool(p_options["meshes/generate_lods"]); + + _generate_meshes(scene, gen_lods); err = OK; diff --git a/editor/import/resource_importer_scene.h b/editor/import/resource_importer_scene.h index 758390b367..aef6c0ac50 100644 --- a/editor/import/resource_importer_scene.h +++ b/editor/import/resource_importer_scene.h @@ -144,6 +144,8 @@ public: float get_surface_lod_size(int p_surface, int p_lod) const; Ref<Material> get_surface_material(int p_surface) const; + void generate_lods(); + bool has_mesh() const; Ref<ArrayMesh> get_mesh(); void clear(); @@ -205,7 +207,7 @@ class ResourceImporterScene : public ResourceImporter { }; void _replace_owner(Node *p_node, Node *p_scene, Node *p_new_owner); - void _generate_meshes(Node *p_node); + void _generate_meshes(Node *p_node, bool p_generate_lods); public: static ResourceImporterScene *get_singleton() { return singleton; } diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index ff3b50303f..f0d512e4b2 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -3017,7 +3017,8 @@ void Node3DEditorViewport::_menu_option(int p_option) { case VIEW_DISPLAY_DEBUG_DECAL_ATLAS: case VIEW_DISPLAY_DEBUG_SDFGI: case VIEW_DISPLAY_DEBUG_SDFGI_PROBES: - case VIEW_DISPLAY_DEBUG_GI_BUFFER: { + case VIEW_DISPLAY_DEBUG_GI_BUFFER: + case VIEW_DISPLAY_DEBUG_DISABLE_LOD: { static const int display_options[] = { VIEW_DISPLAY_NORMAL, VIEW_DISPLAY_WIREFRAME, @@ -3034,6 +3035,7 @@ void Node3DEditorViewport::_menu_option(int p_option) { VIEW_DISPLAY_DEBUG_SCENE_LUMINANCE, VIEW_DISPLAY_DEBUG_SSAO, VIEW_DISPLAY_DEBUG_GI_BUFFER, + VIEW_DISPLAY_DEBUG_DISABLE_LOD, VIEW_DISPLAY_DEBUG_PSSM_SPLITS, VIEW_DISPLAY_DEBUG_DECAL_ATLAS, VIEW_DISPLAY_DEBUG_SDFGI, @@ -3056,6 +3058,7 @@ void Node3DEditorViewport::_menu_option(int p_option) { Viewport::DEBUG_DRAW_SCENE_LUMINANCE, Viewport::DEBUG_DRAW_SSAO, Viewport::DEBUG_DRAW_GI_BUFFER, + Viewport::DEBUG_DRAW_DISABLE_LOD, Viewport::DEBUG_DRAW_PSSM_SPLITS, Viewport::DEBUG_DRAW_DECAL_ATLAS, Viewport::DEBUG_DRAW_SDFGI, @@ -3959,6 +3962,8 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, Edito display_submenu->add_radio_check_item(TTR("SSAO"), VIEW_DISPLAY_DEBUG_SSAO); display_submenu->add_separator(); display_submenu->add_radio_check_item(TTR("GI Buffer"), VIEW_DISPLAY_DEBUG_GI_BUFFER); + display_submenu->add_separator(); + display_submenu->add_radio_check_item(TTR("Disable LOD"), VIEW_DISPLAY_DEBUG_DISABLE_LOD); display_submenu->set_name("display_advanced"); view_menu->get_popup()->add_submenu_item(TTR("Display Advanced..."), "display_advanced", VIEW_DISPLAY_ADVANCED); view_menu->get_popup()->add_separator(); diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h index 66ee678154..079c86ceb4 100644 --- a/editor/plugins/node_3d_editor_plugin.h +++ b/editor/plugins/node_3d_editor_plugin.h @@ -212,6 +212,7 @@ class Node3DEditorViewport : public Control { VIEW_DISPLAY_DEBUG_SDFGI, VIEW_DISPLAY_DEBUG_SDFGI_PROBES, VIEW_DISPLAY_DEBUG_GI_BUFFER, + VIEW_DISPLAY_DEBUG_DISABLE_LOD, VIEW_LOCK_ROTATION, VIEW_CINEMATIC_PREVIEW, VIEW_AUTO_ORTHOGONAL, |