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

模型工作流:自动化的模型内部三角面剔除

1. 关于自动减面

1.1 自动减面的重要性及现状

三维模型是游戏、三维家居设计、数字孪生、VR/AR等几乎所有三维软件的核心资产,模型的质量和性能从根本上决定了三维软件的画面效果和渲染性能。其中,模型减面工作是同时关乎质量和性能这两个要素的重要工作,一个好的模型减面结果,既能保证模型的渲染品质不会过多降低,又能保证模型面数降到一个合理可用的范围。

但三维模型的减面工作需要耗费大量的人力成本,通常一个模型的减面工作根据模型的复杂程度不同,需要耗费0.5到1人/天的成本,如果模型特别复杂,这个时间还会增加。因此,自动化减面工具的引入能极大提升建模人员的工作效率。

1.2 自动减面的挑战

现有的自动化减面工具,基本上都是基于在1997年发布的《Surface Simplification Using Quadric Error Metrics》(下称QEM算法)这篇论文的实现,比如当前游戏行业最流行的工具 PolygonCruncher 就是基于该论文实现的。该工具能够在保证模型拓扑形状的同时进行减面,最终减面的比例会跟该工具的设定有关,其中轮廓保护程度、纹理坐标保护程度、边角保护程度等等都会影响最终的减面比例,在我们家电场景的实际使用过程中,根据使用经验,一个能保持较高品质的减面比例通常在50%左右,这对于动辄十几万甚至上百万的模型来说,是远远达不到安全可用的要求的。

1.3 QEM算法的开创性和局限性

减面工作本质上是一个基于视觉系统和逻辑判断的事情,建模人员需要通过人眼去观察模型的三角面,并据其与模型的遮挡关系,在脑中判断出这个三角面是否可见,或者说是否应该被剔除掉。所以,想要实现自动减面,要么想办法摆脱对视觉系统的依赖,要么想办法实现一套视觉系统。而QEM算法的思路就是前者。

QEM算法创造性的通过计算出三角网格中每个边的一个特殊度量指标——二次误差,以该指标作为一个三角面是否应该减去的依据,从而绕过了视觉系统,仅通过三维数据的数据计算即可完成减面工作。具体来说,一条边的二次误差越大代表其对该局部区域拓扑结构的影响就越大,就越应该保留下来,反之就越应该减去。

但是QEM算法并非无懈可击,由于不依赖视觉系统,它只能根据对拓扑结构的影响程度来选择要减去的三角面,无法进一步根据三角面的可见性情况进行模型内部三角面的剔除。这也是QEM算法在家电模型减面的场景下表现不佳的根本原因。

关于QEM算法的具体原理,可以查看另一篇文章:《模型工作流:模型减面原理分析及优化思路》

1.4 如何破局

因此,我们可以通过引入模拟的视觉系统,来实现模型内部三角面的识别和剔除,从而让模型能在QEM减面的基础上,进一步的将内部三角面减去,从而实现更高效的减面效率。实现的效果如下图所示:

一个拓扑结构比较复杂的例子

2. 基于深度测试的减面

从生物学上来看,人眼最重要的两个能力是色彩识别、深度识别,其中深度识别就是指大脑能根据两个眼睛的“摄像”结果推断出视网膜中某个“像素点”的空间位置的深度关系。同样,对于减面工作来说,我们需要借助眼睛来判断一个三角面到底是暴露在外部,还是被遮挡在内部,其本质上就是判断两个像素点的深度关系。那么,只要在程序中获取到每个三角面的深度关系,那么我们就能识别出那些三角面是被遮挡的,其基本思路如下:

2.1 基本思路

物体的深度是跟人眼的位置和方向有关的,我们会引入若干个虚拟相机,将它们环绕摆放在模型四周,依次来模拟人眼观察的效果。根据模型的实际使用形态不同,相机的摆放可以灵活设定,一般设置8个朝下看+8个朝上看相机足够应对大部分情况,如下图所示。

在这之后,每个相机会进行拍摄,拍摄的内容是“整个模型”的三角面光栅化后的深度值,以下是其中3个相机的拍摄内容。这样,我们就能从图片中获取到每个像素点位置的深度值,对应的就是该像素位置下的模型表面的深度,也就是d2。

