瀏覽代碼

Merge pull request #60147 from lawnjelly/interpolation_out_of_scenario

Rémi Verschelde 3 年之前
父節點
當前提交
e1eb3c2fb1

+ 0 - 6
scene/3d/camera.cpp

@@ -115,10 +115,6 @@ void Camera::_notification(int p_what) {
 			if (current || first_camera) {
 				viewport->_camera_set(this);
 			}
-
-			ERR_FAIL_COND(get_world().is_null());
-			VisualServer::get_singleton()->camera_set_scenario(camera, get_world()->get_scenario());
-
 		} break;
 		case NOTIFICATION_TRANSFORM_CHANGED: {
 			_request_camera_update();
@@ -132,8 +128,6 @@ void Camera::_notification(int p_what) {
 			}
 		} break;
 		case NOTIFICATION_EXIT_WORLD: {
-			VisualServer::get_singleton()->camera_set_scenario(camera, RID());
-
 			if (!get_tree()->is_node_being_edited(this)) {
 				if (is_current()) {
 					clear_current();

+ 5 - 17
scene/main/scene_tree.cpp

@@ -507,13 +507,7 @@ void SceneTree::set_physics_interpolation_enabled(bool p_enabled) {
 	}
 
 	_physics_interpolation_enabled = p_enabled;
-
-	if (root->get_world().is_valid()) {
-		RID scenario = root->get_world()->get_scenario();
-		if (scenario.is_valid()) {
-			VisualServer::get_singleton()->scenario_set_physics_interpolation_enabled(scenario, p_enabled);
-		}
-	}
+	VisualServer::get_singleton()->set_physics_interpolation_enabled(p_enabled);
 }
 
 bool SceneTree::is_physics_interpolation_enabled() const {
@@ -535,11 +529,8 @@ bool SceneTree::iteration(float p_time) {
 
 	current_frame++;
 
-	if (root->get_world().is_valid()) {
-		RID scenario = root->get_world()->get_scenario();
-		if (scenario.is_valid()) {
-			VisualServer::get_singleton()->scenario_tick(scenario);
-		}
+	if (_physics_interpolation_enabled) {
+		VisualServer::get_singleton()->tick();
 	}
 
 	// Any objects performing client physics interpolation
@@ -686,11 +677,8 @@ bool SceneTree::idle(float p_time) {
 
 #endif
 
-	if (root->get_world().is_valid()) {
-		RID scenario = root->get_world()->get_scenario();
-		if (scenario.is_valid()) {
-			VisualServer::get_singleton()->scenario_pre_draw(scenario, true);
-		}
+	if (_physics_interpolation_enabled) {
+		VisualServer::get_singleton()->pre_draw(true);
 	}
 
 	return _quit;

+ 0 - 8
servers/visual/visual_server_raster.cpp

@@ -94,14 +94,6 @@ void VisualServerRaster::request_frame_drawn_callback(Object *p_where, const Str
 	frame_drawn_callbacks.push_back(fdc);
 }
 
-void VisualServerRaster::scenario_tick(RID p_scenario) {
-	VSG::scene->_scenario_tick(p_scenario);
-}
-
-void VisualServerRaster::scenario_pre_draw(RID p_scenario, bool p_will_draw) {
-	VSG::scene->_scenario_pre_draw(p_scenario, p_will_draw);
-}
-
 void VisualServerRaster::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
 	VS::get_singleton()->emit_signal("frame_pre_draw");

+ 24 - 10
servers/visual/visual_server_raster.h

@@ -116,8 +116,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) \
@@ -448,10 +452,14 @@ public:
 //from now on, calls forwarded to this singleton
 #define BINDBASE VSG::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)
@@ -548,20 +556,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 VSG::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)
@@ -583,7 +595,8 @@ public:
 
 	BIND2(instance_set_extra_visibility_margin, RID, real_t)
 
-	// Portals
+	/* PORTALS */
+
 	BIND2(instance_set_portal_mode, RID, InstancePortalMode)
 
 	BIND0R(RID, ghost_create)
@@ -596,13 +609,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)
@@ -616,7 +631,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<Vector3> &)
@@ -764,8 +780,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 */
 

+ 50 - 98
servers/visual/visual_server_scene.cpp

@@ -39,8 +39,8 @@
 
 /* CAMERA API */
 
-Transform VisualServerScene::Camera::get_transform() const {
-	if (!is_currently_interpolated()) {
+Transform VisualServerScene::Camera::get_transform_interpolated() const {
+	if (!interpolated) {
 		return transform;
 	}
 
@@ -54,25 +54,6 @@ RID VisualServerScene::camera_create() {
 	return camera_owner.make_rid(camera);
 }
 
-void VisualServerScene::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 VisualServerScene::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);
@@ -105,8 +86,8 @@ void VisualServerScene::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);
 	}
 }
 
@@ -122,9 +103,9 @@ void VisualServerScene::camera_set_transform(RID p_camera, const Transform &p_tr
 
 	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;
 		}
 
@@ -302,7 +283,6 @@ void VisualServerScene::SpatialPartitioningScene_Octree::set_balance(float p_bal
 
 VisualServerScene::Scenario::Scenario() {
 	debug = VS::SCENARIO_DEBUG_DISABLED;
-	_interpolation_data.interpolation_enabled = false;
 
 	bool use_bvh_or_octree = GLOBAL_GET("rendering/quality/spatial_partitioning/use_bvh");
 
@@ -470,30 +450,22 @@ RID VisualServerScene::scenario_create() {
 	return scenario_rid;
 }
 
-void VisualServerScene::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 VisualServerScene::set_physics_interpolation_enabled(bool p_enabled) {
+	_interpolation_data.interpolation_enabled = p_enabled;
 }
 
-void VisualServerScene::_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 VisualServerScene::tick() {
+	if (_interpolation_data.interpolation_enabled) {
+		update_interpolation_tick(true);
 	}
 }
 
-void VisualServerScene::_scenario_pre_draw(RID p_scenario, bool p_will_draw) {
-	Scenario *scenario = scenario_owner.get(p_scenario);
-	ERR_FAIL_COND(!scenario);
-
+void VisualServerScene::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);
 	}
 }
 
@@ -730,7 +702,7 @@ void VisualServerScene::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 VS::INSTANCE_LIGHT: {
@@ -801,8 +773,8 @@ void VisualServerScene::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);
 	}
 }
 
