Artículos en profundidad sobre la tecnología que da forma al futuro.

Un país entero en voxels: pipeline de geodatos abiertos

Cómo un pipeline de voxels convirtió los datos abiertos de Suiza en un mundo 1:1 de Minecraft, con lecciones sobre teselas y niveles de detalle.

Valle alpino estilo voxel con un glaciar en bloques y picos montañosos cúbicos escalonados.
Un bloque, un metro: un país entero reconstruido en voxels a partir de geodatos abiertos del gobierno.

En algún rincón del portal de datos abiertos del gobierno suizo hay un mapa de alturas de la cara norte del Eiger, muestreado con tanto detalle que casi se puede sentir la roca. Un desarrollador alimentó archivos así a un pipeline de voxels y lanzó el resultado como producto jugable: toda Suiza como un mundo de Minecraft 1:1, donde cada bloque es un metro y el Matterhorn tiene exactamente la altura y la pendiente de la realidad. La descarga pesa 24 GB comprimida, y la región de muestra gratuita por sí sola cubre unos 2.400 km². La ingeniería que hay debajo (teselado, niveles de detalle, generación perezosa) es una clase magistral para mover conjuntos de datos espaciales enormes sin que todo arda.

El problema: un país en voxels no cabe en memoria

Hagamos cuentas. Suiza abarca 41.285 km². A un bloque por metro cuadrado, son 41.300 millones de columnas de superficie antes de cavar un solo agujero. Si cada columna tiene una profundidad modesta de 100 bloques (piedra, tierra, lecho de lago), llegamos a cuatro billones de bloques. Incluso a un byte por bloque, son cuatro terabytes de geometría cruda. Y, sin embargo, el mundo distribuido se comprime en una descarga de 24 GB, lo que dice algo importante: casi nada de esa geometría se guarda como geometría. Se guarda como receta.

El eje vertical también rompe cosas. Minecraft de serie limita el mundo a 384 bloques de altura de construcción. Suiza va desde los 193 m sobre el nivel del mar en el Lago Maggiore hasta los 4.634 m del Dufourspitze: un desnivel de 4.441 m, más de once veces el límite de serie, antes de que nadie haya cavado una mina. Por eso el mundo necesita Cubic Chunks, un mod que sustituye el almacenamiento por columnas de Minecraft por cubos de 16×16×16 apilados todo lo alto que haga falta. Ese mod solo funciona de forma estable en Minecraft Java 1.12.2, y por eso un proyecto que se publica hoy fija una versión del juego de hace años.

La memoria es la tercera pared. Construir bloques a partir de datos de origen la primera vez que un jugador visita una zona consume mucha computación: el proyecto pide 16 GB de RAM como mínimo y se prueba en equipos como un Ryzen 7 7800X3D con 32 GB. Quien haya peleado con presupuestos de streaming en juegos o en GIS reconocerá la forma del problema. Es la misma priorización que haces cuando tu GPU se queda sin VRAM: no puedes retenerlo todo, así que te vuelves muy bueno decidiendo qué retener en este momento.

Primer intento fallido: hornear todo el mundo por adelantado

El enfoque obvio es un único trabajo offline: leer los geodatos, generar archivos de región de Minecraft (el formato Anvil guarda el mundo en regiones de 512×512 bloques), comprimir el resultado y distribuirlo. Dinamarca hizo algo parecido en 2014, cuando la Agencia Danesa de Datos Geográficos publicó todo el país como mapa de Minecraft. Fue una demo emblemática de datos abiertos y demostró que un mapa del tamaño de un país era posible. Entonces, ¿por qué no ese camino?

Porque hornear por adelantado tiene costes estructurales que crecen con la ambición. Cada bloque de cada región debe generarse, escribirse y comprimirse antes de que alguien juegue, lo que convierte cada actualización de datos en una reconstrucción completa más el reenvío de decenas de gigabytes. Cada jugador descarga montañas de terreno que nunca visitará, y la mayor parte de los 41.000 km² no la visitará nadie. Lo peor: un mundo horneado se congela en la instantánea de datos en el momento en que lo publicas. Es un artefacto de escritura única. No puede mejorar sin regenerar y redistribuir todo, y tus usuarios vuelven a descargar el planeta entero.

