做上位机监控这些年,被客户要求最多的不是功能,而是画面要“像一个3D游戏的界面”。实际上在WinCC 8.0之前的版本,想在画面里显示一个能跟着PLC数据动的三维设备,通常只能靠外部插件或者写一堆脚本去控制第三方控件,成本高不说,和WinCC的变量系统集成也麻烦。WinCC 8.0自带的WinCC 3D Control控件改变了这种局面,它可以直接在画面编辑器中加载3D模型,跟PLC变量做联动。这篇文章就围绕这个控件,把我自己的踩坑经历和整理出来的操作路线完整写出来,对正在做数字化车间、设备在线监测或者产线仿真画面的工程师应该会有用。
1. 为什么WinCC 8.0里需要单独的3D控件:我的选型背景
1.1 客户眼中的“3D画面”和组态工程师眼中的3D不是一回事
客户提到3D,通常想的是“画面看起来立体”:有阴影、视角能拖、设备像真的一样。但组态工程师眼里的3D是另一套问题:模型能不能被PLC数据驱动,报警时会不会变色,切换画面时会不会崩溃,WinCC升级之后还能不能继续用。这两套诉求经常对接不上。
如果在WinCC里不用官方3D控件,过去通常有三条路。第一条是用图形编辑器里的2D图符堆叠出等轴测效果,也就是伪3D,换个观察角度就露馅,动作动画也只能靠位移和闪烁来模拟。第二条是用外部3D引擎做一套画面,比如Unity或Unreal,然后通过OPC和WinCC通信,显示效果确实好,但开发和联调成本高,对工厂IT环境也有额外要求。第三条是找第三方ActiveX控件嵌进WinCC界面,按授权点收费,升级WinCC版本后还容易崩。
WinCC 3D Control这条路线,最大的优势在于它属于西门子自家体系,拖到画面里就能和WinCC变量系统、报警系统、用户管理共用一套运行环境,不需要额外通信中间件。虽然它的功能上限不如游戏引擎,但用在工业监控场景里,性价比非常突出。
1.2 WinCC 3D Control解决了什么,没解决什么
先说它擅长的部分。WinCC 3D Control可以加载glTF/GLB格式的三维模型,并把模型里的节点暴露给WinCC脚本。这意味着你可以让某个设备部件按照PLC的数据移动、旋转、缩放,也可以改变模型的可见性和颜色。对一个典型的上位机监控画面来说,这已经覆盖了80%的展示需求:液位升降、阀门开关、电机旋转、报警变色、视角漫游。
但它不是万能的。它不是CAD软件,不会帮你做尺寸测量;也不是游戏引擎,不会有物理碰撞、粒子系统、复杂反射。如果你想做的是“工作人员可以第一人称在车间里走动、开门、拿工具”那种互动漫游,这个控件不是很合适。它的强项是把单个设备或一条产线的核心动作同步成可视化效果,而不是做一个开放的虚拟工厂。
这一点一定要提前和客户对齐,否则项目验收时会非常被动。我在一个项目里遇到客户要求“像CFD动画一样看到内部流体流动”,WinCC 3D Control做不了流体粒子,后来只能改用外部动画序列和切面透明来模拟,好在现场展示效果够用才过关。
1.3 环境与选型:软件版本、显卡和模型格式
我在WinCC 8.0上做验证,操作系统是Windows 10专业版。3D Control在完整安装WinCC后一般会出现在画面对象栏里,如果找不到,检查安装选件里是否勾选了3D Controls相关组件。另外,显卡驱动一定要更新到支持DirectX 11以上的版本,虚拟机、远程桌面环境下3D性能会明显缩水,现场工控机建议至少配一块入门级独立显卡,不需要多贵,但比核显稳定很多。
模型格式方面,WinCC 3D Control原生支持glTF 2.0,通常使用二进制格式的GLB文件。很多工程师一开始想直接传STEP或IGES,这个控件不支持,必须转换。而转换后的模型面数通常很高,材质层级也可能丢失,所以后面模型准备阶段反而是整个项目里最花时间的环节。
| 模型格式 | 能否直接使用 | 材质/动画/节点层级 | 推荐度 |
|---|---|---|---|
| GLB/glTF | 支持 | 完整保留 | 主推 |
| OBJ | 需转换 | 材质一般,无节点层级 | 应急使用 |
| STL | 需转换 | 无材质无层级 | 不推荐 |
| STEP/IGES | 需转换 | 无材质,面数爆炸 | 不推荐直接用 |
2. 模型准备阶段最该花时间的不是建模,而是导出GLB
2.1 为什么非要用glTF/GLB,而不是直接用原始模型
glTF之于3D模型,就像JPEG之于照片。它把网格、材质、贴图、动画、节点层级都封装在一个相对精简的文件里,运行时不依赖原始建模软件就能被解析。WinCC 3D Control内部识别glTF,原因很简单:工控机性能有限,glTF的二进制格式加载效率高,而且支持PBR材质和节点动画,对设备监控刚好够用。
OBJ和STL在工控领域虽然常见,但各有各的问题。OBJ的材质依赖外部MTL文件,路径一变就丢纹理,STL干脆就是一堆三角形,没有颜色、没有材质、没有层级。如果拿STEP导出的STL硬塞给3D控件,最终大概率看到一堆白面,设备部件完全分不清。真正需要保留设备结构层级和运动关系时,GLB是唯一适合直接给这个控件用的格式。
2.2 Blender导出GLB的参数设置
模型整理和转换,我强烈建议用Blender,免费且对glTF支持最好。整个过程分三步。
第一步,把原始模型整理后导入Blender。如果原始模型是SolidWorks导出的STP,可以先用FreeCAD或转换工具转成OBJ,再导入Blender。这一步会丢失装配体层级,所以后续必须在Blender里重新整理节点父子关系。如果设备厂家直接提供了glb/gltf,这一步可以跳过。
第二步,检查材质和贴图。在Blender里使用Principled BSDF材质,把Base Color连上纹理贴图。特别注意,所有贴图都必须确保文件能被正常加载,导出前在“文件 > 外部数据 > 打包资源”里把图片嵌入文件,否则运行时会因为贴图路径丢失而变成黑模。
第三步,导出。菜单“文件 > 导出 > glTF 2.0”,格式选GLB,不要选分离的glTF,这样所有数据都在一个文件里。在导出选项里,优先关闭Draco网格压缩。很多版本的WinCC 3D Control不内置Draco解码,开启后模型加载会失败,具体表现就是不显示模型但也不报错。其他选项保持默认即可,用最简单的配置最稳。
导出时建议的选项: - 格式: GLB - 网格压缩: 关闭 - 纹理: 自动嵌入 - 单位: 米 - +Y Forward / +Z Up(按Blender默认)2.3 面数、层级、坐标原点和单位这几个细节决定后面能不能动
很多项目卡在“模型不能动”上,不是脚本问题,而是模型组织问题。我自己总结出四个最关键的细节。
第一,面数。工控机不像游戏主机,模型面数尽量控制在五十万三角形以内。可视化监控一般只看外形和动作,十到二十万面已经足够逼真。如果原模型有两百万面,就用Blender的Decimate修改器减面,保留轮廓即可。
第二,节点层级。在Blender的Outliner里,给每个需要独立运动的部件重新命名。比如搅拌釜的液面命名为“Liquid”,搅拌桨命名为“Impeller”,箱体命名为“Tank_Body”。节点名最终会出现在WinCC 3D Control的模型树里,建议全部用英文或拼音且不带空格,不要用中文,否则后面写脚本访问节点会非常痛苦。
第三,坐标原点。设备模型的基准点尽量放在底部中心,液面等可动部件也把原点放在自己的底部。原点偏了,旋转和缩放就会围绕错误中心,看起来像在“飘”。
第四,单位。Blender场景单位设置为米。如果原模型是毫米,导入后需要整体缩放。WinCC控件里的位置属性通常以米为单位,单位错了模型大小会差出1000倍,加载后什么都看不见。
2.4 免费模型资源与格式转换的几个路子
不用自己从零建模的情况下,可以找现成的免费3D模型。Khronos官方提供了一批glTF Sample Models,适合先测试控件是否正常。如果做设备模型展示,可以到素材站搜“泵”“阀”“电机”等关键词,下载时注意筛选支持gltf/glb格式的文件。
现在还有一些“图片生成3D模型”的工具,输入照片就能生成glb文件,用来做设备外形示意可以,但生成的模型面数不可控,网格拓扑很乱。真要用在WinCC里,必须经过Blender减面和材质重制。类似地,从电子设计软件导出的元器件模型,比如用立创3D模型下载器拿到的step模型,也要走Blender转换一遍。
我的原则是:任何模型进入WinCC之前,都必须经过Blender检查材质和节点层级。不要相信一次转换能直接到位,尤其是设备模型,提前花半小时整理节点,后面组态能省半天。
3. 在WinCC画面里把GLB模型“摆进”三维场景
3.1 插入控件并加载模型的两种方式
打开WinCC图形编辑器,新建画面,在对象面板下拉列表中找到“3D Control”控件,拖到画面上。控件拖进去后默认会显示一个网格场景和小模型,这时候可以先确认控件能正常渲染。
加载模型有两种方式。第一种是组态时通过属性对话框加载:右键控件,打开属性设置,找到模型文件路径属性,选择GLB文件,然后保存画面。这种方式适合固定模型,项目启动后立即显示,现场操作工不需要做任何切换。
第二种是运行时用脚本加载。在画面的打开事件或某个按钮的点击事件里,给控件指定模型路径。好处是可以在同一个画面里切换不同型号设备的模型。比如切换按钮分组,分别加载A型机和B型机的模型。但要注意,切换模型会释放之前的场景,如果PLC变量还绑定着旧节点,需要先做好空对象判断或者解除绑定。
示意代码大致是这样:
Dim obj3D Set obj3D = ScreenItems("Ctrl3D1") obj3D.LoadModel "D:\Project\3DModels\MixerTank.glb"具体方法名以控件自带的帮助文档为准,思路是通用的。
3.2 模型树:节点的命名就是你后面写脚本的id
加载成功后,再次打开控件属性对话框,一般会看到一个场景树或模型树,里面列出了模型内的节点。比如根节点“Tank_Body”下面有“Liquid”、“Impeller”、“Pipe_in”、“Pipe_out”等子节点。这里非常重要:这些节点名称会成为脚本里的访问路径,所以最好在模型导出前就规范命名,而不是在WinCC里临时改。
我建议做一份“模型节点命名表”,自控工程师和建模工程师各留一份。比如:
| 节点类型 | 命名规范 | 示例 |
|---|---|---|
| 静止壳体 | 设备全称 | Tank_Body |
| 运动部件 | 英文功能名 | Impeller_1 |
| 液面/填充 | Liquid_Level | Liquid_Tank1 |
| 报警变色表面 | 默认名+Alarm后缀 | Body_Alarm |
脚本访问时,多数情况下用类似“/Tank_Body/Liquid_Tank1”这样的节点路径。节点名里有空格或特殊符号,脚本就要转义,特别容易出问题,所以命名越简单越好。
3.3 设置相机、灯光和地面:让画面不像“工业灰”
模型加载进来后,默认场景往往又暗又平。需要手动做几件事。
第一,放一个相机。在模型树里选择或新建相机节点,设置目标点看向设备中心,位置一般放在45度俯视角,视野角度控制在30到45度之间。相机的远近裁剪面要设置合理,太近会把模型切掉,太远会引发深度缓冲精度问题。
第二,调整灯光。工业场景最常用的是平行光加环境光。平行光阴影开启后更有立体感,但阴影贴图分辨率不要太高,否则老电脑会卡。内部结构需要打亮时,可以加一个点光源放在模型中心,但点光源数量尽量不超过3个。
第三,设置背景和地面。背景改成深灰或深蓝,比默认纯黑显得专业。地面网格看甲方喜好,我建议默认关闭,需要空间感时再打开。反射功能非常耗性能,WinCC 3D Control对反射的支持也有限,不要在设备材质上把金属度拉满,用粗糙度0.3左右模拟金属感就够了。
3.4 保存画面后再次打开模型丢失的处理
这是非常常见的坑。组态时模型文件放在D盘某个临时文件夹,保存画面,关闭项目,第二天打开,模型没了,场景空荡荡。原因很简单:WinCC项目里记录的模型路径是绝对路径,但你复制项目或者换电脑之后,原路径不存在了。
推荐做法是在WinCC项目目录下建一个“3DModels”文件夹,把项目用到的GLB文件全部放进去。这样整个项目文件夹整体复制到新电脑上,模型跟着走,不会丢。另外,不要在模型路径里使用中文和特殊符号,部分Windows系统下WinCC底层加载会失败。如果模型已经丢失,只需在控件模型属性里重新选择一次文件,保存画面即可,但最好从源头就把路径规范好。
4. 让模型“活”起来:PLC变量驱动3D对象
4.1 先弄懂控件的对象模型:节点、属性与变量映射
WinCC 3D Control暴露给脚本的核心概念是场景和节点。场景里有根节点和子节点,每个节点有位置、旋转、缩放、可见性、材质颜色等属性。如果你接触过任何3D引擎,这个结构几乎是一样的。
要让设备动作,本质上就是把PLC变量的值映射到节点属性上。比如液位变送器输出0到100%的实数,你希望对应到液面模型的上升高度,那就需要把PLC变量和液面节点的Position.Y或Scale.Y做关联。
这里要注意,WinCC的变量更新不是实时的,你可以配置变量更新周期,最快可能到几百毫秒。3D显示本身也有刷新周期,不建议用PLC变量直接驱动相机连续旋转,那样画面会一顿一顿。更稳妥的方法是把PLC值读入脚本,在脚本里做平滑处理,比如取上一次值的70%加上新值的30%,让动作看起来更顺滑。
4.2 从变量到动画的绑定路径
实际操作时有两条路径。
第一条是属性连接。在控件属性对话框里,选中节点属性后连接外部变量。这种方式最简单,适合液位、位移、阀门开度这类线性关系。难点在于量程换算:液位变量是0到100%,液面模型高度可能是0到1.5米,你需要把PLC变量线性映射到Position.Y的范围内。如果属性连接里不方便写复杂表达式,就去脚本里做。
第二条是C/VBS脚本。脚本的灵活性高,可以在一个循环触发器里读取多个PLC变量,根据状态判断决定节点的可见性和颜色。我一般这样写:画面里放一个循环触发器,时间设为500毫秒,触发一段脚本,脚本先调用读取标签函数,再对控件节点属性赋值。
常规的VBS脚本结构长这样:
Dim level, obj3D level = HMIRuntime.Tags("Level_PV").Read Set obj3D = ScreenItems("Ctrl3D1") obj3D.Scene.Nodes("Liquid").Transform.Position.Y = level * 0.015上面是示意代码,WinCC具体小版本对控件对象接口的命名可能不同,但方向是一样的:先读变量,再找节点,再赋值属性。
4.3 一个真实案例:设备运行状态/数值绑定到模型颜色和旋转
我在现场做过一个搅拌设备监控画面,用了三个变量:液位、搅拌电机频率、设备报警状态。
液位变量是0到100%,对应液面节点“Liquid”的Position.Y,换算系数是0.015米每百分比,液面从0爬到1.5米。有人会问为什么不用Scale.Y缩放液面,因为液面通常是扁平平面,用位移更自然;如果是圆柱体液面,也可以缩放高度,但注意不要缩放X和Z,否则液面直径会变。
搅拌电机频率进入脚本后,控制“Impeller”节点绕Y轴旋转。频率值乘以一个系数得到每次递增的角度,每500毫秒在原有角度上累加。这里要用增量角度而不是绝对角度,否则频率变化时转动看起来会不连续。
报警变量为1时,脚本把“Body_Alarm”节点的材质颜色改为红色,再用一个内存位模拟闪烁,即交替切换可见性或透明度。闪烁周期我控制在500毫秒,太快的闪烁会让人视觉疲劳,现场也会对系统稳定性产生质疑。
4.4 VBS脚本踩坑经验:对象名大小写和方法调用时机
脚本写多了,踩过的坑我列几条最典型的。
第一,ScreenItems名称必须和画面里的控件名称一致。控件放在画面里默认名可能是“WinCC3DControl1”,脚本里写成了别的名字,拿到的就是空引用。建议在脚本开头先把控件对象赋给一个短变量,后面统一用它。
第二,初始化时机。如果画面打开事件里马上调用加载模型或读取节点,控件可能还没完成初始化,脚本会报错。比较稳妥的做法是在画面打开后延时几百毫秒再加载模型,或者把加载动作放在按钮点击事件里。
第三,属性名大小写。VBS通常不区分大小写,但COM接口底层有些仍然区分。遇到“找不到成员”错误时,去帮助文档里复制准确属性名,不要自己猜。
第四,不要频繁读PLC。循环触发器中每500毫秒读一次标签还好,但如果你开了多个画面,每个画面都有3D脚本,标签访问量会成倍增加,CPU容易飙高。建议用变量变化触发器替代固定循环,或者把变量统一读到内部数据结构里再集中分发。
第五,变量不存在时脚本会静默失败。运行阶段如果把PLC变量删掉,脚本不会报错,但模型不动。调试时可以在脚本里临时加一个输出语句,确认变量是否真的读取成功。
5. 我用下来最头疼的四个问题以及排查思路
5.1 黑屏:不是控件问题,多半是模型纹理或显卡设置
黑屏是出现频率最高的问题。我遇到过三种情况。
第一种,模型路径错误。控件加载了一个不存在的GLB,画面区域直接黑屏。解决办法是先看画面运行时的状态输出,或者打开控件日志,确认模型路径是否有效。
第二种,显卡不支持。工控机用了很老的核显,不支持DirectX 11,控件渲染上下文创建失败,显示黑屏但WinCC没有明显报错。这时只能更新显卡驱动,或者换独立显卡。远程桌面下也常出现黑屏或材质异常,因为远程桌面把3D加速关掉了,有条件就到现场看。
第三种,纹理文件未嵌入。GLTF格式如果没有把纹理打包,引用的是外部图片路径,运行时模型找不到贴图,整个材质变成黑色,看起来也是黑屏。解决办法是导出时选择“打包资源”,或者直接使用GLB格式。
5.2 模型加载后不显示:检查GLB版本和网格压缩
与黑屏不同,这种情况是控件还在、背景和灯光也在,但设备模型没有出现。我的排查顺序是:
- 模型是否真的被加载。打开控件属性,看模型节点列表是空还是非空。如果节点列表为空,多半是GLB文件解析失败。
- 检查GLB是否基于glTF 2.0版本。有些软件导出的是glTF 1.0,后缀也是gltf,WinCC控件不认。
- 检查是否开启了Draco压缩。Draco是Google的网格压缩方案,WinCC 3D Control不一定内置解码器。开启后模型加载失败,重新用Blender导出一次,不勾选压缩,问题通常就能解决。
- 检查模型是否在相机裁剪范围之外。GLB坐标过大或过小,模型可能在相机后面造成看不到,调整相机目标或模型缩放即可。
5.3 运行时画面卡顿:减少实时视频贴图、精简场景
3D控件本质上是实时渲染,对CPU和显卡都有压力。最容易犯的错误是把整个车间的模型全部放到一个3D控件里,几百万面数,再开实时阴影,帧率直接掉到个位数。
我的优化手段按优先级排序:先把模型面数减到阈值内,Blender的Decimate修改器可以做;再减少材质的高光反射,把阴影贴图分辨率降低;然后少用点光源,尽量用平行光;再控制控件数量,一个画面里只保留一个3D控件,页面切换时主动卸载。刷新频率也要协调好,不要每10毫秒读一次标签再刷新模型,通常500毫秒已经完全够用。
5.4 安全与权限:WinCC Runtime启动时的ActiveX限制
有个车间项目里,我把画面发布到WinCC Runtime后,点击画面时3D控件不加载,状态栏提示ActiveX被阻止。这不是控件坏了,而是WinCC Runtime对ActiveX的默认权限设置比较严格。需要在运行系统的安全选项里,把该控件加入允许列表,或者用管理员权限重新注册控件。
另外,如果工控机上的运行用户不是管理员组,WinCC运行服务可能无法正常访问显卡驱动,3D场景会退回软件渲染,帧率很低。建议给WinCC运行服务单独配置一个有本地管理员权限的服务账户,虽然和安全基线有冲突,但很多3D应用确实需要这一步。
5.5 控件在画面窗口/多屏环境下的兼容性
WinCC画面窗口是很常见的复用机制,但3D控件塞进画面窗口后出现过几个情况。第一,画面窗口切换时,3D场景偶尔变成黑块或白块,需要切换一下焦点才能恢复。第二,在画面窗口模板里放了3D控件,模板实例化多个窗口时,每个窗口都会加载同一个GLB,内存占用成倍增加。
多屏下的问题大多和Windows显示缩放有关。如果工控机设置了125%或150%显示缩放,3D控件的鼠标坐标会偏移,点击设备部件时选不中。建议把主显示器的显示缩放调回100%,或者为WinCC运行时程序单独设置“替代高DPI缩放行为”。
6. 从空画面到可交互3D监控界面的完整小例程
6.1 用Blender三步做一个带旋转动画的水箱模型
我用一个简单的水箱模型做演示,10分钟就能完成。
第一步,添加一个立方体,拉成水箱外壳,长2米、宽1.5米、高2米,重命名为“Tank_Body”,给一个带轻微金属感的材质。
第二步,在水箱内部添加一个圆柱体作为液面,缩成扁平形状,重命名为“Liquid”,材质设为半透明蓝色。
第三步,添加一个小圆柱体作为搅拌桨叶片,放在水箱底部中央,重命名为“Impeller”,材质浅灰色。
导出前检查:三块模型原点都在物体底部中心,单位是米,节点层级是Tank_Body下挂Liquid和Impeller。导出GLB,命名“MixerTank.glb”,拷到WinCC项目的3DModels文件夹。
6.2 WinCC画面组态步骤
打开WinCC图形编辑器,新建画面,从对象栏拖入WinCC 3D Control。右键控件属性,模型文件路径选择“MixerTank.glb”,画面中央出现水箱模型。
新建两个内部变量:浮点型“Level_Val”,整数型“Motor_On”。再画两个IO域,分别连接这两个变量,运行时手动输入数值方便测试。接下来做绑定:选中3D控件,在属性对话框里找到“Liquid”节点的Position.Y,把它连接到变量“Level_Val”。如果属性连接里不方便做换算,就在画面打开事件写一段脚本,把0到100转换成0到1.5再赋值给节点。
6.3 绑定液位变量与颜色变化脚本
以一个500毫秒循环触发器为例,VBS脚本大致如下:
Dim obj3D, level, motor Set obj3D = ScreenItems("Ctrl3D1") level = HMIRuntime.Tags("Level_Val").Read motor = HMIRuntime.Tags("Motor_On").Read If level < 0 Then level = 0 If level > 100 Then level = 100 obj3D.Nodes("Liquid").Position.Y = level * 0.015 If motor = 1 Then obj3D.Nodes("Impeller").Rotation.Y = obj3D.Nodes("Impeller").Rotation.Y + 15 Else obj3D.Nodes("Impeller").Rotation.Y = obj3D.Nodes("Impeller").Rotation.Y End If这段代码是示意性质,具体属性路径和节点访问方法要以你本机控件帮助为准。关键是理解整体逻辑:先读PLC变量,再映射到模型节点属性,过程是固定的。
6.4 运行效果和调优建议
运行项目,IO域里输入Level_Val=60,液面节点会上升到0.9米位置;Motor_On=1时,搅拌桨转动,同时可以通过脚本让水箱颜色变化。这样一个基本的3D监控画面就跑通了。
如果现场运行流畅,可以继续加入报警闪烁、视角切换按钮、俯仰旋转等。我的调优建议是:脚本里所有数值换算不要散落在多个地方,单独封装成函数,方便维护;模型文件放在项目路径下,不要放桌面;全部完成后用项目复制功能打包测试一次,确认换电脑后模型和变量不丢失。
7. 写在最后:如果电脑配置一般,还有哪些替代思路
最后聊一下我个人的选择标准。并不是所有项目都适合上3D,很多老设备显示器分辨率只有1280x1024,工控机还是好几年前的配置,强行上3D控件只会让画面变成幻灯片。这种情况下我会选折中方案:用平面图加2D图符,设备位置用斜角透视,核心动作用动画闪烁,展示效果也能满足大多数验收需求。
如果确实需要3D,可以把设备模型简化到勉强能辨识的程度,关掉阴影和反射,把场景分辨率降到最小可用。也有人用Web组态加Three.js做可视化,这不在WinCC范围内,但本质是一样的:模型轻量化、变量映射、周期性刷新。WinCC 3D Control真正好用是在配置不算太差的工控机上,配合清晰的模型命名和合理的脚本结构,确实能让监控画面达到让人眼前一亮的程度。我做这个例程时最值的一步,就是提前把模型节点命名想清楚了,后面所有逻辑都顺理成章。希望这篇能帮你少走几步弯路。