簡體   English   中英

圍繞原點以外的點旋轉?

[英]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)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM