跳到主要内容

数据模型 — HomeSceneJSON

HomeSceneJSON 是 Planova 的核心数据结构。它是表示完整室内场景的唯一事实来源:每个房间、墙体、门、家具、材质、灯光和相机位置。AI 流水线产生它,前端存储它,3D 引擎根据它进行渲染。

规范的 TypeScript 定义位于 src/types/scene.ts。Rust 后端在 src-tauri/src/models.rs 中维护自己的模型,用于持久化和 IPC。

Schema 概览

坐标系

HomeSceneJSON 中所有空间值使用作为计量单位,采用 Y 轴向上的坐标系:

  • X -- 左 / 右
  • Y -- 上 / 下(垂直轴,高度)
  • Z -- 前 / 后

高度沿 Y 轴测量。房间多边形(Vec2)和墙体起止位置定义在 XZ 平面上。物体位置(Vec3)包含 Y 分量,用于表示距地面的高度。

基本类型

类型描述示例
string文本值"living_room"
number浮点值3.6
boolean布尔标志true
Vec22D 向量 [x, z][4.5, 3.2]
Vec33D 向量 [x, y, z][1.0, 2.4, 3.0]
uuid通用唯一标识符字符串"a1b2c3d4-..."

根文档

字段类型必填描述
schema_versionstringSchema 版本(如 "1.0"
projectHomeSceneProject项目元数据
globalHomeSceneGlobal全局场景设置
roomsRoom[]房间定义
wallsWall[]墙体线段
openingsOpening[]门和窗
objectsSceneObject[]家具和装饰物品
materialsSceneMaterial[]PBR 材质定义
lightsSceneLight[]光源
camerasCameraPreset[]保存的相机位置
parse_qualityParseQuality流水线质量指标(由流水线注入)

project — HomeSceneProject

字段类型描述
idstring (uuid)唯一项目标识符
namestring人类可读的项目名称
unitstring计量单位。目前始终为 "meter"

global — HomeSceneGlobal

字段类型默认值描述
stylestring"modern"室内风格预设(如 modernminimalistscandinavianindustrialjapaneseluxury
ceiling_heightnumber2.8默认天花板高度(米)
wall_thicknessnumber0.15默认墙体厚度(米)
texture_overridesobjectundefined可选的全局纹理覆盖映射

texture_overrides

类型描述
floorstring覆盖所有地面的纹理 ID
wallstring覆盖所有墙面的纹理 ID
ceilingstring覆盖所有天花板的纹理 ID

设置后,这些覆盖在场景构建时优先于每个房间的材质分配。


rooms[] — Room

每个房间代表 AI 流水线识别出的一个独立封闭空间。

字段类型必填描述
idstring (uuid)唯一房间标识符
typeRoomType来自预定义枚举的房间类型
namestring显示名称(如 "主卧")
polygonVec2[]XZ 平面上的地面多边形顶点,按绕序排列
areanumber计算面积(平方米)
floor_materialstring地面材质 ID
wall_materialstring房间特定墙面的材质 ID
ceiling_materialstring天花板材质 ID

RoomType 枚举

描述
living_room主要起居/娱乐空间
bedroom卧室
kitchen带电器区域的厨房
bathroom带卫浴设施的湿区
dining_room专用就餐区
balcony与室外相邻的延伸空间
corridor通行走廊
study家庭办公室或书房

流水线使用 mat_{style}_{surface}_{room_type} 模式分配材质 ID(如 mat_modern_floor_living_room)。前端引擎根据 materials[] 数组解析这些 ID。


walls[] — Wall

墙体定义为 XZ 平面上具有物理尺寸的线段。

字段类型必填描述
idstring (uuid)唯一墙体标识符
startVec2XZ 平面上的起点
endVec2XZ 平面上的终点
heightnumber墙高(米)
thicknessnumber墙厚(米)
materialstring该墙体的材质 ID 覆盖
room_refsstring[]墙体两侧的房间 ID(通常 1–2 个)

openings[] — Opening

开洞是墙体上用于门和窗的缺口。

字段类型必填描述
idstring (uuid)唯一开洞标识符
typeOpeningType"door""window"
wall_refstring (uuid)该开洞所属墙体的 ID
positionVec2XZ 平面上的位置(开洞中心)
widthnumber开洞宽度(米)
heightnumber开洞高度(米)
sill_heightnumber底边距地面的高度(门为 0)
swingDoorSwing门的开启方向(仅用于 type: "door"

DoorSwing 枚举

描述
left_inward左侧铰链,向内开
left_outward左侧铰链,向外开
right_inward右侧铰链,向内开
right_outward右侧铰链,向外开

objects[] — SceneObject

所有场景物体,包括家具、电器和装饰品。

字段类型必填描述
idstring (uuid)唯一物体标识符
typestring物体类别:"furniture""decoration"
categorystring匹配家具目录的类别键(如 "sofa""bed""dining_table"
asset_idstring外部资源引用(程序化物体未使用)
room_refstring (uuid)该物体放置所在房间的 ID
positionVec3世界空间位置(米)
rotationVec3欧拉旋转(弧度)[rx, ry, rz]
scaleVec3缩放因子 [sx, sy, sz](默认 [1, 1, 1]
sizeVec3包围盒尺寸(米)[width, height, depth]
material_overridesRecord<string, string>按部件的材质覆盖(键 = 部件名称,值 = 材质 ID)

src/data/furnitureCatalog.ts 中的家具目录将类别键映射到默认颜色和几何体指令。引擎的 furnitureModels.ts 使用盒体、圆柱和球体基元从这些定义构建程序化网格。


materials[] — SceneMaterial

材质定义表面的 PBR(基于物理的渲染)外观。

字段类型必填描述
idstring唯一材质标识符(被房间、墙体、物体引用)
typestring始终为 "pbr"
namestring显示名称(如 "浅橡木"、"哑光白")
base_colorstring十六进制颜色字符串(如 "#d1b387"
roughnessnumber表面粗糙度(0 = 镜面,1 = 完全粗糙)
metalnessnumber金属质感(0 = 电介质,1 = 完全金属)
transparentboolean材质是否支持透明
opacitynumber不透明度(0 = 完全透明,1 = 不透明)
texture_urlsobject纹理贴图引用

texture_urls

类型描述
base_colorstring反照率/基础颜色贴图 URL 或 texture:// 协议引用
normalstring法线贴图(用于表面细节)
roughnessstring粗糙度贴图

base_color 使用 texture:// 协议(如 texture://oak)时,引擎通过 proceduralTextures.ts 在 canvas 上程序化生成纹理。


lights[] — SceneLight

字段类型必填描述
idstring (uuid)唯一灯光标识符
typeLightType灯光类型(见下文)
namestring显示名称
positionVec3世界空间位置
rotationVec3欧拉旋转(弧度)
intensitynumber灯光强度(单位取决于类型)
colorstring十六进制颜色字符串
sizeVec2面光源尺寸(仅用于 area 类型)

LightType 枚举

描述
area矩形面光源
point全向点光源
spot方向性聚光灯锥
directional平行光线(类似太阳)

cameras[] — CameraPreset

字段类型必填描述
idstring (uuid)唯一相机标识符
namestring显示名称(如 "总览"、"客厅")
typeCameraType"perspective""orthographic"
positionVec3相机世界空间位置
targetVec3观察目标位置
fovnumber视野角度(仅用于透视相机)

parse_quality — ParseQuality

由流水线在处理后注入。前端用于显示置信度分数,并决定是否展示审核对话框。

字段类型描述
overall_scorenumber整体质量分数(0–1)
geometry_scorenumber墙体连通性、房间封闭性、重叠检测(0–1)
semantic_scorenumber房间类型分类置信度(0–1)
scale_scorenumber真实世界比例检测置信度(0–1)
image_alignment_scorenumberCV 墙体蒙版与渲染几何体之间的 IoU(0–1)
needs_user_reviewboolean质量分数低于阈值时为 true
image_alignmentImageAlignmentReport详细对齐诊断(仅 Hybrid 流水线)

ImageAlignmentReport

字段类型描述
wall_iounumber墙体区域的交并比
wall_precisionnumber检测到的墙体中与图像匹配的比例
wall_recallnumber图像中被检测到的墙体比例
overallnumber综合对齐分数

完整示例

{
"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
}
}
}

设计原则

扁平层级

所有实体数组均定义在根级别。房间不包含墙体或物体——关系通过引用表达(room_refswall_refroom_ref)。这种扁平结构简化了序列化、差异比较、部分更新,以及 Three.js 引擎的直接消费。

引用完整性

实体间的交叉引用使用 UUID 字符串。引擎的 buildScene.ts 在构建时解析这些引用,对悬空引用静默跳过而非崩溃。流水线的 repair.rs 会尝试自动修复损坏的引用。

可扩展性

可以向 schema 添加新的实体类型或字段,而不会破坏现有消费者。前端引擎忽略未知字段和实体类型,实现了前向兼容的 schema 演进。schema_version 字段用于跟踪格式版本以便迁移。