Skip to main content

Data Model — HomeSceneJSON

HomeSceneJSON is the central data structure in Planova. It is the single source of truth that represents a complete interior scene: every room, wall, door, piece of furniture, material, light, and camera position. The AI pipeline produces it, the frontend stores it, and the 3D engine renders from it.

The canonical TypeScript definitions live in src/types/scene.ts. The Rust backend holds its own models in src-tauri/src/models.rs for persistence and IPC.

Schema Overview

Coordinate System

All spatial values in HomeSceneJSON use meters as the unit of measurement with a Y-up coordinate system:

  • X -- Left / Right
  • Y -- Up / Down (vertical axis, height)
  • Z -- Forward / Backward

Heights are measured along the Y axis. Room polygons (Vec2) and wall start/end positions are defined on the XZ plane. Object positions (Vec3) include the Y component for elevation above the floor.

Primitive Types

TypeDescriptionExample
stringText value"living_room"
numberFloating-point value3.6
booleanTrue/false flagtrue
Vec22D vector [x, z][4.5, 3.2]
Vec33D vector [x, y, z][1.0, 2.4, 3.0]
uuidUniversally unique identifier string"a1b2c3d4-..."

Root Document

FieldTypeRequiredDescription
schema_versionstringYesSchema version (e.g., "1.0")
projectHomeSceneProjectYesProject metadata
globalHomeSceneGlobalYesGlobal scene settings
roomsRoom[]YesRoom definitions
wallsWall[]YesWall segments
openingsOpening[]YesDoors and windows
objectsSceneObject[]YesFurniture and decorative objects
materialsSceneMaterial[]YesPBR material definitions
lightsSceneLight[]YesLight sources
camerasCameraPreset[]YesSaved camera positions
parse_qualityParseQualityNoPipeline quality metrics (injected by the pipeline)

project — HomeSceneProject

FieldTypeDescription
idstring (uuid)Unique project identifier
namestringHuman-readable project name
unitstringMeasurement unit. Currently always "meter"

global — HomeSceneGlobal

FieldTypeDefaultDescription
stylestring"modern"Interior style preset (e.g., modern, minimalist, scandinavian, industrial, japanese, luxury)
ceiling_heightnumber2.8Default ceiling height in meters
wall_thicknessnumber0.15Default wall thickness in meters
texture_overridesobjectundefinedOptional global texture override map

texture_overrides

KeyTypeDescription
floorstringOverride texture ID for all floor surfaces
wallstringOverride texture ID for all wall surfaces
ceilingstringOverride texture ID for all ceiling surfaces

When set, these overrides take precedence over per-room material assignments during scene building.


rooms[] — Room

Each room represents a distinct enclosed space identified by the AI pipeline.

FieldTypeRequiredDescription
idstring (uuid)YesUnique room identifier
typeRoomTypeYesRoom type from the predefined enum
namestringYesDisplay name (e.g., "Master Bedroom")
polygonVec2[]YesFloor polygon vertices on the XZ plane, in winding order
areanumberNoCalculated area in square meters
floor_materialstringNoMaterial ID for the floor surface
wall_materialstringNoMaterial ID for room-specific walls
ceiling_materialstringNoMaterial ID for the ceiling surface

RoomType Enum

ValueDescription
living_roomPrimary living/entertainment space
bedroomSleeping quarters
kitchenCooking area with appliance zones
bathroomWet room with plumbing fixtures
dining_roomDedicated eating area
balconyOutdoor-adjacent extension
corridorCirculation hallway
studyHome office or reading room

The pipeline assigns material IDs using the pattern mat_{style}_{surface}_{room_type} (e.g., mat_modern_floor_living_room). The frontend engine resolves these IDs against the materials[] array.


walls[] — Wall

Walls are defined as line segments on the XZ plane with physical dimensions.

FieldTypeRequiredDescription
idstring (uuid)YesUnique wall identifier
startVec2YesStart point on XZ plane
endVec2YesEnd point on XZ plane
heightnumberYesWall height in meters
thicknessnumberYesWall thickness in meters
materialstringNoMaterial ID override for this wall
room_refsstring[]YesIDs of rooms on each side of the wall (typically 1–2)

openings[] — Opening

Openings are cut-outs in walls for doors and windows.

