Skip to content
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

Dose math.mul(quaternion,quaternion) return value needs to be normalized? #171

Open
lieene opened this issue Sep 29, 2020 · 3 comments
Open

Comments

@lieene
Copy link

lieene commented Sep 29, 2020

I my project. rotation.Value = math.normalize(math.mul(deltaRot, rotation.Value)); works fine.
but rotation.Value = math.mul(deltaRot, rotation.Value); Is not always working as expected.
In what condition should we normalize a quaternion?

@unpacklo
Copy link
Collaborator

unpacklo commented Oct 1, 2020

Due to rounding errors, multiplications by some delta will cause drift and your unit length quaternion may turn into a non unit length quaternion, especially if you repeatedly multiply and accumulate rotations.

Generally, you should normalize just before some other computation that requires the quaternion to be unit length. For example, if you knew that you had to multiply the quaternion several times but you only require unit length quaternions after the last multiplication, you can do this:

a = math.mul(delta, a);
a = math.mul(delta2, a);
a = math.normalize(math.mul(delta3, a));

@lieene
Copy link
Author

lieene commented Oct 7, 2020

In Unity.Entity.Transforms

    public struct LocalToWorld : IComponentData
    {
        public float4x4 Value;
        public float3 Right => new float3(Value.c0.x, Value.c0.y, Value.c0.z);
        public float3 Up => new float3(Value.c1.x, Value.c1.y, Value.c1.z);
        public float3 Forward => new float3(Value.c2.x, Value.c2.y, Value.c2.z);
        public float3 Position => new float3(Value.c3.x, Value.c3.y, Value.c3.z);
        public quaternion Rotation => new quaternion(Value);
    }

new quaternion(float4x4 ) is used directly.
But It looks like that function is not expecting and scale in the matrix, even uniform scale.
So when the matrix has scale the return quaternion would be wrong. from my tests.
I tried with my own decompose Shear Scale Rotation function and the return quaternion is right.
Is this an intentional optimization when L2W is not expected to have scale.
Or is this a bug?
P.S. the float4x4 I tested is an orthonormal transform not even sheared just uniformly scaled, with none-burst version new quaternion(float4x4 ).

also Right/Up/Forward are all not normalized. but that's fine.

@lieene
Copy link
Author

lieene commented Oct 7, 2020

Due to rounding errors, multiplications by some delta will cause drift and your unit length quaternion may turn into a non unit length quaternion, especially if you repeatedly multiply and accumulate rotations.

Generally, you should normalize just before some other computation that requires the quaternion to be unit length. For example, if you knew that you had to multiply the quaternion several times but you only require unit length quaternions after the last multiplication, you can do this:

a = math.mul(delta, a);
a = math.mul(delta2, a);
a = math.normalize(math.mul(delta3, a));

drifted away in 4d space ; )
Thanks, that's the same as my expectation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants