You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-14 13:41:12 +00:00
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.
This commit is contained in:
@@ -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());
|
||||
|
||||
Reference in New Issue
Block a user