FieldTypeRequiredDescription
idstring (uuid)YesUnique opening identifier
typeOpeningTypeYes"door" or "window"
wall_refstring (uuid)YesID of the wall this opening belongs to
positionVec2YesPosition on the XZ plane (center of the opening)
widthnumberYesOpening width in meters
heightnumberYesOpening height in meters
sill_heightnumberYesHeight of the bottom edge above floor level (0 for doors)
swingDoorSwingNoDoor swing direction (only for type: "door")

DoorSwing Enum

ValueDescription
left_inwardHinged on the left, swings inward
left_outwardHinged on the left, swings outward
right_inwardHinged on the right, swings inward
right_outwardHinged on the right, swings outward

objects[] — SceneObject

All scene objects including furniture, appliances, and decorative items.

FieldTypeRequiredDescription
idstring (uuid)YesUnique object identifier
typestringYesObject class: "furniture" or "decoration"
categorystringYesCategory key matching the furniture catalog (e.g., "sofa", "bed", "dining_table")
asset_idstringNoExternal asset reference (unused for procedural objects)
room_refstring (uuid)NoID of the room this object is placed in
positionVec3YesWorld-space position in meters
rotationVec3YesEuler rotation in radians [rx, ry, rz]
scaleVec3YesScale factor [sx, sy, sz] (default [1, 1, 1])
sizeVec3YesBounding box dimensions in meters [width, height, depth]
material_overridesRecord<string, string>NoPer-part material overrides (key = part name, value = material ID)

The furniture catalog in src/data/furnitureCatalog.ts maps category keys to default colors and geometry instructions. The engine's furnitureModels.ts builds procedural meshes from these definitions using box, cylinder, and sphere primitives.


materials[] — SceneMaterial

Materials define the PBR (physically based rendering) appearance of surfaces.

FieldTypeRequiredDescription
idstringYesUnique material identifier (referenced by rooms, walls, objects)
typestringYesAlways "pbr"
namestringYesDisplay name (e.g., "Light Oak Wood", "Matte White")
base_colorstringYesHex color string (e.g., "#d1b387")
roughnessnumberYesSurface roughness (0 = mirror, 1 = completely rough)
metalnessnumberYesMetallic quality (0 = dielectric, 1 = fully metallic)
transparentbooleanNoWhether the material supports transparency
opacitynumberNoOpacity value (0 = fully transparent, 1 = opaque)
texture_urlsobjectNoTexture map references

texture_urls

KeyTypeDescription
base_colorstringAlbedo / base color map URL or texture:// protocol reference
normalstringNormal map for surface detail
roughnessstringRoughness map

When base_color uses the texture:// protocol (e.g., texture://oak), the engine generates the texture procedurally on canvas via proceduralTextures.ts.


lights[] — SceneLight

FieldTypeRequiredDescription
idstring (uuid)YesUnique light identifier
typeLightTypeYesLight type (see below)
namestringYesDisplay name
positionVec3YesWorld-space position
rotationVec3YesEuler rotation in radians
intensitynumberYesLight intensity (units depend on type)
colorstringYesHex color string
sizeVec2NoArea light dimensions (only for area type)

LightType Enum

ValueDescription
areaRectangular area light
pointOmnidirectional point light
spotDirectional spotlight cone
directionalParallel rays (sun-like)

cameras[] — CameraPreset

FieldTypeRequiredDescription
idstring (uuid)YesUnique camera identifier
namestringYesDisplay name (e.g., "Overview", "Living Room")
typeCameraTypeYes"perspective" or "orthographic"
positionVec3YesCamera world-space position
targetVec3YesLook-at target position
fovnumberYesField of view in degrees (perspective only)

parse_quality — ParseQuality

Injected by the pipeline after processing. Used by the frontend to display confidence scores and determine whether to show a review dialog.

FieldTypeDescription
overall_scorenumberOverall quality score (0–1)
geometry_scorenumberWall connectivity, room closure, overlap detection (0–1)
semantic_scorenumberRoom type classification confidence (0–1)
scale_scorenumberReal-world scale detection confidence (0–1)
image_alignment_scorenumberIoU between CV wall mask and rendered geometry (0–1)
needs_user_reviewbooleantrue if quality scores fall below thresholds
image_alignmentImageAlignmentReportDetailed alignment diagnostics (hybrid pipeline only)

ImageAlignmentReport

