Interazione utente- programma (dal punto di vista dell'OpenGL)

44
Interazione utente- programma (dal punto di vista dell'OpenGL)

Transcript of Interazione utente- programma (dal punto di vista dell'OpenGL)

Page 1: Interazione utente- programma (dal punto di vista dell'OpenGL)

Interazione utente-programma

(dal punto di vista dell'OpenGL)

Page 2: Interazione utente- programma (dal punto di vista dell'OpenGL)

elementi di interazione uomo->macchina:

dal punto di vista astratto possiamo elencare:

LOCATOR specifica un punto (x,y) su schermo

(ad es click del mouse)

STROKE specifica un insieme di punti (traccia del mouse, oppure una serie di click del mouse)

STRING una stringa di caratteri ("edit object")

VALUATOR un valore scalare (uno slider..)

CHOICE scelta in un menu'

PICK selezione di una componente di un'immagine strutturata...

Page 3: Interazione utente- programma (dal punto di vista dell'OpenGL)

i componenti elencati fanno spesso parte di un sistema grafico (es XWindows, la Borland Builder Visual Class Lib, Java..., ecc);

dal punto di vista dell'esecuzione del programma, abbiamo varie situazioni:

un programma puo' decidere quando ha bisogno di dati (request mode), e i dati devono essere forniti al momento della richiesta

es. tipico in/out stile "console" unix o msdos :

printf("inserisci un intero"); scanf("%d", &dato);

oppure

cout<<"inserisci dato"; cin>>dato;

... il programma su scanf oppure su cin>>

si ferma e aspetta il dato; l'istruzione di lettura e' sincronizzata con l'immissione del dato;

Page 4: Interazione utente- programma (dal punto di vista dell'OpenGL)

schema a eventi:il programma esegue costantemente un ciclo di attesa di

evento, ovvero

il programma lavora indipendentemente dal dispositivo che genera i dati: quando il dato serve al programma esso lo preleva (sample mode, campionamento) da una memoria comune, che

e' la coda degli eventi (di vario genere)

se la coda eventi e' vuota e il programma e' in attesa ("idle") l'OpenGL prevede la possibilita' di far fare al programma qualcosa "se non c'e' null'altro da fare allora fai questo"

ancora, "event mode": dall' ingresso (uno dei ..) viene generato un dato che va inserito in una coda di eventi; appena possibile, il progr.(sistema OpenGL) esamina la coda di eventi e in base al tipo di evento e al dato associato esegue quanto richiesto; l'OpenGL prevede questo come specifica normale di funzionamento:

Page 5: Interazione utente- programma (dal punto di vista dell'OpenGL)

int main (int argc, char **argv) { myOpenWindow( argc, argv ); /* GLUT init */ myInitProj( ); /* init projection matrix */

glutKeyboardFunc( myKeyboard ); /*<<<<<< */ glutSpecialFunc ( myArrowkeys ); /*<<<<<< */ glutReshapeFunc ( myReshape ); /*if reshape*/

glutDisplayFunc ( myDisplay ); /* chiamata da glutPostRedisplay() */ glutMainLoop( ); return (0);} /* main() *//*le procedure glutEventFunct(myProc) hanno parametro ditipo indirizzo di procedura, e myKeyboard, myArrowkeys, myReshape, sono procedure (che scrivo io) da eseguirein risposta agli eventi specificati:

Page 6: Interazione utente- programma (dal punto di vista dell'OpenGL)

procedura da eseguire se si preme un tasto, notificata dal main al sistema OpenGL glut prima di eseguire il glutMainLoop(); con la glutKeyboardFunc( myKeyboard ):

void myKeyboard( unsigned char key, int x, int y) { switch (key) { case 'b': case 'B': /* cambia stato */ blend_colors = ! blend_colors; break; case 27 : /*ESC key-default Unix exit*/ case 'q': case 'Q': exit(0); } glutPostRedisplay(); /*ridisegna appena possib*/} /* myKeyboardPP() */

Page 7: Interazione utente- programma (dal punto di vista dell'OpenGL)

vediamo

alcuni problemi

associati

all'ingresso dati

Page 8: Interazione utente- programma (dal punto di vista dell'OpenGL)

una situazione molto frequente si verifica quando abbiamo un dispositivo di puntamento (es. un mouse) che viene usato per selezionare un oggetto:

abbiamo il problema della distanza tra il punto PCM "posizione corrente del mouse" (marcato sullo schermo da una freccia) e un altro punto P(di un oggetto da selezionare)

PCMP

questo e' il caso piu' semplice: test di "vicinanza" equivale al test di "distanza tra due punti minore di una soglia LIMITE" :

vicino = | P - PCM | < LIMITE

Page 9: Interazione utente- programma (dal punto di vista dell'OpenGL)

distanza tra due punti

P1(x1,y1)

P2(x2,y2)

se

dx=x2-x1 e dy = y2-y1

allora

dist = sqrt( dx*dx + dy*dy )

se i due punti sono pensati come estremi di un vettore allora dist = lunghezza del vettore

P1

P2dx

dy dist

Page 10: Interazione utente- programma (dal punto di vista dell'OpenGL)

double dist ( double x1, double y1, double x2, double y2) {/* distanza tra due punti, buon vecchio

Pitagora */ return sqrt( (x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) );} /* dist */

Page 11: Interazione utente- programma (dal punto di vista dell'OpenGL)

un altro esempio di test di vicinanza e' il test di un punto (posizione del mouse) vicino ad un poligono (es un rettangolo); in tal caso il test puo' essere visto in due modi:

a) test di punto vicino / non vicino ad un lato

oppure

b) test di punto esterno / interno ad un poligono

vediamo il problema di punto vicino ad un lato, ovvero il problema di punto vicino ad un segmento:

s2s1 P

Page 12: Interazione utente- programma (dal punto di vista dell'OpenGL)

seguono alcuni richiami di geometria:punto, vettore, prodotto scalare,

retta, proiezione di vettore su retta, distanza punto retta

segue poi un cenno sul test di punto esterno / interno ad un poligono

Page 13: Interazione utente- programma (dal punto di vista dell'OpenGL)

vettore = definito da due punti:

VP = P2 - P1

ha una lunghezza

| VP | == | P2-P1 |

== dist(P2,P1)

== sqrt( dx*dx + dy*dy )

un orientamento

rispetto il sistema di riferimento

= angolo rispetto asse x

P1

P2

angolo

Page 14: Interazione utente- programma (dal punto di vista dell'OpenGL)

vettore = due punti = VP = P2 - P1

vettore=somma di due vettori S = VP1+VP2=(x1+x2,y1+y2)prodotto scalare:

x = VP1 . VP2 = |VP1| * | VP2 | * cos(a)

se uno dei due (ad es.VP1) e' unitario, il prodotto scalare e' | VP2 | * cos(a) = pred e' la proiezione di VP2 su VP1

se entrambi sono unitari, il prodotto scalare e' cos(a),con a angolo tra i due vettori... da cui cos(a) = (VP1.VP2)/(|VP1| * | VP2 |)(useremo in seguito!)

a

P1

P2

VP2

SVP1

VP1

VP2

pr

a

Page 15: Interazione utente- programma (dal punto di vista dell'OpenGL)

retta: si definisce

in molti modi:

y=mx+b

(y-y1)=m(x-x1)

x/a + y/b = 1

(con m = -b/a)

x = ax * t,

y = ay * t (parametrico)

(x-x1)/(x2-x1)=(y-y1)/(y2-y1)

y=b

x=a

P1(x1,y1)

P2(x2,y2)

Page 16: Interazione utente- programma (dal punto di vista dell'OpenGL)

retta individuata con due punti,

P1 e P2, equazione (r = P2-P1)

P = (P2-P1)*k = r * k con

(x-x1) (x2-x1)

-------- = ---------

(y-y1) (y2-y1)

(y-y1) = (x-x1)/(x2-x1)*(y2-y1)

y= m * x + dy

dove

m = (y2-y1)/(x2-x1)

e

dy = (y1*x2-x1*y2)/(x2-x1)

P1

P2

P

r

Page 17: Interazione utente- programma (dal punto di vista dell'OpenGL)

distanza

punto P --

retta P1-P2

punto P --

segmento P1-P2

P1

P2P

d

r

Page 18: Interazione utente- programma (dal punto di vista dell'OpenGL)

DISTANZA PUNTO P - RETTA (P1,P2)

( retta data dai due punti P1,P2 = dal vettore r (dx,dy) )

un vettore perpendicolare alla linea e'

(scambia dx,dy e cambia segno

per una componente):

v = ( (y2-y1), -(x2-x1) )

allora la distanza punto P e retta

e' data dal prodotto scalare del

vettore v normale alla retta e del

vettore t = P1-P che unisce P e P1,

((x1-x),(y1-y)), quindi dist = |v . r|

|(x1-x)*(y2-y1)- (y1-y)*(x2-x1)|

dist = ----------------------------------

sqrt((x2-x1)^2+(y2-y1)^2)

P1

P2P v

dx

dy

v

r

r

t

Page 19: Interazione utente- programma (dal punto di vista dell'OpenGL)

double distanza_P0_retta12 (int x0, int y0, int x1, int y1, int x2, int y2) { /*distanza di un punto P0 da una retta def.da r=P1-P2, distanza calcolata come prodotto scalare del vettore P1-P0 e del vettore v normale alla retta (a r), definita da (x1,y1) a (x2, y2), il punto e'(x0,y0) */ double lung; double vx,vy; /* v */ /* vettore normalizzato (lung==1) perpendicolare */ lung = dist(x1,y1, x2,y2); if (lung==0.0) return -999.0; /* nulla da fare...*/ /* componenti del vettore perpendicolare a P1-P2 */vx = -(y2-y1)/lung; vy = (x2-x1)/lung; /*proiezione di P0-P1 su v perpendicolare a r e norm*/ vldis = fabs( vx*(x0-x1) + vy*(y0-y1) ); return vldis;} /* distanza_P0_retta12 */

Page 20: Interazione utente- programma (dal punto di vista dell'OpenGL)

peraltro si noti che per stabilire la vicinanza di un punto ad un lato di un poligono non e' sufficiente stabilire che il punto e' vicino alla retta che passa per il lato:

p2

p3

p1

tutti e tre i punti p1,p2,p3 sono vicini alla retta che passa per il lato A-B, nel senso che la distanza punto-retta e' piccola per p1,p2,p3; ma solo il punto p2 e' vicino al lato; si dovra' quindi tenere anche conto della posizione rispetto il segmento A-B

BA

Page 21: Interazione utente- programma (dal punto di vista dell'OpenGL)

vediamo meglio:calcolo la proiezione con segno del vettore A-> pk , sul segm.

A-B, data dal prodotto scalare di r (unitario) (A-B)/|A-B| per A-> pk

si avra' per i tre punti :

( p1-A ) . r < zero,zero < ( p2-A) . r < lungh(A-B), ( p3-A) . r > lungh(A-B)

e quindi p2 e' vicino al lato A-B,

p1 e p3 non lo sono;

p2

p3

p1 BA

r

dist=linedist( x,y, xa,ya,xb,yb );onsegm=vertonseg( x,y, xa,ya,xb,yb );if( (d<limit) && (onsegment) ) { allora..e'.vicino..}

Page 22: Interazione utente- programma (dal punto di vista dell'OpenGL)

double vlineproj (int x0, int y0, int x1, int y1, int x2, int y2) {/* calcola la proiezione del vettore P1-P0 sulla retta definita daidue punti P1 P2, con segno; usata poi in vertonseg qui sotto */ double vlpro, lung; double rx,ry; /* r = (P2- P1),unitario */ lung = dist(x1,y1,x2,y2); if (lung==0.0) return -999.0; rx=(x2-x1)/lung; ry=(y2-y1)/lung; vlpro=rx*(x0-x1)+ry*(y0-y1); return vlpro ;} /* vlineproj */bool vertonseg(int x0, int y0, int x1, int y1, int x2, int y2) {/* vale true 1 se la proiezione di t sta sul segmento */ double prz, lung; lung = dist(x1,y1,x2,y2); if (lung==0.0) return -999.0; prz = vlineproj(x0,y0,x1,y1,x2,y2) ; if (prz >=0 && l<=lung) return 1; else return 0;} /* vertonseg */

Page 23: Interazione utente- programma (dal punto di vista dell'OpenGL)

nella figura a fianco il

cursore (quadratino verde)

e' posizionato vicino al

segmento diagonale a

destra,

il programma riconosce

(con un controllo di

vicinanza del cursore a

tutti i segmenti dell'

immagine) quale segmento

e' vicino al cursore, e

questo appare evidenziato

piu' chiaro,

Page 24: Interazione utente- programma (dal punto di vista dell'OpenGL)

cenno sul test di punto esterno / interno ad un poligono

Pesterno

Pinterno

Page 25: Interazione utente- programma (dal punto di vista dell'OpenGL)

appartenenza di un punto ad un poligono: test di punto P dentro/fuori di un poligono: esistono vari metodi per poligoni generali, es:regola dell' attraversamento pari/dispari : dato P, scelgo punto Q lontano dal poligono, poi conto quante volte si attra-versa un lato del poligono percorrendo tutti i puntida P a Q: P e' dentro se dispari, fuori se pari: in figura sopra, da A (oppure B) a Q sono due (o 4)attraversamenti -> A e B sono fuori, da C a S (oppure T) sono uno (o 3) attraversamenti -> C e' dentro

Q

AC

T

S

B Q

Page 26: Interazione utente- programma (dal punto di vista dell'OpenGL)

un altro metodo:

test di punto P dentro/fuoriregola dell'attraversamento orientato:si conta quante volte un seg-mento P-Q (Q lontano) vieneattraversato dai lati orientatidel poligono, contando +1 seil lato attraversa P-Q da desta sinistra, e -1 se viceversa;alla fine, se il conto e' non zero, allora P sta dentro altrimenti sta fuori;

Q

P

A

B

C

D

Page 27: Interazione utente- programma (dal punto di vista dell'OpenGL)

un altro problema da notare:

test di vicinanza - ma in che coordinate?

quando muovo il mouse, spesso il sistema fornisce al programma le coordinate schermo della posizione corrente del mouse; se si vuole ottenere le coordinate del "mondo utente" o "mondo oggetto" allora si deve fare a ritroso la trasformazione che normalmente viene fatta dalle coordinate oggetto alle coordinate schermo:

model -> object world -> viewport

(almeno 2 matrici di trasformazione, "MODEL_VIEW" e "PROJECTION", la seconda e' predisposta ad es. dalle procedure di inizializzazione...

Page 28: Interazione utente- programma (dal punto di vista dell'OpenGL)

...glMatrixMode(GL_PROJECTION); glLoadIdentity();gluOrtho2D(0.0, MyWidth, 0.0, MyHeight ); // <<<<<<<glViewport(0, 0, MyWidth,MyHeight); ... glMatrixMode(GL_MODELVIEW);glPushMatrix(); glLoadIdentity();glTranslatef(MyBariX,MyBariY,0.0); // <<<<<<<glRotatef(MyAlfa, 0.0, 0.0, 1.0); // <<<<<<<glTranslatef(-MyBariX,-MyBariY,0.0);glTranslatef(MyBariX,MyBariY,0.0); glScalef( MyScala, MyScala, 1.0); // <<<<<<<glTranslatef(-(MyBariX),-(MyBariY),0.0);drawMyObject();...le coordinate (x,y) dell'oggetto sono sempre trasformate attraverso la pipeline di visualizzazione in coordinate schermo...ad es. (0.2,0.01) in un mondo 0.0..1.0, oppure (5700.0,-4000.0) in un mondo (-10000.. +10000)

Page 29: Interazione utente- programma (dal punto di vista dell'OpenGL)

viceversa, se voglio poi nel programma eseguire un test di vicinanza, devo ri-passare da coordinate viewport del mouse a coordinate del mondo oggetto correnti:

... getRealXY ( MyPassMousePosX, MyPassMousePosY, X, Y ); if( dist(X,Y, MyBariX,MyBariY) < D_NEAR ) { we are near }.../* coord.viewport myX,myY => coord.oggetto myXREAL,myYREAL

*/void getRealXY(int myX,int myY, int& myXREAL,int& myYREAL) { GLint viewport[4]; GLdouble mvmatrix[16], projmatrix[16]; GLdouble wx,wy,wz; /* current window coordin. to current my object coord */

glGetIntegerv (GL_VIEWPORT, viewport); glGetDoublev (GL_MODELVIEW_MATRIX, mvmatrix); glGetDoublev (GL_PROJECTION_MATRIX, projmatrix); gluUnProject ( (GLdouble) myX, (GLdouble) myY, 0.0,

mvmatrix, projmatrix, viewport, &wx, &wy, &wz ); myXREAL = (GLint) wx; /* un-project== un-transform */ myYREAL = (GLint) wy;} /* getRealXY */

Page 30: Interazione utente- programma (dal punto di vista dell'OpenGL)

Riempimento (filling): un procedimento intuitivo e':

void fillR4(int x,int y, tcol bordo, tcol fillcolore){ tcol corrente = getPixel(x,y); /* colore del pix corrente */ if( corrente != colorebordo && corrente != fillcolore ) { setPixel(x,y); /* allora setColore/fillcolore; poi vedi vicini: */ fillR4(x+1, y, bordo, fillcolore ); /* destra */ fillR4(x-1, y, bordo, fillcolore ); /* sinistra */ fillR4(x, y+1, bordo, fillcolore ); /* su */ fillR4(x, y-1, bordo, fillcolore ); /* giu' */ } /* if */ } /* fillR4 */

procedimento ricorsivo per visita dei 4 pixel adiacenti (ma costa molta memoria per lo stack);meglio: procedere per linee orizzontali verso sin e verso dest, e poi procedere alle due linee sopra/sotto, e ripetere separatamente per le due linee

Page 31: Interazione utente- programma (dal punto di vista dell'OpenGL)

esempio di uso di procedura di fill(a fianco un es.di esecuzione, partendo dai punti A e B)/*fillColor =1,interiorColor=0 */void FloodFill4 (int x, int y) { if( x<0 || /* controlla */ y<0 || /* se out! */ x>=RasterSizeX || y>=RasterSizeY ) return; /*check se colore interno*/ if( getPixel( x,y ) == 0 ) { DrawMode = DRAW_OR; setPixel( x,y, 1 ); FloodFill4 ( x+1, y ); FloodFill4 ( x-1, y ); FloodFill4 ( x, y-1); FloodFill4 ( x, y+1); } /* if */} /* FloodFill4 */

A

B

Page 32: Interazione utente- programma (dal punto di vista dell'OpenGL)

A) PIU' FINESTRE:

il sistema glut permette di avere piu' finestre; esse sono create con la glutCreateWindow, che fornisce in uscita l'identificatore (un numero intero da 1 in poi) ad ogni finestra sono associate delle proc di gestione evento: ... myWinID1=glutCreateWindow("OGL5E_WWW_111"); glutSetWindow(myWinID1); myCurrentWin = myWinID1; glutDisplayFunc ( myDisplay1 ); ... myWinID2 = glutCreateWindow("OGL5E_WWW_222"); glutSetWindow(myWinID2); myCurrentWin = myWinID2; glutDisplayFunc ( myDisplay2 );

... poi posso attivare la prima finestra: myCurrentWin = myWinID1; /* NOTA !! glutSetWindow(myWinID1);

Page 33: Interazione utente- programma (dal punto di vista dell'OpenGL)

piu' finestre ...void myOpen2Windows( int argc, char* argv[ ] ) { glutInit(&argc, argv); /*GLUT initialization here comune :*/ glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);

/* for the first window: */ glutInitWindowPosition( Xwp1, Ywp1 ); glutInitWindowSize( Xww1, Ywh1 ); myWinID1 = glutCreateWindow("EGD4_D uno"); /* NOTA IL N.RO FINESTRA myWinID1 */ glutSetWindow(myWinID1); myCurrentWin = myWinID1; glutDisplayFunc ( myDis1 ); ... glutReshapeFunc ( myRes1 ); glutKeyboardFunc( myKeyb1 );

/* now the second window: */ glutInitWindowPosition( Xwp2, Xwp2 ); glutInitWindowSize( Xww2, Ywh2 ); myWinID2 = glutCreateWindow("EGD_4D due "); glutSetWindow(myWinID2); myCurrentWin = myWinID2; glutDisplayFunc ( myDis2 ); glutReshapeFunc ( myRes2 ); glutKeyboardFunc ( myKeyb2 ); glutSetWindow(myWinID1); myCurrentWin = myWinID1; } /* myOpenWindow */

Page 34: Interazione utente- programma (dal punto di vista dell'OpenGL)

piu' finestre ...void myOpen2Windows( int argc, char* argv[ ] ) { glutInit(&argc, argv); /* parte comune */ glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE); /* W1 */ glutInitWindowPosition( ... ); glutInitWindowSize( ... ); myWinID1=glutCreateWindow("Titolo"); glutSetWindow(myWinID1); myCurrentWin = myWinID1; glutDisplayFunc ( myD1 ); glutReshapeFunc ( myR1 ); glutKeyboardFunc ( myK ); /* W2 */ glutInitWindowPosition( ... ); glutInitWindowSize( ... ); myWinID2 = glutCreateWindow("OGL5E_WWW_222"); glutSetWindow(myWinID2); myCurrentWin = myWinID2; glutDisplayFunc ( myD2 ); glutReshapeFunc ( myR2 ); glutKeyboardFunc ( myK );

/* NOTA : cambia finestra attiva: */ glutSetWindow(myWinID1); myCurrentWin = myWinID1;

} /* myOpenWindow */

Page 35: Interazione utente- programma (dal punto di vista dell'OpenGL)

piu' finestre in figura lo schermo dopo la creazione di due finestre,

la seconda finestra e' attiva

Page 36: Interazione utente- programma (dal punto di vista dell'OpenGL)

piu' finestre in figura lo schermo dopo la creazione di due finestre,

qui e' attiva la prima finestra:

Page 37: Interazione utente- programma (dal punto di vista dell'OpenGL)

piu' finestre void myKeyboard(unsigned char key, int x, int y) {

switch (key) {

case '1': glutSetWindow( myWinID1 );

glutPopWindow(); break;

case '2': glutSetWindow( myWinID2 );

glutPopWindow(); break;

case '3': if (myWinID3==0) myMakeNewWin();

glutSetWindow( myWinID3 );

glutPopWindow(); break;

case 'k': if( myWinID3 !=0 )

{ glutDestroyWindow(myWinID3);

myWinID3 = 0; }

break;

} } // switch e myKeyboard ...

Page 38: Interazione utente- programma (dal punto di vista dell'OpenGL)

la terza finestra e' creata dopo, procedura tipo:

void myMakeNewWin() {

glutInitWindowPosition( 50,300 );

glutInitWindowSize( 400,400 );

myWinID3 = glutCreateWindow("EGD4_D tre ");

myCurrentWin = myWinID3;

glutDisplayFunc ( myDisplay3 );

glutReshapeFunc ( myReshape3 );

glutKeyboardFunc ( myKeyboard );

glutSetWindow(myWinID3);

glutPopWindow();

} // myMakeNewWin

piu' finestre

Page 39: Interazione utente- programma (dal punto di vista dell'OpenGL)

piu' finestre

in figura dopo la

creazione della

terza finestra

Page 40: Interazione utente- programma (dal punto di vista dell'OpenGL)

piu' finestre durante l'esecuzione si puo' cambiare posizione e dimensione

della finestra; qui, con il tasto spazio, si agisce sulla win 2:

void myKeyboard(unsigned char key, int x, int y) {

switch (key) { ....

case ' ': if( myWinID2 !=0 ) { /* se esiste la finestra 2 ...*/

Xmaxw2=300+rand()%200; Ymaxw2=200+rand()%200;

Xpos_win2= rand()%500; Ypos_win2= rand()%400;

glutSetWindow( myWinID2 ); glutPopWindow();

glutPositionWindow(Xpos_win2, Ypos_win2);

glutReshapeWindow(Xmax_win2, Ymax_win2); glViewport( 0, 0, Xmax_win2, Ymax_win2 );

glMatrixMode(GL_PROJECTION); glLoadIdentity();

gluOrtho2D( ... ); /* y=0 on bottom */

}

} } // myKeyboard

Page 41: Interazione utente- programma (dal punto di vista dell'OpenGL)

void myDisplay3(void) {

float x1,y1,x2,y2,dx,dy,r,g,b; // in una finestra si possono

int k; int wid, hi; // avere due viewport (o piu'):

wid = glutGet(GLUT_WINDOW_WIDTH);

hi = glutGet(GLUT_WINDOW_HEIGHT);

myClear(); /* clear current window (all!) * /

glViewport(0, 0, wid/2, hi); /* left half window !! * /

glMatrixMode(GL_PROJECTION); glLoadIdentity();

gluOrtho2D( 0.0, 1.0 /* x1,x2 */ , 0.0, 1.0 ); /* y=0 on bottom */

myTriFull(-0.1, 1.1, 1.1, 0.9, 0.5, -0.1, 0, 1, 1 ); /* cyano */

glViewport(wid/2, 0, wid, hi); /* right half window */

glMatrixMode(GL_PROJECTION); glLoadIdentity();

gluOrtho2D( 0.0, 1.0, 0.0, 1.0 ); /* y=0 on bottom * /

myTriFull(-0.1, 0.1, 1.1, -0.1, 0.5, 1.2, 1, 0,1 ); /*magenta*/

glFlush();

} /* myDisplay3 * /

piu' viewport

Page 42: Interazione utente- programma (dal punto di vista dell'OpenGL)

terza finestra con

due viewport

glViewport(0, 0, wid/2, hi); /* left half window !! * /

disegna in viewport a sinistra ...

glViewport(wid/2, 0, wid, hi); /* right half window */

disegna in viewport a destra ...

Page 43: Interazione utente- programma (dal punto di vista dell'OpenGL)

piu' finestre, piu' viewport, ...

...

Page 44: Interazione utente- programma (dal punto di vista dell'OpenGL)

FINE

EGD15_interaz2D