-
-
Notifications
You must be signed in to change notification settings - Fork 21.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix Transform::xform(Plane) functions, add Transform unit tests #50637
Conversation
afffe91
to
7316919
Compare
Reminder to myself for finishing this off after 3.4 beta:
Slight snag here, I've just been experimenting with moving the Normally this would not be a concern, but given that this function is likely to be a bottleneck in the physics (hence why it is optimized), it might be worth coming up with an alternative place for the |
@lawnjelly this PR also fixes culling issues discussed in #32764 Reason : the changes include the removal of |
Ah great, I did have a sneaking suspicion that it might! 👍 😁 I'll try and get this finished when I get a spare moment as I'm sure it solves a few bugs. I could get it finished easily by putting the function into cpp but it causes a slowdown, so I need to re-evaluate / possibly discuss with juan again where he is happy to put the |
7316919
to
c742e63
Compare
Maybe it’s worth adding specific unit tests for large scaled input values, to prevent eventual regressions on floating point precision topics in the future ? |
Possibly. We can add further unit tests once this is merged. Various tests have to be looked at on their own merit, this PR is primarily to fix a particular problem, with unit tests to address that problem - if it gets outside this scope it becomes more difficult to review. |
c742e63
to
c9985f1
Compare
After trying various permutations I've added a second commit for a variation that achieves what I think reduz was after, to keep the Transform class as simple as possible. I tried moving the So the second commit moves the fast functions to a third helper class (where we can perhaps put other such functions in the future). This means they can be inlined so will run at full speed. The only downside is these are not exposed to the binding for gdscript / gdnative etc, but realistically they are more likely to be used from the engine code in bottleneck areas. If this second commit is preferred, I can squash the commits, but I'll leave them separate until reviewed. |
c9985f1
to
60dd641
Compare
Ok changes made. I'm happy with this now. We looked at moving the I'll leave this to get the once over by @pouleyKetchoupp for the changes to physics. The physics changes are all bug fixes to allow non-uniform scales, or changes to give identical transforms by using Basis xform rather than Plane xform (where only the normal was required). I'll have a look at doing the version for 4.0 tomorrow. 👍 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes in physics look fine, I haven't re-tested but I assume you did and it still works :)
I agree with your note about having a helper function for the inverse.transpose bit, it makes the code hard to understand. Maybe it could be added as part of this PR, with something like Basis::normal_xform()
the same way we have Basis::transpose_xform()
, with a comment that explains it helps with non-uniform scaling of normals?
Yeah I'm all for making things as clear as possible in cases like this. I will do this today, but I think a separate PR would be better as this really needs merging (once 3.4 beta 3 build is sorted) to get the bugs fixed as it has spent long enough in limbo already. 👍 |
The Transform::xform and xform_inv are made safe for Planes when using non-uniform scaling. Basic unit tests for Transform. Optimization of calling sites to prevent loss of performance from the changes to xform(Plane).
60dd641
to
37f20e1
Compare
OK, all changes done, should be good now if it passes CI. I'll do the other PR for the basis function, and the version for 4.0. 👍 |
Thanks! |
The Transform::xform and xform_inv are made safe for Planes when using non-uniform scaling.
Basic unit tests for Transform.
Optimization of calling sites to prevent loss of performance from the changes to xform(Plane).
Fixes #50548
Fixes #32764
Fixes scaled objects to work in the physics (static objects seem fine there may still be some physics bugs to sort for rigid bodies).
Replacement for #50549
Notes
xform
functions, the otherxform_inv
functions in Transform remain unsafe to use except with uniform (1, 1, 1) scaling, as they use thetranspose
rather thanaffine_inverse
.Vector3
andAABB
because the current implementations aren't safe for use with scaling.--test transform
in the command line).The results of the scaling checks all fail with
xform_inv
functions, even with a regular scale (e.g. 3, 3, 3), basically anything that deviates from 1, 1, 1 scale will return incorrect results:Discussion
This has proved to be a controversial area. There are two options, exemplified by these two PRs:
(Option A) Make all headline
xform
andxform_inv
functions safe (#50549)This fixes the bug and makes all the headline xform functions safe to use with scaling transforms outside of 1, 1, 1. Alternative versions provided for special cases.
Essentially, the idea is to e.g.:
xform_inv
perform the inverse.xform_transpose
perform the transpose.At the moment we have the situation that
xform_inv
is actually the transpose.(Option B) Make only the Plane
xform
andxform_inv
functions safe (this PR)This fixes the original bug (#50548) and makes minimal other changes.
Option B is currently preferred by @reduz. He points out that for types other than
Plane
- the transpose is the 'mathematically correct' way to do this, citing that in gdscript you use the multiplication operators, and that the onus should be on the user to understand the 3d math involved.I remain unconvinced and am still personally in favour of option A, as I believe there are too many opportunities for user error with the current approach. There were a number of bugs as a result of
Plane
, and there may be other undiscovered bugs still occurring with other types, where people expectxform_inv
to be an inverse and not a transpose.Although reduz is familiar with the 3d math involved, he may be an outlier. I'm not sure it is reasonable to expect everyone, including users who may be quite young, and even all engine devs, to be so versed. I suspect that most people will expect that when you inverse a transform, you should get back to your starting point - but that is not currently the case. Note also that the function used by multiplication in gdscript need not necessarily be the same one as
xform
/xform_inv
, even though it is currently.Normal transforms
As an aside, I know Godot tries to keep the basic classes (Basis, Transform) as simple as possible, and pushes complexity to the calling code, but if we look at for example the code needed in physics, for simply transforming a normal:
Although this is technically correct, to me as a reader it is not clear.
The longhand for proper transformation of normals is 'messy', there's no getting around it. So it would be nice to do another pass at these after the PR and see whether we can have some helper functions (perhaps in a separate class?) for transforming normals, to make them easier to read if nothing else.