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
Scarica

EGD22_3Dproiez2Prosp