OpenGL : How to translate an object with it's own axis I'm working with OpenGL to try to rotate / translate my 3d object : a cow.

The requirement is simple : 


If I toggle key 'r'. The cow spinning around and random axis.
If I drag the cow with mouse, it translate along its own x axis which means +x directions is for cow's head
Rotation and translation need not execute at the same time.
Rotation and translation is done is modeling space.


To implement first requirement, I used timer function like this :

void rotateCow(int value) {
    //rotation ended
    if (!rotate_flag)
        return;

    printf("rotateCow\n");

    angle = (angle + 5) % 360;
    glutPostRedisplay();
    glutTimerFunc(30, rotateCow, 1);
}


and for rotation and translation : 
(some of codes are skipped)

void dragCow() {
    glPushMatrix();
    //some codes are skipped..

    //rotation start
    if (rotate_flag == 1) {
        rotate_flag = 2;
        glutTimerFunc(30, rotateCow, 1);
    }

    glTranslatef(trans_x, trans_y, trans_z);
    glRotatef(angle, rotate_x, rotate_y, rotate_z);

    glCallList( cowID ); // Draw cow.
    glPopMatrix();
}

void onMouseDrag( int x, int y ) {
    y = height - y - 1;
    if (trans_flag == DIR_X) {
        trans_x = ((x - oldX) / DRAG) + old_trans_x;
    }

    glutPostRedisplay();
}


If I run as above(rotate and then translate) rotation is as expected.

However, the translation is done in global x-axis not towards head direction of cow.

If I change the order like this : 

glRotatef(angle, rotate_x, rotate_y, rotate_z);
glTranslatef(trans_x, trans_y, trans_z);


It shows that translation is as expected(towards head direction of cow).

However, the rotations not works - the rotation-axis made on global x-axis and the cow revolve around that line.

So how can I solve this problem??
You can put the translation first, and then the rotation, but have the translation happen in the direction of the cow's head. To do that, you need a vector from the center of the cow to its head. Then you need the length of the translation. You can then do the translation in that direction. Like this:

float direction_x;
float direction_y;
float direction_z;
direction_x = cow_head_x - cow_center_x;
direction_y = cow_head_y - cow_center_y;
direction_z = cow_head_z - cow_center_z;

// find the length of the direction vector
float dir_length = sqrt(direction_x * direction_x + direction_y * direction_y + direction_z * direction_z);

// normalize the direction vector by dividing by the length
direction_x /= dir_length;
direction_y /= dir_length;
direction_z /= dir_length;

// Create a new vector pointing in the correct direction with the same
// length as the drag
float cow_translate_x = direction_x * drag_length;
float cow_translate_y = direction_y * drag_length;
float cow_translate_z = direction_z * drag_length;

// Do the transformation
glTranslatef(cow_translate_x, cow_translate_y, cow_translate_z);
glRotate(angle, rotate_x, rotate_y, rotate_z);


You could also get the direction vector by converting the angles to a direction. For example, if the rotation is only around the Y-axis, you could calculate it by doing the following:

float direction_x;
float direction_y;
float direction_z;
direction_x = cos(angle);
direction_y = 0.0; // since we're rotating around the Y axis
direction_z = sin(angle);


In this case, the direction vector is already normalized.

If you do have rotations around all 3 axes, you can calculate the direction vector using spherical coordinates:

direction_x = sin(angle) * cos(phi);
direction_y = sin(angle) * sin(phi);
direction_z = cos(angle);


where angle is the rotation around the y axis and phi is the angle above/below the x/z plane. The direction should already be normalized in this case, too.