-
-
Notifications
You must be signed in to change notification settings - Fork 3.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
Add a few transform convenience methods #2055
Add a few transform convenience methods #2055
Conversation
Previously it was possible to convert a transform to a 4x4 matrix and then invert it, but inverting the transform in-place is both faster and more convenient.
/// homogeneous coordinates. | ||
#[inline] | ||
pub fn transform_point(&self, point: Vec3) -> Vec3 { | ||
self.scale * (self.rotation * point) |
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.
How does translation get applied here?
|
||
/// Returns the result of applying this [`GlobalTransform`] to a [`Vec3`] interpreted as a vector. | ||
/// | ||
/// This applies rotation and scale, but not translation. It's the equivalent of using w=0 in |
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.
Did we swap the comments / math here?
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.
Yeah... I sure did. lol. I'll fix that
/// Returns the result of applying this [`GlobalTransform`] to a [`Vec3`] interpreted as a point. | ||
/// | ||
/// This applies rotation, scale, and translation. It's the equivalent of using w=1 in | ||
/// homogeneous coordinates. |
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.
Could you link an appropriate explanatory article on homogenous coordinates as part of this? It's pretty dense for beginners.
https://www.tomdalling.com/blog/modern-opengl/explaining-homogenous-coordinates-and-projective-geometry/ looks quite nice.
/// Returns the inverse of this transform. | ||
/// | ||
/// The inverse consists of applying the inverse rotation, scale, and | ||
/// translation in reverse order. |
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.
I think spelling out A, then B, then C is clearer than "reverse order".
/// This applies rotation, scale, and translation. It's the equivalent of using w=1 in | ||
/// homogeneous coordinates. | ||
#[inline] | ||
pub fn transform_point(&self, point: Vec3) -> Vec3 { |
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.
Does having two functions of the same name but different function arguments work in Rust?
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.
rust doesn't have function overloading, so it should not work.
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.
One of the functions is on Transform
, the other on GlobalTransform
.
Thanks for the PR! I would also like to see some tests added to ensue these functions have the correct behavior 😄 |
Is there a preference between doc-tests vs. putting the tests in their own functions? I'm gonna add doc-tests for now, but I can change that if you want me to. |
doc tests are when the test is useful to show usage in the doc. if it's actual tests, they should live in |
While writing unit tests I discovered that the existing matrix methods are wrong. The At this point we have a choice. We can either modify |
I heavily prefer SRT as well and agree with your reasoning. If this change is implemented, please note it in the migration guide due to the serious impact on users. |
(also sorry @cart, CI approval on this one would be nice too) |
I could make a separate PR to switch to SRT, or I could make it part of this one. If we do a separate PR I'll probably wait for it to get merged before pushing the tests for this, since they depend on the transform and matrix behavior being consistent. |
@Benjamin-L, I think a separate PR is better: it'll keep the scope smaller for review and keep this PR uncontroversial. |
Alright, I'll mark this one as WIP then since it won't be complete until the other one is done. |
Another discovery: the transform composition method is also broken, even for uniform scaling. I'm gonna use RST ordering, since that's what the code currently does, but this applies for SRT as well.
For a transform
The correct way to compose transformations looks like this:
What the current code does is:
This needs to get fixed regardless of how we resolve the discrepancy between |
Actually, there's also an argument for doing both of those changes as part of the same PR: I want to add a bunch of unit tests that will catch this type of thing in the future. The unit tests won't pass until both problems are fixed. |
Nice find! Thanks a ton. I like both of those fixes in the same PR so then our unit tests can pass. |
What are your thoughts on renaming the |
I think this is a good change. I much prefer focusing on use cases rather than the raw math, and we should try to avoid redundant approaches like this where possible. Adding a doc alias would help with migration pain though :) |
Deprecating the old one instead of removing it would also be an option for less migration pain. |
Ha, I think deprecating functionality violates our Bevy ethos at this stage ;) I'd rather have pointers to the fix than worry about managing deprecation at this stage, especially since nothing else in the engine uses a deprecation strategy yet. (You're fully right that this is the right solution for more mature libraries) |
Honestly, if I was designing this system from scratch I would make the distinction between points and vectors at the type level. I've done this in most of the graphics-related things I've worked on and it has caught a ton of bugs. It does come at the cost of some increased API friction when you do need to convert between the two though, and it might be too late to consider it at this point. |
Have you seen @aevyrie's geometric primitives RFC. This sort of thing is exactly the intent of that work, and would make an excellent comment to include there. |
Ooh, I did not see that RFC before. It's pretty much exactly what I had in mind. |
Once that RFC is implemented, would it make sense to move some of these convenience methods to those structs or traits instead? It makes more sense to me than them being methods of the |
I think having methods that perform an action on a different object in the context of the |
The Mul impls seem like a nice compromise; that sounds good to me. |
Hmm, maybe it makes sense to have a more general |
I think I agree with you, but this deserves to be a comment on the RFC linked or an RFC of its own :p |
So... I just realized something. There's a reason that the order of application for |
Ah, you're right. Well, that makes the decision easy. We should try to document both the ordering and why it's needed carefully then. |
Some of the math errors would also be solved by #1755, I think. |
Oh, yes they would... It might be a good idea to wait on a decision on that issue before continuing with this. |
Yeah I'm cool with making the relevant changes in a single pr if it means adding tests for general transform op correctness. |
Wider gamedev ecosystem Transform survey: #1755 (comment) I think we should stick with the current SRT impl |
@Benjamin-L, can you comment in #2373? We've since relicensed to MIT + Apache, and I'd like to either ensure that this can be picked up or close it out. |
Closing this out as abandoned. Do not reuse this code unless the relicensing is resolved. |
Converting transforms into a matrix in order to operate on vectors or compute the inverse is poor ergonomics, and these operations can be implemented easily as methods in
Transform
andGlobalTransform
. I think the nametransform_vector
is a bit confusing, especially givenmul_vec3
exists. If anybody has a better suggestion that would be great!