Sei sulla pagina 1di 11

#include<stdlib.

h>
#include<stdio.h>
#include <GL/glut.h>
#include <GL/glu.h>
#include <GL/gl.h>
#include <unistd.h>
#include<string.h>
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Ricordarsi che l'ultima istruzione che scrivo la prima ad essere esegui
ta!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
glMatrixMode(parametro) specifica a quale matrice applicare le successive istruz
ioni.
Accetta 4 parametri:
GL_MODELVIEW : matrice che definisce in quale modo gli oggetti vengono trasforma
ti (traslazioni,rotazioni,scaleF)
GL_PROJECTION : matrice che definisce in che modo l'utente vede la scena (proiez
ione prospettica ecc)
GL_TEXTURE
GL_COLOR
--------------------------------------------------------------------------------
------------------------------------------
All'inizio di ogni funzione che disegna qualcosa faccio:
PusMatrix();
gltraslatef(0,0,-8);
PusMatrix();
ecc;
-In questo modo impostando correttamente la funzione di reshape vedo la figura d
a lontano
Se invece faccio direttamente:
gltraslatef(0,0,-8);
PusMatrix();
ecc;
-Ogni volta che chiamo la funzione che disegna, la scena viene disegnata sempre
pi lontana ma dato che la "telecamera" della reshapefunc rimane fissa io non vedo
piu niente
In alternativa il gltraslate() lo posso mettere alla fine della reshapefunc() e
cosi nella funzione di disegno posso iniziare direttamente a fare pushmatrix() e
disegnare la scena
--------------------------------------------------------------------------------
--------------------------------------------

glTranslatef(0,0,-3.6f);
glRotatef(xrot, 1.0f, 0.0f, 0.0f);
glTranslatef(0,0,-5.0f);
In questo caso la rotazione viene fatta rispetto a glTranslatef(0,0,-3.6f) con r
aggio di curvatura = 5.
--------------------------------------------------------------------------------
---------------------------------------
glTranslatef(0,0,-3.6f);
glRotatef(xrot, 1.0f, 0.0f, 0.0f);

In questo caso la rotazione viene fatta su se stesso
--------------------------------------------------------------------------------
---------------------------------------
|\\ ROTAZIONI //|
Ruotare prima intorno all'asse y e poi intorno all'asse z E'DIVERSO da ruotar
e prima intorno all'asse z e poi y.
ES1:
glRotatef(20.0f, 0.0f, 0.0f, 1.0f);
glRotatef(fElect1, 0.0f, 1.0f, 0.0f);
glTranslatef(-70.0f, 0.0f, 0.0f);
In questo caso,dopo la traslazione, l'atomo viene prima ruotato intorno all'asse
y con raggio di rotazione 70 ( usando sempre come origine il traslatef fatto al
l'inizio della funzione), e poi viene ruotato di 45 gradi rispetto a z.
Il rsultato un orbita inclinata di 45 gradi.
ES2:
glRotatef(fElect1, 0.0f, 1.0f, 0.0f);
glRotatef(20.0f, 0.0f, 0.0f, 1.0f);
glTranslatef(-70.0f, 0.0f, 0.0f);
In questo caso,dopo la traslazione, l'atomo viene prima ruotato intorno all'asse
z di 45 gradi, e poi viene ruotato intorno all'asse y ( e ripeto, l'asse y!) co
n raggio di rotazione 70 pixel
Il rsultato un orbita orizzontale leggermente abbassata rispetto all'origine.
E' possibile otenere un risultato molto simile all'ES2 in questo modo:
glRotatef(fElect1, 0.0f, 1.0f, 0.0f);
glTranslatef(0.0f, -20.0f, 0.0f);
glTranslatef(-70.0f, 0.0f, 0.0f);
--------------------------------------------------------------------------------
---------------------------------------
TIMER
Prototipo funzione:
void TimerFunc(int value)
{
glutPostRedisplay();
glutTimerFunc(100, TimerFunc, 1); //100 millisecondi
}
Poi nel main mibasta agggere il comando:
glutTimerFunc(250, TimerFunc, 1);
-In questo modo ottengo un effetto animazione aggiornato ogni 100ms.
- 1 un valore generico che passo alla funzione. Si puo usare stessa funzione per
piu cose diverse con quel valore.
--------------------------------------------------------------------------------
---------------------------------------
Il numero di Push e di pop deve essere uguale SEMPRE!
--------------------------------------------------------------------------------
-------------------------------
Devo assumere che ogni figura abbia un proprio asse che chiamer asse di rotazione
. Ad esempio l'asse di rotazione di un cubo passa per il suo centro e cosi via.
Il CHEAT estremo che l'asse di rotazione non si sposta insieme alla figura quand
o faccio traslatef() MA RIMANE NELLA POSIZIONE IN CUI LA FIGURA E' STATA INIZIAL
MENTE DISEGNATA.
[quelle sopra sono per la maggior parte cazzate. Le rotazioni vengono sempre fat
te attorno ad un vettore che parte dall'origine ( l'origine che ho con loadIdent
ity(); non quello che ho con translatef(); )
e con direzione dato dal rotatef(). ES: rotatef(roty,0,1,0). la figura viene r
uotata rispetto ad un vettore che parte in (0,0,0) e va a finire in (0,1,0).]
Facciamo qualche esempio: [ supponiamo di essere in (0,0,0) all'inizio ]
A) Io ho un cubo e lo voglio far ruotare su se stesso a una distanza d dal centr
o.
Mi basta scrivere:
glTranslatef( d , 0.0f, 0.0f); // Sposto il cubo
glRotatef(gradi,0,1,0); // Il cubo viene ruotato rispetto al suo
asse ( che si trova al centro del cubo dato che il cubo non stato rimosso). Qui
ndi il cubo ruota su se stesso.
glutWireCube (1.0); // Sono in (0,0,0) e quindi il cubo viene
creato li
B) Voglio che il cubo ruoti di una orbita circolare con raggio r

glRotatef(gradi,0,1,0); //L'asse di rotazione e con lui tutta l
a scene: il cubo si muove di orbita circolare
glTranslatef( r , 0.0f, 0.0f); // Il cubo viene spostato ma il suo asse
di rotazione rimane in (0,0,0)
glutWireCube (1.0); // Sono in (0,0,0) e quindi il cubo vien
e creato li
C) Facciamo ora l'esempio del dito che ruota intorno al polso
Il polso un cubo di lato 1 scalato di glScalef (2.0, 0.4, 4.0);
L'asse di rotazione al centro, e, sulle ascisse c' 1 di distanza dai bordi
Il codice del dito :
glTranslatef (1, 0.0, -1.5); // Ora mi devo immaginare che mentre il
dito sta ruotando, lo sposto sul bordo del polso che dista 1 dall'asse
glRotatef(dito1z, 0, 0.0, 1.0); // ....quando faccio la rotazione come s
e il dito ruotase rispetto all'origine ( e nn su se stesso) ==> {IMMAGINARSI LA
FIGURA xk l'ho spiegato da cani}
glTranslatef (1.5, 0.0, 0.0); // Prima sposto il dito di 1,5. In quest
o modo l'asse di rotazione tocca il bordo sinistro. In questo modo....
glScalef (3.0, 0.4, 0.5); // Lo allungo (maggiormente sull'asse x).
Asse al centro, 1,5 dai bordi
glutWireCube (1.0); // Disegno cubo
--------------------------------------------------------------------------------
--------------------------------------------
Picking parte 1 (un oggetto selezionato alla volta )
-Con loadName(); sovrascivo l'ultimo elemento inserito nello stack dei nomi
http://content.gpwiki.org/index.php/OpenGL:Tutorials:Picking
void ProcessSelection(int xPos, int yPos) // questa funzione viene chiamata quan
do premuto il pulsante sx del mouse. E' una funzione di picking
{
GLuint buff[64] = {0}; oppure static GLuint selectBuff[BUFFER_LENGTH];
GLint hits, viewport[4];
// NOTA: il buff[64] molto importante xk ogni volta che viene generata un hi
t, le sue informazione vengono salvate nel buffer.
// Ogni hit occupa 4+ caselle: 1)Numero di oggetti presenti sul name st
ack; 2)Minima profondit 3)Max prof 4)nome dell'oggetto selezionato( loadN
ame(); ) 5)Nome 2o oggetto selez. 6)ecc
// NoTA2: il primo nome che appare nell'hit record [ al punto 4] il primo a
d essere stato inserito nel name stack
glSelectBuffer(64, buff); //dice al compilatore qual' il buffer di selezione
glGetIntegerv(GL_VIEWPORT, viewport); // mi salvo le informazioni sulla viewpor
t ( dimenzione finestra [x,y,width,height])
glRenderMode(GL_SELECT); // mi metto in modalit selezione e la sua grandezza
glInitNames(); //inizializzo lo stack dei nomi degli oggetti
glPushName(0); // scrivo un valore a caso nello stack dei nomi ( altrimenti poi
glLoadName non funziona)
glMatrixMode(GL_PROJECTION); // mi sposto in modalit proiezione
glPushMatrix(); // mi salvo le informazioni relative alla proiezio
ne prospettica corrente ( dato che tra poco dovro modificarla)
glLoadIdentity(); // mi preparo a modificare la proiezione prospetti
ca in modo che solo l'area intorno al mouse appaia sulla scena
//Le prossime due funzioni vengono usate per restringere l'area
gluPickMatrix(xPos, viewport[3] - yPos, 2,2, viewport); // Crea una nuova matric
e di proiezione. xpos,ypos sono il centro della regione di picking. width e heig
ht dicono quanto grande la regione di
//picking. viewport specifica la grandezza della finestra corrente
.
gluPerspective(45.0f, (float)viewport[2] / (float)viewport[3], 1.0, 425.0); // L
a matrice di proiezione corrente viene moltiplicata per la pickmatrix