Segundo intento fallido: un único mapa de alturas a una resolución

La segunda tentación es la normalización: convertir cada entrada en un único ráster global a una sola resolución, para que el pipeline tenga exactamente una ruta de código. Dentro de Suiza tienes swissALTI3D, un modelo de terreno de alta resolución. Más allá de la frontera tienes el DEM Copernicus GLO-30: un punto de elevación cada 30 metros. Si remuestreas todo a 30 m por uniformidad, la cara norte del Eiger se convierte en un montón de arena escalonado. Si remuestreas todo a la resolución más fina disponible, el almacenamiento y el procesamiento explotan, y las regiones fronterizas siguen sin datos reales: solo has sobremuestreado tu ignorancia.

La heterogeneidad golpea la semántica tanto como la elevación. swissBUILDINGS3D cubre Suiza, así que el generador puede levantar edificios de voxels simplificados sobre huellas reales, pero solo dentro del país. Cruza la frontera cerca de Ginebra y no hay capa de edificios en absoluto, así que el pipeline aplica la única alternativa sensata: planta árboles donde deberían ir casas. El agua necesita su propia fuente (swissBATHY3D para los fondos de lagos), al igual que los glaciares, los bosques y los viñedos. No existe un único archivo de entrada. En los geodatos, nunca lo hay.

La lección se generaliza mucho más allá de Minecraft: la resolución es un metadato por tesela, no una constante global. Un pipeline que asume entradas uniformes o desperdicia fidelidad o la inventa, y la fidelidad inventada es peor que una falta de detalle honesta, porque desde dentro nadie puede notar la diferencia.

Una cuadrícula de teselas de mapa que fluye por un embudo y emerge como un paisaje de voxels ensamblado.
La inversión clave: mantén los datos como teselas y recetas, y ensambla bloques solo donde alguien realmente vaya.

Lo que sí funciona: un pipeline por teselas con generación perezosa

El proyecto suizo funciona porque invierte el instinto de hornearlo todo. No descargas un mundo terminado; descargas un paquete de mundo (geodatos preprocesados más un generador a medida) y el juego construye los bloques la primera vez que visitas un lugar. Una primera visita a una zona nueva tarda unos minutos de trabajo; después queda en caché como cualquier otro mundo de Minecraft. La computación se paga por visita en vez de por adelantado, y nunca generas terreno que nadie pise. La tesela es la unidad de todo: almacenamiento, caché, generación y fallos.

El teselado está anclado a LV95, el sistema oficial de coordenadas de levantamiento de Suiza. Cada tesela registra qué conjuntos de datos la cubren y con qué resolución, y convertir coordenadas de levantamiento a coordenadas de bloque es una simple transformación afín. El proyecto publica incluso la fórmula para que puedas tomar coordenadas del visor cartográfico nacional y teletransportarte al punto correspondiente dentro del juego:

def lv95_to_block(east: float, north: float, height: float) -> tuple[int, int, int]:
"""Convert Swiss LV95 survey coordinates to Minecraft block coordinates."""
x = int(east - 2_480_000)   # strip the LV95 easting offset
z = int(1_300_000 - north)  # Minecraft's z axis grows southward
y = int(height)             # one block = one meter above sea level
return x, y, z
# The summit of the Jungfrau, 4,158 m:
print(lv95_to_block(2_640_188, 1_154_072, 4158))
# -> (160188, 4158, 145928)
# x and z match the in-game teleport command exactly; the game just
# drops you a few meters higher so you land on the summit, not in it.

