[Risolto][C] [OpenGL] Dubbio sulla gluUnProject

Atem1
Salve ragazzi,
l'esercizio in questione richiede di disegnare una sfera rossa che si deve muovere quando c'è movimento passivo del mouse: in tal caso il centro della sfera deve coincidere con la coordinata dello schermo in cui si trova il puntatore del mouse.
In pratica deve far questo:

#include <GL/glut.h>
#include <GL/glu.h>
#include <GL/gl.h>

#define SCREEN_X 800
#define SCREEN_Y 600

GLdouble spherex, spherey;

void SetupRC()
{
    glClearColor(0.0f,0.0f,0.0f,1.0f);
}

void RenderScene()
{
    glClear(GL_COLOR_BUFFER_BIT);
    glMatrixMode(GL_MODELVIEW);
   // glLoadIdentity(); //riga1
    glColor3f(255,0,0);
   // glPushMatrix(); //riga2
    glTranslatef(spherex,spherey,0.0f);
    glutSolidSphere(30.0f,100,100);
  // glPopMatrix();//riga3
    glutSwapBuffers();


}

void mouse(int x, int y)
{
    GLdouble spherez, model[16], project[16];
    GLint viewport[4];
    glGetDoublev(GL_MODELVIEW_MATRIX, model);
    glGetDoublev(GL_PROJECTION_MATRIX, project);
    glGetIntegerv(GL_VIEWPORT, viewport);
    gluUnProject(x,viewport[3]-y,0.0f,model,project,viewport,&spherex,&spherey,&spherez);
    glutPostRedisplay();
}

void ChangeSize(int w, int h)
{
    GLfloat range=100.0f;
    if (h==0) h=1;
    glViewport(0,0,w,h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    w=w;
    h=h;
    if (w<=h) glOrtho(-range,range,-range*h/w,range*h/w,-range,range);
    else glOrtho(-range*w/h,range*w/h,-range,range,-range,range);
}

int main(int argc, char **argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
    glutInitWindowPosition(100,100);
    glutInitWindowSize(SCREEN_X, SCREEN_Y);
    glutCreateWindow("Esempi");
    glutPassiveMotionFunc(mouse);
    glutReshapeFunc(ChangeSize);
    glutDisplayFunc(RenderScene);
    SetupRC();
    glutMainLoop();
    return 0;
}





Il mio dubbio sta all'interno della funzione RenderScene() ed in particolare sulle 3 righe che ho commentato come "riga1, riga2, riga3"
Se attivo le 3 righe il programma continua a funzionare correttamente.
Se attivo riga2, e riga3 il programma continua a funzionare correttamente.
Se invece attivo solamente riga1 (glLoadIdentity) e lascio commentate riga2 e riga3 il programma non funziona.
Cioè il caso in cui il programma non funziona correttamente è questo:

void RenderScene()
{
    glClear(GL_COLOR_BUFFER_BIT);
    glMatrixMode(GL_MODELVIEW);
   glLoadIdentity(); //riga1
    glColor3f(255,0,0);
   // glPushMatrix(); //riga2
    glTranslatef(spherex,spherey,0.0f);
    glutSolidSphere(30.0f,100,100);
  // glPopMatrix();//riga3
    glutSwapBuffers();
}


E non capisco il motivo.
Perchè se attivo anche riga2 e riga3 il programma funziona? Non dovrebbe essere codici equivalenti?

Risposte
Atem1
La situazione mi è chiara solo nel caso in cui non attivo glLoadIdentity e allora uso glPushMatrix() e glPopMatrix() per salvare la matrice originale prima delle trasformazioni di traslazione.
Però se chiamo la glLoadIdentity non capisco perchè poi dovrei effettuare anche le operazioni di glPushMatrix e glPopMatrix se tanto alla prossima chiamata di RenderScene riparto nuovamente dalla glLoadIdentity...

E non capisco nemmeno il motivo per cui il programma funziona se tutte e 3 le righe sono commentate.
spherex, spherey e spherez non dovrebbero rappresentare le coordinate finali? Quindi prima di effettuare la traslazione non dovrei riportarmi sull'origine caricando la glLoadidentity?

apatriarca
Il problema è che quando non inserisci le righe 2 e 3, la matrice ModelView non è l'identità. Quando quindi richiedi questa matrice nella funzione mouse, ottieni una posizione della sfera relativa ad una matrice diversa dall'identità. Usando quindi l'identità con questa nuova posizione ti darà dei problemi che non ha negli altri casi.

EDIT: glColor3f richiede colori con valori in [0, 1] e non [0, 255]..

Atem1
"apatriarca":
EDIT: glColor3f richiede colori con valori in [0, 1] e non [0, 255]..

Ops in effetti mi è scappato e non l'avevo notato... di solito uso glColor3ub(255,0,0)

"apatriarca":
Il problema è che quando non inserisci le righe 2 e 3, la matrice ModelView non è l'identità. Quando quindi richiedi questa matrice nella funzione mouse, ottieni una posizione della sfera relativa ad una matrice diversa dall'identità. Usando quindi l'identità con questa nuova posizione ti darà dei problemi che non ha negli altri casi.


Ah ok grazie mille! Il primo dubbio è stato risolto.

Però resta ancora il secondo dubbio
"Atem":
E non capisco nemmeno il motivo per cui il programma funziona se tutte e 3 le righe sono commentate.
spherex, spherey e spherez non dovrebbero rappresentare le coordinate finali? Quindi prima di effettuare la traslazione non dovrei riportarmi sull'origine caricando la glLoadidentity?


Secondo me commentando sia la glLoadIdentity che le glPushMatrix e glPopMatrix, il programma non dovrebbe funzionare correttamente. E invece funziona: la cosa non mi è chiara....

apatriarca
Il programma funziona perché le coordinate che ti vengono restituite da gluUnProject tengono conto della matrice ModelView corrente. Non sono quelle "reali" perché la matrice cambia continuamente, ma siccome le trasformazioni sono concordi tutto va alla fine bene lo stesso.

Atem1
Ok grazie mille ora è tutto chiaro :)

Edit: ho cambiato il titolo perchè mi sono reso conto che il mio problema era sulla gluUnProject e non sulla glLoadIdentity()

Rispondi
Per rispondere a questa discussione devi prima effettuare il login.