# Rotation Matrix example

I would like to share the rotation matrix method that I created with you because there are not much tutorials about them. and the ones that I found where not very helpfull to me.

so what this method does it rotates a point in 3d space around an other point in 3d space.
rotation is alpha,beta and gamma.

this way you can rotate a 3d object by rotating every cornerpoint of the object around the objects center.

the method:

``````
public class Physics
{
static float new_rotated_x, new_rotated_y, new_rotated_z;
static float last_point_x, last_point_y, last_point_z, last_alpha, last_beta, last_gamma;

public static float RotationMatrix(String pointtype,float point_x,float point_y,float point_z, float center_point_x, float center_point_y, float center_point_z, float alpha, float beta, float gamma)
{
//pointtype:                                       either, "x","y" or "z" depending on the axis you want to return
//point_x,point_y,point_z:                         the coordinates of the point that rotates - coordinates of the center point
//center_point_x,center_point_y,center_point_z:    the the coordinates of the center point (the point revolves around the center point)
//rotation alpha,beta,gamma                        rotation alpha,beta,gamma

/* 3D Rotation matrix
*
*  R(alpha,beta,gamma) = Rz (alpha) Ry (beta) Rx (gamma)
*
*  | [cos_a * cos_b]   [cos_a * sin_b * sin_g - sin_a * cos_g]     [cos_a * sin_b * cos_g + sin_a * sin_g] |
*  | [sin_a * cos_b]   [sin_a * sin_b * sin_g + cos_a * cos_g]     [sin_a * sin_b * cos_g - cos_a * sin_g] |
*  | [-sin_b       ]   [cos_b * sin_g                        ]     [cos_b * cos_g                        ] |
*
*/

//dont recalculate because x,y and z are already calculated before
if (last_point_x == point_x && last_point_y == point_y && last_point_z == point_z && last_alpha == alpha && last_beta == beta && last_gamma == gamma)
{

}

//recalculate
else
{
double sin_a = Math.sin(alpha);
double sin_b = Math.sin(beta);
double sin_g = Math.sin(gamma);

double cos_a = Math.cos(alpha);
double cos_b = Math.cos(beta);
double cos_g = Math.cos(gamma);                                                                                                              double[] PositionMatrix = {   point_x,   point_y,   point_z};

//ReturnMatrix[row][column]
double[][] RotationMatrix =   {    {cos_a * cos_b,   (cos_a * sin_b * sin_g) - (sin_a * cos_g),   (cos_a * sin_b * cos_g) + (sin_a * sin_g)  },
{sin_a * cos_b,   (sin_a * sin_b * sin_g) + (cos_a * cos_g),   (sin_a * sin_b * cos_g) - (cos_a * sin_g)  },
{-sin_b       ,    cos_b * sin_g                           ,   cos_b * cos_g                              }    };

double new_x_calc_1 = RotationMatrix[0][0]   *   PositionMatrix[0];
double new_x_calc_2 = RotationMatrix[0][1]   *   PositionMatrix[1];
double new_x_calc_3 = RotationMatrix[0][2]   *   PositionMatrix[2];

double new_y_calc_1 = RotationMatrix[1][0]   *   PositionMatrix[0];
double new_y_calc_2 = RotationMatrix[1][1]   *   PositionMatrix[1];
double new_y_calc_3 = RotationMatrix[1][2]   *   PositionMatrix[2];

double new_z_calc_1 = RotationMatrix[2][0]   *   PositionMatrix[0];
double new_z_calc_2 = RotationMatrix[2][1]   *   PositionMatrix[1];
double new_z_calc_3 = RotationMatrix[2][2]   *   PositionMatrix[2];

new_rotated_x = (float)(new_x_calc_1 + new_x_calc_2 + new_x_calc_3);
new_rotated_y = (float)(new_y_calc_1 + new_y_calc_2 + new_y_calc_3);
new_rotated_z = (float)(new_z_calc_1 + new_z_calc_2 + new_z_calc_3);

last_point_x = point_x;
last_point_y = point_y;
last_point_z = point_z;
last_alpha = alpha;
last_beta = beta;
last_gamma = gamma;
}

if (pointtype.contains("x"))
{
return(new_rotated_x+center_point_x);
}
else if (pointtype.contains("y"))
{
return(new_rotated_y+center_point_y);
}
else if (pointtype.contains("z"))
{
return(new_rotated_z+center_point_z);
}
return(0);
}
}

``````

and this is how the method is called in an object, in this case a cube:

``````
@Override
public void render()
{

if (killed == true || brender == false)
{
return;
}

rotation_alpha +=0.001;
rotation_beta +=0.01;
rotation_gamma += 0.00;

cx1 =  - xsize;
cy1 =  - xsize;
cz1 =  - xsize;

cx2 =  + xsize;
cy2 =  - xsize;
cz2 =  - xsize;

cx3 =  + xsize;
cy3 =  + xsize;
cz3 =  - xsize;

cx4 =  - xsize;
cy4 =  + xsize;
cz4 =  - xsize;

cx5 =  - xsize;
cy5 =  - xsize;
cz5 =  + xsize;

cx6 =  + xsize;
cy6 =  - xsize;
cz6 =  + xsize;

cx7 =  + xsize;
cy7 =  + xsize;
cz7 =  + xsize;

cx8 =  - xsize;
cy8 =  + xsize;
cz8 =  + xsize;

float newcx1 = Physics.RotationMatrix("x", cx1, cy1, cz1, x, y, z, rotation_alpha, rotation_beta, rotation_gamma);
float newcy1 = Physics.RotationMatrix("y", cx1, cy1, cz1, x, y, z, rotation_alpha, rotation_beta, rotation_gamma);
float newcz1 = Physics.RotationMatrix("z", cx1, cy1, cz1, x, y, z, rotation_alpha, rotation_beta, rotation_gamma);

float newcx2 = Physics.RotationMatrix("x", cx2, cy2, cz2, x, y, z, rotation_alpha, rotation_beta, rotation_gamma);
float newcy2 = Physics.RotationMatrix("y", cx2, cy2, cz2, x, y, z, rotation_alpha, rotation_beta, rotation_gamma);
float newcz2 = Physics.RotationMatrix("z", cx2, cy2, cz2, x, y, z, rotation_alpha, rotation_beta, rotation_gamma);

float newcx3 = Physics.RotationMatrix("x", cx3, cy3, cz3, x, y, z, rotation_alpha, rotation_beta, rotation_gamma);
float newcy3 = Physics.RotationMatrix("y", cx3, cy3, cz3, x, y, z, rotation_alpha, rotation_beta, rotation_gamma);
float newcz3 = Physics.RotationMatrix("z", cx3, cy3, cz3, x, y, z, rotation_alpha, rotation_beta, rotation_gamma);

float newcx4 = Physics.RotationMatrix("x", cx4, cy4, cz4, x, y, z, rotation_alpha, rotation_beta, rotation_gamma);
float newcy4 = Physics.RotationMatrix("y", cx4, cy4, cz4, x, y, z, rotation_alpha, rotation_beta, rotation_gamma);
float newcz4 = Physics.RotationMatrix("z", cx4, cy4, cz4, x, y, z, rotation_alpha, rotation_beta, rotation_gamma);

float newcx5 = Physics.RotationMatrix("x", cx5, cy5, cz5, x, y, z, rotation_alpha, rotation_beta, rotation_gamma);
float newcy5 = Physics.RotationMatrix("y", cx5, cy5, cz5, x, y, z, rotation_alpha, rotation_beta, rotation_gamma);
float newcz5 = Physics.RotationMatrix("z", cx5, cy5, cz5, x, y, z, rotation_alpha, rotation_beta, rotation_gamma);

float newcx6 = Physics.RotationMatrix("x", cx6, cy6, cz6, x, y, z, rotation_alpha, rotation_beta, rotation_gamma);
float newcy6 = Physics.RotationMatrix("y", cx6, cy6, cz6, x, y, z, rotation_alpha, rotation_beta, rotation_gamma);
float newcz6 = Physics.RotationMatrix("z", cx6, cy6, cz6, x, y, z, rotation_alpha, rotation_beta, rotation_gamma);

float newcx7 = Physics.RotationMatrix("x", cx7, cy7, cz7, x, y, z, rotation_alpha, rotation_beta, rotation_gamma);
float newcy7 = Physics.RotationMatrix("y", cx7, cy7, cz7, x, y, z, rotation_alpha, rotation_beta, rotation_gamma);
float newcz7 = Physics.RotationMatrix("z", cx7, cy7, cz7, x, y, z, rotation_alpha, rotation_beta, rotation_gamma);

float newcx8 = Physics.RotationMatrix("x", cx8, cy8, cz8, x, y, z, rotation_alpha, rotation_beta, rotation_gamma);
float newcy8 = Physics.RotationMatrix("y", cx8, cy8, cz8, x, y, z, rotation_alpha, rotation_beta, rotation_gamma);
float newcz8 = Physics.RotationMatrix("z", cx8, cy8, cz8, x, y, z, rotation_alpha, rotation_beta, rotation_gamma);

Draw.drawRect(newcx1,newcy1,newcz1,newcx2,newcy2,newcz2,newcx6,newcy6,newcz6,newcx5,newcy5,newcz5,red,green,blue,transparancy);

Draw.drawRect(newcx4,newcy4,newcz4,newcx1,newcy1,newcz1,newcx5,newcy5,newcz5,newcx8,newcy8,newcz8,red,green,blue,transparancy);

Draw.drawRect(newcx2,newcy2,newcz2,newcx3,newcy3,newcz3,newcx7,newcy7,newcz7,newcx6,newcy6,newcz6,red,green,blue,transparancy);

Draw.drawRect(newcx4,newcy4,newcz4,newcx3,newcy3,newcz3,newcx7,newcy7,newcz7,newcx8,newcy8,newcz8,red,green,blue,transparancy);

Draw.drawRect(newcx1,newcy1,newcz1,newcx2,newcy2,newcz2,newcx3,newcy3,newcz3,newcx4,newcy4,newcz4,red,green,blue,transparancy );

Draw.drawRect(newcx5,newcy5,newcz5,newcx6,newcy6,newcz6,newcx7,newcy7,newcz7,newcx8,newcy8,newcz8,red,green,blue,transparancy );

}

