From 87b91721dad0b67fa60a974546fc1b413fdb2430 Mon Sep 17 00:00:00 2001 From: Relintai Date: Sun, 27 Aug 2023 17:25:38 +0200 Subject: [PATCH] Ported: Physics interpolation - Move out of Scenario Move VisualServer interpolation data out of Scenario and into VisualServerScene, so the interpolation data and enabled status is now common to all Scenarios. Fix physics interpolation in multithreaded mode by ensuring tick and pre-draw are called. - lawnjelly https://github.com/godotengine/godot/commit/d2b1d296340bb514b16af037c7ad6ed19e7b4a3f --- scene/3d/camera.cpp | 6 - scene/main/scene_tree.cpp | 21 +-- servers/rendering/rendering_server_raster.cpp | 8 - servers/rendering/rendering_server_raster.h | 34 ++-- servers/rendering/rendering_server_scene.cpp | 152 ++++++------------ servers/rendering/rendering_server_scene.h | 87 +++++----- .../rendering/rendering_server_wrap_mt.cpp | 30 ---- servers/rendering/rendering_server_wrap_mt.h | 26 +-- servers/rendering_server.h | 23 +-- 9 files changed, 158 insertions(+), 229 deletions(-) diff --git a/scene/3d/camera.cpp b/scene/3d/camera.cpp index 3afdf6504..a81a2875b 100644 --- a/scene/3d/camera.cpp +++ b/scene/3d/camera.cpp @@ -120,10 +120,6 @@ void Camera::_notification(int p_what) { if (current || first_camera) { world->_camera_set(this); } - - ERR_FAIL_COND(get_world_3d().is_null()); - RenderingServer::get_singleton()->camera_set_scenario(camera, get_world_3d()->get_scenario()); - } break; case NOTIFICATION_TRANSFORM_CHANGED: { _request_camera_update(); @@ -137,8 +133,6 @@ void Camera::_notification(int p_what) { } } break; case NOTIFICATION_EXIT_WORLD: { - RenderingServer::get_singleton()->camera_set_scenario(camera, RID()); - if (!get_tree()->is_node_being_edited(this)) { if (is_current()) { clear_current(); diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index 84fde2050..a08a83416 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -586,12 +586,7 @@ void SceneTree::set_physics_interpolation_enabled(bool p_enabled) { _physics_interpolation_enabled = p_enabled; - if (root->get_world_3d().is_valid()) { - RID scenario = root->get_world_3d()->get_scenario(); - if (scenario.is_valid()) { - RenderingServer::get_singleton()->scenario_set_physics_interpolation_enabled(scenario, p_enabled); - } - } + RenderingServer::get_singleton()->set_physics_interpolation_enabled(p_enabled); } bool SceneTree::is_physics_interpolation_enabled() const { @@ -621,11 +616,8 @@ bool SceneTree::iteration(float p_time) { current_frame++; - if (root->get_world_3d().is_valid()) { - RID scenario = root->get_world_3d()->get_scenario(); - if (scenario.is_valid()) { - RenderingServer::get_singleton()->scenario_tick(scenario); - } + if (_physics_interpolation_enabled) { + RenderingServer::get_singleton()->tick(); } // Any objects performing client physics interpolation @@ -795,11 +787,8 @@ bool SceneTree::idle(float p_time) { #endif - if (root->get_world_3d().is_valid()) { - RID scenario = root->get_world_3d()->get_scenario(); - if (scenario.is_valid()) { - RenderingServer::get_singleton()->scenario_pre_draw(scenario, true); - } + if (_physics_interpolation_enabled) { + RenderingServer::get_singleton()->pre_draw(true); } return _quit; diff --git a/servers/rendering/rendering_server_raster.cpp b/servers/rendering/rendering_server_raster.cpp index 09e6c0848..9d16d0c46 100644 --- a/servers/rendering/rendering_server_raster.cpp +++ b/servers/rendering/rendering_server_raster.cpp @@ -101,14 +101,6 @@ void RenderingServerRaster::request_frame_drawn_callback(Object *p_where, const frame_drawn_callbacks.push_back(fdc); } -void RenderingServerRaster::scenario_tick(RID p_scenario) { - RSG::scene->_scenario_tick(p_scenario); -} - -void RenderingServerRaster::scenario_pre_draw(RID p_scenario, bool p_will_draw) { - RSG::scene->_scenario_pre_draw(p_scenario, p_will_draw); -} - void RenderingServerRaster::draw(bool p_swap_buffers, double frame_step) { //needs to be done before changes is reset to 0, to not force the editor to redraw RS::get_singleton()->emit_signal("frame_pre_draw"); diff --git a/servers/rendering/rendering_server_raster.h b/servers/rendering/rendering_server_raster.h index d6fa079b4..9675e5223 100644 --- a/servers/rendering/rendering_server_raster.h +++ b/servers/rendering/rendering_server_raster.h @@ -115,8 +115,12 @@ public: #define BIND4RC(m_r, m_name, m_type1, m_type2, m_type3, m_type4) \ m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4) const { return BINDBASE->m_name(arg1, arg2, arg3, arg4); } +#define BIND0N(m_name) \ + void m_name() { BINDBASE->m_name(); } #define BIND1(m_name, m_type1) \ void m_name(m_type1 arg1) { DISPLAY_CHANGED BINDBASE->m_name(arg1); } +#define BIND1N(m_name, m_type1) \ + void m_name(m_type1 arg1) { BINDBASE->m_name(arg1); } #define BIND2(m_name, m_type1, m_type2) \ void m_name(m_type1 arg1, m_type2 arg2) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2); } #define BIND2C(m_name, m_type1, m_type2) \ @@ -357,10 +361,14 @@ public: //from now on, calls forwarded to this singleton #define BINDBASE RSG::scene + /* EVENT QUEUING */ + + BIND0N(tick) + BIND1N(pre_draw, bool) + /* CAMERA API */ BIND0R(RID, camera_create) - BIND2(camera_set_scenario, RID, RID) BIND4(camera_set_perspective, RID, float, float, float) BIND4(camera_set_orthogonal, RID, float, float, float) BIND5(camera_set_frustum, RID, float, Vector2, float, float) @@ -455,20 +463,24 @@ public: BIND7(environment_set_fog_depth, RID, bool, float, float, float, bool, float) BIND5(environment_set_fog_height, RID, bool, float, float, float) - /* SCENARIO API */ - #undef BINDBASE #define BINDBASE RSG::scene + /* INTERPOLATION */ + + BIND1(set_physics_interpolation_enabled, bool) + + /* SCENARIO API */ + BIND0R(RID, scenario_create) BIND2(scenario_set_debug, RID, ScenarioDebugMode) BIND2(scenario_set_environment, RID, RID) BIND3(scenario_set_reflection_atlas_size, RID, int, int) BIND2(scenario_set_fallback_environment, RID, RID) - BIND2(scenario_set_physics_interpolation_enabled, RID, bool) /* INSTANCING API */ + BIND0R(RID, instance_create) BIND2(instance_set_base, RID, RID) @@ -490,7 +502,8 @@ public: BIND2(instance_set_extra_visibility_margin, RID, real_t) - // Portals + /* PORTALS */ + BIND2(instance_set_portal_mode, RID, InstancePortalMode) BIND0R(RID, ghost_create) @@ -503,13 +516,15 @@ public: BIND4(portal_link, RID, RID, RID, bool) BIND2(portal_set_active, RID, bool) - // Roomgroups + /* ROOMGROUPS */ + BIND0R(RID, roomgroup_create) BIND2(roomgroup_prepare, RID, ObjectID) BIND2(roomgroup_set_scenario, RID, RID) BIND2(roomgroup_add_room, RID, RID) - // Occluders + /* OCCLUDERS */ + BIND0R(RID, occluder_instance_create) BIND2(occluder_instance_set_scenario, RID, RID) BIND2(occluder_instance_link_resource, RID, RID) @@ -523,7 +538,8 @@ public: BIND1(set_use_occlusion_culling, bool) BIND1RC(Geometry::MeshData, occlusion_debug_get_current_polys, RID) - // Rooms + /* ROOMS */ + BIND0R(RID, room_create) BIND2(room_set_scenario, RID, RID) BIND4(room_add_instance, RID, RID, const AABB &, const Vector &) @@ -674,8 +690,6 @@ public: virtual bool has_changed(ChangedPriority p_priority = CHANGED_PRIORITY_ANY) const; virtual void init(); virtual void finish(); - virtual void scenario_tick(RID p_scenario); - virtual void scenario_pre_draw(RID p_scenario, bool p_will_draw); /* STATUS INFORMATION */ diff --git a/servers/rendering/rendering_server_scene.cpp b/servers/rendering/rendering_server_scene.cpp index 61fb9898d..d6f8a17e5 100644 --- a/servers/rendering/rendering_server_scene.cpp +++ b/servers/rendering/rendering_server_scene.cpp @@ -40,8 +40,8 @@ /* CAMERA API */ -Transform RenderingServerScene::Camera::get_transform() const { - if (!is_currently_interpolated()) { +Transform RenderingServerScene::Camera::get_transform_interpolated() const { + if (!interpolated) { return transform; } @@ -55,25 +55,6 @@ RID RenderingServerScene::camera_create() { return camera_owner.make_rid(camera); } -void RenderingServerScene::camera_set_scenario(RID p_camera, RID p_scenario) { - Camera *camera = camera_owner.get(p_camera); - ERR_FAIL_COND(!camera); - - Scenario *old_scenario = camera->scenario; - - if (p_scenario.is_valid()) { - camera->scenario = scenario_owner.get(p_scenario); - ERR_FAIL_COND(!camera->scenario); - } else { - camera->scenario = nullptr; - } - - if (old_scenario && (old_scenario != camera->scenario)) { - // remove any interpolation data associated with the camera in this scenario - old_scenario->_interpolation_data.notify_free_camera(p_camera, *camera); - } -} - void RenderingServerScene::camera_set_perspective(RID p_camera, float p_fovy_degrees, float p_z_near, float p_z_far) { Camera *camera = camera_owner.get(p_camera); ERR_FAIL_COND(!camera); @@ -106,8 +87,8 @@ void RenderingServerScene::camera_reset_physics_interpolation(RID p_camera) { Camera *camera = camera_owner.get(p_camera); ERR_FAIL_COND(!camera); - if (camera->is_currently_interpolated()) { - camera->scenario->_interpolation_data.camera_teleport_list.push_back(p_camera); + if (_interpolation_data.interpolation_enabled && camera->interpolated) { + _interpolation_data.camera_teleport_list.push_back(p_camera); } } @@ -123,9 +104,9 @@ void RenderingServerScene::camera_set_transform(RID p_camera, const Transform &p camera->transform = p_transform.orthonormalized(); - if (camera->is_currently_interpolated()) { + if (_interpolation_data.interpolation_enabled && camera->interpolated) { if (!camera->on_interpolate_transform_list) { - camera->scenario->_interpolation_data.camera_transform_update_list_curr->push_back(p_camera); + _interpolation_data.camera_transform_update_list_curr->push_back(p_camera); camera->on_interpolate_transform_list = true; } @@ -303,7 +284,6 @@ void RenderingServerScene::SpatialPartitioningScene_Octree::set_balance(float p_ RenderingServerScene::Scenario::Scenario() { debug = RS::SCENARIO_DEBUG_DISABLED; - _interpolation_data.interpolation_enabled = false; bool use_bvh_or_octree = GLOBAL_GET("rendering/quality/spatial_partitioning/use_bvh"); @@ -416,30 +396,22 @@ RID RenderingServerScene::scenario_create() { return scenario_rid; } -void RenderingServerScene::scenario_set_physics_interpolation_enabled(RID p_scenario, bool p_enabled) { - Scenario *scenario = scenario_owner.get(p_scenario); - ERR_FAIL_COND(!scenario); - scenario->_interpolation_data.interpolation_enabled = p_enabled; +void RenderingServerScene::set_physics_interpolation_enabled(bool p_enabled) { + _interpolation_data.interpolation_enabled = p_enabled; } -void RenderingServerScene::_scenario_tick(RID p_scenario) { - Scenario *scenario = scenario_owner.get(p_scenario); - ERR_FAIL_COND(!scenario); - - if (scenario->is_physics_interpolation_enabled()) { - update_interpolation_tick(scenario->_interpolation_data, true); +void RenderingServerScene::tick() { + if (_interpolation_data.interpolation_enabled) { + update_interpolation_tick(true); } } -void RenderingServerScene::_scenario_pre_draw(RID p_scenario, bool p_will_draw) { - Scenario *scenario = scenario_owner.get(p_scenario); - ERR_FAIL_COND(!scenario); - +void RenderingServerScene::pre_draw(bool p_will_draw) { // even when running and not drawing scenes, we still need to clear intermediate per frame // interpolation data .. hence the p_will_draw flag (so we can reduce the processing if the frame // will not be drawn) - if (scenario->is_physics_interpolation_enabled()) { - update_interpolation_frame(scenario->_interpolation_data, p_will_draw); + if (_interpolation_data.interpolation_enabled) { + update_interpolation_frame(p_will_draw); } } @@ -614,7 +586,7 @@ void RenderingServerScene::instance_set_scenario(RID p_instance, RID p_scenario) } // remove any interpolation data associated with the instance in this scenario - instance->scenario->_interpolation_data.notify_free_instance(p_instance, *instance); + _interpolation_data.notify_free_instance(p_instance, *instance); switch (instance->base_type) { case RS::INSTANCE_LIGHT: { @@ -697,8 +669,8 @@ void RenderingServerScene::instance_reset_physics_interpolation(RID p_instance) Instance *instance = instance_owner.get(p_instance); ERR_FAIL_COND(!instance); - if (instance->is_currently_interpolated()) { - instance->scenario->_interpolation_data.instance_teleport_list.push_back(p_instance); + if (_interpolation_data.interpolation_enabled && instance->interpolated) { + _interpolation_data.instance_teleport_list.push_back(p_instance); } } @@ -712,19 +684,11 @@ void RenderingServerScene::instance_set_transform(RID p_instance, const Transfor Instance *instance = instance_owner.get(p_instance); ERR_FAIL_COND(!instance); - if (!instance->is_currently_interpolated() || !instance->scenario) { + if (!(_interpolation_data.interpolation_enabled && instance->interpolated) || !instance->scenario) { if (instance->transform == p_transform) { return; //must be checked to avoid worst evil } -#ifdef DEV_ENABLED - // If we are interpolated but without a scenario, unsure whether - // this should be supported... - if (instance->is_currently_interpolated()) { - WARN_PRINT_ONCE("Instance interpolated without a scenario."); - } -#endif - #ifdef DEBUG_ENABLED for (int i = 0; i < 4; i++) { @@ -776,10 +740,10 @@ void RenderingServerScene::instance_set_transform(RID p_instance, const Transfor instance->transform_checksum_curr = new_checksum; if (!instance->on_interpolate_transform_list) { - instance->scenario->_interpolation_data.instance_transform_update_list_curr->push_back(p_instance); + _interpolation_data.instance_transform_update_list_curr->push_back(p_instance); instance->on_interpolate_transform_list = true; } else { - DEV_ASSERT(instance->scenario->_interpolation_data.instance_transform_update_list_curr->size()); + DEV_ASSERT(_interpolation_data.instance_transform_update_list_curr->size()); } // If the instance is invisible, then we are simply updating the data flow, there is no need to calculate the interpolated @@ -794,16 +758,16 @@ void RenderingServerScene::instance_set_transform(RID p_instance, const Transfor instance->interpolation_method = TransformInterpolator::find_method(instance->transform_prev.basis, instance->transform_curr.basis); if (!instance->on_interpolate_list) { - instance->scenario->_interpolation_data.instance_interpolate_update_list.push_back(p_instance); + _interpolation_data.instance_interpolate_update_list.push_back(p_instance); instance->on_interpolate_list = true; } else { - DEV_ASSERT(instance->scenario->_interpolation_data.instance_interpolate_update_list.size()); + DEV_ASSERT(_interpolation_data.instance_interpolate_update_list.size()); } _instance_queue_update(instance, true); } -void RenderingServerScene::Scenario::InterpolationData::notify_free_camera(RID p_rid, Camera &r_camera) { +void RenderingServerScene::InterpolationData::notify_free_camera(RID p_rid, Camera &r_camera) { r_camera.on_interpolate_transform_list = false; if (!interpolation_enabled) { @@ -816,7 +780,7 @@ void RenderingServerScene::Scenario::InterpolationData::notify_free_camera(RID p camera_teleport_list.erase_multiple_unordered(p_rid); } -void RenderingServerScene::Scenario::InterpolationData::notify_free_instance(RID p_rid, Instance &r_instance) { +void RenderingServerScene::InterpolationData::notify_free_instance(RID p_rid, Instance &r_instance) { r_instance.on_interpolate_list = false; r_instance.on_interpolate_transform_list = false; @@ -831,15 +795,15 @@ void RenderingServerScene::Scenario::InterpolationData::notify_free_instance(RID instance_teleport_list.erase_multiple_unordered(p_rid); } -void RenderingServerScene::update_interpolation_tick(Scenario::InterpolationData &r_interpolation_data, bool p_process) { +void RenderingServerScene::update_interpolation_tick(bool p_process) { // update interpolation in storage RSG::storage->update_interpolation_tick(p_process); // detect any that were on the previous transform list that are no longer active, // we should remove them from the interpolate list - for (unsigned int n = 0; n < r_interpolation_data.instance_transform_update_list_prev->size(); n++) { - const RID &rid = (*r_interpolation_data.instance_transform_update_list_prev)[n]; + for (unsigned int n = 0; n < _interpolation_data.instance_transform_update_list_prev->size(); n++) { + const RID &rid = (*_interpolation_data.instance_transform_update_list_prev)[n]; Instance *instance = instance_owner.getornull(rid); bool active = true; @@ -864,15 +828,15 @@ void RenderingServerScene::update_interpolation_tick(Scenario::InterpolationData } if (!active) { - r_interpolation_data.instance_interpolate_update_list.erase(rid); + _interpolation_data.instance_interpolate_update_list.erase(rid); } } // and now for any in the transform list (being actively interpolated), keep the previous transform // value up to date ready for the next tick if (p_process) { - for (unsigned int n = 0; n < r_interpolation_data.instance_transform_update_list_curr->size(); n++) { - const RID &rid = (*r_interpolation_data.instance_transform_update_list_curr)[n]; + for (unsigned int n = 0; n < _interpolation_data.instance_transform_update_list_curr->size(); n++) { + const RID &rid = (*_interpolation_data.instance_transform_update_list_curr)[n]; Instance *instance = instance_owner.getornull(rid); if (instance) { instance->transform_prev = instance->transform_curr; @@ -884,15 +848,15 @@ void RenderingServerScene::update_interpolation_tick(Scenario::InterpolationData // we maintain a mirror list for the transform updates, so we can detect when an instance // is no longer being transformed, and remove it from the interpolate list - SWAP(r_interpolation_data.instance_transform_update_list_curr, r_interpolation_data.instance_transform_update_list_prev); + SWAP(_interpolation_data.instance_transform_update_list_curr, _interpolation_data.instance_transform_update_list_prev); // prepare for the next iteration - r_interpolation_data.instance_transform_update_list_curr->clear(); + _interpolation_data.instance_transform_update_list_curr->clear(); // CAMERAS // detect any that were on the previous transform list that are no longer active, - for (unsigned int n = 0; n < r_interpolation_data.camera_transform_update_list_prev->size(); n++) { - const RID &rid = (*r_interpolation_data.camera_transform_update_list_prev)[n]; + for (unsigned int n = 0; n < _interpolation_data.camera_transform_update_list_prev->size(); n++) { + const RID &rid = (*_interpolation_data.camera_transform_update_list_prev)[n]; Camera *camera = camera_owner.getornull(rid); // no longer active? (either the instance deleted or no longer being transformed) @@ -902,8 +866,8 @@ void RenderingServerScene::update_interpolation_tick(Scenario::InterpolationData } // cameras , swap any current with previous - for (unsigned int n = 0; n < r_interpolation_data.camera_transform_update_list_curr->size(); n++) { - const RID &rid = (*r_interpolation_data.camera_transform_update_list_curr)[n]; + for (unsigned int n = 0; n < _interpolation_data.camera_transform_update_list_curr->size(); n++) { + const RID &rid = (*_interpolation_data.camera_transform_update_list_curr)[n]; Camera *camera = camera_owner.getornull(rid); if (camera) { camera->transform_prev = camera->transform; @@ -913,19 +877,19 @@ void RenderingServerScene::update_interpolation_tick(Scenario::InterpolationData // we maintain a mirror list for the transform updates, so we can detect when an instance // is no longer being transformed, and remove it from the interpolate list - SWAP(r_interpolation_data.camera_transform_update_list_curr, r_interpolation_data.camera_transform_update_list_prev); + SWAP(_interpolation_data.camera_transform_update_list_curr, _interpolation_data.camera_transform_update_list_prev); // prepare for the next iteration - r_interpolation_data.camera_transform_update_list_curr->clear(); + _interpolation_data.camera_transform_update_list_curr->clear(); } -void RenderingServerScene::update_interpolation_frame(Scenario::InterpolationData &r_interpolation_data, bool p_process) { +void RenderingServerScene::update_interpolation_frame(bool p_process) { // update interpolation in storage RSG::storage->update_interpolation_frame(p_process); // teleported instances - for (unsigned int n = 0; n < r_interpolation_data.instance_teleport_list.size(); n++) { - const RID &rid = r_interpolation_data.instance_teleport_list[n]; + for (unsigned int n = 0; n < _interpolation_data.instance_teleport_list.size(); n++) { + const RID &rid = _interpolation_data.instance_teleport_list[n]; Instance *instance = instance_owner.getornull(rid); if (instance) { instance->transform_prev = instance->transform_curr; @@ -933,24 +897,24 @@ void RenderingServerScene::update_interpolation_frame(Scenario::InterpolationDat } } - r_interpolation_data.instance_teleport_list.clear(); + _interpolation_data.instance_teleport_list.clear(); // camera teleports - for (unsigned int n = 0; n < r_interpolation_data.camera_teleport_list.size(); n++) { - const RID &rid = r_interpolation_data.camera_teleport_list[n]; + for (unsigned int n = 0; n < _interpolation_data.camera_teleport_list.size(); n++) { + const RID &rid = _interpolation_data.camera_teleport_list[n]; Camera *camera = camera_owner.getornull(rid); if (camera) { camera->transform_prev = camera->transform; } } - r_interpolation_data.camera_teleport_list.clear(); + _interpolation_data.camera_teleport_list.clear(); if (p_process) { real_t f = Engine::get_singleton()->get_physics_interpolation_fraction(); - for (unsigned int i = 0; i < r_interpolation_data.instance_interpolate_update_list.size(); i++) { - const RID &rid = r_interpolation_data.instance_interpolate_update_list[i]; + for (unsigned int i = 0; i < _interpolation_data.instance_interpolate_update_list.size(); i++) { + const RID &rid = _interpolation_data.instance_interpolate_update_list[i]; Instance *instance = instance_owner.getornull(rid); if (instance) { TransformInterpolator::interpolate_transform_via_method(instance->transform_prev, instance->transform_curr, instance->transform, f, instance->interpolation_method); @@ -1014,11 +978,11 @@ void RenderingServerScene::instance_set_visible(RID p_instance, bool p_visible) instance->visible = p_visible; // Special case for physics interpolation, we want to ensure the interpolated data is up to date - if (instance->scenario && instance->scenario->_interpolation_data.interpolation_enabled && p_visible && instance->interpolated && !instance->on_interpolate_list) { + if (_interpolation_data.interpolation_enabled && p_visible && instance->interpolated && instance->scenario && !instance->on_interpolate_list) { // Do all the extra work we normally do on instance_set_transform(), because this is optimized out for hidden instances. // This prevents a glitch of stale interpolation transform data when unhiding before the next physics tick. instance->interpolation_method = TransformInterpolator::find_method(instance->transform_prev.basis, instance->transform_curr.basis); - instance->scenario->_interpolation_data.instance_interpolate_update_list.push_back(p_instance); + _interpolation_data.instance_interpolate_update_list.push_back(p_instance); instance->on_interpolate_list = true; _instance_queue_update(instance, true); @@ -1027,7 +991,7 @@ void RenderingServerScene::instance_set_visible(RID p_instance, bool p_visible) // If this step is ignored, an unmoving instance could remain on the interpolate lists indefinitely // (or rather until the object is deleted) and cause unnecessary updates and drawcalls. if (!instance->on_interpolate_transform_list) { - instance->scenario->_interpolation_data.instance_transform_update_list_curr->push_back(p_instance); + _interpolation_data.instance_transform_update_list_curr->push_back(p_instance); instance->on_interpolate_transform_list = true; } } @@ -2527,8 +2491,7 @@ void RenderingServerScene::render_camera(RID p_camera, RID p_scenario, Size2 p_v } break; } - // This getter allows optional fixed timestep interpolation for the camera. - Transform camera_transform = camera->get_transform(); + Transform camera_transform = _interpolation_data.interpolation_enabled ? camera->get_transform_interpolated() : camera->transform; _prepare_scene(camera_transform, camera_matrix, ortho, camera->env, camera->visible_layers, p_scenario, p_shadow_atlas, RID(), camera->previous_room_id_hint); _render_scene(camera_transform, camera_matrix, 0, ortho, camera->env, p_scenario, p_shadow_atlas, RID(), -1); @@ -2883,9 +2846,7 @@ bool RenderingServerScene::free(RID p_rid) { if (camera_owner.owns(p_rid)) { Camera *camera = camera_owner.get(p_rid); - if (camera->scenario) { - camera->scenario->_interpolation_data.notify_free_camera(p_rid, *camera); - } + _interpolation_data.notify_free_camera(p_rid, *camera); camera_owner.free(p_rid); memdelete(camera); @@ -2907,14 +2868,7 @@ bool RenderingServerScene::free(RID p_rid) { Instance *instance = instance_owner.get(p_rid); - if (instance->scenario) { - instance->scenario->_interpolation_data.notify_free_instance(p_rid, *instance); - } else { - if (instance->on_interpolate_list || instance->on_interpolate_transform_list) { - // These flags should be set to false when removing the scenario. - WARN_PRINT_ONCE("Instance delete without scenario and on interpolate lists."); - } - } + _interpolation_data.notify_free_instance(p_rid, *instance); instance_set_scenario(p_rid, RID()); instance_set_base(p_rid, RID()); diff --git a/servers/rendering/rendering_server_scene.h b/servers/rendering/rendering_server_scene.h index 09908d816..23f833b5d 100644 --- a/servers/rendering/rendering_server_scene.h +++ b/servers/rendering/rendering_server_scene.h @@ -55,7 +55,13 @@ public: uint64_t render_pass; static RenderingServerScene *singleton; + /* EVENT QUEUING */ + + void tick(); + void pre_draw(bool p_will_draw); + /* CAMERA API */ + struct Scenario; struct Camera : public RID_Data { @@ -76,8 +82,6 @@ public: Transform transform; Transform transform_prev; - Scenario *scenario; - bool interpolated : 1; bool on_interpolate_transform_list : 1; @@ -86,10 +90,7 @@ public: int32_t previous_room_id_hint; - // call get transform to get either the transform straight, - // or the interpolated transform if using fixed timestep interpolation - Transform get_transform() const; - bool is_currently_interpolated() const { return scenario && scenario->is_physics_interpolation_enabled() && interpolated; } + Transform get_transform_interpolated() const; Camera() { visible_layers = 0xFFFFFFFF; @@ -100,7 +101,6 @@ public: size = 1.0; offset = Vector2(); vaspect = false; - scenario = nullptr; previous_room_id_hint = -1; interpolated = true; on_interpolate_transform_list = false; @@ -111,7 +111,6 @@ public: mutable RID_Owner camera_owner; virtual RID camera_create(); - virtual void camera_set_scenario(RID p_camera, RID p_scenario); virtual void camera_set_perspective(RID p_camera, float p_fovy_degrees, float p_z_near, float p_z_far); virtual void camera_set_orthogonal(RID p_camera, float p_size, float p_z_near, float p_z_far); virtual void camera_set_frustum(RID p_camera, float p_size, Vector2 p_offset, float p_z_near, float p_z_far); @@ -283,26 +282,6 @@ public: SelfList::List instances; - bool is_physics_interpolation_enabled() const { return _interpolation_data.interpolation_enabled; } - - // fixed timestep interpolation - struct InterpolationData { - void notify_free_camera(RID p_rid, Camera &r_camera); - void notify_free_instance(RID p_rid, Instance &r_instance); - LocalVector instance_interpolate_update_list; - LocalVector instance_transform_update_lists[2]; - LocalVector *instance_transform_update_list_curr = &instance_transform_update_lists[0]; - LocalVector *instance_transform_update_list_prev = &instance_transform_update_lists[1]; - LocalVector instance_teleport_list; - - LocalVector camera_transform_update_lists[2]; - LocalVector *camera_transform_update_list_curr = &camera_transform_update_lists[0]; - LocalVector *camera_transform_update_list_prev = &camera_transform_update_lists[1]; - LocalVector camera_teleport_list; - - bool interpolation_enabled; - } _interpolation_data; - Scenario(); ~Scenario() { memdelete(sps); } }; @@ -318,9 +297,6 @@ public: virtual void scenario_set_environment(RID p_scenario, RID p_environment); virtual void scenario_set_fallback_environment(RID p_scenario, RID p_environment); virtual void scenario_set_reflection_atlas_size(RID p_scenario, int p_size, int p_subdiv); - virtual void scenario_set_physics_interpolation_enabled(RID p_scenario, bool p_enabled); - void _scenario_tick(RID p_scenario); - void _scenario_pre_draw(RID p_scenario, bool p_will_draw); /* INSTANCING API */ @@ -380,8 +356,6 @@ public: singleton->_instance_queue_update(this, p_aabb, p_materials); } - bool is_currently_interpolated() const { return scenario && scenario->is_physics_interpolation_enabled() && interpolated; } - Instance() : scenario_item(this), update_item(this) { @@ -429,6 +403,26 @@ public: SelfList::List _instance_update_list; + // fixed timestep interpolation + virtual void set_physics_interpolation_enabled(bool p_enabled); + + struct InterpolationData { + void notify_free_camera(RID p_rid, Camera &r_camera); + void notify_free_instance(RID p_rid, Instance &r_instance); + LocalVector instance_interpolate_update_list; + LocalVector instance_transform_update_lists[2]; + LocalVector *instance_transform_update_list_curr = &instance_transform_update_lists[0]; + LocalVector *instance_transform_update_list_prev = &instance_transform_update_lists[1]; + LocalVector instance_teleport_list; + + LocalVector camera_transform_update_lists[2]; + LocalVector *camera_transform_update_list_curr = &camera_transform_update_lists[0]; + LocalVector *camera_transform_update_list_prev = &camera_transform_update_lists[1]; + LocalVector camera_teleport_list; + + bool interpolation_enabled = false; + } _interpolation_data; + void _instance_queue_update(Instance *p_instance, bool p_update_aabb, bool p_update_materials = false); struct InstanceGeometryData : public InstanceBaseData { @@ -582,6 +576,8 @@ private: void _ghost_destroy_occlusion_rep(Ghost *p_ghost); public: + /* PORTALS API */ + struct Portal : RID_Data { // all interactions with actual portals are indirect, as the portal is part of the scenario uint32_t scenario_portal_id = 0; @@ -602,7 +598,8 @@ public: virtual void portal_link(RID p_portal, RID p_room_from, RID p_room_to, bool p_two_way); virtual void portal_set_active(RID p_portal, bool p_active); - // RoomGroups + /* ROOMGROUPS API */ + struct RoomGroup : RID_Data { // all interactions with actual roomgroups are indirect, as the roomgroup is part of the scenario uint32_t scenario_roomgroup_id = 0; @@ -622,7 +619,8 @@ public: virtual void roomgroup_set_scenario(RID p_roomgroup, RID p_scenario); virtual void roomgroup_add_room(RID p_roomgroup, RID p_room); - // Occluders + /* OCCLUDERS API */ + struct OccluderInstance : RID_Data { uint32_t scenario_occluder_id = 0; Scenario *scenario = nullptr; @@ -662,10 +660,15 @@ public: // editor only .. slow virtual Geometry::MeshData occlusion_debug_get_current_polys(RID p_scenario) const; - const PortalResources &get_portal_resources() const { return _portal_resources; } - PortalResources &get_portal_resources() { return _portal_resources; } + const PortalResources &get_portal_resources() const { + return _portal_resources; + } + PortalResources &get_portal_resources() { + return _portal_resources; + } + + /* ROOMS API */ - // Rooms struct Room : RID_Data { // all interactions with actual rooms are indirect, as the room is part of the scenario uint32_t scenario_room_id = 0; @@ -699,7 +702,9 @@ public: virtual bool rooms_is_loaded(RID p_scenario) const; virtual void callbacks_register(RenderingServerCallbacks *p_callbacks); - RenderingServerCallbacks *get_callbacks() const { return _rendering_server_callbacks; } + RenderingServerCallbacks *get_callbacks() const { + return _rendering_server_callbacks; + } // don't use these in a game! virtual Vector instances_cull_aabb(const AABB &p_aabb, RID p_scenario = RID()) const; @@ -732,8 +737,8 @@ public: void update_dirty_instances(); // interpolation - void update_interpolation_tick(Scenario::InterpolationData &r_interpolation_data, bool p_process = true); - void update_interpolation_frame(Scenario::InterpolationData &r_interpolation_data, bool p_process = true); + void update_interpolation_tick(bool p_process = true); + void update_interpolation_frame(bool p_process = true); bool free(RID p_rid); diff --git a/servers/rendering/rendering_server_wrap_mt.cpp b/servers/rendering/rendering_server_wrap_mt.cpp index ade60b354..c34cdfde5 100644 --- a/servers/rendering/rendering_server_wrap_mt.cpp +++ b/servers/rendering/rendering_server_wrap_mt.cpp @@ -36,18 +36,6 @@ void RenderingServerWrapMT::thread_exit() { exit.set(); } -void RenderingServerWrapMT::thread_scenario_tick(RID p_scenario) { - if (!draw_pending.decrement()) { - rendering_server->scenario_tick(p_scenario); - } -} - -void RenderingServerWrapMT::thread_scenario_pre_draw(RID p_scenario, bool p_will_draw) { - if (!draw_pending.decrement()) { - rendering_server->scenario_pre_draw(p_scenario, p_will_draw); - } -} - void RenderingServerWrapMT::thread_draw(bool p_swap_buffers, double frame_step) { if (!draw_pending.decrement()) { rendering_server->draw(p_swap_buffers, frame_step); @@ -94,24 +82,6 @@ void RenderingServerWrapMT::sync() { } } -void RenderingServerWrapMT::scenario_tick(RID p_scenario) { - if (create_thread) { - draw_pending.increment(); - command_queue.push(this, &RenderingServerWrapMT::thread_scenario_tick, p_scenario); - } else { - rendering_server->scenario_tick(p_scenario); - } -} - -void RenderingServerWrapMT::scenario_pre_draw(RID p_scenario, bool p_will_draw) { - if (create_thread) { - draw_pending.increment(); - command_queue.push(this, &RenderingServerWrapMT::thread_scenario_pre_draw, p_scenario, p_will_draw); - } else { - rendering_server->scenario_pre_draw(p_scenario, p_will_draw); - } -} - void RenderingServerWrapMT::draw(bool p_swap_buffers, double frame_step) { if (create_thread) { draw_pending.increment(); diff --git a/servers/rendering/rendering_server_wrap_mt.h b/servers/rendering/rendering_server_wrap_mt.h index 7fbf46e9f..7cfd2f964 100644 --- a/servers/rendering/rendering_server_wrap_mt.h +++ b/servers/rendering/rendering_server_wrap_mt.h @@ -53,8 +53,6 @@ class RenderingServerWrapMT : public RenderingServer { SafeNumeric draw_pending; void thread_draw(bool p_swap_buffers, double frame_step); void thread_flush(); - void thread_scenario_tick(RID p_scenario); - void thread_scenario_pre_draw(RID p_scenario, bool p_will_draw); void thread_exit(); @@ -286,7 +284,6 @@ public: /* CAMERA API */ FUNCRID(camera) - FUNC2(camera_set_scenario, RID, RID) FUNC4(camera_set_perspective, RID, float, float, float) FUNC4(camera_set_orthogonal, RID, float, float, float) FUNC5(camera_set_frustum, RID, float, Vector2, float, float) @@ -377,13 +374,18 @@ public: FUNC7(environment_set_fog_depth, RID, bool, float, float, float, bool, float) FUNC5(environment_set_fog_height, RID, bool, float, float, float) + /* INTERPOLATION API */ + + FUNC1(set_physics_interpolation_enabled, bool) + + /* SCENARIO API */ + FUNCRID(scenario) FUNC2(scenario_set_debug, RID, ScenarioDebugMode) FUNC2(scenario_set_environment, RID, RID) FUNC3(scenario_set_reflection_atlas_size, RID, int, int) FUNC2(scenario_set_fallback_environment, RID, RID) - FUNC2(scenario_set_physics_interpolation_enabled, RID, bool) /* INSTANCING API */ FUNCRID(instance) @@ -407,7 +409,8 @@ public: FUNC2(instance_set_extra_visibility_margin, RID, real_t) - // Portals + /* PORTALS API */ + FUNC2(instance_set_portal_mode, RID, InstancePortalMode) FUNCRID(ghost) @@ -420,13 +423,15 @@ public: FUNC4(portal_link, RID, RID, RID, bool) FUNC2(portal_set_active, RID, bool) - // Roomgroups + /* ROOMGROUPS API */ + FUNCRID(roomgroup) FUNC2(roomgroup_prepare, RID, ObjectID) FUNC2(roomgroup_set_scenario, RID, RID) FUNC2(roomgroup_add_room, RID, RID) - // Occluders + /* OCCLUDERS API */ + FUNCRID(occluder_instance) FUNC2(occluder_instance_set_scenario, RID, RID) FUNC2(occluder_instance_link_resource, RID, RID) @@ -440,7 +445,8 @@ public: FUNC1(set_use_occlusion_culling, bool) FUNC1RC(Geometry::MeshData, occlusion_debug_get_current_polys, RID) - // Rooms + /* ROOMS API */ + FUNCRID(room) FUNC2(room_set_scenario, RID, RID) FUNC4(room_add_instance, RID, RID, const AABB &, const Vector &) @@ -586,8 +592,8 @@ public: virtual void finish(); virtual void draw(bool p_swap_buffers, double frame_step); virtual void sync(); - virtual void scenario_tick(RID p_scenario); - virtual void scenario_pre_draw(RID p_scenario, bool p_will_draw); + FUNC0(tick) + FUNC1(pre_draw, bool) FUNC1RC(bool, has_changed, ChangedPriority) /* RENDER INFO */ diff --git a/servers/rendering_server.h b/servers/rendering_server.h index 0c6d62363..6fd666c03 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -523,7 +523,6 @@ public: /* CAMERA API */ virtual RID camera_create() = 0; - virtual void camera_set_scenario(RID p_camera, RID p_scenario) = 0; virtual void camera_set_perspective(RID p_camera, float p_fovy_degrees, float p_z_near, float p_z_far) = 0; virtual void camera_set_orthogonal(RID p_camera, float p_size, float p_z_near, float p_z_far) = 0; virtual void camera_set_frustum(RID p_camera, float p_size, Vector2 p_offset, float p_z_near, float p_z_far) = 0; @@ -723,6 +722,10 @@ public: virtual void environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_end, float p_depth_curve, bool p_transmit, float p_transmit_curve) = 0; virtual void environment_set_fog_height(RID p_env, bool p_enable, float p_min_height, float p_max_height, float p_height_curve) = 0; + /* INTERPOLATION API */ + + virtual void set_physics_interpolation_enabled(bool p_enabled) = 0; + /* SCENARIO API */ virtual RID scenario_create() = 0; @@ -739,7 +742,6 @@ public: virtual void scenario_set_environment(RID p_scenario, RID p_environment) = 0; virtual void scenario_set_reflection_atlas_size(RID p_scenario, int p_size, int p_subdiv) = 0; virtual void scenario_set_fallback_environment(RID p_scenario, RID p_environment) = 0; - virtual void scenario_set_physics_interpolation_enabled(RID p_scenario, bool p_enabled) = 0; /* INSTANCING API */ @@ -779,8 +781,8 @@ public: virtual void instance_set_extra_visibility_margin(RID p_instance, real_t p_margin) = 0; - /* ROOMS AND PORTALS API */ - // Portals + /* PORTALS API */ + enum InstancePortalMode { INSTANCE_PORTAL_MODE_STATIC, // not moving within a room INSTANCE_PORTAL_MODE_DYNAMIC, // moving within room @@ -801,13 +803,15 @@ public: virtual void portal_link(RID p_portal, RID p_room_from, RID p_room_to, bool p_two_way) = 0; virtual void portal_set_active(RID p_portal, bool p_active) = 0; - // Roomgroups + /* ROOMGROUPS API */ + virtual RID roomgroup_create() = 0; virtual void roomgroup_prepare(RID p_roomgroup, ObjectID p_roomgroup_object_id) = 0; virtual void roomgroup_set_scenario(RID p_roomgroup, RID p_scenario) = 0; virtual void roomgroup_add_room(RID p_roomgroup, RID p_room) = 0; - // Occluders + /* OCCLUDERS API */ + enum OccluderType { OCCLUDER_TYPE_UNDEFINED, OCCLUDER_TYPE_SPHERE, @@ -829,7 +833,8 @@ public: virtual void set_use_occlusion_culling(bool p_enable) = 0; virtual Geometry::MeshData occlusion_debug_get_current_polys(RID p_scenario) const = 0; - // Rooms + /* ROOMS API */ + enum RoomsDebugFeature { ROOMS_DEBUG_SPRAWL, }; @@ -1039,8 +1044,8 @@ public: virtual bool has_changed(ChangedPriority p_priority = CHANGED_PRIORITY_ANY) const = 0; virtual void init() = 0; virtual void finish() = 0; - virtual void scenario_tick(RID p_scenario) = 0; - virtual void scenario_pre_draw(RID p_scenario, bool p_will_draw) = 0; + virtual void tick() = 0; + virtual void pre_draw(bool p_will_draw) = 0; /* STATUS INFORMATION */