Sobre la rejilla de teselas, la generación es una pila de capas evaluada por columna. La altura base viene de swissALTI3D. La cobertura superficial (agua, bosque, carreteras, líneas ferroviarias, presas, barreras antiavalanchas) viene de swissTLM3D. Los fondos de lagos vienen de swissBATHY3D, las alturas de los árboles de swissSURFACE3D, los contornos glaciares de los inventarios GLAMOS que llegan hasta 1850, y el espesor del hielo de un conjunto de datos de la ETH Zúrich, así que el glaciar de Aletsch está realmente tallado en hielo y no es una textura blanca extendida sobre la roca. Los prados, los canchales y los viñedos vienen del mapa federal de hábitats; incluso los árboles de las calles de Zúrich vienen del catastro arbóreo de la propia ciudad. En total, unos quince conjuntos de datos abiertos, todos de uso libre: swisstopo abrió sus datos, incluido para uso comercial, en 2021.

Un mundo de voxels no es una imagen del terreno. Es una caché de millones de pequeñas decisiones que tu pipeline tomó, una por metro cuadrado, y la calidad del mundo es exactamente la calidad de esas decisiones.

El nivel de detalle es un problema de datos, no un truco de renderizado

La distancia de renderizado por defecto de Minecraft muestra unos cientos de metros. Las capturas del proyecto muestran el glaciar de Aletsch curvándose a lo lejos durante kilómetros: esa vista lejana («Fernsicht») es una representación aparte, de menor fidelidad, que el juego construye una vez en el primer arranque. Es un nivel de detalle clásico, pero la decisión importante es dónde vive el LOD: se calcula a partir de los datos de origen durante la ingesta, no lo improvisa el renderizador sobre la marcha.

Si has construido pirámides de teselas de mapas, conoces la matemática. Cada nivel de zoom reduce a la mitad la resolución en ambos ejes, así que una pirámide completa cuesta 1 + 1/4 + 1/16 + … ≈ 4/3 de la capa base: un sobrecoste de almacenamiento del 33% a cambio de un comportamiento suave a cada escala. El LOD del terreno de voxels es la misma pirámide puesta de pie: el terreno lejano es el nivel de zoom grueso, el cercano es el fino, y el arte real está en elegir un esquema de claves que permita obtener rápido la celda correcta. Nos hemos topado con las mismas preguntas en los compromisos entre geohashes e índices espaciales adecuados: la elección de la clave decide el coste de búsqueda en todo lo que viene después.

Mi decisión favorita de LOD aquí no es visual en absoluto. La descarga gratuita es una porción de 2.400 km²: la región UNESCO Jungfrau-Aletsch, con el Eiger, el Mönch, el Jungfrau y el glaciar más grande de los Alpes, ejecutando exactamente el mismo pipeline que el país completo de pago. Es un lanzamiento canario convertido en función de producto. Pesa 1,1 GB en lugar de 24, no requiere registro, y si funciona en tu máquina, el mapa completo también funcionará. Si lanzas productos de datos grandes, copia esto sin dudar: tu nivel gratuito debería ser una porción representativa de tu terreno más difícil, no una demo castrada de tu caso más fácil.

Montañas de voxels que pasan de bloques pequeños y finos en primer plano a bloques gigantes y gruesos en la distancia brumosa.
El terreno lejano es solo el nivel de zoom grueso de la misma pirámide: el LOD se decide en la ingesta, no en el renderizador.

Streaming de teselas espaciales en el navegador

La misma disciplina aparece en la discreta página web del proyecto. Su mapa general incluye un control deslizante para comparar el mundo de voxels con la fotografía aérea real, y las imágenes no salen en absoluto de los servidores del proyecto. Tu navegador descarga las teselas de SWISSIMAGE directamente del servicio de swisstopo, y solo cuando mueves el control. Perezoso, directo al origen, amigable con la caché: el gran ancho de banda lo sirve infraestructura pública que existe precisamente para esto, y la factura de alojamiento del proyecto se mantiene cerca de cero.

