0

I've been trying to understand matrices and vectors and implemented Rodrigue's rotation formula to determine the rotation matrix about an axis for a given angle. I've got function Transform which calls out to function 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;
        }

All the values, resultant rotation matrix and the changed vectors are as expected for +angle of rotation, but wrong for negative angles and from then on, has cascading effect until the all the vectors are re-initialised. Can someone please help me figure out the problem? I cannot use any inbuilt functions like glm::rotate.

genpfault
  • 51,148
  • 11
  • 85
  • 139
uci649
  • 1
  • If it only works for positive numbers, a lazy solution would be to add 360 to a negative rotation value. That way you could get the same rotation just with a positive number. – Henri Jun 12 '20 at 16:24
  • As soon as the first error crops up, all the subsequent matrices are wrong whether +/-ve angle until the vertices and rotation angle are reset. – uci649 Jun 12 '20 at 20:17

1 Answers1

0

I do not use Rodrigues_rotation_formula because it needs to compute a system of equation on runtime and gets very complicated in higher dimensions.

Instead I am using axis aligned incremental rotations along with 4x4 homogenous transform matrices which are really easily portable to higher dimensions like 4D rotors.

Now there are local and global rotations. Local rotations will rotate around your matrix coordiante system local axises and global ones will rotate around world (or main coordinate system)

What you want is create a transform matrix around some point,axis and angle. To do that just:

  1. create a transform matrix A

    that has one axis aligned to axis of rotation and origin is center of rotation. To construct such matrix you need 2 perpendicular vectors which are easily obtainable from cross product.

  2. rotate A around its local axis aligned to axis of rotation by angle

    by simple multiplication of A by axis aligned incremental rotation R so

    A*R;
    
  3. revert the original transform of A before rotation

    by simply multiplying inverse of A to the result so

    A*R*Inverse(A);
    
  4. apply this on matrix M you want to rotate

    also by simply multiplying this to M so:

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

And that is it... Here 3D OBB approximation you can find function :

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

That does exactly that. Where m is original matrix to transform (and returns the rotated one), ang is signed angle in [rad], p0 is center of rotation and dp is axis of rotation direction vector.

This approach does not have any singularities nor problems to rotate by negative angles ...

If you want to use this with glm or any other GLSL like math just change the templates to what you use so float,vec3,mat4 instead of T,_vec3<T>,mat4<T>.

Spektre
  • 49,595
  • 11
  • 110
  • 380