-
Notifications
You must be signed in to change notification settings - Fork 13
Proper matrix transformations for sprites #19
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
base: master
Are you sure you want to change the base?
Conversation
|
Thanks! I will take a look soon. |
|
To merge this, the first thing we would have to do is take out the |
|
Removed the ultraviolet dependency, had to add a matrix rotation function to the default implementation as well (copied it from cgmath in a simplified manner). Everything seems to work, however, when you enable the Also, I think it might be a good option to incorporate |
|
You might want to keep an eye out for nalgebra now, too, because with nalgebra 0.21 and the new SIMD optimizations it is competitive with ultraviolet according to the posted benchmarks: https://rustsim.org/blog/2020/03/23/simd-aosoa-in-nalgebra/ nalgebra's biggest disadvantage to me seems to be it's complication in the documentation and such, but Personally I could go with either and I don't have a particular suggestion. They both are interesting for their own reasons. :) |
|
@zicklag, hmm, interesting, in some benchmarks it is more than 2 or 3 times faster than the ultraviolet counterpart. Also, giving some options to decide between more precise 64-bit floats and faster 16-bit floats might be a good idea, however, I might imagine there are more low-hanging optimisations |
|
Thanks! I've pushed a fix to master regarding the With regards to third party algebra libraries, |
src/kit/sprite2d/mod.rs
Outdated
| h: u32, | ||
| src: Rect<f32>, | ||
| dst: Rect<f32>, | ||
| dst: Vector2<f32>, |
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 wonder why you've changed the API here from a rect to a position + scale? This seems like an unnecessary change and will break a lot of things.
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.
In theory, Rect should be sufficient in this situation as it is basically a combination of two 2d vectors itself. However, I think it's a little clearer for an average user to have them separate as it explicitly tells you the roles of both vectors. Also, this way of handling position + scale seems to be more common among the engines used by lots of game developers (especially 2d-oriented): Love2d, XNA, Game Maker.
In the end, I think it makes sense to have both APIs available, as some users coming from Unity or even XNA as well might find the Rect API more intuitive. This approach will also allow things to not break, as you have mentioned above.
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 understand that it's a more common API, but this change is unrelated to adding rotation to sprites, and is a breaking change.
The advantage of the rect is when a specific area needs to be filled with a sprite (eg. the screen), it's easier than having to calculate the required scale.
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.
There's a lot of code out there that's going to have to be changed if the API is changed like this. If we only add angle, it's an easy fix, but changing from a Rect to a Vector pair is going to be pretty annoying.
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.
Sure, I will add back the rect API, but I think we can keep both, in the end. What do you think about this?
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.
Hmm, that could be confusing. I would rather have a builder-like API as we do for shape2d in the long term. Something like: batch.add(Sprite::new(...).scale(4.0).position([4,4]).repeat(...)..), otherwise it's a lot of parameters to remember positionally, no?
src/kit/sprite2d/mod.rs
Outdated
| -src.height() * origin.y * scale.y, | ||
| 0.0, | ||
| )); | ||
| let rotation = Matrix4::from_angle_z(*angle * 3.14 / 180.0); |
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.
There is a PI constant here: https://doc.rust-lang.org/std/f32/consts/constant.PI.html
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.
My bad, didn't know that, will replace it in the next commit.
|
@cloudhead, did the changes you mentioned, can you have a look? |
| let vec5 = Vector3::new(0.0, 1.0, 1.0); | ||
| let vec5 = transformation * vec5; | ||
| let vec6 = Vector3::new(1.0, 1.0, 1.0); | ||
| let vec6 = transformation * vec6; |
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.
You can iterate over a Vec<Vertex> and apply the transformation on each Vector2, it would be a lot cleaner :)
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.
This could still use some work.
Yup, we're getting there! Don't forget to fix the examples when you've finalized the library code. |
|
@cloudhead, finally got some time away from work and studying - so here are a couple of commits that should solve all the discussed issues. |
cloudhead
left a comment
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.
Nice progress, there are still some issues though 🧐
src/kit/sprite2d/mod.rs
Outdated
| origin: Vector2<f32> | ||
| ) -> Sprite { | ||
| Sprite::new(src).position(pos).scale(scale).origin(origin) | ||
| } |
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.
These two methods (sprite_pos and sprite_origin) are not needed.
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.
You mean the function calls, not the functions themselves?
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.
No I mean the functions themselves, since we have the builder.
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.
Gotcha.
| pub fn angle(mut self, angle: f32) -> Self { | ||
| self.angle = angle; | ||
| self | ||
| } |
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.
This API should look the same as for shape2d. See here: https://github.com/cloudhead/rgx/blob/master/src/kit/shape2d/mod.rs#L173
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, my choice of the name is not great, I agree, will change it. However, do you think passing the rotation origin each time you want to rotate the sprite is a good idea? In my mind, people will expect it to work as it does in any other modern game engine or library - set origin once and then expect all the rotations to happen around that origin point.
Also, I guess, it is more performant to avoid copying 60% more information each time you want to change the angle.
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.
This isn't a game engine though, it's a graphics library. The game entity can store its origin and then pass it in when it needs to be rendered. The extra copy of the origin will not impact performance.
src/lib.rs
Outdated
| @@ -1,4 +1,5 @@ | |||
| #![deny(clippy::all)] | |||
| #![feature(stmt_expr_attributes)] | |||
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.
What's this?
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 believe at some point I used attributes for expressions somewhere, I guess it should not be needed anymore, I will investigate 😄
| //! Most of the code in this module was borrowed from the `cgmath` package. | ||
|
|
||
| pub use num_traits::{cast, Float, One, Zero}; | ||
| use num_traits::real::Real; |
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.
Is this used?
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 will have a look, thanks for pointing that out!
|
Additionally, https://github.com/cloudhead/rgx/pull/19#discussion_r420379790 was not addressed properly. |
| pub pos: Vector2<f32>, | ||
| pub angle: f32, | ||
| pub scale: Vector2<f32>, | ||
| pub origin: Vector2<f32>, |
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.
Origin should be Point2
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.
So should pos actually.
Rename the functions, formatting
Solves #16.
This is the first introduction of proper matrix transformations for the sprite rendering. It includes scale, translation and rotation with origin. Also a new, simple example is included.
Please note, this pull request has a lot of cleaning to do, so I am waiting for your first review!