Allegro también contiene algunas funciones de ayuda de 3d para manipular vectores, construir o usar matrices de transformación, y hacer proyecciones de perspectiva de un espacio 3d en la pantalla. Estas funciones no son, y nunca serán, una librería 3d total (mi objetivo es dar rutinas de soporte genéricas, y no código gráfico muy especializado :-) pero estas funciones pueden serle útiles para desarrollar su propio código 3d.
Allegro usa el sistema de coordenadas de mano derecha, es decir, si apunta con el dedo gordo de su mano derecha al eje positivo x, y con el índice al eje positivo y, su dedo corazón apuntará en la dirección positiva del eje z. Esto también significa que para las rotaciones, si hace que el dedo gordo de su mano derecha siga el eje de rotación, sus dedos se curvarán en la dirección positiva de la rotación.
Hay dos versiones de todas las funciones matemáticas de 3d: una usando aritmética de punto fijo, y la otra usando coma flotante. La sintaxis para ambas es idéntica, pero las funciones y estructuras de coma flotante tienen el sufijo '_f'. Ejemplo: la función cross_product() de punto fijo tiene el equivalente de coma flotante en cross_product_f(). Si está programando en C++, Allegro también sobrecarga estas funciones para que las use con la clase "fija".
La transformación 3d se realiza modelando una matriz. Esta es un array de 4x4 números que pueden ser multiplicados con un punto 3d para producir otro punto 3d. Si ponemos los valores correctos en la matriz, podemos usarla para varias operaciones como translación, rotación y escalado. El truco consiste en que puede multiplicar dos matrices para producir una tercera, y esta tendrá el mismo efecto en los puntos 3d que aplicando las dos matrices originales una después de la otra. Por ejemplo, si tiene una matriz que rota un punto, y otra que lo mueve en una dirección, puede combinarlas para producir una matriz que realizara la rotación y translación en un paso. Puede crear transformaciones extremadamente complejas de este modo, teniendo que multiplicar cada punto 3d por una sola matriz.
Allegro hace trampa al implementar la estructura de la matriz. La rotación y el escalado de un punto 3d puede ser realizado con una matriz simple de 3x3, pero para trasladar el punto y proyectarlo en la pantalla, la matriz tiene que ser extendida a 4x4, y el punto extendido a una cuarta dimensión, al añadir una coordenada extra: w=1. Esto es algo malo en términos de eficiencia, pero afortunadamente, es posible realizar una optimización. Dada la siguiente matriz 4x4:
se puede observar un patrón de qué partes hacen qué. La rejilla 3x3 de arriba a la izquierda implementa la rotación y el escalado. Los tres valores de arriba de la cuarta columna (d, h y l) implementan la translación, y siempre y cuando la matriz sea usada sólo para transformaciones afines, m, n y o serán siempre cero y p siempre será 1. Si no sabe que significa 'afín', lea a Foley & Van Damme: básicamente cubre el escalado, la translación y rotación del objeto pero no la proyección. Ya que Allegro usa una función aparte para la proyección, las funciones de matriz sólo tienen que servir para la transformación afín, lo que significa que no hay que guardar la fila inferior de la matriz. Allegro asume que esta contiene (0,0,0,1), y por eso optimiza las funciones de manipulación de matrices.( a, b, c, d ) ( e, f, g, h ) ( i, j, k, l ) ( m, n, o, p )
Las matrices se almacenan en estructuras:
extern MATRIX identity_matrix;typedef struct MATRIX - matriz de punto fijo { fixed v[3][3]; - componente 3x3 de escalado y rotación fixed t[3]; - componente x/y/z de translación } MATRIX; typedef struct MATRIX_f - matriz de coma flotante { float v[3][3]; - componente 3x3 de escalado y rotación float t[3]; - componente x/y/z de translación } MATRIX_f
void get_translation_matrix(MATRIX *m, fixed x, fixed y, fixed z);
void get_translation_matrix_f(MATRIX_f *m, float x, float y, float z);
Construye una matriz de translación, guardándola en m. Si se aplica a un
punto (px, py, pz), esta matriz producirá el punto (px+x, py+y, pz+z). En
otras palabras: mueve las cosas.
Relacionado con: apply_matrix, get_transformation_matrix, qtranslate_matrix.void get_scaling_matrix(MATRIX *m, fixed x, fixed y, fixed z);
Relacionado con: apply_matrix, get_transformation_matrix, qscale_matrix.void get_x_rotate_matrix(MATRIX *m, fixed r);
Relacionado con: apply_matrix, get_rotation_matrix, get_y_rotate_matrix, get_z_rotate_matrix.void get_y_rotate_matrix(MATRIX *m, fixed r);
Relacionado con: apply_matrix, get_rotation_matrix, get_x_rotate_matrix, get_z_rotate_matrix.void get_z_rotate_matrix(MATRIX *m, fixed r);
Relacionado con: apply_matrix, get_rotation_matrix, get_x_rotate_matrix, get_y_rotate_matrix.void get_rotation_matrix(MATRIX *m, fixed x, fixed y, fixed z);
Relacionado con: apply_matrix, get_transformation_matrix, get_vector_rotation_matrix, get_align_matrix, get_x_rotate_matrix, get_y_rotate_matrix, get_z_rotate_matrix.void get_align_matrix(MATRIX *m, fixed xfront, yfront, zfront, fixed xup, fixed yup, fixed zup);
Relacionado con: apply_matrix, get_camera_matrix.void get_align_matrix_f(MATRIX *m, float xfront, yfront, zfront, float xup, yup, zup);
Relacionado con: get_align_matrix.void get_vector_rotation_matrix(MATRIX *m, fixed x, y, z, fixed a);
Relacionado con: apply_matrix, get_rotation_matrix, get_align_matrix.void get_transformation_matrix(MATRIX *m, fixed scale, fixed xrot, yrot, zrot, x, y, z);
Relacionado con: apply_matrix, get_rotation_matrix, get_scaling_matrix, get_translation_matrix.void get_transformation_matrix_f(MATRIX_f *m, float scale, float xrot, yrot, zrot, x, y, z);
Relacionado con: get_transformation_matrix.void get_camera_matrix(MATRIX *m, fixed x, y, z, xfront, yfront, zfront, fixed xup, yup, zup, fov, aspect);
Relacionado con: apply_matrix, get_align_matrix.void get_camera_matrix_f(MATRIX_f *m, float x, y, z, xfront, yfront,zfront, float xup, yup, zup, fov, aspect);
Relacionado con: get_camera_matrix.void qtranslate_matrix(MATRIX *m, fixed x, fixed y, fixed z);
Relacionado con: get_translation_matrix.void qscale_matrix(MATRIX *m, fixed scale);
Relacionado con: get_scaling_matrix.void matrix_mul(const MATRIX *m1, MATRIX *m2, MATRIX *out);
Relacionado con: apply_matrix.fixed vector_length(fixed x, fixed y, fixed z);
Relacionado con: normalize_vector.void normalize_vector(fixed *x, fixed *y, fixed *z);
Relacionado con: vector_length, dot_product, cross_product.fixed dot_product(fixed x1, y1, z1, x2, y2, z2);
Relacionado con: cross_product, normalize_vector.void cross_product(fixed x1, y1, z1, x2, y2, z2, *xout, *yout, *zout);
Relacionado con: dot_product, polygon_z_normal, normalize_vector.fixed polygon_z_normal(const V3D *v1, V3D *v2, V3D *v3);
Relacionado con: cross_product.void apply_matrix(const MATRIX *m, fixed x, y, z, *xout, *yout, *zout);
Relacionado con: matrix_mul.void set_projection_viewport(int x, int y, int w, int h);
Relacionado con: persp_project.void persp_project(fixed x, y, z, *xout, *yout);
Relacionado con: set_projection_viewport.