Sfoglia il codice sorgente

Physics Interpolation - refactor client interpolation pump

* Move client interpolation pump to earlier in the iteration before 3D physics synced
* Allow `get_global_transform_interpolated()` to prime the client interpolation inside a physics tick
lawnjelly 1 anno fa
parent
commit
d80b206643
4 ha cambiato i file con 17 aggiunte e 9 eliminazioni
  1. 1 0
      doc/classes/Spatial.xml
  2. 3 3
      main/main.cpp
  3. 8 1
      scene/3d/spatial.cpp
  4. 5 5
      scene/main/scene_tree.cpp

+ 1 - 0
doc/classes/Spatial.xml

@@ -24,6 +24,7 @@
 			<description>
 				When using physics interpolation, there will be circumstances in which you want to know the interpolated (displayed) transform of a node rather than the standard transform (which may only be accurate to the most recent physics tick).
 				This is particularly important for frame-based operations that take place in [method Node._process], rather than [method Node._physics_process]. Examples include [Camera]s focusing on a node, or finding where to fire lasers from on a frame rather than physics tick.
+				[b]Note:[/b] This function creates an interpolation pump on the [Spatial] the first time it is called, which can respond to physics interpolation resets. If you get problems with "streaking" when initially following a [Spatial], be sure to call [method get_global_transform_interpolated] at least once [i]before[/i] resetting the [Spatial] physics interpolation.
 			</description>
 		</method>
 		<method name="get_parent_spatial" qualifiers="const">

+ 3 - 3
main/main.cpp

@@ -2367,14 +2367,14 @@ bool Main::iteration() {
 
 		uint64_t physics_begin = OS::get_singleton()->get_ticks_usec();
 
-		PhysicsServer::get_singleton()->flush_queries();
-
 		// Prepare the fixed timestep interpolated nodes
-		// BEFORE they are updated by the physics 2D,
+		// BEFORE they are updated by the physics,
 		// otherwise the current and previous transforms
 		// may be the same, and no interpolation takes place.
 		OS::get_singleton()->get_main_loop()->iteration_prepare();
 
+		PhysicsServer::get_singleton()->flush_queries();
+
 		Physics2DServer::get_singleton()->sync();
 		Physics2DServer::get_singleton()->flush_queries();
 

+ 8 - 1
scene/3d/spatial.cpp

@@ -407,7 +407,14 @@ Transform Spatial::get_global_transform_interpolated() {
 	// Pass through if physics interpolation is switched off.
 	// This is a convenience, as it allows you to easy turn off interpolation
 	// without changing any code.
-	if (Engine::get_singleton()->is_in_physics_frame() || !is_physics_interpolated_and_enabled()) {
+	if (!is_physics_interpolated_and_enabled()) {
+		return get_global_transform();
+	}
+
+	// If we are in the physics frame, the interpolated global transform is meaningless.
+	// However, there is an exception, we may want to use this as a means of starting off the client
+	// interpolation pump if not already started (when _is_physics_interpolated_client_side() is false).
+	if (Engine::get_singleton()->is_in_physics_frame() && _is_physics_interpolated_client_side()) {
 		return get_global_transform();
 	}
 

+ 5 - 5
scene/main/scene_tree.cpp

@@ -559,6 +559,11 @@ void SceneTree::iteration_prepare() {
 		// are flushed before pumping the interpolation prev and currents.
 		flush_transform_notifications();
 		VisualServer::get_singleton()->tick();
+
+		// Any objects performing client physics interpolation
+		// should be given an opportunity to keep their previous transforms
+		// up to date before each new physics tick.
+		_client_physics_interpolation.physics_process();
 	}
 }
 
@@ -575,11 +580,6 @@ bool SceneTree::iteration(float p_time) {
 
 	current_frame++;
 
-	// Any objects performing client physics interpolation
-	// should be given an opportunity to keep their previous transforms
-	// up to take before each new physics tick.
-	_client_physics_interpolation.physics_process();
-
 	flush_transform_notifications();
 
 	if (MainLoop::iteration(p_time)) {