El direccionamiento de teselas en la web es un problema resuelto, y conviene conocerlo a fondo si alguna vez tocas trabajo geoespacial:

import math
def latlon_to_tile(lat: float, lon: float, zoom: int) -> tuple[int, int]:
"""Standard slippy-map (XYZ) tile addressing used by OSM and most WMTS fronts."""
n = 2 ** zoom
x = int((lon + 180.0) / 360.0 * n)
lat_rad = math.radians(lat)
y = int((1.0 - math.asinh(math.tan(lat_rad)) / math.pi) / 2.0 * n)
return x, y
# At zoom 15, any point on Earth lands in one of 1,073,741,824 tiles.
# Fetch the few that intersect the viewport. Skip the other billion.

Dos detalles importan más que la fórmula. Primero, la petición se aplaza hasta que la intención del usuario es inequívoca (el control se mueve de verdad), lo que es a la vez una optimización de ancho de banda y una muestra de cortesía hacia un servicio público gratuito financiado con dinero público. Segundo, la procedencia viaja con las teselas: la página acredita SWISSIMAGE, swissBOUNDARIES3D y swissNAMES3D justo en el mapa. Cuando tu producto es una obra derivada de datos abiertos, la atribución en el punto de visualización no es decoración. Es la licencia funcionando como debe.

Qué robar del pipeline de Suiza

Primero los contraargumentos, porque los practicantes plantearon buenos. Los esfuerzos hechos a mano, como Build the Earth, pusieron a miles de voluntarios a modelar edificios reales, y ningún pipeline automático alcanza esa fidelidad: una huella de swissBUILDINGS3D voxelizada es una aproximación tosca, y si lo que te importa es la arquitectura, una exportación solo de terreno es quizá el artefacto más limpio. Justo. Pero cobertura y fidelidad se compensan directamente: la automatización te da 41.285 km² hoy; construir a mano te da un casco antiguo precioso, algún día. Mi postura: para un producto de datos gana la generación automatizada con procedencia publicada, y los hitos construidos a mano y curados pueden añadirse encima donde importan.

Y la procedencia es la parte que todos se saltan. Este proyecto publica una lista de defectos conocidos: huecos cerca de las fronteras donde solo llega la malla Copernicus de 30 m, zonas irregulares o planas, puentes y carreteras incorrectos o ausentes, y un control de calidad hecho por muestreo y no metro a metro. Esa lista hace un trabajo real: convierte los informes de «aquí el mundo está mal» en documentación del tipo «sí, ese conjunto de datos termina ahí». Todo producto de datos derivados debería publicar su matriz de procedencia y su lista de errores conocidos. Los que no lo hacen no son más precisos; solo son menos honestos.

  • Tesela todo. La tesela es tu unidad de almacenamiento, caché, generación y fallo. Los monolitos no degradan con elegancia.
  • Nunca reduzcas resolución en la ingesta. Conserva la resolución nativa de cada fuente y remuestrea en el renderizado.
  • Genera de forma perezosa. Cuando el mundo es más grande que el tiempo de juego de cualquiera, la computación por visita gana al horneado previo.
  • Construye la pirámide de LOD en la ingesta. Presupuesta el ~33% de sobrecoste y compra escalado suave a cualquier distancia.
  • Publica una porción canario. Un fragmento gratuito y representativo de tus datos más difíciles vale más que cualquier ficha técnica.
  • Publica la procedencia y los defectos conocidos. Forman parte del producto, no son una disculpa por él.

El país completo cuesta 15 CHF con todas las versiones futuras incluidas, y solo para residentes suizos, por razones legales, una restricción curiosamente encantadora para un bien puramente digital. Pero el producto real no es el mapa. Es la demostración de que una sola persona con datos públicos, un pipeline por teselas y documentación honesta puede lanzar más que la infraestructura geoespacial de la mayoría de los equipos. Tu conjunto de datos probablemente no tiene 41.285 km². Tus excusas también son más pequeñas.