前言
上文提到如果项目需求的业务管理功能多、集成度高,那么就建议使用webgl的技术方向进行模型轻量化。
目前市面上有不少成熟的模型轻量化工具,比如广联达BIMFace、葛兰岱尔的GLWebGLBIMEngine、e建筑等,都是在平台转换,在线、离线式使用,基本都使用的threejs实现模型的展示,其中bimface的通讯格式为二进制,猜测为自定义的数据格式,GLWebGLBIMEngine和e建筑使用的是gltf。还见过一家使用silverlight结合unity做模型展示,但是这并不是主流趋势,很多浏览器已经不支持。
一、轻量化流程
经过多种途径的试探,结合目前的资源,决定全面转向threejs实现轻量化,实现的大概流程:
理想中轻量化应该是上传RVT文件后,服务器自动对各版本的文件进行解析处理,将相应的数据及文件存入数据库及文件服务器。模型的展示应该是组件化模块化,对于其他应用模块提供标准开放接口,方便外部调用。所以应该本着文件尽可能小、展示真实、操作流畅的原则进行开发。
二、数据提取
1.revit分类
首先要大概了解revit类别结构
- Category:类别,比如梁、板、柱、门、窗等大的分类。
- Family:族,子分类。
- FamilySymbol:族类型,个人理解是体现子类的规格。
- FamilyInstance:实例化出新的对象,体现在revit中就是创建了一个新的构件,这个构件属于Category、Family、FamilySymbol一种,熟悉面向对象的编程语言应该很容易理解这个概念
所以简单的理解revit的数据存储结构是树状结构
2.revit分类编码规则
Revit 分类编码采用的是国际行业标准的Omniclass编码,是对建筑全生命周期进行编码,印象中总共有30多个table,revit主要使用的是第23个table中的编码,例如:23.25.30.11.14.11,在表中可以查到对应的解释。Revit内置大约有1000多种族分类。
3.插件开发
环境的搭建可以参照
https://blog.csdn.net/qq_36754364/article/details/86724985
提取数据需要依赖revti的sdk, c#引用链接库RevitAPI.dll、RevitDBAPI.dll,实现IExportContext接口,方法流程:
注:获取的element包含了场景数据,如相机。也包括轻量化不需要的元素,如中心线、洞等,执行插件只获取当前视图view的元素,也支持链接rvt的进一步遍历。
4.导出gltf
使用GITF格式作为模型文件,一是它的目标是成为模型界的通用格式,类似图片界的jpeg。二是对OpenGL的兼容性好,数据格式清晰简单,三是自己对计算机图形学不了解,自定义格式难度大,还是考虑成熟的数据格式。
GITHUB上有开源的导出GLTF的代码,地址:
https://github.com/McCulloughRT/Revit2glTF
public struct glTF
{
public glTFVersion asset;
public List<glTFScene> scenes;
public List<glTFNode> nodes;
public List<glTFMesh> meshes;
public List<glTFBuffer> buffers;
public List<glTFBufferView> bufferViews;
public List<glTFAccessor> accessors;
public List<glTFMaterial> materials;
}
这里是对GLTF的文件格式定义,按照revit二次开发规范实现IExternalCommand,IExportContext接口生成dll和addin文件,然后关联到revit上即可导出文件:
导出结果:
4.文件大小优化
对模型进一步优化可以使用谷歌开源的Draco,大幅加速 3D 数据的编码、传输和解码。
gltf-pipeline:https://github.com/CesiumGS/gltf-pipeline,依赖NODE.JS,通过命令行窗口可以对模型进行优化:
- 转换GLB:
gltf-pipeline -i NewProject.gltf -o NewProject.glb
- 转换Draco:
gltf-pipeline -i NewProject.gltf -o buildDraco.gltf –d
源文件大小为6M,压缩完后为1M,压缩比接近6:1,对于管线、精装修等mesh多的情况达不到这种压缩比。
总结
提取的算法优化空间还很大,比如移除重复顶点和重复面、三角网简化等,只不过自己的能力不足,需要继续学习,感兴趣的同学可以进一步优化。