With this tutorial that I prefer to call exercise I hope to give you the opportunity to explore a topic often poorly treated:

The Matrix (not the movie)

The prerequisites are a minimum of knowledge of trigonometry, a little bit of geometry and XPresso. It is not for all, but trust me, it is a simple task.

Since I have received some requests on how to concatenate the Bend Deformer automatically I planned on doing this exercise by providing the project file, so you can see everything in detail without having to write anything. But it would be more interesting to redo from scratch all the things.

Demo video:

I will make a brief review of how the matrices are structured, just to refresh your memory.

Matrix = [offset|v1|v2|v3]

It is made up of four vectors: offset, v1, v2 and v3.

offset= position of the origin

v1= v1 coordinates

v2= v2 coordinates

v3= v3 coordinates

A Matrix that lies exactly at the origin of the coordinate system and has a scale of 1;1;1 with no rotation would look like this:

M=[0;0;0|1;0;0|0;1;0|0;0;1]

offset = 0;0;0

v1 = 1;0;0

v2 = 0;1;0

v3 = 0;0;1

This is an orthogonal matrix and we also will manipulate these type of matrices.

Each vector v1, v2 and v3 is an unit vector (a vector whose length is 1) and is also known as a normalized vector.

The length of each vector of the matrix (v1, v2 or v3) define the scale of in that direction. For example if v1 has length equal to 2 then the scal S.X is equal to 2.

Every object has a matrix in C4D and it contains information about position, scale and rotation of that object in relation to the coordinate system.

fig.1

For simplicity, we look at what happens in the two-dimensional space.

The matrix in this case would be composed of only three vectors:

M = [offset;v1:v2]

In the fig.1 we can see the values of the individual vector components.

offset = 0;0

v1= √2/2 ; √2/2

v2= -√2/2 ; √2/2

Note as v1 and v2 are in this case unit vectors, in fact:

v1.lunghezza = √[(√2/2)^2+(√2/2)^2] = 1

The same for the v2.

fig.2

Now in general, the matrix is rotated by alpha degrees.

And these are the vector components:

offset = 0;0

v1 = cos(alpha) ; sen(alpha)

v2 = -sen(alpha) ; cos(alpha)

fig.3

In 3D space, if the rotation is around the z-axis the question is the same seen before, but now we have 4 vectors with 3 components.

offset = 0;0;0

v1 = cos(alpha) ; sen(alpha);0

v2 = -sen(alpha) ; cos(alpha);0

v3 = 0 ; 0 ; 1

Let’s move now to the specific problem that concerns the concatenation of two Bend Deformer.

The first Bend (Bend.1) will be free to move and rotate. The second Bend (Bend.2) will be set at the top of Bend.1 and it will follow the deformation given by the Strength and Angle manipulations of the first one. Keep Y-Axes Length is enabled for each Bend.

In the file project you can see the normal vector on the top of Bend.1 with the length equal to the Y-size of Bend.2 diveded by 2 , so the point P1 is on top of the Bend.1 and P2 is on the center of Bend.2 (P1 and P2 are child of Bend.1).

From now:

alpha = Strength

beta = Angle

fig.4

R=Bend.1.lenght/alpha

Bend.1.lenght is the Y-size of Bend.1 and it is the length of the arc which subtends the angle alpha. R is the Radius of that arc.

Obviously we will pay attention to the alpha value. If it will be zero we’ll need to be sure that nothing strange is happening (but it will).

Step 1

Calculate the P1 coordinates

Watching the fig.4 we can find that (if alpha ≠ 0):

P1.x = R*(1-cos(alpha))

P1.y = R*sin(alpha)-lenght/2

If we extend the observation to a 3D space we also have to considerate the P1.z wich value is the same of P1.x modulated by sin(beta) (cos(beta) for P1.x):

P1.x = R*(1-cos(alpha))*cos(beta)

P1.y = R*sin(alpha)-lenght/2

P1.z = R*(1-cos(alpha))*sin(beta)

