[Risolto][C] [OpenGL] Dubbio sulla gluUnProject
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:
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:
E non capisco il motivo.
Perchè se attivo anche riga2 e riga3 il programma funziona? Non dovrebbe essere codici equivalenti?
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
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?
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?
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]..
EDIT: glColor3f richiede colori con valori in [0, 1] e non [0, 255]..
"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....
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.
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()

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