[Tutorial] 1. Primeros pasos en 3D.

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. :P

--------------------------------------------------------------------------------------------
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 XD):
Imagen
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:
Imagen

He adjuntado el ejemplo para que os lo descargueis.

Tutorial1.rar (19.25 KB)

Tutorial 1 de 3D


PD: Puede que no me explique muy bien a veces, pero si teneis dudas aquí estoy para resolverlas.
MUCHAS gracias, se agradece... ^^

[oki] [plas]
Repito, no me suelo explicar muy bien. Si no entendeis algo me lo decis. El próximo tutorial hablaré de las IDs de los objetos y de algunas cosas que he pasado de explicar ahora...

El mejor emulador para 3D es no$gba, pero como hay cosas que no hace bien del todo... lo mejor es probar de vez en cuando en la DS, sobre todo cuando se añaden luces y cosas por el estilo (ya os enseñaré...).

PD: El texto del tutorial está en el archivo adjunto.
PD2: Yo he modificado ciertas partes de PAlib para que la fuente por defecto sea la que veis, a vosotros os saldrá la normal XD.
como molas!! ^^ Si no fuese porque mañana tengo examen me ponía a ello ahora mismo, pero... En fins, mañana comento qué tal el tuto. Y gracias!
Muy bueno el tutorial =D. Merodeando por ahí me encontré un PDF con info sobre el 3D en PALib. Pongo la url, solo decir que es un trabajo de universidad(no importa, pero lo digo). http://www.lcc.uma.es/pfc/640.pdf
alexpowerup escribió:Muy bueno el tutorial =D. Merodeando por ahí me encontré un PDF con info sobre el 3D en PALib. Pongo la url, solo decir que es un trabajo de universidad(no importa, pero lo digo). http://www.lcc.uma.es/pfc/640.pdf

Jejeje, ya lo tengo.
PiratePila está baneado por "crearse clones para trollear"
Muy buen tutorial y muy buen PDF.

Al final me voy a animar a trabajar con 3D (sobretodo ahora en verano, que hay tiempo). XD
PiratePila escribió:Al final me voy a animar a trabajar con 3D (sobretodo ahora en verano, que hay tiempo). XD

Aunque sea haz una demo o algo, que al principio asusta porque hay que ajustar muchas cosas, pero luego es mucho más potente que el hardware 2D y mucho más cómodo de usar. Por ejemplo, si haces una proyección ortogonal puedes hacer sprites 3D que tienen muchas más posibilidades que los normales (transparencias unos sobre otros, rotaciones con total libertad, dar colores a los vértices del sprite...).
Está muy bien, gracias, pero al intentar compilar el ejemplo que adjuntas me da muchos errores, que si función implícita, que si demasiados argumentos en tal función...

:S
PRUC|-| escribió:Está muy bien, gracias, pero al intentar compilar el ejemplo que adjuntas me da muchos errores, que si función implícita, que si demasiados argumentos en tal función...

:S


Si te has bajado el archivo adjunto no te tiene quedar ni un solo warning. Yo tengo palib 080203, libnds 20071023 y devkitarm r21. Prueba a compilar los ejemplos de esta carpeta:
C:\devkitPro\examples\nds\Graphics\3D

Cualquiera valdrá.

EDIT: Esto es una cosita que he hecho esta tarde en 20 minutitos, probadla y me contais, jejeje:

Fireworks.rar (116.76 KB)

Demo de 3D que muestra una especie de fuegos artificiales.
ANTONIOND escribió:EDIT: Esto es una cosita que he hecho esta tarde en 20 minutitos, probadla y me contais, jejeje:


... simplemente: [mad]
judelco escribió:... simplemente: [mad]

¿Te asustas de lo decepcionante que es o de lo impresionante que es?

EDIT:R/L para girar la cámara (no ha quedado muy bien...).

EDIT2: Otra demo. Simplemente hay que mirar, no se puede hacer nada con los botones:

Balls.rar (120.72 KB)

Bolas chocando.
Hola, en la linea 41 me da error el ejemplo.
glViewport(0,0,255,191);
Asi es como me compila:
glViewPort(0,0,255,191); //Con la P mayuscula
Pumuki13 escribió:Hola, en la linea 41 me da error el ejemplo.
glViewport(0,0,255,191);
Asi es como me compila:
glViewPort(0,0,255,191); //Con la P mayuscula

La forma correcta es con minúscula, pero las versiones antiguas de libnds la tienen con mayúsculas.
A mi también me da errores al compilar:
main.c
c:/devkitPro/Programas/3D/source/main.c: In function 'main':
c:/devkitPro/Programas/3D/source/main.c:42: warning: implicit declaration of fun
ction 'glViewport'
arm-eabi-g++ -g -mthumb-interwork -mno-fpu -L/c/devkitPro/PAlib/lib -Wl,--gc-sec
tions -specs=ds_arm9.specs main.o -Lc:/devkitPro/PAlib//lib -lpa9 -L/c/devkitPro
/libnds/lib -lfat -lnds9 -ldswifi9 -o build.elf
main.o: In function `main':
c:/devkitPro/Programas/3D/source/main.c:42: undefined reference to `glViewport'
collect2: ld returned 1 exit status
make[1]: *** [/c/devkitPro/Programas/3D/3D.elf] Error 1
make: *** [build] Error 2


EDITO: Ya me compila, era lo que decía el amigo Pumuki13.
He tenido que cambiar el glViewPort y he puesto glViewPort(1,1,255,191), porque sino las figuras se me salían de la pantalla, de todas formas se ven más pequeñas, os pongo captura:

Imagen

Sólo una cosa más, ¿cómo actualizo la libnds? XD
Se me ve igual que a ti Serede.
Vamos a ver... Eso me pasaba a mi a con las primeras libnds con las que use el 3D, ACTUALIZAD. Se ve distinto por un ¿bug? en la función gluPerspective. Actualizar las libnds es tan fácil como ejecutar el devkitpro updater y desmarcar todo menos las libnds.
ANTONIOND escribió:Vamos a ver... Eso me pasaba a mi a con las primeras libnds con las que use el 3D, ACTUALIZAD. Se ve distinto por un ¿bug? en la función gluPerspective. Actualizar las libnds es tan fácil como ejecutar el devkitpro updater y desmarcar todo menos las libnds.

Yo tengo el devkitARM actualizado, cuando abro el updater sólo me salen el devkitPSP y el devkitPCP, aparte del insight y el Programmer's Notepad.
Serede escribió:
ANTONIOND escribió:Vamos a ver... Eso me pasaba a mi a con las primeras libnds con las que use el 3D, ACTUALIZAD. Se ve distinto por un ¿bug? en la función gluPerspective. Actualizar las libnds es tan fácil como ejecutar el devkitpro updater y desmarcar todo menos las libnds.

Yo tengo el devkitARM actualizado, cuando abro el updater sólo me salen el devkitPSP y el devkitPCP, aparte del insight y el Programmer's Notepad.

¿Has probado a dar al [+] que hay a la izquierda de cada una de esas cosas?

De todos modos puedes probar con otras libnds:
http://sourceforge.net/project/showfile ... _id=151608
ANTONIOND escribió:
Serede escribió:
ANTONIOND escribió:Vamos a ver... Eso me pasaba a mi a con las primeras libnds con las que use el 3D, ACTUALIZAD. Se ve distinto por un ¿bug? en la función gluPerspective. Actualizar las libnds es tan fácil como ejecutar el devkitpro updater y desmarcar todo menos las libnds.

Yo tengo el devkitARM actualizado, cuando abro el updater sólo me salen el devkitPSP y el devkitPCP, aparte del insight y el Programmer's Notepad.

¿Has probado a dar al [+] que hay a la izquierda de cada una de esas cosas?

De todos modos puedes probar con otras libnds:
http://sourceforge.net/project/showfile ... _id=151608

Pone:
devkitPPC
- devkitPPC
- libogc
- libfat-ogc
- Gamecube examples
- Wii examples
- Gcube
devkitPSP
- devkitPSP
- psp sdk documentation
Programmer's Notepad
Insight
Serede escribió:
ANTONIOND escribió:De todos modos puedes probar con otras libnds:
http://sourceforge.net/project/showfile ... _id=151608

Pone:
devkitPPC
- devkitPPC
- libogc
- libfat-ogc
- Gamecube examples
- Wii examples
- Gcube
devkitPSP
- devkitPSP
- psp sdk documentation
Programmer's Notepad
Insight

Pues descarga una de las versiones de la página que te he dicho ahi arriba.
ANTONIOND escribió:
Serede escribió:
ANTONIOND escribió:De todos modos puedes probar con otras libnds:
http://sourceforge.net/project/showfile ... _id=151608

Pone:
devkitPPC
- devkitPPC
- libogc
- libfat-ogc
- Gamecube examples
- Wii examples
- Gcube
devkitPSP
- devkitPSP
- psp sdk documentation
Programmer's Notepad
Insight

Pues descarga una de las versiones de la página que te he dicho ahi arriba.

Updated [sonrisa] Thx
Imagen
Ya se me ve bien a mi tambien y sin cambiar por la P mayuscula.
Para cuando el siguiente tuto? Es que con esto no se puede hacer mucho.... xD (a menos que quieras hacer un homebrew cuya funcion sea un triangulito dando vueltas [boing] )
judelco escribió:Para cuando el siguiente tuto? Es que con esto no se puede hacer mucho.... xD (a menos que quieras hacer un homebrew cuya funcion sea un triangulito dando vueltas [boing] )

"Silly's Entretaiment DS", sería un gran homebrew, los spammers se entretendrían con eso en vez de dar la tabarra en EOL.
Serede escribió:
judelco escribió:Para cuando el siguiente tuto? Es que con esto no se puede hacer mucho.... xD (a menos que quieras hacer un homebrew cuya funcion sea un triangulito dando vueltas [boing] )

"Silly's Entretaiment DS", sería un gran homebrew, los spammers se entretendrían con eso en vez de dar la tabarra en EOL.


Perdon Serede, pero no lo cojo [+risas] Que has querido decir exactamente?

PD: AntonioND, ya hablamos por el msn
judelco escribió:
Serede escribió:
judelco escribió:Para cuando el siguiente tuto? Es que con esto no se puede hacer mucho.... xD (a menos que quieras hacer un homebrew cuya funcion sea un triangulito dando vueltas [boing] )

"Silly's Entretaiment DS", sería un gran homebrew, los spammers se entretendrían con eso en vez de dar la tabarra en EOL.


Perdon Serede, pero no lo cojo [+risas] Que has querido decir exactamente?

PD: AntonioND, ya hablamos por el msn

Nada, es que EOL está algo desierto y me aburría xD.

P. D. : No lo decía por tí ni por nadie eh, ni mucho menos.
judelco escribió:
Serede escribió:
judelco escribió:Para cuando el siguiente tuto? Es que con esto no se puede hacer mucho.... xD (a menos que quieras hacer un homebrew cuya funcion sea un triangulito dando vueltas [boing] )

"Silly's Entretaiment DS", sería un gran homebrew, los spammers se entretendrían con eso en vez de dar la tabarra en EOL.


Perdon Serede, pero no lo cojo [+risas] Que has querido decir exactamente?

PD: AntonioND, ya hablamos por el msn


Hay otros 2 tutoriales, y ya haré el siguiente algún dia... XD
29 respuestas