Hola a todos.
Este es el segundo tutorial de 3D en libnds. En el anterior tutorial dejé unas cuantas cosas sin explicar porque lo único que quería es que viérais un ejemplo sencillito de 3D sin usar ningún efecto raro. Hoy voy a explicar algunas propiedades de los polígonos, luces y transparencias.
Hay un máximo de 4 luces, y no se puede hacer transparente un cuerpo encima de otro transparente. Bueno, si se puede, pero salen cosas bastante raras...
Si tenéis cualquier duda preguntad.
--------------------------------------------------------------------------------------------
Las luces funcionan de la siguiente manera:
-Tienes que darle propiedades a los materiales de los polígonos. ¿Qué es eso? Pues decir cómo va a usar la información de las luces que configuremos. Podemos decir que refleje sólo la luz roja, que el propio cuerpo emita luz...
-Hay que configurar las luces (evidentemente). Para ello se da un color y un vector a la luz deseada. Por ejemplo, una luz RBG(31,31,31) con un vector (0,-1,0) es una luz blanca que cae del techo.
-Hay que decir en el formato de los polígonos que se va a usar la luz deseada (0 a 3). Puedes hacer que ciertas luces afecten a algunos objetos y a otros no, etc.
-Cuando estás dibujando el polígono en cuestión tienes que ir diciendo las normales de cada cara. ¿Qué son las normales? Una normal es un vector perpendicular a la superficie del polígono de longitud 1. Por ejemplo, la normal del suelo es (0,1,0) y la del techo (0,-1,0).
Menudo lío, ¿no? Afortunadamente, las 2 primeras cosas sólo se hacen una vez, la 3ª también lo normal es hacerla una vez (por frame) y la última no os preocupéis, que ya os daré un programita con el que se convierten modelos de un programa de diseño de 3D de ordenador en uno que la DS puede usar.
-------------------------------------------------------------------------------------------------
Las transparencias funcionan de la siguiente manera:
-Hay que activar GL_BLEND igual que el antialias.
-Hay que decir en el formato de los polígonos la cantidad de transparencia.
-Hay que tener en cuenta que solo se puede hacer transparencia de un objeto transparente sobre otro transparente si tienen distinta ID.
Eso es todo. La transparencia puede tomar valores de 0 a 31, 31 = cuerpo opaco, 1 a 30 = transparencia, 0 = solo se ven las aristas.
-------------------------------------------------------------------------------------------------
Las propiedades que se le pueden dar a los polígonos son las luces que vas a ver, toon shading, niebla, alpha (transparencia), el culling (partes del polígono que no se dibujan), la ID del polígono y algunas otras cositas. No voy a ver esto a fondo porque ni siquiera se como funcionana algunas cosas, pero os voy a decir los tipos de culling que hay:
POLY_CULL_FRONT No dibuja los polígonos de frente.
POLY_CULL_BACK No dibuja los polígonos de espalda (lo recomendaría para polígonos no transparentes.)
POLY_CULL_NONE Dibuja todos los polígonos.
-------------------------------------------------------------------------------------------------
Estos son los ejemplos:
Luces y culling:
main.c:
#include <PA9.h>
void Dibujar3D();
int rot_quad;
bool culling; //Para hacer culling o no.
int main()
{
PA_Init();
PA_InitVBL();
PA_InitText(1, 0);
PA_OutputText(1,0,0,"Tutorial de 3D usando libnds\npor AntonioND.\n\n\nEsto es un ejemplo de libnds\nmodificado.");
PA_OutputText(1,0,10,"A: Cambiar culling.\nB: Mover.");
videoSetMode(MODE_0_3D);
glInit();
glEnable(GL_ANTIALIAS);
glClearColor(0,0,0,31);
glClearPolyID(63);
glClearDepth(GL_MAX_DEPTH);
glViewport(0,0,255,191);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(70, 256.0 / 192.0, 0.1, 100);
//Configura la luz 0 con un color RGB15(31,0,0) = Rojo, con un vector (0,-1,0)
glLight(0, RGB15(31,0,0) , 0, floattov10(-1.0), 0);
//Luz 1, color RGB15(0,31,0) = Verde, vector (0,1,0)
glLight(1, RGB15(0,31,0) , 0, floattov10(1.0) , 0);
//Luz 2, color RGB15(0,0,31) = Azul
glLight(2, RGB15(0,0,31) , floattov10(1.0), 0, 0);
//RGB15(31,31,0) = Amarillo
glLight(3, RGB15(31,31,0) , floattov10(-1.0), 0, 0);
//Comportamiento de los materiales respecto a la luz.
//El color en RGB15 es el máximo color que puede tener el polígono por ese tipo de luz.
//Por ejemplo, si tengo una luz de RGB15(31,31,31) pero el material GL_DIFFUSE es
//RGB15(16,16,16), el color máximo que puede alcanzar por la luz es RGB15(16,16,16).
//Lo otro es la propiedad, lo he explicado un poco.
//Color reflejado por la pared, suelo...
glMaterialf(GL_AMBIENT, RGB15(8,8,8));
//Luces que dan diréctamente a el polígono.
glMaterialf(GL_DIFFUSE, RGB15(31,31,31));
//Color que se refleja a la cámara (como en un espejo)...
glMaterialf(GL_SPECULAR, 0);
//Color que emite el propio polígono.
glMaterialf(GL_EMISSION, RGB15(5,5,5));
while (1)
{
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
culling ^= Pad.Newpress.A;
rot_quad -= Pad.Held.B;
//Dibujar la escena
Dibujar3D();
glFlush(0);
PA_WaitForVBL();
}
return 0;
}
void Dibujar3D()
{
//Atributos de los polígonos
if(culling)
{
glPolyFmt(POLY_ALPHA(31) | POLY_CULL_FRONT | POLY_FORMAT_LIGHT0 | POLY_FORMAT_LIGHT1 |
POLY_FORMAT_LIGHT2 | POLY_FORMAT_LIGHT3);
}
else
{
glPolyFmt(POLY_ALPHA(31) | POLY_CULL_NONE | POLY_FORMAT_LIGHT0 | POLY_FORMAT_LIGHT1 |
POLY_FORMAT_LIGHT2 | POLY_FORMAT_LIGHT3);
}
glTranslatef(0.0f,0.0f,-3.0f);
glRotateX(rot_quad);
glRotateY(rot_quad);
glRotateZ(rot_quad);
glBegin(GL_QUADS);
//La normal es el vector perpendicular a una cara, se usa para las luces y debe
//estar normalizada (tiene que medir 1)
glNormal3f( 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);
glNormal3f( 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);
glNormal3f( 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);
glNormal3f( 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);
glNormal3f( 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);
glNormal3f(-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);
glEnd();
return;
}
Blending (gracias a Dr.Demencio):
#include <PA9.h>
void Dibujar3D();
float rot_tri, rot_quad;
int main()
{
PA_Init();
PA_InitVBL();
PA_InitText(1, 0);
PA_OutputText(1,0,0,"Tutorial de 3D usando libnds\npor AntonioND.\n\n\nEsto es un ejemplo de libnds\nmodificado.");
PA_OutputText(1,0,10,"Arriba/Abajo: Cambiar\n transparencia.");
videoSetMode(MODE_0_3D);
glInit();
//Activar blending y antialias
glEnable(GL_ANTIALIAS | GL_BLEND);
glClearColor(0,0,0,31);
glClearPolyID(63);
glClearDepth(GL_MAX_DEPTH);
glViewport(0,0,255,191);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(70, 256.0 / 192.0, 0.1, 100);
u8 blending = 15;
while (1)
{
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
if(blending < 31 && Pad.Newpress.Up) blending ++;
if(blending > 0 && Pad.Newpress.Down) blending--;
rot_tri+=0.5f;
rot_quad-=0.3f;
//Las caras traseras tienen ID 0
glPolyFmt(POLY_ID(0) |POLY_ALPHA(blending) | POLY_CULL_FRONT);
Dibujar3D();
//Las caras delanteras tienen ID 1
glPolyFmt(POLY_ID(1) |POLY_ALPHA(blending) | POLY_CULL_BACK);
Dibujar3D();
glFlush(0);
PA_WaitForVBL();
}
return 0;
}
void Dibujar3D()
{
glLoadIdentity();
glTranslatef(-1.5f,0.0f,-6.0f);
glRotateY(rot_tri);
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();
glLoadIdentity();
glTranslatef(1.5f,0.0f,-7.0f);
glRotateX(rot_quad);
glRotateY(rot_quad);
glRotateZ(rot_quad);
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);
glEnd();
return;
}
Despues de compilar tendremos estos resultados:
Descarga:
http://www.mediafire.com/?wif5djmelxg