// NOTA1: i valori che passo alla funzione sopra devono essere gli stessi c
he uso nella ReshapeFunc();
// NOTA2: in pickmatrix (2,2) sono i pixel della nuova viewing volume. Prov
o a modifcare quel valore e vedo cosa succede ( anche se clicco fuori dal pianet
a mi dice che ci sono dentro).
glMatrixMode(GL_MODELVIEW); // mi sposto in modalit modelview e disegno la scena
RenderScene();
glMatrixMode(GL_PROJECTION); // torno in modalit proiezioni e ripristino il viewi
ng volume iniziale
glPopMatrix(); // NOTA: devo aspettare di disegnare la scena prima di ripristin
are la proiezione originale. Se faccio popMatrix() prima di entrare in modelview
e aver disegnato non va + nulla
hits = glRenderMode(GL_RENDER);
// Questa funzione fa tante cose:
// 1) Esce dalla modalit GL_SELECT ed entra in GL_RENDER ( la modalit di default
[quella che sempre selezionata anche se non chiamo mai glrendermode ??] usata p
er disegnare qualcosa sul framebuffer
// 2) Salva in hits QUANTI hits sono stati generati metro ero in GL_SELECT mod
e
// Imagine that when you are in GL_SELECT mode, everytime you draw something t
hat is visible, a counter is incremented. Then, when you call glRenderMode(GL_RE
NDER) to actually draw something on the
// framebuffer, the counter is returned to you. This counter is the number of
objects drawn when in GL_SELECT mode. If you restrict the drawing area to half s
creen, the counter is incremented only for the // object in the visible area.
I think you got the trick :) If you restrict the area to a single pixel, which
is where the mouse is, glRenderMode will return a counter that is the number of
objects under // the mouse. In this way you can determine which objects are
under the mouse.
// Quando solo in select mode e disegno la segna, il contatore delle HIT aumen
ta solo per gli oggetti visibili. Cosi si spiega xk le hit siano 1 anche se facci
o 5 loadName();
if(hits == 1) // ora processo le hit
ProcessPlanet(buff[3]); //invio alla funzione il nome dell'ogge
tto selezionato
else
glutSetWindowTitle("Nothing was clicked on!");
glMatrixMode(GL_MODELVIEW); // infine mi rimetto in modalit modelview
}
--------------------------------------------------------------------------------
---------------------------------------------------------

