用 React Three Fiber 做一套智慧医院数字孪生:编辑器、大屏和 BIM 浏览器
做楼宇数字孪生时,经常会把「好看的三维」和「能改的后台」拆成两套系统。这个项目把它们放在同一个前端里:同一套三维场景,既能在后台摆设备,也能直接切到可视化大屏;旁边再挂一个本地解析的 IFC 浏览器。场景目前落在一座智慧医院综合体上,周边是程序化生成的城市。
下面按实际做出来的能力写,预留和演示数据会单独标出来,避免和已经跑通的功能混在一起。
产品分成四条入口
路由按路径分流,不靠多页框架:
| 入口 | 路径 | 做什么 |
|---|---|---|
| 后台编辑器 | / | 摆设备、改楼层、调场景,保存孪生数据 |
| 可视化大屏 | /screen | 同一套三维场景加上指标、图表和楼层导航 |
| BIM 浏览器 | /bim | 浏览器里打开 IFC,做构件树、测量和剖切 |
| 三维设计 | /design | 嵌入外部参数化设计器(本机 127.0.0.1:5000) |
编辑器和大屏共用同一个 BuildingScene,天空、灯光、地面、天气和后期不会各画一套。桌面端用 Electron 打成 Windows 安装包和便携版,产品名是「智汇数字孪生编辑器」。
技术栈:React 19、TypeScript、Vite、Zustand、Ant Design 6(暗色)、Three.js、React Three Fiber、drei、ECharts、web-ifc-three。
医院场景本身
主场景不是一张贴图楼,而是按医院综合体拆开的体块:
- 主塔楼约 15 层,白板立面加横向镀膜玻璃。玻璃按块拼,一层两行,外面反光、不看穿室内。
- 门诊裙房在南侧,正中是「门诊」门廊。
- 东西侧翼标成 3 号楼、5B 号楼,中间有连廊。
- 南大门是石柱门楼,门楣写「龙国第一医院」,车道居中,两侧是伸缩门和花坛。
- 屋顶字标:南檐是中英文院名,北檐是「住院部」,表示住院部在楼后。
- 院内:围墙、石材地坪、广场行道树、路灯。门前是水泥路网,接到南侧市政路;围墙上有医药主题海报。
- 停车场:广场两侧地面车位,含无障碍车位、急救车位和停车标志。
楼层按医院用房排:地下车库、门诊大厅、门诊层、医技层、病房层、行政层,最上面是屋顶机房。总层数可以改,某一层还可以单独改面宽、进深和层高。楼体是固定构件,不能像设备那样拖走。
院墙外面是一套程序化城市,大约 64 米一格的街区,路网、标线和夜景亮窗都画在 shader 里。分区包括住宅、商务办公、科创、商业、公共配套,再加上生态湖和东侧水岸。场景里用气泡标出综合楼、门诊裙房、侧翼、门前广场和这几片城区。
后台编辑器
编辑器是典型的三栏:左边素材,中间视口,右边属性。
场景文件。 新建会回到出厂布点。保存优先写后端 PUT /api/dt/scene(设备和已摆放的特效);后端没开时落到浏览器本地。打开时同样先请求后端,没有存档就提示。撤销、重做走设备列表的历史栈,快捷键是 Ctrl+Z / Ctrl+Y。
设备库。 十五类低模设备,拖进视口或从表单添加,编码必填:
- 物联感知:温湿度、CO₂、烟感、能耗电表、水表
- 暖通:空调机组、风机盘管
- 机电电气:电梯、配电柜、水泵
- 消防安防:消火栓、半球摄像机、枪机、门禁
- 车位
选中之后可以改名字、颜色、透明度、位置、旋转和缩放。移动直接拖,旋转和缩放走变换手柄。Delete 删除。搜索框按名称、编码、类型过滤,点一条就飞到那个设备,并弹出三维信息条。
图层。 建筑、结构、机电、暖通、电气、消防、弱电、管网、摄像机、车位、绿化、特效、分区标注可以单独开关。部分图层还能调透明度,用来看楼里的设备和管线。
楼层查看。 三件事是分开的:
- 楼层展开:把各层沿高度拉开
- 楼层剖切:藏掉所选层以上的楼板和设备
- 楼层直达:只留一层,方便改这一层的设备
模型树按楼层列出设备和特效,点一层可以改这一层的尺寸。
视口。 浏览模式和编辑模式分开。浏览时不能拖设备,漫游、定位和热力还能用。另外有:
- 第一人称漫游(WASD,落在当前楼层)
- 保安巡逻:第三人称沿着广场环线走,和漫游互斥
- 昼夜和灯光预设
- 晴、雨、雪,以及雾的类型、颜色和距离
- 天空、曝光、环境反射、阴影和辉光
- 玻璃颜色、粗糙度、金属度和透明度预设
- 空间热力:能耗、温度、CO₂、人员密度、出租率、工位使用率
热力目前是按楼层算出的演示色,物联网接上之后再换成实测值。
特效库。 可以从左侧拖到地面:
- 粒子:火焰、烟雾、烟花、喷泉、火圈、龙卷风、体积云
- 着色器:雷达、电子围栏、警告光圈、全息光柱、扩散波纹等
- 树草:白蜡、橡树、松树和草坪块,树可以改形态参数
这些对象和设备一起保存。
物联网配置。 每台设备都能填协议(MQTT、Modbus TCP、OPC UA、HTTP)、地址和测点。现在平台还没接,状态是「未接入」;填过的内容会随场景保存,接入后不用再改点位结构。接入总览里也能看到全部设备仍是预留状态。
顶栏的「发布」和「设置」还是占位:发布只弹出提示,模型版本管理尚未做。
可视化大屏
/screen 把编辑器里的场景放到中间,左右挂指标。后端可用时读 dt-api(默认 127.0.0.1:9100),大约 15 秒刷新一次;连不上就改用本地演示数,页面上会标明数据源。
已经铺上的块:
- 设备总数、未接入数、今日能耗、平均温度、平均 CO₂、在场人数、出租率、空闲车位
- 24 小时温度 / 湿度 / CO₂
- 按系统统计的设备分布(这块跟当前场景里的设备数走,不是写死的)
- 各层能耗强度
- 出租率和工位使用率
- 告警列表(未接入时为空)
- 物联网状态:协议预留,在线数据源为 0
三维这边保留搜索定位、楼层直达、楼层展开、空间着色,以及建筑、结构、管网、暖通、绿化的显隐。点设备弹出详情卡;摄像头类型预留了视频播放(hls.js)。工具条里可以自动巡游、复位和全屏。
BIM 浏览器
/bim 用 web-ifc-three 在浏览器里解析 IFC,不把模型先转到服务端。
- 打开本地
.ifc,或加载示例 - 另有「楼层结构还原」和按层加载机电(1、2、3、7、8、9 层)
- 构件树可搜索,支持隐藏、隔离、聚焦
- 点构件看 IFC 属性,按属性集分组
- 测距离、面积、角度;Enter 结束一组测量
- 剖切盒,拖面改范围
- 前、后、左、右、顶、底六个标准视图,以及旋转、复位、清空
- 状态栏给出文件名、构件数、三角面数和加载耗时
三维设计页是另一条线:探测本机设计服务是否在线,在线就用 iframe 嵌进去,离线就提示地址。模版、房子和参数化建模在那个服务里,不在本仓库的三维场景里。
数据怎么接
编辑器状态用 Zustand。场景持久化只提交两样:设备列表、已放置的特效和树。楼体几何仍由代码生成,不进存档。
大屏和编辑器约定同一套后端。接口不可用时,编辑器退回本地存档,大屏退回演示曲线,三维场景本身照常转。这样没接物联网平台时,布点、漫游和演示可以先用。
适合继续写的点
如果这篇要再拆技术文,比较值得单独写的是:
- 医院立面怎么用实例化玻璃块拼出来,并避开楼面共面闪烁
- 城市路网和楼体用 shader 分区,而不是成千上万个贴片
- 编辑器和大屏共用一个 R3F 场景时,浏览态和编辑态怎么隔开
- IFC 在浏览器里做构件树、测量和剖切盒
物联网实时值、告警推送和模型版本管理还没接上。现在的重点是把医院场景、设备布点和三条查看入口先跑通。