[osg-users] How to scale rotations ?

Janusz janusz at 3dcalc.pl
Fri Jul 25 12:13:32 PDT 2008

Dear all:

Appreciate any answer on the topic:

I am reading an orientation / rotation matrix info from a sensor, then 
visualizing the rotation of an object on screen with OSG. Given the 
matrix or the resulting quaternion I need to be able to scale the 
rotations independently, i.e.

heading_scale*heading_angle, heading_scale=<0,1>

in order to be able to control them on its own or restrict the rotation 
to one angle only.

I have written 2 functions. The first one converts a quaternion to the 
Euler angles, the other one does the opposite. In between the calls to 
the functions I am trying to scale the rotations or switch them on/off 
as needed.

The results are not quite good, however, and I often get trapped in the 
famous "gimbal lock" as probably expected. :-)

Q: Is there any other possibility to handle rotations on its own? Is 
there a way to do that without running the conversion, scaling, then 
converting back to quat ?

All I have is the rotation matrix.

Appreciate any answer/advice or pointing me in the right direction.

Best regards,
Janusz Goldasz

void getEulerFromQuat(osg::Quat q, double& heading, double& attitude, 
double& bank)
    double sqx = q.x()*q.x();  
    double sqy = q.y()*q.y();  
    double sqz = q.z()*q.z();

    double t = q.x()*q.y() + q.z()*q.w();
    if (t>0.49999)
        heading = 2 * atan2(q.x(),q.w());
        attitude = osg::PI_2;
        bank = 0;
    else if (t<-0.49999)
        heading = -2 * atan2(q.x(),q.w());
        attitude = - osg::PI_2;
        bank = 0;
        heading = atan2(2*q.y()*q.w()-2*q.x()*q.z() , 1 - 2*sqy - 2*sqz);
        attitude = asin(2*t);
        bank = atan2(2*q.x()*q.w()-2*q.y()*q.z() , 1 - 2*sqx - 2*sqz);

void getQuatFromEuler(double heading, double attitude, double bank, 
osg::Quat& q)
    double c1 = cos(heading/2);  
    double s1 = sin(heading/2);  
    double c2 = cos(attitude/2);  
    double s2 = sin(attitude/2);  
    double c3 = cos(bank/2);  
    double s3 = sin(bank/2);
    double c1c2 = c1*c2; 
    double s1s2 = s1*s2; 

    double w =c1c2*c3 - s1s2*s3;
    double x =c1c2*s3 + s1s2*c3;
    double y =s1*c2*c3 + c1*s2*s3;
    double z =c1*s2*c3 - s1*c2*s3;

    q[0] = x; q[1] = y;
    q[2] = z; q[3] = w;

More information about the osg-users mailing list