In generale le trasformazioni di vista e quelle di proiezione vanno progettate assieme.
Per esempio vogliamo guardare la scena in modo da avere l'asse x diretto verso la nostra destra, l'asse y diretto verso il nostro alto, l'asse z diretto dietro la nostra schiena. E' la situazione di default, ma proviamo a "rifarla a mano".
Supponiamo per esempio che la nostra scena sia centrata in C=(xC,yC,zC), che occupi un volume cubico di lato l e che il volume di vista da inquadrare sia un cubo concentrico a quello, di lato L>l.
Sistemiamo la telecamera.
Usiamo la funzione gluLookAt a cui dobbiamo passare
la posizione della telecamera, la posizione del punto verso cui
e' rivolta e la direzione del vettore che segna "l'alto".
In proiezione ortografica non importa DOVE e' la telecamera, ma solo
COME e' orientata.
Possiamo collocarla in C e puntarla verso un punto
T che stia
sulla retta passante per C e parallela all'asse z,
e tale che T abbia coordinata z minore di quella di C.
Quindi scegliamo T=(xC,yC,zC-d) con d>0.
L'alto e' dato dal versore dell'asse y (0,1,0).
Istruzioni:
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(xC,yC,zC, xC,yC,zC-d, 0,1,0);
Scegliamo l'ampiezza dell'inquadratura.
Usiamo la funzione glOrtho a cui dobbiamo passare
le coordinate x minima e massima, y minima e massima, z
minima e massima del volume di vista da inquadrare.
IMPORTANTE: queste coordinate sono espresse in un sistema di riferimento
trasformato la cui origine e' il punto
nel quale abbiamo messo la telecamera (coordinate di vista).
Nel nostro caso tale punto e' il centro della scena C.
Quindi se le coordinate minime e massime della scena prima (in
coordinate del mondo) erano
Per esempio vogliamo un volume di vista (tronco di piramide) con asse parallelo all'asse z, base minore verso le z positive e base maggiore verso le z negative, le due basi sono quadrate.
Supponiamo per esempio che la nostra scena sia centrata in C=(xC,yC,zC) e che occupi un volume cubico di lato l.
Sistemiamo la telecamera.
Usiamo sempre la funzione gluLookAt a cui dobbiamo passare
i parametri gia' detti sopra.
In proiezione prospettica e' importante DOVE posizioniamo la telecamera,
perche' diventera' il vertice della priramide che, troncata, sara'
il nostro volume di vista.
Mettiamo la telecamera in punto V che stia
sulla retta passante per C e parallela all'asse z,
e tale che T abbia coordinata z maggiore della
massima coordinata z della scena.
Quindi scegliamo V=(xC,yC,zC+d) con d>l/2.
Puntiamo la telecamera verso C.
L'alto e' dato dal versore dell'asse y (0,1,0).
Istruzioni:
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(xC,yC,zC+d, xC,yC,zC, 0,1,0);
Scegliamo l'ampiezza dell'inquadratura.
Usiamo la funzione gluPerspective a cui dobbiamo passare
l'angolo di apertura, la aspect ratio della base della piramide,
e le distanze delle basi minore (near)
e maggiore (far) del tronco di piramide dal punto di vista.
L'angolo di apertura per sicurezza lo prendiamo abbastanza grande,
per es. 60 gradi.
L'aspect ratio e' 1 perche' vogliamo piramide a base quadrata.
Le distanze near e far
delle basi del tronco di piramide dal punto di vista vanno
scelte in modo tale che tutta la scena sia compresa fra le due basi:
direzione z zV=zC+d zC <-----------------+-----+-------+-------+-------- | | l/2 | l/2 | | |<----->|<----->| | d | |<----------->|Quindi:
In condizioni normali, le istruzioni OpenGL (specifiche di primitive, attributi, trasformazioni ecc.) vengono mandate dal programma al motore grafico di OpenGL, che la processa immediatamente per produrre l'immagine della scena, e poi le "dimentica" (non le memorizza). Se il programma vuole rieseguire la stessa sequenza di istruzioni una seconda volta, deve reinviarla, con spesa di tempo.
Display list = serie di istruzioni OpenGL a cui e' stato assegnato un nome (identificatore numerico).
Una display list viene visualizzata usando i parametri dello stato corrente di OpenGL. Cosi' la stessa primitiva, inserita in una display list, puo' essere chiamata con stato corrente modificato, dando luogo a un effetto diverso.
Per esempio, tra una chiamata e l'altra della display list posso cambiare colore, spessore di linea, trasformazioni geometriche ecc.
Posso disegnare un'intera scena (es. composta da parallelepipedi di dimensioni e colori diversi) usando un'unica display list che viene scalata/traslata/colorata in modo diverso.
NOTA: Una display list viene visualizzata sotto l'influsso dello stato corrente al momento in cui chiamo glCallList. Questo non vieta di modificare lo stato corrente dentro la display list stessa. Tenere pero' presente che, in questo caso, dopo ogni chiamata alla display list trovero' lo stato modificato. Molto meglio cambiare lo stato localmente alla display list, usando glPush e glPop.
Parte da chiamare una sola volta all'inizio, definisce una display list contenente un quadrato:
mylist = glGenLists(1); glNewList(mylist,GL_COMPILE); glBegin(GL_QUADS); glVertex2f(0.0,0.0); glVertex2f(1.0,0.0); glVertex2f(1.0,1.0); glVertex2f(0.0,1.0); glEnd(); glEndList();Parte da chiamare ogni volta che occorre disegnare la display list, qui disegna piu' quadrati traslati uno rispetto all'altro, chiamando la display list varie volte:
glMatrixMode(GL_MODELVIEW); for (i=0; i<5.0; i++) { glPushMatrix(); glTranslatef(0.2*i,0.0,0.0); glScalef(0.1,0.1,1.0); glCallList(mylist); glPopMatrix(); }