OpenGL è un potente strumento di programmazione 3D utilizzato per disegnare scene tridimensionali complesse da semplici primitive. Questo articolo ti insegnerà come disegnare un semplice cubo che puoi ruotare per visualizzare in tre dimensioni!
Per questo progetto avrai bisogno di un editor di codice e una certa conoscenza della programmazione C.
Passi
Parte 1 di 3: configurazione iniziale
Passaggio 1. Installa OpenGL Per iniziare, segui questi passaggi per installare OpenGL sul tuo sistema
Se hai già OpenGL, oltre a un compilatore C compatibile installato, puoi saltare questo passaggio e passare al successivo.
Passaggio 2. Creare il documento
Crea un nuovo file nel tuo editor di codice preferito e salvalo come mycube.c
Passaggio 3. Aggiungi #include
Queste sono le inclusioni di base di cui avrai bisogno per il tuo programma. È importante rendersi conto che in realtà sono necessarie diverse inclusioni per i diversi sistemi operativi. Assicurati di includere tutti questi elementi per assicurarti che il tuo programma sia versatile e possa essere eseguito per qualsiasi utente.
// Include #include #include #include #define GL_GLEXT_PROTOTYPES #ifdef _APPLE_ #include #else #include #endif
Passaggio 4. Aggiungi prototipi di funzioni e variabili globali
Il prossimo passo è dichiarare alcuni prototipi di funzioni.
// Prototipi di funzioni void display(); void specialKeys(); // Variabili globali double rotate_y=0; doppia rotazione_x=0;
Passaggio 5. Imposta la funzione main()
int main(int argc, char* argv){ // Inizializza GLUT ed elabora i parametri utente glutInit(&argc, argv); // Richiedi finestra True Color con doppio buffer con Z-buffer glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
Passaggio 6. Creare la finestra
Il prossimo passo è creare la finestra all'interno del quale disegnerai il cubo. In questo tutorial, la finestra si chiama "Awesome Cube".
// Crea finestra glutCreateWindow("Awesome Cube");
Passaggio 7. Abilita il test di profondità
OpenGL è un linguaggio rigoroso in quanto non presuppone che siano abilitate funzionalità speciali. Affinché il tuo programma venga visualizzato correttamente in 3 dimensioni utilizzando lo Z-buffer che hai visto in precedenza, devi abilitare il test di profondità. Mentre continui a esplorare OpenGL, scoprirai molte funzionalità che dovrai abilitare tra cui illuminazione, trame, abbattimento e molto altro.
// Abilita il test di profondità del buffer Z glEnable(GL_DEPTH_TEST);
Passaggio 8. Aggiungi funzioni di callback
Ecco le funzioni di callback per le quali hai scritto i prototipi in precedenza. Queste funzioni verranno chiamate ogni volta attraverso il ciclo principale. La funzione di visualizzazione ridisegna la scena in base a eventuali modifiche alle variabili apportate dalla chiamata precedente. La funzione specialKeys ci permette di interagire con il programma.
// Funzioni di callback glutDisplayFunc(display); glutSpecialFunc(specialKeys);
Passaggio 9. Avviare MainLoop
Questo richiamerà la funzione principale fino alla chiusura del programma per consentire le animazioni e l'interazione dell'utente.
// Passa il controllo a GLUT per gli eventi glutMainLoop(); // Ritorna al sistema operativo return 0; }
Parte 2 di 3: la funzione display()
Passaggio 1. Comprendere lo scopo di questa funzione
Tutto il lavoro per disegnare il tuo cubo sarà svolto in questa funzione. L'idea generale alla base del tuo cubo è disegnare tutti e sei i lati individualmente e posizionarli nella posizione appropriata.
Concettualmente, ogni lato verrà disegnato definendo i quattro angoli e lasciando che OpenGL colleghi le linee e le riempia con un colore che definisci. Di seguito sono riportati i passaggi per eseguire questa operazione
Passaggio 2. Aggiungi glClear()
Il primo passo che devi compiere in questa funzione è quello di cancella il colore e il buffer Z. Senza questi passaggi, i vecchi disegni potrebbero essere ancora visibili sotto i nuovi disegni e gli oggetti disegnati non sarebbero nella posizione corretta sullo schermo.
void display(){ // Cancella schermo e Z-buffer glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
Passaggio 3. Aggiungi glBegin() e glEnd()
OpenGL definisce gli oggetti come combinazioni di diversi poligoni. Usando il glInizio() comando, metti effettivamente giù una matita che disegnerà una forma. Per sollevare la matita e iniziare una nuova forma, devi usare il glEnd() comando. In questo tutorial utilizzerai GL_POLYGON per disegnare ciascun lato del cubo, ma è possibile utilizzare altre opzioni di parametri come GL_LINE, GL_QUAD o GL_TRIANGLE per creare altre forme.
- Qui inizierai con la parte anteriore del tuo cubo. Successivamente aggiungerai colore a tutti e 6 i lati.
// Lato multicolore - FRONT glBegin(GL_POLYGON); // Vertici verranno aggiunti nel passaggio successivo glEnd();
Passaggio 4. Aggiungi glVertex3f()
Una volta che hai dichiarato che vuoi iniziare il tuo poligono, devi definire i vertici dell'oggetto. glVertex ha più forme a seconda di cosa vuoi fare con il tuo oggetto.
- Il primo è in quante dimensioni stai lavorando. Il 3 sopra in glVertex3f dice che stai disegnando in 3 dimensioni. E' possibile lavorare anche in 2 o 4 dimensioni. La f sopra in glVertex3f dice che stai lavorando con numeri in virgola mobile. Puoi anche usare shorts, interi o doppi.
- Si noti che questi punti sono definiti in a Antiorario maniera. Questo non è molto importante al momento, ma quando inizi a lavorare con l'illuminazione, le trame e il rivestimento, questo diventerà incredibilmente importante, quindi prendi l'abitudine di definire i tuoi punti in senso antiorario ora.
- Aggiungi aggiungi i vertici tra le linee glBegin() e glEnd().
// Lato multicolore - FRONT glBegin(GL_POLYGON); glVertex3f(-0,5, -0,5, -0,5); // P1 glVertex3f(-0,5, 0,5, -0,5); // P2 glVertex3f(0,5, 0,5, -0,5); // P3 glVertex3f(0,5, -0,5, -0,5); // P4 glEnd();
Passaggio 5. Aggiungi glColor3f()
glColor funziona in modo simile a glVertex. È possibile definire punti come short, interi, doppi o float. Ogni colore ha un valore da 0 a 1. Tutti gli 0 rendono il punto nero e tutti gli 1 rendono il punto bianco. Il 3 in glColor3f() si riferisce al sistema di colori RGB senza canale alfa. L'alfa di un colore ne definisce la trasparenza. Per cambiare il livello alfa, usa glColor4f() con l'ultimo parametro che è un valore da 0 a 1 per da opaco a trasparente.
- Quando chiami glColor3f() ogni vertice disegnato da quel punto in poi sarà di quel colore. Pertanto, se vuoi che tutti e quattro i vertici siano rossi, imposta il colore una volta in qualsiasi momento prima dei comandi glVertex3f() e tutti i vertici saranno rossi.
- Il Front side definito di seguito mostra come definire un nuovo colore per ogni vertice. Quando lo fai, puoi vedere un'interessante proprietà dei colori OpenGL. Poiché ogni vertice del poligono ha il suo colore, OpenGL fonderà automaticamente i colori! Il passaggio successivo mostrerà come assegnare quattro vertici con lo stesso colore.
//Lato multicolore - FRONT glBegin(GL_POLYGON); glColor3f(1.0, 0.0, 0.0); glVertex3f(0,5, -0,5, -0,5); // P1 è rosso glColor3f(0.0, 1.0, 0.0); glVertex3f(0,5, 0,5, -0,5); // P2 è verde glColor3f(0.0, 0.0, 1.0); glVertex3f(-0,5, 0,5, -0,5); // P3 è blu glColor3f(1.0, 0.0, 1.0); glVertex3f(-0,5, -0,5, -0,5); // P4 è viola glEnd();
Passaggio 6. Gestire gli altri lati
Calcola quale sarà la posizione di ciascun vertice per gli altri cinque lati del cubo ma, per semplicità, questi sono stati calcolati per te e sono inclusi nel funzione display() finale sotto.
// Lato bianco - BACK glBegin(GL_POLYGON); glColor3f(1.0, 1.0, 1.0); glVertex3f(0,5, -0,5, 0,5); glVertex3f(0,5, 0,5, 0,5); glVertex3f(-0,5, 0,5, 0,5); glVertex3f(-0,5, -0,5, 0,5); gEnd(); // Lato viola - RIGHT glBegin(GL_POLYGON); glColor3f(1.0, 0.0, 1.0); glVertex3f(0,5, -0,5, -0,5); glVertex3f(0,5, 0,5, -0,5); glVertex3f(0,5, 0,5, 0,5); glVertex3f(0,5, -0,5, 0,5); gEnd(); // Lato verde - LEFT glBegin(GL_POLYGON); glColor3f(0.0, 1.0, 0.0); glVertex3f(-0,5, -0,5, 0,5); glVertex3f(-0,5, 0,5, 0,5); glVertex3f(-0,5, 0,5, -0,5); glVertex3f(-0,5, -0,5, -0,5); gEnd(); // Lato blu - TOP glBegin(GL_POLYGON); glColor3f(0.0, 0.0, 1.0); glVertex3f(0,5, 0,5, 0,5); glVertex3f(0,5, 0,5, -0,5); glVertex3f(-0,5, 0,5, -0,5); glVertex3f(-0,5, 0,5, 0,5); gEnd(); // Lato rosso - BOTTOM glBegin(GL_POLYGON); glColor3f(1.0, 0.0, 0.0); glVertex3f(0,5, -0,5, -0,5); glVertex3f(0,5, -0,5, 0,5); glVertex3f(-0,5, -0,5, 0,5); glVertex3f(-0,5, -0,5, -0,5); gEnd(); glFlush(); glutSwapBuffers(); }
Vogliamo anche aggiungere due ultime righe di codice per questa funzione. Questi sono glFlush();
e glutSwapBuffers();
che ci danno l'effetto di doppio buffer di cui hai appreso in precedenza.
Parte 3 di 3: Interattività con l'utente
Passaggio 1. Aggiungi specialKeys()
Hai quasi finito, ma al momento puoi disegnare un cubo ma non hai modo di ruotarlo. Per fare questo, lo farai creare una chiave speciale() funzione per permetterci di premere i tasti freccia e ruotare il cubo!
- Questa funzione è il motivo per cui hai dichiarato le variabili globali rotazioni_x e rotazioni_y. Quando si premono i tasti freccia destra e sinistra, rotate_y verrà incrementato o decrementato di 5 gradi. Allo stesso modo, quando si premono i tasti freccia su e giù, ruotare_x cambierà di conseguenza.
void specialKeys(int key, int x, int y) { // Freccia destra - aumenta la rotazione di 5 gradi if (key == GLUT_KEY_RIGHT) rotate_y += 5; // Freccia sinistra - riduce la rotazione di 5 gradi altrimenti if (key == GLUT_KEY_LEFT) rotate_y -= 5; else if (chiave == GLUT_KEY_UP) rotate_x += 5; else if (tasto == GLUT_KEY_DOWN) rotate_x -= 5; // Richiedi aggiornamento display glutPostRedisplay(); }
Passaggio 2. Aggiungi glRotate()
La tua ultima affermazione è aggiungere l'affermazione che ruoterà il tuo oggetto. Torna alla funzione display() e prima del lato FRONT, aggiungi queste righe:
// Reimposta le trasformazioni glLoadIdentity(); // Ruota quando l'utente cambia rota_x e rota_y glRotatef(ruota_x, 1.0, 0.0, 0.0); glRotatef(ruotare_y, 0.0, 1.0, 0.0); // Lato multicolore - FRONTE ….
Passaggio 3. Aggiungere i seguenti comandi per ridimensionare il cubo di 2 lungo l'asse x, 2 lungo l'asse y, ruotare il cubo di 180 gradi attorno all'asse y e traslare il cubo di 0,1 lungo l'asse x
Assicurati di disporre questi e i precedenti comandi glRotate() nell'ordine corretto come descritto sopra. (Se non sei sicuro, questo viene fatto nel codice finale alla fine del tutorial.)
// Altre trasformazioni glTranslatef(0.1, 0.0, 0.0); glRotatef(180, 0.0, 1.0, 0.0); glScalef(2.0, 2.0, 0.0);
Passaggio 4. Compila ed esegui il tuo codice
Supponendo che tu stia usando gcc come compilatore, esegui questi comandi dal tuo terminale per compilare e testare il tuo programma.
Su Linux: gcc cube.c -o cube -lglut -lGL./ mycube Su Mac: gcc -o foo foo.c -framework GLUT -framework OpenGL./ mycube Su Windows: gcc -Wall -ofoo foo.c -lglut32cu - lglu32 -lopengl32./ mycube
Passaggio 5. Controlla il tuo codice completo
Dovrebbe essere così:
// // File: mycube.c // Autore: Matt Daisley // Creato: 25/4/2012 // Progetto: Codice sorgente per Crea un cubo in OpenGL // Descrizione: Crea una finestra OpenGL e disegna un cubo 3D / / Che l'utente può ruotare utilizzando i tasti freccia // // Controlli: Freccia sinistra - Ruota a sinistra // Freccia a destra - Ruota a destra // Freccia su - Ruota su // Freccia giù - Ruota giù // ------ --------------------------------------------------- -- // Include // ----------------------------- --------------- #include #include #include #define GL_GLEXT_PROTOTYPES #ifdef _APPLE_ #include #else #include #endif // ------------- ------------------------------- // Prototipi di funzioni / / ------------------------------------------------- --------- display vuoto(); void specialKeys(); // ------------------------------------------------ ---------- // Variabili globali // -------------------- ------------------------ doppia rotazione_y=0; doppia rotazione_x=0; // ------------------------------------------------ ---------- // display() Funzione di callback // ------------------------------- ------------- void display(){ // Cancella schermo e Z-buffer glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); // Reimposta le trasformazioni glLoadIdentity(); // Altre trasformazioni // glTranslatef(0.1, 0.0, 0.0); // Non incluso // glRotatef(180, 0.0, 1.0, 0.0); // Non incluso // Ruota quando l'utente cambia rotante_x e rotante_y glRotatef(ruotare_x, 1.0, 0.0, 0.0); glRotatef(ruotare_y, 0.0, 1.0, 0.0); // Altre trasformazioni // glScalef(2.0, 2.0, 0.0); // Non incluso //Lato multicolore - FRONT glBegin(GL_POLYGON); glColor3f(1.0, 0.0, 0.0); glVertex3f(0,5, -0,5, -0,5); // P1 è rosso glColor3f(0.0, 1.0, 0.0); glVertex3f(0,5, 0,5, -0,5); // P2 è verde glColor3f(0.0, 0.0, 1.0); glVertex3f(-0,5, 0,5, -0,5); // P3 è blu glColor3f(1.0, 0.0, 1.0); glVertex3f(-0,5, -0,5, -0,5); // P4 è viola glEnd(); // Lato bianco - BACK glBegin(GL_POLYGON); glColor3f(1.0, 1.0, 1.0); glVertex3f(0,5, -0,5, 0,5); glVertex3f(0,5, 0,5, 0,5); glVertex3f(-0,5, 0,5, 0,5); glVertex3f(-0,5, -0,5, 0,5); gEnd(); // Lato viola - RIGHT glBegin(GL_POLYGON); glColor3f(1.0, 0.0, 1.0); glVertex3f(0,5, -0,5, -0,5); glVertex3f(0,5, 0,5, -0,5); glVertex3f(0,5, 0,5, 0,5); glVertex3f(0,5, -0,5, 0,5); gEnd(); // Lato verde - LEFT glBegin(GL_POLYGON); glColor3f(0.0, 1.0, 0.0); glVertex3f(-0,5, -0,5, 0,5); glVertex3f(-0,5, 0,5, 0,5); glVertex3f(-0,5, 0,5, -0,5); glVertex3f(-0,5, -0,5, -0,5); gEnd(); // Lato blu - TOP glBegin(GL_POLYGON); glColor3f(0.0, 0.0, 1.0); glVertex3f(0,5, 0,5, 0,5); glVertex3f(0,5, 0,5, -0,5); glVertex3f(-0,5, 0,5, -0,5); glVertex3f(-0,5, 0,5, 0,5); gEnd(); // Lato rosso - BOTTOM glBegin(GL_POLYGON); glColor3f(1.0, 0.0, 0.0); glVertex3f(0,5, -0,5, -0,5); glVertex3f(0,5, -0,5, 0,5); glVertex3f(-0,5, -0,5, 0,5); glVertex3f(-0,5, -0,5, -0,5); gEnd(); glFlush(); glutSwapBuffers(); } // --------------------------------- ----------- // Funzione di callback specialKeys() // ------------------------------ -------------- void specialKeys(int key, int x, int y) { // Freccia destra - aumenta la rotazione di 5 grado if (chiave == GLUT_KEY_RIGHT) ruotare_y += 5; // Freccia sinistra - riduce la rotazione di 5 gradi altrimenti if (key == GLUT_KEY_LEFT) rotate_y -= 5; else if (tasto == GLUT_KEY_UP) rotate_x += 5; else if (tasto == GLUT_KEY_DOWN) rotate_x -= 5; // Richiedi aggiornamento display glutPostRedisplay(); } // --------------------------------- ----------- // funzione principale // ------------------------------- ------------- int main(int argc, char* argv){ // Inizializza GLUT ed elabora i parametri utente glutInit(&argc, argv); // Richiedi finestra True Color con doppio buffer con Z-buffer glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); // Crea finestra glutCreateWindow("Awesome Cube"); // Abilita il test di profondità del buffer Z glEnable(GL_DEPTH_TEST); // Funzioni di callback glutDisplayFunc(display); glutSpecialFunc(specialKeys); // Passa il controllo a GLUT per gli eventi glutMainLoop(); // Ritorna al sistema operativo return 0; }