Hola a todos.
Como ya dije en otro hilo, voy a hacer un par de tutoriales de 3D usando las funciones que ofrecen las libnds. Como la mayoría de vosotros usáis PAlib he hecho este tutorial pensando en poder usar las 2 librerías a la vez. Las funciones de 3D son muy parecidas a las de opengl, asi que si ya sabéis algo de opengl os resultará muy sencillo todo esto. Es muy importante tener buena visión espacial, ya que os facilitará las cosas. Y como último consejo... No penséis que un juego 3D se programa fácilmente. El diseño de un objeto 3D con su textura, su animación, etc lleva mucho mas tiempo que uno en 2D, y no es tan fácil de enseñar como tú quieres que salga. Aun así no os desanimeis, cuando se acaba un juego en 3D el resultado suele ser mucho mejor que uno de 2D y da más satisfacción.
--------------------------------------------------------------------------------------------
En primer lugar os voy a hablar un poco del hardware 3D de la DS.
La DS tiene dos motores de gráficos, uno para cada pantalla, y sólo el de la pantalla principal tiene acceso al hardware 3D. Una vez que inicias el modo 3D no puedes usar sprites en esa pantalla, tampoco es que los vayas a necesitar... La imágen obtenida se muestra en el lugar del background 0. Hay un límite de vértices que se puedan dibujar por frame, creo que en torno a los 6000 y pico. Pueden parecer pocos, pero realmente hay de sobra para casi cualquier cosa. El mayor problema que os encontraréis es la poca memoria que tiene la DS para usar texturas, pero ya os hablaré de eso.
--------------------------------------------------------------------------------------------
Bueno, ahora os contaré un poco cómo van las 3D.
En primer lugar hay que tener una idea muy clara de cual es el sistema de coordenadas que vamos a usar. Mirad esta imagen (echa con el paint
):
X+, por ejemplo, quiere decir que cuando trasladamos en el eje X una cantidad positiva, se desplaza en la dirección de la flecha.
Las flechas indican como se gira un objeto cuando se gira una cantidad positiva de grados.
Dependiendo de la proyección que pongamos estos ejes estaran situados de otra manera.
Si necesitais más información buscad algún tutorial de opengl en google, no quiero explicar estas cosas que seguro que hay mejores maneras de explicar que la mía.
-------------------------------------------------------------------------------------------------
Y aquí viene el primer ejemplo. Echad un buen vistazo a todos los comentarios. Al principio es lioso, pero cuando te acostumbras es mucho mas fácil. Además, en un juego no tienes que usar muchas funciones que digamos, una vez que ajustas todo ya es mover, girar, dibujar...
main.c:
#include <PA9.h> //Con incluir esto de momento valdrá.
void Dibujar3D(); //Función donde dibujamos todo.
float rot_tri, rot_quad; //Ángulos de rotación de los objetos.
int main()
{
//Iniciar las PAlib...
PA_Init();
PA_InitVBL();
//Cuando inicies 3D la pantalla en 2D será la 1 en PAlib, no importa que sea la
//superior o la inferior (ya os diré la función para cambiarla).
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.");
//Configurar la pantalla principal para que use 3D (las 3D usan el background 0).
videoSetMode(MODE_0_3D);
//Iniciar el motor de 3D
glInit();
//Activar antialiasing (A partir de ahora le llamaré AA)
glEnable(GL_ANTIALIAS);
//Configurar color de fondo
//Rojo, Verde, Azul, Alpha. Todos van de 0 a 31.
//Para que funcione el AA tienes que dejar el último número a 31.
glClearColor(0,0,0,31);
//ID del fondo, tiene que tener una para él solo para que funcione AA.
glClearPolyID(63);
//Configurar la profundidad al máximo.
glClearDepth(GL_MAX_DEPTH);
//Parte de la pantalla donde veremos la escena 3D, estas coordenadas son para pantalla
//completa. Las 2 primeras es la esquina inferior izquierda, las 2 últimas la esquina
//superior derecha.
glViewport(0,0,255,191);
//Cargar matriz de proyección
glMatrixMode(GL_PROJECTION);
//Reiniciarla, dejarla en su estado inicial... Como lo queráis decir...
glLoadIdentity();
//Fijar perspectiva con la que veremos los objetos.
gluPerspective(70, 256.0 / 192.0, 0.1, 100);
//Atributos de los polígonos, ya os hablaré de esto.
glPolyFmt(POLY_ALPHA(31) | POLY_CULL_BACK);
while (1)
{
//Cargar matriz de modelos, con ésta dibujaremos las figuras que queramos.
glMatrixMode(GL_MODELVIEW);
//Reiniciarla, dejarla en su estado inicial... Como lo queráis decir...
//Así nos aseguramos de que se borran todos los cambios hechos antes.
glLoadIdentity();
//Dibujar la escena
Dibujar3D();
//Mostrar en la pantalla lo dibujado.
glFlush(0);
PA_WaitForVBL();
}
return 0;
}
void Dibujar3D()
{
//Mover lo que vamos a dibujar a partir de ahora (X, Y, Z)
glTranslatef(-1.5f,0.0f,-6.0f);
//Rotar lo que vamos a dibujar a partir de ahora (En torno al eje Y)
glRotateY(rot_tri);
//Dibujar triángulos
glBegin(GL_TRIANGLES);
//Color para los vértices que se dibujen a partir de este momento (Rojo, Verde, Azul)
glColor3f(1.0f,0.0f,0.0f);
//Coordenadas para un nuevo vértice (X, Y, Z)
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);
//Acabar de dibujar polígonos.
glEnd();
//En vez de deshacer lo que habíamos movido y girado, reiniciamos la matriz
//para anular esos cambios.
glLoadIdentity();
glTranslatef(1.5f,0.0f,-7.0f);
glRotateX(rot_quad);
glRotateY(rot_quad);
glRotateZ(rot_quad);
//Dibujar cuadrados.
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();
rot_tri+=0.5f; //Cambiar ángulo de rotación.
rot_quad-=0.3f;
return;
}
Despues de compilar tendremos este resultado:
He adjuntado el ejemplo para que os lo descargueis.
PD: Puede que no me explique muy bien a veces, pero si teneis dudas aquí estoy para resolverlas.