Reading from LocalToWorld and quaternion [SOLVED]

Have methods to read LocalToWorld been added to the math yet? float4x4.c3.xyz gone? Also are there methods to read Euler angles from a quaternion?

If I’m doing this correctly, this is pretty awkward: 4510798--417043--upload_2019-5-7_14-48-50.png

Looking for this: 4510798--417052--upload_2019-5-7_14-56-1.png (matrix is 4x4)
or matrix.translation (matrix is LocalToWorld)

It’s on place.
4511512--417109--upload_2019-5-7_17-57-43.png

It’s wouldn’t, afaik. @Joachim_Ante_1 answered to this couple of times on this forum.

you want transform point space?
math.transform(float4x4 matrix, float3 point)

Thanks. My autocompletion barely works at times c3.xyz doesn’t show up. It’ll do the trick, I mean it’s not intuitive I had to dig up an old forum post to see that that’s how world position is done. Scale is not pretty. Hope the methods will be added soon.

Minor complaint I think math.transform(float3 point, float4x4 matrix) and math.mul(float3 vector, quaternion rotation) is more intuitive than when arguments are other way around. I’m rotating vector, taking vector and applying rotation. But when I try to do that, it acts like it’s an impossible operation until you realize that it let’s you do it if you switch vector and matrix around.

Float3 has implicit operators to Vector3, so you can do:

      Vector3 v1 = new float3();
      float3 v2 = new Vector3();

You can get translation directly from LocalToWorld without recurring to float4x4

var ltw = new LocalToWorld();
      var translation = ltw.Position;

For some reason I didn’t realize that c3 is just a float4…

Cool, thank you.

EDIT:

quaternion now has all the angle methods including Euler.

Is it possible to get rotation from LocalToWorld?

‘yes’ but it’s a tad more challenging if there is scale.

If there is no scale, just

var rotation = new quaternion(localToWorld.Value);

However if there is scale, you need to remove it first

       public static quaternion Rotation(this LocalToWorld localToWorld)
        {
            var scale = localToWorld.Value.GetScale();
            var inverted = scale.Invert();
            var value = localToWorld.Value.ScaleBy(inverted); // remove the scale

            return new quaternion(value);
        }

(GetScale, Invert and ScaleBy are other extensions of mine. let me know if you need)

2 Likes

my math is somewhat terrible, how does having scale factor into this?

I’m no good at explaining maths so I’ll just post 2 diagrams that hopefully help

Adding scale will affect these orientation vectors

1 Like

If there’s scale, you can do this:
quaternion.LookRotation(ltw.Forward, ltw.Up)

Not sure if it is faster, but it is definitely less code and works out of the box.

Edit: Use LookRotationSafe! Thanks @tertle !

2 Likes

Finally got around to testing, this doesn’t seem to work with scale. Please correct me if I’m wrong, but here is my test.

[Test]
        public void Rotation()
        {
            var scale = new float3(12, 33, 123);
            var e = new float3(0.1f, 0.2f, 0.3f);

            var position = new float3(0, 0, 0);
            var rotation = quaternion.EulerXYZ(e);

            var localToWorld = new LocalToWorld
            {
                 // seems to produce same result
                 // Value = float4x4.TRS(position, rotation, scale),
                 // But this is what Transform system uses so replicate
                 Value = math.mul(new float4x4(rotation, position), float4x4.Scale(scale)),
            };

            var result = quaternion.LookRotation(localToWorld.Forward, localToWorld.Up);

            AssertMath.AreApproximatelyEqual(rotation, result, 0.00001f);
        }

Using LookRotationSafe seems to produce the correct result (and matches what I was previously doing.)

var result = quaternion.LookRotationSafe(localToWorld.Forward, localToWorld.Up);

The direction vectors aren’t normalized when there is scale.

/// <summary>
/// Returns a quaternion view rotation given a unit length forward vector and a unit length up vector.
/// The two input vectors are assumed to be unit length and not collinear.
/// If these assumptions are not met use float3x3.LookRotationSafe instead.
/// </summary>
public static quaternion LookRotation(float3 forward, float3 up)

If you normalize the direction vectors LookRotation again produces expected result

var result = quaternion.LookRotation(math.normalize(localToWorld.Forward), math.normalize(localToWorld.Up));
3 Likes

Good catch! Thank you!

Thanks. very useful. I modified a bit your github repo to use math VS Math:

public static float3 InvertSafe(float3 f)
    {
        float x = math.abs(f.x) < float.Epsilon ? 0 : 1 / f.x;
        float y = math.abs(f.y) < float.Epsilon ? 0 : 1 / f.y;
        float z = math.abs(f.z) < float.Epsilon ? 0 : 1 / f.z;

        return new float3(x, y, z);
    }