C 是否围绕原点以外的点旋转?

C 是否围绕原点以外的点旋转?,c,math,matrix,3d,rotational-matrices,C,Math,Matrix,3d,Rotational Matrices,这更像是数学上的y,而不是编程上的y,但是我如何改进这个旋转矩阵来接受一个旋转点呢?有轴,它指定旋转的性质,但也有顶点围绕轴旋转的点。如何改进此矩阵以接受职位?它碰巧是用C写的,但这不是很相关,因为我在寻找逻辑 matrix_float4x4 Rotate(const float Radians, const float X, const float Y, const float Z) { const float Sin = sinf(Radians),

这更像是数学上的y,而不是编程上的y,但是我如何改进这个旋转矩阵来接受一个旋转点呢?有轴,它指定旋转的性质,但也有顶点围绕轴旋转的点。如何改进此矩阵以接受职位?它碰巧是用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)

mat4\u t m;//要相对于特定点旋转,请首先平移到原点,然后应用旋转,然后再平移回原点。这可以通过矩阵连接(以及其他方式)来实现。您所需要的只是一个旋转矩阵函数(您已经拥有)、一个平移矩阵函数和一个矩阵乘法函数。希望这能为你指明正确的方向。(请记住,在连接矩阵时顺序很重要,而且顺序可能取决于您使用的约定。)@scg我没有这样想,但要感谢本地坐标与世界坐标的对比。在ExpTranslate中,最后的m->columns[I].y应该是.z!我的矩阵实现是行主顺序,我认为您是列主顺序,列[0]是您的第一列,而我的编号方案遵循规则:行-列(在您的术语中是行[n].xyzw)。@ErdalKüçük Oops,ok,那么输入是什么?有
rad
x
y
z
,但是如果
x
y
z
是旋转发生的中心点,那么我应该在哪里描述旋转轴呢?反之亦然?这是两个不同的函数。第一个叫做translate,它取一个矩阵和x,y,z坐标。第二个称为rotate的参数相同,包括角度rad。对不起,我删除了很多我的原始代码。我的矩阵只是一个结构,包含名为a11..a44的字段。作为函数参数,我只使用m。明确地说,在translate函数中,aMN是矩阵的字段。让我澄清一下,这里必须对代码块进行编码,第一个是translate,
x
y
z
,这里指的是中心点,但在第二个代码块中,
x
y
z
是旋转轴吗?我现在说得更清楚了。中心只是另一个平移矩阵。翻译的T是对象在世界上的新位置,而中心是对象的轴心点。非常感谢您的帮助和时间!