``````

Just a code style tip. You have this.

``````
if (last_point_x == point_x &&
last_point_y == point_y &&
last_point_z == point_z &&
last_alpha == alpha &&
last_beta == beta &&
last_gamma == gamma)
{

}

//recalculate
else
{

``````

I think this is a little bit vague. You can instead, do it in a single if statement by adding a negate operator. Like this.

``````
if ( !(last_point_x == point_x &&
last_point_y == point_y &&
last_point_z == point_z &&
last_alpha == alpha &&
last_beta == beta &&
last_gamma == gamma))
{
// Code here
}

``````

I think it’s much simpler now. Also you can give some explanation for your code. Otherwise nice article.

I think I’m gonna add my own rotation matrix implementation here.
http://pastebin.com/Gq4mHL82

It was designed for simplicity, not performance. However on the Oracle desktop VM the performance is very good thanks to nearly all object creations being optimized away by the JIT.

You can use it e.g to rotate a point around an arbitrary axis.

Here is a usage example

``````
//creates a matrix that first rotates by 18 degrees around the x axis,
//then 36 deg around y and finally 90 deg around z
Matrix m1 = Matrix.IDENTITY.rotX(Math.PI/10)
.rotY(Math.PI/5)
.rotZ(Math.PI/2);

//a matrix that rotates by 90 deg around the axis (1,1,1)
Matrix m2 = new Matrix(new Vec(1,1,1), Math.PI/2);
System.out.println(m1);
System.out.println();
System.out.println(m2);
//m3 rotates first by m1 and then by m2
//the rotation is relative to the absolute coordinate system.
//not relative the m1
Matrix m3 = m1.rotateAbs(m2);
System.out.println();
System.out.println(m3);
System.out.println();
Vec point = new Vec(2,3,5);
Vec point2 = point.rotate(m3);
System.out.println(point2);
System.out.println();
//performs the opposite rotation to m3
Matrix m4 = m3.oppositeRotMatrix();
Vec point3 = point2.rotate(m4);
System.out.println(point3);

``````

this prints

``````
[0.000, -0.951, 0.309]
[0.809, 0.182, 0.559]
[-0.588, 0.250, 0.769]

[0.333, -0.244, 0.911]
[0.911, 0.333, -0.244]
[-0.244, 0.911, 0.333]

[-0.733, -0.134, 0.667]
[0.413, -0.867, 0.280]
[0.541, 0.481, 0.690]

(1.470, -0.373, 5.975)

(2.000, 3.000, 5.000)

``````

thank you for the tips.
I would like to alter the first post to explain more. how can I do that?

Click on this image that appears at the bottom right of your post.

aaaaaaaaaaaaaaaahhhhh, kill it with fire :o

excuse me?

Ok, I probably should not use such hard words on a beginner as we all were there once, but your code is bad really bad.
I take from your code that you don’t quite figured out how objects work. You should definitely check that out as your very next step.

Now back to your code, it is so bad because everything is static and you use only static because you don’t know how objects work.
So why do you need objects, objects help you bundle repeating data together. In your example you could create objects for rectangles and matrices. An array is an object and because of their structure it is easy to see that one could represent a matrix with an array. Like you are doing in some sort already. The thing is arrays are generic objects which don’t need to be a matrix, but can be anything else. Like you could also represent numbers with Strings.

So you should definitely create a Matrix class which not only holds the data, but can also have all the functionality like transforming a point.

``````
class Matrix4x4{
float[] data = new float[16]

static fromEularAngles(float a, float b, float c);

Point3 transform(Point3 input);
}

``````

You don’t want to repeat the whole matrix initialisation for each point, so you have created some tricky caching in some global variables. Your hack to not have to write the function 3 times for x,y and z is also interesting.
But, if you use objects you don’t have to do this complicated trickery anymore, your code could look like this:

``````
Point3 xyz = new Point3(x,y,z);

Matrix4x4 m = Matrix4x4.fromEularAngles(rotA, rotB, rotC);

Point3 rotated = m.transform(xyz);

drawCubeAt(rotated);

``````

So I should make a new matrix object everytime I want to rotate?
is it not better to make a matrix object for each cube once in the constructor, and then call a method inside that matrix to do the rotation when needed?

No, you should, and need to keep the same matrix. There’s nothing terribly wrong with your code except for the static floats, there’s just no point in them. Of course, just to rotate a cube, thats rather a lot of code, but its not terrible. Creating a new matrix every rotation would reset the matrix data, so your rotation and any translations would be lost. Plus, you dont want to create that many objects for an action that will be repeated lots. Creating a new matrix every rotation would be very inefficient as the garbage collector would be running like mad…

@opiop65 all your statements are wrong

@Rakiayn how and when to cache a calculation(e.g. a matrix) depends on the use case. It makes sense to give each renderable object an own matrix, which can be changed each render call. This wasn’t the case in your example, because the matrix of the cube is completely different in every frame anyway.

PS: I really hope that you are not using OpenGL, because if you are using it you should not calculate the positions of every cube corner yourself.

@Danny02 and how am I wrong? This should be interesting.

@opiop65

his code is probably mathematical correct(didn’t check that) but it is really terrible and when you don’t think so you should feel bad about yourself.
[list]
[li]using Strings for x, y & z

• PositionMatrix
• static caching
• not a generic way to do matrix rotation but some very use case specific way

[/li]

• [quote]Creating a new matrix every rotation would reset the matrix data, so your rotation and any translations would be lost.
[/quote]
There is no way around rebuilding your matrix for each new rotation
• Your last argument about creating to much objects in the render loop is bullshit.

[li]you need to create a new matrix for each rotation anyway (above)

• Such objects will probably be created on the stack anyway, so no need for garbage collection
• the GC is very very good with short living objects

[/li]
[/list]

sry but you have no idea what you are talking about, about the vm and matrix math.

I changed the code, I would appreciate your opinion.

``````
public abstract class Cube extends ROGameObject
{
public float cx1;
public float cy1;
public float cz1;

public float cx2;
public float cy2;
public float cz2;

public float cx3;
public float cy3;
public float cz3;

public float cx4;
public float cy4;
public float cz4;

public float cx5;
public float cy5;
public float cz5;

public float cx6;
public float cy6;
public float cz6;

public float cx7;
public float cy7;
public float cz7;

public float cx8;
public float cy8;
public float cz8;

public float lijn_xy;
public float lijn_xyz;

public float velocity_x;
public float velocity_y;
public float velocity_z;

public float dir_velocity_x;
public float dir_velocity_y;
public float dir_velocity_z;

public float rotation_alpha = 0f;
public float rotation_beta = 0f;
public float rotation_gamma = 0f;

public float corner_length;

public RotationMatrix m;

public void calculate_corner_length()
{
float length_xy = (float)Math.sqrt((xsize*xsize)+(xsize*xsize));
corner_length = (float)Math.sqrt((length_xy*length_xy)+(xsize*xsize));

}

@Override
public void render()
{

if (killed == true || brender == false)
{
return;
}

rotation_alpha =45f;
rotation_beta += 10f;
rotation_gamma = 0;

cx1 =  - xsize;
cy1 =  - xsize;
cz1 =  - xsize;

cx2 =  + xsize;
cy2 =  - xsize;
cz2 =  - xsize;

cx3 =  + xsize;
cy3 =  + xsize;
cz3 =  - xsize;

cx4 =  - xsize;
cy4 =  + xsize;
cz4 =  - xsize;

cx5 =  - xsize;
cy5 =  - xsize;
cz5 =  + xsize;

cx6 =  + xsize;
cy6 =  - xsize;
cz6 =  + xsize;

cx7 =  + xsize;
cy7 =  + xsize;
cz7 =  + xsize;

cx8 =  - xsize;
cy8 =  + xsize;
cz8 =  + xsize;

newpoint center = new newpoint(x,y,z);

newpoint corner_1 = new newpoint(cx1,cy1,cz1);
newpoint corner_2 = new newpoint(cx2,cy2,cz2);
newpoint corner_3 = new newpoint(cx3,cy3,cz3);
newpoint corner_4 = new newpoint(cx4,cy4,cz4);
newpoint corner_5 = new newpoint(cx5,cy5,cz5);
newpoint corner_6 = new newpoint(cx6,cy6,cz6);
newpoint corner_7 = new newpoint(cx7,cy7,cz7);
newpoint corner_8 = new newpoint(cx8,cy8,cz8);

if (m == null)
{
m = new RotationMatrix();
}
m.changeangle(rotation_alpha, rotation_beta, rotation_gamma);

newpoint rotated_1 = m.transform(corner_1,center);
newpoint rotated_2 = m.transform(corner_2,center);
newpoint rotated_3 = m.transform(corner_3,center);
newpoint rotated_4 = m.transform(corner_4,center);
newpoint rotated_5 = m.transform(corner_5,center);
newpoint rotated_6 = m.transform(corner_6,center);
newpoint rotated_7 = m.transform(corner_7,center);
newpoint rotated_8 = m.transform(corner_8,center);

DrawRect(rotated_1,rotated_2,rotated_6,rotated_5,red,green,blue,transparancy);
DrawRect(rotated_4,rotated_1,rotated_5,rotated_8,red,green,blue,transparancy);
DrawRect(rotated_2,rotated_3,rotated_7,rotated_6,red,green,blue,transparancy);
DrawRect(rotated_4,rotated_3,rotated_7,rotated_8,red,green,blue,transparancy);
DrawRect(rotated_1,rotated_2,rotated_3,rotated_4,red,green,blue,transparancy);
DrawRect(rotated_5,rotated_6,rotated_7,rotated_8,red,green,blue,transparancy);

}

public void DrawRect(newpoint point1, newpoint point2, newpoint point3, newpoint point4, float red, float green, float blue, float alpha)
{

}

}

``````

the rotation matrix:

``````
package pkg3dproject;

public class RotationMatrix
{
public float alpha;
public float beta;
public float gamma;

public void changeangle(float rotA, float rotB, float rotC)
{
alpha = rotA;
beta = rotB;
gamma = rotC;
}

public newpoint transform(newpoint rotpoint, newpoint centerpoint)
{

/* 3D Rotation matrix
*
*  R(alpha,beta,gamma) = Rz (alpha) Ry (beta) Rx (gamma)
*
*  | [cos_a * cos_b]   [cos_a * sin_b * sin_g - sin_a * cos_g]     [cos_a * sin_b * cos_g + sin_a * sin_g] |
*  | [sin_a * cos_b]   [sin_a * sin_b * sin_g + cos_a * cos_g]     [sin_a * sin_b * cos_g - cos_a * sin_g] |
*  | [-sin_b       ]   [cos_b * sin_g                        ]     [cos_b * cos_g                        ] |
*
*/

double sin_a = Math.sin(alpha);
double sin_b = Math.sin(beta);
double sin_g = Math.sin(gamma);

double cos_a = Math.cos(alpha);
double cos_b = Math.cos(beta);
double cos_g = Math.cos(gamma);

//ReturnMatrix[row][column]
double RotationMatrix[] =   {      cos_a * cos_b,   (cos_a * sin_b * sin_g) - (sin_a * cos_g),   (cos_a * sin_b * cos_g) + (sin_a * sin_g)  ,
sin_a * cos_b,   (sin_a * sin_b * sin_g) + (cos_a * cos_g),   (sin_a * sin_b * cos_g) - (cos_a * sin_g)  ,
-sin_b       ,    cos_b * sin_g                           ,   cos_b * cos_g                               };

double new_x_calc_1 = RotationMatrix[0]   *   rotpoint.px;
double new_x_calc_2 = RotationMatrix[1]   *   rotpoint.py;
double new_x_calc_3 = RotationMatrix[2]   *   rotpoint.pz;

double new_y_calc_1 = RotationMatrix[3]   *   rotpoint.px;
double new_y_calc_2 = RotationMatrix[4]   *   rotpoint.py;
double new_y_calc_3 = RotationMatrix[5]   *   rotpoint.pz;

double new_z_calc_1 = RotationMatrix[6]   *   rotpoint.px;
double new_z_calc_2 = RotationMatrix[7]   *   rotpoint.py;
double new_z_calc_3 = RotationMatrix[8]   *   rotpoint.pz;

rotpoint.px = (float)(new_x_calc_1 + new_x_calc_2 + new_x_calc_3);
rotpoint.py = (float)(new_y_calc_1 + new_y_calc_2 + new_y_calc_3);
rotpoint.pz = (float)(new_z_calc_1 + new_z_calc_2 + new_z_calc_3);

rotpoint.px += centerpoint.px;
rotpoint.py += centerpoint.py;
rotpoint.pz += centerpoint.pz;

return(rotpoint);
}

}

``````

new point code:

``````

package pkg3dproject;

public class newpoint
{
float px,py,pz;

public newpoint(float nx, float ny, float nz)
{
px = nx;
py = ny;
pz = nz;
}
}

``````

If your only transforming a single point with a matrix, then it’s an inefficient method. Do a direct method instead (aka no matrix). Matrices are a win when your transforming more than one point with the same transform.

My personal opinion is to never ever (except potentially the camera) use euler angles at runtime (ok for load/storage and/or tool time).

You don’t need to recalculate the array every time you rotate a new point.
Also you forgot to subtract the center point before rotating rotpoint.
And why are you mixing float and double. Choose one and stick with it.
You also don’t need to return rotpoint. You changed the old one. You only need to return it if you created a new one.

Here is a changed version of your class.

``````public class RotationMatrix
{
public float alpha;
public float beta;
public float gamma;
float rm[];

public void changeangle(float rotA, float rotB, float rotC)
{
alpha = rotA;
beta = rotB;
gamma = rotC;
float sin_a = (float)Math.sin(alpha);
float sin_b = (float)Math.sin(beta);
float sin_g = (float)Math.sin(gamma);

float cos_a = (float)Math.cos(alpha);
float cos_b = (float)Math.cos(beta);
float cos_g = (float)Math.cos(gamma);

rm = new float[] { cos_a * cos_b, (cos_a * sin_b * sin_g) - (sin_a * cos_g), (cos_a * sin_b * cos_g) + (sin_a * sin_g),
sin_a * cos_b, (sin_a * sin_b * sin_g) + (cos_a * cos_g), (sin_a * sin_b * cos_g) - (cos_a * sin_g),
-sin_b        ,  cos_b * sin_g                           , cos_b * cos_g                            };

}

public void transform(newpoint rotpoint, newpoint centerpoint)
{
float px = rotpoint.px - centerpoint.px,
py = rotpoint.py - centerpoint.py,
pz = rotpoint.pz - centerpoint.pz;

rotpoint.px = rm[0]*px + rm[1]*py + rm[2]*pz;
rotpoint.py = rm[3]*px + rm[4]*py + rm[5]*pz;
rotpoint.pz = rm[6]*px + rm[7]*py + rm[8]*pz;

rotpoint.px += centerpoint.px;
rotpoint.py += centerpoint.py;
rotpoint.pz += centerpoint.pz;
}
}
``````

thank you ;D