FieldTypeDescription
wall_iounumberIntersection over union of wall regions
wall_precisionnumberFraction of detected walls that match the image
wall_recallnumberFraction of image walls that were detected
overallnumberCombined alignment score

Complete Example

{
"schema_version": "1.0",
"project": {
"id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"name": "Modern Apartment",
"unit": "meter"
},
"global": {
"style": "modern",
"ceiling_height": 2.8,
"wall_thickness": 0.15,
"texture_overrides": {
"floor": "oak",
"wall": "white_plaster"
}
},
"rooms": [
{
"id": "room-001",
"type": "living_room",
"name": "Living Room",
"polygon": [
[0, 0],
[5.5, 0],
[5.5, 4.2],
[0, 4.2]
],
"area": 23.1,
"floor_material": "mat_modern_floor_living_room",
"wall_material": "mat_modern_wall",
"ceiling_material": "mat_modern_ceiling"
},
{
"id": "room-002",
"type": "bedroom",
"name": "Master Bedroom",
"polygon": [
[5.5, 0],
[9.0, 0],
[9.0, 4.2],
[5.5, 4.2]
],
"area": 14.7,
"floor_material": "mat_modern_floor_bedroom",
"wall_material": "mat_modern_wall",
"ceiling_material": "mat_modern_ceiling"
},
{
"id": "room-003",
"type": "kitchen",
"name": "Kitchen",
"polygon": [
[0, 4.2],
[3.8, 4.2],
[3.8, 7.5],
[0, 7.5]
],
"area": 12.54,
"floor_material": "mat_modern_floor_kitchen",
"wall_material": "mat_modern_wall",
"ceiling_material": "mat_modern_ceiling"
},
{
"id": "room-004",
"type": "bathroom",
"name": "Bathroom",
"polygon": [
[3.8, 4.2],
[5.8, 4.2],
[5.8, 7.5],
[3.8, 7.5]
],
"area": 6.6,
"floor_material": "mat_modern_floor_bathroom",
"wall_material": "mat_modern_wall",
"ceiling_material": "mat_modern_ceiling"
},
{
"id": "room-005",
"type": "corridor",
"name": "Hallway",
"polygon": [
[5.8, 4.2],
[9.0, 4.2],
[9.0, 5.2],
[5.8, 5.2]
],
"area": 3.2,
"floor_material": "mat_modern_floor_corridor",
"wall_material": "mat_modern_wall",
"ceiling_material": "mat_modern_ceiling"
}
],
"walls": [
{
"id": "wall-001",
"start": [0, 0],
"end": [9.0, 0],
"height": 2.8,
"thickness": 0.15,
"room_refs": ["room-001", "room-002"]
},
{
"id": "wall-002",
"start": [5.5, 0],
"end": [5.5, 4.2],
"height": 2.8,
"thickness": 0.15,
"room_refs": ["room-001", "room-002"]
},
{
"id": "wall-003",
"start": [0, 0],
"end": [0, 7.5],
"height": 2.8,
"thickness": 0.15,
"room_refs": ["room-001", "room-003"]
},
{
"id": "wall-004",
"start": [0, 4.2],
"end": [9.0, 4.2],
"height": 2.8,
"thickness": 0.15,
"room_refs": ["room-001", "room-003", "room-005"]
}
],
"openings": [
{
"id": "opening-001",
"type": "door",
"wall_ref": "wall-002",
"position": [3.5, 2.1],
"width": 0.9,
"height": 2.1,
"sill_height": 0,
"swing": "left_inward"
},
{
"id": "opening-002",
"type": "window",
"wall_ref": "wall-001",
"position": [2.5, 0],
"width": 1.8,
"height": 1.2,
"sill_height": 0.9
},
{
"id": "opening-003",
"type": "door",
"wall_ref": "wall-004",
"position": [7.0, 4.2],
"width": 0.9,
"height": 2.1,
"sill_height": 0,
"swing": "right_inward"
}
],
"objects": [
{
"id": "obj-001",
"type": "furniture",
"category": "sofa",
"room_ref": "room-001",
"position": [2.5, 0, 2.0],
"rotation": [0, 0, 0],
"scale": [1, 1, 1],
"size": [2.2, 0.85, 0.9]
},
{
"id": "obj-002",
"type": "furniture",
"category": "coffee_table",
"room_ref": "room-001",
"position": [2.5, 0, 3.2],
"rotation": [0, 0, 0],
"scale": [1, 1, 1],
"size": [1.2, 0.45, 0.6]
},
{
"id": "obj-003",
"type": "furniture",
"category": "bed",
"room_ref": "room-002",
"position": [7.2, 0, 2.1],
"rotation": [0, 0, 0],
"scale": [1, 1, 1],
"size": [1.8, 0.55, 2.0]
},
{
"id": "obj-004",
"type": "furniture",
"category": "dining_table",
"room_ref": "room-003",
"position": [1.9, 0, 5.8],
"rotation": [0, 0, 0],
"scale": [1, 1, 1],
"size": [1.6, 0.75, 0.9]
},
{
"id": "obj-005",
"type": "decoration",
"category": "plant",
"room_ref": "room-001",
"position": [0.5, 0, 0.5],
"rotation": [0, 0.4, 0],
"scale": [1, 1, 1],
"size": [0.4, 1.2, 0.4]
}
],
"materials": [
{
"id": "mat_modern_floor_living_room",
"type": "pbr",
"name": "Light Oak Wood",
"base_color": "#d1b387",
"roughness": 0.65,
"metalness": 0.0,
"texture_urls": {
"base_color": "texture://oak"
}
},
{
"id": "mat_modern_wall",
"type": "pbr",
"name": "Matte White",
"base_color": "#f2f2ee",
"roughness": 0.9,
"metalness": 0.0
},
{
"id": "mat_modern_ceiling",
"type": "pbr",
"name": "Ceiling White",
"base_color": "#ffffff",
"roughness": 0.95,
"metalness": 0.0
},
{
"id": "mat_modern_floor_kitchen",
"type": "pbr",
"name": "Light Gray Tile",
"base_color": "#ccccbe",
"roughness": 0.3,
"metalness": 0.0,
"texture_urls": {
"base_color": "texture://tile"
}
},
{
"id": "mat_modern_floor_bathroom",
"type": "pbr",
"name": "White Marble Tile",
"base_color": "#ede8e0",
"roughness": 0.2,
"metalness": 0.05,
"texture_urls": {
"base_color": "texture://marble"
}
}
],
"lights": [
{
"id": "light-001",
"type": "directional",
"name": "Sun",
"position": [5, 10, 5],
"rotation": [-0.5, 0.3, 0],
"intensity": 0.8,
"color": "#faf0e8"
},
{
"id": "light-002",
"type": "point",
"name": "Living Room Ceiling Light",
"position": [2.75, 2.6, 2.1],
"rotation": [0, 0, 0],
"intensity": 500,
"color": "#fff2d9"
},
{
"id": "light-003",
"type": "point",
"name": "Bedroom Ceiling Light",
"position": [7.25, 2.6, 2.1],
"rotation": [0, 0, 0],
"intensity": 400,
"color": "#fff2d9"
}
],
"cameras": [
{
"id": "cam-001",
"name": "Overview",
"type": "perspective",
"position": [4.5, 8, 12],
"target": [4.5, 0, 3.75],
"fov": 50
},
{
"id": "cam-002",
"name": "Living Room",
"type": "perspective",
"position": [1.5, 1.6, 1.5],
"target": [4.0, 1.0, 3.0],
"fov": 60
}
],
"parse_quality": {
"overall_score": 0.87,
"geometry_score": 0.92,
"semantic_score": 0.88,
"scale_score": 0.91,
"image_alignment_score": 0.78,
"needs_user_review": false,
"image_alignment": {
"wall_iou": 0.82,
"wall_precision": 0.89,
"wall_recall": 0.76,
"overall": 0.78
}
}
}

Design Principles

Flat Hierarchy

All entity arrays are defined at the root level. Rooms do not contain walls or objects -- instead, relationships are expressed through references (room_refs, wall_ref, room_ref). This flat structure simplifies serialization, diffing, partial updates, and direct consumption by the Three.js engine.

Referential Integrity

Cross-references between entities use UUID strings. The engine's buildScene.ts resolves these references at build time and silently skips objects with dangling references rather than crashing. The pipeline's repair.rs attempts to fix broken references automatically.

Extensibility

New entity types or fields can be added to the schema without breaking existing consumers. The frontend engine ignores unknown fields and entity types, enabling forward-compatible schema evolution. The schema_version field tracks the format for migration purposes.