#2D Transforms
1100 messages · Page 2 of 2 (latest)
I know this group is working on Transforms and has the most concern for the VecN APIs. I am happy to move this if there is a better place.
I've explored how each of the VecN types can be turned into SIMD types (f32x4, __m128). Clean loads and stores are what SIMD writers need to move out of GLAM and into more powerful SIMD types.
Vec2 is perfect for 8 byte loads.
Vec4 is perfect for 16 byte loads.
Vec3 is not ideal. Loading it into register requires a 8 byte load, a 4 byte load, and a swizzle. Storing is similar.
Vec3A is almost perfect.
- GLAM's scalar implementation constructors do not set the padding. A 16 byte load is reading uninitialized memory, which is UB.
- GLAM's vectorized implementations initialize padding in both constructors.
Vec3A::splatproducesXXXXandVec3A::newproducesXYZZ. As the padding is initialized, reading the padding is technically not UB. - The inability to access the secret
wfield prevents superword-level parallelism auto-vectorization strategies.
TL;DR: pls no Vec3
Whats the current status of this Working Group? If you were to propose a Goal, what would you call it?
2D Transforms?
yes
i think it's stalled out on staffing, both me and @crystal wolf are very interested in supporting this work but no one is driving atm
so maybe not staffing but more like lead contributor
i think theres just more pressing things atm
things might be a bit clearer after renderer unification
I'm also a bit curious to see how it would feed into unified rendering. Blurring the lines between 2D and 3D is in some ways a competing goal to specialized 2D apis
agree. that basically emerged as a more pressing goal
Personally I only care about the rendering side of 2d improvements. The transform side I don't care much about. If it was me I'd just use 3d transform everywhere 😅
we really need to do that asap cus the maintenance burden in bug surface is really bad
hahaha totally fair enough!
in that case let’s def call this one postponed ?
Yeah, I think that makes the most sense
im invested in this mostly from the point of view of having alternative transforms be more well supported
i dont particularly care much about 2d
i care about it bc it’s a good target market for us that we don’t support the best
it would be nice if we had a 2d sme but no one has shown that interest/competecy
all the rendering contribs just care about 3d
part of the goal of the infra unification was to ensure at least that 2d doesn't get left behind even if it still could use more QoL stuff
a lot of QoL can probably be done in userspace too
My big fear about alternative transforms (in all cases) is that it means code that operates on them must also be specialized.
Ex: if you are blending 2D and 3D (ex: you're using sprites in 3D or something) and you want to "move everything in the +X direction", you need to write code for both Transform and Transform2d
that sounds like user code and thus a user problem
They wouldn't have the problem if we forced them to use Transform for both cases
the name is probably a little to narrow too, this was also about more generally supporting patterns like y-sort and z-index that many users seem to expect and interact with transforms
i dont think forcing the user to do anything is a good idea
If we have an upstream Transform2d that is the "defaut" for sprites, then we're inherently forcing developers to write 2D and 3D code separately
this is a bit in the weeds
I agree with your sentiment. But all API design is "forcing users to do something". The point of Bevy is to provide "ways of thinking" that produce the best benefit for the most people
i think we should prob postpone this
fair
imo api should encourage good practices which have good outcomes, it shouldnt hold your paintbrush and tell you how you can use it
its a hard problem space mostly cus of the ecosystem
Agreed. But also this principle can be used to argue for or against 2D transforms
yeah to be clear i dont have a concrete stance on whether there should be a 2d transform upstream, i more believe that bevy should make it easier to have custom transform types, which provide a conversion to GlobalTransform for rendering, and propagation rules for hierarchy
my mantra is that the engine should have an untyped, data driven core with a typeful and humane opinionated api on top which reflects our way of thinking. but those who want to be heterodox should be able to re-use all the important engine features without having to reimplement the entire engine themselves (i.e. rendering)
i dont like our existing Transform, and its inherently a very opinionated thing which everything builds upon
which is another way of saying it should be possible for someone to do Transform2d in userspace
exactly
Transform itself should not be a foundational crate
it should be possible to swap in userspace
thats a tall ask though
we are so aligned char lol
my vibe is that the "inner" api doesn't have to be like "good" it just needs to be possible
i think Transform is that type for the renderer
the main thing you'd have to solve in userspace yourself is propagation
patricks mesh extraction stuff is kind of the api
which would be really difficult to re-implement yourself
but the work we're doing on 2d will hopefully make just a bit more generic
since we need to be able to support 2d mesh instances on the gpu
so i think we'll get there through that work
I mean, it is? That's what we do at work. We disable the TransformPlugin and use our own thing that outputs a GlobalTransform. Or do you mean something different?
we dont use all of bevy at work
like animation for example i would doubt could work with what we do
Ah, right, good point
i also dont think that its possible to remove Transform from Camera
we tack stuff on top
we dont really replace it
I guess the renderer itself is good at not depending on Transform too much but that's not true for everything else
i think vero is imagining without GlobalTransform too?
I want to bring in the example of UiTransform and UiGlobalTransform. This was a change made a couple of release back, part of the motivation was that Transform was too complicated for most UI users - people didn't want to have to deal with Quats when rotating stuff in 2d, the entity origin point was computed differently, etc. However, this change was also a regression in terms of our desire to unify the different modalities of 2d, 3d and ui.
The way I like to think about this is that there are two levels of transform. Currently we have a "local" and "global" transform; but we can also think of these as the "ergonomic" vs. "universal" transform: the ergonomic transform is more opinionated, simplified, easier to use in a given context but at the price of fewer choices; whereas the "universal" transform is a superset of what all of the different ergonomic transforms are able to represent. So 2d rotation gets turned into a quat, since one is a subset of the other.
Also, one big difference between Transform and UiTransform was the rules on when it was legal to mutate it.
Because the UI layout system modifies transforms, but people also want to be able to animate ui elements.
this is a big reason we want to bring ui into the shared renderer infra
personally i'm agnostic about all these questions even though i think they're really important
but we want to have a clear line where the render can just be something that eats data and goes brrr
and i'd like to support y'all having that debate
without needing to rewrite 100% of 2d/ui rendering itnernals
yeah that
s what i meant to say
but good to clarify you're fine with that in main world
fwiw ive heard global transform referred to as "render transform" sometimes and i deeply disagree with that
thats not a good rename and should not be done
game logic for computing entity distance and other things like audio spatialization depend on GlobalTransform
its the renderer api but does not belong to the renderer
same way bevy lights are the rendering api but do not belong to the renderer
its scene definitiion
do you guys think that looking at Godot's implementation (afaik they have two different apis for 2d and 3d) would be valuable?
2D Transforms
FWIW one thing I really enjoy about Transform being used for 2D as well is that I can within fully 2D projects decide on standard 'thicknesses'/ranges for particular subtrees (like say a hand of cards being [-1,1] and laying out its cards within that range). Then in the parent tree where I use them (like a whole scene/interface that includes a hand of cards), scale/translate it on Z to take up a particular slice of that tree's thickness, or even animate gradually going in front of/behind the Z levels reserved for other elements. I wouldn't be able to do this if Sprite just used an unsigned integer Z index (without adding custom systems that generate Z indexes)
i ran into that problem recently where i wanted to animate a card by rotating it in the z axis
but shouldn’t a shader solve this instead? or maybe you can instantiate a 3d plane and put the sprites texture on it.
for performance/optimization reasons maybe having 2 apis for 2d and 3d could help, i’m sure there would be a lot of code that can be ignored to reduce compile times, lower binary size, etc
I realise that this has probably been suggested many times, but what are the reasons we can't:
Have &Transform and &mut Transform implement QueryData such that the item they return is a type which stores &mut or & versions of each separate Translation, Rotation, and Scale component.
Have Transform implement Bundle.
Notably Transform is not a Component, despite being used very similarly to one.
We can then have a Transform2d which works similarly, but has convenience methods for 2d.
I believe I can provide a simple proof of concept for this.
The code shouldn't be too difficult, aside from the manual implementation of bundle, which the documentation explicitly forbids.
I'll update this message once I have concocted that proof of concept.
While it is missing some of the features, it does at least show the heart of the idea in this file: https://github.com/coolcatcoder/schedule/blob/master/src/transform_2d.rs
My idea would solve this problem that I am replying to.
Anything targeting Transform also affects Transform2d, because neither are components, just fancy wrappers.
~~Without virtual fields or a way to deref to Transform2dItemMut<'a>, change detection is impossible if you want direct access to &mut Vec2 fields.
Instead you have to use functions to get access to the translation, rotation, and scale.
A bit clunky.
(If there were someway of getting a Mut<T> for each field, then that could work, but that is beyond what I know how to do.)
Edit: Actually. I have an idea. I'll keep playing around.~~
Oh wow, it works.
I've gotten change detection working, while still having fields.
Nice. Will commit later, as I still need to beautify my code a bit.
Ah you know what, I can make it pretty in the morning. I've committed the current ugly mess that works.
I looked through the pinned messages in the interest of seeing what it would take to get this WG back on track. The hackmd document has a good summary but has not been updated in a while: https://hackmd.io/U3KBDCeGSk-gwJwDpNmzGQ
However, I think the doc punts on too many things
This is not to say that we should try to solve everything at once, but we need a grand vision of where we want to get to that at least acknowledges these other issues
Like maybe we aren't moving away from UiGlobalTransform soonish, but at least should settle on where it fits in the overall picture
I envision a design centered on a dependency graph of specialized components
I know I’m very late to the party but I feel like creating a new Transform2d component is pretty unecessary?
I feel like a lot of the problems this is meant to fix are problems that exist within Transform itself and are just more obvious in 2D, and would be fixed by simply providing a better API and tools for working with Transform (more concise, accessible ways to rotate a specific axis, for instance).
Having a Transform2D component seems to just complicate things internally because it’d be another abstraction that would have to be maintained along with the Transform component. I believe both Unity and Godot have the same generic Transform for every object.
If anything, maybe a 2D counterpart should just be a purely visual, optional, abstraction over the normal Transform in the editor / inspector, but even that feels quite unecessary.
Same applies to the UI transform, is it really beneficial to split up and duplicate the API rather than making it more modular and simpler to use?
Sorry for being such a hater, I’ve just been skimmimg through this thread for the first time and, as a mainly 2D game dev, I feel a lot of these ideas are misguided. Obviously I may be wrong or not seeing the whole picture, in which case I’m eager to hear what these planned changes actually bring to the table.
I could agree with that take.
Except that I still think that there is value in having a Transform2d that, while not a component, implements enough traits to pretend to be one. (In reality the implementation would always defer back to the central Transform component.)
(This is also really simple to implement in a third party crate. I personally do this, and I find it works great.)
yeah I think this would be pretty cool if it works and can be implemented in a way that doesn’t require significant extra maintainence