Informàtica gràfica 2. Modelatge geomètric

El primer pas per a obtindre el modelatge d’un objecte consisteix en definir objectes de revolució.

Un objecte de revolució el definim amb un perfil i l’eix sobre el que gira el perfil. En el nostre cas, l’eix de revolució serà sempre l’eix ‘Y’ i el perfil el definirem com una funció que ens tornarà el valor de ‘X’ per als valors de ‘Y’ entre l’interval [-0.5, 0.5].

Gràficament la idea seria la següent:

rev1

Per exemple, per a modelar un cilindre la funció que haurem d’utilitzar serà la de la recta, i obtindriem un objecte de revolució com aquest:

cilindre

Per a obtindre l’anterior objecte de revolució hem utilitzat el següent codi:

Els objectes es dibuixen com un conjunt d’anells, i el radi de cada anell depèn de l’altura a la que es dibuixe. Depenent de la funció particular que ens torne el valor del radi com a funció de l’altura obtindrem unes figures o unes altres.

D’aquesta manera, anem a analitzar una mica de codi, que és el que realment ens interessa. El que anem a analitzar es troba en el fitxer modelado.c.

En primer lloc, el codi que dibuixa la figura de revolució és el següent:

/*--------------------------------------------------------------------------
 Algorisme de dibuix per a la figura de revolució
 H: altura de la figura
 N: nombre d'anells i divisions en cada anell
  --------------------------------------------------------------------------*/
void formaAlambre(float H, int N, float(*f)(float y)) {
	int i;
	float y, r;

	for(i = 0; i < N; i++) { // per a cada nivell d'altura
		y = i*H/N-(H/2);
		r = f(y);            // obtenim el radi
		anillo(r, y, N);     // i dibuixem un anell
	}
}

Per a canviar l'altura o el nombre d'anells només haurem de canviar els valors de H i N respectivament.

El codi que ens definix el perfil, és a dir, la figura de revolució que anem a obtindre, és el següent:

float fCilindro(float y) {
	return(0.5); // funció lineal
}

Per a obtindre un con només haurem de canviar aquest codi pel següent:

float fCon(float y) {
	return ((y+0.5f)/2); //funció del con
}

con

O una esfera:

float fEsfera(float y) {
	return((float)sqrt(fabs(0.25-(y*y)))); // funció de l'esfera
}

Buy Viagra Professional Online Pharmacy No Prescription Needed href="http://cdecdf.com/blog/wp-content/grafica/2/esfera.png" target="_blank">esfera

Podem provar diferents codis per a obtindre diferents figures geomètriques, com per exemple:

float f1(float y) {
	return((float)sqrt(fabs((((0.4-sqrt(fabs((0.04)-(0.25))))*(0.4-sqrt(fabs((0.04)-(0.25)))))-(y*y)))));
}

f1

float f2(float y) {
	return((float)sqrt(((0.015-(0.25-(sqrt(fabs(0.25+(y*y)))))*(0.25-(sqrt(fabs(0.25+(y*y))))))*(0.015-(0.25-(sqrt(fabs(0.25+(y*y)))))*(0.25-(sqrt(fabs(0.25+(y*y)))))))));
}

f2

float f3(float y) {
	return((float)sqrt(fabs(((0.5)*(0.5))-((y-0.4)*(y-0.4)))));
}

f3

És senzill veure que les tres figures anteriors tenen diferent nombre d'anells que les primeres; simplement modificant el nombre d'anells (valor de N) podem obtindre objectes com aquestos:

Amb 50 anells:

esfera1

Amb 100 anells:

esfera2

Amb 1000 anells:

esfera3

Podreu comprovar que el temps de resposta és molt diferent a l'executar aquestes figures canviant el nombre d'anells, sempre depenent del vostre hardware.

Per a accelerar aquest temps d'execució quan tenim molts objectes, OpenGL ens proporciona les llistes de visualització, una espècie de macros on podem emmagatzemar la geometria dels objectes que anem a dibuixar en la nostra escena, entre d'altres.

Encara que no anem a entrar en detalls sobre açò, un exemple d'utilització seria aquest:

escenario = glGenLists(1); /* Solicitamos un identificador */
if(escenario != 0) {              /* es valido si distinto de 0 */
    glNewList(escenario, GL_COMPILE); /* Inicia la definicion */
    escena();                         /* nuestros objetos */
    glEndList();                      /* finaliza la definición */
}

I per a dibuixar un objecte a través d'aquesta llista, utilitzariem:

glCallList(escenario);