3D prospettive non parallele grafica in tre dimensioni : visualizzazione su schermo (2D) di un "mondo" ovvero una "scena" di un insieme di oggetti a 3 dimensioni in questa parte sono presentati cenni su : passaggio da 3 D a 2 D : le proiezioni prospettiche ricorda : Fondam. di grafica tridimensionale interattiva di R.Scateni,P.Cignoni, C.Montani,R.Scopigno, McGrawHill It, 2005; proiezioni geometriche piane abbiamo visto le proiezioni parallele : ortografiche piante e alzati, assonometriche isometriche, dimetriche, trimetriche oblique cavaliera cabinet altre vediamo ora le proiezioni prospettiche: a 1 punto di fuga, a 2 punti di fuga, a 3 punti di fuga piano di proiezione oggetto (segmento) da rappresentare centro di vista o punto di riferimento della prospettiva proiezioni prospettiche a 1, 2 o 3 punti di fuga: le linee parallele dello spazio oggetti che NON sono parallele al piano di proiezione convergono nel piano di proiezione verso un punto di fuga; (le linee parallele al piano di proiezione rimangono parallele al piano di proiezione) possono esserci infiniti punti di fuga, interessano in particolare i punti di fuga delle linee parallele ad uno degli assi (tre direzioni al max); vediamo ora le rappresentazioni prospettiche: rappresentazione a due punti di fuga, molto usata ... il disegno di oggetti in prospettiva fa parte dell'insegnamento nelle scuole secondarie da molti anni (veniva insegnato nel 1890 a TS sia nei licei come nelle scuole professionali per artigiani) prospettiva a 2 punti di fuga, due esempi prospettiva a 2 punti di fuga, ancora un esempio http://www.artekjara.it/Manuale/disegno/prospettiva_angolare.shtml vediamo ora le rappresentazioni prospettiche: a 1 punto di fuga, a 2 punti di fuga, a 3 punti di fuga ... la rappresentazione prospettica e' disponibile in Open GL , vedremo le tre procedure OpenGL per la definizione di una rappresentazione prospettica: glFrustum (left, right, bottom, top, near, far); gluPerspective( angle, aspect, znear, zfar); gluLookAt( x0,y0,z0, xref,yref,zref, upx,upy,upz); prospettiva a un punto di fuga un punto di fuga centrato: un punto di fuga non centrato prospettiva a un punto di fuga, due esempi: prospettiva a un punto di fuga http://www.galleriaborghese.it/spada/it/prospett.htm prospettiva 1653, palazzo Spada, di Francesco Castelli detto il Borromini se il piano di proiezione e' perpendicolare all' asse z (non interseca altri assi) allora abbiamo un punto di fuga, e le linee parallele agli assi x e y rimangono parallele *) in generale *) piano proiezione perpendicolare a asse z y x z piano di proiezione perpendicolare all' asse z (non interseca altri assi) : abbiamo un punto di fuga, le linee parallele agli assi x e y rimangono parallele in figura una vista prospettica di un cubo (a "fil di ferro") con un punto di fuga: il piano di proiezione e' orto-gonale all' asse z, le linee // agli assi x e y rimangono tali ... dal rinascimento in poi, la proiezione prospettica o prospettiva a due punti di fuga e' normalmente utilizzata nel disegno tecnico (e non) grazie al realismo e alla "piacevolezza" della scena; prospettiva a due punti di fuga, che abbiamo gia' visto qui una ripetizione: y x z se il piano di proiezione e' perpendicolare all' asse y ("verticale") e interseca gli assi x ("orizzontale") e z ("verso l'osservatore"), abbiamo due punti di fuga, e solo le linee verticali (parallele all'asse y) rimangono parallele (rimangono verticali) : infine, se il piano di proiezione interseca tutti e tre gli assi (la normale al piano di proiezione non e' parallela ad alcun piano di coordinate dell' oggetto) allora abbiamo una prospettiva con tre punti di fuga: PF1 PF2 prospettiva a tre punti di fuga PF3 la proiezione prospettica a tre punti di fuga, dove anche le linee verticali convergono - in basso (come in fig. a destra) oppure in alto, e' poco usata ... La prospettiva con 3 punti di fuga aggiunge poco al realismo della scena, e "distorce la scena" si usa poco (effetti speciali in film di animazione digitale) per passare dal mondo di coordinate (x,y,z) di un oggetto della scena 3D al mondo coordinate (x,y) nel piano di proiezione nella rappresentazione prospettica si usa una matrice di trasformazione prospettica: P2D = MTP x P3D P2D = il punto in 2D e' dato dal prodotto matriciale (coord.omogenee) di MTP per il P3D = punto in 3D vediamo... trasformazione prospettica : y P(x,y,z) Pp(xp,yp,zp) x z d Mpro y P(x,y,z) Pp(xp,yp,zp) y yp d P(x,y,z) punto dell'oggetto, Pp(xp,yp,zp) su piano prospettico, dai triangoli simili (sin. sotto) ho: yp/d = y/z e xp/d = x/z da cui xp=x*d/z, yp=y*d/z, zp=d da cui la trasformazione matriciale z 1 0 0 0 0 1 0 0 0 0 1 1/d 0 0 0 0 infatti dal prodotto Mpro* P con P(x,y,z,w) righe per colonne si ha P=(x,y,z,z/d) se ora divido per w=z/d, e quindi (x/w,y/w,z/w)=(x/(z/d),y/(z/d),z/(z/d)) riottengo quanto sopra: (xp,yp,zp)=(x*d/z,y*d/z,z*d/z) matrice di trasformazione prospettica generale: nel caso generale avremo (Hearn Baker ecc) : 1 0 -dx/dy zp*dx/dz 0 1 -dy/dz zp*dy/dz Mgen 0 0 -zp/(Q*dz) zp2/(Q*dz)+zp 0 0 -1/(Q*dz) zp2/(Q*dz)+1 dove P e' il punto da proiettare, Pp e' la proiezione di P sul piano di proiezione (perpendicolare all'asse z e situato a distanza zp dall'origine), centro di proiezione non vincolato x oppure y CP Pp(xp,yp,zp) P(x,y,z) (0,0,zp) z vediamo i limiti dello spazio visualizzato: inevitabilmente solo una parte della scena del mondo degli oggetti puo' essere visualizzata, e quindi si deve specificare i limiti di questo spazio: gli oggetti che stanno fuori tale spazio non vengono visualizzati, sono tagliati termine tecnico, clipping clip 2 |klɪp| verb ( clipped |klɪpt|, clipping |ˌklɪpɪŋ|) [ trans. ] 1 cut short or trim (hair, wool, nails, or vegetation) with shears or scissors : clipping the hedge. trim or remove the hair or wool of (an animal) : clip your horse. ( clip something off) cut off a thing or part of a thing with shears or scissors : he clipped off a piece of wire | figurative she clipped nearly two seconds off the old record. cut (a section) from a newspaper or magazine : a photograph clipped from a magazine. speak (words) in a quick, precise, staccato manner : “Yes?” The word was clipped short | [as adj. ] ( clipped) cold, clipped tones. Computing process (an image) so as to remove the parts outside a certain area. Electronics truncate the amplitude of (a signal) above or below predetermined levels. 2 strike briskly or with a glancing blow : the steamroller clipped some parked cars | branches clipped his face. [ trans. ] strike or kick (something, esp. a ball) briskly in a specified direction : he clipped a right-field double. 3 informal swindle or rob (someone) : in all the years he ran the place, he was clipped only three times. 4 [ intrans. ] informal move quickly in a specified direction : we clip down the track. frustum |ˌfrəstəm| |ˌfrʌstəm| noun ( pl. -ta |-tə| |ˌfrəstə| |-tə|or -tums |ˌfrəstəmz|) Geometry the portion of a cone or pyramid that remains after its upper part has been cut off by a plane parallel to its base, or that is intercepted between two such planes. ORIGIN mid 17th cent.: specifico il volume di visualizzazione con: Pvista (PRP) e finestra di visualizzazione , separatamente i limiti per l'asse z (near/far) oppure specifico il volume di visualizzazione dando: Pvista (PRP) , angolo di visualizzazione (entrambe le cose in OpenGL) - e separatamente i limiti per l'asse z (near/far) ricorda l' orientamento dei tre sistemi di assi: dell'oggetto, del piano di proiezione, dell'osservatore (punto di vista) nella prospettiva ortogonale la posizione del punto di vista sull'asse z non ha importanza, sono importanti solo i limiti di visualizzazione [ se sbagliati, non vedo nulla <:-( ] clipping asse z: quello che sta fuori dei limiti per l'asse z viene tagliato, cioe' quello che sta prima di znear o dopo zfar; qui esempio di eliminazione dovuta al cambio di zfar (da 2 a 0.3) : qui visualizzati 4 cubetti messi sui vertici di un cubo (progr. EGD3D_01XORTHO), a inizio di myDisplay e' chiamata la glOrtho( xmin, xmax, ymin, ymax, znear, zfar ); con xmin=-2,xmax=2,..,znear =-2, zfar = 2; ... si cambiano i limiti z con left_arrow ( znear=znear*0.75; zfar=zfar*0.75; ) clipping asse z: quello che sta fuori dei limiti per l'asse z (se z esce da [znear..zfar] ) viene tagliato. In figura e' usata la prospettiva parallela (glOrto), dove il frustum e' un parallelepipedo (xmin..zfar). qui visualizzati 4 cubetti messi sui vertici di un cubo (progr. EGD3D_01XORTHO), a inizio di myDisplay e' chiamata la glOrtho( xmin, xmax, ymin, ymax, znear, zfar ); con xmin=-2,xmax=2,..,znear =-2, zfar = 2; poi si cambiano i limiti znear,zfar (usato zn=zn*0.75; zf=zf*0.75); il frustum si accorcia nel senso delle z, e le parti fuori sono eliminate 3 D - geometria, prospettive, OpenGL 3D y z x Per definire la visione prospettica in OpenGL si usano le procedure glFrustum e gluPerspective: glFrustum(left,right, bottom,top, near,far) definisce la prospettiva con il volume di vista, una piramide tronca detta appunto "frustum"; nota: left, right, bottom, top sono coordinate, near,far sono distanze dal punto di vista 3 D - geometria, prospettive, OpenGL 3D il volume di vista (dove sono gli oggetti che saranno visualizzati) e' un parallelepipedo (vista ortogonale) oppure una piramide tronca (prospettiva) detta "frustum" - in OGL il piano di vista e' sempre il piano z=znear. asse z, con z<0 in OGL il piano di vista e' sempre il piano z=znear, l'osservatore sta nell'origine z e guarda verso le z<0 y x 3 D - geometria, prospettive, OpenGL 3D nella prospettiva non ortogonale il frustum e' una piramide tronca nota: znear e zfar DEVONO essere positivi NON nulli ad es. 0.01--100.0 1.0--2.0 ecc, e TUTTE le z degli oggetti sono in tale intervallo il piano di vista e' il piano z=znear. glFrustum (left, right, bottom, top, near, far) void myDisplay() { // prospettiva definita con frustum : glClearColor( 0.1, 0.1, 0.3, 1.0f ); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_B...BIT); glMatrixMode( GL_PROJECTION); glLoadIdentity(); glFrustum(-1.1,1.1, -1.1,1.1, 2.0, 100.0 ); // xmin, xmax, ymin,ymax znear,zfar glPushMatrix(); glLineWidth(3.0); glTranslatef( 0, 0, -4.0 ); glColor4f( 0.2, 0.2, 1.0, 0.5); glutWireCube(2.0); glRotatef( +10.0, 1.0, 0.0, 0.0); glColor4f( 1.0, 0.2, 0.2, 0.5); glutWireCube(2.0); glPopMatrix(); myLines(); glFlush(); } // myDis void myDisplay(){ // prospettiva definita con frustum : glClearColor( 0.1, 0.1, 0.3, 1.0f ); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_B...BIT); glMatrixMode( GL_PROJECTION); glLoadIdentity(); glFrustum(-1.1,1.1, -1.1,1.1, 2.0, 100.0 ); // xmin, xmax, ymin,ymax znear,zfar glPushMatrix(); glLineWidth(3.0); glTranslatef( 0, 0, -4.0 ); glColor4f( 0.2, 0.2, 1.0, 0.5); glutWireCube(2.0); glRotatef( +10.0, 1.0, 0.0, 0.0); glColor4f( 1.0, 0.2, 0.2, 0.5); glutWireCube(2.0); glPopMatrix(); myLines(); glFlush(); } // myDis nota il primo cubo blu centrato, il secondo rosso inclinato in avanti (ruota attorno asse x di 10 gradi) void myDisplay(){ ... glFrustum(-1.1,1.1, -1.1,1.1, 2,100); // znear, zfar glPushMatrix(); .. glPopMatrix(); myLines(); glFlush(); } /* myDisplay */ void myLines(){ float x=-0.5,z,r=1,g=0,b=1; while(x<=0.5){ glLineWidth(2); z= -1; while(z>=-100) { nota in mezzo due glBegin(GL_LINES); glColor3f(r,g,b); tratti orizzontali (a glVertex3f(x, -0.5, z ); y=-0.5), uno a sinistra glVertex3f(x, -0.5, z -1.0 ); (x=-0.5) e uno dest glEnd(); z -= 2; g += 0.1; b -= 0.1; (x=0.5), tratteggio a } x +=1.0; r=0; distanza di z=z-2; } /* while x,z */ ... void myDisplay(){ ... glFrustum(-1.1,1.1, -1.1,1.1, 2,100); glPushMatrix(); .. glPopMatrix(); myLines(); glFlush(); } /* display */ void myLines(){ float x=-0.5,z,r=1,g=0,b=1; ... glColor3f( 1, 1, 1 ); glBegin(GL_LINES); glVertex3f(-1,0, -4); glVertex3f( 1,0, -4); // hor glVertex3f(0,-1, -4); glVertex3f( 0,1, -4); // ver glEnd(); } // myLines infine due segmenti bianchi, in posizione z = -4, e con vertici in (-1,0) -- (1,0) (orizzontale) (0,-1) -- (0,1) (verticale) il resto: #if defined __APPLE__ #include <GLUT/glut.h> #else #include <windows.h> #include <GL/gl.h> #include <GL/glu.h> #include <GL/glut.h> #endif float wi=500,he=500; void myOpenWin(int n,char*a[ ]){ glutInit( n, a ); glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE ); glutInitWindowPosition(40,40); glutInitWindowSize(wi, he); glutCreateWindow( "FRU"); } /* myOpenWin */ void myInit ( ) { wi = glutGet( GLUT_WINDOW_WIDTH); he = glutGet( GLUT_WINDOW_HEIGHT); glViewport(0,0,wi,he); } /* Init */ int main ( int n, char * a[]) { myOpenWin( n, a ); myInit(); glutDisplayFunc( myDisplay); glutMainLoop( ); return 0; } /* main */ nel main: ... glMatrixMode( GL_PROJECTION); glLoadIdentity(); glFrustum(-1,1, -1,1, 1.5,20); ...// limiti x y nella Display: z glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glPushMatrix(); glTranslatef( tx, ty, tz ); glRotatef(ang, 1.0,1.0,1.0); // rotate ang degrees around // the vector (1,1,1) */ nota: i lati NON si mantengono paralleli! (prog. OGL3D_2FRUSTUM) glScalef ( 1.0, 2.0, 1.0 ); // cube elongated upward DrawCube(); gluPerspective la libreria OpenGL offre un secondo modo per specificare una prospettiva, forse un piu' intuitivo: vengono specificati i parametri = apertura angolare dell' "obiettivo" ("fovy" (*) = rapporto dx/dy (1 quadrato, w/h >1 orizzontale ...) = limiti z della scena: troncato quello che sta prima (o addiritura dietro l'osservatore) oppure dopo (troppo lontano verso le z negative) gluPerspective ( double fovy, double aspect, double znear, double zfar ); ------------------------------------- (*) nota "fovy" = Field Of Viewing Angle gluPerspective per specificare una prospettiva si puo' anche dare: = apertura angolare dell' "obiettivo" ("fovy" (*) = rapporto tra dx e dy (1 se quadrato, w/h >1 se orizzontale ...) = limiti della scena (troncare quello che sta prima (o addiritura dietro l'osservatore) oppure dopo (troppo lontano verso le z negative) gluPerspective( double fovy, double aspect, double znear, double zfar); esempio: fovy 45.0 (gradi) aspect 1.6 (w/h) znear 0.5 gluPerspective( 45.0, 1.6, 0.5, 100.0 ); ------------------------------------- (*) nota "fovy" = Field Of Viewing Angle zfar 100.0 la libr. OpenGL prevede la possibilita' di specificare direttamente un tipo di prospettiva come dai parametri nella figura sopra gluPerspective( db fovy, db aspect, db znear, db zfar); db sta per double, fovy angolo apertura (asse y) (15 gradi=tele, 60 gradi=grandang) w/h e' l'aspect ratio , znear e zfar sono i limiti delle distanze dal viewpoint agli oggetti lungo l'asse z negativo, in genere positivi /* 3D_3PERSP_Cube perspective view truncated pyramid = frustum: (* ------------------object---------- top | ------------------------------ bottom | | | eye near limit zf far limit == distance viewpoint zn between viewpoint and object ==origin (0,0,0) we look down negative z axis, positive z toward us object is clipped if nearer than frustum "near", zn, or farther than frustum "far"; zf or out of left/right, top/bottom limits with glPerspective( angle, aspect, znear, zfar) we specify fovy=viewangle, aspect=width/height, near, far; the viewangle gives the viewing volume angle; in this example the object is sized 1, with vertex coordinates (-0.5,-0.5,-0.5) (-0.5,0,0),(0,-0.5,0),..(0.5,0.5, 0.5) and is moved (MODELVIEW, then translate) to position (0,0,-10), viewpoint is in (0,0,0) and the viewing volume is given with: gluPerspective( viewang, 1.0, zn, zf ); fovy=viewangle, 1.0=aspect=width/height, zn,zf= znear, zfar where viewang = 45.0 and znear= 0.5, zfar = 100.0; di seguito e'riportata parte del testo del progr.ma 3D_3PERSP dove e' anche illustrato un modo per definire un oggetto: vengono definiti separatamente tutti i vertici (un cubo ha otto vertici), (X e' una costante, qui vale 0.5) GLfloat vdata[8][3]= /*sono 8 punti che def il cubo*/{ {X,X, X}, {X,-X, X}, {-X,-X, X}, {-X,X, X}, {X,X,-X}, {X,-X,-X}, {-X,-X,-X}, {-X,X,-X} poi le facce (ogni faccia del cubo ha 4 vertici, e sono scelti tra i vertici elencati del cubo), GLint tindices[6][4] = { /* vertici delle 6 facce */ {1,2,3,4}, /* top*/ {5,8,7,6}, /*bottom*/ ... } si definisce una faccia in modo che osservando la faccia dall'esterno i vertici vengono elencati in senso antiorario (vedremo in seguito per il problema delle faccie nascoste) /* DEFINIZIONE E DISEGNO DEL CUBO: */ const GLdouble X= 0.5; /* size of half edge */ /* upper face vert. 1,2,3,4 clockwise, lower face 5,6,7,8 */ GLint kk[6]={0,1,2,3,4,5}; /* order of faces drawing */ static GLfloat vdata[8][3]= /*sono 8 punti che def il cubo*/{ {X,X, X}, {X,-X, X}, {-X,-X, X}, {-X,X, X}, {X,X,-X}, {X,-X,-X}, {-X,-X,-X}, {-X,X,-X} }; /* how to link vertices to make a RECT: the first (top) rect */ /* is made from vertices 1,2,3,4; bottom rect is 5,8,7,6, etc*/ static GLint tindices[6][4] = { {1,2,3,4}, /* top*/ {5,8,7,6}, /*bottom*/ {1,5,6,2}, /* front*/ {4,3,7,8}, /*rear*/ {2,6,7,3}, /* left side*/ {1,4,8,5} /*right side*/ }; /* end tindices */ ... void DrawCube(){ GLint i,ii; for (i=0; i<6; i++) { glBegin(GL_POLYGON); ii=kk[i]; /* gives the order */ glVertex3fv( &vdata[ tindices[ii][0]-1 ] [0]); glVertex3fv( &vdata[ tindices[ii][1]-1 ] [0]); glVertex3fv( &vdata[ tindices[ii][2]-1 ] [0]); glVertex3fv( &vdata[ tindices[ii][3]-1 ] [0]); glEnd(); } /* for i */} /* DrawCube */ 3 D - geometria, prospettive, OpenGL 3D esempio di un risultato prodotto dal programma OGL3D_3PERS P una terza possibilita' di specifica di una prospettiva abbiamo visto due modi per definire la visione prospettica di una scena: glFrustum ( left, right, bottom, top, near, far) e gluPerspective( fovy, aspect, znear, zfar); entrambe le procedure pero' sono meno intuitive rispetto l'idea di dire: metto la telecamera montata in una certa posizione, diretta verso un certo punto e orientata in un certo angolo rispetto la verticale - allora in analogia alla macchina fotografica per ottenere la specifica di una prospettiva : posso dire DOVE sta la macchina, e dove sta l' oggetto da visualizzare, e come e' orientata la macchina fotografica - puo' essere inclinata (non verticale = parallela all'asse y) in aggiunta a glFrustum e gluPerspective abbiamo : gluLookAt( eyePosX, eyePosY, eyePosZ, lookAtX, lookAtY, lookAtZ, upX, upY, upZ ); l'openGL ha una procedura per specificare con una procedura la posizione del punto di vista, degli oggetti e del versore "v_alto": { segue una gluPerspective(), glOrtho() and glFrustum() } gluLookAt( x0,y0,z0, xref,yref,zref, vax,vay,vaz); P0=viewpoint Pref=origine o riferim. oggetti, valto=direzione dove sta l'alto gluLookAt e' una procedura per specificare con una chiamata la posizione del punto di vista e del versore "v_alto": in figura, il punto di vista e' spostato rispetto l'oggetto, e ruotato ("up vector" <> asse y) gluLookAt( x0,y0,z0, xref,yref,zref, vax,vay,vaz); con P0=(0,0,0) origine oggetti Pref=viewpoint valto=direzione dove sta l'alto esempio uso gluLookAt (da Nate Robins, projection tutorial) http://www.xmission. com/~nate/tutors.html in figura l'angolo di apertura e' 88 gradi (grandangolo) rapporto x/y e' 1, znear, zfar 1 e 10 il punto di vista e' nel punto (0,0,2) (indicato a sinistra con gli assi in rosso) l'orientamento della "macchina fotografica" e' in alto gluPerspective e gluLookAt esempio uso gluLookAt (da Nate Robins, projection tutorial) cambia fovy e Lookat: in figura l'angolo di apertura e' 18 gradi (teleobiettivo) rapporto x/y e' 1, znear, zfar 1 e 10 il punto di vista e' nel punto (0,0.5, 2.6 ) all'altezza del viso, il centro "dove si guarda" e' all'altezza 0.7 (viso), orientamento macchina fotografica e' in alto gluPerspective e gluLookAt esempio uso gluLookAt (Nate Robins, projection) qui e' usata la glOrtho, con frustum "stretto", si ritaglia solo il viso; cambia anche il punto di vista, e' nel punto (0.2, 1.1, 4.2) sopra la testa (il viso si vede dall'alto), il centro dove si guarda e' all' altezza 0.7 (viso), orientamento macchina fotografica e' in alto glOrtho e gluLookAt Un esempio di uso di gluLookAt: posso visualizzare la stessa scena da due punti di vista diversi in due finestre diverse: la display e' la stessa, cambia la prospettiva ovvero posso usare due punti di vista diversi con la gluLookAt : gluLookAt( eyePosX, eyePosY, eyePosZ, lookAtX, lookAtY, lookAtZ, upX, upY, upZ ) (eyePosX, eyePosY, eyePosZ) posizione dell'occhio (lookAtX, lookAtY, lookAtZ) posizione dell'oggetto a cui guardo (upX, upY, upZ) orientamento della mia testa nella figura seguente abbiamo vp1 = Eye1 x,y,z = 2.90 1.60 -3.00 nota eyey=1.6 vp1 = Obj x,y,z = 0.00 0.00 -6.00 cioe' vista dall'alto vp1 = UP vec xyz= -0.60 1.00 -0.20 vp2 = Eye1 x,y,z = -0.80 -1.50 -3.90 nota eyey= -1.5 vp2 = Obj x,y,z = 0.00 0.00 -6.00 cioe' vista dal basso vp2 = UP vec xyz = 0.00 1.00 0.40 vista tre cubetti unitari con due viewport diversi, e con valori di gluLookAt diversi; dati: posiz occhio, posiz.oggetto, versore vertic vp1 = Eye1 x,y,z = 2.90 1.60 -3.00 nota eyey=1.6 vp1 = Obj x,y,z = 0.00 0.00 -6.00 cioe' vista dall'alto vp1 = UP vec xyz= -0.60 1.00 -0.20 vp2 = Eye1 x,y,z = -0.80 -1.50 -3.90 nota eyey= -1.5 vp2 = Obj x,y,z = 0.00 0.00 -6.00 cioe' vista dal basso vp2 = UP vec xyz = 0.00 1.00 0.40 esempio con due finestre, stessa scena, con due viste diverse: (programma di Michael Toffolon, 12 nov 2008, EGD3D06X2dueFinestreToffolon.cpp) void myOpenWin ( int argc, char * argv[] ) { glutInit(&argc, argv); glutInitDisplayMode( ... ); glutInitWindowPosition(px,py); glutInitWindowSize( Wx,Wy ); myWinID1=glutCreateWindow("Prima"); // inizial. 1.a finestra glutSetWindow(myWinID1); myCurrentWin = myWinID1; gluLookAt(eX1,eY1,eZ1,lX1,lY1,lZ1,uX1,uY1,uZ1); // punto di glutDisplayFunc(myDispl1); // vista, punta in direzione ... glutReshapeFunc(myResh1); glutKeyboardFunc( myKeyb ); myInitPersp(); myInitData(); glutInitWindowPosition(px+Wx, py);// inizializzo 2.a finestra myWinID2=glutCreateWindow("Seconda"); glutSetWindow(myWinID2); myCurrentWin = myWinID2; gluLookAt(eX2,eY2,eZ2,lX2,lY2,lZ2,uX2,uY2,uZ2); // 2.o punto glutDisplayFunc( myDispl1 ); // di vista, punta in direzione ... glutReshapeFunc(myResh1); glutKeyboardFunc( myKeyb ); myInitPersp();myInitData(); } // myOpenWin void myInitPersp(){ // se tasto aggiorno parametri prospettiva int w=glutGet(GLUT_WINDOW_WIDTH); int h=glutGet(GLUT_WINDOW_HEIGHT); glViewport(0,0,w,h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(apertura, aspetto, vicino, lontano); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); // e verifico in che finestra sono: se cambiata aggiorno lo stato.. if(glutGetWindow()==myWinID1){ if(myWinID1!=myCurrentWin){ tx2=tx;..y..z..; rotx2=rotx; ..y..z ; tx=tx1;..y..z..; rotx=rotx1;..y..z..; myCurrentWin=myWinID1; } // if myWin.. gluLookAt(eX1,eY1,eZ1,lX1,lY1,lZ1,uX1,uY1,uZ1); }else{ if(myWinID2!=myCurrentWin){ tx1=tx;..y..z..; rotx1=rotx;..y..z..; tx=tx2;..y..z..;rotx=rotx2;..y..z..; myCurrentWin=myWinID2; } gluLookAt(eX2,eY2,eZ2,lX2,lY2,lZ2,uX2,uY2,uZ2);} glutPostRedisplay(); } // myInitPersp, chiamata anche in: void myKeyboard(..){ .. myInitPersp(); glutPostRedisplay();} orientamento dei poligoni e visualizzazione dei poligoni ancora tre argomenti per la visualizzazione di oggetti in 3D in EGD3D_07DisplayListCuboAnima sono usate alcune possibilita' dell' OpenGL: glPolygonMode e orientamento dei poligoni culling display list orientamento dei poligoni e visualizzazione dei poligoni ancora tre argomenti per la visualizzazione di oggetti in 3D nota: l' orientamento dei poligoni deve essere consistente, in EGD3D_07DisplayListCuboAnima e' usata specifica della modalita' di tracciamento di una faccia (un poligono) a seconda se la faccia e' orientata in avanti o verso dietro; attenzione: un poligono e' orientato, nel senso che il verso di percorrenza dei vertici definisce un orientamento; in OpenGL si assume orientamento positivo quello antiorario: default: glFrontFace(GL_CCW); le facce con orientamento anti-orario (counter-clock-wise) si assumono volte verso l'osservatore, e quindi sono visibili (si puo'cambiare: se chiamo glFrontFace(GL_CW); allora le facce con orientamento orario (clock-wise) si assumono volte verso l'osservatore orientamento dei poligoni e visualizzazione dei poligoni nel programma EGD3D_07DisplayListCuboAnima e' usata una variabile DisplayMode per controllare il tipo di visualizzazione, 1 lines 2 fill 3 fill and lines switch(DisplayMode) { case 1: glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break; case2:glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); break; case 3: glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); glPolygonMode(GL_BACK, GL_FILL); // facce piene glPolygonMode(GL_FRONT,GL_LINE);//solo bordi //c'e'anche glPolygonMode( GL_FRONT, GL_POINTS); break; } // switch orientamento dei poligoni e visualizzazione dei poligoni inoltre in EGD3D_07DisplayListCuboAnima e' usato il "culling" o selezione faccie da far vedere se culling e' attivo NON sono mostrate le facce nascoste, cioe' orientate via dall'osservatore) glCullFace(GL_BACK); if(doCulling) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE); orientamento dei poligoni e visualizzazione dei poligoni in EGD3D_07DisplayListCuboAnima e' usata la display list: procedure usate per definire un oggetto a partire da vertici: CubeListId = glGenLists(1); // numero identificazione display list glNewList( CubeListId, GL_COMPILE ); //inizia costruire lista glPushMatrix(); //- salva matrice trasformaz.corrente glPushAttrib(GL_CURRENT_BIT); // salva colore,traslazione.. glColor3f(0.8, 0.2,0.2); glBegin(GL_POLYGON); glColor3f(0.2, 0.2, 0.8); glVertex2f(0.0, 1.0); glColor3f(1.0, 0.5, 0.5); glVertex2f(-3.0, 7.0); glEnd(); glTranslatef(2.0,0.0,0.0); ... glPopAttrib(); glPopMatrix(); // ripristina glEndList(); orientamento dei poligoni e visualizzazione dei poligoni CubeListId = glGenLists(1); glNewList( CubeListId, GL_COMPILE ); // inizia costruire lista glPushMatrix(); glPushAttrib(GL_CURRENT_BIT); // salva stato ... glBegin(GL_POLYGON); glPopAttrib(); glPopMatrix(); - ripristina glEndList(); in seguito per disegnare l'oggetto nella myDisplay: ... glCallList(CubeListId); display lists: danno un esecuzione piu' efficiente del codice, i comandi OpenGL tra glNewList(..) e glEndList() sono interpretati e memorizzati, e l'esecuzione successiva e' piu' veloce; es: #define myList 1 void faiC(){ GLint i; GLfloat co,se; in seguito si glNewList(myList,GL_COMPILE); esegue la glBegin(GL_POLYGON); display list con for(i=0; i<100; i++) { il semplice co=cos(i*2*M_PI/100.0); richiamo: se=sin(i*2*M_PI/100.0); glVertex2f(co,se); glCallList( } // for i myList glEnd(); ); (vedere list.c glEndList(); esempi red-book) e con la slide seguente, che e' solo l'indice dei programmi demo, abbiamo finito questa prima parte della grafica 3D, con la presentazione delle possibilita' date in OpenGL in 3D per la resa prospettica di una scena 3D programmi, parte EGD_07_3D1 : 1 EGD3D_01ORTHO 11 EGD3D_01X1ORTHO (9 O 4 CUBI, ANIMAZ) EGD3D_01X2ORTanim (Vers.di A.SORIO) 2 EGD3D_02XORTHO (SCELTA OGGETTO) 3 EGD3D_03FRUSTUM 31 EGD3D_03X1FRUSTUM 4 EGD3D_04PERSPcubeDef 5 EGD3D_05DisplayListCubo 6 EGD3D_06LookAt scelta oggetto, LookAt 61 EGD3D_06X1LookAt9cubi.cpp piu'oggetti 62 EGD3D_06X2LookAtDue - due viewport 63 EGD3D_06X3LookAtDue - due window 7 EGD3D_07DisplayListCuboAnima 8 EGD3D_08PerspAnima3P3CUBI 12