WorldWind Kotlin 2.0.5
This release adds three new local data formats (ArcGIS SLPK/I3S scene layers, Cesium 3D Tiles archives, and LAS/LAZ point clouds), extends offline bulk caching to vector layers, and delivers a round of performance and stability fixes for tiled vector rendering — alongside a large internal consolidation pass that removes ~1,900 lines of duplicated code with no behavior change.
✨ New format support
- ArcGIS SLPK (I3S) scene layers — render an Esri Scene Layer Package (I3S 1.7+ integrated mesh) in place from a local
.slpk, with no extraction or copy. Reuses the existing 3D Tiles streaming, traversal, cache, and GPU pipeline through a byte-source seam. Seam-free across tiles, textured, withaltitudeOffsetsupport. Validated on real Esri IntegratedMesh v1.8 datasets. (JVM + Android) - Cesium 3D Tiles archives (
.3tz/.3dtiles) — open a local 3D Tiles archive directly on the globe withopenArchived3dTilesLayer(file). Magic-byte sniffing picks the reader:.3tz(ZIP) or.3dtiles(SQLitemediatable). No decoder or layer subclass needed — the archive holds ordinary 3D Tiles content. (JVM + Android) - LAS/LAZ point clouds — new
PointCloudLayerloads a standalone.las/.lazfile onto the globe, reusing the.pntsGPU path. Pure-Kotlin LAS reader (point formats 0–3, 6–8) and LASzip decoder (chunked formats 0–3), verified byte-identical against thelaz-rsreference. Auto-georeferences WGS84/NAD83/ETRS89 UTM and geographic CRS, geoid-aware altitude so orthometric LiDAR rests on terrain, livealtitudeOffset, and progressive off-thread loading that keeps single-threaded targets (JS/wasm) interactive.
📦 Offline bulk caching for vector layers
- Bulk region download for MVT and OSM Buildings — the "save a region for offline use" flow (previously WMS/WMTS raster and elevation only) now covers MVT vector tiles and OSM Buildings, writing through to the same GeoPackage / IndexedDB / file stores. A resolution range picks the same slippy zoom levels as the raster/elevation path.
tileCount()on MVT and OSM Buildings layers, mirroringLevelSet.tileCount, so a download can be sized before committing to it.clone()promoted to theVectorLayercontract, implemented by all four vector layers — each builds a fresh instance from config only, never sharing live scopes, semaphores, or caches.
🚀 Performance & stability
- Bounded GPU memory for tiled feature layers — the resident-tile LRU can now be bounded by real VBO/EBO bytes instead of a flat tile count, so a few dense full-res WFS tiles can no longer balloon GPU memory until the Adreno KGSL driver fails to
mmap.TiledFeatureLayerdefaults to a 96 MB budget. - Per-frame upload throttle — a pan's burst of freshly-fetched tiles is now admitted a few at a time instead of all in one frame, spreading their GPU buffer uploads across frames and eliminating an observed ~410 ms GL-thread hitch.
- MVT assembly parallelism capped — the background assembly pool no longer sizes to every core; it now leaves cores free for the render/GC threads. Measured on an S23: worst-case frame 568 → 335 ms,
GL.draw492 → 201 ms. - WFS refresh efficiency —
WfsLayernow caches the GetCapabilities document and reuses a single HTTP client across refreshes, so an auto-refreshing viewport no longer re-downloads capabilities or rebuilds an HTTP client on every pan. The fetch loop is also split from renderable decode, dropping a per-page renderable graph that was built and immediately discarded.
🐞 Fixes
- Web:
serviceTypeToDataTypewas missing "WCS 2.0.1", registering WCS coverages as tiles on JS/wasm. - iOS:
FileSystemElevationBackend.writeTilenever deleted the ancillary sidecar on default packing, mis-decoding a re-packed tile. - Web:
ContentManager.findEntryhard-codedlastModified = nullwhilelistEntriespopulated it. - Non-casting 3D-tile meshes are now correctly excluded from the shadow cascade cull.
- JVM: a fast click with incidental jitter no longer triggers an unwanted inertial fling — the gesture must now move beyond the same 5 dp slop the minimap uses, scaled by display density.
🧹 Internal / maintainability
A behavior-preserving consolidation pass across independent subsystems (verified compiling on JVM/JS/wasmJs/iOS, with jvmTest passing):
- All eight 2D map projections now share their grid/border tessellation loops (−609 lines), backed by a new consistency test covering every projection.
- Web-Mercator / slippy tile math consolidated into a single
SlippyTilessource of truth (tile conversions,MercatorSectordelegation, fractional unprojection). - Shared cores extracted for: tile-fetch exponential backoff, bulk-retrieval retry/backoff, iOS/Web elevation-backend delegation, shadow/sightline receiver uniform plumbing (−231 lines), the MSM shadow GLSL reconstruction, glTF accessor readers, moments blur, and the lazy HTTP client pattern.
- Five latent bugs fixed while de-duplicating tile-key and slippy math (see Fixes above).
Tutorials
- New tutorials wired across JVM / web / iOS / Android shells: Point Cloud (LAS/LAZ), ArcGIS SLPK (I3S), and 3D Tiles Archive.
- Tutorial lists reordered into themed groups progressing from basics to complex format rendering, consistently across all platforms; the Android drawer gets a distinct icon per theme.
Full changelog: v2.0.4...v2.0.5