当前位置: 首页 > news >正文

什么是模型轻量化?如何自动进行模型轻量化?

轻量化是已经是3D可视化业界人所共知的一个概念,虽然至今没有任何严谨的学术或者理论定义,但是这个概念已经几乎成为了行业的标准。它的大意是说,一个适用用于浏览器端渲染的模型数据,包括几何数据和行业数据,必然可以做的很小,如果和原建模软件的原始模型文件比较的话,如果做到1/4那是及格标准,做到1/10,乃至1/20之一是优秀。今天我们将讨论下这个概念下具体的技术实现方案和背后的计算机图形学理论,并且希望得出一个对整个行业有参考价值的结论。

定义

在讨论轻量化的可行技术方案之前,我们需要对轻量化进行一个定义和概念厘清。本文所探讨的轻量化,指对三维建筑模型模型,例如Revit,IFC等文件中三维几何数据部分的数据压缩。本文针对的轻量化不涉及任何其他非三维几何数据,包括纹理图片、材质信息、建筑BIM信息、二维图形信息以及软件特有的附加信息。很多平台产品将自己的纯三维几何数据大小和带有众多信息的原模型大小相对比,得出自己轻量化程度高的结论是非常不科学的。

我们需要对三维几何信息进行进一步定义。这里的三维信息特指三维三角形网格(triangular mesh)或者三维线网格(polyline mesh)。每一个mesh由一个顶点数组和一个索引数组组成。顶点数组中每一个顶点一定包含position,即三个32bit IEEE754 floating number,分别对应顶点的x, y, z坐标,可能包含normal,即三个32bit IEEE754 floating number,可能包含纹理坐标UV,即两个32bit IEEE754 floating number,可能包含顶点颜色,即四个8bit byte,分别对应RGBA四个通道。针对三角形网格,因为考虑渲染效率,一定采用顶点法线(vertex normal),而不是面法线(face normal)。索引数组为一个unsigned int 16的数组,元素个数为3 * 三角形数量或者2 * 线段数量。

除了定义mesh,我们进一步定义轻量化的应用场景。轻量化仅指进轻量化程序处理后用于保存和网络传输的数据量可以压缩到比原始三维网格的数据量小。在进行渲染前,轻量化的数据可能会解压缩以便是适配于GPU渲染API的需要,解压缩的数据量可能会增大,甚至比原先的三维网格数量量更大,这是为了渲染效率优化的考虑。本文所讨论的轻量化仅针对优化存储优化和传输优化,并不针对渲染的优化。同时,我们认为因为渲染的API的接口规范已给定,渲染时实现100%还原度的无损数据压缩是不存在的,虽然本文最后对这类应用情况也提出了一种可行性方案。

技术方向

轻量化的技术方向大致可以分为Instancing,Compression,LOD和Parameterization。下文对四个技术方向以及其落地分别进行探讨。

  • Instancing

Instance,多实例是已经非常普遍的渲染技术[2]。它的原理是针对同样的几何物体,只保存一份几何数据,通过在渲染管线中分别绘制若干次,且每次应用不同的几何变化和材质信息得到在同一帧多个类似几何物体的渲染效果,见图1。用实际的例子说,如果要绘制很多相同的桌子,我们只需要使用一份桌子的几何数据,然后绘制多编,每一遍把桌子放在不同的位置即可。目前的渲染管线已经完全将instancing放在了硬件管线中执行,大大节约了GPU内存的开销和CPU的计算开销(主要指发起一个drawcall的驱动使用CPU资源)[1, 3]。WebGL 1.0中可以通过使用ANGLE_instance_arrays[3]就扩展实现这个功能,在WebGL 2.0中已经有原生API支持,即gl.drawElementsInstanced。

