简体   繁体   中英

Rotate around a point other than origin?

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}
        }
    };
}

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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM