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
d2b1d29634
This commit is contained in:
Relintai 2023-08-27 17:25:38 +02:00
parent 736106af8a
commit 87b91721da
9 changed files with 158 additions and 229 deletions

View File

@ -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();

View File

@ -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;

View File

@ -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");

View File

@ -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<Vector3> &)
@ -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 */

View File

@ -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());

View File

@ -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> 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<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); }
};
@ -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<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 {
@ -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<ObjectID> 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);

View File

@ -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();

View File

@ -53,8 +53,6 @@ class RenderingServerWrapMT : public RenderingServer {
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();
@ -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<Vector3> &)
@ -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 */

View File

@ -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 */