# Architecture Documentation This document explains the architecture of the EID Wireless documentation system and its interactive diorama renderer. --- ## Overview The EID Wireless documentation is a **text-first** technical resource that uses interactive 3D visualizations (dioramas) as *supplemental* learning tools. The core principle is: **readers should be able to understand the concepts without interactives, but gain deeper insight through them**. This is achieved through a hybrid architecture: 1. **Typst** generates static HTML documents from `.typ` source files 2. **Custom JavaScript renderer** provides interactive dioramas embedded in those pages 3. **Vite** bundles everything together for development and production The dioramas are not the primary content—they're visual aids that appear *after* conceptual explanations and serve to reinforce understanding through visualization. --- ## Architecture Goals ### Primary Goal: Text-First Documentation The documentation system prioritizes readable, searchable, accessible text content. Interactive dioramas: - Are **optional** and **degrade gracefully** (pages work without JavaScript) - Are **out-of-the-way** (don't interfere with reading flow) - Are **supplemental** (don't contain core information that isn't in text) - Are **mobile-friendly** (scrolling behavior is preserved by default) ### Secondary Goals 1. **Accurate Minecraft rendering** - Dioramas must faithfully represent block states, rotations, and redstone behavior 2. **Efficient rendering** - Multiple dioramas can appear on a single page; rendering must be performant 3. **Easy authoring** - Content creators should focus on concepts, not graphics programming 4. **Version independence** - Documentation should work across different Minecraft versions --- ## System Architecture ### High-Level Flow ``` Typst Source (.typ files) ──▶ HTML + JavaScript ──▶ Browser │ └─▶ Interactive Dioramas (WebGL) ``` ### Components #### 1. Typst Document Generator **Role**: Converts `.typ` source files into HTML pages **Key Files**: - `main.typ` - Main entry point, defines document structure - `lib.typ` - Library functions (`diorama()`, `callout()`, etc.) - `content/*.typ` - Documentation chapters - `typst.toml` - Package metadata **Responsibilities**: - Compile `.typ` files into HTML using `tinymist` language server - Embed interactive elements via `#show` directives - Generate navigation between pages **Key Pattern** - Diorama Embedding: ```typ #show raw.where(lang: "mc-diorama"): it => diorama( orbit: true, pan: true, autoplay: true, it.text, ) ``` This directive tells Typst to: 1. Find all `mc-diorama` code blocks 2. Wrap them in the `diorama()` function 3. Pass block content as the world definition #### 2. World Definition System **Role**: Defines Minecraft scenes using a timeline-based domain-specific language **Format**: ``` p x y z block_type properties t time ``` Where: - `p` places or modifies blocks at coordinates - `t` advances the timeline - Properties are `key=value` pairs (e.g., `facing=east`, `powered=true`) **Example**: ``` p 0 0 0 dropper facing=up triggered=false p 0 1 0 dropper facing=up triggered=false t 2 p 0 0 0 triggered=true t 4 p 0 0 0 triggered=false ``` This format is designed to be: - **Human-readable** - Easy to write and debug - **Concise** - Minimal boilerplate - **Timeline-aware** - Changes occur at specific game ticks #### 3. WebGL Renderer (Engine) **Role**: Renders Minecraft blocks as 3D models using WebGL **Key Files**: - `src/engine.js` - Main renderer class - `src/world.js` - World state management - `src/diorama.js` - Camera and view management - `src/math.js` - Matrix operations (orthographic projection, look-at, etc.) **Architecture**: ``` Engine (singleton) ├── Dioramas (multiple per page) │ ├── Canvas (2D context for offscreen rendering) │ └── Frame (world timeline state) └── Resources (blockstates, models, textures) ├── Cache (async resource loading) ├── Blockstate Handler (parses JSON blockstate definitions) ├── Model Handler (builds geometry from models) └── Texture Handler (atlas textures into single canvas) ``` **Key Features**: - **Instanced rendering** - Thousands of blocks rendered efficiently - **Lazy updates** - Only re-renders when content changes - **View culling** - Skips rendering for off-screen dioramas - **Texture atlasing** - Packs all textures into single texture for batch rendering #### 4. Controller System **Role**: Handles user interaction with dioramas **Key Files**: - `src/controller.js` - SpacetimeController class - `src/components.js` - Custom HTML elements **Features**: - **Orbit controls** - Rotate view (left drag) - **Pan controls** - Move view (middle drag or shift+left) - **Zoom controls** - Scale view (right drag or ctrl+left) - **Timeline autoplay** - Auto-play animations with configurable speed - **Mobile support** - Touch gestures with scroll delegation - **State preservation** - Camera position and timeline state can be reset **Mobile-Specific Behavior**: - Default browser scroll is preserved (diagram doesn't capture scroll) - Touch interaction requires deliberate engagement (200ms timeout) - 1-finger touch: orbit (don't interfere with scroll) - 2-finger touch: pan + zoom (pinch gesture) #### 5. Build System **Role**: Integrates Typst output with JavaScript rendering **Key Files**: - `vite.config.js` - Vite configuration - `mise.toml` - Development tool configuration - `dist/` - Production output directory **Workflow**: ```bash # Development mise run dev # Runs Vite dev server + Typst watch # Build mise run build # Compile Typst + bundle with Vite ``` **Vite Configuration**: - `root: .typ-bundle` - Typst-generated HTML is the Vite root - `publicDir: public` - Static assets served from Minecraft assets - Alias `/src` → `src/` - JavaScript modules accessible from HTML - Watch mode monitors both `.typ` and `src/**/*` files --- ## Data Flow ### 1. Document Compilation ``` Typst Source (.typ) ↓ (tinymist) HTML + Scripts ↓ (Vite bundling) dist/index.html ``` ### 2. World Parsing ``` mc-diorama Code Block ↓ (World constructor) World Object ├── events[] - Timeline events (changes at each tick) ├── initialState - Block state at t=0 └── labels - Named timeline positions ``` ### 3. Frame Playback ``` World Object ↓ (WorldFrame) Frame Object ├── blocks[] - Current block state ├── currentTime - Timeline position └── listeners[] - Callbacks on state change ``` ### 4. Rendering Pipeline ``` Frame State Change ↓ Engine.updateAll() ├── Parse blocks → Blockstates → Models ├── Build geometry (positions, normals, UVs) ├── Update texture atlas └── Create instanced meshes (VBOs) Frame State Change (again) ↓ Engine.render() ├── Check visibility (cull off-screen dioramas) ├── Update camera matrices (orthographic projection) ├── Draw instanced meshes (WebGL) └── Copy to 2D canvas (for HTML display) ``` ### 5. Resource Loading ``` Request Blockstate/Model/Texture ↓ Cache.getAsync() ├── Check if already loading → return promise ├── Check if already loaded → return data └── Kick off fetch + prepare fallback Fetch Complete ↓ Handler.process() ├── Parse JSON (blockstate/model) ├── Build geometry (model) └── Return structured data ↓ Cache.onResolve() → Engine.requestUpdate() ``` --- ## User Experience: What Users Actually See Dioramas appear as interactive 3D diagrams within the documentation: ``` ┌─────────────────────────────────────┐ │ Text explanation of redstone... │ │ (this is the primary content) │ ├─────────────────────────────────────┤ │ ┌───────────────────────────────┐ │ │ │ [Diorama: 3D interactive │ │ │ │ view of the mechanism] │ │ │ │ │ │ │ │ (click/drag to interact) │ │ │ └───────────────────────────────┘ │ │ Caption: "Figure 1: Mechanism" │ └─────────────────────────────────────┘ ``` **Key UX Principles**: 1. **Dioramas are after the text** - Readers understand conceptually first, then visualize 2. **Dioramas don't steal scroll** - Default browser scroll works; interaction requires deliberate action 3. **Mobile-first interaction** - Touch gestures don't interfere with page navigation 4. **Progressive enhancement** - Pages work without JS; dioramas add value when JS is available ### Camera System Dioramas use **orthographic projection** (not perspective) because: 1. Redstone mechanisms are small and detailed 2. Orthographic preserves proportions 3. Better for technical diagrams 4. Easier to measure distances **Camera Parameters**: - `target` - Point camera looks at (world coordinates) - `radius` - Distance from target - `theta` - Horizontal rotation angle (degrees) - `phi` - Vertical rotation angle (degrees) **Matrix Calculation**: 1. Convert spherical coordinates to Cartesian (eye position) 2. Calculate view direction and up vector 3. Build view matrix via `mat4LookAt()` 4. Build orthographic projection matrix based on radius and aspect ratio 5. Combine: `viewProj = projection × view` ### Instanced Rendering Each unique block variant gets its own instanced mesh: ``` Geometry (positions, normals, UVs, tints, shades) ↓ Instance Data ├── Matrix[] (16 floats each) - World transformation └── Color[] (3 floats each) - Redstone power tint ↓ GPU Buffer (VBO) ↓ DrawElementsInstanced() ``` This allows thousands of blocks to be rendered in a single draw call. ### Texture Atlasing All block textures are packed into a single canvas: ``` 16×16px blocks ↓ Atlas Canvas (256×256px default) ├── Cell 0: block_0.png ├── Cell 1: block_1.png ├── Cell 2: block_2.png └── ... ↓ UV Map ├── u, v (cell position) └── du, dv (cell size) ``` Texture loading is **asynchronous** but **synchronous fallback** is provided: - Renderer immediately gets UV coordinates - Texture data loads in background - Fallback texture (black silhouette) shown until loaded --- ## Interactive Element Design ### Accessibility First Dioramas must work without JavaScript: ```html ``` ### Performance Optimizations 1. **Lazy rendering** - Only update when content changes 2. **Visibility culling** - Skip off-screen dioramas 3. **State preservation** - Only rebuild meshes when blocks change 4. **Texture batching** - Single texture bind for all blocks 5. **Instanced drawing** - One draw call per block type ### Mobile-First Interaction **Touch Handling**: - 200ms delay before engaging (allows scroll detection) - 1-finger: orbit (doesn't interfere with page scroll) - 2-finger: pan + zoom (pinch gesture) - Touch doesn't block page scroll unless clearly interacting **Scroll Delegation**: ```javascript canvas.addEventListener('touchstart', e => { // Check if user is trying to scroll if (maxTouchDistance < 10px) { // Let browser handle scroll return; } // Engage diorama interaction e.preventDefault(); }); ``` --- ## Extensibility ### Adding New Block Types 1. **Blockstate JSON** - Define block variants in `public/assets/minecraft/blockstates/` 2. **Model JSON** - Define geometry in `public/assets/minecraft/models/` 3. **Texture PNG** - Add texture image in `public/assets/minecraft/textures/` The system automatically discovers and loads these assets. ### Adding New Diorama Features The controller system is designed for easy extension: ```javascript class SpacetimeController { constructor(diorama, options = {}) { this.opts = {orbit: true, pan: true, zoom: true, ...options}; // Add new options here } } ``` New features can be added as optional behaviors without breaking existing dioramas. --- ## Development Workflow ### Running Locally ```bash mise run dev # Opens browser at localhost:5173 # Automatically reloads on changes to .typ or src/**/* ``` ### Building for Production ```bash mise run build # Compiles Typst to .typ-bundle/ # Bundles with Vite to dist/ ``` ### Debugging **Enable debug redraw**: ```javascript window.mcEngine.debug_redraw = true; // Highlights regions that are being redrawn ``` **Check resource loading**: ```javascript window.mcEngine.cache.data // Shows all loaded resources ``` **Inspect frame state**: ```javascript const frame = document.querySelector('mc-diorama').frame; console.log(frame.blocks, frame.currentTime); ``` --- ## Future Architecture Changes The JavaScript API is intentionally unstable. Planned changes: 1. **Component system** - Move from custom elements to framework components 2. **WebAssembly rendering** - Potential Rust/WASM renderer for better performance 3. **TypeScript migration** - Improve type safety and IDE support 4. **Animation system** - More sophisticated timeline interpolation 5. **Shader effects** - Enhanced visual feedback (glows, particles, etc.) These changes won't break the Typst authoring experience—the diorama content format will remain the same. --- ## References - Typst documentation: https://typst.app/docs - WebGL2 documentation: https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API - Minecraft Java Edition documentation: https://minecraft.wiki/w/Java_Edition - Instanced rendering: https://learnopengl.com/Advanced-OpenGL/Instancing