An interactive 3D floor plan renderer for the EDSim emergency department
simulator. Built with React + Vite + TypeScript + Three.js
(@react-three/fiber + @react-three/drei).
This package implements Phase 1 of the frontend redesign tracked in Issue #15: a Tiled-JSON parser and a 3D Three.js scene with extruded walls, textured floors, and Kenney furniture models.
npm install # install deps (first time run only)
npm run view-map # Starts web serverOpen http://127.0.0.1:5173. You should see a 3D floor plan of the ED with:
- Extruded walls with real height and shadow casting
- Textured floors (wood planks in the waiting room, polished concrete elsewhere)
- Kenney 3D furniture models (beds, chairs, desks, monitors, tables)
- Google Maps-style navigation controls (zoom, rotate, reset)
- OrbitControls: drag to orbit, scroll to zoom, right-drag to pan
- Sidebar with map catalogue, display toggles, and parsed-count stats
Example: Click on the replay button top right to see an example.
Replay File: If you have a replay file generated from EDSim, drag and drop the file and it will automatically load the replay.
environment/react_frontend/
├── src/
│ ├── main.tsx # React entry point
│ ├── MapViewer.tsx # Top-level page (sidebar + 3D canvas)
│ ├── components/
│ │ ├── ThreeFloorPlan.tsx # Three.js scene (walls, floors, furniture, lighting, controls)
│ │ ├── AgentLayer.tsx # Loads Agent Mesh
│ │ ├── PlaybackBar.ts # Bar to control playback
│ │ ├── ReplayDropZone.ts # Drag and drop of replay file
│ │ └── AgentMesh.ts # Renders persona mesh
│ ├── parser/
│ │ ├── types.ts # MapLayout, ZoneRegion, EquipmentPlacement, ...
│ │ ├── csv.ts # Decoders for the special_blocks/*.csv tables
│ │ ├── parseTiledJSON.ts# The parser pipeline
│ │ ├── loadMapLayout.ts # fetch() helper that drives the parser
│ │ └── index.ts # Public barrel
│ ├── assets/
│ │ ├── index.ts # Asset catalogue (texture URLs, model paths)
│ │ ├── textures/ # Floor texture PNGs (wood, concrete)
│ │ └── furniture/ # Kenney isometric sprite PNGs (kept for reference)
│ ├── theme/
│ │ └── colors.ts # Zone colours, canvas background
│ ├── data/
│ | └── maps.ts # Catalogue of available Tiled fixtures
| ├── Replay/
| │ ├── expandFrames.ts
│ │ ├── loadReplay.ts # Loads replay file generated by EDSim
│ │ ├── roleColors.ts # Gets color for 3D representation of agents
│ │ ├── types.ts # PersonaRole, ReplayAgentDelta, ReplayFrame...
│ │ ├── usePersonaPositions.ts # Reads persona positions
│ │ └── usePlayback.ts # Sets up playback for replay
├── public/
│ └── models/ # Kenney GLTF furniture models (.glb)
├── tests/
│ ├── unit/ # vitest parser tests (51)
│ ├── e2e/ # Playwright viewer tests (6)
└── Replay/ # vitest replay tests (12)
├── scripts/
│ ├── generate-assets.mjs # Build-time PNG texture generator
│ └── dump-parser.mjs # CLI parser output dumper
└── README.md
ThreeFloorPlan renders the following hierarchy:
- GroundPlane — large dark surface surrounding the building
- ZoneFloor — one
PlaneGeometryper zone region, textured with the raster PNG (wood or concrete) and tinted with the zone colour - Walls —
BoxGeometryper wall segment, extruded to 2.5 units height, white MeshStandardMaterial, shadow casting enabled - Furniture — Kenney
.fbxmodels loaded viauseFBX, placed at each equipment tile position, casting and receiving shadows - Lighting —
DirectionalLight(2048px shadow map) + warmAmbientLightfill - OrbitControls — drag/scroll/right-drag camera interaction
- NavControls — HTML overlay with zoom/rotate/reset buttons
Kenney Furniture Kit 2.0 (CC0) GLTF models in public/models/hostipals:
| Model | Equipment type | |---|---|---| | bed.fbx | bed | | chair.fbx | chair | | waiting_chair.fbx | waiting_room_chair | | computer.fbx | computer | | diagnostic_table.fbx | diagnostic_table | | medical_cart.fbx | medical_equipment | | wheelchair.fbx | wheelchair | | reception_desk.fbx | reception_desk |
npm run test # 51 vitest unit tests (parser)- Drop the Tiled JSON under
environment/frontend_server/static_dirs/assets/the_ed/visuals/. - If it introduces new tile GIDs, update the
matrix/special_blocks/*.csvfiles. - Append a new entry to
src/data/maps.ts. - The sidebar picks it up automatically.