Initial repository scaffold for a Rust/WebGPU engine with a Svelte frontend.
This repository starts from the architecture in the provided notes:
core engine crate and a wasm binding crate.Cargo.toml: Rust workspace manifest.cargo/config.toml: wasm target tuningcrates/core: engine-facing types and module boundariescrates/wasm: wasm-bindgen entry pointsfrontend: Svelte + Vite shelldocs: architecture and translation notes adapted from the guidancecrates/core/src/tiles.crates/wasm.Document Purpose: Provide a detailed, actionable architecture for translating CesiumJS's
@cesium/engineinto a minimal Rust + wgpu runtime, while preserving the full declarative API contract defined inCECIUMNEXT_api.txtandCesiumNext Rust WebGPU.md.
Per CECIUMNEXT_api.txt, every item in Sections 1–15 is KEPT as declarative vocabulary. The Rust backend is a translator, not a re-inventor.
| Category | Treatment | Examples |
|---|---|---|
| Declarative Language Constructs | ✅ KEPT — API surface preserved; calls translated to Rust integration points | Scene, Camera, Cesium3DTileset, Cesium3DTilesTerrainData, MetadataSchema, AdminBoundary, MCP Tools |
| Implementation Artifacts | ❌ DROPPED — Replaced by modern Rust/WebGPU equivalents | writeTextToCanvas, exportKml*, WebGLOptions, GltfGpmLocal, ITwin*, obtainTranslucentCommandExecutionFunction |
Do not cull based on keyword matching. Evaluate by actual role in 3D Tiles Next:
| Term | Treatment | Rationale |
|---|---|---|
Cesium3DTilesTerrainData |
✅ KEPT | glTF-native (.glb) terrain tile structure for 3D Tiles Next; includes gltf, waterMask, interpolateHeight, upsample, childTileMask |
HeightReference, HeightmapEncoding (glTF context) |
✅ KEPT | Needed for feature clamping to glTF-based terrain meshes; part of 3D Tiles Next spec |
QuantizedMeshTerrainData, createWorldTerrainAsync |
❌ DROPPED | Legacy quantized-mesh terrain provider system; not glTF-native |
GlobeSurfaceTile, TerrainProvider interface |
⚠️ REFACTORED | Retain abstract clamping logic; replace concrete providers with glTF tile content handlers |
graph TD
A[CesiumJS Engine Module] --> B{Analysis}
B -->|Declarative API construct| C[Translate: Conceptual port, minimal code reuse]
B -->|Implementation artifact| D[Rewrite: New Rust/WebGPU implementation]
B -->|Legacy/out-of-scope| E[Delete: Never re-implement]
C --> F[Examples: Tile JSON parsing, SSE calc, camera double-precision]
D --> G[Examples: WebGL→wgpu renderer, gltf crate loader, buffer pooling]
E --> H[Examples: B3DM/I3DM/PNTS, CZML/KML datasources, legacy widgets]
Based on packages/engine/README.md structure, here is the precise mapping to the Rust/WebGPU target:
| CesiumJS Module | Rust Target | Translation Strategy | API Items Preserved |
|---|---|---|---|
Source/Core/ (math, coordinates) |
core/math/ |
Replace JS numbers with f64; use glam for vectors; implement Copy/Clone/Send traits |
Cartesian2/3/4, Cartographic, BoundingSphere, Rectangle, Plane, Ray, Ellipsoid, WebMercatorProjection |
Source/Scene/Cesium3DTileset.js |
core/tiles/tileset.rs |
Parse 3D Tiles Next JSON schema only; implement implicit tiling resolver with Morton codes | Cesium3DTileset, Cesium3DTile, Cesium3DTileContent, MetadataSchema, Expression |
Source/Scene/Cesium3DTilesTerrainData.js |
core/tiles/terrain_data.rs |
Map glTF-native terrain structure; retain interpolateHeight, upsample, childTileMask logic |
Cesium3DTilesTerrainData, HeightReference, HeightmapEncoding (glTF context) |
Source/Scene/ScreenSpaceError.js |
core/math/lod.rs |
Port SSE formula; calibrate for WebGPU precision model | computeScreenSpaceError, geometric error LOD |
Source/Scene/TileBoundingVolume.js |
core/math/bounds.rs |
Convert bounding volume hierarchy; frustum culling with double-offset trick | BoundingVolume, OrientedBoundingBox, CullingVolume |
Source/Scene/TileRequestScheduler.js |
core/tiles/queue.rs |
Priority queue with SSE × distance × visibility weighting | RequestScheduler, LRUCache, TileDiscardPolicy |
Source/Scene/Camera.js |
core/camera/transform.rs |
Double-precision camera with eye-to-center offset; relative transforms | Camera, PerspectiveFrustum, ScreenSpaceCameraController |
| CesiumJS Module | Rust Target | Rewrite Rationale | Key Differences |
|---|---|---|---|
Source/Renderer/ (WebGL) |
core/render/ (wgpu + WGSL) |
WebGL implicit state → wgpu explicit pipelines; cross-platform GPU API | Descriptor sets, render pass ordering, buffer/texture pooling, WGSL shaders |
Source/Scene/GltfLoader.js |
core/gltf/loader.rs + extensions.rs |
Leverage gltf crate; add trait-based handlers for EXT_mesh_features, KHR_gaussian_splatting |
Async decoding, SPZ decompression, extension trait system |
Source/Core/Resource.js |
core/runtime/resource.rs |
WASM-friendly streaming with HTTP range + SharedArrayBuffer workers | Buffer pooling, eviction policies, memory64 targeting |
Source/DataSources/ (Entity system) |
Trait-based Feature + SurrealDB sync |
Decouple rendering from semantic layer; enable AI graph queries | DataSource becomes trait; Entity maps to graph node ID |
Source/Widgets/ |
Svelte 5 components | Reactive UI without Cesium's legacy widget abstractions | Runes/signals; custom <Canvas> wrapper; minimal essential controls |
| CesiumJS Module | Reason for Deletion | Replacement (If Any) |
|---|---|---|
B3dmParser, I3dmParser, PntsParser |
Legacy tile formats; not glTF-native | glTF-native tile content only |
QuantizedMeshTerrainData, createWorldTerrainAsync |
Legacy terrain provider; not 3D Tiles Next | glTF-based terrain via Cesium3DTilesTerrainData |
CzmlDataSource, KmlDataSource, GeoJsonDataSource |
Legacy vector/temporal formats | Out of scope for 3D Tiles Next MVP |
EntityCollection, DataSourceCollection |
Replaced by trait-based loaders | TilesetLoader trait + SurrealDB graph |
Animation, Timeline, CesiumInspector widgets |
Legacy widget suite | Re-implement essentials in Svelte 5 |
WebGLOptions, VertexArray, ShaderProgram |
WebGL-specific implementation | wgpu pipeline configs + WGSL |
writeTextToCanvas, exportKml*, PinBuilder |
Canvas 2D / file export (app-layer) | App-layer concern; not engine contract |
cesium-next/
├── core/
│ ├── camera/
│ │ ├── transform.rs # DVec3 precision, relative-to-center, frustum planes
│ │ ├── controls.rs # Orbit/pan/zoom state machine (MCP-compatible)
│ │ └── precision.rs # Double-offset trick: WGS84 → eye-to-center
│ ├── math/
│ │ ├── bounds.rs # BoundingVolume (region/box/sphere), frustum culling
│ │ ├── lod.rs # Geometric error, screen-space error, SSE calc
│ │ ├── spatial.rs # Morton codes, implicit tiling math, HilbertOrder
│ │ └── projection.rs # Geographic/WebMercatorProjection (2D overlay alignment)
│ ├── tiles/
│ │ ├── tileset.rs # Tileset JSON parser, implicit tiling resolver
│ │ ├── tile.rs # Tile state machine, geometric error, content URI
│ │ ├── terrain_data.rs # Cesium3DTilesTerrainData: glTF-native terrain tile
│ │ ├── cache.rs # LRU eviction, memory budget enforcement
│ │ └── queue.rs # Priority request queue (SSE × distance × visibility)
│ ├── gltf/
│ │ ├── loader.rs # gltf crate + async buffer streaming
│ │ ├── extensions.rs # Trait handlers: EXT_mesh_features, KHR_gaussian_splatting
│ │ ├── compress.rs # Draco, KTX2/Basis, meshopt, SPZ decoders (async workers)
│ │ └── upload.rs # GPU resource upload (buffer/texture pooling)
│ ├── render/
│ │ ├── pipeline.rs # wgpu render pipelines: PBR, unlit, gaussian splat, OIT
│ │ ├── shader/ # WGSL: pbr.wgsl, splat.wgsl, depth.wgsl, terrain.wgsl
│ │ ├── pass.rs # Render pass orchestration, occlusion culling
│ │ └── stats.rs # Frame profiler hooks (draw calls, GPU time, memory)
│ ├── runtime/
│ │ ├── engine.rs # Main update loop, delta time, frame pacing
│ │ ├── context.rs # Shared state: camera, tile cache, render context
│ │ ├── resource.rs # HTTP range requests, buffer pooling, worker bridge
│ │ └── mcp_router.rs # JSON-RPC command handler for AI agents
│ └── semantic/ (optional)
│ ├── graph_builder.rs # Idempotent tile→graph enrichment pipeline
│ ├── schema.rs # SurrealDB schema initialization + typed edges
│ ├── edges.rs # Edge taxonomy enum + RELATE helpers
│ └── ml.rs # SurrealML inference hooks (ORT/PyTorch/sklearn)
├── wasm/
│ ├── lib.rs # wasm-bindgen entry point
│ ├── bindings.rs # init(), load_tileset(), set_camera(), mcp_handle()
│ └── worker.rs # SharedArrayBuffer bridge for decode threads
├── frontend/
│ ├── Canvas.svelte # WASM engine wrapper, WebGL/WebGPU canvas lifecycle
│ ├── runes/
│ │ ├── camera.svelte.ts # Reactive camera state binding
│ │ ├── layers.svelte.ts # Tileset/layer visibility toggles
│ │ └── selection.svelte.ts # Picking + metadata propagation
│ └── widgets/
│ ├── Controls.svelte # Orbit controls, zoom, reset
│ ├── Inspector.svelte # Feature metadata + graph query panel
│ └── Geocoder.svelte # Location search stub (WGS84 → camera target)
├── mcp/
│ ├── protocol.rs # JSON-RPC schema, tool/resource definitions
│ └── agent_context.rs # Viewport state serialization for AI agents
└── Cargo.toml # Workspace + feature flags
Cesium3DTilesTerrainData Translation// core/tiles/terrain_data.rs
use bitflags::bitflags;
use gltf::Document;
use std::sync::Arc;
bitflags! {
/// Child tile availability mask (SW, SE, NW, NE) — from JS childTileMask
pub struct ChildTileMask: u8 {
const SOUTHWEST = 0b0001;
const SOUTHEAST = 0b0010;
const NORTHWEST = 0b0100;
const NORTHEAST = 0b1000;
}
}
/// Terrain data for a single tile where terrain is represented as glb (binary glTF)
/// Direct translation of Cesium.Cesium3DTilesTerrainData(options)
pub struct Cesium3DTilesTerrainData {
// Core glTF terrain mesh
pub gltf_doc: Arc<Document>, // Parsed .glb terrain mesh
// Height bounds (meters above ellipsoid)
pub minimum_height: f64,
pub maximum_height: f64,
// Bounding volumes for culling
pub bounding_sphere: BoundingSphere,
pub oriented_box: OrientedBoundingBox,
// Horizon occlusion for visibility culling
pub horizon_occlusion_point: Cartesian3, // Ellipsoid-scaled coordinates
// Edge seam stitching
pub skirt_height: f64,
// Child tile availability (bitmask)
pub child_tile_mask: ChildTileMask,
// Optional data requests
pub request_vertex_normals: bool,
pub request_water_mask: bool,
// Attribution
pub credits: Vec<Credit>,
// Water mask: 255=water, 0=land (CPU buffer + optional GPU texture)
pub water_mask: Option<Vec<u8>>, // Uint8Array buffer
pub water_mask_texture: Option<wgpu::TextureView>, // GPU upload (optional)
// Internal state
_was_upsampled: bool, // For wasCreatedByUpsampling()
}
| JS Method | Rust Implementation | Notes |
|---|---|---|
interpolateHeight(rectangle, longitude, latitude) |
pub fn interpolate_height(&self, rect: &Rectangle, lon: f64, lat: f64) -> Option<f64> |
Bilinear interpolation on terrain mesh/heightmap; used for feature clamping |
isChildAvailable(thisX, thisY, childX, childY) |
pub fn is_child_available(&self, child_x: u32, child_y: u32) -> bool |
Check bitmask for child availability; drives implicit tiling resolver |
upsample(tilingScheme, ...) |
pub async fn upsample(&self, tiling_scheme: &TilingScheme, desc_x: u32, desc_y: u32, desc_level: u32) -> Result<Self, TerrainError> |
Async upsampling for descendant tiles; runs in background worker; returns new tile with _was_upsampled = true |
wasCreatedByUpsampling() |
pub fn was_created_by_upsampling(&self) -> bool |
Simple getter for internal state |
// In core/gltf/loader.rs — when loading terrain tile content
async fn load_terrain_tile(resource: &Resource) -> Result<Cesium3DTilesTerrainData> {
// 1. Fetch .glb + metadata JSON
let glb_bytes = resource.fetch_range(0..).await?;
let gltf_doc = Arc::new(gltf::import_slice(&glb_bytes)?.0);
// 2. Parse terrain-specific metadata from tile JSON
let terrain_meta: TerrainMetadata = resource.fetch_json().await?;
// 3. Construct Cesium3DTilesTerrainData
Ok(Cesium3DTilesTerrainData {
gltf_doc,
minimum_height: terrain_meta.minimum_height,
maximum_height: terrain_meta.maximum_height,
bounding_sphere: terrain_meta.bounding_sphere,
oriented_box: terrain_meta.oriented_box,
horizon_occlusion_point: terrain_meta.horizon_occlusion_point,
skirt_height: terrain_meta.skirt_height,
child_tile_mask: ChildTileMask::from_bits_truncate(terrain_meta.child_tile_mask),
request_vertex_normals: terrain_meta.request_vertex_normals,
request_water_mask: terrain_meta.request_water_mask,
credits: terrain_meta.credits,
water_mask: terrain_meta.water_mask, // CPU buffer
water_mask_texture: None, // Will be uploaded to GPU in render pipeline
_was_upsampled: false,
})
}
// In core/render/pipeline.rs — terrain-specific shader binding
fn bind_terrain_uniforms(
render_pass: &mut RenderPass,
terrain: &Cesium3DTilesTerrainData,
camera: &Camera,
) {
// Bind water mask texture if available
if let Some(water_tex) = &terrain.water_mask_texture {
render_pass.set_bind_group(2, &terrain_bind_group, &[water_tex]);
}
// Pass height bounds for displacement/LOD calculations
render_pass.set_push_constants(0, &terrain.minimum_height.to_ne_bytes());
render_pass.set_push_constants(8, &terrain.maximum_height.to_ne_bytes());
}
CECIUMNEXT_api.txt to extract all declarative constructs.API_Item → Rust_Module → Translation_Action.packages/engine/README.md:For each KEPT API item, generate a Rust stub with:
// TODO: implement backend logic comments.wasm-bindgen annotations for FFI exposure.Example: ```rust // Auto-generated stub for Cesium3DTilesTerrainData #[wasm_bindgen] pub struct Cesium3DTilesTerrainData { // Fields preserved exactly as in JS API #[wasm_bindgen(getter)] pub fn minimum_height(&self) -> f64 { /* TODO */ }
#[wasm_bindgen] pub fn interpolate_height(&self, rectangle: JsValue, longitude: f64, latitude: f64) -> JsValue { // TODO: implement bilinear interpolation JsValue::UNDEFINED }
}
### 5.4 Phase 3: Backend Implementation (Weeks 4–8)
1. Replace `TODO` stubs with actual Rust logic:
- Use `glam` for math, `gltf` crate for loading, `wgpu` for rendering.
- Implement double-precision camera with eye-to-center offset.
- Port SSE calculation with WebGPU precision considerations.
2. Ensure all API calls route through the stub layer — no direct backend calls from frontend.
### 5.5 Phase 4: Legacy Stripping Validation (Week 9)
1. Run a static analysis pass to detect any deleted implementation artifacts:
- Search for `WebGLOptions`, `exportKml`, `writeTextToCanvas`, etc.
- Fail the build if any are found.
2. Verify that all KEPT API items have working stubs + backend implementations.
### 5.6 Phase 5: Integration Testing (Weeks 10–12)
1. Load public 3D Tiles Next tilesets; verify:
- Tile streaming + implicit tiling works.
- `Cesium3DTilesTerrainData` terrain tiles render correctly.
- `interpolateHeight` returns accurate elevations.
- MCP commands control camera + query graph.
2. Profile performance against MVP budgets.
---
## 6. Semantic Layer: SurrealDB Integration (Optional Module)
### 6.1 Graph Builder: Idempotent Tile Processing
```rust
// core/semantic/graph_builder.rs
pub async fn on_tile_loaded(
tile_id: &str,
terrain: Option<&Cesium3DTilesTerrainData>,
gltf_doc: &gltf::Document,
features: &[MeshFeature],
db: &SurrealDbClient,
) -> Result<()> {
// Fast existence check — skip if already processed (idempotent)
if db.tile_processed(tile_id).await? { return Ok(()); }
// Extract geometry + metadata → SurrealDB native types
let nodes = if let Some(terrain) = terrain {
extract_terrain_features(terrain, gltf_doc)?
} else {
extract_gltf_features(gltf_doc, features)?
};
// Build typed edges (fixed taxonomy — no generic "Related")
let edges = build_typed_edges(&nodes, EdgeTaxonomy::real_estate())?;
// Optional: vector embeddings + SurrealML inference
#[cfg(feature = "surrealml")]
{
let embeddings = compute_embeddings(&nodes)?;
let predictions = run_inference(db, &nodes, &embeddings, &["housing_feasibility"]).await?;
db.atomic_write(nodes, edges, Some(predictions)).await?;
}
#[cfg(not(feature = "surrealml"))]
{
db.atomic_write(nodes, edges, None).await?;
}
Ok(())
}
pub enum EdgeType {
// Spatial
Contains, LocatedIn, AdjacentTo, Overlaps, Above, Below,
// Structural
PartOf, HasPart, ChildOfTile, InstanceOf,
// Administrative
PartOfAdmin(AdminLevel), BelongsToLayer(String),
// Semantic (housing/projects focus)
SuitableForHousing, ImpactsTraffic, HasDemand, EconomicallyViable,
// Inferred (ML)
ClassifiedAs(String), Near { distance_m: f32 }, LikelyUsedFor(String),
}
// No generic "Related" edge permitted — every relationship must carry explicit meaning.
{
"jsonrpc": "2.0",
"method": "fly_to_trajectory",
"params": {
"type": "keyhole_spiral",
"target": [12.9716, 100.8944, 0],
"start_radius": 5000,
"end_radius": 50,
"duration_ms": 12000,
"easing": "cubic-bezier(0.4, 0, 0.2, 1)"
},
"id": 1
}
/viewport/state → Camera, frustum, visible tiles
/active/layers → Enabled tilesets, overlay opacity
/admin/hierarchy → Current admin level, structure key context
/selected/feature → Picked feature ID + graph node + properties
/terrain/elevation → Height at WGS84 coordinate (via Cesium3DTilesTerrainData.interpolateHeight)
// core/runtime/mcp_router.rs
pub async fn handle_mcp_request(request: McpRequest) -> Result<McpResponse> {
match request.method.as_str() {
"set_camera" => {
let params: SetCameraParams = serde_json::from_value(request.params)?;
engine.set_camera(params.position, params.target, params.fov);
Ok(McpResponse::success(request.id, json!({ "status": "ok" })))
}
"get_terrain_elevation" => {
let params: GetElevationParams = serde_json::from_value(request.params)?;
let height = engine.query_terrain_height(params.longitude, params.latitude)?;
Ok(McpResponse::success(request.id, json!({ "height_m": height })))
}
_ => Err(McpError::method_not_found(request.method)),
}
}
| Metric | Target | Measurement |
|---|---|---|
| Frame time (GPU) | ≤16.6 ms (60 fps) | wgpu timestamp queries |
| Draw calls/frame | ≤800 | Render pass instrumentation |
| Tile decode latency (p95) | <16 ms | Instant::now on worker thread |
| GPU memory (city scene) | ≤2.8 GB | wgpu::Device::poll + JS performance.memory |
| Graph query latency | <100 ms | SurrealDB EXPLAIN + client timing |
| MCP response time | <50 ms | JSON-RPC round-trip timing |
CECIUMNEXT_api.txt are exposed via wasm-bindgen.Cesium3DTilesTerrainData tiles render correctly; interpolateHeight returns accurate elevations.| Risk | Probability | Impact | Mitigation |
|---|---|---|---|
| WebGPU browser support gaps | Medium | High | Require WebGPU; clear fallback message; track caniuse |
| glTF extension maturity (EXT_mesh_features draft) | Medium | Medium | Track Khronos 3d-tiles repo; feature-flag unstable extensions |
| Memory pressure on large scenes | High | High | Aggressive LRU + SSE culling from day 1; buffer pooling; WASM memory64 |
| SurrealDB bundle size / complexity | Low | Medium | Compile-time feature flag --no-default-features --features rendering_only |
| WASM threading + SharedArrayBuffer | Medium | Medium | Fallback to single-threaded decode; document COOP/COEP headers |
Cesium3DTilesTerrainData precision issues |
Medium | High | Double-offset trick for GPU; f64 CPU math; visual regression tests |
Select which starter artifact you'd like first:
Cargo.toml with minimal dependencies + feature flags, wasm-pack config, basic wgpu canvas examplecore/tiles/tileset.rs with Morton code resolver, SSE calc, priority queue, first Rust code for 3D Tiles Next JSON parsingCesium3DTilesTerrainData Full Implementation — core/tiles/terrain_data.rs with all methods, GPU upload, interpolation logic<Canvas> Wrapper — Reactive camera/layer state via runes, WASM engine lifecycle management, basic controls componentmcp/protocol.rs with tool/resource definitions, JSON-RPC handler, viewport state serializercore/semantic/graph_builder.rs with typed edge enum, SurrealQL schema initialization, atomic write helperReply with the number (or "all") and preferred format (markdown, code blocks, or full files), and I'll generate it immediately.
Final Confirmation: This specification respects the full API contract from
CECIUMNEXT_api.txtandCesiumNext Rust WebGPU.md. No declarative construct is dropped based on keyword matching. Only implementation artifacts explicitly listed as "DROPPED" are excluded. The Rust backend is a translator, not a re-inventor.
CesiumNext is a ground-up reimplementation of CesiumJS's core engine as a minimal Rust + wgpu runtime with a Svelte 5 frontend, purpose-built for 3D Tiles Next 1.1+ (glTF-native, implicit tiling, EXT_mesh_features) and KHR_gaussian_splatting (with SPZ compression).
| Principle | Implementation |
|---|---|
| API Compatibility | Preserve the declarative Cesium API surface as a shared vocabulary; translate calls to Rust/WebGPU integration points |
| Format Focus | Support only 3D Tiles Next 1.1+ (glTF-based), Gaussian splats; drop legacy formats (B3DM/I3DM/PNTS, quantized-mesh, CZML, KML) |
| Backend Modernization | Replace WebGL with wgpu + WGSL; use Rust idioms for memory safety, concurrency, and performance |
| Frontend Reactivity | Svelte 5 runes/signals for UI state; custom <Canvas> wrapper for WASM engine binding |
| Semantic Intelligence | Optional SurrealDB layer for metadata→graph translation; typed edges, vector embeddings, SurrealML inference |
| AI Agent Interface | MCP (Model Context Protocol) JSON-RPC commands for viewport control, state queries, and context retrieval |
Estimated MVP Timeline: 6–9 months with a 3-person team (2 Rust engine, 1 Svelte/UI)
Based on the CECIUMNEXT_api.txt reference, we categorize every API item as:
| Category | Definition | Treatment |
|---|---|---|
| Declarative Language Constructs | Shared vocabulary for describing geospatial state (scene, camera, tiles, metadata) | ✅ KEPT — API surface preserved; calls translated to Rust backend |
| Implementation Artifacts | Runtime scaffolding, legacy renderer bindings, app-layer concerns | ❌ DROPPED — Replaced by modern Rust/WebGPU equivalents |
// Rust equivalents for Cesium scene/clock concepts
pub struct Scene { /* wgpu context, tile cache, camera ref */ }
pub struct Clock { /* JulianDate, ClockStep, TimeIntervalCollection */ }
pub struct Entity { /* glTF feature + metadata + graph node ID */ }
Scene, Clock, JulianDate, Entity, DataSource (as trait for tileset loaders)CzmlDataSource, KmlDataSource, GeoJsonDataSource (legacy formats)DataSource becomes a trait implemented by TilesetLoader, GltfStream, etc.// Double-precision math for WGS84 → eye-to-center offset
pub struct Cartesian3 { pub x: f64, pub y: f64, pub z: f64 }
pub struct Cartographic { pub longitude: f64, pub latitude: f64, pub height: f64 }
pub fn wgs84_to_eye_center(position: Cartesian3, reference: Cartesian3) -> Cartesian3;
Cartesian2/3/4, Cartographic, Rectangle, BoundingSphere)WebMercatorProjection, GeographicProjection) — needed for 2D overlay alignment even in 3D viewerPlane, Ray, CullingVolume, IntersectionTests)// 3D Tiles Next core types
pub struct Cesium3DTileset { /* implicit tiling, root tile, schema */ }
pub struct MetadataSchema { /* classes, properties, enum values */ }
pub struct Cesium3DTileFeature { /* feature ID, attributes, geometry ref */ }
Cesium3DTileset, Cesium3DTile, MetadataSchema, MetadataClass, ExpressionAnchorPointDirect/Indirect for feature geometry bindingCesium3DTilesTerrainData (legacy terrain provider) — but retain any 3D terrain concepts tied to glTF-based tiles (e.g., heightmap textures in glTF extensions)// Camera state + picking interface for MCP/Svelte
pub struct Camera { pub position: DVec3, pub view_matrix: Mat4, pub frustum: PerspectiveFrustum }
pub fn pick(scene: &Scene, screen_pos: (f32, f32)) -> Option<PickResult>;
Camera, ScreenSpaceCameraController, pick/drillPickPickedMetadataInfo + graph node ID for SurrealDB queries// Property interpolation for camera trajectories, feature animations
pub trait Property<T>: Send + Sync {
fn sample(&self, time: JulianDate) -> T;
}
pub struct SampledPositionProperty { /* keyframes + interpolation type */ }
Property, SampledProperty, CatmullRomSpline, EasingFunctionfly_to_trajectory command compiles to SampledPositionProperty + Rust spline evaluator// Model Context Protocol JSON-RPC surface
pub enum McpTool {
SetCamera { position: [f64; 3], target: [f64; 3], fov: f64 },
FlyToTrajectory { trajectory: TrajectoryConfig },
QueryAdminHierarchy { level: u8, parent_id: Option<String> },
GetPickedMetadata { screen_x: f32, screen_y: f32 },
ApplyRegionalKey { key: String, admin_level: u8 },
}
wasm/bindings.rs; state serialization via serde| Legacy Cesium Module | Rust/WebGPU Replacement | Rationale |
|---|---|---|
Renderer (WebGL) |
wgpu + WGSL shaders |
Modern GPU API, cross-platform (WebGPU/Vulkan/Metal) |
GltfLoader |
gltf crate + custom extension handlers |
Leverage Rust ecosystem; add EXT_mesh_features, KHR_gaussian_splatting |
ResourceLoader |
Async HTTP + buffer pooling + LRU cache | WASM-friendly streaming; SharedArrayBuffer for workers |
EntitySystem |
Trait-based Feature + SurrealDB graph sync |
Decouple rendering from semantic layer; enable AI queries |
WidgetSystem |
Svelte 5 components + runes | Reactive UI without Cesium's legacy widget abstractions |
# Cargo.toml feature flags to exclude legacy code
[features]
default = ["3dtiles_next", "gaussian_splats", "semantic_graph"]
legacy_formats = [] # B3DM/I3DM/PNTS — disabled by default
imagery_layers = [] # 2D tile imagery — out of scope for MVP
czml_kml = [] # Temporal/vector data formats — deferred
B3DM/I3DM/PNTS parsers, quantized-mesh terrain, CZML/KML/GeoJSON datasourcesEntityCollection, DataSourceCollection (replaced by trait-based loaders)Animation, Timeline, CesiumInspector) — reimplement essentials in Svelte⚠️ Critical Note on "Terrain": Do not cull anything solely because it contains the word "terrain". 3D Tiles Next supports glTF-based terrain meshes, heightmap textures, and displacement extensions. Only remove:
Cesium3DTilesTerrainData(legacy quantized-mesh provider)createWorldTerrainAsync(legacy terrain service)HeightmapEncoding(legacy terrain compression)Retain:
HeightReference(for feature clamping to terrain)- Any glTF extension that encodes terrain geometry or displacement
cesium-next/
├── core/
│ ├── camera/ # DVec3 precision, frustum, relative transforms
│ ├── math/ # Bounding volumes, culling, LOD, spatial indexing
│ ├── tiles/ # Tileset JSON, implicit tiling, request queue, cache
│ ├── gltf/ # Loader, Draco/KTX2/meshopt/SPZ decoders, extension traits
│ ├── render/ # wgpu pipelines: PBR, unlit, Gaussian splat, OIT
│ ├── runtime/ # Engine loop, frame pacing, MCP command router
│ └── semantic/ (opt) # graph_builder, SurrealDB client, SurrealML hooks
├── wasm/
│ ├── lib.rs # wasm-bindgen entry point
│ ├── bindings.rs # init(), load_tileset(), set_camera(), mcp_handle()
│ └── worker.rs # SharedArrayBuffer bridge for decode threads
├── frontend/
│ ├── Canvas.svelte # WASM engine wrapper, WebGL/WebGPU canvas lifecycle
│ ├── runes/ # Reactive camera, layers, selection state
│ └── widgets/ # Svelte components: Controls, Inspector, Geocoder
├── mcp/
│ ├── protocol.rs # JSON-RPC schema, tool/resource definitions
│ └── agent_context.rs # Viewport state serialization for AI agents
└── Cargo.toml # Workspace + feature flags
graph LR
A[HTTP Range Request] --> B[Tile JSON Parser]
B --> C[Implicit Tiling Resolver]
C --> D[glTF Loader + Extension Handlers]
D --> E[GPU Upload: Buffers/Textures]
E --> F[wgpu Render Pass]
D --> G[graph_builder: Feature Extraction]
G --> H[SurrealDB: Nodes + Typed Edges]
H --> I[SurrealML: Inference on Load]
F --> J[Svelte: Reactive UI Update]
I --> K[MCP: Agent Query Response]
// core/semantic/graph_builder.rs — idempotent, viewer-aware
pub async fn on_tile_loaded(
tile_id: &str,
gltf_doc: &gltf::Document,
features: &[MeshFeature],
db: &SurrealDbClient,
) -> Result<()> {
// Fast existence check — skip if already processed
if db.tile_processed(tile_id).await? { return Ok(()); }
// Extract geometry + metadata → SurrealDB native types
let nodes = extract_features(gltf_doc, features)?;
let edges = build_typed_edges(&nodes, EdgeTaxonomy::default())?;
// Optional: vector embeddings + SurrealML inference
#[cfg(feature = "surrealml")]
{
let embeddings = compute_embeddings(&nodes)?;
let predictions = run_inference(db, &nodes, &embeddings).await?;
db.atomic_write(nodes, edges, predictions).await?;
}
#[cfg(not(feature = "surrealml"))]
{
db.atomic_write(nodes, edges, None).await?;
}
Ok(())
}
Edge Taxonomy (Fixed, Typed — No Generic "Related")
pub enum EdgeType {
// Spatial
Contains, LocatedIn, AdjacentTo, Overlaps, Above, Below,
// Structural
PartOf, HasPart, ChildOfTile, InstanceOf,
// Administrative
PartOfAdmin(Level), BelongsToLayer(String),
// Semantic (housing/projects focus)
SuitableForHousing, ImpactsTraffic, HasDemand, EconomicallyViable,
// Inferred (ML)
ClassifiedAs(String), Near { distance_m: f32 }, LikelyUsedFor(String),
}
Where your time actually goes isn't translation. It's integration validation. AI will generate 70–80% of the code, but you'll need to manually fix:
clone(); you'll replace with Arc, &mut, zero-copy buffers)async + WASM workers + SharedArrayBuffer (AI misses backpressure, race conditions, memory64 constraints)If you want to actually ship a working vertical slice in 7 days using AI as a force multiplier, here's the exact execution path:
AI Prompt:"Translate this JS module to Rust. Replace JS numbers with f64. Implement Rust traits for Copy/Clone/Send. Remove JS-specific APIs. Use glam for vectors. Output complete, compilable Rust."
What AI generates: BoundingVolume, ImplicitTiling, SSECalc, TileQueue
Your fix: Replace AI's clone() chains with Arc<Mutex<>> for shared cache, &mut for mutable paths, and zero-copy wgpu::Buffer slices for tile data.
AI Prompt:"Convert this WebGL shader state to wgpu + WGSL. Use explicit bind groups, descriptor layouts, and render passes. Replace implicit state with explicit pipeline configs. Output complete wgpu::RenderPipelinesetup +.wgsl files."
What AI generates: PBR + unlit + splat shaders, pipeline configs, pass orchestration
Your fix: Add BufferPool/TexturePool manually. Ensure WGSL uses f32 consistently. Verify render pass ordering (depth → opaque → transparent → splats).
AI Prompt:"Create wasm-bindgen FFI for these camera/scene functions. Use wasm-bindgen+web-sys. Output a Svelte 5
AI Prompt:"Generate a Rust SurrealDB client wrapper that creates nodes/edges atomically from glTF features. Output MCP JSON-RPC handler for /viewport/stateandset_camera. Use serde for serialization."
What AI generates: graph_builder.rs, edge taxonomy enum, MCP router, viewport serializer
Your fix: Force async + wasm-bindgen-futures. Add idempotency check (tile_processed flag). Ensure MCP responses are schema-compliant.
AI Prompt:"Debug z-fighting at city scale. Implement double-precision relative-to-center offset for camera. Fix LOD popping by calibrating SSE formula."
What you do: Load a public 3D Tiles Next tileset. Verify tile boundary seams, SSE thresholds, and GPU memory leaks. AI will give you the math; you validate the visual result.
AI Prompt:"Generate a wgpu frame profiler + JS performance.memory hook. Output a benchmark script that measures draw calls, GPU time, and tile decode latency."
What you do: Run on RTX 3060 / M2. Validate ≥60fps, <4GB RAM, MCP responds <100ms. Fix remaining hotspots manually.
If you want the exact Day 1 scaffold + AI prompt templates + Rust struct skeletons to start compiling within 2 hours, say go. I'll drop it clean, copy-paste ready, zero fluff. You'll be translating, not theorizing.
// core/camera/transform.rs
pub struct Camera {
// World-space reference point (WGS84 → ECEF)
pub reference_center: DVec3,
// Relative-to-center position (f32 precision sufficient)
pub local_position: Vec3,
// View/projection matrices computed with double-offset trick
pub view_matrix: Mat4,
pub projection_matrix: Mat4,
}
pub fn compute_view_matrix(camera: &Camera) -> Mat4 {
// GPU receives relative coordinates; CPU handles double-precision offset
// Prevents z-fighting and precision loss at city/country scale
}
// core/gltf/compress.rs
pub enum CompressionCodec {
Draco(GeometryCompression),
Ktx2(TextureCompression),
Meshopt(VertexCompression),
Spz(GaussianSplatCompression), // Niantic SPZ
}
pub async fn decode_primitive(
primitive: &gltf::Primitive,
codecs: &[CompressionCodec],
) -> Result<DecodedBuffers> {
// Parallel decode: geometry + textures + splats
// Upload to GPU via buffer/texture pooling
}
{
"jsonrpc": "2.0",
"method": "fly_to_trajectory",
"params": {
"type": "keyhole_spiral",
"target": [12.9716, 100.8944, 0],
"start_radius": 5000,
"end_radius": 50,
"duration_ms": 12000,
"easing": "cubic-bezier(0.4, 0, 0.2, 1)"
},
"id": 1
}
MCP Resources (Agent-Readable State)
/viewport/state → Camera, frustum, visible tiles
/active/layers → Enabled tilesets, overlay opacity
/admin/hierarchy → Current admin level, structure key context
/selected/feature → Picked feature ID + graph node + properties
| Metric | Target | Measurement |
|---|---|---|
| Frame time (GPU) | ≤16.6 ms (60 fps) | wgpu timestamp queries |
| Draw calls/frame | ≤800 | Render pass instrumentation |
| Tile decode latency (p95) | <16 ms | Instant::now on worker thread |
| GPU memory (city scene) | ≤2.8 GB | wgpu::Device::poll + JS performance.memory |
| Graph query latency | <100 ms | SurrealDB EXPLAIN + client timing |
| Splat count @60fps | 8–12 M | Custom benchmark harness |
Test Datasets: Cesium 3D Tiles Next samples, Niantic SPZ Gaussian city, OSM-building extrusions + POI overlays.
| Risk | Probability | Impact | Mitigation |
|---|---|---|---|
| WebGPU browser support gaps | Medium | High | Require WebGPU; clear fallback message; track caniuse |
| glTF extension maturity (EXT_mesh_features draft) | Medium | Medium | Track Khronos 3d-tiles repo; feature-flag unstable extensions; start with reference loaders |
| Memory pressure on large scenes | High | High | Aggressive LRU + SSE culling from day 1; buffer pooling; WASM memory64 targeting |
| SurrealDB bundle size / complexity | Low | Medium | Compile-time feature flag --no-default-features --features rendering_only; lazy-load DB client |
| WASM threading + SharedArrayBuffer | Medium | Medium | Fallback to single-threaded decode; document COOP/COEP headers requirement |
| SPZ decoder licensing/WASM compatibility | Low | High | Verify MIT license; maintain fallback to uncompressed splats; contribute to upstream if needed |
cargo build --release + wasm-pack produce deterministic artifacts; CI passes.Select which starter artifact you'd like first:
Cargo Workspace Skeleton
Cargo.toml with minimal dependencies + feature flags wasm-pack build config + memory64 rustflags wgpu canvas example with WASM bindingsTileset + Implicit Tiling Module Spec
core/tiles/tileset.rs with Morton code resolver Svelte 5 <Canvas> Wrapper Stub
MCP JSON-RPC Schema + Rust Router
mcp/protocol.rs with tool/resource definitions SurrealDB Graph Builder Skeleton
core/semantic/graph_builder.rs with typed edge enum Reply with the number (or "all") and preferred format (markdown, code blocks, or full files), and I'll generate it immediately.
This specification is deliberately narrow: translate only the declarative API surface and rewrite the engine in modern Rust/WebGPU idioms. No legacy abstractions, no compatibility shims, no Cesium folder structure.
The result is not "Cesium in Rust" — it is the next-generation 3D Tiles Next runtime, built from the ground up for WebGPU, semantic understanding, and AI agent integration.