Closed JeroenoBoy closed 1 year ago
Ok, thank you for that brilliant work. Will merge it after finish my refactoring branch where I've reworked authoring components to be more flexible (+ some minor bug fixes).
Is it problematic to split LocalTransform2D
to 3 independent components Translation
/ Rotation
/ Scale
? Asking because I find solid TRS component is not very handy in case where I want to change the position of entity from EntityCommandBuffer
or from ComponentLookup
without erasing whole LocalTransform2D
or reading it's value to save it's rotation and scale.
Yes, that is a required component for this way of handling positions. This component gets updates via the transform system and should not be manually updated. Use LocalToWorld2D to update the positions of an entity
In your use case I think you want seperate components for the L2W? Never really required it to have seperate components myself though
Yes, that is a required component for this way of handling positions. This component gets updates via the transform system and should not be manually updated. Use LocalToWorld2D to update the positions of an entity
Can you explain me how your implementation works? Like in unity's transform we have TRS components + LocalToWorld
and LocalToParent
matrices. And all of this can be manually updated.
I'm sorry, I was a little bit out of date with current unity's transforms implementation. I've read docs and as I understand both
LocalToWorld
and LocalTransform
should be editable at runtime.
And it also seems like LocalTransform
is a preferred way to do translation / etc when you don't know your entity place at hierarchy.
I even see methods like Rotate
and Translate
for LocalTransform2D
, so it definitely should be editable.
However I see that unity no longer have TRS components and there is solid LocalTransform
component. It is a bit conflicting with performance in my mind like when I want to read only position I also load float4
and float3
for every entity. And I guess in 95% cases we really need only position.
Also as I can see despite we are in 2D space we still use 4x4 matrix passed to shader. And what is optimized is LocalTransform2D
which uses float2
properties instead of float3
as well as LocalToWorldSystem
which operates with this 2D version of LocalTransform
.
So this is quite the same implementation as a built-in one. Is this right?
Yes, that is correct. I just copied and pasted unity's version, then making it all 2d, then making it work with NSprites-foundation
There is some kind of problem with culling process. It seems like sprite gets culled every time it is NOT fully on screen. Also I doubt 2D rectangle bounds still can fully work because now we have full 3D transform matrix.
Wow it was hard! There was a bunch of problems I believe I've solved:
LocalToWorld2D.Rotation
was return wrong value new quaternion(Value)
(where value
is float4x4
matrix). instead it should return new quaternion(orthonormalize(new float3x3(Value)))
this way ltw rotation and returned by property rotation are identical.Bounds2.From
was deeply invalidated (also by previous issue) with calculation of adjusted scale. There was a formula very similar to 2x2 rotation matrix multiplication by vector2 but without a negative sin in c01. Though it calculates scale nearly right but it was needed absolute sin and cos values to account negative x and y in a right way.(.5f, .5f)
it was good but with any other values the center of bounds was somewhere in a wrong place. So I've decided to get local center and rotate it by rotation matrix.So Bounds2D.From
now looks this and package now have Bounds2DDebugSystem
which draws where bounds are.
public static Bounds2D From(in LocalToWorld2D ltw, in Scale2D size, in Pivot pivot)
{
var rotation = MathHelper.euler(ltw.Rotation).z;
var scale = ltw.Scale * size.value;
var localCenter= -scale * pivot.value + scale * .5f;
var sin = math.sin(rotation);
var cos = math.cos(rotation);
static float2 RotateScale2D(in float sin, in float cos, in float2 v)
{
var abssin = math.abs(sin);
var abscos = math.abs(cos);
return new float2(v.x * abscos + v.y * abssin, v.x * abssin + v.y * abscos);
}
static float2 RotateFloat2(in float sin, in float cos, in float2 v)
=> new(v.x * cos - v.y * sin, v.x * sin + v.y * cos);
var adjustedScale = RotateScale2D(sin, cos, scale);
var position = ltw.Position + RotateFloat2(sin, cos, localCenter);
return new Bounds2D(position, adjustedScale);
}
(the round is a actual position of a sprite)