Visualizzazione post con etichetta OpenGL. Mostra tutti i post
Visualizzazione post con etichetta OpenGL. Mostra tutti i post

sabato 15 agosto 2015

Still learning

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.

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:

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.
Un esempio di chiamata alla funzione di dimensionamento:

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);
 
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
}

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...
}