Orienting objects in a 3D software can be a task that sometimes takes more time than predicted. In Autodesk Maya it can be obtained in several different ways - constraints, direct connections or even the OrientJoint tool if the object is type is a joint.
Nevertheless, these methods are far from the optimal solution in terms of performance and are sometimes tricky to setup - with a special regard to the aimConstraint.
Here it is explained how to obtain the same result, orienting ANY kind of of object towards another, without relying on pre-made tools (constraints) or spending time in the NodeEditor setting up nodes. With a little bit of linear algebra, we can compute a transformation matrix that encodes the correct values to orient the object in the desired way.
Before diving into the code, it's important to first clarify some basic concepts of Linear Algebra to ensure the material is accessible to everyone.
- Identity Matrix: It is a square matrix with all the diagonal-elements equal to 1, 0 in all the others and it is generally identified by the symbol I. If I is multiplied by any given matrix, it applies no information, fulfilling the multiplicative identity property. It can be seen as the matricial equivalent of the multiplication by 1.
-
Affine Transformation Matrix: Any matrix that can be interpreted as a combination of translation, rotations, scalings
-
Matrix Transposition: operation which flips the matrix over its diagonal, switching rows with columns. The transpose of a matrix
$\mathbf{A}$ it is denoted as$\mathbf{A^T}$ , -
A vector can be represented in two different forms: row or column. This distinction affects how vectors are displayed:
-
Row-Vector:
$\vec{v} = \left\lbrack \matrix{1 & 0 & 0 & 0} \right\rbrack$ , -
Column-Vector:
$\vec{v} = \left\lbrack \matrix{1 \cr 0 \cr 0 \cr 0} \right\rbrack $ .
To switch between these representations, a transpose operation is required. In computer science are called Row-Major and Column-Major representation and, since vectors and matrices are stored in arrays, it's crucial to know which representation is being used, as it impacts the order in which values are stored.
-
Row-Vector:
From now on, the Column-Vector form will be used to display all vectors and matrices.
Also known as scalar product, it is a vector operation that produces a scalar value. Given two vectors a, b, the dot product between them is defined as:
where
This operation fulfills several properties, among which:
-
Commutative:
$\mathbf{a} \cdot \mathbf{b} = \mathbf{b} \cdot \mathbf{a}$ , -
Distributive over vector addition:
$\mathbf{\vec{a}} \cdot (\mathbf{\vec{b}} + \mathbf{\vec{c}}) = (\mathbf{\vec{a}} \cdot \mathbf{\vec{b}}) + (\mathbf{\vec{a}} \cdot \mathbf{\vec{c}})$ , -
Orthogonal: Two not null vectors are orthogonal iff
$\mathbf{\vec{a}} \cdot \mathbf{\vec{b}} = 0$ .
Also known as vector product, it is a vector operation that produces a vector perpendicular to the plane formed by the original vectors. Giving two vectors a, b, the cross product between them can be defined as:
where
This operation fulfills several properties, among which:
-
Anticommutative:
$\mathbf{\vec{a}} \times \mathbf{\vec{b}} = -(\mathbf{\vec{b}} \times \mathbf{\vec{a}})$ , -
Distributive over vector addition:
$\mathbf{\vec{a}} \times (\mathbf{\vec{b}} + \mathbf{\vec{c}}) = (\mathbf{\vec{a}} \times \mathbf{\vec{b}}) + (\mathbf{\vec{b}} \times \mathbf{\vec{c}})$ .
As stated before, an Affine Transformation Matrix can be interpreted as a combination of three (four if we consider shear) different operations and in a 3D environment it is represented as a 4x4 matrix.
where the
Translations is the easiest of the operations, and its 4x4 representation is defined as:
If applied to an object, it moves (translate) it alone one or more axis. In particular, it adds the translation vector (tx, ty, tz) to the object, shifting its position.
A Scaling Matrix changes the object's size along one or more axis. Its 4x4 representation is the following:
Applying a Scaling Matrix to an object, means multiplying the object's coordinates by the scalar values of the corresponding axis:
The Rotation Matrix is the more complicated, as its definition is a little less intuitive than the previous matrices. It has a different definition depending on the rotation axis and the 4x4 representation of the three rotation matrices, for each rotation axis (x, y, z), by an angle 𝜃 is:
When working with rotations, angles are usually assigned a sign (+/-) to indicate the direction of rotation—either clockwise or counterclockwise. In mathematical conventions, positive angles (
Once it is clear how the basic operations (translation, scale and rotation) can be represented in a 4x4 matrix form, it is now time to combine them. This procedure simply involves a sequence of matrix multiplication operations. The final matrix can be represented as follows:
In this specific case, if we apply A to an object, the operation that are performe, in order are:
- Scaling it by (
$s_x$ ,$s_y$ ,$s_z$ ), - Rotating it along the X axis by
$\theta_x$ , - Rotating it along the Y axis by
$\theta_y$ , - Rotating it along the Z axis by
$\theta_z$ , - Translating it with the vector (
$t_x$ ,$y_y$ ,$t_z$ )
The power and efficiency of using matrices is that it is not necessary to store intermediate values after each multiplication. It is possible - and usually preferable - to perform all the sequence of multiplications and then use that final matrix - called the Affine Transformation Matrix - and use it to transform the object accordingly.
Some notes have to be made, though. Even if the intermediate steps are not necessary, the order of multiplications strongly matters. Indeed, givn three matrices A, B, C, that can be any of the previously explained operations:
- Matrix multiplication is associative: it is true that ABC = (AB)C = A(BC),
- Matrix multiplication is not commutative in general: it is generally false that AB = BA.