lunes, 30 de abril de 2007

Problema con los polígonos (III)

Sospecho que el problema puede ser de la librería que utilizo para programar en OpenGL ES, la "Vincent Mobile 3D Rendering Library". Es muy raro que los polígonos que no se pintan correctamente no sean siempre los miesmos y que solo lo hagan según el ángulo en que se gira el modelo. Si fuera problema del cálculo de las normales o de los triángulos que forman los polígonos cabe pensar que se verían mal siempre los mismos, y en cualquier posición. La forma ideal de comprobarlo sería utilizar otra librería alternativa, o solo como prueba usar la especificación completa de OpenGL (la que no es especial para dispositivos móviles).

Antes de eso, he estado mirando en los foros de la página de desarrollo de la librería Vincent Mobile, y he encontrado como segunda entrada del foro este comentario sin respuesta:

(...) right now i am runing a example on ZeusCMD using viccnet lib.
it address: http://www.zeuscmd.com/tutorials/opengles/22-Fog.php
it runs ok at v0.84 lib. but there are "white-noise" at the dege when the object rotate.
by the way,i used ppc emulator 2003. libGLES_CM.dll is directly copied from binary version.
He probado el ejemplo mencionado de la página de ZeusCMD y me sucede lo mismo, al girar el cubo se ve aparecer el ruido blanco que se menciona en el foro, pero solo sucede con la versión 1.0 de la librería; si se usa una algo más antigua (la 0.84) el cubo se muestra correctamente. Lo que he hecho a continuación es probar el avatar usando esa versión vieja de la librería, para ver que pasaba. El resultado es que el modelo sigue sin verse bien, incluso son más los polígonos que se pintan incorrectamente, también arbitrariamente según se gira el objeto.

Conclusión: Es un problema de la librería.

Opciones que tengo:

- Utilizar otra librería diferente, por ejemplo la "Hybrid's Rasteroid", que es una implementación comercial de OpenGL ES, que se puede utilizar de forma gratuita si no es con fines comerciales. El problema es que tendré que reconfigurar el entorno de desarrollo para utilizarla en lugar de la Vincent, y tendré que incorporar al programa otra librería, la GLUT-ES. Esta sirve para tareas auxiliares como creación de ventanas y captura del teclado y el ratón. Hasta ahora estaba usando funciones propias de la Vincent que se ocupaban de esas tareas, pero si la sustituyo ya no valdrán.

- La otra opción es ignorar por el momento el problema, seguir trabajando con un modelo más simple esperando que no pase lo mismo, y centrarme en el resto de aspectos del avatar, como la animación o el comportamiento.

jueves, 26 de abril de 2007

Problema con los polígonos (II)

Sigo con el problema que hace que no todos los polígonos se pinten correctamente, dejando huecos a través de los que se ven lo que hay detrás. En el caso del modelo con el que estoy trabajando casi da miedo, porque en la zona de la boca falla especialmente y según cómo se gira se puede ver toda la cabeza y el rostro correctamente, en la zona de la mandíbula toda la hilera de dientes, como una calavera.

He estado probando la solución que se me ocurrio en la entrada anterior, pero no ha funcionado. La idea era multiplicar todos los puntos por un factor fijo para que estuviesen más alejados entre sí y que no se solaparan unos con otros al hacer los cálculos, pero no ha resultado.

Primero he probado con la transformación de escalado, dando el mismo valor en los tres ejes, y no se han notado mejoras. Después he modificado la función que lée el modelo del fichero 3DS y según leía las coordenadas de los vértices las multiplicaba por ese valor fijo, pero tampoco ha mejorado, incluso creo que ha empeorado.

Además de hacer las operaciones anteriores también he tenido que modificar la posición de la cámara (alejándola) y ampliar el espacio del escenario alejando más los planos que lo delimitan, ya que al multiplicar las coordenadas aumentaba también el tamaño del objeto, hasta que se salía de la pantalla.

Parece pues claro que no es problema de que los vértices estén demasiado juntos, o de que las normales estén mal calculadas, ya que los polígonos que no se dibujan no son siempre los mismos, sino que varían según el ángulo en que se rota el modelo. Tendré que pensar en otra solución...

martes, 24 de abril de 2007

Problema con los polígonos

En la entrada anterior se quedó pendiente un problema al pintar los polígonos del modelo que ya había surgido en la representación con color plano pero que al aplicarle la textura se hace mucho más evidente. Cuando se gira la figura en la pantalla alrededor de cualquier eje en algunos momentos hay polígonos que no se pintan, dejando entonces ver los que hay detrás de ellos, cosa que no debería ser así.

He estado toda la tarde mirando y probando funciones de OpenGL-ES que controlan el culling y el depth-buffer. Lo primero sirve para evitar que se calculen los polígonos que no se van a ver en la pantalla (por ejemplo, los que quedan en la parte de atras de la cabeza) para que el proceso de representación sea más rápido. Pensé que quizás en alguno de ellos se calculaba mal la normal y por eso unas veces se pintaban y otras no, pero no era nada de eso. El depth-buffer es la representación interna que utiliza la librería para saber que objetos están delante de otros y cuales hay que pintar o cuales no. Tampoco solucioné nada mirándolo por ahí.

Casi al final se me ocurrió otra cosa. Observé que eso solo ocurre en las zonas en la que hay varias 'capas' de objetos, o que los polígonos están muy juntos, como por ejemplo: La boca y los dientes que están dentro; o los globos oculares y las cuencas que los rodean. Seguramente al estar en esos sitios los puntos muy juntos si los cálculos no son suficientemente precisos (y podrían no serlo, algunos dispositivos usan aritmética de coma fija en lugar de flotante) puede dar como resultado que los que están más atrás se solapen con los de más adelante.

Para solucionarlo, se podría multiplicar las coordenadas de los puntos por un factor fijo y de esa forma estarían más alejados unos de otros. Eso se puede hacer de forma muy sencilla con la transformación de cambio de escala glScalef y valores apropiados. Hice una prueba rápida y, efectivamente el efecto desapareció casi completamente, aunque con el lógico resultado de que el modelo no cabía en la pantalla. Es necesario hacer algo para que entre todo en el campo visual, como alejar el punto donde se sitúa la cámara, o similar.

lunes, 23 de abril de 2007

Representación con textura

Para pintar la textura es necesario asignar a cada vértice del modelo un punto de la textura, y de esa forma se aplica como se haría si se "empapelara" la jaula de alambre 3D con un papel pintado en 2D.

La información sobre las coordenadas de los puntos de la textura asociados a los vértices está contenida en el fichero .3DS, y es leída de él al cargar el modelo. Además de ello es necesario también cargar la imagen de la textura desde un fichero gráfico. En la página de ZeusCMD hay un tutorial sobre cómo hacerlo.

En él se explica además como sortear un pequeño problema que ya había tenido, que es el de las rutas absolutas de los ficheros. En el Windows Mobile/PocketPC si no se especifica la ruta completa del fichero que se quiere abrir toma por defecto el directorio raiz (/) en lugar de aquel en que reside el ejecutable, que es un comportamiento totalmente distinto al que estamos acostumbrados en otros sistemas. Lo que hay que hacer es tomar la ruta completa del fichero ejecutable (el parámetro argv[0] de la función main de C) y de ahí extraer el nombre del directorio, para luego ponerlo delante de cualquier otro archivo que se abra a partir de ese momento. Esto todavía no lo he implementado en mi programa, pero lo haré próximamente, de momento los fichero que necesita abrir (el .3DS del modelo, el .BMP de la textura, y el log) se guardan en el raiz, lo que es ciertamente poco limpio.

Después de incorporar la textura, el modelo queda así, mucho mejor:




Hay sin embargo algo que no está bien del todo, según cómo se gira el modelo hay polígonos que no se pintan bien. Esto ya lo había notado al hacer la representación con color plano y sombreado, pero es mucho más evidente al ponerle la textura:



A parte de que, según he visto ahora al poner aquí las fotos, se ve muy oscuro, hace falta más luz.

De ambas cosas me ocuparé en la próxima sesión de trabajo.

jueves, 19 de abril de 2007

Sobre el uso de código ajeno

En lo que llevo hecho de proyecto estoy usando código básicamente de dos sitios: La página ZeusCMD y la de Spacesimulator. El objetivo es explorar las posibilidades y posibles inconvenientes de desarrollar avatares con gráficos avanzados en 3D para dispositivos móviles como teléfonos. Al tratarse de un trabajo con fines educativos (lo estoy haciendo en la Universidad) y sin ánimo de lucro (al menos inmediato) no estoy incumpliendo los términos de uso que hay en las mencionadas páginas.

Si el resultado fuese después utilizado por terceros para obtener un beneficio económico no podrían hacer uso del código fuente generado. Además, el mismo contiene las cabeceras originales de sus autores donde se indican su procedencia y términos de uso.

Tengo pensado cuando termine el trabajo enviar un correo de agradecimiento a los autores de ambas páginas por la gran ayuda que han supuesto, seguro que lo apreciarán.

Representación con color sombreado

Para representar el modelo con zonas de más o menos luminosidad según la incidencia de la luz (modelo de iluiminación de Gouraud) es necesario calcular las normales de los planos de los triángulos que forman la superficie del modelo.

De nuevo consultando los tutoriales de spacesimulator.net he encontrado un código en C muy bien documentado donde se hacen todas las operaciones necesarias. Lo he incorporado al programa y adaptado para que funcione con lo que ya tenía hecho, y el resultado ha sido el esperado; el busto tiene ahora apariencia de volumen.

Lo siguiente será aplicarle una textura para que quede todavía mejor, y después anirmalo.

lunes, 16 de abril de 2007

Representación en color plano

Después de algún problema he conseguido por primera vez ver el modelo del avatar(una busto) representado en la pantalla del emulador.

El problema lo he tenido porque a la función glDrawElements que he utilizado para representarlo debía indicarle el tipo de dato de los indices de la lista de vértices de los polígonos. El tipo que le especificaba era GL_UNSIGNED_SHORT, pero el tipo que usaba el vector donde los almacenaba era int, por lo que cuando lo pintaba aparecía una forma que recordaba muy vagamente a una cabeza humana. En cuanto me he dado cuenta del fallo, simplemente cambiando el valor del tipo de los indices a unsigned short int se ha arreglado. Tras hacerlo, lo que ha aparecido en la pantalla sí que coincidía con lo que ya había visto con un visor de ficheros 3DS, solo que el color es totalmente liso, no hay sombras ni sensación de volumen. Para dárselo es necesario calcular las normales de los polígonos para que se pueda calcular el ángulo que forma el plano con respecto al punto de luz de la escena.

sábado, 14 de abril de 2007

Limitaciones

En los últimos días he estado adaptando el código fuente de un cargador de ficheros 3DS para cargar el modelo del avatar. El fichero contiene la información de, entre otras cosas, las coordenadas de los puntos y de los polígonos que forman el modelo. Los primeros vienen como una lista de valores (x, y, z) y los segundos (que son triángulos) como una lista de referencias a los vértices que los forman.

Al hacer el programa que se ocupa de todas estas cuestiones me he encontrado con las primeras limitaciones que se esperaba surgieran en un proyecto de este tipo sobre un dispositivo de capacidades reducidas.

- La primera limitación es propiamente del entorno de desarrollo. En la función que carga el fichero 3DS se hace una llamada para averiguar el tamaño del mismo (filelength) que no está implementada en las librerías del Embedded Visual C++. Otras funciones similares tampoco funcionaban y he tenido que buscar otra forma de averiguar esa información utilizando solo funciones estándares.

- Algo similar me ha ocurrido con otra función de C, freopen, que quería utilizar para mandar la salida estándar a un fichero de texto de forma que pueda escribir en él mensajes de debug que me permitan saber qué está haciendo la aplicación cuando no se ve nada en la pantalla.

- Otra limitación ha sido de capacidad de proceso del dispositivo que utilizo para las pruebas (una PDA emulada). La función que carga el fichero 3DS escribe en la salida estándar cada chunk de información que va leyendo. Al ser muy numerosos el fichero de texto donde se iban escribiendo alcanzaba rápidamente un tamaño considerable para las prestaciones del aparato (más de 8 Mb). La solución en este caso fue simple, se limitó la información de salida a la estrictamente necesaria para saber si era o no correcto lo que se estaba leyendo.

- La otra limitación que he encontrado de momento es de la propia especificación de OpenGL-ES. Los tutoriales que estaba consultando para sabe cómo dibujar el modelo eran para la librería OpenGL original, y algunas funciones no existen en la versión para dispositivos móviles. Ejemplos de estas son glBegin, glEnd, o glVertex3f, que se usaban para construir los polígonos (triángulos) a partir de los vértices. En su lugar use otra función, glDrawElements, que también está disponible en OpenGL aunque parece que no es muy utilizada, a pesar de que es muy práctica ya que con una simple llamada se construyen todos los triángulos especificando únicamente una lista de vértices.

A raiz de lo que ocurrió en el último caso, he empezado a consultar la guía de referencia oficial de OpenGL-ES cada vez que tengo que usar una función nueva.

martes, 10 de abril de 2007

Malla del avatar

Me han pasado los datos de la malla del personaje/avatar, en formato .3ds y .max

He estado mirando ambos formatos por encima y el .3DS (de 3D Studio) parece más interesante para nuestros propósitos. He instalado un visor para ver qué aspecto tiene el avatar, y ahora lo siguiente será hacer un programa que cargue y visualice ficheros de este tipo en el dispositivo móvil. De momento basta con que carge el modelo de jaula de alambre; y después se hará lo propio con las texturas.

He encontrado varias páginas donde se explica con diverso grados de complejidad la estructura de este formato de fichero. Una de ellas que me ha gustado es la de tutoriales de Spacesimulator.net, contiene mucha información sobre gráficos, OpenGL y su aplicación a los videojuegos, explicado paso a paso en varias lecciones.

Por cierto, sobre librerías SAPI (conversión de texto a voz) para PocketPC y similares, no he encontrado nada, al menos que sea más o menos abierto.

martes, 3 de abril de 2007

Siguientes pasos

Después de estar aprendiendo unas semanas a programar con OpenGL-ES y el entorno de desarrollo del Embedded Visual C++ llega el momento de implementar algo. Se comenzará cargando una malla de un modelo no demasiado complejo y se comprobará si el dispositivo es capaz de moverlo con suficiente soltura (rotar, trasladar, etc).

Después, se estudiará la forma de animarlo para que hable, para lo cual será necesario también mirar si existe alguna librería tipo SAPI para dispositivos móviles.