PIPELINE DELLE TRASFORMAZIONI +------------------------+ |[3D] Object coordinates | sistema di riferimento locale in cui e' |(o modeling coordinates)| definito un singolo oggetto della scena +------------------------+ | definite agendo sulla matrice MODELVIEW, tipicamente TRASFORMAZ.DI| tra glPushMatrix e glPopMatrix affinche' la trasformazione MODELLAZIONE | agisca solo sull'oggetto in questione (ogni oggetto | deve essere trasformato in modo diverso) V +------------------------+ sistema di riferimento globale di tutta |[3D] World coordinates | la scena +------------------------+ | servono per posizionare la scena davanti alla telecamera, | definite agendo sulla matrice MODELVIEW, senza TRASFORMAZ.DI| Push e Pop, perche' sono trasformazioni della VISTA | scena nel suo globale V +------------------------+ sistema di riferimento solidale con la |[3D] View coordinates | telecamera: occhio in (0,0,0), che guarda verso | (o eye coordinates) | la direzione negativa dell'asse z +------------------------+ TRASFORMAZ.DI| definiscono tipo di trasformazione (parallela o PROIEZIONE | prospettica) e volume di vista V +------------------------+ sistema di riferimento normalizzato nel cubo |[3D] Normalized | con x,y,z tra -1 e +1, contiene (deformato | projection coordinates | dalla trasf. di proiezione) il volume di vista +------------------------+ TRASFORMAZ.DI| fatte automaticamente da OpenGL, il programma controlla VIEWPORT | l'estensione della viewport con glViewport V +------------------------+ |[2D] Device coordinates | sistema di riferimento della finestra sullo |(o viewport coordinates)| schermo (coordinate 2D espresse in pixel) +------------------------+ TRASFORMAZIONI DI MODELLAZIONE E DI VISTA In OpenGL sono controllate dalla stessa matrice (ModelView). Le abbiamo viste le volte precedenti. - Trasformaz. di modellazione: Eseguite per prime. Dimensiono (glScale), oriento (glRotate), posiziono (glTranslate) i miei oggetti per comporre la scena. Eseguite su ogni oggetto separatamente, spesso tra glPushMatrix e glPopMatrix. - Trasformaz. di vista: Eseguite DOPO quelle di modellazione, una volta composta la scena (questo significa che le corrispondenti funzioni OpenGL sono invocate PRIMA nel codice). Oriento (glRotate), posiziono (glTranslate) la scena davanti alla telecamera (o la telecamera davanti alla scena). TRASFORMAZIONI DI VISTA E PROIEZIONE Per default il volume di vista e' il cubo con x,y,z tra -1 e +1, la proiezione e' parallela, e la direzione di vista e' quella dell'asse z negativo. Finora abbiamo usato la trasformazione di default, definendo trasformazioni di vista che collocassero la scena nel cubo suddetto. In generale, e' necessario: 1) Eseguire TRASFORMAZIONI DI VISTA per portare la scena davanti alla telecamera. L'occhio e'  situato in (0,0,0) e guarda verso le z negative. Devo ruotare la scena e traslarla per portarla davanti all'occhi nella giusta angolazione. Uso glTranslate e glRotate sulla matrice MODELVIEW. Nota: mentre le trasformazioni di modellazione possono essere molte (ogni oggetto della scena puo' essere soggetto a trasformazioni di modellazione diverse), la trasformazione di vista agisce sulla scena nel suo complesso ed' e' UNA SOLA. E' bene definirla tutta assieme in un solo posto nel codice. 2) Eseguire TRASFORMAZIONI DI PROIEZIONE per definire il tipo di proiezione e il volume di vista. Agisco sulla matrice PROJECTION con una fra: glOrtho(left,right,bottom,top,near,far); moltiplica la matrice corrente con matrice ortografica (proiezione parallela). specifica il volume di vista come il parallelepipedo di diagonale (left,bottom,-near) - (right,top,-far). notare che per avere un volume di vista giacente davanti all'occhio, near e far devono essere positivi glFrustum(left,right,bottom,top,near,far); moltiplica la matrice corrente con matrice prospettica. il volume di vista e' un tronco di piramide con l'apice in (0,0,0) (l'occhio), base minore il rettangolo di diagonale (left,bottom) - (right,top) giacente sul piano z=-near, e base maggiore sul piano z=-far (ottenuta effettuando una proiezione da (0,0,0) della base minore sul piano z=-far). near e far devono essere positivi. Nota: al crescere del rapporto far/near, si perde precisione nella proiezione. quindi e' meglio evitare di definire volumi di vista troppo profondi, e casomai scalare prima la scena. Nota sulle trasformazioni di proiezione: come la trasformazione di vista, la trasformazione di proiezione agisce sulla scena nel suo complesso ed' e' UNA SOLA. E' bene definirla tutta assieme in un solo posto nel codice. FACILITAZIONI Nel pacchetto GL-UTILITIES (funzioni che iniziano con glu anziche' con gl) esistono delle funzioni che permettono di controllare questi due passi 1) (trasformazione di vista) e 2) (trasformazione di proiezione) piu' facilmente. Trasformazione di vista facilitata: gluLookAt(eyex,eyey,eyez,centerx,centery,centerz,upx,upy,upz) porta la telecamera davanti alla scena, dove (eyex,eyey,eyez) = punto dove voglio collocare l'occhio, (centerx,centery,centerz) = centro della scena, verso il quale l'occhio deve essere rivolto, (upx,upy,upz) = direzione che definisce "l'alto". Trasformazione prospettica facilitata: gluPerspective(fovy,aspect,znear,zfar) definisce trasformazione prospettica, dove fov = field of view = angolo di apertura della piramide in gradi, aspect = deformazione largehha:altezza della base del tronco di piramide (in generale la si fa coincidere con quella della viewport), znear, zfar = distanza delle due basi del tronco di piramide dallo occhio (valori positivi) Nota: le trasformazioni di proiezione OpenGL (glOrtho e glFrustum) permettono di definire volumi di vista non simmetrici rispetto alla direzione dell'occhio (left e right possono essere diversi tra loro e idem top e bottom --> posso definire volumi di vista distorti), mentre gluPerspective definisce solo volumi di vista simmetrici. PIANI DI CLIP AGGIUNTIVI Il volume di vista e' costituito da 6 piani di clip: tutto cio' che cade fuori dai semipiani positivi di questi 6 piani (fuori dal parallelepipedo o tronco di piramide da essi racchiuso) non viene visualizzato. Posso tagliare via ulteriori parti dal volume di vista definendo piani di clip addizionali (es. se voglio visualizzare una sezione di un solido). glClipPlane(,); = costante simbolica del tipo GL_CLIP_PLANEi con i tra 0 e GL_MAX_CLIP_PLANES0-1] = array di 4 float che definiscono i coefficienti della equazione del piano Ax+By+Cz+D=0 L'equazione e' specificata in world coordinates, ma viene subito trasformata in eye coordinates internamente, successive modifiche alla matrice Modelview non hanno effetto sul piano di clip. Per poter usare il piano di clip devo chiamare anche glEnable(GL_CLIP_PLANEi); TRASFORMAZIONI DI PROIEZIONE E DI VIEWPORT Il contenuto del volume di vista viene mappato (deformandolo) nel cubo normalizzato delle coordinate di proiezione. Questo cubo viene poi appiattito schiacciandolo nella direzione z e mappato nelle coordinate 2D della viewport grafica (finestra sullo schermo). Per preservare nell'immagine le proporzioni della scena, l'aspect ratio (rapporto tra dimensioni x e y) della viewport e quella del volume di vista devono essere uguali. Posso ottenere questo o adeguando la viewport al volume di vista (eventualmente selezionando solo una sottoparte della finestra attuale per il rendering - come abbiamo visto la volta scorsa) oppure adeguando il volume di vista alla viewport (inquadrando piu' o meno della scena a seconda della forma della finestra di rendering). Esempio: la finestra iniziale ha dimensione 400x400 pixel, le trasformazioni iniziali sono: gluPerspective(fov,1.0,near,far); glViewport(0,0,400,400); [aspect ratio = 1.0 perche' finestra quadrata] se la finestra viene deformata a 400x200, la trasformazione di proiezione si adegua: gluPerspective(fov,2.0,near,far); glViewport(0,0,400,200); [aspect ratio = 2.0 perche' dimensione x e' il doppio di quella y] NOTE SU GLUPERSPECTIVE L'angolo fov (field of view) da usarsi nella gluPerspective si puo' calcolare con formule trigonometriche a partire da: - la distanza d della scena dal punto di vista - la dimensione s della scena fov = 2 * arco_tangente( s/2d ) [ricordarsi di riconvertirlo in gradi!!] Come dimensione e distanza dal punto di vista della scena si possono considerare quelle della sfera circoscritta alla scena: - calcolo il bounding box (bbox) della scena (questo ha la brutta proprieta' di non essere invariante per rotazione) - calcolo la sfera circoscritta al bbox (questa e' invariante) - considero d = distanza del centro della sfera dal punto di vista, s = raggio della sfera