Configuración y Gestión de Terrenos 3D en Cesium.js

Conceptos Básicos del Terreno en Cesium

Por defecto, el motor de renderizado de Cesium no aplica elevaciones topográficas reales. El modelo base es un elipsoide suave (WGS84 Ellipsoid), lo que significa que las regiones montañosas se visualizarán completamente planas a menos que se configure explícitamente una fuente de elevación.

Proveedores de Terreno (TerrainProvider)

Al igual que las capas de imágenes, la arquitectura de Cesium utiliza la clase abstracta TerrainProvider para gestionar y cargar datos de elevación. Las implementaciones más comunes incluyen:

  • ArcGISTiledElevationTerrainProvider: Conecta con servicios de elevación alojados en ArcGIS.
  • CesiumTerrainProvider: Diseñado para consumir teselas de terreno en formato quantized-mesh, ya sean propias o de terceros.
  • CustomHeightmapTerrainProvider: Permite generar mapas de altura proceduralmente mediante funciones matemáticas.
  • EllipsoidTerrainProvider: Representa el elipsoide base con elevación cero (comportamiento por defecto).

Estrategias de Inicialización del Terreno

Es fundamental comprender una diferencia arquitectónica clave: mientras que las capas de imágenes (ImageryLayer) se gestionan como una colección y premiten superposiciones múltiples, un visor de Cesium solo puede tener un único proveedor de terreno activo a la vez. La asignación se realiza directamente a la propiedad terrainProvider.

Inyección durante la instanciación del Visor

Se puede pasar el proveedor directamente en el objeto de opciones de configuración al crear la instancia del Viewer:

const scene3D = new Cesium.Viewer("renderTarget", {
  terrainProvider: new Cesium.ArcGISTiledElevationTerrainProvider({
    url: "https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer"
  })
});

Asignación dinámica post-instanciación

Alternativamente, el proveedor puede asignarse o reemplazarse en tiempo de ejecución modificando la propiedad correspondiente:

const scene3D = new Cesium.Viewer("renderTarget");

const terrainConfig = {
  url: "https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer"
};
const arcgisElevation = new Cesium.ArcGISTiledElevationTerrainProvider(terrainConfig);

scene3D.terrainProvider = arcgisElevation;

Implementaciones Prácticas de Proveedores

CesiumTerrainProvider con servicios externos

Este proveedor es el estándar para consumir terrenos optimizados en formato quantized-mesh. A continuación, se muestra cómo integrar un servicio de MapTiler, el cual requiere una clave de API válida:

const maptilerApiKey = 'YOUR_API_KEY_HERE';
const externalTerrain = new Cesium.CesiumTerrainProvider({
  url: `https://api.maptiler.com/tiles/terrain-quantized-mesh/?key=${maptilerApiKey}`,
  requestVertexNormals: true // Necesario para iluminación realista
});

scene3D.terrainProvider = externalTerrain;

Generación procedural con CustomHeightmapTerrainProvider

Para escenarios donde no se dispone de un servidor de teselas, es posible calcular la elevación matemáticamente. El siguiente ejemplo genera un terreno ondulado basado en funciones trigonométricas:

const gridCols = 128;
const gridRows = 128;

const proceduralElevation = new Cesium.CustomHeightmapTerrainProvider({
  callback: function(tileX, tileY, zoomLevel) {
    const elevationData = new Float32Array(gridCols * gridRows);
    
    for (let row = 0; row < gridRows; row++) {
      for (let col = 0; col < gridCols; col++) {
        const normalizedY = (tileY + row / (gridRows - 1)) / Math.pow(2, zoomLevel);
        // Generación de ondas con amplitud de 5000 metros
        const waveHeight = 5000 * (Math.cos(3000 * normalizedY) * 0.5 + 0.5);
        elevationData[row * gridCols + col] = waveHeight;
      }
    }
    return elevationData;
  },
  width: gridCols,
  height: gridRows
});

scene3D.terrainProvider = proceduralElevation;

Terreno global de Cesium ion

La forma más rápida de obtener un terreno global de alta resolución con datoss batimétricos es utilizar la API de Cesium ion. Además, se pueden habilitar máscaras de agua para animar las superficies oceánicas:

const worldElevation = Cesium.createWorldTerrain({
  requestWaterMask: true, // Habilita animaciones de flujo en océanos y costas
  requestVertexNormals: true
});

scene3D.terrainProvider = worldElevation;

Visualización de Curvas de Nivel

Para análisis topográfico, Cesium permite superponer curvas de nivel (líneas de contorno) directamente sobre el globo mediante materiales personalizados. Esto se logra configurando el material ElevationContour en la escena:

function renderTopographicContours(strokeWidth, altitudeStep, strokeColor) {
  const contourMaterial = Cesium.Material.fromType("ElevationContour");
  
  contourMaterial.uniforms.width = strokeWidth;
  contourMaterial.uniforms.spacing = altitudeStep;
  contourMaterial.uniforms.color = strokeColor;
  
  scene3D.scene.globe.material = contourMaterial;
}

// Renderiza líneas amarillas de 1.5px de grosor cada 50 metros de altitud
renderTopographicContours(1.5, 50.0, Cesium.Color.YELLOW);

Etiquetas: Cesium.js WebGL TerrainProvider 3D-GIS JavaScript

Publicado el 8-3 08:52