Anuncios Google

Curso aplicado de GRRLIB - 9º Entrega

Tutoriales Avanzados Homebrewes

Después de 8 tutoriales de programación en 2D, seguro que ya empezabais a echar de menos comenzar con la programación en 3D. Puede que al principio os cueste un poco, pero os aseguro que los resultados merecen la pena. El Hardware de la Wii bien merece que sepáis sacarle partido a su procesador gráfico. Entrad leed y juzgarlo por vosotros mismos. Veréis como pronto estareis creando el código fuente de vuestro propio programa en 3D y comprobaréis que vuestras creaciones adquieren una apariencia espectacular

PROGRAMACIÓN EN 3D CON GRRLIB

Devkitpro suministra una biblioteca de programación en 3D llamada GX que es bastante compleja de utilizar. GRRLIB se basa en GX simplificando todo lo que hace complicada la programación en 3D.

A los que conocen algo la programación en 3D tengo que decirles que GX tiene ciertos aspectos parecidos a OpenGL, pero no coincide con éste en muchos otros aspectos. De todas formas conocer OpenGL es una ventaja a la hora de aprender programación en 3D para Wii.

Comenzaremos el curso con algunos conceptos básicos de programación tridimensional para luego continuar con la programación específica de GRRLIB

REPRESENTACIÓN TRIDIMENSIONAL

Hasta ahora hemos utilizado un sistema de coordenadas bidimensional que nos era suficiente para representar nuestra escena en el plano de la pantalla de nuestro televisor. Es decir utilizábamos dos coordenadas (x,y) para representar la posición de un objeto en ese mundo, tomando como referencia la esquina superior izquierda de la pantalla.

Si queremos  representar nuestro mundo en 3D necesitaremos una coordenada adicional (z).

Además nos será mucho más práctico situar el origen de coordenadas en el centro de la pantalla para permitir una representación mediante perspectiva.

 

Hasta aquí podría ser suficiente si nos limitáramos simplemente a dibujar objetos simples en un espacio limitado en 3D, pero cuando modelamos nuestro mundo en tres dimensiones debemos tomar en consideración muchos más factores, como es la posición del observador, las luces de la escena o la información de la composición de las superficies de los objetos.

Además nos resultará muy interesante el poder cambiar el sistema de referencia o realizar transformaciones de rotación, traslación y escalado sobre los objetos.

Es por ello que para el modelado en 3D nos hemos de apoyar en sistemas un poco más sofisticados en los que tendremos en cuenta los siguientes elementos:

  1. Posición de la cámara o del observador.
  2. Campo de visión. Es decir distancia mínima y máxima de visibilidad desde la cámara y ángulo de visión. 
  3. Sistema de coordenadas mundiales, que es como denominaremos a nuestro sistema de coordenadas de tres ejes con origen en el centro de la pantalla, tal y como lo hemos definido anteriormente.

A la hora de representar un objeto nuestra Wii no puede utilizar directamente las coordenadas de dibujo que nosotros le pasamos, ya que la pantalla del televisor no puede representar objetos tridimensionales. En realidad lo que vemos es una representación en dos dimensiones de de ese dibujo en 3D. Es decir vemos lo que llamamos una proyección en 2D de una escena en 3D.

Para calcular esa proyección, nuestra Wii debe tener en cuenta la posición del observador, el ángulo de visión y las transformaciones sobre los objetos

Todas estas transformaciones se realizan mediante cálculo matricial, pero no os preocupéis que todo esto lo calculará nuestra Wii automáticamente, aunque sí que deberemos conocer por encima este proceso para comprender qué parámetros de configuración debemos usar.

TRANSFORMACIONES DEL MODELO DE VISTA

Para entender a que nos referimos con esto debemos tener en cuenta que lo que se va a ver en nuestra pantalla depende directamente del punto de vista desde donde lo miramos. Es decir del punto donde esté situada la cámara.

El hardware de la Wii nos mostrará lo que se ve desde ese punto de vista que debemos definir.

TRANSFORMACIONES DE MODELO

Llamamos transformaciones de modelo a las que se aplican sobre los objetos para modificarlos y que alcancen su posición definitiva antes de pasar a proyectar el resultado en coordenadas 2D.

Las transformaciones de vista que utilizaremos son Translación, Escalado y Rotación.

Tenemos que tener en cuenta que aquí es muy importante el orden de los factores. No es lo mismo mover un objeto y luego rotarlo que rotarlo y después moverlo.

En las figuras podéis ver un ejemplo de lo que os hablo.

Primero traslación y luego rotación..... 

Primero rotación y luego traslación......

Como veis los resultados son totalmente diferentes.

TRANSFORMACIONES DE PROYECCIÓN

Si os fijáis en cómo se ven los objetos en el mundo real os daréis cuenta que cuando más lejos está un objeto más pequeño se ve. Esto es debido a que nuestra visión tiene un campo mayor según nos alejamos de nuestros ojos.

   

