【问题标题】:Determining rotation matrix about an axis for a given angle确定给定角度绕轴的旋转矩阵
【发布时间】:2020-10-02 11:39:45
【问题描述】:

我一直在尝试理解矩阵和向量,并实现了 Rodrigue 的旋转公式来确定给定角度下围绕轴的旋转矩阵。我有函数 Transform 调用函数 Rotate。

        // initial values of eye ={0,0,7}
        //initial values of up={0,1,0}
        void Transform(float degrees, vec3& eye, vec3& up) {
            vec3 axis = glm::cross(glm::normalize(eye), glm::normalize(up));
            glm::normalize(axis);
            mat3 resultRotate = rotate(degrees, axis);
            eye = eye * resultRotate;
            glm::normalize(eye);
            up = up * resultRotate;`enter code here`
            glm::normalize(up);
            }
        mat3 rotate(const float degrees, const vec3& axis) {
        //Implement Rodrigue's axis-angle rotation formula
        float radDegree = glm::radians(degrees);
        float cosValue = cosf(radDegree);
        float minusCos = 1 - cosValue;
        float sinValue = sinf(radDegree);
        float cartesianX = axis.x;
        float cartesianY = axis.y;
        float cartesianZ = axis.z;
        mat3 myFinalResult = mat3(cosValue +(cartesianX*cartesianX*minusCos), ((cartesianX*cartesianY*minusCos)-(cartesianZ*sinValue)),((cartesianX*cartesianZ*minusCos)+(cartesianY*sinValue)),
        ((cartesianX*cartesianY*minusCos)+(cartesianZ*sinValue)), (cosValue+(cartesianY*cartesianY*minusCos)), ((cartesianY*cartesianZ*minusCos) - (cartesianX*sinValue)),
        ((cartesianX*cartesianZ*minusCos)-(cartesianY*sinValue)),     ((cartesianY*cartesianZ*minusCos) + (cartesianX*sinValue)), ((cartesianZ*cartesianZ*minusCos) + cosValue));
         return myFinalResult;
        }

所有值、结果旋转矩阵和更改的向量都与 + 旋转角度的预期一样,但对于负角度是错误的,从那时起,具有级联效应,直到所有向量都重新初始化。有人可以帮我解决问题吗?我不能使用任何内置函数,例如 glm::rotate。

【问题讨论】:

  • 如果它只适用于正数,一个懒惰的解决方案是将 360 添加到负旋转值。这样,您只需使用正数即可获得相同的轮换。
  • 一旦出现第一个错误,无论是+/-ve角度,所有后续矩阵都是错误的,直到顶点和旋转角度被重置。

标签: c++ graphics rotation matrix-multiplication glm-math


【解决方案1】:

我不使用Rodrigues_rotation_formula,因为它需要在运行时计算方程组,并且在更高维度上变得非常复杂。

相反,我使用axis aligned incremental rotations4x4 homogenous transform matrices,它们很容易移植到4D rotors 等更高维度。

现在有局部和全局旋转。局部旋转将围绕您的矩阵坐标系局部轴旋转,全局旋转将围绕世界(或主坐标系)旋转

你想要的是围绕一些point,axisangle 创建一个变换矩阵。要做到这一点:

  1. 创建一个变换矩阵A

    一个轴与旋转轴对齐,原点是旋转中心。要构建这样的矩阵,您需要 2 个垂直向量,这些向量很容易从叉积中获得。

  2. 围绕与旋转轴对齐的局部轴旋转Aangle

    通过A 与轴对齐增量旋转R 的简单相乘,所以

    A*R;
    
  3. 在旋转之前恢复A的原始变换

    通过简单地将A 的倒数乘以结果

    A*R*Inverse(A);
    
  4. 将此应用到要旋转的矩阵M

    也可以简单地将其乘以 M 所以:

    M*=A*R*Inverse(A);
    

就是这样......在这里3D OBB approximation你可以找到函数:

template <class T> _mat4<T> rotate(_mat4<T> &m,T ang,_vec3<T> p0,_vec3<T> dp)
    {
    int i;
    T c=cos(ang),s=sin(ang);
    _vec3<T> x,y,z;
    _mat4<T> a,_a,r=mat4(
         1, 0, 0, 0,
         0, c, s, 0,
         0,-s, c, 0,
         0, 0, 0, 1);
    // basis vectors
    x=normalize(dp);    // axis of rotation
    y=_vec3<T>(1,0,0);  // any vector non parallel to x
    if (fabs(dot(x,y))>0.75) y=_vec3<T>(0,1,0);
    z=cross(x,y);       // z is perpendicular to x,y
    y=cross(z,x);       // y is perpendicular to x,z
    y=normalize(y);
    z=normalize(z);
    // feed the matrix
    for (i=0;i<3;i++)
        {
        a[0][i]= x[i];
        a[1][i]= y[i];
        a[2][i]= z[i];
        a[3][i]=p0[i];
        a[i][3]=0;
        } a[3][3]=1;
    _a=inverse(a);
    r=m*a*r*_a;
    return r;
    };

正是这样做的。其中m 是要变换的原始矩阵(并返回旋转后的矩阵),ang[rad] 中的有符号角度,p0 是旋转中心,dp 是旋转轴方向向量。

这种方法没有任何奇点,也没有旋转负角的问题...

如果您想将它与 glm 或任何其他 GLSL (如数学)一起使用,只需将模板更改为您使用的模板,例如 float,vec3,mat4 而不是 T,_vec3&lt;T&gt;,mat4&lt;T&gt;

【讨论】:

    猜你喜欢
    • 2019-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-08
    • 1970-01-01
    • 1970-01-01
    • 2018-10-24
    • 1970-01-01
    相关资源
    最近更新 更多