Back to blog

Tech NotesApril 20, 2025

Building 2D→3D Floor Plan Sync with Konva.js + Three.js

By Hiramise Team

Hiramise shares a single JSON document between the 2D canvas and the 3D viewer. Moving equipment in 2D instantly reflects in 3D. Here's how we built it.

Coordinate System Design

2D and 3D use different coordinate systems. Konva.js has a top-left origin (Y-down); Three.js has a center origin (Y-up). A shared conversion function bridges them.

  • Internal storage unit: mm integers (prevents floating-point error accumulation)
  • 2D rendering: mm → pixels (DPR and zoom factor applied)
  • 3D rendering: mm → Three.js units (1 unit = 100mm)
  • Y-axis flip: floorY = roomHeight_mm − konvaY

Shared JSON Schema

Floor plan data is stored as a single JSON with 3 sections: boundary (walls), equipment (equipment list), and metadata (business type, country).

  • boundary: outer + inner wall polylines, mm coordinates
  • equipment: id, archetype, x_mm, y_mm, width_mm, depth_mm, rotation_deg
  • metadata: country, category, specialty, format

3D Rendering Pipeline

Each equipment entry maps to a GLB model via archetype ID. The model is auto-scaled to match width_mm and depth_mm dimensions.

  • Tier 1 (55%): Three.js parametric code — no GLB file needed
  • Tier 2–4: GLB uploaded to R2 → loaded via useGLTF
  • Scaling: scale.x = targetWidth / modelNativeWidth
  • Rotation: rotation.y = −(rotation_deg × π / 180) (Y-axis flip correction)
This architecture means adding a new equipment catalog item only requires one GLB file and one archetype mapping line. No changes to the core renderer.
Tech NotesPublished: April 20, 2025
By Hiramise Team
Building 2D→3D Floor Plan Sync with Konva.js + Three.js | Hiramise | Hiramise