En un modelo 3D si representáramos todos los puntos del mismo tamaño no conseguiríamos ese efecto, ya que el objeto tendría el mismo tamaño por muy alejado que estuviera del observador.

Es por ello que una vez nuestra Wii tiene calculado el mundo en su posición final debe realizar unas transformación adicional que se llama transformación de proyección, para ello utiliza el ángulo de visión que nosotros le definiremos para empequeñecer la imagen según se aleja de la posición en la que le hemos dicho que está el observador.

TIPOS DE ILUMINACIÓN

Pero por mucho que diseñemos necesitamos iluminar la escena para que podamos ver el resultado.

Al igual que en OpenGL, el hardware de Wii permite cuatro diferentes tipos de iluminación;  Iluminación ambiente, iluminación difusa, iluminación especular e iluminación de foco (o spot).

El color final de un punto de la pantalla dependerá del tipo (o tipos) de iluminación que intervengan en la escena.

Iluminación ambiente. Es aquella luz que se trasmite por igual en todas direcciones y que no viene de ningún sitio concreto.

Iluminación difusa. Al igual que la luz ambiente, la luz difusa se transmite en todas direcciones por igual, pero a diferencia de aquella, sí que tiene un punto de origen. La luz difusa además, se va atenuando según se aleja del punto de origen.

Iluminación especular. Se trata de una luz que rebota según la normal del polígono que ilumina. Con dicha luz se consiguen efectos de reflejo.

Iluminación de foco. En este caso la luz tiene el comportamiento de un foco. Parte de un punto en concreto y se transmite según un cono de luz que va ensanchándose según se aleja del punto de origen.

FUNCIONES 3D EN GRRLIB

Como os dije más arriba, GRRLIB está pensado para facilitarnos la vida. Si programáramos directamente en GX, para definir nuestro mundo en 3D necesitaríamos un montón de funciones definiendo todos y cada uno de los parámetros de nuestro universo. GRRLIB sin embargo define la mayoría de los parámetros por nosotros, pudiendo definir nuestro espacio 3D con tan solo unas pocas funciones.

Vamos a comenzar paso por paso a explicar las funciones fundamentales.

Lo primero que debemos hacer antes de empezar a modelar es indicarle a nuestra Wii que lo siguiente van a ser instrucciones en 3D y de paso decirle como debe realizar las transformaciones de proyección, es decir cómo es nuestro ángulo de visión.

Para ello utilizaremos la función GRRLIB_3DMode:

void GRRLIB_3dMode ( f32 minDist, f32 maxDist, f32 fov, bool texturemode, bool normalmode )
Cambia a modo 3D y configura la matriz de posición
Parametros
minDist: Distancia mínima a la camara.
maxDist: Distancia máxima a la camara.
fov: (Field Of View) Campo de visión de la cámara
texturemode: 
	false, GX no usará coordenadas de textura. 
	true, GX Usará coordenadas de textura.
normalmode:
	false, GX no usará coordenadas normales.
	true, GX usará coordenadas normales.

Como veis dependiendo del ángulo que le pasemos en el parámetro fov el campo de visión será mayor o menor.

La función nos pide dos parámetros booleanos en los que deberemos decirle a GRRLIB si los objetos que vamos a dibujar llevan o no texturas y si vamos a definir los vectores normales de las superficies del objeto.

En esta primera entrega en 3D vamos a trabajar sin texturas y con normales por lo que llamaremos a la función con el primero de estos dos parámetros con valor "false" y el segundo "true". Tendremos tiempo en entregas posteriores de explicar estos dos aspectos.

Para cambiar la posición y el objetivo de la cámara podemos usar la función GRRLIB_Camera3dSettings:

void GRRLIB_Camera3dSettings ( f32 posx, f32 posy, f32 posz, f32 upx, f32 upy, f32 upz, f32 lookx, f32 looky, f32 lookz )
Asigna los parámwetros de la cámara
Parametros
posx posición x de la cámara.
posy posición y de la cámara.
posz posición z de la cámara.
upx componente x de la posición "arriba" de la cámara.
upy componente y de la posición "arriba" de la cámara.
upz componente z de la posición "arriba" de la cámara
lookx posición x del punto al que mira la cámara.
looky posición y del punto al que mira la cámara.
lookz posición z del punto al que mira la cámara.

Hay que tener en cuenta que, a partir de ese momento, si queremos utilizar funciones en 2D deberemos llamar a la función GRRLIB_2dMode.

GRRLIB_2dMode();

Pero dejemos por ahora el 2D a un lado y volvamos a nuestro espacio en 3D.

Una vez hemos definido nuestro sistema de proyección y antes de empezar a dibujar, tenemos que indicarle a GRRLIB cuáles son las transformaciones que vamos a aplicar a todo lo que vayamos a dibujar a continuación.

Para ello tenemos varias posibilidades:

void GRRLIB ObjectView ( f32 posx, f32 posy, f32 posz, f32 angx, f32 angy, f32 angz, f32 scalx, f32 scaly, f32 scalz )
Configura la matriz de vista (en este orden escala, rotación y translación).
Parametros
posx coordenada de posición x del objeto.
posy coordenada de posición y del objeto.
posz coordenada de posición z del objeto.
angx angulo de rotación x del objeto.
angy angulo de rotación y del objeto.
angz angulo de rotación z del objeto.
scalx escala x del objeto.
scaly escala y del objeto.
scalz escala z del objeto.

La función GRRLIB_ObjectView aplica un escalado, una rotación y una traslación exactamente en ese orden.

Es decir, primero escalará los objetos multiplicando la magnitud de sus coordenadas x por scalx, la de sus coordenadas y por scaly y la de sus coordenadas z por scalz.

Después girará el resultado en un ángulo angx tomando el ejex como eje de rotación, con un ángulo angy sobre el eje y, y con un ángulo angz sobre el eje z.

Por último trasladará el resultado a la posición posx, posy, posz.

Esta función tiene su razón de ser en que ese es el orden más habitual en el que se aplican las transformaciones, aunque no nos sirve de mucho si queremos aplicar las transformaciones en otro orden.

void GRRLIB_ObjectViewInv ( f32 posx, f32 posy, f32 posz, f32 angx, f32 angy, f32 angz, f32 scalx, f32 scaly, f32 scalz )
Configura la matriz de vista (en este orden escala, translación y rotación).
Parametros
posx coordenada de posición x del objeto.
posy coordenada de posición y del objeto.
posz coordenada de posición z del objeto.
angx angulo de rotación x del objeto.
angy angulo de rotación y del objeto.
angz angulo de rotación z del objeto.
scalx escala x del objeto.
scaly escala y del objeto.
scalz escala z del objeto.

La función GRRLIB_ObjectViewInv es idéntica a la anterior pero intercambia el orden de la rotación y la traslación. Es decir, primero escala, después traslada y por último rota.

Como podéis ver, este sistema aunque sencillo, es muy rígido y se ve enseguida la necesidad de una forma más flexible de aplicar transformaciones, que nos permita elegir el orden en el que realicemos las mismas.

GRRLIB nos provee de funciones de rotación traslación y escalado independientes que nos permitirán elegir el orden que se nos antoje.

GRRLIB nos pide que le indiquemos cuando empiezan y cuando terminan las transformaciones. Para ello disponemos de dos funciones GRRLIB_ObjectViewBegin() y GRRLIB_ObjectViewEnd().

Todas las transformaciones que queramos realizar deberemos ponerlas entre estas dos funciones.

void GRRLIB_ObjectViewBegin (void)
Inicializa la matriz de objetos.
 
void GRRLIB_ObjectViewRotate ( f32 angx, f32 angy, f32 angz )
Gira la matriz de vista
angx angulo de rotación x del objeto.
angy angulo de rotación y del objeto.
angz angulo de rotación z del objeto.
 
void GRRLIB_ObjectViewScale ( f32 scalx, f32 scaly, f32 scalz )
Escala la matriz de vista
scalx escala x del objeto.
scaly escala y del objeto.
scalz escala z del objeto.
 
void GRRLIB_ObjectViewTrans ( f32 posx, f32 posy, f32 posz )
Traslada la matriz de vista
posx coordenada de posición x del objeto.
posy coordenada de posición y del objeto.
posz coordenada de posición z del objeto.
 
void GRRLIB_ObjectViewEnd (void)
Concatena la matriz de objetos con la de vista y calcula la inversa de la matriz normal

En el siguiente ejemplo todos los objetos que dibujemos a continuación sufrirán las siguientes transformaciones:

  • Primero se girarán 30 grados sobre el eje Y.
  • Después se moverán 20 unidades sobre el eje X.
  • Luego se escalarán al doble de su tamaño sobre el eje Y
  • Por último se girarán 10 grados sobre el eje X y 60 sobre el eje Z

GRRLIB_ObjectViewBegin();
 
GRRLIB_ObjectViewRotate(0,30,0);
GRRLIB_ObjectViewTrans(0,20,0);
GRRLIB_ObjectViewScale(2,1,1);
GRRLIB_ObjectViewRotate(10,0,60);
 
GRRLIB_ObjectViewEnd();
 

FUNCIONES DE DIBUJO DE OBJETOS

Todo lo anterior está muy bien, pero no tiene ninguna utilidad si no dibujamos nada.

En GX todo se dibuja a base de triángulos o de Quads o cuadriláteros (que no son más que un par de triángulos unidos por su base). No existen las superficies curvas. Estas las deberemos simular a base de juntar triángulos.

En la figura podemos ver un ejemplo de un toro circular formado por triángulos.

 

Como esto es muy complicado para determinadas figuras, GRRLIB nos suministra una serie de funciones que nos permiten dibujar algunas de las formas geométricas más usuales.

Todas ellas se basan en repetir quads (figuras de cuatro lados) que, como hemos dicho antes, son al fin y al cabo parejas de triángulos. 

 

void GRRLIB_DrawCube (f32 size, bool filled, u32 col)

Dibuja un cubo de lado size. Esta es la figura más sencilla ya que cada una de sus caras son directamente quads.

En filled le diremos si las caras deben colorearse con el color col.

void GRRLIB_DrawCylinder (f32 r, f32 h, int d, bool filled, u32 col)

Dibuja un cilindro de radio r y altura h.  

En filled le diremos si las caras deben colorearse con el color col.

Si imaginamos que cortamos el cilindro en porciones como si fuera un pastel, en d indicaremos la densidad de las porciones.

El cuerpo del cilindro lo forma a partir de quads y la base circular con triángulos. Cuanto mayor sea la densidad que indiquemos en el parámetro d mayor será el realismo pero también aumentará la carga del procesador.  

void GRRLIB_DrawCone (f32 r, f32 h, int d, bool filled, u32 col)

Dibuja un cono de radio r y altura h.

En filled le diremos si las caras deben colorearse con el color col.

En d indicaremos la densidad de las porciones.

Tanto el cuerpo del cono como la base están formados por triángulos. De nuevo cuanto mayor sea la densidad que indiquemos en el parámetro d mejor será el resultado.

void GRRLIB_DrawSphere (f32 r, int lats, int longs, bool filled, u32 col)

Dibuja una esfera de radio r.

En filled le diremos si las caras deben colorearse con el color col.

El parámetro lats indica el número latitudes (líneas horizontales) de la esfera y longs indica el número de longitudes (líneas verticales).

Aquí toda la esfera está formada por quads. Sólo tenemos que imaginarnos un globo terraqueo con sus latitudes y longitudes.

void GRRLIB_DrawTorus (f32 r, f32 R, int nsides, int rings, bool filled, u32 col)

Dibuja un toro circular de radio menor r y radio mayor R. Un toro tiene el aspecto de un Donut, como el ejemplo de arriba. 

En filled le diremos si las caras deben colorearse con el color col.

El parámetro nsides indica el número de caras por anillo y rings indica el número de anillos.

FUNCIONES DE CONTROL DE LA ILUMINACIÓN

En GRRLIB se suministran las siguientes funciones de control de la iluminación.

La primera función define la luz ambiente, es decir la luz que no proviene de ningún lugar en concreto. Las zonas que no están alumbradas por ninguna otra luz adoptarán el color asignado por esta función.

void GRRLIB SetLightAmbient ( u32 ambientcolor )

La siguiente función nos permite definir hasta un total de 8 luces difusas (0..7). En este caso debemos indicar la posición, el color y lo que la luz se atenúa según se aleja de su origen.

void GRRLIB SetLightDiff ( u8 num, guVector pos, f32 distattn, f32 brightness, u32 lightcolor )
Configura los parámetros de una luz difusa
Parametros
num - Número de luz (0..7)
pos - Posición (x,y,z) de la luz difusa.
distattn - Atenuación por distancia
brightness - Brillo de la luz (0.0 .... 1.0)
lightcolor - Color en formato RGBA.

Para el caso de las luces especulares tendremos la función:

void GRRLIB SetLightSpec ( u8 num, guVector dir, f32 shy, u32 lightcolor, u32 speccolor )
Configura los parámetros de una luz especular
Parametros
num - Número de la luz (0..7).
dir - Dirección del reflejo (x,y,z).
shy -Brillo de reflejo.(4..254)
lightcolor - Color de la luz en formato RGBA.
speccolor - Color del reflejo en formato RGBA.

En dicha función definiremos la dirección del reflejo el brillo y los colores de la luz y del reflejo.

Por último GRRLIB dispone de una función para proveer a la escena de luces tipo foco:

void GRRLIB SetLightSpot ( u8 num, guVector pos, guVector lookat, f32 angAttn0, f32 angAttn1, f32 angAttn2, f32 distAttn0, f32 distAttn1, f32 distAttn2, u32 lightcolor )
Configura los parámetros de una luz de foco
Parametros
num - Número de luz
pos - Posición de la luz (x,y,z).
lookat - Punto al que enfoca la luz (x,y,z).
angAttn0 - Atenuación del cono factor 0
angAttn1 - Atenuación del cono factor 1
angAttn2 - Atenuación del cono factor 2
distAttn0 - Atenuación por distancia factor 0
distAttn1 - Atenuación por distancia factor 1
distAttn2 - Atenuación por distancia factor 2
lightcolor - Color de la luz en formato RGBA

En este caso, como nos encontramos ante una luz direccional, debemos decirle el punto que está siendo iluminado por el foco.

Además, en una luz de tipo foco tenemos tres conos concéntricos que denominamos zona 0, zona 1 y zona 2. Podemos configurar atenuaciones diferentes para cada zona. 

 

UN EJEMPLO PRÁCTICO

Para esta entrega, ya que es la primera que trata el tema de las 3D, empezaremos con un ejemplo sencillo. El ejemplo que vamos a ver es una modificación de uno de los ejemplos que vienen con el GRRLIB, al que le he añadido el uso de todas las funciones de dibujo de esta entrega que no estaban ya incluidas en el ejemplo.

Incluiremos el uso sólo dos funciones de manejo de luz para no sobrecargar la escena. El resto de tipos de luz los iremos viendo progresivamente en los ejemplos de las siguientes entregas.

El resultado del programa lo podéis ver en el vídeo de arriba. Básicamente consiste en dibujar las distintas formas que hemos visto girando sobre sí mismas y al mismo tiempo alrededor del centro de la pantalla.

Como es un programa sencillo no tenemos funciones auxiliares, por lo que pasaremos directamente a ver el contenido del main.

Empezaremos en el main declarando algunas variables auxiliares que nos serán necesarias en el programa.

f32 a = 0;
f32 offset = 1.5f;
f32 rotpas = 75.0f;

La variable a la utilizaremos como una variable de referencia para incrementar progresivamente los ángulos de rotación de las figuras.

La variable offset corresponde al radio de giro de las figuras respecto del centro de la pantalla y la variable rotpas se utiliza como desplazamiento del ángulo de cada figura con respecto a la anterior.

Seguidamente inicializamos librerías fuentes bitmap, etc.

    GRRLIB_Init();
    WPAD_Init();
 
    GRRLIB_texImg *tex_font = GRRLIB_LoadTexture(font);
    GRRLIB_InitTileSet(tex_font, 16, 16, 32);

GRRLIB posee una estructura llamada GRRLIB_Settings que nos permite asignar determinados parámetros de configuración en nuestro programa.

En concreto vamos a asignar el campo antialias a true. Este parámetro sirve para que los bordes de los objetos se suavicen y evitar los dientes de sierra.

GRRLIB_Settings.antialias = true;

Con GRRLIB_SetBackgroundColour asignamos el color de fondo a negro, y con GRRLIB_Camera3dSettings asignamos los valores de posición de la cámara y el punto hacia donde miramos.

    GRRLIB_SetBackgroundColour(0x00, 0x00, 0x00, 0xFF);
    GRRLIB_Camera3dSettings(0.0f,0.0f,5.0f, 0,1,0, 0,0,0);

En nuestro caso hemos situado la cámara en la posición (0,0,5) (o sea 5 unidades hacia nosotros en z), el vector arriba es (0, 1, 0), es decir estamos en posición vertical, y el punto hacia donde miramos es el origen de coordenadas.

Seguidamente entramos en el bucle principal y comenzamos leyendo la información de los mandos:

        GRRLIB_2dMode();
        WPAD_ScanPads();
        if(WPAD_ButtonsDown(0) & WPAD_BUTTON_HOME) exit(0);

Inmediatamente después cambiaremos a modo 3D, asignando como posición visible más cercana a la cámara 0.1 y la más lejana 1000. Asignamos también un ángulo de proyección de 45º, y diremos que trabajamos con normales y sin texturas:

        GRRLIB_3dMode(0.1,1000,45,0,1);

Las siguientes dos funciones nos sirven para asignar un luz ambiente mínima (de este color se verán las sombras) y una luz difusa de color blanco, situada en el punto (0,3,3), es decir ligeramente por delante y arriba de nosotros.

        GRRLIB_SetLightAmbient(0x111111FF);
        GRRLIB_SetLightDiff(0,(guVector){0.0f,3.0f,3.0f},20.0f,1.0f,0xFFFFFFFF);

Tras poner el modo 3d, pasaremos a utilizar las 5 funciones de dibujo de objetos que hemos visto en esta entrega.

Como dijimos antes, todas las figuras giran sobre sí mismas y sobre un centro de rotación por lo que cada bloque es muy similar al resto. Veremos sólo uno de ellos con detalle ya que el resto se interpretaran de forma muy similar.

        GRRLIB_ObjectViewBegin();
        GRRLIB_ObjectViewRotate(0,a*3,0);
        GRRLIB_ObjectViewTrans(0,offset,0);
        GRRLIB_ObjectViewRotate(a,a*3,a*2+2*rotpas);
        GRRLIB_ObjectViewEnd();
        GRRLIB_DrawCone(0.5f,1.2f,20,1,GRRLIB_NAVY);

Para poder combinar los dos tipos rotaciones sobre el objeto utilizaremos GRRLIB_ObjectViewBegin/End ya que para este caso no nos sirve ni GRRLIB_ObjectView ni GRRLIB_ObjectViewInv

Si no los trasladamos, todos los objetos comienzan en 0,0,0, por lo que la primera rotación la realizaremos con el objeto situado en ese punto. Al pasarle el valor a*3 al segundo parámetro de GRRLIB_ObjectViewRotate, le estamos diciendo que gire un ángulo de a*3 sobre el eje Y.

El resultado final de este primer giro será que el objeto girará sobre su eje Y a una velocidad de a*3.

Lo siguiente que realizamos es una traslación del objeto hasta una distancia offset del centro para fijar el radio de giro.

Ya alejados del centro aplicamos una rotación un poco más compleja sobre los tres ejes y a diferentes velocidades (a, a*3, a*2), resultando un efecto de una órbita que se va desplazando.

Para que no se solapen los objetos asignamos un desplazamiento en el giro correspondiente al eje z que es diferente para cada uno de los objetos (n*rotpas). Para el caso del ejemplo es 2*rotpas.

Una vez terminamos de dibujar las cinco figuras incrementamos la variable a y pasamos a modo 2D para mostrar el texto.

        a+=0.8;
        GRRLIB_2dMode();

Entonces mostraremos el texto y llamaremos a GRRLIB_Render para que se renderice la escena.

        GRRLIB_Printf((640-(16*29))/2, 20, tex_font, GRRLIB_SILVER, 1, "NUESTRO PRIMER PROGRAMA 3D");
        GRRLIB_Render();

Ya fuera del bucle liberamos la memoria y salimos del programa.

    GRRLIB_Exit(); // Be a good boy, clear the memory allocated by GRRLIB
    GRRLIB_FreeTexture(tex_font);
 
    exit(0);

El programa final queda como sigue:

#include <grrlib.h>
 
#include <stdlib.h>
#include <math.h>
#include <malloc.h>
#include <wiiuse/wpad.h>
#include "font.h"
 
// Colores RGBA
#define GRRLIB_BLACK   0x000000FF
#define GRRLIB_MAROON  0x800000FF
#define GRRLIB_GREEN   0x008000FF
#define GRRLIB_OLIVE   0x808000FF
#define GRRLIB_NAVY    0x000080FF
#define GRRLIB_PURPLE  0x800080FF
#define GRRLIB_TEAL    0x008080FF
#define GRRLIB_GRAY    0x808080FF
#define GRRLIB_SILVER  0xC0C0C0FF
#define GRRLIB_RED     0xFF0000FF
#define GRRLIB_LIME    0x00FF00FF
#define GRRLIB_YELLOW  0xFFFF00FF
#define GRRLIB_BLUE    0x0000FFFF
#define GRRLIB_FUCHSIA 0xFF00FFFF
#define GRRLIB_AQUA    0x00FFFFFF
#define GRRLIB_WHITE   0xFFFFFFFF
#define GRRLIB_LBLUE   0x5050FFFF
 
int main(void){
    f32 a = 0;
    f32 offset = 1.5f;
    f32 rotpas = 75.0f;
 
    GRRLIB_Init();
    WPAD_Init();
 
    GRRLIB_texImg *tex_font = GRRLIB_LoadTexture(font);
    GRRLIB_InitTileSet(tex_font, 16, 16, 32);
 
    GRRLIB_Settings.antialias = true;
 
    GRRLIB_SetBackgroundColour(0x00, 0x00, 0x00, 0xFF);
    GRRLIB_Camera3dSettings(0.0f,0.0f,5.0f, 0,1,0, 0,0,0);
 
 
    while(1) {
        GRRLIB_2dMode();
        WPAD_ScanPads();
        if(WPAD_ButtonsDown(0) & WPAD_BUTTON_HOME) exit(0);
 
 
        GRRLIB_3dMode(0.1,1000,45,0,1);
        GRRLIB_SetLightAmbient(0x111111FF);
        GRRLIB_SetLightDiff(0,(guVector){0.0f,3.0f,3.0f},20.0f,1.0f,0xFFFFFFFF);
 
 
        GRRLIB_ObjectViewBegin();
        GRRLIB_ObjectViewRotate(0,a*3,0);
        GRRLIB_ObjectViewTrans(0,offset,0);
        GRRLIB_ObjectViewRotate(a,a*3,a*2+1*rotpas);
        GRRLIB_ObjectViewEnd();
        GRRLIB_DrawCylinder(0.5f,1.0f,20,1,GRRLIB_RED);
 
 
        GRRLIB_ObjectViewBegin();
        GRRLIB_ObjectViewRotate(0,a*3,0);
        GRRLIB_ObjectViewTrans(0,offset,0);
        GRRLIB_ObjectViewRotate(a,a*3,a*2+2*rotpas);
        GRRLIB_ObjectViewEnd();
        GRRLIB_DrawCone(0.5f,1.2f,20,1,GRRLIB_NAVY);
 
        GRRLIB_ObjectViewBegin();
        GRRLIB_ObjectViewRotate(0,a*3,0);
        GRRLIB_ObjectViewTrans(0,offset,0);
        GRRLIB_ObjectViewRotate(a,a*3,a*2+3*rotpas);
        GRRLIB_ObjectViewEnd();
        GRRLIB_DrawSphere(0.5f,20,20,1,GRRLIB_YELLOW);
 
        GRRLIB_ObjectViewBegin();
        GRRLIB_ObjectViewRotate(0,a*3,0);
        GRRLIB_ObjectViewTrans(0,offset,0);
        GRRLIB_ObjectViewRotate(a,a*3,a*2+4*rotpas);
        GRRLIB_ObjectViewEnd();
        GRRLIB_DrawTorus(0.3f,0.5f,10,20,1,GRRLIB_PURPLE);
 
        GRRLIB_ObjectViewBegin();
        GRRLIB_ObjectViewRotate(0,a*3,0);
        GRRLIB_ObjectViewTrans(0,offset,0);
        GRRLIB_ObjectViewRotate(a,a*3,a*2+5*rotpas);
        GRRLIB_ObjectViewEnd();
        GRRLIB_DrawCube(0.8f,1,GRRLIB_LIME);
 
        a+=0.8;
        GRRLIB_2dMode();
 
        // Cambia a modo 2D para mostrar el texto
        GRRLIB_2dMode();
        GRRLIB_Printf((640-(16*29))/2, 20, tex_font, GRRLIB_SILVER, 1, "NUESTRO PRIMER PROGRAMA 3D");
        GRRLIB_Render();
    }
    GRRLIB_Exit(); // Be a good boy, clear the memory allocated by GRRLIB
    GRRLIB_FreeTexture(tex_font);
 
    exit(0);
}

Y con ésto ya hemos terminado un capítulo más de nuestro curso. En este caso se trata de nuestro primer programa en 3D.

Sé que este tipo de programa es bastante más trabajoso, pero los resultados finales son espectaculares, por lo que merece la pena el esfuerzo.

En el próximo capítulo veremos cómo manejar las texturas en nuestros gráficos en 3D y como realizar cualquier tipo de objeto, sin tener que limitarnos a los objetos que ya tenemos predefinidos.

4.3125
Tu voto: Ninguno Votos totales: 4.3 (32 votos)

Anuncios Google

Comentarios

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 martinezcanto

MIS PRIMEROS PINITOS

Buenas

 

Como ves sigo aplicando cosas de tus tutoriales, aunque sea saltando de uno a otro segun mis necesidades.

 

Ahora estoy haciendo mis primeros pinitos en iluminacion, ya que sigo sin conseguir dar el aspecto transparente a mis texturas, y ya en otra ocasion me comentaste que se tenia que hacer con iluminacion.

 

En principio al color de la textura en este caso el blanco le he cambiado los dos ultimos digitos para darle transparencia, he puesto por ejemplo 0xFFFFFF55. Conforme voy bajando los dos ultimos digitos la textura se difumina pero como desapareciendo, no se vuelve transparente. En el ejemplo que esto mirando tengo un cono texturado y dentro una esfera. Aunque con la transparencia aplicada no veo la esfera.

 

He puesto una luz ambiente 0xFFFFFFFF.

 

Si aplico la luz ambiente sola , se ve el cono con mucho brillo, brillo que se reduce al cambiar la transparencia de la textura, pero la bola interior no se ve.

 

He añadido una luz difusa con los siguientes datos

luz nº 0

posicion (0.0.25.0f)

ateniacion (10.0)

brillo (1.0)

color 0XFFFFFFFF

 

Con estos datos parece que todo se oscurece, incluso la figura casi desaparece completamente, he probado a cambiar posiones mas cercanas 0.0.10 o 0.0.5 pero apenas noto cambios. Incluso he modificado el parametro atenuacion agrandandolo 50.0 o disminuyendolo 5.0, pero no consigo practicamente nada, a veces incluso la figura se difumina algo mas...

 

Que mas puedo probar? por cierto el parametro atenuacion indica la posicion ultima de la luz? quiero decir, que quizas este equivacandome y al estar la figura ubicada en la posicion 0.0.0, la tenuacion tiene que ser negativa?

 

Como siempre agradecido por tus sabios consejos....

 

Saludos

 

 

 

 

 

 

 

Imagen de wilco2009

En el capítulo 10 tienes un

En el capítulo 10 tienes un ejemplo con trasparencias.

Tal y como se dice en ese capítulo, las trasparencias las conseguimos con el canal alfa del color de la figura que queremos hacer trasparente:

"Para el efecto de transparencia utilizaremos el canal alfa. Como vimos en la programación en 2D, el último componente del formato de color RGBA es el canal alfa. Si el valor del canal alfa es 0xFF el objeto será totalmente opaco, pero si reducimos ese valor conseguiremos un efecto de transparencia. Cuanto más bajo más transparente. "

Ten en cuenta que el orden en que dibujes los objetos respecto de las luces es también importante ya que si dibujas un objeto antes de definir una luz este no se verá afectado por la luz.

El tema de la atenuación no tiene que ver con la trasparencia, sino con lo deprisa que se atenúa la luz según se aleja del foco.

Observa bien el ejemplo del capítulo 10. Quizás puede ser una buena idea partir de este ejemplo e ir sustituyendo con las figuras que tu quieras para ir viendo el comportamiento.


Curso aplicado de GRRLIB - Parte 1 - Parte 2 - Parte 3 - Parte 4 - Parte 5 - Parte 6 - Parte 7 - Parte 8 - Parte 9 - Parte 10 - Parte 11

Profundizando en los mandos de la Wii - Parte 1 - Parte 2 - Parte 3  - Parte 4 (Balanceboard) - Parte 5 (Miis) 

Homebrew - WiiTriis -  LifemiiWii

GRRLIB

Bueno ya estoy de nuevo aquí dispuesto ha recuperar las partes del curso no leidas desde la 3.

Quiero felicitar el año a todo y también a wilco2009.

Aprovecho para darte las gracias por tú curso, magnifico en todo lo que he visto de pasada en cuanto a las 2d y 3d, ya me gustaría que me lo hubieran dado tan mascado cuando empecé con assembler a hacer gráficos en 3d.

También decirte que tengo algunos amigos enganchados a tú curso y tienen la intención de cuando este completo hacerse una versión impresa en tapa rústica y me han dicho de su parte que te de las gracias por el curso y que por favor llegues hasta el final y no lo dejes incompleto que tienen adicción a tú curso.

Por lo tanto te insto a acabar el curso y no abandonarlo en ningún momento y llegar hasta el final.

Un saludo a todos y feliz año aunque sea tarde para felicitar.

cjv99.

Imagen de wilco2009

De verdad que me encanta

De verdad que me encanta saber que hay gente que les gusta y que sigue mi trabajo. Al fin y al cabo esa es la recompensa de este esfuerzo, saber que hay gente que le es de utilidad.

Gracias a ti por tus palabras y dales también las gracias a tus amigos por seguir el curso con tanto interés.

Ahora mismo estoy preparando la 10ª entrega, pero no creo que de para muchas entregas más. Quizás podría alargarse un poco haciendo algunos capítulos con programas de ejemplo que asienten el contenido del curso.

De todas formas estoy descubriendo algunas lagunas en GRRLIB en lo que se refiere al manejo de luces. Pero como tenemos el código fuente, quizás con la ayuda del curso del maestro Hermes y con la colaboración de algunos de vosotros podamos llenar esos huecos que seguro que echaréis en falta cuando lleguéis a ese nivel.

 


Curso aplicado de GRRLIB - Parte 1 - Parte 2 - Parte 3 - Parte 4 - Parte 5 - Parte 6 - Parte 7 - Parte 8 - Parte 9 - Parte 10 - Parte 11

Profundizando en los mandos de la Wii - Parte 1 - Parte 2 - Parte 3  - Parte 4 (Balanceboard) - Parte 5 (Miis) 

Homebrew - WiiTriis -  LifemiiWii

Genial este curso de programación

Quiero felicitarte por estos tutoriales tan bien desarrollados y explicados ... Genial

Feliz Año Nuevo

Imagen de wilco2009

Feliz año y gracias a ti.

Feliz año y gracias a ti.

Imagen de wilco2009

Jajaja. Gracias Javi. A ver

Jajaja. Gracias Javi.

A ver si es verdad que publican una crítica en The Times.

Estos tutoriales son

Estos tutoriales son brutales! Te felicito enormemente!

Un saludo y feliz año nuevo!

Imagen de wilco2009

Gracias y feliz año a ti

Gracias y feliz año a ti tambien.

GRRLIB

Una pregunta, ¿vas a enseñar las durezas en las texturas?, ¿Enseñarás a usar filtros de suavizado de bordes npor ejemplos o incluso efectos de particulas,etc.. o como usar compresión de texturas? y GRRLIB acepta algún formato como 3ds o los multiples que exiten, sería como el limitado yeti 3d, etc..?, todo esto lo intento con bennugd.

Y está muy bien que tengamos disponible el código fuente de GRRLIB.

Un saludo.

cjv99.

Imagen de wilco2009

Entiendo que te refieres a

Entiendo que te refieres a bumpmaping.

Se que se puede, pero sinceramente no me he metido a investigar como se hace todavía.

Desde luego GRRLIB no está preparado para ello por lo que hay que abordarlo directamente desde GX con funciones como GX_SetTevIndBumpST o GX_SetTevIndBumpXYZ.

En cuanto a lo de aceptar algún formato de modelador 3D (como 3DS) te diré que lamentablemente no lo hace directamente, pero si conoces el formato de grabación de los archivos que quieras leer es relativamente sencillo hacerse uno mismo una biblioteca que lea objetos de ese tipo.

Yo en particular conozco por encima los archivos .obj del Blender y tengo hecha una utilidad al respecto que es posible que acabe sacando en alguno de los tutoriales.


Curso aplicado de GRRLIB - Parte 1 - Parte 2 - Parte 3 - Parte 4 - Parte 5 - Parte 6 - Parte 7 - Parte 8 - Parte 9 - Parte 10 - Parte 11

Profundizando en los mandos de la Wii - Parte 1 - Parte 2 - Parte 3  - Parte 4 (Balanceboard) - Parte 5 (Miis) 

Homebrew - WiiTriis -  LifemiiWii

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.