对应轻量化的Instancing表达,已经有一定的研究[4,5]。研究的主要解决问题,如何在一个场景中,对几何体进行一一对比,如果两个几何体是同一个几何体,那么只需要实际保存一份几何数据,将另外一个几何体压缩为一个空间变化和材质信息。判断两个几何体是否相同往往从附加在几何体上的语义出发,例如两个几何体是不是都标记为一张桌子,或者直接从mesh相似度出发。纯几何的算法是非常具有挑战性的,因为单纯的内存比较显然在大多数情况下不适用,只要索引数组略有变化或者一个简单的平移变换,这种比较就失效了。现在业界应用比较多的是Hausdorff距离[6],即计算两个mesh之间的最小欧式距离。这个距离算法一样对简单的旋转无能无力。

另一方面在建筑建模中,我们发现大多数的建模软件已经内置了Instancing的功能。一个物体如果在场景中重复出现多次,在模型文件中它的几何数据只保留了一份,每一个实例压缩为了一个4x4空间变换矩阵。这样的发现告诉我们,在BIM的数据流中想通过instancing来减少几何数据的大小已经不太现实,源文件已经在这个方面做到了最好。

综上所述,在实际的生产环境中,利用Instancing来减少原始文件的尺寸,效果不会太好。

  • 压缩

压缩的概念就很好理解,就是和普通的文件压缩类似。有两种方向,第一种是几何无关的,例如直接用将模型数据进行gzip压缩后保存,因为浏览器原生支持gzip解压[7],在传输过程还是gzip压缩数据,而在应用层已经为解压后的模型数据,根据我们经验,针对上文中提及的几何数据,gzip的压缩率在2:1,即能压缩到原始数据一半的大小。第二种方向是几何相关的,比如Google的Draco库[8],Khronos的Open3DGC[9]。Draco的公开资料中并没有提及它的具体算法,但是它的压缩率是惊人的,见图2。对于Open3DGC,它在一定程度上利用了quantization的方法,是一种有损压缩。虽然他们加入了针对几何信息更好的压缩,但是本质上还是一种压缩算法,需要在载入到GPU前将数据解压缩。

压缩是目前在轻量化中实用价值最高的方法,原因是它完全对于渲染透明,且在服务器端保存的几何数据量大幅度减少,所需要的无非是一些计算性能的开销,例如Draco解压一个100MB左右的文件需要1秒左右的CPU时间。

  • LOD

Level-of-Detail(LOD)[11, 12],一个渲染加速技术,对于离相机原的物体采取比离近的物体精度低的多的几何数据,甚至一个billboard来表达。这样在一个帧内就能大大减少vertex数量,减轻渲染管线的计算量,见图4。LOD某种程度上可以会被误认为一种简化mesh模型的技术容易把LOD混同轻量化来谈,这是一种认识误区,正如前面所述,LOD是一种渲染加速技术,它不但不能减少文件保存时和传输时的尺寸,还是需要增加文件尺寸的。例如图4中,除了原始的最左边的模型,模型处理程序还需要构建出右边三个简化模型,将其传输到客户端用于渲染加速。额外的三个简化模型大大增加了模型的数据尺寸。

但是也有通过quantization方法,在不增加文件尺寸的基础上提供了LOD技术[13](图5)。它把模型的定点坐标的floating number全部转换为normalized整形,然后依靠cutting off来实现downsampling。这是一个非常巧妙的办法,唯一的开销是在vertex shader中需要将normalized floating number展开。

图5 Pop Buffer利用quantization来做LOD

LOD虽然不能直接降低模型的几何数据大小,但是依据LOD的层级可以实现模型几何数据的增量传输(progressive loading),也就是先传输低层级的几何数据且显示,最后再传输那些更加细致的几何数据。如果用户允许一定程度上的几何细节损失,LOD也可以成为一种轻量化方法。对于模型简化的算法可以参考[14, 15, 16]。另一个非常类似的研究方向是mesh streaming,更多的应用于大规模地形模型的渲染。

  • Parameterization

参数化这个做法就是将mesh转成nurbs或者其他参数表达方式。这个技术本来是在逆向工程中使用,从激光扫描的点云中恢复参数曲面用来车床加工[20, 21, 22]。对于参数易表达的面,比如球体,这种方式大大减少了数据量。但是对于建筑来说,大多数面片都是平面,并不能减少太多数据量,甚至在有些情况曲面消耗的存储空间比mesh更大,比如带很多trim的曲面。何况GPU并不支持参数曲面的实时绘制。

还有两种类似参数化的方法,分别是remeshing即重新mesh[23],见图6和subdividision 曲面细分[24],见图7。前者将mesh重新采样做成一个新的mesh,后者将一个曲面细分,生成一个更加复杂的曲面,实质上是生成一个由原先曲面作为控制点的b-spline surface。理论上,我们只要找到一个和现有mesh几何相近但是更简化的表达,就达到了压缩的目的,但是这样做并不容易,原因还是建筑模型中大多数的几何体并不适用于细分曲面。

图6 Remeshing

图7 细分曲面

但是参数化表达并无不可取之处,对于几种特殊的情况,参数化表达可以达到非常好的效果。比如管道等利用extrusion操作生成的物体结构,见图8。这样的扫描体完全可以用一条路径加一个横截面来表达,如果横截面为一个方便公式表达的形状,例如圆形,那么数据压缩的效果会更加明显。为了进一步减轻客户端将这种参数表达的形体展开为mesh的工作量,我们可以将path中的采样点预先计算出来。

一个可行性数据压缩框架

上文已经总结了可用于压缩的四个基本方向,我们认为并不存在一个适用于普遍场景的“轻量化”方案。一个相对可行性方案也是Modelo采用的是

  1. 保存原建模文件中的instancing信息
  2. 如果原建模文件中有NURBS曲面(b-rep),控制它的网格细分力度,取得效果和文件体积平衡。
  3. 对于extrusion物体进行参数化,将其压缩所成line strip和一个横截面
  4. 采用Google Draco对其进行压缩
  5. 采用gzip将其压缩

对于一般场景,这个方案最终的压缩率几乎取决于第四步Draco的压缩表现,这也是为什么我们认为“轻量化”的更应该称之为“几何数据压缩”的原因。只有对于极少数的场景,例如可以简化的管道,第三步就可以发挥极大的作用,大大降低文件尺寸,但是这步的工程实现难度也很大,需要考虑很多细节,这里也不一一阐述了。

 总结

三维模型轻量化技术可以通过多种方式来减少模型文件大小和处理负荷,从而提高三维模型的性能和运行效率。在实践中,可以根据具体的应用场景和需求选择最适合的轻量化技术来优化三维模型。

老子云3D可视化与模型优化服务平台icon-default.png?t=N7T8https://www.laozicloud.com/

老子云单模型轻量化

通过底层算法快速有效的对单物品模型进行轻量化处理,目前包含三种处理模式:减面模式、合并模式、抽壳模式(其他模式陆续上线中)。

减面模式

保留原始模型信息,仅使模型网格更轻量。

目标面数: 服务后模型的百分比面数,目标面数百分比越低,轻量化效果越明显。

目标格式: FBXOBJSTL

GPU轻量化: 相比CPU轻量化,处理速度更快,精细化程度更佳。您可选择是否开启GPU轻量化。


合并模式

合并模型材质和贴图,不保留原始UV信息(可选择是否保留原始模型网格和动画)。

目标面数: 服务后模型的百分比面数,目标面数百分比越低,轻量化效果越明显。

目标格式: FBXOBJSTL

漫反射贴图精度: 表现物体表面反射和颜色的贴图(如果模型有漫反射贴图或非白色材质颜色信息,会开启漫反射烘焙)。精度取值范围1024-8192。

烘焙AO贴图: 包含光照数据的灰度贴图,模拟物体之间所产生的阴影。

保留模型网格和动画: 开启后仅合并所有材质和贴图。

抽壳模式

完全忽视内部结构,仅保留表层展现,以求更极致的轻量化及更高效的展示效果,适用于BIM在大场景中的LOD生成

倾斜摄影轻量化

适用于倾斜摄影OSGB模型的多端展示与交互,自动切割为多区块多层级,根据人眼自动识别来实现模型不同区块不同层级的精度加载。

目标精度: 可自行设置服务后模型的目标精度,线上提供普清、标清、高清、超清四种效果选择。

目标格式: AMRTOSGB、3DTiles

老子云3D可视化与模型优化服务平台icon-default.png?t=N7T8https://www.laozicloud.com/

相关文章:

  • Linux命令的语法和帮助系统
  • 海豚调度异常处理: 使用 arthas 在内存中删除启动失败的工作流
  • AMS(ActivityManagerService)源码解析2,Android应用是如何被启动的
  • 【Android】安Android Studio环境搭建注意点
  • QT
  • 练习时长 1 年 2 个月的 Java 菜鸡练习生最近面经,期望25K
  • article:文章信息表
  • 和鲸101计划:以神经计算建模培训,助力北大学术人才培养
  • lspci总结
  • 【最新鸿蒙应开发】——HarmonyOS沙箱目录
  • 【Kafka】Kafka Producer 分区-05
  • Python 使用 Thick 方式连接 Oracle Database BaseDB 23ai
  • 前端将Markdown文本转换为富文本显示/编辑,并保存为word文件
  • vue 之 vuex
  • HTML(6)——表单
  • ----------
  • 2017 前端面试准备 - 收藏集 - 掘金
  • Docker下部署自己的LNMP工作环境
  • Essential Studio for ASP.NET Web Forms 2017 v2,新增自定义树形网格工具栏
  • JS函数式编程 数组部分风格 ES6版
  • python大佬养成计划----difflib模块
  • react-native 安卓真机环境搭建
  • Spring技术内幕笔记(2):Spring MVC 与 Web
  • vue学习系列(二)vue-cli
  • 高度不固定时垂直居中
  • 警报:线上事故之CountDownLatch的威力
  • 如何邀请好友注册您的网站(模拟百度网盘)
  • 我建了一个叫Hello World的项目
  • 在Mac OS X上安装 Ruby运行环境
  • const的用法,特别是用在函数前面与后面的区别
  • ​520就是要宠粉,你的心头书我买单
  • ​LeetCode解法汇总2670. 找出不同元素数目差数组
  • ​TypeScript都不会用,也敢说会前端?
  • ### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTr
  • (003)SlickEdit Unity的补全
  • (ctrl.obj) : error LNK2038: 检测到“RuntimeLibrary”的不匹配项: 值“MDd_DynamicDebug”不匹配值“
  • (C语言)二分查找 超详细
  • (DFS + 剪枝)【洛谷P1731】 [NOI1999] 生日蛋糕
  • (初研) Sentence-embedding fine-tune notebook
  • (附源码)计算机毕业设计高校学生选课系统
  • (附源码)小程序 交通违法举报系统 毕业设计 242045
  • (黑客游戏)HackTheGame1.21 过关攻略
  • (每日持续更新)jdk api之FileFilter基础、应用、实战
  • (牛客腾讯思维编程题)编码编码分组打印下标(java 版本+ C版本)
  • (三)终结任务
  • (一)插入排序
  • (一一四)第九章编程练习
  • (原创)攻击方式学习之(4) - 拒绝服务(DOS/DDOS/DRDOS)
  • (转)人的集合论——移山之道
  • (轉)JSON.stringify 语法实例讲解
  • ***微信公众号支付+微信H5支付+微信扫码支付+小程序支付+APP微信支付解决方案总结...
  • .bat批处理(十一):替换字符串中包含百分号%的子串
  • .net core 实现redis分片_基于 Redis 的分布式任务调度框架 earth-frost
  • .NET Core实战项目之CMS 第十二章 开发篇-Dapper封装CURD及仓储代码生成器实现
  • .NET DevOps 接入指南 | 1. GitLab 安装