相机1

相机2

相机3

然后,我们需要在程序中,通过空间计算,获取每个三角形的在上述每个相机下的深度值,记为d1。这样,我们依次遍历模型的每一个三角形,计算每个三角形的d1和d2的大小关系,如果d1 > d2,则代表这个三角形的深度比模型表面更深,那么就意味着这个三角形在当前相机位置下是不可见的,如下图所示:

注意,d1的获取我们不能使用光栅化来完成,因为面的数量过大,此时CPU的效率远比GPU一个一个渲染FrameBuffer要高很多。

然后我们每个相机都重复上述操作,记录下每个相机的不可见的三角形的集合,最终把所有这些集合进行一个“取交集”的操作,就能得到在所有相机下都不可见的三角形,这样我们后续就能安全的进行内部三角面的剔除了,伪代码如下:

// 伪代码
-- 遍历每一个相机
for camera in cameras:
    -- 拍摄该相机下的整个模型的深度图
    wholeObjectDepthMap = renderCameraDepthMap camera wholeObject
    -- 遍历改模型的所有物体
    for obj in allObjects:
        -- 遍历该物体的所有三角面
        for face in obj.faces:
            -- 采样该面的关键点
            faceSamplePoints = sampleFacePoints face
            -- 遍历这些关键点
            for point in faceSamplePoints:
                -- 计算关键点的NDC坐标
                ndc = worldToNDCCoord point
                -- 计算关键点的UV坐标
                uv = NDCToUVCoord ndc
                -- 使用UV坐标采样深度图的颜色
                color = readPixel wholeObjectDepthMap uv
                -- 颜色值转深度值,即是d2
                d2 = (1.0 - color/255.0)
                -- ndc坐标系的z值就是d1(根据图形学理论)
                d1 = ndc.z
                -- 如果d1的深度大于d2的深度,那么就代表d1所在的关键点不可见
                if d1 > d2:
                    -- 该三角面的、该点,不可见

2.2 一些优化点

2.2.1 深度精度优化

为了尽可能提升深度值的精度,我们需要把相机视锥参数调整到“恰好包裹起整个物体”的状态,这样才能尽可能的减少相机的near平面和far平面的距离,以此来提升深度精度。

注意,这里我们使用正交投影相机,视锥在程序内部是一个长方体(如图中白色虚线所示),而不是锥形。

2.2.2 三角面关键点

考虑到一个三角面被遮挡的情况千奇百怪,比如可能中间被遮挡边角露出,也可能反过来。因此对三角面的关键点选取数量越多,我们的判断精度就越高。但是三角面数量越多,我们的计算耗时就越大,这需要权衡。经过实践,在三角形的边角和中心区域共6个点可以应对绝大部分情况。

2.2.3 预剔除

有一些物体它本身已经完全隐藏在另一个物体内部,此时这个物体其实可以整个抛弃,没必要再判断每个三角形的可见情况。实现思路也很简单,除了拍摄整个模型的深度图,然后每个物体也拍一个深度图。

伪代码如下:

// 伪代码
-- 遍历每一个相机
for camera in cameras:
    -- 拍摄该相机下的整个模型的深度图
    wholeObjectDepthMap = renderCameraDepthMap camera wholeObject
    -- 遍历改模型的所有物体
    for obj in allObjects:
        -- 拍摄该相机下的“单个物体”的深度图
        objectDepthMap = renderCameraDepthMap camera obj 
        objectBBoxWorld = getObjBBox obj
        objectNDCRange = worldToNDCRange objectBBoxWorld 
        -- 获取UV的坐标范围,如上图红框所示
        objectUVRange = NDCToUVRange objectNDCRange
        -- 遍历两张图在该坐标范围内的像素颜色,进行深度值的判断
        for u in objectUVRange.rows:
            for v in objectUVRange.cols:
                color2 = readPixel wholeObjectDepthMap uv
                color1 = readPixel objectDepthMap uv
                
                d2 = (1.0 - color2/255.0)
                d1 = (1.0 - color1/255.0)
                
                if d1 > d2:
                    -- continue
                else
                    -- exit 有一个像素可见,那么整个物体都可见,直接退出循环

2.3 自动减面效果测试

基于深度测试的减面方法是通用的,因此对于各种品类的家电家具模型都有非常好的效果,相比于传统的基于QEM算法的减面方案,减面效率得到了巨大的提升。

品类

产品

原始面数

纯QEM算法方案

深度测试方案(配合QEM减面)

电饭煲

HRC-FS4042A-FN01D0028

3.3w

1.1w

减面比例:66%

0.52w

减面比例:84%

电水壶

FM00E0000

9.2w

2.8w

减面比例:69%

0.74w

减面比例:92%

吸油烟机

海尔-家用-吸油烟机-CXW-258-EC967U1

12w

7.5w

减面比例:36%

0.83w

减面比例:93%

净水器

卡萨帝-反渗透-净水机-600G-CRO600-DFBGU1

15w

9.6w

减面比例:36%

1w

减面比例:93%

用水

圆镀铬龙头HJ2107

12.5w

8.4w

减面比例:33%

0.5w

减面比例:96%

智能浴霸

海尔-智能浴霸-X3U1

12.6w

7.2w

减面比例:43%

0.78w

减面比例:93%

热水器

卡萨帝-电热-热水器-80L-CES80H-PROS3CEK02U1

39w

21w

减面比例:46%

2.9w

减面比例:92%

洗衣机

海尔-滚筒-洗衣机-10kg-G100318B14LS

59w

43w

减面比例:27%

10w

减面比例:83%

电视

卡萨帝-液晶电视机-K85E10

62w

56w

减面比例:9%

13w

减面比例:79%

壁挂空调

海尔-挂机-空调室内机-2匹-KFR-50GW18MEA83U1套机

66w

59w

减面比例:10%

2.7w

减面比例:96%

柜式空调

海尔-柜机-空调室内机-大3匹-KFR-72LW17DAA81VU1

79w

63w

减面比例:20%

11w

减面比例:86%

冰箱

卡萨帝-多开门-电冰箱-550L-BCD-550WLCFPA4YBU1

150w

70w

减面比例:53%

17w

减面比例:89%

3. 团队介绍

三翼鸟数字化技术平台-筑巢自研平台」依托实体建模技术与人工智能技术打造面向家电的智能设计平台,为海尔特色的成套家电和智慧场景提供可视可触的虚拟现实体验。智慧设计团队提供全链路设计,涵盖概念化设计、深化设计、智能仿真、快速报价、模拟施工、快速出图、交易交付、设备检修等关键环节,为全屋家电设计提供一站式解决方案。


http://www.kler.cn/a/455656.html

相关文章:

  • [江科大STM32] 第五集STM32工程模板——笔记
  • 跨语言学习之C++ 和 Python 的赋值操作 (等号“=“) 的区别
  • 基于Pycharm与数据库的新闻管理系统(3)MongoDB
  • python学opencv|读取图像(二十一)使用cv2.circle()绘制圆形进阶
  • 《鸿蒙HarmonyOS应用开发从入门到精通(第2版)》学习笔记——HarmonyOS技术理念
  • 【小程序】自定义组件的data、methods、properties
  • ID卡网络读卡器Python小程序开发
  • Python软体中简化版MapReduce任务的实现:处理大量日志数据
  • spring security 超详细使用教程(接入springboot、前后端分离)
  • 研发效率提升
  • USB免驱IC读卡器QT小程序开发
  • Hive SQL 之 `LATERAL VIEW EXPLODE` 的正确打开方式
  • DS的使用
  • StarRocks 排查单副本表
  • Kotlin 语言基础语法及标准库
  • [2029].第6-06节:MyISAM引擎中的索引与 InnoDB引擎中的索引对比
  • C# 线程安全集合
  • 阿里云技术公开课:基于阿里云 Elasticsearch 构建 AI 搜索和可观测 Chatbot
  • 计算机故障找不到x3daudio1_7.dll怎么解决?
  • C#开发实例2—模拟考试
  • Jsonlizer,一个把C++各类数据转成 Json 结构体的玩意儿
  • asp.net core系统记录当前在线人数
  • 组建基于IPV6的网络
  • 更新本地项目到最新git版本脚本
  • 每天40分玩转Django:Django Email
  • 微服务网关路由