Rotate 4x4 matrix formula

Started by
3 comments, last by stannic 11 years, 2 months ago

I am trying to figure out how to work with a 4x4 matrix, in particular rotating them. I have been searching and reading differnt things but I keep hitting a brick wall when I see the formulas. I can see which parts of the matrix need to be changed depending on if I rotate on the x, y or z axis. But I cannot interpet their formulas so as to use them in code.

I have tried several experiments and I am not geting the right numbers. And since they use letters and greek letters and give no point of refernce for them I am sure additional calculation are need but there is no clear reference to the correct calculation. In one fomula I saw they used cosine and sine with the theta character in parenthases which previously in the article it was defined as pi/2 (which makes no sense at all) but that didn't work when I used it.

I am hoping someone has some nice clearly defined formulas I can work with.

Advertisement

A piece of code is worth a thousand words. The following comes from my C++ math library. It's templated, but it should be fairly readable. It takes a unit vector representing the axis to rotate around and an angle in radians and returns a rotation matrix. See also the entries on Wikipedia.


//Creates a rotation matrix from radians
template <typename type_elements, typename type_float1, typename type_float2>
Matrix<type_elements,4,4> get_mat4_rotation_rad(const type_float1 vec[3], type_float2 theta) {
    type_elements c = cos( (type_elements)(theta) );
    type_elements s = sin( (type_elements)(theta) );
    type_elements C = (type_elements)(1) - c;
    type_elements x   = vec[0], y   = vec[1], z   = vec[2];
    type_elements xs  =   x* s, ys  =   y* s, zs  =   z* s;
    type_elements xC  =   x* C, yC  =   y* C, zC  =   z* C;
    type_elements xyC =   x*yC, yzC =   y*zC, zxC =   z*xC;
    return Matrix<type_elements,4,4>(
        (double)(x*xC+c),(double)(xyC-zs),(double)(zxC+ys),0.0,
        (double)(xyC+zs),(double)(y*yC+c),(double)(yzC-xs),0.0,
        (double)(zxC-ys),(double)(yzC+xs),(double)(z*zC+c),0.0,
                     0.0,             0.0,             0.0,1.0
    );
}

-G

[size="1"]And a Unix user said rm -rf *.* and all was null and void...|There's no place like 127.0.0.1|The Application "Programmer" has unexpectedly quit. An error of type A.M. has occurred.
[size="2"]

Thanks Geometrian for posting that code. I haven't worked in C++ for about a year so I will have to take a bit of time to dig into that and see what I can glean from it.

Since my post I have found a few more examples and articles but I am still a bit off on my calculatios. I am sure some will laugh but the formula I found that cracked everything open was not a formula to create the matrix but a formula that allowed one to pull the degrees of rotation out of the matrix. I took it and just reversed it, then from there I knew where to place the results and I figured out matrix multiplicaion.

But like I said things are bit off. There are some built in functions for simplifing rotation (they are limiting what I can do), and I am comparing my numbers to them. If I just rotate on one axis the numbers are fine it is when I rotate on more than one that things get messed up.

I have my code outputing the numbers from the built in rotation fuctions (first matrix below) and from my calculations (second matrix below), here's what I am seeing


X: 2deg
Y: 2deg

0.9993908270190958, 0.001217974870087876, -0.03487823687206265, 0,
0, 0.9993908270190958, 0.03489949670250097, 0,
0.03489949670250097, -0.03487823687206265, 0.9987820251299122, 0,
99.93908270190957, 100.06088018891836, 0.002125983043832047, 1

X cosine: 0.9993908270190958
X sine: 0.03489949670250097
Y cosine: 0.9993908270190958
Y sine: 0.03489949670250097

0.9993908270190958, 0, -0.03489949670250097, 0,
0.001217974870087876, 0.9993908270190958, 0.03487823687206265, 0,
0.03487823687206265, -0.03489949670250097, 0.9987820251299122, 0,
100, 100, 0, 1

Note that there is a 100 translate on both the X and Y axis so I can throughtly test my numbers.

I looks like the X and Y cosine and sine calculations are correct but something is not being calculated correctly after that. Nor is the calculation being applies to the translate values (I suspect I need to just research a bit to solve this). Hmm, as I look a little closer it looks like maybe some numbers are in the wrong spot ... but why?

Here is a pseudo version of the code I currently have


basematrix = [
    [1, 0, 0, 0],
    [0, 1, 0, 0],
    [0, 0, 1, 0],
    [100, 100, 0, 1]
];

function RotateMatrix(y, x)
{
    halfrot = 3.141592653589793 / 180;	// pi divided by 180

    xcos = cos(x * halfrot);
    xsin = sin(x * halfrot);

    ycos = cos(y * halfrot);
    ysin = sin(y * halfrot);

    ymatrix = [
        [ycos, 0, -ysin, 0],
        [0, 1, 0, 0],
        [ysin, 0, ycos, 0], 
        [0, 0, 0, 1]
    ];

    xmatrix = [
        [1, 0, 0, 0],
        [0, xcos, xsin, 0],
        [0, -xsin, xcos, 0], 
        [0, 0, 0, 1]
    ];

    calcmatrix = MatrixMultiply(ymatrix, basematrix);

    calcmatrix = MatrixMultiply(xmatrix, calcmatrix);

    for (i = 0; i < 4; i++)
    {
        for (j = 0; j < 4; j++)
        {
            //output calcmatrix[i][j]
        }
    }
}

function MatrixMultiply(matrixa, matrixb)
{
    newmatrix = [];
    for (i = 0; i < 4; ++i)
    {
        for (j = 0; j < 4; ++j)
        {
            newmatrix[i][j] = matrixa[i][0] * matrixb[0][j] 
                            + matrixa[i][1] * matrixb[1][j] 
                            + matrixa[i][2] * matrixb[2][j] 
                            + matrixa[i][3] * matrixb[3][j];
        }
    }	
    return newmatrix;
}

Maybe someone can see what I did wrong.

Hi.

Maybe some thing like this

float4x4 rotateX = { 1.0, 0.0, 0.0, 0.0, 0.0, cos(rot.x), -sin(rot.x), 0.0, 0.0, sin(rot.x), cos(rot.x), 0.0, 0.0, 0.0, 0.0, 1.0 };
float4x4 rotateY = { cos(rot.y), 0.0, sin(rot.y), 0.0, 0.0, 1.0, 0.0, 0.0, -sin(rot.y), 0.0, cos(rot.y), 0.0, 0.0, 0.0, 0.0, 1.0 };
float4x4 rotateZ = { cos(rot.z), -sin(rot.z), 0.0, 0.0, sin(rot.z), cos(rot.z), 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 };

My guess is that your problem has something to do with notation and order of operations.

Remember that [A][X][Y] != [Y][X][A] != [X][Y][A] != [A][Y][X]

This topic is closed to new replies.

Advertisement