Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[3.x] Discrete Level of Detail #85437

Merged
merged 1 commit into from
Mar 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions doc/classes/Camera.xml
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,11 @@
</method>
</methods>
<members>
<member name="affect_lod" type="bool" setter="set_affect_lod" getter="get_affect_lod" default="true">
If [code]true[/code], the camera will be used to calculate the level of detail in [LOD] nodes.
Objects further from the camera will select lower levels of detail than those closer to the camera.
[b]Note:[/b] This property has no effect if [member projection] is set to [constant PROJECTION_ORTHOGONAL].
</member>
<member name="cull_mask" type="int" setter="set_cull_mask" getter="get_cull_mask" default="1048575">
The culling mask that describes which 3D render layers are rendered by this camera.
</member>
Expand Down
16 changes: 0 additions & 16 deletions doc/classes/GeometryInstance.xml
Original file line number Diff line number Diff line change
Expand Up @@ -45,22 +45,6 @@
<member name="lightmap_scale" type="int" setter="set_lightmap_scale" getter="get_lightmap_scale" enum="GeometryInstance.LightmapScale" default="0">
Scale factor for the generated baked lightmap. Useful for adding detail to certain mesh instances.
</member>
<member name="lod_max_distance" type="float" setter="set_lod_max_distance" getter="get_lod_max_distance" default="0.0">
The GeometryInstance's max LOD distance.
[b]Note:[/b] This property currently has no effect.
</member>
<member name="lod_max_hysteresis" type="float" setter="set_lod_max_hysteresis" getter="get_lod_max_hysteresis" default="0.0">
The GeometryInstance's max LOD margin.
[b]Note:[/b] This property currently has no effect.
</member>
<member name="lod_min_distance" type="float" setter="set_lod_min_distance" getter="get_lod_min_distance" default="0.0">
The GeometryInstance's min LOD distance.
[b]Note:[/b] This property currently has no effect.
</member>
<member name="lod_min_hysteresis" type="float" setter="set_lod_min_hysteresis" getter="get_lod_min_hysteresis" default="0.0">
The GeometryInstance's min LOD margin.
[b]Note:[/b] This property currently has no effect.
</member>
<member name="material_overlay" type="Material" setter="set_material_overlay" getter="get_material_overlay">
The material overlay for the whole geometry.
If a material is assigned to this property, it will be rendered on top of any other active material for all the surfaces.
Expand Down
27 changes: 27 additions & 0 deletions doc/classes/LOD.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="LOD" inherits="Spatial" version="3.6" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
Provides discrete level of detail.
</brief_description>
<description>
Automatically hides and shows [Spatial] children depending on the distance from the closest [Camera] to the [LOD] node. Child nodes that don't inherit from [Spatial] are ignored by the LOD system.
Children are shown in order with the first children shown when closest to the [Camera], and the latter children shown when further away.
The threshold distances for changes are determined by [member Spatial.lod_range].
For example, a first child with a range of [code]2[/code] will be shown from distance 0 to 2. A second child with a range of [code]5[/code] will be shown from distance 2 to 7, etc.
</description>
<tutorials>
</tutorials>
<methods>
</methods>
<members>
<member name="hysteresis" type="float" setter="set_hysteresis" getter="get_hysteresis" default="1.0">
To prevent flickering at borders, a hysteresis distance will be added to threshold distances when the object is moving away from the [Camera].
</member>
<member name="lod_priority" type="int" setter="set_lod_priority" getter="get_lod_priority" default="0">
Determines the rate at which level of detail will be updated.
Higher priorities will update faster, but use more CPU.
</member>
</members>
<constants>
</constants>
</class>
4 changes: 4 additions & 0 deletions doc/classes/Spatial.xml
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,10 @@
<member name="global_translation" type="Vector3" setter="set_global_translation" getter="get_global_translation">
Global position of this node. This is equivalent to [code]global_transform.origin[/code].
</member>
<member name="lod_range" type="float" setter="set_lod_range" getter="get_lod_range" default="10.0">
Determines the threshold distance at which this node will be shown or hidden when this node is parented by a [LOD] node.
For example, a first child with a range of [code]2[/code] will be shown from distance 0 to 2. A second child with a range of [code]5[/code] will be shown from distance 2 to 7, etc.
</member>
<member name="merging_mode" type="int" setter="set_merging_mode" getter="get_merging_mode" enum="Spatial.MergingMode" default="0">
The merging mode determines whether merging features of the engine ([MergeGroup] and [RoomManager]) will attempt to operate on branches of the scene tree.
The default mode inherited from the scene tree root is [constant MERGING_MODE_ON].
Expand Down
19 changes: 0 additions & 19 deletions doc/classes/VisualServer.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1462,14 +1462,6 @@
Once finished with your RID, you will want to free the RID using the VisualServer's [method free_rid] static method.
</description>
</method>
<method name="instance_geometry_set_as_instance_lod">
<return type="void" />
<argument index="0" name="instance" type="RID" />
<argument index="1" name="as_lod_of_instance" type="RID" />
<description>
Not implemented in Godot 3.x.
</description>
</method>
<method name="instance_geometry_set_cast_shadows_setting">
<return type="void" />
<argument index="0" name="instance" type="RID" />
Expand All @@ -1478,17 +1470,6 @@
Sets the shadow casting setting to one of [enum ShadowCastingSetting]. Equivalent to [member GeometryInstance.cast_shadow].
</description>
</method>
<method name="instance_geometry_set_draw_range">
<return type="void" />
<argument index="0" name="instance" type="RID" />
<argument index="1" name="min" type="float" />
<argument index="2" name="max" type="float" />
<argument index="3" name="min_margin" type="float" />
<argument index="4" name="max_margin" type="float" />
<description>
Not implemented in Godot 3.x.
</description>
</method>
<method name="instance_geometry_set_flag">
<return type="void" />
<argument index="0" name="instance" type="RID" />
Expand Down
14 changes: 14 additions & 0 deletions editor/editor_node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1347,7 +1347,17 @@ void EditorNode::_find_node_types(Node *p_node, int &count_2d, int &count_3d) {
void EditorNode::_save_scene_with_preview(String p_file, int p_idx) {
EditorProgress save("save", TTR("Saving Scene"), 4);

Ref<World> edited_world;

if (editor_data.get_edited_scene_root() != nullptr) {
// Allow a generic mechanism for the engine to make changes prior, and after saving.
if (editor_data.get_edited_scene_root()->get_tree() && editor_data.get_edited_scene_root()->get_tree()->get_root()) {
edited_world = editor_data.get_edited_scene_root()->get_tree()->get_root()->get_world();
if (edited_world.is_valid()) {
edited_world->notify_saving(true);
}
}
Comment on lines +1353 to +1359
Copy link
Member

@Calinou Calinou Feb 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This hook could be really useful to have in editor plugins and @tool scripts, also in 4.x 🙂

There are multiple instances where I've wanted to make editor-visible changes that aren't serialized to scene files outside of LOD.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I was surprised there wasn't something like this already. Although it may have to be done carefully in some cases to avoid race conditions.


save.step(TTR("Analyzing"), 0);

int c2d = 0;
Expand Down Expand Up @@ -1428,6 +1438,10 @@ void EditorNode::_save_scene_with_preview(String p_file, int p_idx) {
save.step(TTR("Saving Scene"), 4);
_save_scene(p_file, p_idx);

if (edited_world.is_valid()) {
edited_world->notify_saving(false);
}

if (!singleton->cmdline_export_mode) {
EditorResourcePreview::get_singleton()->check_for_invalidation(p_file);
}
Expand Down
1 change: 1 addition & 0 deletions editor/icons/icon_l_o_d.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 16 additions & 0 deletions editor/plugins/spatial_editor_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#include "editor/spatial_editor_gizmos.h"
#include "scene/3d/camera.h"
#include "scene/3d/collision_shape.h"
#include "scene/3d/lod_manager.h"
#include "scene/3d/mesh_instance.h"
#include "scene/3d/physics_body.h"
#include "scene/3d/room_manager.h"
Expand Down Expand Up @@ -2735,7 +2736,12 @@ void SpatialEditorViewport::_notification(int p_what) {
} else {
set_freelook_active(false);
}

call_deferred("update_transform_gizmo_view");

if (camera) {
camera->set_affect_lod(visible);
}
}

if (p_what == NOTIFICATION_RESIZED) {
Expand Down Expand Up @@ -5503,6 +5509,14 @@ void SpatialEditor::_menu_item_pressed(int p_option) {
VisualServer::get_singleton()->set_use_occlusion_culling(!is_checked);
view_menu->get_popup()->set_item_checked(checkbox_id, !is_checked);

} break;
case MENU_VIEW_LEVEL_OF_DETAIL: {
int checkbox_id = view_menu->get_popup()->get_item_index(p_option);
bool is_checked = view_menu->get_popup()->is_item_checked(checkbox_id);
LODManager::set_enabled(!is_checked);
view_menu->get_popup()->set_item_checked(checkbox_id, !is_checked);
EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor()->update_tree();

} break;
case MENU_VIEW_CAMERA_SETTINGS: {
settings_dialog->popup_centered(settings_vbc->get_combined_minimum_size() + Size2(50, 50));
Expand Down Expand Up @@ -7076,13 +7090,15 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) {
p->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_grid", TTR("View Grid"), KEY_NUMBERSIGN), MENU_VIEW_GRID);
p->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_portal_culling", TTR("View Portal Culling"), KEY_MASK_ALT | KEY_P), MENU_VIEW_PORTAL_CULLING);
p->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_occlusion_culling", TTR("View Occlusion Culling")), MENU_VIEW_OCCLUSION_CULLING);
p->add_check_shortcut(ED_SHORTCUT("spatial_editor/view_level_of_detail", TTR("View Level of Detail")), MENU_VIEW_LEVEL_OF_DETAIL);

p->add_separator();
p->add_shortcut(ED_SHORTCUT("spatial_editor/settings", TTR("Settings...")), MENU_VIEW_CAMERA_SETTINGS);

p->set_item_checked(p->get_item_index(MENU_VIEW_ORIGIN), true);
p->set_item_checked(p->get_item_index(MENU_VIEW_GRID), true);
p->set_item_checked(p->get_item_index(MENU_VIEW_OCCLUSION_CULLING), true);
p->set_item_checked(p->get_item_index(MENU_VIEW_LEVEL_OF_DETAIL), true);

p->connect("id_pressed", this, "_menu_item_pressed");

Expand Down
1 change: 1 addition & 0 deletions editor/plugins/spatial_editor_plugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -674,6 +674,7 @@ class SpatialEditor : public VBoxContainer {
MENU_VIEW_GRID,
MENU_VIEW_PORTAL_CULLING,
MENU_VIEW_OCCLUSION_CULLING,
MENU_VIEW_LEVEL_OF_DETAIL,
MENU_VIEW_GIZMOS_3D_ICONS,
MENU_VIEW_CAMERA_SETTINGS,
MENU_LOCK_SELECTED,
Expand Down
13 changes: 9 additions & 4 deletions editor/scene_tree_editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include "editor/node_dock.h"
#include "editor/plugins/animation_player_editor_plugin.h"
#include "editor/plugins/canvas_item_editor_plugin.h"
#include "scene/3d/lod_manager.h"
#include "scene/gui/label.h"
#include "scene/main/viewport.h"
#include "scene/resources/packed_scene.h"
Expand Down Expand Up @@ -162,7 +163,7 @@ void SceneTreeEditor::_toggle_visible(Node *p_node) {
}
}

void SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) {
void SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent, bool p_disable_visibility) {
if (!p_node) {
return;
}
Expand Down Expand Up @@ -405,9 +406,9 @@ void SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) {

bool v = p_node->call("is_visible");
if (v) {
item->add_button(0, get_icon("GuiVisibilityVisible", "EditorIcons"), BUTTON_VISIBILITY, false, TTR("Toggle Visibility"));
item->add_button(0, get_icon("GuiVisibilityVisible", "EditorIcons"), BUTTON_VISIBILITY, p_disable_visibility, TTR("Toggle Visibility"));
} else {
item->add_button(0, get_icon("GuiVisibilityHidden", "EditorIcons"), BUTTON_VISIBILITY, false, TTR("Toggle Visibility"));
item->add_button(0, get_icon("GuiVisibilityHidden", "EditorIcons"), BUTTON_VISIBILITY, p_disable_visibility, TTR("Toggle Visibility"));
}

if (!p_node->is_connected("visibility_changed", this, "_node_visibility_changed")) {
Expand Down Expand Up @@ -437,8 +438,12 @@ void SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) {
item->set_as_cursor(0);
}

// In some cases we want to disable visibility control by the user
// for automatically visibility-controlled children.
bool disable_visibility = p_node->is_class("LOD") && LODManager::is_enabled();

for (int i = 0; i < p_node->get_child_count(); i++) {
_add_nodes(p_node->get_child(i), item);
_add_nodes(p_node->get_child(i), item, disable_visibility);
}

if (valid_types.size()) {
Expand Down
2 changes: 1 addition & 1 deletion editor/scene_tree_editor.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ class SceneTreeEditor : public Control {

void _compute_hash(Node *p_node, uint64_t &hash);

void _add_nodes(Node *p_node, TreeItem *p_parent);
void _add_nodes(Node *p_node, TreeItem *p_parent, bool p_disable_visibility = false);
void _test_update_tree();
void _update_tree(bool p_scroll_to_selected = false);
bool _update_filter(TreeItem *p_parent = nullptr, bool p_scroll_to_selected = false);
Expand Down
3 changes: 3 additions & 0 deletions scene/3d/camera.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,8 @@ void Camera::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_doppler_tracking"), &Camera::get_doppler_tracking);
ClassDB::bind_method(D_METHOD("get_frustum"), &Camera::get_frustum);
ClassDB::bind_method(D_METHOD("get_camera_rid"), &Camera::get_camera);
ClassDB::bind_method(D_METHOD("set_affect_lod", "enable"), &Camera::set_affect_lod);
ClassDB::bind_method(D_METHOD("get_affect_lod"), &Camera::get_affect_lod);

ClassDB::bind_method(D_METHOD("set_cull_mask_bit", "layer", "enable"), &Camera::set_cull_mask_bit);
ClassDB::bind_method(D_METHOD("get_cull_mask_bit", "layer"), &Camera::get_cull_mask_bit);
Expand All @@ -523,6 +525,7 @@ void Camera::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "frustum_offset"), "set_frustum_offset", "get_frustum_offset");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "near", PROPERTY_HINT_EXP_RANGE, "0.01,8192,0.01,or_greater"), "set_znear", "get_znear");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "far", PROPERTY_HINT_EXP_RANGE, "0.1,8192,0.1,or_greater"), "set_zfar", "get_zfar");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "affect_lod"), "set_affect_lod", "get_affect_lod");

BIND_ENUM_CONSTANT(PROJECTION_PERSPECTIVE);
BIND_ENUM_CONSTANT(PROJECTION_ORTHOGONAL);
Expand Down
4 changes: 4 additions & 0 deletions scene/3d/camera.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ class Camera : public Spatial {

DopplerTracking doppler_tracking;
Ref<SpatialVelocityTracker> velocity_tracker;
bool affect_lod = true;

protected:
void _update_camera();
Expand Down Expand Up @@ -170,6 +171,9 @@ class Camera : public Spatial {

Vector3 get_doppler_tracked_velocity() const;

void set_affect_lod(bool p_enable) { affect_lod = p_enable; }
bool get_affect_lod() const { return affect_lod; }

Camera();
~Camera();
};
Expand Down
Loading
Loading