Anuncios Google

Tutoriales de programación 3D para NDS: 2- Transformaciones, Antialias y Culling

Buenas, gracias a los ánimos que me habéis dado en el tutorial anterior, traigo en esta ocasión el segundo, sobre el que trataremos principalmente sobre el Antialias para mejorar gráficos, dibujaremos figuras algo más complejas (cubos, pirámides), y le aplicaremos transformaciones (mover, rotar, escalar) a dichos objetos. Por si fuera poco, también sabremos qué es el culling y cómo se usa, y a manejar algo más las matrices (no vamos a calcularlas), y puede que algo más.

Bueno, sin más preámbulos, empezamos!

1- Antialias, qué es y cómo se usa

Bien, sé que habéis oído varias veces esa palabra en el tutorial anterior, pues en este váis a ver de qué se trata. Pues trata principalmente un tipo de suavizado de polígonos alterando la imagen final. Esto no nos lleva a ninguna parte así que os pongo un ejemplo:

En la imagen de arriba vemos una línea a la cual no se le ha aplicado el Antialias, y vemos los bordes como "de sierra", irregulares y poco llamativos. Pero con el Antialias activado, esos bordes se suavizan y dan mayor impresión de 3D.

 

Pero usar Antialias tiene una serie de inconvenientes, los expongo a continuación:

- El color de fondo debe ser opaco,  por lo que las capas 2D no podremos usarlas (no se verían)

- Los polígonos deben tener la misma ID (esto se ve afectado en transparencias)

- El color de fondo debe ser negro

 

Pero usar el Antialias ya es cosa vuestra, ahora para iniciarlo usamos la función glEnable()

void glEnable(GLenum estados);
      estados -> Los estados que queremos iniciar, soportan bitflags, por ejemplo
                      glEnable(GL_ANTIALIAS | GL_BLEND);
 
Nota: Para quitar un estado iniciado antes con glEnable(), se usa la función glDisable();
 
void glDisable(GLenum estados);
       estados -> Los mismos que con glEnable();

Bien, pues sabiendo esto, este es el código para iniciar el Antialias:

void Antialias(void){
 
        // Inicia Antialias con glEnable();
        glEnable(GL_ANTIALIAS);
 
        // Color de fondo negro y opaco (0, 0, 0, 31);
        glClearColor(0, 0, 0, 31);
 
       // Todos los poligonos deben tener la misma ID
       glClearPolyID(63);   // 63 es el valor

void QuitaAntialias(void){
 
       // Quita Antialias con glDisable();
       glDisable(GL_ANTIALIAS);
 
       // Color de fondo tranparente
       glClearColor(0, 0, 0, 0);
}

Una última cosa, esto se suele poner al iniciar OpenGL, pero no pasa nada si se pone o se quita en tiempo de ejecución.

 

2- Transformaciones a los objetos 3D

Bien, si recordáis el triángulo de la lección anterior, estaba rotando en el eje Z, y nos preguntamos: ¿Cómo se hace eso?¿Se pueden hacer cosas así? La respuesta es SI, OpenGL admite 3 tipos de transformaciones a los objetos, son las siguientes:

void glTranslatef(float x, float y, float z);
           Mueve (traslada) un objeto en torno a los ejes XYZ
 
void glRotateX(float angulo);
           Rota un objeto en el espacio sobre el eje X, según el ángulo definido.
           Para rotarlo en Y o en Z se usan las funciones glRotateY() y glRotateZ() con los
           mismos argumentos
 
void glScalef(float x, float y, float z);
           Escala un objeto en el espacio, es decir, que se agrande o se achique en
           los ejes XYZ

El ejemplo del triángulo rotando:

        // Rota el triangulo en Z
	glRotateZ(++rotacion_triangulo);
	if(rotacion_triangulo == 360) rotacion_triangulo = 0;
 
	// Empieza a dibujar el triangulo
	glBegin(GL_TRIANGLE);
 
		glColor3b(255, 0, 0);  // Rojo
		glVertex3f(-1.0, -1.0, 0.0);
		glColor3f(0, 0, 255);  // Azul
		glVertex3f(1.0, -1.0, 0.0);
		glColor3b(0, 255, 0);  // Verde
		glVertex3f(0.0, 1.0, 0.0);

Bien, ahora que sabéis usar las transformaciones véis nuevas posibilidades pero estas transformaciones lo que mueven no es el objeto, sino el espacio, os pongo un ejemplo:

Tenemos un cubo:

Lo rotamos 2 puntos en Z

Lo movemos en X

¿Qué ha pasado? El cubo se ha movido en X, pero con la rotación que le habíamos puesto antes.

Bien, ¿cómo solucionamos esto?, hay 2 maneras de hacerlo:

1- Reiniciando la matriz de modelado (glLoadIdentity()), no es muy usual pero funciona)

2- La manera más profesional, con OpenGL podemos guardar temporalmente la matriz que queramos en la pila, para que después de transformar el objeto, se restaure. Resultado: El objeto se ha movido y el espacio no ha sufrido cambios.

Ahora os daré las funciones para guardar y restaurar matrices, son las siguientes:

void glPushMatrix(void);
          Guarda la matriz seleccionada anteriormente en la pila de matrices.
 
void glPopMatrix(int n);
          Restaura 'n' matrices de la pila (recomiendo ponerlo a 1)

Un ejemplo con el triángulo de antes:

 // Selecciona la matriz de modelado y guardala
   glMatrixMode(GL_MODELVIEW);
   glPushMatrix();
 
   // Rota el triangulo en Z
	glRotateZ(++rotacion_triangulo);
	if(rotacion_triangulo == 360) rotacion_triangulo = 0;
 
	// Empieza a dibujar el triangulo
	glBegin(GL_TRIANGLE);
 
		glColor3b(255, 0, 0);  // Rojo
		glVertex3f(-1.0, -1.0, 0.0);
		glColor3f(0, 0, 255);  // Azul
		glVertex3f(1.0, -1.0, 0.0);
		glColor3b(0, 255, 0);  // Verde
		glVertex3f(0.0, 1.0, 0.0);
 
	// Hemos dibujado y transformado el objeto, restaura la matriz de modelado
	glPopMatrix(1);

Así es cómo funcionan las transformaciones, no os preocupéis si no se entiende, al final del tutorial pondré unas prácticas para que veáis cómo funcionan, y tenéis los comentarios para cualquier duda.

3- Culling, aumento de velocidad y renderizado

Bien, ahora llegamos a un punto en el que tenemos un objeto, por ejemplo, un cubo. Y resulta que, desde la posición actual de la cámara sólo se ven las caras frontales, pero, sin embargo, también se han dibujado las traseras, y os preguntáis: ¿Cómo puedo hacer que las caras traseras que no puedo ver no se dibujen y aumente la velocidad del programa? o ¿Cómo puedo hacer que no se dibujen las caras frontales para poder ver lo que hay dentro del objeto?.

Pues muy fácil, OpenGL puede hacer esto con un método llamado culling, que significa "escoger". Con esto "escogemos" las caras que OpenGL  no va a procesar y que no se mostrarán.

Bien, para hacer esto llamamos a la función glPolyFmt(), que, como vimos, es la encargada de poner atributos a los polígonos, como el culling. Los valores del culling pueden ser:

POLY_CULL_NONE --> Se dibujan todas las caras
POLY_CULL_FRONT --> No se dibujan las caras frontales
POLY_CULL_BACK --> No se dibujan las caras traseras

Sabiendo, esto, aplicamos el culling con el glPolyFmt() al principio de dibujar:

glPolyFmt(POLY_ALPHA(31) | POLY_CULL_BACK);
// No se dibujan las caras traseras, obligatorio poner POLY_ALPHA(31) si no no se ve
la escena (es transparente)

Con esto las caras traseras no se dibujarán, esto es altamente recomendado sobre todo para polígonos no transparentes.

4- Por qué no usar FLOAT

Bien, últimamente hemos estado usando variables float para todo: Cámara, Perspectiva, Vértices, cuando en verdad la NDS no tiene unidad de coma flotante (no calcula float).

¿Cómo es posible esto? Pues porque la NDS usa otro tipo de variables llamados variables F32 y V16 (F32 para cámara y perspectiva y V16 para vértices)(son variables INT). Esto no significa que tengamos que acostumbrarnos a variables F32 o V16, porque las funciones en las que usamos float lo transforman automáticamente a dicho tipo de variable, por ejemplo, miremos la función gluLookAt:

void gluLookAt(float px, float py, float pz, float ex, float ey, float ez, float rx, float ry, float rz){
 
		gluLookAtf32(floattof32(px), floattof32(py), floattof32(pz), floattof32(ex), floattof32(ey), floattof32(ez),
		             floattof32(rx), floattof32(ry), floattof32(rz));
   }

Como véis, pasamos los argumentos en float, y nos lo transforma a F32 para que se pueda usar.

Para hacer esto hay unas macros de Libnds en el archivo videogl.h, son los siguientes:

floattof32(n)  --> Transforma float en F32
f32tofloat(n) --> Transforma F32 en float
floattov16(n) --> Transforma float en V16
v16tofloat(n) --> Transforma float en V16

En realidad esto no tiene nada, sólo es para que veáis cómo procesa la NDS los valores float sin poder calcularlos...

5- Ejercicios para practicar

A partir de ahora los ejercicios que hagamos tendrán una estructura como esta:

main.c --> Codigo principal (se incluyen minilibrerias necesarias)(lógica del juego)
cabecera.h --> Variables y defines
cabecera.c --> Funciones de la cabecera.h
header.h --> Variables y defines
header.c --> Funciones de header.h

Ejercicio 1- Transladando y culling

Esta práctica está abordada a transladar objetos en el espacio, usando las funciones glPushMatrix() y glPopMatrix(), además de usar el culling por delante y por detrás.

Con + mueves el cubo

Con ABXY mueves la pirámide

Con LR cambias el culling

Descarga:http://www.mediafire.com/?fu3s27sj781958q

Ejercicio 2: Rotación y cámara

En este ejercicio puedes ver un cubo el cual podemos rotar sobre sus ejes, usando las funciones glRotateX(), glRotateY() y glRotateZ(). También podemos mover la cámara (convirtiendo float en f32)

Con + mueves la cámara

Con A rotas X

Con B rotas Y

Con X rotas Z

Descarga: http://www.mediafire.com/?84y3f8dr98i44er

Ejercicio 3: Escalar, color de fondo y Antialias

En este ejercicio puedes escalar (agrandar o achicar) la pirámide que tienes, puedes cambiar el color de fondo y activar/desctivar el Antialias para ver qué pasa.

Con AB escalas en X

Con XY escalas en Y

Con LR escalas en Z

Con + cambias el color de fondo

Tocando la pantalla táctil puedes activar/desactivar el Antialias.

Descarga: http://www.mediafire.com/?cvag1978l3lav7u

 

Bueno, este es el fin de este segundo tutorial, en el siguiente aprenderemos a usar listas compiladas (para dibujar más rápido), materiales y luces.

Hasta entonces, saludos!

 


~Actualmente estudiando Ingeniería de las Tecnologías de la Telecomunicación en la Escuela de Ingenieros~


Anuncios Google

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de Andresmargar

Gracias ;)

Gracias por todos vuestros apoyos a los tutoriales :D

excelente; Me impresiona la

excelente; Me impresiona la calidad que le das a tus tutoriales.

 

Como he dicho

en tu anterior tutorial, me será muy util para cuando aprenda algo más de C (no se mucho...), del resto, te felicito por el tutorial. ;)

 

Saludos!

Imagen de magicblack2009

Excelente tutorial, tengo que

Excelente tutorial, tengo que ponerme, aprender bien C (mis conocimientos no son para tirar cohetes) y luego ponerme con estos geniales tutoriales.

Salu2!


¿Quieres estar totalmente informado sobre el universo 3DS? Visita Magic3DS.

También puedes estar al tanto de toda la actualidad de 3DS en Twitter: @Magic3DS

Imagen de Andresmargar

Gracias

Me alegro de que te gusten ^^

Imagen de Pitoanto

Estoy intentando aprender a

Estoy intentando aprender a programar para NDS y cuando llegue al nivel adecuado lo miraré pero tiene una pinta estupenda, te felicito xD
Salu2!


(PA) The New NDS God (xD)

Seguidor de varios Youtubers/Gamers xDD tonterías que no importan nada xD

Imagen de Andresmargar

xD

Gracias por tu apoyo xD

Imagen de Pitoanto

Gracias a ti por hacer los

Gracias a ti por hacer los tutoriales que es difícil encontrar un buen tutorial en internet xD

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.