miércoles, 16 de mayo de 2012

Terrenos y Mapas de Alturas

music: L7 -"Pretend We're Dead"-

( NOTA: es probable que cambie las partes en las que digo píxel por téxel, dado que, aunque lo que voy a llamar Mapa de Alturas no es una textura propiamente dicha -no se mapea en ningún modelo 3D-, el concepto de píxel parece estar semánticamente más asociado con el monitor, mientras que el de téxel lo está más con una unidad atómica, indivisible, de una imagen. Aún no estoy seguro, de momento lo dejo como TO-DO ).

En los últimos días he estado desempolvando uno de los que fueron mis programas favoritos del Máster. Con él se genera la representación visual de un terreno a partir de un Mapa de Alturas, esto es, una imagen de escala de grises (o como es mi caso, una imagen RGB a la que hemos "desatudado" el color) cuyos valores de gris (color) equivalen a una determinada "altura" en un mundo 3D; esto es, a un determinado valor positivo a la coordenada Y de cada uno de los vértices que conforman el terreno.

Así, como valores extremos del rango:

-Un pixel en el mapa de alturas que tenga un color Negro (R:0, G:0, B:0) otorgará un 0.0 como valor a la coordenada Y del vértice correspondiente a ese píxel en el terreno, vamos, en el mundo 3D.

-Y un pixel en el mapa de alturas que tenga un color Blanco (R:255, G:255, B:255) otorgará un valor máximo como valor a la coordenada Y del vértice correspondiente.

Para preparar el Mapa de Alturas se parte de una imagen a la que, mediante Photoshop , hemos quitado el color, retocado a nuestro gusto y por último escalado a un tamaño de 128x128 píxeles. La guardaremos empleando el formato Photoshop RAW (*.RAW), que no debe confundirse con imágenes RAW de cámara digital (so pena de perder un montón de días haciéndote el lío padre como me pasó a mí). :P A todo esto, debo comprobar si el nuevo GIMP 2.8 también tiene soporte para abrir imágenes Photoshop RAW.

No necesitaremos que el fichero posea una cabecera que contenga el ancho y alto de la imagen en píxeles, pero justo por ello sí tendremos que ser nosotros los que tengamos que indicar al "Objeto Terreno" el tamaño del Mapa de Alturas que le pasamos  (que como ya hemos dicho, será 128 píxeles de ancho y de largo).

A partir del Mapa de Alturas tendremos en el mundo 3D una malla poligonal cuadrada de 128x128 = 16384 vértices, dividida en (128 - 1) * (128 - 1) = 16129 sectores cuadrados contiguos, como una rejilla. Pero dado que la unidad atómica que nos interesa para renderizar es el triángulo -y no el cuadrado-, dividimos cada sector en dos triángulos rectángulos que comparten la hipotenusa. El número total de triángulos será el doble que el de sectores, esto es, 32258. : )

Por último, se crea un Vertex Buffer y un Index Buffer, y las coordenadas X,Y y Z son calculadas para cada vértice e introducidas, con la ayuda del Index Buffer, en el Vertex Buffer.

Aquí es donde entra en juego al Mapa de Alturas. Como anteriormente se ha mencionado la coordenada Y del actual vértice (del aquel que hay que generar actualmente las coordenadas, vamos) se toma consultando el valor de color del píxel correspondiente en el Mapa de Alturas; en concreto, se consultará la componente de color G de dicho píxel. Las coordenadas X y Z se generan a partir de un valor de espaciado entre sectores (un valor fijo, actualmente es 16) y de unos Offset en X y en Z: el offset en X es la mitad del ancho del Mapa de Alturas, y el Z la mitad del alto (para el caso, ambos valdrán 64).

Así, si pensamos en una rejilla o matriz 2D a cuyas filas accediéramos mediantes en índice i y a cuyas columnas accediéramos mediante el índice j, las coordenadas X,Y,Z para cada vértice 3D [i][j] se calcularían así:

Vertice3DActual[i][j].X = (i * EspaciadoEntreSectores) - (Offset_X * EspaciadoEntreSectores)
Vertice3DActual[i][j].Y = MapaAlturas[i][j].Componente_G
Vertice3DActual[i][j].Z = (j * EspaciadoEntreSectores) - (Offset_Z * EspaciadoEntreSectores)

Tras haber calculado las coordenadas de todos lo vértices se calculan las normales para los tres vértices de cada triángulo, los índices para el Index Buffer, se sitúa una cámara libre dotada de un movimiento básico de 6 grados de libertad y... estos son los resultados.




La flecha roja indicaría a grandes rasgos la posición y orientación de la cámara. Efectivamente, la última escena es un poquito "marciana". ; )

Hasta otra. :P

No hay comentarios:

Publicar un comentario