# c4d.Matrix¶

class c4d.Matrix

## Members¶

Matrix.v1

The X axis of a left-handed coordinate system.

Type: Vector

Matrix.v2

The Y axis of a left-handed coordinate system.

Type: Vector

Matrix.v3

The Z axis of a left-handed coordinate system.

Type: Vector

Matrix.off

The translation vector for this matrix.

Type: Vector

Matrix.__init__([off=Vector(0)[, v1=Vector(1, 0, 0)[, v2=Vector(0, 1, 0)[, v3=Vector(0, 0, 1)]]]])
Parameters: off (Vector) – Position v1 (Vector) – X-axis v2 (Vector) – Y-axis v3 (Vector) – Z-axis Matrix A new matrix.
Matrix.__str__()

Returns the Matrix as string. Called if str() is wrapped around an instance of Matrix. (see __str__).:

```import c4d
v1 = c4d.Vector(3)
v2 = c4d.Vector(12,4, 9.3)
v3 = c4d.Vector(9,80,3)
off = c4d.Vector(v1+v2)
vec = c4d.Matrix(off, v1, v2, v3)
print vec                # output 'Matrix(v1: (3, 3, 3); v2: (12, 4, 9.3); v3: (12, 4, 9.3); off: (15, 7, 12.3))'
```
Return type: str The Vector as string.

Parameters: other (Matrix) – The other matrix.
Matrix.__sub__(self, other)
Matrix.__rsub__(self, other)

Subtract the two matrices from each other.

Parameters: other (Matrix) – The other matrix.
Matrix.__mul__(self, other)
Matrix.__rmul__(self, other)

New in version R13.029.

If both objects are of type Matrix, it multiplies the left hand matrix by the right hand matrix. If the left object of type Matrix and the right one of type Vector, multiply the vector by the matrix. This includes any translation in the matrix. In the last case, the left object can be of type Vector and the right one of type Matrix so it multiplies the vector by the matrix. This does not include any translation.

Parameters: other (Matrix or Vector) – Check the description above.
Matrix.__div__(self, other)

Divide each element in the matrix by the scalar.

Parameters: other (float) – The scalar.
Matrix.__invert__()

Invert the matrix.

Return type: Matrix Returns a copy of the inverted matrix.
Matrix.__eq__(other)

Check if two matrices are identical.

Parameters: other (Matrix) – The matrix to check. bool Returns True if both matrices are identical.
Matrix.__ne__(self, other)

Check if two vectors are unidentical.

Parameters: other (Matrix) – The matrix to check. bool Returns True if both matrices are unidentical.
Matrix.Normalize()

Normalize the matrix.

Matrix.GetNormalized()

Returns a new copy of this matrix, which is normalized.

Return type: Matrix The matrix.
Matrix.Mul(v)

Multiply the vector by the matrix, this includes any translation in the matrix.

Parameters: v (Vector) – The vector to multiply. Vector The vector.
Matrix.MulV(v)

Multiply the vector by the matrix, this does not include any translation.

Parameters: v (Vector) – The vector to multiply. Vector The vector.
Matrix.GetTensorMatrix()

Returns the matrix’ tensor.

Return type: Matrix The tensor matrix.
Matrix.Scale(v)

Matrix scaling.

Parameters: v (Vector or float) – The scaling value.

## The matrix has you¶

Single precision matrix mathematics - A matrix is basically an array of number arranged in a rectangular pattern. The matrices used in CINEMA 4D, represented by the class Matrix, consist of three rows and four columns, i.e. they have the dimension 3x4. The first row is always “1, 0, 0, 0”, which means that there are 12 numbers that are used. These numbers are grouped into four vectors, one for the remaining numbers in each column. The four vectors are called off, v1, v2 and v3, together these four vectors can be used to represent the coordinate system for a CINEMA 4D object. A coordinate system consists of three axes, one for each coordinate (X, Y and Z). The system also has a base position, from which the three axes originate. This base position is stored in off, and the three axis vectors are stored in v1, v2 and v3 respectively. Also check out Matrix fundamentals. So now we can follow the white rabbit - knock knock - neo.

Note

CINEMA 4D uses a left-handed coordinate system.

Here is a small example how to use the type Matrix:

