Skip to content

[3.x] FTI - Add custom interpolation for wheels#105816

Merged
lawnjelly merged 1 commit intogodotengine:3.xfrom
lawnjelly:fti_hotwheels
Apr 30, 2025
Merged

[3.x] FTI - Add custom interpolation for wheels#105816
lawnjelly merged 1 commit intogodotengine:3.xfrom
lawnjelly:fti_hotwheels

Conversation

@lawnjelly
Copy link
Copy Markdown
Member

@lawnjelly lawnjelly commented Apr 27, 2025

Now the 3D FTI has been moved to scene side, we have the opportunity to finally fix wheel interpolation to cope with high speed rotation.

Fixes #72207
See #52846 (comment)
See #52846 (comment)

Description

Uses a somewhat "new" approach of managing the wheel interpolation from the vehicle rather than the wheels. This should be more efficient, and I don't think there should be any downsides. The vehicle is therefore set to the default physics_interpolation_mode ON and the wheels OFF, and the vehicle controls the wheels.

Notes

  • Adds bespoke interpolation code to cope with wheels rotating at more than 180 degrees per tick.
  • Now handles wrapping of the rotation to prevent float error once m_rotation reaches high values.
  • Also applicable to 4.x after Physics Interpolation - Move 3D FTI to SceneTree #104269 is merged.
  • Custom wheel interpolation solutions are no longer required in games after this PR.
  • Handles resets and also vehicles first entering the tree on the frame, where transform must be reset after the first physics tick (which is the first place an xform is available).

This video is 10tps showing the new wheel interpolation. Texture added to wheels to make it easier to see.

2025-04-26.19-32-17.mp4

Discussion

This doesn't provide a general solution to the problem of phasing, it is specific to wheels. If we later do decide on a general solution, this solution can easily be replaced.

@lawnjelly lawnjelly added this to the 3.7 milestone Apr 27, 2025
@lawnjelly lawnjelly requested a review from a team as a code owner April 27, 2025 07:58
@lawnjelly lawnjelly requested review from Calinou and rburing April 27, 2025 08:14
@lawnjelly lawnjelly force-pushed the fti_hotwheels branch 2 times, most recently from fb406ad to e531267 Compare April 27, 2025 09:36
@lawnjelly lawnjelly marked this pull request as draft April 27, 2025 09:41
@lawnjelly lawnjelly marked this pull request as ready for review April 27, 2025 09:54
@lawnjelly lawnjelly marked this pull request as draft April 27, 2025 10:13
@lawnjelly lawnjelly marked this pull request as ready for review April 27, 2025 10:53
@lawnjelly
Copy link
Copy Markdown
Member Author

Sorry about that faffing, I fixed the wheels to wraparound to prevent float error, and had to make some adjustments for the resets to work correctly.

@lawnjelly
Copy link
Copy Markdown
Member Author

Although the changes are pretty small to put in local space:

void VehicleBody::_update_process_mode() {
	set_process_internal(is_physics_interpolated_and_enabled());
}
void VehicleBody::_notification(int p_what) {

			Transform xform;
			Transform inv_vehicle_xform = get_global_transform_interpolated().affine_inverse();

			for (int i = 0; i < wheels.size(); i++) {
				VehicleWheel &w = *wheels[i];
				w.fti_data.update_world_xform(xform, f);
				w.set_transform(inv_vehicle_xform * xform);
			}

I'm still not absolutely convinced we should change this. The other approach is faster, and I am wondering if we should change if there is evidence that it causes a problem for a user (we are trying to future proof and predict ahead of time user problems, although I do take your point that it is in a sense compat breaking, even there is no standard yet for wheels with FTI).

It's also just as possible for the user to get local space by doing this calculation themselves (multiplying by inverse parent global xform) if they really needed it.

On the other hand if we do change it now, then it makes it more difficult to warrant taking it out at a later stage. 🤔

Let me know what you think, I can easily change it back.

@rburing
Copy link
Copy Markdown
Member

rburing commented Apr 29, 2025

While it's not the most common thing to access a wheel's local transform, I could imagine e.g. someone using position.z to distinguish wheels, which would quietly break if position was suddenly the global position.

Perhaps in the future wheels could be top-level by default and it could be documented that they only work as top-level. The middle ground of setting top-level dynamically would be annoying to document and understand, though the code would be more efficient.

@lawnjelly
Copy link
Copy Markdown
Member Author

lawnjelly commented Apr 30, 2025

I'll update the 4.x PR with the changes.

BTW for future reference there are several implications to local space versus global space here:

  • Extra calculation when sending to server.
  • Extra calculation in the scene traversal code (the scene traversal code recognises top_level)
  • Could end up in a different position if a node was moved above the vehicle in the scene tree on the frame (this might be better, but is a difference)

More generally physics objects update their transforms via the global xform afaik, so to some extent multiplying by inverse parent xform is "pretending" that they are in local space, but maybe that makes it easier for users to understand. It also has implications for their interpolation "track", as interpolation takes place in local space.

@lawnjelly lawnjelly merged commit 909cb94 into godotengine:3.x Apr 30, 2025
14 checks passed
@lawnjelly
Copy link
Copy Markdown
Member Author

Thanks!

@lawnjelly lawnjelly deleted the fti_hotwheels branch April 30, 2025 07:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants