Programación en Lenguaje Ensamblador

-El Verdadero Lenguaje de las Máquinas-

Programación Gráfica y la Rotación de Objetos

Un Programador de Videojuegos no le teme a las Matemáticas

La rotación es la marca que identifica a las verdaderas gráficas vectoriales y que las distingue de los humildes sprites. En la época de los 8 bits cuando las multiplicaciones eran demasiado tardadas cuando no imposibles de hacer los juegos simulaban rotaciones por medio de animaciones cíclicas de sprites. Mas tarde cuando la multiplicación de enteros estuvo disponible en las consolas fue posible rotar y escalar sprites con una técnica llamada matemáticas de punto fijo. No fue sino hasta la época en la que se implemento el procesamiento de punto flotante que las computadoras pudieron hacer auténticos cálculos trigonométricos que las rotaciones no se vieron realistas. En esta entrada se va a ver todo lo que un interesado en la programación gráfica debe de saber para implementar rotaciones vectoriales.

En la primera imagen se muestra una entidad metemática muy especial conocida como el Círculo Unitario. Se trata de un círculo con centro en el origen y un radio de una unidad. El radio como ya han de saber es la distancia del centro del círculo a cualquier parte de este y se mantiene constante. Supongo que todos ustedes ya saben todo esto así que pasaré a lo siguiente. Si examinamos el círculo veremos una flecha negra inclinada. Esa flecha es un vector cuya longitud es una unidad, y proyecta sombras en los ejes coordenados (en rojo) esa sombras son las componentes del vector radio o como vimos en la entrada anterior los pasos que hay que dar a partir del origen en dirección de cada uno de los ejes para alcanzar la punta del vector. O explicado con abejitas y flores, el vector radio es hijo del vector X y el vector Y en las proporciones que indican las sombras.

Pero aún hay mas, si tomamos el radio y las sombras que este proyecta en los ejes coordenados podemos formar un triángulo. Para ser exactos un triángulo rectángulo. El símbolo redondo partido por la mitad que recuerda al logotipo de una marca de autos japoneses significa para nosotros ángulo. El ángulo va desde el eje horizontal X hasta el vector radio siempre en sentido contrario a las manecillas del reloj. Este ángulo se mide en radianes y no en grados. Finalmente, las sombras o componentes vectoriales que conforman el lado horizontal y vertical del rectángulo pueden tomar cualquier valor entre -1 y 1 dependiendo del lugar hacia donde apunte el vector radio. Estos dos lados son conocidos en matemáticas como Seno y Coseno.

Hay otra cosa interesante relacionada con el vector radio y las funciones Seno y Coseno. Como ya dije, estos 3 elementos forman un triángulo rectángulo donde, si tomamos como referencia el vértice o esquina donde se encuentra el ángulo (el del simbolo que parece marca japonesa de automóviles). Para los que no recuerdan el teorema de pitágoras es el que dice que el cuadrado de la hipotenusa es igual a la suma del cuadrado de los dos catetos. La hipotenusa es el lado inclinado que es también el mas largo. Los catetos son los lados cortos horizontales y verticales. El cateto adyacente es el que está pegado al ángulo que estamos midiendo y el cateto opuesto es el que le queda de frente. En un círculo unitario la hipotenusa es también el vector radio, el cateto adjacente es el Coseno del angulo y componente X del vector. Mientras que el cateto opuesto es el Seno del ángulo y componente Y del vector radio. Sencillo.

El cateto adyacente es el Coseno, el cateto opuesto es el Seno y la hipotenusa es el propio vector que siempre va a medir una unidad en el círculo unitario. De este modo, siguiendo el viejo y muy conocido teorema de Pitágoras podemos obtener algo llamado identidad trigonométrica fundamental que dice que si elevamos al cuadrado el Seno y el Coseno de un ángulo cualquiera y luego los sumamos el resultado siempre va a ser igual a 1. Eso en notación matemática nos da (Sen(x))^2 + (Cos(x))^2 = 1. Por cierto, el viejo teorema de Pitágoras es muy importante en programación gráfica y juegos 3D en general, pues se usa mucho para medir distancias y hacer cálculos de iluminación.

Aquí es donde vamos a usar la GPU de mano que es nuestra calculadora de bolsillo y vamos a buscar unos botones marcados como SIN y COS. Nos aseguramos de que la calculadora esté ajustada en radianes y nos ponemos a enviarle a estas funciones los números que queramos. El resultado siempra va a estar entre -1 y 1. Esto es porque seno y coseno son las componentes del vector radio de un círculo unitario y estas se mueven de -1 a 1 conforme la flecha apunta a cualquier parte del círculo como si fuera un reloj. El ángulo en radianes nos indica hacia donde la flecha negra se encuentra apuntando. Ahora vamos a ver que demonios es un radian.

Pizzas y Radianes

El radian se usa para medir el arco de las circunferencias. En lugar de usar expresiones como ‘medio círculo’ en matemáticas usamos el radián. Un radián es la longitud de arco que mide lo mismo que el radio del círculo. Si recuerdan sus clases básicas de geometría recordarán que había un número llamado Pi que era mas o menos 3.1416. Ese número es la proporción entre el diámetro y la longitud del perímetro del círculo. Y como el diámetro mide el doble del radio, necesitamos 2*Pi o mas o menos 6.1832 radianes para igualar la circunferencia total del círculo. Para entender mejor el valor de los radianes voy a mostrar una interesante propiedad a la que llamo la propiedad de la rebanada de pizza y que se muestra en la imagen junto a este párrafo.

La propiedad de la rebanada de pizza dice que si tenemos una pizza de radio R y le cortamos una rebanada tan amplia como ese mismo radio R, el área total de esa rebanada de pizza será igual a la de la mitad de una pizza cuadrada de lado R

Lo anterior se demuestra en la segunda imagen. El área de un círculo de radio R es Pi multiplicado por el cuadrado del radio o Pi*R^2 y el perímetro es el doble del radio multiplicado por Pi o 2*Pi*R. Si ambas expresiones las dividimos simultaneamente por 2*Pi obtenemos la extensión del arco de longitud R y el area de la rebanada de pizza cuyo lado redondo es tan largo como R. Obtenemos un perímetro de R y un área de (1/2)(R^2). En fin, toda esta explicación es solo para demostrar la importancia que tienen los radianes como medida de los ángulos a la hora de hacer rotaciones. También sirven para cuando trabajamos con arcos o círculos incompletos.

Y hablando de arcos incompletos. Como la medida de un radian es muy poco intuitiva para los seres humanos. A la hora de trabajar con ellos siempre se manejan en múltiplos de Pi. La proporción mas importante es la siguiente: 3.1416 radianes equivalen a medio círculo. O mas exacto Pi*radian = 1/2 circulo. A partir de esta proporción se obtienen todas las demás medidas intuitivas de la circunferencia:

2*Pi*r Círculo Completo
Pi*r Medio Círculo
(1/2)*Pi*r Cuarto de Círculo
(1/4)*Pi*r Octavo de Círculo

Otro consejo: Como tanto Pi como relación del radian con la circunferencia no son lo que se dice muy amistosos. Lo que la gente hace es manejar una unidad híbrida conocida en el bajo mundo como el PiRadian. Un PiRadian como ya se dijo equivale a medio círculo. Sin necesidad de usar decimales raros.

Fórmulas de Rotación Vectorial

Bueno, ya le di muchas vueltas al asunto y no hemos visto nada de rotaciones. Supongamos que queremos hacer una función que reciba como entrada un vector y un ángulo en radianes. Digamos que queremos rotar el vector R un cuarto de vuelta. En radianes un cuarto de vuelta es Pi/2 o aproximadamente 1.5708. Las fórmulas para hacer esta rotación se muestran en la última imagen de la entrada. El error mas común en las rotaciones es sobreescribir los mismos valores a la mitad del cálculo. Para evitar esto los valores iniciales del vector se guardan como ‘valores viejos’ y a partir de ellos se calculan los valores nuevos. Una vez hecho el cálculo pueden desecharse los valores viejos o ser sobreescritos.


En cuanto al origen de las fórmulas, podría explicarles de donde salieron pero esto sería muy largo y tedioso. Si son tan nerds como para querer saberlo vayan y busquen en su libro de trigonometría de la escuela. Pueden encontrar estas fórmulas y su explicación mas profunda en el tema de suma de ángulos y sus propiedades trigonométricas. Por cierto, estas rotaciones son siempre respecto a un plano perpendicular a los ejes coordenados tridimensionales. Piensen en el piso y las paredes de su cuarto. Es posible hacer que un objeto rote respecto a cualquier eje en el espacio por medio de otras fórmulas que comentaré en el futuro. Proceso que puede aplicarse por ejemplo en un cañon que le apunta al jugador mientras este se mueve por el campo de batalla.

Tablas Precalculadas y Grados de 8 Bits

Ahora que saben como se rotan vectores dado un ángulo en radianes es hora de que les revele un par de optimizaciones. La primera es la de usar grados de 8 bits. Todo el mundo acostumbra dividir una circunferencia en 360 grados. Pero si nosotros la dividimos en 256 grados podemos obtener muchas ventajas. La mas obvia sería usar máscaras de bits para hacer medias vueltas, o cuartos de vueltas o mantener girando un objeto incrementando indefinidamente el indicador de grados de 8 bits y combinando este valor con una máscara AND. Para obtener grados de 8 bits dividimos la circunferencia que mide 2*Pi entre 256, o lo que es lo mismo Pi/128 que nos da un total aproximado de 0.02454 radianes por grado de 8 bits.

La segunda optimización depende directamente de la anterior. Si dividimos la circunferencia en 256 partes podemos calcular una sola vez el valor del Seno y el Coseno de cada uno de esos 256 grados de 8 bits una única vez al inicializar el programa y guardar los resultados en 2 arrays de punto flotante. De ese modo cuando queramos obtener el seno y el coseno de un grado determinado solo usaríamos ese número como índice del array y convertiríamos un cálculo trigonométrico en una sencilla multiplicación. Digamos por ejemplo que queremos rotar un vector un cuarto de vuelta. En el sistema de grados de 8 bits un cuarto de vuelta sería 32. Tomamos el valor en la posición 32 de las tablas y los usamos en las fórmulas de rotación de la última imagen. Esto también sirve para evitar las operaciones de stack en una FPU de Intel. Solo habría que cargar las componentes vectoriales a la FPU y pasarle la posición de memoria de la tabla precalculada, multiplicar y escribir el resultado en la memoria.

En fin, luego de toda esta explicación pueden haber sucedido dos cosas, una es que decidieran renunciar a la programación gráfica por miedo a las matemáticas y otra es que hayan puesto cara del ‘MeGusta’. En la siguiente entrada vamos a ver como se aplican la traslación, rotación y escala de vectores para animar modelos vectoriales en el espacio tridimensional. Recuerden que hasta ahora no hemos tenido necesidad de otra cosa aparte de libreta de cuadrícula, lápiz con borrador y una calculadora escolar

Anuncios

octubre 5, 2011 - Posted by | Uncategorized | , , ,

2 comentarios »

  1. Muy bueno, espero que después de la teoría se haga un par de ejemplos.

    Saludos.
    StrongCod3r.

    Comentario por StrongCod3r | octubre 5, 2011 | Responder

    • Si todo sale bien espero llegar al menos a la proyeccion 3D en el plano y detalle de superficies antes de que termine el 2011

      Comentario por asm86 | octubre 5, 2011 | Responder


Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: