1
votes

This is more math-y than programming-y but how can I improve this rotation matrix to accept a point at which to rotate around? There's the axis, which specifies the nature of the rotation, but there's also the point at which the vertices are rotated around per the axis. How can I improve this matrix to accept a position? It happens to be written in C but that's not very relevant, because I'm looking for the logic.

matrix_float4x4 Rotate(const float Radians, const float X, const float Y, const float Z) {
    const float 
        Sin = sinf(Radians),
        Cos = cosf(Radians),
        C = 1-Cos, SinX = Sin*X,
        SinY = Sin*Y,
        SinZ = Sin*Z,
        CX = X*C,
        CY = Y*C,
        CZ = C*Z;
    return (matrix_float4x4){
        .columns = {
            {Cos+(X*CX), (Y*CX)+SinZ, (Z*CX)-SinY, 0},
            {(X*CY)-SinZ, Cos+(Y*CY), (Z*CY)+SinX, 0},
            {(X*CZ)+SinY, (Y*CZ)-SinX, Cos+(Z*CZ), 0},
            {0, 0, 0, 1}
        }
    };
}
1
To rotate with respect to a particular point, first translate to the origin, then apply the rotation, then translate back. This can be done (among other ways) using matrix concatenation. All you need is a rotation matrix function (which you already have), a translation matrix function, and a matrix multiplication function. Hopefully that will get you pointed in the right direction. (Keep in mind that order matters when concatenating matrices, and that the order can depend on what conventions you're using.)scg
@scg I didn't think of it that way but thanksuser14629932
Think of local coordinates vs. world coordinates.tadman
In ExpTranslate, the last m->columns[i].y should be .z! My matrix implementation is row major order, and i think you are column major order, column[0] is your first column, whereas my numbering scheme follows the rule: row column (in your terminology row[n].xyzw).Erdal Küçük
@ErdalKüçük Oops, OKuser14629932

1 Answers

1
votes

The question is, do you want to transform the object or the world? In other words, you can rotate the object and move (translate) it to a specific position or you can rotate the world around a specific point (orbit camera).

As pointed out by 'scg': T * R != R * T

A Transformation formula for the object would be: T * C * R * -C (T: Translate, C: Center, R: Rotation)

Now, there are a lot of operations involved. If you look at a Translation- or Rotationmatrix, there are a lot of zeros. You can eliminate those steps:

Example:

typedef struct mat4_rec {
    float
    a11, a12, a13, a14,
    a21, a22, a23, a24,
    a31, a32, a33, a34,
    a41, a42, a43, a44;
} mat4_t;

mat4_t* translate(mat4_t *m, float x, float y, float z)
{
    m->a14 += m->a11 * x + m->a12 * y + m->a13 * z;
    m->a24 += m->a21 * x + m->a22 * y + m->a23 * z;
    m->a34 += m->a31 * x + m->a32 * y + m->a33 * z;
    m->a44 += m->a41 * x + m->a42 * y + m->a43 * z;
    
    return m;
}

To translate a 4x4 Matrix (M *= T). These are a lot less operations than a full 4x4 Multiplication.

Rotation (M *= R) would look like this:

mat4_t* rotate(mat4_t *m, float rad, float x, float y, float z)
{
    float s = sinf(rad);
    float c = cosf(rad);
    float t = 1.0f - c;
    
    float a11 = x * x * t +     c;
    float a12 = x * y * t - z * s;
    float a13 = x * z * t + y * s;
    float a21 = y * x * t + z * s;
    float a22 = y * y * t +     c;
    float a23 = y * z * t - x * s;
    float a31 = z * x * t - y * s;
    float a32 = z * y * t + x * s;
    float a33 = z * z * t +     c;
    
    float m11 = m->a11;
    float m12 = m->a12;
    float m13 = m->a13;
    float m21 = m->a21;
    float m22 = m->a22;
    float m23 = m->a23;
    float m31 = m->a31;
    float m32 = m->a32;
    float m33 = m->a33;
    float m41 = m->a41;
    float m42 = m->a42;
    float m43 = m->a43;
    
    m->a11 = m11 * a11 + m12 * a21 + m13 * a31;
    m->a12 = m11 * a12 + m12 * a22 + m13 * a32;
    m->a13 = m11 * a13 + m12 * a23 + m13 * a33;
    m->a21 = m21 * a11 + m22 * a21 + m23 * a31;
    m->a22 = m21 * a12 + m22 * a22 + m23 * a32;
    m->a23 = m21 * a13 + m22 * a23 + m23 * a33;
    m->a31 = m31 * a11 + m32 * a21 + m33 * a31;
    m->a32 = m31 * a12 + m32 * a22 + m33 * a32;
    m->a33 = m31 * a13 + m32 * a23 + m33 * a33;
    m->a41 = m41 * a11 + m42 * a21 + m43 * a31;
    m->a42 = m41 * a12 + m42 * a22 + m43 * a32;
    m->a43 = m41 * a13 + m42 * a23 + m43 * a33;
    
    return m;
}

To implement the transformation: T * C * R * -C

mat4_t m; // <- set to identiy or something else

// T - move position of object by one unit along the x axis
translate(&m, 1, 0, 0);

// C - move pivot point down along the y axis
translate(&m, 0, -1, 0);

// R - 180 degress around the z axis
rotate(&m, M_PI, 0, 0, 1);

// -C - restore pivot point
translate(&m, 0, 1, 0);

// multiply matrix by any vector (M * V)