For new raytraced stuff, I started learning human 3D modeling.
Here some picture of example of CGI.
Now it's time to improve the quality of the models created.
In questo blog si parla di programmazione con il linguaggio C++, i post cercheranno di essere molto esplicativi sull'argomento trattato.
Visualizzazione post con etichetta OpenGL. Mostra tutti i post
Visualizzazione post con etichetta OpenGL. Mostra tutti i post
sabato 15 agosto 2015
sabato 4 aprile 2015
A small reflective box
Here we show the code to generate a reflective box that simulate mirrors, these generates infinite reflection of objects inside the box.
#version 3.7;
global_settings {
assumed_gamma 1.0
max_trace_level 25
}
#default {finish {ambient 0}}
#include "colors.inc"
#include "stones.inc"
//-------------------------------------------
#declare CamLoc = < 1.5, 3.5,-7>;
camera {
location CamLoc
up y*image_height/image_width right x
look_at < 0, 1, 0>
angle 35
}
light_source {CamLoc, color rgb 0.3}
light_source {<-50, 150,-180>, color White}
light_source {< 20, 25, 75>, color rgb 0.5}
//*******************************************
box {<-50,-1,-50>, < 50, 0, 50>
texture {
pigment {checker color rgb < 0.15, 0.1, 0.5>, color White}
}
}
#declare Bordorag = 0.05;
union {
box {<-1, 0,-1>, < 1, 2, 1>
texture {
pigment {color White filter 1}
}
interior_texture {
pigment {color rgb 0}
finish {reflection 0.85}
}
no_shadow
}
cylinder {<-1, 0,-1>, < 1, 0,-1>, Bordorag}
cylinder {< 1, 0,-1>, < 1, 0, 1>, Bordorag}
cylinder {< 1, 0, 1>, <-1, 0, 1>, Bordorag}
cylinder {<-1, 0, 1>, <-1, 0,-1>, Bordorag}
cylinder {<-1, 2,-1>, < 1, 2,-1>, Bordorag}
cylinder {< 1, 2,-1>, < 1, 2, 1>, Bordorag}
cylinder {< 1, 2, 1>, <-1, 2, 1>, Bordorag}
cylinder {<-1, 2, 1>, <-1, 2,-1>, Bordorag}
cylinder {<-1, 0,-1>, <-1, 2,-1>, Bordorag}
cylinder {< 1, 0,-1>, < 1, 2,-1>, Bordorag}
cylinder {< 1, 0, 1>, < 1, 2, 1>, Bordorag}
cylinder {<-1, 0, 1>, <-1, 2, 1>, Bordorag}
sphere {<-1, 0,-1>, Bordorag*2}
sphere {< 1, 0,-1>, Bordorag*2}
sphere {< 1, 0, 1>, Bordorag*2}
sphere {<-1, 0, 1>, Bordorag*2}
sphere {<-1, 2,-1>, Bordorag*2}
sphere {< 1, 2,-1>, Bordorag*2}
sphere {< 1, 2, 1>, Bordorag*2}
sphere {<-1, 2, 1>, Bordorag*2}
texture {
pigment {color Red}
}
translate y*Bordorag
}
sphere {< 0.3, 1.5, 0.4>, 0.35
texture {
pigment {color rgb < 0.5, 0, 0>}
finish {
reflection {0.5 metallic}
diffuse 0.4
brilliance 2
specular 1 roughness 0.01
metallic
}
}
}
sphere {<-0.5, 0.5,-0.2>, 0.1
texture {
pigment {color rgb < 1, 1, 0>}
finish {
reflection {0.5 metallic}
diffuse 0.4
brilliance 2
specular 1 roughness 0.01
metallic
}
}
}
box {<-0.3,-0.1,-0.2>, < 0.5, 0.1, 0.2>
texture { T_Grnt5
//normal { agate 0.15 scale 0.15}
finish { phong 0.5 }
scale 1
} // end of texture
translate < 0.5, 0.3,-0.5>
}
//-------------------------------------------
Here is the picture generated by the code:
#version 3.7;
global_settings {
assumed_gamma 1.0
max_trace_level 25
}
#default {finish {ambient 0}}
#include "colors.inc"
#include "stones.inc"
//-------------------------------------------
#declare CamLoc = < 1.5, 3.5,-7>;
camera {
location CamLoc
up y*image_height/image_width right x
look_at < 0, 1, 0>
angle 35
}
light_source {CamLoc, color rgb 0.3}
light_source {<-50, 150,-180>, color White}
light_source {< 20, 25, 75>, color rgb 0.5}
//*******************************************
box {<-50,-1,-50>, < 50, 0, 50>
texture {
pigment {checker color rgb < 0.15, 0.1, 0.5>, color White}
}
}
#declare Bordorag = 0.05;
union {
box {<-1, 0,-1>, < 1, 2, 1>
texture {
pigment {color White filter 1}
}
interior_texture {
pigment {color rgb 0}
finish {reflection 0.85}
}
no_shadow
}
cylinder {<-1, 0,-1>, < 1, 0,-1>, Bordorag}
cylinder {< 1, 0,-1>, < 1, 0, 1>, Bordorag}
cylinder {< 1, 0, 1>, <-1, 0, 1>, Bordorag}
cylinder {<-1, 0, 1>, <-1, 0,-1>, Bordorag}
cylinder {<-1, 2,-1>, < 1, 2,-1>, Bordorag}
cylinder {< 1, 2,-1>, < 1, 2, 1>, Bordorag}
cylinder {< 1, 2, 1>, <-1, 2, 1>, Bordorag}
cylinder {<-1, 2, 1>, <-1, 2,-1>, Bordorag}
cylinder {<-1, 0,-1>, <-1, 2,-1>, Bordorag}
cylinder {< 1, 0,-1>, < 1, 2,-1>, Bordorag}
cylinder {< 1, 0, 1>, < 1, 2, 1>, Bordorag}
cylinder {<-1, 0, 1>, <-1, 2, 1>, Bordorag}
sphere {<-1, 0,-1>, Bordorag*2}
sphere {< 1, 0,-1>, Bordorag*2}
sphere {< 1, 0, 1>, Bordorag*2}
sphere {<-1, 0, 1>, Bordorag*2}
sphere {<-1, 2,-1>, Bordorag*2}
sphere {< 1, 2,-1>, Bordorag*2}
sphere {< 1, 2, 1>, Bordorag*2}
sphere {<-1, 2, 1>, Bordorag*2}
texture {
pigment {color Red}
}
translate y*Bordorag
}
sphere {< 0.3, 1.5, 0.4>, 0.35
texture {
pigment {color rgb < 0.5, 0, 0>}
finish {
reflection {0.5 metallic}
diffuse 0.4
brilliance 2
specular 1 roughness 0.01
metallic
}
}
}
sphere {<-0.5, 0.5,-0.2>, 0.1
texture {
pigment {color rgb < 1, 1, 0>}
finish {
reflection {0.5 metallic}
diffuse 0.4
brilliance 2
specular 1 roughness 0.01
metallic
}
}
}
box {<-0.3,-0.1,-0.2>, < 0.5, 0.1, 0.2>
texture { T_Grnt5
//normal { agate 0.15 scale 0.15}
finish { phong 0.5 }
scale 1
} // end of texture
translate < 0.5, 0.3,-0.5>
}
//-------------------------------------------
Here is the picture generated by the code:
sabato 20 aprile 2013
Un sistema di coordinate in breve
Qualunque sia il sistema con il quale la finestra
viene creata, o ridimensionata, il sistema invia una notifica
all'utente. Anche se si sta usando GLUT, la notifica è automatica;
questo tipo di routine è memorizzata dalla funzione
glutReshapeFunc(). Bisogna registrare una chiamata alla
funzione che:
- Ristabilisca l'area del rettangolo ove viene calcolata l'immagine;
- Definire il sistema di coordinate dell'oggetto che deve essere disegnato.
void riforma (int l, int a)
{
glViewport (0,0, (GLsizei)
l, (Glsizei) a);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, (GLdouble)
l, 0.0, (Gldouble) a);
}
Le funzioni di GLUT ricevono internamente due
parametri, lunghezza ed altezza della finestra nuova, mossa, o
ridimensionata; glViewport() aggiusta i pixel dell'immagine
per il disegno dell'intera finestra. Nelle tre istruzioni successive,
le coordinate del disegno sono impostate sull'angolo in basso a
sinistra come (0,0) e sull'angolo in lato a destra come (l,a). Si può
fare l'esempio con un foglio di carta millimetrata. I valori l e a
definiti in riforma(), rappresentano il numero di righe e colonne
dell'immagine. Quindi si fissa un asse sul foglio millimetrato
mediante la funzione gluOrtho2D(), la quale fissa l'origine a
(0,0) come l'angolo più in basso a sinistra. Pertanto quando vengono
calcolati le linee, i punti ed i poligoni essi appariranno come
oggetti bidimensionali in posizioni prevedibili.
sabato 13 aprile 2013
Forzare il disegno
Come già
illustrato in precedenza, i sistemi grafici moderni possono essere
pensati come una catena di montaggio. L'unità centrale di processo
(CPU) invia i comandi di disegno. Tuttavia l'hardware installato deve
effettuare altre operazioni e trasformazioni geometriche. Viene
effettuato il clipping, seguita da ombreggiatura e texture. Infine i
valori sono scritti in piani di bit per lo schermo. Nelle
architetture ad alto livello queste operazioni sono effettuate da
componenti hardware diverse, le quali sono state progettate per
operazioni specifiche da completare velocemente. In questo modo la
CPU non deve attendere che ogni comando di disegno sia completato per
eseguirne un altro. Mentre la CPU si trova al vertice della catena di
montaggio, le altre componenti effettuano le operazioni successive.
Inoltre l'applicazione può essere eseguita più macchine
contemporaneamente, attraverso connessioni di rete che costituiscono
un legame client - server. Tutto questo può essere estremamente
inefficiente se la rete esegue un comando per volta, in quanto vi può
essere un notevole ritardo nella trasmissione. Solitamente il client
raccogli un insieme di comandi prima di inviare il pacchetto di dati.
Per questo motivo OpenGL fornisce il comando glFlush(),
il quale forza il client ad inviare il pacchetto di rete anche se non
fosse al completo. Dove non vi è una rete collegata tutti i comandi
sono eseguiti immediatamente sul server, e glFlush() non
ha alcun effetto. Comunque se si sta scrivendo una applicazione che
possa lavorare bene con o senza rete, è bene aggiungere il comando
glFlush() al termine
di ogni immagine o scena. Da notare che glFlush()
non attende che il fotogramma sia completo, solo forza il disegno ad
essere eseguito, quindi garantisce che tutti i precedenti comandi
esecutivi
in un tempo finito e non vi siano altri comandi eseguiti. Altre
situazioni alle quali glFlush() è utile:
- Render via software che costruisce una immagine in memoria e non vuole aggiornare lo schermo continuativamente;
- Implementare una raccolta dei comandi per ammortizzare i costi di avvio. Come citato nell'esempio della rete di macchine.
mercoledì 10 aprile 2013
Specificare un colore
Con OpenGL, la descrizione della forma di un oggetto
che deve essere disegnato è indipendente dal suo colore. Qualunque
sia la geometria dell'oggetto disegnato, userà lo schema di colore
corrente. Lo schema di colore può essere semplice come “disegna
tutto rosso scarlatto” oppure complicato come “ prendi un oggetto
fatto di plastica blu, con un riflettore giallo puntato su di esso,
in modo che vi sia una luce diffusa rossastra su tutto il resto”.
In generale, il programmatore OpenGL deve impostare il colore o lo
schema di colore per disegnare l'oggetto. Non appena lo schema di
colore viene modificato, tutti gli oggetti saranno disegnati con
quello schema di colore. Questo metodo aiuta OpenGL a raggiungere
ottime performance che non si otterrebbero se non tenesse traccia
dello schema di colore. Un esempio di pseudo-codice:
imposta_colore(rosso);
disegna_oggetto(A);
imposta_colore(verde);
disegna_oggetto(B);
disegna_oggetto(C);
Colorazione, ombreggiatura, illuminazione sono
grandi argomenti che richiedono capitoli di libri, o lunghi
paragrafi dedicati ad essi. Tuttavia, per disegnare semplici forme
primitive, necessita solo una conoscenza di base su come impostare il
colore corrente, questa informazione viene fornita nel paragrafo
seguente. Per impostare il colore si utilizza il comando glColor3f().
Richiede 3 parametri il cui valore è compreso tra 0.0 e 1.0, virgola
mobile. Questi rappresentano le componenti Rosso, Verde, Blu del
colore. Utilizzare il valore 1.0 per un solo parametro, azzerando gli
altri, crea un colore puro.
glColor3f(1.0, 0.0, 0.0);
Crea il colore rosso più luminoso del sistema di
disegno, senza componenti verdi o blu. Tutti i parametri a 0 creano
un colore nero, tutti a 1 il colore bianco. Qui vi sono gli otto
comandi del colore che possono essere impostati per esempio.
glColor3f(0.0, 0.0, 0.0);
nero
glColor3f(1.0, 0.0, 0.0);
rosso
glColor3f(0.0, 1.0, 0.0);
verde
glColor3f(1.0, 1.0, 0.0);
giallo
glColor3f(0.0, 0.0, 1.0);
blu
glColor3f(1.0, 0.0, 1.0);
magenta
glColor3f(0.0, 1.0, 1.0);
ciano
glColor3f(1.0, 1.0, 1.0);
bianco
Come si può notare, nella precedente routine era
stato spiegato come impostare il colore di pulizia dello schermo in
glClearColor() , usa quattro
parametri, i primi tre sono i parametri di glColor3f();
il quarto è il valore di alfa.
sabato 6 aprile 2013
Un kit di disegno indispensabile
Questo articolo spiega come azzerare la finestra e
prepararla per il disegno, impostare i colori dell'oggetto da
disegnare, e forza il completamento del disegno. Nessuno di questi
argomenti ha che fare con il disegno in modo diretto, ma ogni
programma che disegna oggetti geometrici deve gestire queste cose.
Azzerare la Finestra
Per disegnare sul computer, ci si comporta come se
si dovesse disegnare su un foglio bianco, e poi si traccia
l'immagine. Su di un computer, la memoria contiene l'ultima immagine
utilizzata per riempire lo schermo, pertanto bisogna azzerarla usando
un colore di sfondo prima di disegnare una nuova scena. Il colore
utilizzato dipende dall'applicazione, per un programma di scrittura
si usa un colore bianco (il colore della carta) prima di tracciare il
testo. Se si sta disegnando una immagine vista nello spazio, il
colore scelto può essere il nero, prima di disegnarne le stelle ed i
pianeti. Alcune volte non è necessario riscrivere l'intera immagine
ma solo alcune parti. A questo punto ci si può chiedere cosa voglia
dire azzerare la finestra, non si potrebbe disegnare un rettangolo
delle stesse dimensioni della stessa? Esiste una operazione più
semplice , in quanto OpenGL semplifica con un comando speciale
dedicato al solo azzeramento della finestra, inoltre su alcune
macchine, l'hardware grafico consiste di buffer multipli contenenti i
colori dei pixel che sono mostrati. Questi ed altri buffer devono
essere ripuliti di tanto in tanto, pertanto è utile possedere un
comando dedicato allo scopo.
Bisogna inoltre sapere che i colori dei pixel sono
immagazzinati nell'hardware grafico come bitplane. Vi sono due modi
per memorizzare, il primo (RGBA), rosso, verde, blu e alfa,
immagazzina i valori direttamente come bitplane. Oppure esiste un
singolo indice di valore che fa riferimento al colore di tabella. Il
colore RGBA è quello comunemente usato. Un esempio di linea di
codice nel quale la finestra viene azzerata con il nero è:
glClearColor(0.0, 0.0, 0.0,
0.0);
glClear(GL_COLOR_BUFFER_BIT);
In questo caso la chiamata a glClearColor() è la stessa di prima, il comando glClearDepth() specifica che il valore di ogni pixel dio profondità deve essere impostato, e il parametro glClear() consiste ora di OR bitwise, di tutti i buffer che devono essere puliti.
La prima linea di codice serve comunicare di
azzerare lo schermo con il nero, il comando successivo ripulisce
l'intera finestra con il colore corrente. Il singolo parametro
glClear() indica quale
buffer di memoria deve essere ripulito. In questo caso vien pulito
solo il buffer del colore, dove viene conservata l'immagine.
Tipicamente, viene impostato il colore una sola volta, all'inizio
dell'applicazione, e l'operazione di pulizia avviene spesso. OpenGL
tiene traccia del colore corrente di pulizia come variabile di stato.
Se bisogna ripulire anche il buffer della profondità dell'immagine s
i usa la sequenza di comandi:
glClearColor(0.0, 0.0, 0.0, 0.0);
glClearDepth(1.0);
glClear(GL_COLOR_BUFFER_BIT |
GL_DEPTH_BUFFER_BIT);
In questo caso la chiamata a glClearColor() è la stessa di prima, il comando glClearDepth() specifica che il valore di ogni pixel dio profondità deve essere impostato, e il parametro glClear() consiste ora di OR bitwise, di tutti i buffer che devono essere puliti.
venerdì 29 marzo 2013
Movimento = Ridisegno + Scambio
La struttura di una animazione reale, non differisce
molto da questa descrizione. Solitamente, è più facile ridisegnare
l'intero buffer dall'inizio per ogni fotogramma, piuttosto che
cercare di capire cosa deve essere ridisegnato. Ciò è verissimo per
i simulatori di volo, nel quale un cambiamento dell'orientamento del
mezzo, costringe al riposizionamento di tutto ciò che si vede fuori
dall'abitacolo. Nella maggior parte delle animazioni, gli oggetti
sono ridisegnati mediante semplici trasformazioni (un cambio del
punto di vista dell'osservatore, o un veicolo che si muove lungo la
strada, un oggetto ruotato leggermente). Se è necessario un lungo
processo di calcolo per le operazioni non grafiche, il tasso di
fotogrammi subisce un brusco calo. Da tenere in mente quindi, che il
tempo di attesa dopo la routine scambia_i_buffer() , viene
usato per questi calcoli. OpengGL non ha una routine di comando
scambia_i_buffer() in quanto
ciò è legato all'hardware disponibile ed al sistema di gestione
delle finestre nella macchina sulla quale il programma viene
eseguito.
domenica 17 marzo 2013
Il Refresh che mette in pausa
Per alcune implementazioni di OpenGL, inoltre la
routine scambia_i_buffer(), oltre a invertire il buffer di memoria in
disegno e quello visualizzato, aspetta sino a quando il periodo di
rinfresco dello schermo non è concluso, e la schermata non viene
visualizzata. Questa routine permette al nuovo buffer di memoria di
essere visualizzato completamente, partendo dall'inizio. Assumendo
una frequenza di 60 volte al secondo questo significa che il numero
di fotogrammi massimi raggiungibili è di 60 frame per second
(fps), e se tutti i frame sono azzerati in meno di un
sessantesimo di secondo, l'animazione scorre fluidamente. Quel che
può accadere solitamente è la costruzione di un fotogramma è
troppo complessa per essere disegnata in 1/60 di secondo, pertanto il
fotogramma vien mostrato più di una volta. Se il tempo necessario
per calcolare è di 1/45 di secondo, la velocità raggiungibile di 30
fps, la grafica ha un tempo di ozio pari a 1/90 di secondo. Inoltre
il tempo di rinfresco dei monitor è costante, pertanto bisogna
aspettarsi delle conseguenze sulle prestazioni dell'applicazione.
Bisogna valutare attentamente le caratteristiche dell'applicazione in
fase di sviluppo, aggiungere delle componenti può non avere alcuna
conseguenza sino ad un certo punto quando un nuovo componente del
programma costringe il sistema a rallentare da 60 fps a 30 fps.
Inoltre se la complessità della scena è prossima al valore intero
(1/60, 1/30, 1/20) può subire variazioni casuali, le quali causano
una visualizzazione irregolare, fastidiosa agli occhi di un
osservatore. In questo caso è necessario semplificare la scena, in
modo che tutti i frame siano abbastanza veloci, o rallentarli tutti
allo stesso valore. Una gestione sofisticata del frame rate si rende
necessaria in queste applicazioni.
venerdì 8 marzo 2013
Animazione con OpenGL
Una delle cose più eccitanti da fare con la grafica
al computer è disegnare immagini in movimento. Che tu sia un
ingegnere che vuole osservare un componente meccanico in tutti i
lati, o un pilota che vuole imparare a far volare un aeroplano usando
una simulazione, o semplicemente un appassionato; l'animazione è una
parte importante della computer grafica. Al cinema il movimento viene
ottenuto mediante una sequenza di immagini proiettate per un
ventiquattresimo di secondo sullo schermo. Ogni immagine viene posta
dietro l'obiettivo, il diaframma si apre e l'immagine vine mostrata;
il diaframma si richiude temporaneamente, e la pellicola viene fatta
avanzare di un fotogramma, quindi il fotogramma vien proiettato e
così via. Se si osservano 24 immagini al secondo, il cervello umano
provvede ad amalgamarle in un'unica sequenza animata. Di fatto i
proiettori moderni mostrano un numero doppio di fotogrammi (48) al
secondo per ridurre l'evanescenza. Le immagini in computer grafica
sono solitamente rinfrescate alla velocità di 60 - 76 fotogrammi al
secondo, il limite massimo è dio 120 fotogrammi al secondo. Ma per
il tempo di risposta dell'occhio umano, superare questo limite non
produce alcun effetto visibile. La ragione per cui i film funzionano
è che ogni immagine è completa quando viene proiettata.
Traducendolo in pseudo-linguaggio, si può scrivere:
apri_finestra();
per (i=0; i < 1000; i++)
{
azzera_finestra();
disegna_fotogramma();
aspetta_tempo_1_24esimo_secondo();
}
Se si aggiunge al sistema il tempo per pulire lo
schermo e disegnare un'immagine, questo programma può dare dei
risultati non graditi in quanto si avvicinano pericolosamente a 1/24
di secondo. Gli oggetti visibili per 1/24 di secondo che presentano
un'immagine solida in teoria, ma quando vengono disegnati dal
computer possono apparire come spettri, in quanto il computer non fa
in tempo ad azzerare l'immagine presente per sostituirla con
un'altra. La maggior parte delle applicazioni OpenbGL consente il
doppio buffering, via hardware o software, in modo da ridurre i tempi
morti. Così mentre un'immagine viene mostrata, la successiva viene
creata in memoria ed i due buffer sono scambiati di posto al termine
della proiezione della prima immagine. Pertanto i due buffer lavorano
in parallelo alternandosi nella proiezione, è come avere due
proiettori contemporanei che proiettano lo stesso film alternandone i
fotogrammi. Una versione modificata del programma si scrive in questo
modo:
apri_finestra_in
doppio_buffer();
per (i=0; i < 1000; i++)
{
azzera_finestra();
disegna_fotogramma();
scambia_i_buffer();
}
lunedì 4 marzo 2013
GLUT, OpenGL Utility Toolkit
Come si sa OpenGL non contiene comandi di rendering,
ma è progettato per essere indipendente dal sistema operativo e
dalla gestione delle finestre. Di conseguenza, non contien comandi
per aprire le finestre, o leggere eventi dal mouse o dalla tastiera.
Sfortunatamente, è impossibile scrivere un programma di grafica
completo senza almeno aprire una finestra, e i programmi più utili
richiedono una forma di input da parte dell'utente per operare i
comandi del sistema operativo e del sistema a finestra. In molti
casi, un programma completo crea gli esempi più interessanti, in
questo GLUT semplifica il sistema di gestione delle finestre,
dell'input e così via. Se si possiede una implementazione di GLUT e
OpenGL sul sistema, gli esempi mostrati saranno eseguiti senza
problemi. Inoltre, i comandi di disegno delle OpenGL sono limitati al
disegno di geometrie semplici quali punti, linee e poligoni; GLUT
include alcune routine che permettono di creare oggetti 3D più
complicati quali sfere, toroidi, teiere. In questo modo le immagini
mostrate dai programmi sono rese più interessanti. GLUT può essere
non molto soddisfacente come applicazione, ma può essere un buon
punto di partenza per imparare OpenGL.
Gestione della Finestra
Cinque routine che eseguono i compiti necessari a gestire la finestra.- glutInit(int *argc, char **argv) inizia GLUT e processa ogni argomento di comando (per X, possono esserci opzioni sullo schermo e la geometria). glutInit() deve essere chiamata come prima GLUT routine.
- glutInitDisplayMode(unsigned int modo) specifica se si vuole usare RGBA o modello di colore indicizzato. Si può anche specificare se si vuole finestra a singolo o doppio buffer. (Se si lavora con la mappa dei colori ne si vorrà caricare uno; usare glutSetColor() per farlo.) Infine si può usare la routine per indicare se si vuole una finestra associata ad un tipo di profondità, tratto, buffer di accumulazione. Per esempio si vuole creare una finestra con doppio buffering, e colore RGBA, bisogna chiamare: glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH).
- glutInitWindowPosition(int x, int y) specifica localizzazione nello schermo partendo dall'angolo in lato a sinistra.
- glutInitWindowSize(int larghezza int taglia) specifica larghezza e altezza della finestra.
- int glutCreateWindow(char *stringa) crea la finestra del contesto OpenGL. Restituisce un indicatore unico per la finestra. Avvertenza, sino a quando glutMainLoop() viene chiamato la finestra non è visualizzata.
Le chiamate alla Visualizzazione
glutDisplayFunc(void (*func)(void)) è la prima e la più importante funzione di chiamata alla visualizzazione. Non appena GLUT determina il contesto della finestra che deve essere visualizzata, la chiamata alla funzione registrata mediante glutDisplayFunc() viene eseguita. Pertanto le routines di cui si ha bisogno per ridisegnare la scena nello schermo attraverso il richiamo della funzione.
Se il programma cambia i contenuti della finestra, a volte bisogna richiamare glutPostRedisplay(void), il quale fornisce una scappatoia a glutMainLoop() funzione per essere richiamata mediante questa nuove opportunità.
Eseguire il programma
L'ultima funzione da richiamare è glutMainLoop(void). Tutte le finestre che sono state create vengono mostrare, e il rendering di queste è ora effettivo. Il processo degli eventi comincia ed avviata la registrazione degli eventi a schermo. Una volta entrati nell'anello, non se ne esce.
domenica 3 marzo 2013
File inclusione OpenGL
Per tutte le
applicazioni OpenGL è necessario includere il file gl.h. Quasi tutte
le applicaizoni OpenGL usano GLU la sopramenzionata OpenGL Utility
Library. Così quasi ogni file sorgente OpenGL inizia con:
#include
<gl.h>
#include<glu.h>
Se si sta accedendo
direttamente alla libreria di interfaccia della finestra per
supportare OpenGL come GLX, AGL, PGL, WGL si devono includere file
addizionali di header. Ad esempio per richiamare GLX può essere
necessario aggiungere le linee di codice:
#include
<X11/xlib.h>
#include<GL/glx.h>
Se invece si sta
utilizzando GLUT per gestire le funzioni della finestra, bisogna
includere il codice:
#include<GL/glut.h>
Non è necessario
includere tutti i file intestazione automaticamente, ma è necessario
sceglierli. GLUT include tutte le funzioni contenute in WGL per
Microsoft Windows.
domenica 24 febbraio 2013
OpenGL Librerie collegate
OpenGL fornisce un
potente set di comandi di rendering primitivo ma potente, tutti i
comandi di disegno ad alto livello devono essere tradotti in questi
comandi. Inoltre i programmi OpenGL devono sottostare al meccanismo
che regola le finestre di sistema. Un certo numero di librerie
esistono allo scopo di semplificare il compito di programmazione
incluse le seguenti:
La OpenGL Utility
Library (GLU) contiene una serie di routine a basso livello che
eseguono comandi OpenGL come l'impostazione delle matrici per
specificare l'orientamento della prospettiva e la proiezione, esegue
la tassellazione dei poligoni e la resa delle superfici. La libreria
è fornita come parte dell'implementazione OpenGL. Tutte le routine
GLU usano il prefisso glu.
Per ogni sistema
operativo a finestra esiste una libreria che estende la funzionalità
del sistema a finestra per supportare il rendering OpenGL. Per le
macchine che usano il sistema X Window esiste l'estensione OpenGL X
Window System (GLX) come aggiunta a OpenGL. Le routine GLX usano il
prefisso glX.
Per il sistema operativo Windows Microsoft, vi sono le WGL la quale
fornisce interfaccia OpenGL. Tutte le routine WGL usano il prefisso
wgl.
Open Inventor è un
programma ad oggetti basato su OpenGL, il quale fornisce oggetti e
metodi per creare applicazioni grafiche a tre dimensioni. E' stato
scritto in C++ e fornisce oggetti precostruiti ed eventi già
descritti per interagire con essi, si tratta di una applicazione ad
alto livello capace di creare ed editare scenari a tre dimensioni,
inoltre può salvare oggetti su disco e scambiare dati in vari
formati grafici. Open Inventor è separato da OpenGL.
lunedì 11 febbraio 2013
Modellare solidi con OpenGL II
Seconda parte del programma:
GLvoid UccidiFinestraGL(GLvoid) // Uccide la finestra
{
if (schermopieno)
{
ChangeDisplaySettings(NULL,0);
ShowCursor(TRUE);
}
if (hRC) // Abbiamo il contesto di rendering
{
if (!wglMakeCurrent(NULL,NULL))
{
MessageBox(NULL,"Rilascio fallito di DC e RC .","ERRORE SHUTDOWN",MB_OK | MB_ICONINFORMATION);
}
if (!wglDeleteContext(hRC))
{
MessageBox(NULL,"Rilascio fallito del contesto di rendering.","ERRORE SHUTDOWN",MB_OK | MB_ICONINFORMATION);
}
hRC=NULL; // Imposta RC a NULL
}
if (hDC && !ReleaseDC(hWnd,hDC)) // Possiamo impostare il DC
{
MessageBox(NULL,"Rilascio fallito del Dispositivo Contesto.","ERRORE SHUTDOWN",MB_OK | MB_ICONINFORMATION);
hDC=NULL; // Imposta DC a NULL
}
if (hWnd && !DestroyWindow(hWnd)) // Possiamo distruggere la finestra?
{
MessageBox(NULL,"Non riesce a rilasciare hWnd.","ERRORE SHUTDOWN",MB_OK | MB_ICONINFORMATION);
hWnd=NULL; // Set hWnd To NULL
}
if (!UnregisterClass("OpenGL",hInstance)) // Are We Able To Unregister Class
{
MessageBox(NULL,"Non riesce a cancellare la classe.","ERRORE SHUTDOWN",MB_OK | MB_ICONINFORMATION);
hInstance=NULL; // Set hInstance To NULL
}
}
BOOL CreaFinestraGL(char* titolo, int larghezza, int altezza, int bits, bool schermopienoflag)
{
GLuint PixelFormat;
WNDCLASS wc;
DWORD dwExStyle;
DWORD dwStyle;
RECT WindowRect;
WindowRect.left=(long)0;
WindowRect.right=(long)larghezza;
WindowRect.top=(long)0;
WindowRect.bottom=(long)altezza;
schermopieno=schermopienoflag;
hInstance = GetModuleHandle(NULL);
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wc.lpfnWndProc = (WNDPROC) WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = "OpenGL";
if (!RegisterClass(&wc))
{
MessageBox(NULL,"Classe Window fallito rilascio.","ERRORE",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}
if (schermopieno) // Prova schermopieno?
{
DEVMODE dmScreenSettings; // Modalità del dispositivo
memset(&dmScreenSettings,0,sizeof(dmScreenSettings));
dmScreenSettings.dmSize=sizeof(dmScreenSettings);
dmScreenSettings.dmPelsWidth = larghezza;
dmScreenSettings.dmPelsHeight = altezza;
dmScreenSettings.dmBitsPerPel = bits;
dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
// Try To Set Selected Mode And Get Results. NOTE: CDS_schermopieno Gets Rid Of Start Bar.
if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)
{
// If The Mode Fails, Offer Two Options. Quit Or Use Windowed Mode.
if (MessageBox(NULL,"La scheda video non supporta modalita' a pieno schermo. Usare modalita' finestra?","Open GL",MB_YESNO|MB_ICONEXCLAMATION)==IDYES)
{
schermopieno=FALSE; // Windowed Mode Selected. schermopieno = FALSE
}
else
{
// Pop Up A Message Box Letting User Know The Program Is Closing.
MessageBox(NULL,"Programa chiudera' ora.","ERRORE",MB_OK|MB_ICONSTOP);
return FALSE; // Return FALSE
}
}
}
if (schermopieno) // Siamo ancora a pieno schermo?
{
dwExStyle=WS_EX_APPWINDOW;
dwStyle=WS_POPUP; // Stile finestra
ShowCursor(FALSE);
}
else
{
dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; // Stile finestra estesa
dwStyle=WS_OVERLAPPEDWINDOW;
}
AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);
// Crea la finestra
if (!(hWnd=CreateWindowEx( dwExStyle,
"OpenGL",
titolo,
dwStyle |
WS_CLIPSIBLINGS |
WS_CLIPCHILDREN,
0, 0,
WindowRect.right-WindowRect.left,
WindowRect.bottom-WindowRect.top,
NULL,
NULL, // No Menu
hInstance, // Instanza
NULL))) //
{
UccidiFinestraGL(); // Resetta lo schermo
MessageBox(NULL,"Errore creazione finestra.","ERRORE",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Ritorna FALSE
}
static PIXELFORMATDESCRIPTOR pfd= {
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW |
PFD_SUPPORT_OPENGL |
PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,
bits,
0, 0, 0, 0, 0, 0,
0,
0,
0,
0, 0, 0, 0,
16,
0,
0,
PFD_MAIN_PLANE,
0,0, 0, 0
};
if (!(hDC=GetDC(hWnd))) // Abbiamo contesto del dispositivo?
{
UccidiFinestraGL();
MessageBox(NULL,"Non crea un dispositivo di Contento GL.","ERRORE",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}
if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd)))
{
UccidiFinestraGL();
MessageBox(NULL,"Non trova un Formato Pixel.","ERRORE",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}
if(!SetPixelFormat(hDC,PixelFormat,&pfd)) // Possiamo impostare il formato pixel?
{
UccidiFinestraGL();
MessageBox(NULL,"Non riesce ad impostare un Formato Pixel.","ERRORE",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}
if (!(hRC=wglCreateContext(hDC)))
{
UccidiFinestraGL();
MessageBox(NULL,"Non riesce a creare un Contesto GL.","ERRORE",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}
if(!wglMakeCurrent(hDC,hRC))
{
UccidiFinestraGL();
MessageBox(NULL,"Non attiva un Contesto di rendering GL.","ERRORE",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}
ShowWindow(hWnd,SW_SHOW);
SetForegroundWindow(hWnd);
SetFocus(hWnd);
RidimensioneScenaGL(larghezza, altezza);
if (!InizGL())
{
UccidiFinestraGL();
MessageBox(NULL,"Inizializzazione fallita.","ERRORE",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Restituisci FALSO
}
return TRUE; // Successo
}
LRESULT CALLBACK WndProc( HWND hWnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
switch (uMsg) // Controlla i messaggi
{
case WM_ACTIVATE:
{
if (!HIWORD(wParam))
{
attivo=TRUE; // Programma attivo
}
else
{
attivo=FALSE; // Program non più attivo
}
return 0;
}
case WM_SYSCOMMAND: // Intercetta Comandi di sistema
{
switch (wParam)
{
case SC_SCREENSAVE:
case SC_MONITORPOWER:
return 0;
}
break; // Uscita
}
case WM_CLOSE:
{
PostQuitMessage(0);
return 0;
}
case WM_KEYDOWN:
{
tasti[wParam] = TRUE;
return 0;
}
case WM_KEYUP:
{
tasti[wParam] = FALSE;
return 0;
}
case WM_SIZE: // Ridimensiona finestra OpenGL
{
RidimensioneScenaGL(LOWORD(lParam),HIWORD(lParam));
return 0;
}
}
// Passa i messaggi non gestiti DefWindowProc
return DefWindowProc(hWnd,uMsg,wParam,lParam);
}
int WINAPI WinMain( HINSTANCE hInstance, // Instance
HINSTANCE hPrevInstance, // Previous Instance
LPSTR lpCmdLine, // Command Line Parameters
int nCmdShow) // Window Show State
{
MSG msg; // Windows Message Structure
BOOL fatto=FALSE; // Bool Variable To Exit Loop
// Chiede all'utente quale modlità schermo preferisce
if (MessageBox(NULL,"Vuoi eseguire modalita' a pieno schermo?", "Pieno Schermo?",MB_YESNO|MB_ICONQUESTION)==IDNO)
{
schermopieno=FALSE; // Modalità finestra
}
// Crea la finestra OpenGL
if (!CreaFinestraGL("Tutorial Oggetti Solidi",800,600,16,schermopieno))
{
return 0; // Quit se la finestra non viene creata
}
while(!fatto) // Loop del programma
{
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
if (msg.message==WM_QUIT)
{
fatto=TRUE;
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
else // Se non ci sono messaggi
{
// Disegna la scena. E controlla ESC e DisegnaScenaGL()
if ((attivo && !DisegnaScenaGL()) || tasti[VK_ESCAPE])
{
fatto=TRUE; // ESC o DisegnaScenaGL Segnala Quit
}
else
{
SwapBuffers(hDC); // Swap Buffers (Doppio buffer)
}
if (tasti[VK_F1])
{
tasti[VK_F1]=FALSE;
UccidiFinestraGL();
schermopieno=!schermopieno; // Toggle schermopieno / modalità finestra
// Ricrea la finestra OpenGL
if (!CreaFinestraGL("Tutorial oggetti solidi",800,600,32,schermopieno))
{
return 0; // Esce dal progrmma se la finestra non viene creata
}
}
}
}
// Spegnimento
UccidiFinestraGL(); // Cancella la finstra
return (msg.wParam); // Esce dal programma
}
GLvoid UccidiFinestraGL(GLvoid) // Uccide la finestra
{
if (schermopieno)
{
ChangeDisplaySettings(NULL,0);
ShowCursor(TRUE);
}
if (hRC) // Abbiamo il contesto di rendering
{
if (!wglMakeCurrent(NULL,NULL))
{
MessageBox(NULL,"Rilascio fallito di DC e RC .","ERRORE SHUTDOWN",MB_OK | MB_ICONINFORMATION);
}
if (!wglDeleteContext(hRC))
{
MessageBox(NULL,"Rilascio fallito del contesto di rendering.","ERRORE SHUTDOWN",MB_OK | MB_ICONINFORMATION);
}
hRC=NULL; // Imposta RC a NULL
}
if (hDC && !ReleaseDC(hWnd,hDC)) // Possiamo impostare il DC
{
MessageBox(NULL,"Rilascio fallito del Dispositivo Contesto.","ERRORE SHUTDOWN",MB_OK | MB_ICONINFORMATION);
hDC=NULL; // Imposta DC a NULL
}
if (hWnd && !DestroyWindow(hWnd)) // Possiamo distruggere la finestra?
{
MessageBox(NULL,"Non riesce a rilasciare hWnd.","ERRORE SHUTDOWN",MB_OK | MB_ICONINFORMATION);
hWnd=NULL; // Set hWnd To NULL
}
if (!UnregisterClass("OpenGL",hInstance)) // Are We Able To Unregister Class
{
MessageBox(NULL,"Non riesce a cancellare la classe.","ERRORE SHUTDOWN",MB_OK | MB_ICONINFORMATION);
hInstance=NULL; // Set hInstance To NULL
}
}
BOOL CreaFinestraGL(char* titolo, int larghezza, int altezza, int bits, bool schermopienoflag)
{
GLuint PixelFormat;
WNDCLASS wc;
DWORD dwExStyle;
DWORD dwStyle;
RECT WindowRect;
WindowRect.left=(long)0;
WindowRect.right=(long)larghezza;
WindowRect.top=(long)0;
WindowRect.bottom=(long)altezza;
schermopieno=schermopienoflag;
hInstance = GetModuleHandle(NULL);
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wc.lpfnWndProc = (WNDPROC) WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = "OpenGL";
if (!RegisterClass(&wc))
{
MessageBox(NULL,"Classe Window fallito rilascio.","ERRORE",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}
if (schermopieno) // Prova schermopieno?
{
DEVMODE dmScreenSettings; // Modalità del dispositivo
memset(&dmScreenSettings,0,sizeof(dmScreenSettings));
dmScreenSettings.dmSize=sizeof(dmScreenSettings);
dmScreenSettings.dmPelsWidth = larghezza;
dmScreenSettings.dmPelsHeight = altezza;
dmScreenSettings.dmBitsPerPel = bits;
dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
// Try To Set Selected Mode And Get Results. NOTE: CDS_schermopieno Gets Rid Of Start Bar.
if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)
{
// If The Mode Fails, Offer Two Options. Quit Or Use Windowed Mode.
if (MessageBox(NULL,"La scheda video non supporta modalita' a pieno schermo. Usare modalita' finestra?","Open GL",MB_YESNO|MB_ICONEXCLAMATION)==IDYES)
{
schermopieno=FALSE; // Windowed Mode Selected. schermopieno = FALSE
}
else
{
// Pop Up A Message Box Letting User Know The Program Is Closing.
MessageBox(NULL,"Programa chiudera' ora.","ERRORE",MB_OK|MB_ICONSTOP);
return FALSE; // Return FALSE
}
}
}
if (schermopieno) // Siamo ancora a pieno schermo?
{
dwExStyle=WS_EX_APPWINDOW;
dwStyle=WS_POPUP; // Stile finestra
ShowCursor(FALSE);
}
else
{
dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; // Stile finestra estesa
dwStyle=WS_OVERLAPPEDWINDOW;
}
AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);
// Crea la finestra
if (!(hWnd=CreateWindowEx( dwExStyle,
"OpenGL",
titolo,
dwStyle |
WS_CLIPSIBLINGS |
WS_CLIPCHILDREN,
0, 0,
WindowRect.right-WindowRect.left,
WindowRect.bottom-WindowRect.top,
NULL,
NULL, // No Menu
hInstance, // Instanza
NULL))) //
{
UccidiFinestraGL(); // Resetta lo schermo
MessageBox(NULL,"Errore creazione finestra.","ERRORE",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Ritorna FALSE
}
static PIXELFORMATDESCRIPTOR pfd= {
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW |
PFD_SUPPORT_OPENGL |
PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,
bits,
0, 0, 0, 0, 0, 0,
0,
0,
0,
0, 0, 0, 0,
16,
0,
0,
PFD_MAIN_PLANE,
0,0, 0, 0
};
if (!(hDC=GetDC(hWnd))) // Abbiamo contesto del dispositivo?
{
UccidiFinestraGL();
MessageBox(NULL,"Non crea un dispositivo di Contento GL.","ERRORE",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}
if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd)))
{
UccidiFinestraGL();
MessageBox(NULL,"Non trova un Formato Pixel.","ERRORE",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}
if(!SetPixelFormat(hDC,PixelFormat,&pfd)) // Possiamo impostare il formato pixel?
{
UccidiFinestraGL();
MessageBox(NULL,"Non riesce ad impostare un Formato Pixel.","ERRORE",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}
if (!(hRC=wglCreateContext(hDC)))
{
UccidiFinestraGL();
MessageBox(NULL,"Non riesce a creare un Contesto GL.","ERRORE",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}
if(!wglMakeCurrent(hDC,hRC))
{
UccidiFinestraGL();
MessageBox(NULL,"Non attiva un Contesto di rendering GL.","ERRORE",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}
ShowWindow(hWnd,SW_SHOW);
SetForegroundWindow(hWnd);
SetFocus(hWnd);
RidimensioneScenaGL(larghezza, altezza);
if (!InizGL())
{
UccidiFinestraGL();
MessageBox(NULL,"Inizializzazione fallita.","ERRORE",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Restituisci FALSO
}
return TRUE; // Successo
}
LRESULT CALLBACK WndProc( HWND hWnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
switch (uMsg) // Controlla i messaggi
{
case WM_ACTIVATE:
{
if (!HIWORD(wParam))
{
attivo=TRUE; // Programma attivo
}
else
{
attivo=FALSE; // Program non più attivo
}
return 0;
}
case WM_SYSCOMMAND: // Intercetta Comandi di sistema
{
switch (wParam)
{
case SC_SCREENSAVE:
case SC_MONITORPOWER:
return 0;
}
break; // Uscita
}
case WM_CLOSE:
{
PostQuitMessage(0);
return 0;
}
case WM_KEYDOWN:
{
tasti[wParam] = TRUE;
return 0;
}
case WM_KEYUP:
{
tasti[wParam] = FALSE;
return 0;
}
case WM_SIZE: // Ridimensiona finestra OpenGL
{
RidimensioneScenaGL(LOWORD(lParam),HIWORD(lParam));
return 0;
}
}
// Passa i messaggi non gestiti DefWindowProc
return DefWindowProc(hWnd,uMsg,wParam,lParam);
}
int WINAPI WinMain( HINSTANCE hInstance, // Instance
HINSTANCE hPrevInstance, // Previous Instance
LPSTR lpCmdLine, // Command Line Parameters
int nCmdShow) // Window Show State
{
MSG msg; // Windows Message Structure
BOOL fatto=FALSE; // Bool Variable To Exit Loop
// Chiede all'utente quale modlità schermo preferisce
if (MessageBox(NULL,"Vuoi eseguire modalita' a pieno schermo?", "Pieno Schermo?",MB_YESNO|MB_ICONQUESTION)==IDNO)
{
schermopieno=FALSE; // Modalità finestra
}
// Crea la finestra OpenGL
if (!CreaFinestraGL("Tutorial Oggetti Solidi",800,600,16,schermopieno))
{
return 0; // Quit se la finestra non viene creata
}
while(!fatto) // Loop del programma
{
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
if (msg.message==WM_QUIT)
{
fatto=TRUE;
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
else // Se non ci sono messaggi
{
// Disegna la scena. E controlla ESC e DisegnaScenaGL()
if ((attivo && !DisegnaScenaGL()) || tasti[VK_ESCAPE])
{
fatto=TRUE; // ESC o DisegnaScenaGL Segnala Quit
}
else
{
SwapBuffers(hDC); // Swap Buffers (Doppio buffer)
}
if (tasti[VK_F1])
{
tasti[VK_F1]=FALSE;
UccidiFinestraGL();
schermopieno=!schermopieno; // Toggle schermopieno / modalità finestra
// Ricrea la finestra OpenGL
if (!CreaFinestraGL("Tutorial oggetti solidi",800,600,32,schermopieno))
{
return 0; // Esce dal progrmma se la finestra non viene creata
}
}
}
}
// Spegnimento
UccidiFinestraGL(); // Cancella la finstra
return (msg.wParam); // Esce dal programma
}
domenica 10 febbraio 2013
Modellare solidi con OpenGL I
Il seguente programma consente di modellare solidi utilizzando le OpenGL, e ruotarne la posizione nello spazio. Utilizzando la libreria GLEXT e GLU.
#include <windows.h> // File intestazione necessario
#include <gl\gl.h>
#include <gl\glu.h>
#include <gl\glext.h>
HDC hDC=NULL; // GDI privato
HGLRC hRC=NULL; // Contesto di rendering
HWND hWnd=NULL; // Gestisce la finestra
HINSTANCE hInstance; // Gestisce istanza
bool tasti[256]; // Vettore per le routine tastiera
bool attivo=TRUE; // Flag per la finestra attiva
bool schermopieno=TRUE; // Flag per lo schermopieno
GLfloat rtri; // Angolo per i triangoli
GLfloat rquad; // Angolo per i quadrati
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // Dichiarazione di WndProc
GLvoid RidimensioneScenaGL(GLsizei larghezza, GLsizei altezza) // Ridimensiona ed inizializza GL Window
{
if (altezza==0) // Previene divisione per 0
{
altezza=1;
}
glViewport(0,0,larghezza,altezza); // Reset dello schermo corrente
glMatrixMode(GL_PROJECTION); // Seleziona la matrice di proiezione
glLoadIdentity(); // Azzera la finestra Matrice
// Calcola l'aspetto della finstra e le sue dimensioni
gluPerspective(100.0f,(GLfloat)larghezza/(GLfloat)altezza,0.1f,100.0f);
glMatrixMode(GL_MODELVIEW); // Seleziona la matrice del Modelview
glLoadIdentity();
}
int InizGL(GLvoid) // Impostazioni per OpenGL
{
glShadeModel(GL_SMOOTH); // Abilita ombreggiatura
glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // Schermo a sfondo nero
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
return TRUE; // Inizializzazione OK
}
int DisegnaScenaGL(GLvoid) // Qui vi sono le istruzioni di disegno
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(-1.5f,0.0f,-6.0f);
glRotatef(rtri,0.0f,1.0f,0.0f);
glBegin(GL_TRIANGLES);
glColor3f(1.0f,0.0f,0.0f);
glVertex3f( 0.0f, 1.0f, 0.0f);
glColor3f(0.0f,1.0f,0.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glColor3f(0.0f,0.0f,1.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glColor3f(1.0f,0.0f,0.0f);
glVertex3f( 0.0f, 1.0f, 0.0f);
glColor3f(0.0f,0.0f,1.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glColor3f(0.0f,1.0f,0.0f);
glVertex3f( 1.0f,-1.0f, -1.0f);
glColor3f(1.0f,0.0f,0.0f);
glVertex3f( 0.0f, 1.0f, 0.0f);
glColor3f(0.0f,1.0f,0.0f);
glVertex3f( 1.0f,-1.0f, -1.0f);
glColor3f(0.0f,0.0f,1.0f);
glVertex3f(-1.0f,-1.0f, -1.0f);
glColor3f(1.0f,0.0f,0.0f);
glVertex3f( 0.0f, 1.0f, 0.0f);
glColor3f(0.0f,0.0f,1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glColor3f(0.0f,1.0f,0.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glEnd(); // Disegno della Piramide
glLoadIdentity();
glTranslatef(1.5f,0.0f,-6.0f);
glRotatef(rquad,1.0f,1.0f,1.0f);
glBegin(GL_QUADS);
glColor3f(0.0f,1.0f,0.0f);
glVertex3f( 1.0f, 1.0f,-1.0f);
glVertex3f(-1.0f, 1.0f,-1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
glColor3f(1.0f,0.5f,0.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glVertex3f( 1.0f,-1.0f,-1.0f);
glColor3f(1.0f,0.0f,0.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glColor3f(1.0f,1.0f,0.0f);
glVertex3f( 1.0f,-1.0f,-1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glVertex3f(-1.0f, 1.0f,-1.0f);
glVertex3f( 1.0f, 1.0f,-1.0f);
glColor3f(0.0f,0.0f,1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f,-1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glColor3f(1.0f,0.0f,1.0f);
glVertex3f( 1.0f, 1.0f,-1.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glVertex3f( 1.0f,-1.0f,-1.0f); // Disegno del cubo
glEnd();
glLoadIdentity();
glTranslatef(5.5f,0.0f,-8.0f);
glRotatef(rquad*2,1.0f,0.0f,0.0f);
glBegin(GL_QUADS);
glColor3f(0.0f,1.0f,0.0f);
glVertex3f( 1.0f, 2.0f,-1.0f);
glVertex3f(-1.0f, 2.0f,-1.0f);
glVertex3f(-1.0f, 2.0f, 1.0f);
glVertex3f( 1.0f, 2.0f, 1.0f);
glColor3f(1.0f,0.5f,0.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glVertex3f( 1.0f,-1.0f,-1.0f);
glColor3f(1.0f,0.0f,0.0f);
glVertex3f( 1.0f, 2.0f, 1.0f);
glVertex3f(-1.0f, 2.0f, 1.0f );
glVertex3f(-1.0f,-1.0f, 1.0f );
glVertex3f( 1.0f,-1.0f, 1.0f );
glColor3f(1.0f,1.0f,0.0f);
glVertex3f( 1.0f,-1.0f,-1.0f );
glVertex3f(-1.0f,-1.0f,-1.0f);
glVertex3f(-1.0f, 2.0f,-1.0f);
glVertex3f( 1.0f, 2.0f,-1.0f);
glColor3f(0.0f,0.0f,1.0f);
glVertex3f(-1.0f, 2.0f, 1.0f);
glVertex3f(-1.0f, 2.0f,-1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glColor3f(1.0f,0.0f,1.0f);
glVertex3f( 1.0f, 2.0f,-1.0f);
glVertex3f( 1.0f, 2.0f, 1.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glVertex3f( 1.0f,-1.0f,-1.0f); // Disegno della scatola
glEnd();
rtri+=0.2f; // Aumenta la rotazione per il triangolo
rquad-=0.15f; // Diminuisce la rotazione per il quadrato
return TRUE; // Continua...
}
#include <windows.h> // File intestazione necessario
#include <gl\gl.h>
#include <gl\glu.h>
#include <gl\glext.h>
HDC hDC=NULL; // GDI privato
HGLRC hRC=NULL; // Contesto di rendering
HWND hWnd=NULL; // Gestisce la finestra
HINSTANCE hInstance; // Gestisce istanza
bool tasti[256]; // Vettore per le routine tastiera
bool attivo=TRUE; // Flag per la finestra attiva
bool schermopieno=TRUE; // Flag per lo schermopieno
GLfloat rtri; // Angolo per i triangoli
GLfloat rquad; // Angolo per i quadrati
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // Dichiarazione di WndProc
GLvoid RidimensioneScenaGL(GLsizei larghezza, GLsizei altezza) // Ridimensiona ed inizializza GL Window
{
if (altezza==0) // Previene divisione per 0
{
altezza=1;
}
glViewport(0,0,larghezza,altezza); // Reset dello schermo corrente
glMatrixMode(GL_PROJECTION); // Seleziona la matrice di proiezione
glLoadIdentity(); // Azzera la finestra Matrice
// Calcola l'aspetto della finstra e le sue dimensioni
gluPerspective(100.0f,(GLfloat)larghezza/(GLfloat)altezza,0.1f,100.0f);
glMatrixMode(GL_MODELVIEW); // Seleziona la matrice del Modelview
glLoadIdentity();
}
int InizGL(GLvoid) // Impostazioni per OpenGL
{
glShadeModel(GL_SMOOTH); // Abilita ombreggiatura
glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // Schermo a sfondo nero
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
return TRUE; // Inizializzazione OK
}
int DisegnaScenaGL(GLvoid) // Qui vi sono le istruzioni di disegno
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(-1.5f,0.0f,-6.0f);
glRotatef(rtri,0.0f,1.0f,0.0f);
glBegin(GL_TRIANGLES);
glColor3f(1.0f,0.0f,0.0f);
glVertex3f( 0.0f, 1.0f, 0.0f);
glColor3f(0.0f,1.0f,0.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glColor3f(0.0f,0.0f,1.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glColor3f(1.0f,0.0f,0.0f);
glVertex3f( 0.0f, 1.0f, 0.0f);
glColor3f(0.0f,0.0f,1.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glColor3f(0.0f,1.0f,0.0f);
glVertex3f( 1.0f,-1.0f, -1.0f);
glColor3f(1.0f,0.0f,0.0f);
glVertex3f( 0.0f, 1.0f, 0.0f);
glColor3f(0.0f,1.0f,0.0f);
glVertex3f( 1.0f,-1.0f, -1.0f);
glColor3f(0.0f,0.0f,1.0f);
glVertex3f(-1.0f,-1.0f, -1.0f);
glColor3f(1.0f,0.0f,0.0f);
glVertex3f( 0.0f, 1.0f, 0.0f);
glColor3f(0.0f,0.0f,1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glColor3f(0.0f,1.0f,0.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glEnd(); // Disegno della Piramide
glLoadIdentity();
glTranslatef(1.5f,0.0f,-6.0f);
glRotatef(rquad,1.0f,1.0f,1.0f);
glBegin(GL_QUADS);
glColor3f(0.0f,1.0f,0.0f);
glVertex3f( 1.0f, 1.0f,-1.0f);
glVertex3f(-1.0f, 1.0f,-1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
glColor3f(1.0f,0.5f,0.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glVertex3f( 1.0f,-1.0f,-1.0f);
glColor3f(1.0f,0.0f,0.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glColor3f(1.0f,1.0f,0.0f);
glVertex3f( 1.0f,-1.0f,-1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glVertex3f(-1.0f, 1.0f,-1.0f);
glVertex3f( 1.0f, 1.0f,-1.0f);
glColor3f(0.0f,0.0f,1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f,-1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glColor3f(1.0f,0.0f,1.0f);
glVertex3f( 1.0f, 1.0f,-1.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glVertex3f( 1.0f,-1.0f,-1.0f); // Disegno del cubo
glEnd();
glLoadIdentity();
glTranslatef(5.5f,0.0f,-8.0f);
glRotatef(rquad*2,1.0f,0.0f,0.0f);
glBegin(GL_QUADS);
glColor3f(0.0f,1.0f,0.0f);
glVertex3f( 1.0f, 2.0f,-1.0f);
glVertex3f(-1.0f, 2.0f,-1.0f);
glVertex3f(-1.0f, 2.0f, 1.0f);
glVertex3f( 1.0f, 2.0f, 1.0f);
glColor3f(1.0f,0.5f,0.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glVertex3f( 1.0f,-1.0f,-1.0f);
glColor3f(1.0f,0.0f,0.0f);
glVertex3f( 1.0f, 2.0f, 1.0f);
glVertex3f(-1.0f, 2.0f, 1.0f );
glVertex3f(-1.0f,-1.0f, 1.0f );
glVertex3f( 1.0f,-1.0f, 1.0f );
glColor3f(1.0f,1.0f,0.0f);
glVertex3f( 1.0f,-1.0f,-1.0f );
glVertex3f(-1.0f,-1.0f,-1.0f);
glVertex3f(-1.0f, 2.0f,-1.0f);
glVertex3f( 1.0f, 2.0f,-1.0f);
glColor3f(0.0f,0.0f,1.0f);
glVertex3f(-1.0f, 2.0f, 1.0f);
glVertex3f(-1.0f, 2.0f,-1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glColor3f(1.0f,0.0f,1.0f);
glVertex3f( 1.0f, 2.0f,-1.0f);
glVertex3f( 1.0f, 2.0f, 1.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glVertex3f( 1.0f,-1.0f,-1.0f); // Disegno della scatola
glEnd();
rtri+=0.2f; // Aumenta la rotazione per il triangolo
rquad-=0.15f; // Diminuisce la rotazione per il quadrato
return TRUE; // Continua...
}
Iscriviti a:
Post (Atom)
