围绕原点以外的点旋转?

Rotate around a point other than origin?

这比编程更数学,但我如何改进这个旋转矩阵以接受旋转的点?有一个轴,它指定了旋转的性质,但也有顶点围绕每个轴旋转的点。我怎样才能改进这个矩阵来接受一个职位?它恰好是用 C 编写的,但这不是很相关,因为我正在寻找逻辑。

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

问题是,你是要改造物体还是改造世界?换句话说,您可以旋转对象并将其移动(平移)到特定位置,或者您可以围绕特定点旋转世界(轨道相机)。

正如'scg'所指出的:T * R != R * T

对象的转换公式为:T * C * R * -C (T:平移,C:居中,R:旋转)

现在,涉及到很多操作。如果您查看平移矩阵或旋转矩阵,就会发现有很多零点。您可以消除这些步骤:

示例:

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

翻译 4x4 矩阵 (M *= T)。这些操作比完整的 4x4 乘法少得多。

旋转 (M *= R) 看起来像这样:

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

实现转换: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)