titus
titus

Reputation: 5784

rotate 3d model around absolute axes

I can't figure out how to convert mouse drag into rotation around Ox and Oy of the image plane.
I followed the first answer from here and I'm storing the modelView matrix in an array, and updating it every time the mouse moves. alpha and beta are proportional to the mouse increments from the previous position.

This code updates the rotation when the mouse moves:

glLoadMatrixf(currentModelViewMatrix);
glRotatef(beta,0,1,0);
glRotatef(alpha,1,0,0);
glGetFloatv(GL_MODELVIEW_MATRIX, currentModelViewMatrix);

I tried the solution from the end of this explanation but didn't make any difference.

Only the rotation given by beta is absolute, the rotation given by alpha is around an axis in the model which turns when there is a rotation around the first axis. I don't know how to make the second rotation be absolute. The way it is right now doesn't seem intuitive to a user.


edit: The increment code:

GLfloat currentModelViewMatrix[16];
GLfloat whole[16];
void glob()
{ 
  glLoadIdentity();
  glRotatef(beta,0,1,0);
  glRotatef(alpha,1,0,0);
  glMultMatrixf(currentModelViewMatrix);
  glGetFloatv(GL_MODELVIEW_MATRIX, currentModelViewMatrix); 

  glLoadIdentity();
  glTranslatef(0,0,-20);
  glMultMatrixf(currentModelViewMatrix);
  glGetFloatv(GL_MODELVIEW_MATRIX,whole); 

  alpha=beta=0;
}

And before every model, the matrix is loaded:

glLoadMatrixf(whole);

The full code:

#include "math.h"
#include "string.h"
#include "stdio.h"
#include "GL/freeglut.h"
#include "GL/gl.h"
#include "GL/glu.h"
float alpha,beta;

void key(int key, int x, int y)
{   printf("%d",key);
    switch(key)
    {   case GLUT_KEY_RIGHT:
            printf("right\n");
            break;
        case GLUT_KEY_LEFT:
            printf("left\n");
            break;
        case GLUT_KEY_UP:
            printf("top\n");
            break;
        case GLUT_KEY_DOWN:
            printf("bottom\n");
            break;
    }
    glutPostRedisplay();
    fflush(stdout); 
}

void otherkeys(unsigned char key,int x,int y)
{   printf("%c\n",key);
    fflush(stdout);
    switch(key)
    {   case '+':
            printf("plus\n");
            break;
        case '-':
            printf("minus\n");
            break;
        case 'w':
                alpha+=10;
            break;
        case 's':
                alpha-=10;
            break;
        case 'd':
                beta+=10;
            break;
        case 'a':
                beta-=10;
            break;
    }
    glutPostRedisplay();
}
void drawCube()
{   int i,j,d;
    glBegin(GL_LINES);
        for(i=0;i<8;i++)
        {   for(j=i+1;j<8;j++)
            {   d=j^i;
                if(d==1||d==2||d==4)
                {   glVertex3i(i%2,i/2%2,i/4%2 );   
                    glVertex3i(j%2,j/2%2,j/4%2 );   
                }                   
            }
        }
    glEnd();
}

GLfloat currentModelViewMatrix[16];
GLfloat whole[16];
void glob()
{   
    glLoadIdentity();
    glRotatef(beta,0,1,0);
    glRotatef(alpha,1,0,0);
    glMultMatrixf(currentModelViewMatrix);
    glGetFloatv(GL_MODELVIEW_MATRIX, currentModelViewMatrix);   

    glLoadIdentity();
    glTranslatef(0,0,-20);
    glMultMatrixf(currentModelViewMatrix);
    glGetFloatv(GL_MODELVIEW_MATRIX,whole); 

    alpha=beta=0;
}
void renderFunction()
{   int i;
    glClearColor(0.0,0.0,0.0,0.0);
    glClear(GL_COLOR_BUFFER_BIT);   
    glColor3f(1.0,1.0,1.0); 
    glMatrixMode(GL_PROJECTION); 
        glLoadIdentity();
//              glRotatef(angle2,0.0,0.0,1.0);
        gluPerspective(60, 1.333, 0.1, 100);

    glMatrixMode(GL_MODELVIEW);

    glColor3f(1.0,0.0,0.0); 
    for(i=1;i<8;i++)
    {   
        glLoadMatrixf(whole);   
        glTranslatef(i*2.0,0,0);
        drawCube();
    }

    glColor3f(0.0,1.0,0.0); 
    for(i=1;i<6;i++)
    {
        glLoadMatrixf(whole);   
        glTranslatef(0,i*2.0,0);
        drawCube();
    }

    glColor3f(0.0,0.0,1.0); 
    for(i=0;i<5;i++)
    {
        glLoadMatrixf(whole);   
        glTranslatef(0,0,i*2.0);
        drawCube();
    }

    glFlush();
}

/*mouse*/
int prevx,prevy,dx,dy;
void rotate(int dx,int dy)
{   printf("%f %f\n",dy/10.0,dy/10.0);
    alpha=dy/2.0;
    beta=dx/2.0;
    glob();
}

void passive(int x,int y)
{   prevx=x;prevy=y;}

void active(int x,int y)
{   dx=x-prevx;
    prevx=x;
    dy=y-prevy;
    prevy=y;
    rotate(dx,dy);
}

void globinit()
{
    glLoadIdentity();
    glGetFloatv(GL_MODELVIEW_MATRIX, currentModelViewMatrix);   

    glLoadIdentity();
    glTranslatef(0,0,-20);
    glGetFloatv(GL_MODELVIEW_MATRIX, whole);    
}
int main (int argc, char* argv[])
{       
    glutInit(&argc,argv);

    glutInitDisplayMode(GLUT_SINGLE);
    glutInitWindowSize(800,600);
    glutInitWindowPosition(100,100);
    glutCreateWindow("Open GL bla bla");
    glutDisplayFunc(renderFunction);
    glutIdleFunc(renderFunction);
    glutSpecialFunc(key);
    glutKeyboardFunc(otherkeys);
    glutMotionFunc(active);
    glutPassiveMotionFunc(passive);
    globinit();
    glutMainLoop(); 
    return 0;
}

Upvotes: 0

Views: 900

Answers (1)

Nico Schertler
Nico Schertler

Reputation: 32667

Try the following:

glLoadIdentity();
glRotatef(beta,0,1,0);
glRotatef(alpha,1,0,0);
glMultMatrixf(currentModelViewMatrix);
glGetFloatv(GL_MODELVIEW_MATRIX, currentModelViewMatrix);

Due to the changed order the rotations are performed in the global coordinate system rather than a local one.

Upvotes: 1

Related Questions