```v_1    = Vector(30)
v_2    = Vector(1.5, 9.87, 2)
v_3    = Vector(0)
off    = Vector() #Vector with components: 0
mat    = Matrix(off, v_1, v_2, v_3) #create new instance of Matrix
print mat.v1.x #return 30
```

## Freeze transformations¶

With R12 you probably have noticed that BaseObject no longer has members like GetPos, but instead twice as many: BaseObject.GetRelPos() and BaseObject.GetAbsPos().

To understand what’s going on I’ll quickly introduce you to Freeze Transformations.

For (character) animation it is important that you can define rest poses. Think e.g. of the typical CG human that has arms and legs stretched. Most objects carry all kinds of complicated position, scale and rotation information. Freeze Transformations allow you to “freeze” this information, but reset position/rotation to 0.0 and scale to 1.0. This is great as it allows you at any time to go back to the original - just reset all position and angle information to 0.0 - and your object has reached its rest state again. You could achieve the same by adding for every single object in your hierarchy a parent null object, but Freeze Transformations let you do this without the need to change the hieararchical structure. Technically however you can think of it as a “parent null object” without the actual body of a physical object.

All parts of the application that deal with keyframing only access values without the freeze transformation part. This way you can conveniently animate (the rest pose is always 0.0 for position and rotation) and avoid rotation singularities. The correct routines for animation and keyframing are labeled “Rel”.

Other parts of the application however (e.g. like a target expression) need to get the absolute local position of a target - the position that consists of frozen and regular matrix. For those purposes you need to use the routines that are labeled “Abs”.

To clarify: as long as an object has no Freeze transformation assigned (which is always the default case when you create a new object) there is no difference between the Abs or Rel. So e.g. after creating an object it doesn’t matter which routine you choose. If you however want to read the position of an object (and that object uses freeze transformations) there is a difference.

BaseObject.GetMl() / BaseObject.SetMl() and BaseObject.GetMg() / BaseObject.SetMg() always include the frozen information, thus are “Abs” versions.

After so much theory a practical example. Take a look at the cube and null object in the picture below. The null object has a position of (0/200/0) and rotation of (0°/45°/0°). The cube has a position of (0/100/0). You can see to the left its global position in space.

Now let’s try to do the same with one single object:

You can see that the Null object’s position / rotation have been transferred to the Cube’s frozen position and frozen rotation. The result is exactly the same as before, just without the need for an extra null object.

Now if you call cube.GetAbsPos the return value will be (0/270.711/-70.711). When you call cube.GetRelPos however you’ll get (0/100/0) as a result. The coordinate manager offers exactly those two display modes: Object (Abs) and Object (Rel).

As copying position, rotation and scale data from one object to another is much more complex than before there is a new routine BaseObject.CopyMatrixTo() that copies all position, rotation and scale data (including the frozen states) over to another object.

Let’s take a look at the mathematical background: In CINEMA 4D the matrix multiplication order for two matrices A and B:

```[C] = [A] * [B]
```

is defined as the rule “A after B”... so the following two lines are equivalent:

```transformed_point = original_point * [C]
transformed_point = (original_point * [B]) * [A]
```

(the original point is first transformed by matrix [B] and then later by [A])

An object’s global matrix is calculated this way:

`[Global Matrix] = [Global Matrix of Parent] * [Local Matrix]`

or:

`[Global Matrix] = op.GetUpMg() * op.GetMl()`

To calculate the local matrix of an object the formula is:

`[Local Matrix] = [Frozen Translation] * [Frozen Rotation] * [Relative Translation] * [Relative Rotation] * [Frozen Scale] * [Relative Scale]`

or:

`[Local Matrix] = MatrixMove(op.GetFrozenPos()) * HPBToMatrix(op.GetFrozenRot()) * MatrixMove(op.GetRelPos()) * HPBToMatrix(op.GetRelRot()) * MatrixScale(op.GetFrozenScale) * MatrixScale(op.GetRelScale())`

or equally:

`[Local Matrix] = MatrixMove(op.GetAbsPos()) * HPBToMatrix(op.GetAbsRot()) * MatrixScale(op.GetAbsScale)`

Please note that the both scales are applied at the very beginning, so the local matrix is not the same as [Frozen Matrix] * [Relative Matrix]. This is necessary in order to guarantee that your local matrix always stays a rectangular system; distorted systems would be too complicated to handle.