I'm using the new Unity.Mathematics library. I'm trying to to replace Quaternion.FromTo(Vector3 from, Vector3 to) which returns a quaternion with what it would take to get a vector "from" rotated to become linearly dependent with "to".

My implementation ultimately uses the quaternion.AxisAngle method, I use a cross product to find the axis and a dot product and arccos to find the angle.

Here's what I have so far, I think the angle between is working but I included it just in case. The custom QuaternionFromToFast method is definitely not.

public static float AngleBetween(float3 v1, float3 v2)
            return AngleBetweenFast(math.normalizesafe(v1), math.normalizesafe(v2));
        public static float AngleBetweenFast(float3 v1Normalized, float3 v2Normalized)
            float dot = math.dot(v1Normalized, v2Normalized);
            return math.acos(dot);
        public static quaternion QuaternionFromToFast(float3 fromNormalized, float3 toNormalized)
            float angleBetween = AngleBetweenFast(fromNormalized, toNormalized);
            float3 axis = math.cross(fromNormalized, toNormalized);
            var fromToRotation = quaternion.AxisAngle(axis, angleBetween);

            return fromToRotation;

Here's some debug code and a gif to illustrate the issues.

When I use Unity's Quaternion.FromTo the basis vectors are all be rotated onto the same line towards the target (the blue sphere). However that is not the case with my own implementation.

Gizmos.color = Color.green;
            Gizmos.DrawRay(float3.zero, math.mul(MathUtils.QuaternionFromTo(math.right(), target), math.right()));
            Gizmos.color = Color.red;
            Gizmos.DrawRay(float3.zero, math.mul(MathUtils.QuaternionFromTo(math.forward(), target), math.forward()));
            Gizmos.color = Color.blue;
            Gizmos.DrawRay(float3.zero, math.mul(MathUtils.QuaternionFromTo(math.left(), target), math.left()));
            Gizmos.DrawSphere(target, .1f);

gif showing problems

  • \$\begingroup\$ How does the behaviour of this code differ from what you want? Do you have specific test cases for which it returns the wrong quaternion? \$\endgroup\$
    – DMGregory
    Commented Mar 28, 2022 at 1:33
  • \$\begingroup\$ Added (visual) test cases. \$\endgroup\$
    – Charly
    Commented Mar 28, 2022 at 15:01

1 Answer 1


"from" rotated to become linearly dependent with "to".

It is unclear what you are asking for.

All true vectors must be based from the origin. Points in space are not calculatable vectors for operations.

You must tranlate both points so that one point resides at the origin:

Vector3 displacement = to - from;

The rotation in Euler angles is the normalization of this vector.

Vector3 rot = math.normalizesafe(displacement);

From there you have the angles in radians:

Follow at a constant speed:

Position += rot * speed;

Project shadow movement on a world axis:

displacement.y = 0; // or hightmap[x,z];
Position += displacement;

Convert to a rotation matrix and transform onto a different axis and apply affine transformation(s), may cause streching and transform back to world space.

Too many possibilities to enumerate here.

And lastly convert it to a Quaternion


From there slerp will allow linear rotational speed.


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .