Unity Quaternion.LookRotation

public static Quaternion LookRotation(Vector3 forward, [DefaultValue(“Vector3.up”)] Vector3 upwards)
{
return Quaternion.INTERNAL_CALL_LookRotation(ref forward, ref upwards);
}
[ExcludeFromDocs]
public static Quaternion LookRotation(Vector3 forward)
{
Vector3 up = Vector3.up;
return Quaternion.INTERNAL_CALL_LookRotation(ref forward, ref up);
}

// from http://answers.unity3d.com/questions/467614/what-is-the-source-code-of-quaternionlookrotation.html
private static Quaternion INTERNAL_CALL_LookRotation(ref Vector3 forward, ref Vector3 up)
{

forward = Vector3.Normalize(forward);
Vector3 right = Vector3.Normalize(Vector3.Cross(up, forward));
up = Vector3.Cross(forward, right);
var m00 = right.x;
var m01 = right.y;
var m02 = right.z;
var m10 = up.x;
var m11 = up.y;
var m12 = up.z;
var m20 = forward.x;
var m21 = forward.y;
var m22 = forward.z;

float num8 = (m00 + m11) + m22;
var quaternion = new Quaternion();
if (num8 > 0f)
{
var num = (float)Math.Sqrt(num8 + 1f);
quaternion.w = num * 0.5f;
num = 0.5f / num;
quaternion.x = (m12 – m21) * num;
quaternion.y = (m20 – m02) * num;
quaternion.z = (m01 – m10) * num;
return quaternion;
}
if ((m00 >= m11) && (m00 >= m22))
{
var num7 = (float)Math.Sqrt(((1f + m00) – m11) – m22);
var num4 = 0.5f / num7;
quaternion.x = 0.5f * num7;
quaternion.y = (m01 + m10) * num4;
quaternion.z = (m02 + m20) * num4;
quaternion.w = (m12 – m21) * num4;
return quaternion;
}
if (m11 > m22)
{
var num6 = (float)Math.Sqrt(((1f + m11) – m00) – m22);
var num3 = 0.5f / num6;
quaternion.x = (m10 + m01) * num3;
quaternion.y = 0.5f * num6;
quaternion.z = (m21 + m12) * num3;
quaternion.w = (m20 – m02) * num3;
return quaternion;
}
var num5 = (float)Math.Sqrt(((1f + m22) – m00) – m11);
var num2 = 0.5f / num5;
quaternion.x = (m20 + m02) * num2;
quaternion.y = (m21 + m12) * num2;
quaternion.z = 0.5f * num5;
quaternion.w = (m01 – m10) * num2;
return quaternion;
}

Euler vs Quaternion

// Vector3.Lerp – linear interpolation
euler3 = Vector3.Lerp(euler1, euler2, alpha);
cube1.transform.rotation = Quaternion.Euler(euler3);
// Quaternion.Slerp – quaternion spherical linear interpolation
quat3 = Quaternion.Slerp(quat1, quat2, alpha);
cube2.transform.rotation = quat3;

Euler Rotation in Unity

// Create a Ra matrix Euler(30, 60, 45)
Matrix4x4 ra = Matrix4x4.Rotate(Quaternion.Euler(30, 60, 45));
// Create a Rb matrix rz -> rx -> ry
Matrix4x4 rz = Matrix4x4.Rotate(Quaternion.Euler(0, 0, 45));
Matrix4x4 rx = Matrix4x4.Rotate(Quaternion.Euler(30, 0, 0));
Matrix4x4 ry = Matrix4x4.Rotate(Quaternion.Euler(0, 60, 0));
Matrix4x4 rb = ry * rx * rz; // Z → X → Y

// ra == rb

// Create a Rc matrix ry -> rx -> rz
Matrix4x4 rc = rz * rx * ry; // Y → X → Z

// rb != rc

Rotate a point about an arbitrary axis

Rotate a point about an arbitrary axis (3 dimensions)
Written by Paul Bourke

https://paulbourke.net/geometry/rotate/


/*
Rotate a point p by angle around an arbitrary line segment p1-p2
Return the rotated point.
Positive angles are anticlockwise looking down the axis
towards the origin. Assume right hand coordinate system.
*/
public static Vector3 ArbitraryRotate(Vector3 p, float angle, Vector3 p1, Vector3 p2)
{
Vector3 u, q1, q2, q3, q4, q5, q6, q7;
float d;

// (1) translate space so that the rotation axis passes through the origin
q1 = p – p1;

// (2) rotate space about the x axis so that the rotation axis lies in the xz plane
u = p2 – p1; // rotation-axis vector
u = Vector3.Normalize(u);
d = Mathf.Sqrt(u.y*u.y + u.z*u.z);
if (d != 0) {
q2.x = q1.x;
q2.y = q1.y * u.z / d – q1.z * u.y / d;
q2.z = q1.y * u.y / d + q1.z * u.z / d;
} else {
q2 = q1;
}

// (3) rotate space about the y axis so that the rotation axis lies along the z axis
q3.x = q2.x * d – q2.z * u.x;
q3.y = q2.y;
q3.z = q2.x * u.x + q2.z * d;

// (4) perform the desired rotation by theta about the z axis
float theta = Mathf.Deg2Rad * angle;
q4.x = q3.x * Mathf.Cos(theta) – q3.y * Mathf.Sin(theta);
q4.y = q3.x * Mathf.Sin(theta) + q3.y * Mathf.Cos(theta);
q4.z = q3.z;

// (5) apply the inverse of step (3)
q5.x = q4.x * d + q4.z * u.x;
q5.y = q4.y;
q5.z = -q4.x * u.x + q4.z * d;

// (6) apply the inverse of step (2)
if (d != 0) {
q6.x = q5.x;
q6.y = q5.y * u.z / d + q5.z * u.y / d;
q6.z = -q5.y * u.y / d + q5.z * u.z / d;
} else {
q6 = q5;
}

// (7) apply the inverse of step (1)
q7 = q6 + p1;
return q7;
}

/*
Rotate a point p by angle around an arbitrary axis
Return the rotated point.
Positive angles are anticlockwise looking down the axis
towards the origin. Assume right hand coordinate system.
*/
public static Vector3 ArbitraryRotate(Vector3 p, float angle, Vector3 axis)
{
Vector3 q = Vector3.zero;
float costheta, sintheta;
float theta = Mathf.Deg2Rad * angle;

axis = Vector3.Normalize(axis);
costheta = Mathf.Cos(theta);
sintheta = Mathf.Sin(theta);

q.x += (costheta + (1 – costheta) * axis.x * axis.x) * p.x;
q.x += ((1 – costheta) * axis.x * axis.y – axis.z * sintheta) * p.y;
q.x += ((1 – costheta) * axis.x * axis.z + axis.y * sintheta) * p.z;

q.y += ((1 – costheta) * axis.x * axis.y + axis.z * sintheta) * p.x;
q.y += (costheta + (1 – costheta) * axis.y * axis.y) * p.y;
q.y += ((1 – costheta) * axis.y * axis.z – axis.x * sintheta) * p.z;

q.z += ((1 – costheta) * axis.x * axis.z – axis.y * sintheta) * p.x;
q.z += ((1 – costheta) * axis.y * axis.z + axis.x * sintheta) * p.y;
q.z += (costheta + (1 – costheta) * axis.z * axis.z) * p.z;

return q;
}

Composing Transformation

// white cube at origin
cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
cube.GetComponent().material.color = new Color(1.0f, 1.0f, 1.0f, 1.0f);
cube.transform.parent = this.gameObject.transform;

// translation, rotation, scale
Vector3 translation = new Vector3(1.5, 0, 0);
Quaternion rotation = Quaternion.Euler(0, 0, 45);
Vector3 scale = new Vector3(0.2, 0.2, 0.2);

// white cube with S->R->T
cube.transform.localScale = scale;
cube.transform.rotation = rotation;
cube.transform.position = translation;
Matrix4x4 matrix = cube.transform.localToWorldMatrix;
Debug.Log(“cube.transform.localToWorldMatrix=\n” + matrix);

// Create a composing transformation Scale -> Rotation -> Translation
Matrix4x4 m1 = Matrix4x4.TRS(translation, rotation, scale);
// Create a composing transformation Scale -> Rotation -> Translation
Matrix4x4 m2 = Matrix4x4.Translate(translation) *
Matrix4x4.Rotate(rotation) * Matrix4x4.Scale(scale); // Scale -> Rotation -> Translation
if (m1 == m2) Debug.Log(“m1 == m2”);
if (m1 == matrix) Debug.Log(“m1 == matrix”);

// Create a composing transformation Translation -> Rotation ->Scale
Matrix4x4 m3 = Matrix4x4.Scale(scale) *
Matrix4x4.Rotate(rotation) * Matrix4x4.Translate(translation); 
if (m1 != m3) Debug.Log(“m1 != m3”);