Picking (Esempio 2)
http://www.lighthouse3d.com/opengl/picking/index.php3?openglway
Prima qualche definizione:
-Name stack: Opengl permette di assegnare nomi (che in realt sono numeri) agli og
getti disegnati. I nomi vengono salvati dentro lo stack dei nomi ( con loadname(
) o pushname() ).
-Hit record: ogni volta che un oggetto disegnato interseca il viewing volume, vi
ene generata un hit record. Ogni hit record contiene i nomi presenti nello stack
dei nomi + altro (vedi sorpa)
Ogni hit record viene salvato nel buffer di selezione ogni volta che il il name
stack viene modificato o quando esco dalla modalit di selezione.
Esempio 2: come possibile che quando clikko su una luna di marte, il pc sappia c
he quella luna appartiene a marte ?????
Supponiamo di clikkare sulla luna1 ( quindi il viewing volume ristretto alla lun
a 1)
// Draw Mars
glColor3f(1.0f, 0.0f, 0.0f);
glPushMatrix();
glTranslatef(100.0f, 0.0f, 0.0f);
glLoadName(MARS); // inserisco nello st
ack dei nomi "MARS"
glutSolidSphere(20.0,40,40);
// Draw Moon1
glTranslatef(-40.0f, 40.0f, 0.0f);
glColor3f(0.85f, 0.85f, 0.85f);
glPushName(MOON1); //inserisco nello stac
k dei nomi "MOON1"
glutSolidSphere(5.0,40,40); //creo un oggetto che
si interseca col viewing volume -----> creo un hit
glPopName(); //modifico lo stack de
i nomi ----> le informazioni sull'hit vengono salvate nel buffer di selezione
A questo punto il buffer di selezione contiene:
-Casella 0: numero di oggetti sullo stack dei nomi ( 2 in questo caso)
- 1: min prof
- 2: max prof
- 3: MARS (NB: non c' scritto "MARS" ma un numero) #define MARS
2
- 4: MOON1
--------------------------------------------------------------------------------
---------------------------------------------------------------
LUCI
-Luce ambientale: luce che arriva da ogni direzione
-Luce diffusa: luce che arriva da una direzione ben precisa
-Per abilitare le luci faccio ( nel setupRC ):
glLightfv(GL_LIGHT0,GL_AMBIENT,ambientLight);
glLightfv(GL_LIGHT0,GL_DIFFUSE,diffuseLight);
dove ambientlight e diffuselight sono del tipo GLfloat diffuseLight[] = { 0.7
f, 0.7f, 0.7f, 1.0f };
-Poi devo fare:
glEnable(GL_LIGHT0);
Cosi abilito la luce 0
-Infine per posizionare la luce faccio ( nella funzione di reshape):
glLightfv(GL_LIGHT0,GL_POSITION,lightPos);
l'ultima cifra di lightpos 1 (altrimenti non va bene)
--------------------------------------------------------------------------------
-----------------------------------------------------------------------
LUCI ( Normali )
-Se si vogliono utilizzare sorgenti di luce, necessario indicare con quale angol
o la luceincide sulla superficie illuminata, cio bisogna specificare le normali p
er ogni vertice del poligono.
Un vettore v=(x,y,z) un segmento che parte dall'origine e arriva fino al punto (
x,y,z).
Bisogna calcolare le normali. Una normale un vettore uscente dalla superficie (
cio perpendicolare alla superfiecie stessa).
Calcolare la normale di un quadrato o un cerchio semplice, ma per un poligono co
mplesso non lo .
Dato che la maggior parte dei poligoni complessi fatta di triangoli, ora vi spie
gher come si calcola la normale di un triangolo messo in qualsiasi posizione.
-NORMALE TRIANGOLO: ogni triangolo definito da 3 vertici: p1,p2,p3.
1)Definiamo come vertice di riferimento ( "l'origine" dei vettori ) uno dei 3 v
ertici. Ad esempio p1
2)Definiamo 2 vettori:v1 e v2. Questi vettori partono da p1 e vanno a finire in
: v1=(p2-p1) e v2=(p3-p1)
NOTA: facendo quella differenza come se stessimo spostando l'origine(0,0,0) i
n p1. E' la stessa cosa che si fa in analisi2 in alcuni esercizi della prima par
te.
3)Dato che la normale perpendicolare al triangolo ( e anche a v1 e v2), calcoli
amo il prodotto VETTORIALE n=(v1 X v2) .
4)Il vettore n la normale che stavamo cercando ma non ancora NORMALIZZATA (cio i
l suo modulo !=1 ).
5)Per normalizzare sufficiente calcolare il modulo di n e divedere ogni sua com
ponente per esseo.
N=(x,y
,z) Nnorm =(x/|N|,y/|N|,z/|N|)
- ATTENZIONE: Le normali non vengono influenzate da translatef e da rotatef MA
vengono INFLUENZATE DA scaleF()
--------------------------------------------------------------------------------
---------------------------------

LUCI (cose capite veramente)
Il coloro di un oggetto dipende dalla luce che esso riflette.
Un oggetto ci appare rosso non xk rosso ma xk assorbe tutte le componenti della lu
ce tranne quella rossa.
In opengl per impostare le propriet di riflessioni dei materiali si fa in questo
modo:
-glEnable(GL_COLOR_MATERIAL); [Nella funzione di i
nizializzazione]
-glColorMaterial(GL_FRONT, GL_AMBIENT); [All'inizio della fu
nzione di rendering] [solo la superficie esterna rifletter la luce]
-glColor3f(0.0f, 1.0f, 1.0f); [prima di disegnare
qualcosa] [il materiale assorba la luce rossa & riflette tutta la luce blue
verde]
-DisegnaQualcosa();

In questo modo abbiamo impostato che l'oggetto da noi disegnato rifletta la comp
onente BLU&VERDE(0,1,1) della luce ambientale (GL_AMBIENT).
Ora vediamo come impostare le luci:
-glEnable(GL_LIGHTING); [Nella funzione
di inizializzazione]
1)LUCE AMBIENTALE (cio che illumina tutto):

-GLfloat ambientColor[] = {1.0f, 0.0f, 1.0f, 1.0f}; [Array. (1.0.1
)=Rosso&Blu Alpha=1 <-- sempre cos]
-glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientColor); [All'inizio del
la funzione di rendering] [imposto luce ambientale di colore rosso&blu]
Dato che tutta la componente rossa viene assorbita, il nostro oggetto ci apparir
blu anche se la luce ha una componente rossa.
2)LUCE DIFFUSA (tipo torcia messa vicino all'oggetto)
-glEnable(GL_LIGHT1); [Nella funzion
e di inizializzazione] [abilita una delle 8 luci disponibili (0-7)]
-glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); [se metto solo
GL_AMBIENT la luce viene riflessa in modo sbagliato]
-GLfloat Diffuse1[] = {0.0f, 1.0f, 0.0f, 1.0f} ; [luce di color
e verde]
-GLfloat lightPos1[] = {0.0f, 0.0f, 2.5f, 0.0f}; [voglio posizi
onare la torcia in (0,0,2.5). Illumina verso l'origine]
-glLightfv(GL_LIGHT1, GL_DIFFUSE, Diffuse1);
-glLightfv(GL_LIGHT1, GL_POSITION, lightPos1);
-Prima l'oggetto era solo blu.Ora che colpito anche da luce verde diventer blu+ve
rde = azzurro.
3.1)LUCE SPECULARE (non troppo giusto)
Un esempio di riflesso speculare un panorama che viene riflesso nell'acqua. [ne
ll'acqua vediamo il panorama ma leggermente pi blu]
Quello che la luce speculare ci fa vedere un riflesso della fonte luminosa sopra
l'oggetto.
Quindi,se la fonte luminosa verde e l'oggetto rosso,quello che vedremo sar un ogg
etto di colore rosso+(1/2 verde) = arancione [1/2 un nu
mero a caso, non realmente la met]
-glEnable(GL_LIGHT0); [Nella funzio
ne di inizializzazione] [abilita una delle 8 luci disponibili (0-7)]
- NON devo mettere glCOLor material
-GLfloat Specular0[] = {0.0f, 1.0f, 0.0f, 1.0f}; [luce di colo
re verde]
-GLfloat lightPos0[] = {0.0f, 0.0f, -2.5f, 0.0f}; [voglio posiz
ionare la torcia in (0,0,2.5). Illumina verso l'origine]
-glLightfv(GL_LIGHT0, GL_SPECULAR, Specular0);
-glLightfv(GL_LIGHT0, GL_POSITION, lightPos0);
3.2)LUCE SPECULARE (pi giusto)
-glEnable(GL_LIGHT0); [Nella funzio
ne di inizializzazione] [abilita una delle 8 luci disponibili (0-7)]
-GLfloat specref[] = { 0.6f, 0.6f, 0.6f, 1.0f }; [all'inizio d
ella funzione di rendering]
-glMaterialfv(GL_FRONT, GL_SPECULAR,specref); [all'inizio d
ella funzione di rendering]
-glMateriali(GL_FRONT, GL_SHININESS,30); [all'inizio d
ella funzione di rendering]
-GLfloat Specular0[] = {0.0f, 1.0f, 0.0f, 1.0f} [luce di colo
re verde]
-GLfloat lightPos0[] = {0.0f, 0.0f, -2.5f, 0.0f}; [voglio posiz
ionare la torcia in (0,0,2.5). Illumina verso l'origine]
-glLightfv(GL_LIGHT0, GL_SPECULAR, Specular0);
-glLightfv(GL_LIGHT0, GL_POSITION, lightPos0);
Per impostare le luci correttamente necessario impostare le NORMALI di ogni figu
ra.
-ES: faccia frontale di un quadrato. Luce ambientale + luce diffusa in (0,0,2.5)
.
glNormal3f(0.0f, 0.0f, 1.0f);
glVertex3f(-1.5f, -1.0f, 1.5f);
glVertex3f(1.5f, -1.0f, 1.5f);
glVertex3f(1.5f, 1.0f, 1.5f);
glVertex3f(-1.5f, 1.0f, 1.5f);
La normale uscente dalla faccia e forma un angolo di 180 con la luce diffusa. E'
come se mi stessero puntando una torcia in faccia ---> tutta la mia faccia viene
illuminata
[miei occhi = normale]
-Se mettessi:
glNormal3f(0.0f, 0.0f, -1.0f);
E' come se mi girassi e mi puntassero una torcia alle spalle ----> la mia faccia
non viene illuminata angolo = 0
-Con le funzione che disegnano solidi ( glutSolidCube ecc ) non necessario speci
ficare le normali.
--------------------------------------------------------------------------------
-------------
DISABILITARE LUCI
Ci sono 2 modi:
1) glDisable(GL_LIGHTING);
In questo modo tutte le luci vengono spente ( anche light0,1,2) ma la figura rim
ane visibile.
2) glDisable(GL_LIGHT1);
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientLight_off);
In questo modo disabilito le luci0,1,2,3 e sovrascrivo a quella ambientale un va
lore nullo (ambient_off vale (0,0,0,0) ).
Il risultato che vedo solo lo schermo nero.
--------------------------------------------------------------------------------
---------------
-posiziona luci
-rotate
=
Luci fisse e figura che si muove
-rotate
-posiziona luci
=
Luci ruotano insieme a figura
--------------------------------------------------------------------------------
-------------------------
I poligoni complessi disegnali sempre con l'asse che passa per il centro altrime
nti la prendi nel culo.
--------------------------------------------------------------------------------
--------------------------
Come tutti sappiamo opengl un programma di merda e quindi:
A) Se Scrivo:

glBegin(GL_TRiangle_FAN);
gltranslatef(0,10,0);
glvertex(0,0,0);
ecc;
glEnd();
Il translatef NON viene eseguito.
B) Se Scrivo:

gltranslatef(0,10,0);
glBegin(GL_TRiangle_FAN);
glvertex(0,0,0);
ecc;
glEnd();
Il translatef VIENE eseguito.
--------------------------------------------------------------------------------
-----------------------------------
COME DISEGNARE PAVIMENTO
glDisable(GL_LIGHTING); //pavimento
glColor3f(0.5,0.5,0.5);
glRotatef (-90.0, 1.0, 0.0, 0.0); // lo ruota di 90. In questo modo
ho un rettangolo(pavimento) parallelo all'asse y (y=0)
glRectf(-70,-70,70,70); //crea rettangolo con vertici (-
70;-70)e(70;70)
glEnable(GL_LIGHTING);
Le luci vengono disabilitate/abilitate per evitare che sul pavimento ci siano ri
flessi della luce.
--------------------------------------------------------------------------------
--------------------------------------

Potrebbero piacerti anche