@@ -816,19 +788,11 @@ void VisualServerScene::instance_set_transform(RID p_instance, const Transform &
 	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++) {
@@ -883,23 +847,23 @@ void VisualServerScene::instance_set_transform(RID p_instance, const Transform &
 	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 (!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 VisualServerScene::Scenario::InterpolationData::notify_free_camera(RID p_rid, Camera &r_camera) {
+void VisualServerScene::InterpolationData::notify_free_camera(RID p_rid, Camera &r_camera) {
 	r_camera.on_interpolate_transform_list = false;
 
 	if (!interpolation_enabled) {
@@ -912,7 +876,7 @@ void VisualServerScene::Scenario::InterpolationData::notify_free_camera(RID p_ri
 	camera_teleport_list.erase_multiple_unordered(p_rid);
 }
 
-void VisualServerScene::Scenario::InterpolationData::notify_free_instance(RID p_rid, Instance &r_instance) {
+void VisualServerScene::InterpolationData::notify_free_instance(RID p_rid, Instance &r_instance) {
 	r_instance.on_interpolate_list = false;
 	r_instance.on_interpolate_transform_list = false;
 
@@ -927,15 +891,15 @@ void VisualServerScene::Scenario::InterpolationData::notify_free_instance(RID p_
 	instance_teleport_list.erase_multiple_unordered(p_rid);
 }
 
-void VisualServerScene::update_interpolation_tick(Scenario::InterpolationData &r_interpolation_data, bool p_process) {
+void VisualServerScene::update_interpolation_tick(bool p_process) {
 	// update interpolation in storage
 	VSG::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;
@@ -960,15 +924,15 @@ void VisualServerScene::update_interpolation_tick(Scenario::InterpolationData &r
 		}
 
 		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;
@@ -980,15 +944,15 @@ void VisualServerScene::update_interpolation_tick(Scenario::InterpolationData &r
 
 	// 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)
@@ -998,8 +962,8 @@ void VisualServerScene::update_interpolation_tick(Scenario::InterpolationData &r
 	}
 
 	// 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;
@@ -1009,19 +973,19 @@ void VisualServerScene::update_interpolation_tick(Scenario::InterpolationData &r
 
 	// 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 VisualServerScene::update_interpolation_frame(Scenario::InterpolationData &r_interpolation_data, bool p_process) {
+void VisualServerScene::update_interpolation_frame(bool p_process) {
 	// update interpolation in storage
 	VSG::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;
@@ -1029,24 +993,24 @@ void VisualServerScene::update_interpolation_frame(Scenario::InterpolationData &
 		}
 	}
 
-	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);
@@ -2803,8 +2767,7 @@ void VisualServerScene::render_camera(RID p_camera, RID p_scenario, Size2 p_view
 		} 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);
@@ -4466,10 +4429,7 @@ void VisualServerScene::update_dirty_instances() {
 bool VisualServerScene::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);
@@ -4490,15 +4450,7 @@ bool VisualServerScene::free(RID p_rid) {
 		update_dirty_instances();
 
 		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_use_lightmap(p_rid, RID(), RID(), -1, Rect2(0, 0, 1, 1));
 		instance_set_scenario(p_rid, RID());

+ 45 - 41
servers/visual/visual_server_scene.h

@@ -57,6 +57,11 @@ public:
 	uint64_t render_pass;
 	static VisualServerScene *singleton;
 
+	/* EVENT QUEUING */
+
+	void tick();
+	void pre_draw(bool p_will_draw);
+
 	/* CAMERA API */
 	struct Scenario;
 
@@ -78,8 +83,6 @@ public:
 		Transform transform;
 		Transform transform_prev;
 
-		Scenario *scenario;
-
 		bool interpolated : 1;
 		bool on_interpolate_transform_list : 1;
 
@@ -88,10 +91,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;
@@ -102,7 +102,6 @@ public:
 			size = 1.0;
 			offset = Vector2();
 			vaspect = false;
-			scenario = nullptr;
 			previous_room_id_hint = -1;
 			interpolated = true;
 			on_interpolate_transform_list = false;
@@ -113,7 +112,6 @@ public:
 	mutable RID_Owner<Camera> 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);
@@ -270,26 +268,6 @@ public:
 
 		SelfList<Instance>::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<RID> instance_interpolate_update_list;
-			LocalVector<RID> instance_transform_update_lists[2];
-			LocalVector<RID> *instance_transform_update_list_curr = &instance_transform_update_lists[0];
-			LocalVector<RID> *instance_transform_update_list_prev = &instance_transform_update_lists[1];
-			LocalVector<RID> instance_teleport_list;
-
-			LocalVector<RID> camera_transform_update_lists[2];
-			LocalVector<RID> *camera_transform_update_list_curr = &camera_transform_update_lists[0];
-			LocalVector<RID> *camera_transform_update_list_prev = &camera_transform_update_lists[1];
-			LocalVector<RID> camera_teleport_list;
-
-			bool interpolation_enabled;
-		} _interpolation_data;
-
 		Scenario();
 		~Scenario() { memdelete(sps); }
 	};
@@ -305,9 +283,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 */
 
@@ -365,8 +340,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) {
@@ -412,6 +385,26 @@ public:
 
 	SelfList<Instance>::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<RID> instance_interpolate_update_list;
+		LocalVector<RID> instance_transform_update_lists[2];
+		LocalVector<RID> *instance_transform_update_list_curr = &instance_transform_update_lists[0];
+		LocalVector<RID> *instance_transform_update_list_prev = &instance_transform_update_lists[1];
+		LocalVector<RID> instance_teleport_list;
+
+		LocalVector<RID> camera_transform_update_lists[2];
+		LocalVector<RID> *camera_transform_update_list_curr = &camera_transform_update_lists[0];
+		LocalVector<RID> *camera_transform_update_list_prev = &camera_transform_update_lists[1];
+		LocalVector<RID> 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 {
@@ -688,6 +681,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;
@@ -708,7 +703,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;
@@ -728,7 +724,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;
@@ -768,10 +765,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;
@@ -805,7 +807,9 @@ public:
 	virtual bool rooms_is_loaded(RID p_scenario) const;
 
 	virtual void callbacks_register(VisualServerCallbacks *p_callbacks);
-	VisualServerCallbacks *get_callbacks() const { return _visual_server_callbacks; }
+	VisualServerCallbacks *get_callbacks() const {
+		return _visual_server_callbacks;
+	}
 
 	// don't use these in a game!
 	virtual Vector<ObjectID> instances_cull_aabb(const AABB &p_aabb, RID p_scenario = RID()) const;
@@ -840,8 +844,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);
 
 	//probes
 	struct GIProbeDataHeader {

+ 0 - 30
servers/visual/visual_server_wrap_mt.cpp

@@ -36,18 +36,6 @@ void VisualServerWrapMT::thread_exit() {
 	exit.set();
 }
 
-void VisualServerWrapMT::thread_scenario_tick(RID p_scenario) {
-	if (!draw_pending.decrement()) {
-		visual_server->scenario_tick(p_scenario);
-	}
-}
-
-void VisualServerWrapMT::thread_scenario_pre_draw(RID p_scenario, bool p_will_draw) {
-	if (!draw_pending.decrement()) {
-		visual_server->scenario_pre_draw(p_scenario, p_will_draw);
-	}
-}
-
 void VisualServerWrapMT::thread_draw(bool p_swap_buffers, double frame_step) {
 	if (!draw_pending.decrement()) {
 		visual_server->draw(p_swap_buffers, frame_step);
@@ -94,24 +82,6 @@ void VisualServerWrapMT::sync() {
 	}
 }
 
-void VisualServerWrapMT::scenario_tick(RID p_scenario) {
-	if (create_thread) {
-		draw_pending.increment();
-		command_queue.push(this, &VisualServerWrapMT::thread_scenario_tick, p_scenario);
-	} else {
-		visual_server->scenario_tick(p_scenario);
-	}
-}
-
-void VisualServerWrapMT::scenario_pre_draw(RID p_scenario, bool p_will_draw) {
-	if (create_thread) {
-		draw_pending.increment();
-		command_queue.push(this, &VisualServerWrapMT::thread_scenario_pre_draw, p_scenario, p_will_draw);
-	} else {
-		visual_server->scenario_pre_draw(p_scenario, p_will_draw);
-	}
-}
-
 void VisualServerWrapMT::draw(bool p_swap_buffers, double frame_step) {
 	if (create_thread) {
 		draw_pending.increment();

+ 17 - 10
servers/visual/visual_server_wrap_mt.h

@@ -54,8 +54,6 @@ class VisualServerWrapMT : public VisualServer {
 	SafeNumeric<uint64_t> 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();
 
@@ -374,7 +372,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)
@@ -468,15 +465,21 @@ 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)
 
 	FUNC2(instance_set_base, RID, RID)
@@ -498,7 +501,8 @@ public:
 
 	FUNC2(instance_set_extra_visibility_margin, RID, real_t)
 
-	// Portals
+	/* PORTALS API */
+
 	FUNC2(instance_set_portal_mode, RID, InstancePortalMode)
 
 	FUNCRID(ghost)
@@ -511,13 +515,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)
@@ -531,7 +537,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<Vector3> &)
@@ -674,8 +681,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 */

+ 14 - 9
servers/visual_server.h

@@ -619,7 +619,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;
@@ -821,6 +820,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;
@@ -837,7 +840,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 */
 
@@ -881,8 +883,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
@@ -903,13 +905,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,
@@ -931,7 +935,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,
 	};
@@ -1131,8 +1136,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 */