These coordinates are relative to the coordinate system generates by the matrix of Bend.1. In other words they are relative to the Bend.1 object.

In fact in XPresso the calculated coordinates are connected to the local coordinate input of P1.

Now we need to calculate the P2 coordinates.

I made this finding the normal vector n on top of Bend.1 and moltiiplicating this by the B2.length diveded by 2. This vector added to the local coordinates of P1 give us

the local coordinates of P2.

Now take a look again to fig.4 and notice that the vector n should have a length equal to 1 (normalized vector).

Project it to the XYZ axes and you can find this:

n.x = sen(alpha)*cos(beta)

n.y = cos(alpha)

n.z = sen(alpha)*sin(beta)

At this point we can calculate P2 local coordinates (see the Xpresso nodes) and extract the global coordinates to set the Bend.2 global coordinates.

But we need to know also the rotation of Bend.2. So we are going to calculate the global matrix of Bend.2.

This is the “tips of the day” which is probably the dark side of the entire tutorial.

Somebody, probably, are saying:”you don’t need to use the matrix.. just set the rotation…”

Ok, try it!…

Have you tried?

Ok, it is not a simple way…

So we need to manipolate the matrices.

Observe how the deformer changes the top polygon and how the Bend.2 should be moved.

If we operate on the Straigth value of Bend.1 (our alpha value) fixed whith XYZ=(0;0;0) and PHB=(0;0;0) the rotation of Bend.2 is simple to manipulate and we would not need to obtain the matrix. But we want to have Bend.1 free to move and rotate and also we would like to operate with the angle property (our beta value).

The main concept that needs to be clarified about the matrices manipulation in Xpresso is that:

if we have a matrix A.g (that we can think as the global matrix of an object O.a) and a child object O.b (child of O.a) with a local matrix B.l we could calculate the global matrix B.g in this simple way:

B.g = A.g * B.l

and an important question is that matrix multiplication in general is not commutative, so:

A*B ≠ B*A

If you need to better understand this question you need to study a little bit of algebra.

At this point we can think to divide our problem in more steps where each one is a partial rotation of the Bend.1 matrix (a copy) that, at the end, will become exactly the Bend.2 matrix.

Observing the Bend.1 behaviour after a while I could assume that in order the rotations that I need are these (important: each one is applied to the new “coordinate system” given by the previous calculation):

1. rotation.1 around the y-axis driven by the Angle property (H rotation) –> Matrix.1

2. rotation.2 around the z-axis driven by the Streigth property (B rotation) –> Matrix.2

3. rotation.3, again, around the y-axis driven by the Angle property but in the other direction (H rotation) –> Matrix.3

Watch the single effect applied to the cones.

The simplest way to obtain the result is, probably, to create an hierarchy, child of Bend.1, of 3 nulls. From the top we could manipulate the first by rotation.1, the second by rotation.2 and the third by rotation.3. And the result will be what we want. This approuch is also valid for the previous part of the tutorial.

But because I want to give you the opportunity to understand better the matrices, we’re going on by calculating these single matrices. The offset will be always sets to (0;0;0) because we need only the rotation factor.

Matrix.1

v1 = cos(beta) ; 0 ; sin(beta)

v2 = 0 ; 1 ; 0

v3 = -sin(beta) ; 0 ; cos(beta)

Matrix.2

v1 = cos(alpha) ; -sin(alpha) ; 0

v2 = sin(alpha) ; cos(alpha) ; 0

v3 = 0 ; 0 ; 1

Matrix.3

v1 = cos(beta) ; 0 ; -sin(beta)

v2 = 0 ; 1 ; 0

v3 = sin(beta) ; 0 ; cos(beta)

Now to obtain the Bend.2 global matrix we need to multiplicate the global matrix of Blend.1 in order by these matrices.

Bend.2.M.g = Bend.1.M.g * Matrix.1 * Matrix.2 * Matrix.3

And the task is now completed.

For any question and correction comment below.

And sorry for the language errors.