Skip to content

Commit ac46f47

Browse files
committed
Physics Interpolation - Move 3D FTI to SceneTree
Moves 3D interpolation from server to the client code (`SceneTree`). Complete rework of 3D physics interpolation, but using the same user API.
1 parent 4ef0cd6 commit ac46f47

24 files changed

+589
-415
lines changed

core/templates/local_vector.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,15 @@ class LocalVector {
103103
return false;
104104
}
105105

106+
bool erase_unordered(const T &p_val) {
107+
int64_t idx = find(p_val);
108+
if (idx >= 0) {
109+
remove_at_unordered(idx);
110+
return true;
111+
}
112+
return false;
113+
}
114+
106115
U erase_multiple_unordered(const T &p_val) {
107116
U from = 0;
108117
U occurrences = 0;

doc/classes/BoneAttachment3D.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,5 +59,6 @@
5959
Whether the BoneAttachment3D node will override the bone pose of the bone it is attached to. When set to [code]true[/code], the BoneAttachment3D node can change the pose of the bone. When set to [code]false[/code], the BoneAttachment3D will always be set to the bone's transform.
6060
[b]Note:[/b] This override performs interruptively in the skeleton update process using signals due to the old design. It may cause unintended behavior when used at the same time with [SkeletonModifier3D].
6161
</member>
62+
<member name="physics_interpolation_mode" type="int" setter="set_physics_interpolation_mode" getter="get_physics_interpolation_mode" overrides="Node" enum="Node.PhysicsInterpolationMode" default="2" />
6263
</members>
6364
</class>

doc/classes/RenderingServer.xml

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1931,14 +1931,6 @@
19311931
Sets the visibility range values for the given geometry instance. Equivalent to [member GeometryInstance3D.visibility_range_begin] and related properties.
19321932
</description>
19331933
</method>
1934-
<method name="instance_reset_physics_interpolation">
1935-
<return type="void" />
1936-
<param index="0" name="instance" type="RID" />
1937-
<description>
1938-
Prevents physics interpolation for the current physics tick.
1939-
This is useful when moving an instance to a new location, to give an instantaneous change rather than interpolation from the previous location.
1940-
</description>
1941-
</method>
19421934
<method name="instance_set_base">
19431935
<return type="void" />
19441936
<param index="0" name="instance" type="RID" />
@@ -1980,14 +1972,6 @@
19801972
If [code]true[/code], ignores both frustum and occlusion culling on the specified 3D geometry instance. This is not the same as [member GeometryInstance3D.ignore_occlusion_culling], which only ignores occlusion culling and leaves frustum culling intact.
19811973
</description>
19821974
</method>
1983-
<method name="instance_set_interpolated">
1984-
<return type="void" />
1985-
<param index="0" name="instance" type="RID" />
1986-
<param index="1" name="interpolated" type="bool" />
1987-
<description>
1988-
Turns on and off physics interpolation for the instance.
1989-
</description>
1990-
</method>
19911975
<method name="instance_set_layer_mask">
19921976
<return type="void" />
19931977
<param index="0" name="instance" type="RID" />

doc/classes/VehicleWheel3D.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
[b]Note:[/b] The simulation does not take the effect of gears into account, you will need to add logic for this if you wish to simulate gears.
6565
A negative value will result in the wheel reversing.
6666
</member>
67+
<member name="physics_interpolation_mode" type="int" setter="set_physics_interpolation_mode" getter="get_physics_interpolation_mode" overrides="Node" enum="Node.PhysicsInterpolationMode" default="2" />
6768
<member name="steering" type="float" setter="set_steering" getter="get_steering" default="0.0">
6869
The steering angle for the wheel, in radians. Setting this to a non-zero value will result in the vehicle turning when it's moving.
6970
</member>

scene/3d/bone_attachment_3d.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,7 @@ void BoneAttachment3D::notify_rebind_required() {
366366
#endif // TOOLS_ENABLED
367367

368368
BoneAttachment3D::BoneAttachment3D() {
369+
set_physics_interpolation_mode(PHYSICS_INTERPOLATION_MODE_OFF);
369370
}
370371

371372
void BoneAttachment3D::_bind_methods() {

scene/3d/camera_3d.cpp

Lines changed: 14 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,13 @@ void Camera3D::_request_camera_update() {
4141
_update_camera();
4242
}
4343

44+
void Camera3D::fti_update_servers() {
45+
if (camera.is_valid()) {
46+
Transform3D tr = _get_adjusted_camera_transform(_get_cached_global_transform_interpolated());
47+
RS::get_singleton()->camera_set_transform(camera, tr);
48+
}
49+
}
50+
4451
void Camera3D::_update_camera_mode() {
4552
force_change = true;
4653
switch (mode) {
@@ -92,12 +99,8 @@ void Camera3D::_update_camera() {
9299
if (!is_physics_interpolated_and_enabled()) {
93100
RenderingServer::get_singleton()->camera_set_transform(camera, get_camera_transform());
94101
} else {
95-
// Ideally we shouldn't be moving a physics interpolated camera within a frame,
96-
// because it will break smooth interpolation, but it may occur on e.g. level load.
97-
if (!Engine::get_singleton()->is_in_physics_frame() && camera.is_valid()) {
98-
_physics_interpolation_ensure_transform_calculated(true);
99-
RenderingServer::get_singleton()->camera_set_transform(camera, _interpolation_data.camera_xform_interpolated);
100-
}
102+
// Force a refresh next frame.
103+
fti_notify_node_changed();
101104
}
102105

103106
if (is_part_of_edited_scene() || !is_current()) {
@@ -111,58 +114,15 @@ void Camera3D::_physics_interpolated_changed() {
111114
_update_process_mode();
112115
}
113116

114-
void Camera3D::_physics_interpolation_ensure_data_flipped() {
115-
// The curr -> previous update can either occur
116-
// on the INTERNAL_PHYSICS_PROCESS OR
117-
// on NOTIFICATION_TRANSFORM_CHANGED,
118-
// if NOTIFICATION_TRANSFORM_CHANGED takes place
119-
// earlier than INTERNAL_PHYSICS_PROCESS on a tick.
120-
// This is to ensure that the data keeps flowing, but the new data
121-
// doesn't overwrite before prev has been set.
122-
123-
// Keep the data flowing.
124-
uint64_t tick = Engine::get_singleton()->get_physics_frames();
125-
if (_interpolation_data.last_update_physics_tick != tick) {
126-
_interpolation_data.xform_prev = _interpolation_data.xform_curr;
127-
_interpolation_data.last_update_physics_tick = tick;
128-
physics_interpolation_flip_data();
129-
}
130-
}
131-
132-
void Camera3D::_physics_interpolation_ensure_transform_calculated(bool p_force) const {
133-
DEV_CHECK_ONCE(!Engine::get_singleton()->is_in_physics_frame());
134-
135-
InterpolationData &id = _interpolation_data;
136-
uint64_t frame = Engine::get_singleton()->get_frames_drawn();
137-
138-
if (id.last_update_frame != frame || p_force) {
139-
id.last_update_frame = frame;
140-
141-
TransformInterpolator::interpolate_transform_3d(id.xform_prev, id.xform_curr, id.xform_interpolated, Engine::get_singleton()->get_physics_interpolation_fraction());
142-
143-
Transform3D &tr = id.camera_xform_interpolated;
144-
tr = _get_adjusted_camera_transform(id.xform_interpolated);
145-
}
146-
}
147-
148117
void Camera3D::set_desired_process_modes(bool p_process_internal, bool p_physics_process_internal) {
149118
_desired_process_internal = p_process_internal;
150119
_desired_physics_process_internal = p_physics_process_internal;
151120
_update_process_mode();
152121
}
153122

154123
void Camera3D::_update_process_mode() {
155-
bool process = _desired_process_internal;
156-
bool physics_process = _desired_physics_process_internal;
157-
158-
if (is_physics_interpolated_and_enabled()) {
159-
if (is_current()) {
160-
process = true;
161-
physics_process = true;
162-
}
163-
}
164-
set_process_internal(process);
165-
set_physics_process_internal(physics_process);
124+
set_process_internal(_desired_process_internal);
125+
set_physics_process_internal(_desired_physics_process_internal);
166126
}
167127

168128
void Camera3D::_notification(int p_what) {
@@ -186,60 +146,18 @@ void Camera3D::_notification(int p_what) {
186146
#endif
187147
} break;
188148

189-
case NOTIFICATION_INTERNAL_PROCESS: {
190-
if (is_physics_interpolated_and_enabled() && camera.is_valid()) {
191-
_physics_interpolation_ensure_transform_calculated();
192-
193-
#ifdef RENDERING_SERVER_DEBUG_PHYSICS_INTERPOLATION
194-
print_line("\t\tinterpolated Camera3D: " + rtos(_interpolation_data.xform_interpolated.origin.x) + "\t( prev " + rtos(_interpolation_data.xform_prev.origin.x) + ", curr " + rtos(_interpolation_data.xform_curr.origin.x) + " ) on tick " + itos(Engine::get_singleton()->get_physics_frames()));
195-
#endif
196-
197-
RenderingServer::get_singleton()->camera_set_transform(camera, _interpolation_data.camera_xform_interpolated);
198-
}
199-
} break;
200-
201-
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
202-
if (is_physics_interpolated_and_enabled()) {
203-
_physics_interpolation_ensure_data_flipped();
204-
_interpolation_data.xform_curr = get_global_transform();
205-
}
206-
} break;
207-
208149
case NOTIFICATION_TRANSFORM_CHANGED: {
209-
if (is_physics_interpolated_and_enabled()) {
210-
_physics_interpolation_ensure_data_flipped();
211-
_interpolation_data.xform_curr = get_global_transform();
212150
#if defined(DEBUG_ENABLED) && defined(TOOLS_ENABLED)
151+
if (is_physics_interpolated_and_enabled()) {
213152
if (!Engine::get_singleton()->is_in_physics_frame()) {
214153
PHYSICS_INTERPOLATION_NODE_WARNING(get_instance_id(), "Interpolated Camera3D triggered from outside physics process");
215154
}
216-
#endif
217155
}
156+
#endif
218157
_request_camera_update();
219158
if (doppler_tracking != DOPPLER_TRACKING_DISABLED) {
220159
velocity_tracker->update_position(get_global_transform().origin);
221160
}
222-
// Allow auto-reset when first adding to the tree, as a convenience.
223-
if (_is_physics_interpolation_reset_requested() && is_inside_tree()) {
224-
_notification(NOTIFICATION_RESET_PHYSICS_INTERPOLATION);
225-
_set_physics_interpolation_reset_requested(false);
226-
}
227-
} break;
228-
229-
case NOTIFICATION_RESET_PHYSICS_INTERPOLATION: {
230-
if (is_inside_tree()) {
231-
_interpolation_data.xform_curr = get_global_transform();
232-
_interpolation_data.xform_prev = _interpolation_data.xform_curr;
233-
_update_process_mode();
234-
}
235-
} break;
236-
237-
case NOTIFICATION_SUSPENDED:
238-
case NOTIFICATION_PAUSED: {
239-
if (is_physics_interpolated_and_enabled() && is_inside_tree() && is_visible_in_tree()) {
240-
_physics_interpolation_ensure_transform_calculated(true);
241-
RenderingServer::get_singleton()->camera_set_transform(camera, _interpolation_data.camera_xform_interpolated);
242-
}
243161
} break;
244162

245163
case NOTIFICATION_EXIT_WORLD: {
@@ -289,8 +207,7 @@ Transform3D Camera3D::_get_adjusted_camera_transform(const Transform3D &p_xform)
289207

290208
Transform3D Camera3D::get_camera_transform() const {
291209
if (is_physics_interpolated_and_enabled() && !Engine::get_singleton()->is_in_physics_frame()) {
292-
_physics_interpolation_ensure_transform_calculated();
293-
return _interpolation_data.camera_xform_interpolated;
210+
return _get_adjusted_camera_transform(_get_cached_global_transform_interpolated());
294211
}
295212

296213
return _get_adjusted_camera_transform(get_global_transform());

scene/3d/camera_3d.h

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -97,42 +97,25 @@ class Camera3D : public Node3D {
9797
RID pyramid_shape;
9898
Vector<Vector3> pyramid_shape_points;
9999

100-
///////////////////////////////////////////////////////
101-
// INTERPOLATION FUNCTIONS
102-
void _physics_interpolation_ensure_transform_calculated(bool p_force = false) const;
103-
void _physics_interpolation_ensure_data_flipped();
104-
105-
// These can be set by derived Camera3Ds, if they wish to do processing
106-
// (while still allowing physics interpolation to function).
100+
// These can be set by derived Cameras.
107101
bool _desired_process_internal = false;
108102
bool _desired_physics_process_internal = false;
109103

110-
mutable struct InterpolationData {
111-
Transform3D xform_curr;
112-
Transform3D xform_prev;
113-
Transform3D xform_interpolated;
114-
Transform3D camera_xform_interpolated; // After modification according to camera type.
115-
uint32_t last_update_physics_tick = 0;
116-
uint32_t last_update_frame = UINT32_MAX;
117-
} _interpolation_data;
118-
119104
void _update_process_mode();
120105

121106
protected:
122107
// Use from derived classes to set process modes instead of setting directly.
123108
// This is because physics interpolation may need to request process modes additionally.
124109
void set_desired_process_modes(bool p_process_internal, bool p_physics_process_internal);
125110

126-
// Opportunity for derived classes to interpolate extra attributes.
127-
virtual void physics_interpolation_flip_data() {}
128-
129111
virtual void _physics_interpolated_changed() override;
130112
virtual Transform3D _get_adjusted_camera_transform(const Transform3D &p_xform) const;
131113
///////////////////////////////////////////////////////
132114

133115
void _update_camera();
134116
virtual void _request_camera_update();
135117
void _update_camera_mode();
118+
virtual void fti_update_servers() override;
136119

137120
void _notification(int p_what);
138121
void _validate_property(PropertyInfo &p_property) const;

0 commit comments

Comments
 (0)