uniform sampler2D myTexture; // 纹理

uniform vec3 lightDir; // 光照方向(全局常量)

varying vec2 uv; // 插值得到的纹理坐标

varying vec3 normal; // 插值得到的法线

void main() {

vec3 kd = texture2D(myTexture, uv).rgb; // 从纹理获取漫反射系数

vec3 n = normalize(normal);

vec3 l = normalize(lightDir);

float diffuseIntensity = max(0.0, dot(n, l));

gl_FragColor = vec4(kd * diffuseIntensity, 1.0); // 输出像素颜色

}


现代GPU还支持几何着色器(Geometry Shader)、计算着色器(Compute Shader)等,功能更加强大。

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/9f104bbd50a0d7c5e600ed7a64f4daa8_20.png>

---

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/9f104bbd50a0d7c5e600ed7a64f4daa8_22.png>

## 纹理映射(Texture Mapping)初步

着色模型中的各种系数(如`k_d`)可以不是常数。纹理映射的核心思想是:定义物体表面任意一点的不同属性(如颜色、粗糙度等)。

**基本概念:**
*   **纹理(Texture)**:一张二维图像。
*   **纹理坐标(UV Coordinates)**:用于定位纹理上的点。通常规范化到[0, 1]范围,横轴为U,纵轴为V。
*   **映射(Mapping)**:建立物体表面点(三维)与纹理坐标(二维)的对应关系。

**工作原理:**
1.  对于三维模型的每个顶点,除了位置坐标,还预先指定其对应的纹理坐标`(u, v)`。这通常由建模人员或参数化算法完成。
2.  对于一个三角形,已知其三个顶点的纹理坐标。
3.  对于三角形内部的任意一点,其纹理坐标可以通过其三个顶点的纹理坐标**插值**获得。
4.  根据插值得到的`(u, v)`坐标,去查询纹理图像,获得该点的属性(如颜色),并用于着色计算。

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/9f104bbd50a0d7c5e600ed7a64f4daa8_24.png>

纹理可以重复平铺(Tiling)使用,设计良好的**可平铺纹理(Tileable Texture)**能在边界处无缝衔接。

---

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/9f104bbd50a0d7c5e600ed7a64f4daa8_26.png>

## 课程总结

本节课我们一起学习了:
1.  **完整的布林-冯着色模型**,包括其漫反射、高光和环境光分量的定义与公式。
2.  **着色频率**的概念,比较了逐三角形(Flat)、逐顶点(Gouraud)和逐像素(Phong)着色的区别与适用场景。
3.  **实时渲染管线**的完整流程,理解了从顶点到像素的转换过程,以及顶点着色器和片段着色器的角色。
4.  **纹理映射**的基本原理,即通过UV坐标将二维纹理图像映射到三维物体表面,以定义表面属性的变化。

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/9f104bbd50a0d7c5e600ed7a64f4daa8_28.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/9f104bbd50a0d7c5e600ed7a64f4daa8_30.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/9f104bbd50a0d7c5e600ed7a64f4daa8_31.png>

我们留下了一个核心问题:如何在三角形内部根据顶点属性进行**插值**?这需要用到**重心坐标(Barycentric Coordinates)**的概念,我们将在下节课详细探讨。

# GAMES101-现代计算机图形学入门-闫令琪---P9-Lecture-09-Shading-3--Texture-Mapping-Cont-----GAMES-Webinar---BV1X7411F744_note

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/5be1398b5ff5229267d27d5e0347268c_0.png>

在本节课中,我们将继续学习纹理映射的相关知识。我们将重点探讨如何在三角形内部进行属性插值,以及如何解决纹理映射中出现的“纹理过大”和“纹理过小”问题。通过引入重心坐标、双线性插值、Mipmap和各向异性过滤等概念,我们将学习如何高效、高质量地处理纹理。

---

## 概述

上一讲我们介绍了着色模型和纹理映射的基本概念。本节我们将深入纹理映射的具体实现细节,特别是如何解决纹理采样时遇到的质量问题。我们将从三角形内部的插值方法开始,逐步讲解纹理放大和缩小时的处理技术。

---

## 1. 重心坐标与插值 🔺

在上一节中,我们提到为了在三角形内部实现平滑的着色过渡,需要进行插值。本节中,我们来看看如何利用重心坐标在三角形内部对任意属性进行插值。

### 为什么需要插值?
在图形学中,许多计算(如颜色、法线、纹理坐标)是在三角形的顶点上完成的。为了在三角形内部得到平滑过渡的效果,我们需要根据顶点的值计算出内部任意点的值。

### 插值什么内容?
可以插值的属性包括但不限于:
*   **颜色**:实现顶点颜色在三角形内部的平滑渐变。
*   **纹理坐标 (UV)**:确定三角形内点对应纹理图像上的位置。
*   **法线向量**:用于实现逐像素着色(Phong Shading)。
*   **深度值**:在光栅化过程中进行深度测试。

### 如何插值:重心坐标
重心坐标是定义在三角形上的一套坐标系,用于描述三角形所在平面内任意点的位置。

**定义**:对于三角形ABC所在平面内的任意点(x, y),都可以表示为三个顶点坐标的线性组合:
`(x, y) = α * A + β * B + γ * C`
其中,系数需满足:`α + β + γ = 1`。

**点在三角形内的条件**:当且仅当所有系数均为非负数时(`α ≥ 0, β ≥ 0, γ ≥ 0`),该点位于三角形内部。

**计算方法**:重心坐标可以通过面积比来计算。以系数α为例:
`α = (A点对面小三角形的面积) / (三角形ABC的总面积)`
同理可计算β和γ。三角形的重心坐标即为(1/3, 1/3, 1/3)。

**插值公式**:已知三角形三个顶点的属性值`V_A, V_B, V_C`,则三角形内任意点(重心坐标为(α, β, γ))的属性值`V`可通过下式插值得到:
`V = α * V_A + β * V_B + γ * V_C`

**一个重要注意事项**:重心坐标在投影变换下不具备不变性。因此,对于三维空间中的属性(如深度),应在三维空间中进行插值,再将结果映射回屏幕空间,而不是在投影后的二维三角形中直接插值。

---

## 2. 纹理映射的应用 🖼️

了解了插值方法后,我们来看看如何将纹理应用到物体表面。核心思路是:对于屏幕上的每个采样点(如像素中心),利用插值得到其纹理坐标(UV),然后从纹理图像中查询该坐标处的颜色值。

**基本步骤**:
1.  通过重心坐标,插值出当前像素点对应的纹理坐标(u, v)。
2.  在纹理图像上查询坐标(u, v)处的颜色值。
3.  将此颜色值作为漫反射系数`kd`,代入布林-冯着色模型进行计算,从而得到该像素的最终颜色。

这相当于将纹理图像“贴”在了物体表面,并结合了光照模型产生明暗效果。

---

## 3. 纹理过小与放大问题 🔍

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/5be1398b5ff5229267d27d5e0347268c_2.png>

当纹理图像的分辨率低于屏幕渲染分辨率时,纹理会被拉大,导致一个屏幕像素可能对应纹理上的一片区域。如果简单地取最近纹理像素的颜色,会产生明显的块状瑕疵。

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/5be1398b5ff5229267d27d5e0347268c_4.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/5be1398b5ff5229267d27d5e0347268c_6.png>

### 问题分析
一个屏幕像素覆盖了纹理上的一片连续区域,但我们只采样了一个点(如像素中心映射的点)。当纹理细节变化剧烈时,单点采样无法代表整个区域,导致走样。

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/5be1398b5ff5229267d27d5e0347268c_8.png>

### 解决方案:双线性插值
为了提高质量,我们不再寻找最近的单个纹理像素,而是考虑该点周围四个最近的纹理像素,并通过两次线性插值来估算该点的颜色。

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/5be1398b5ff5229267d27d5e0347268c_10.png>

**步骤如下**:
1.  对于非整数纹理坐标(u, v),找到其周围四个最近的纹理像素:`u00, u01, u10, u11`。
2.  计算该点与左下角像素`u00`的水平距离`s`和垂直距离`t`(s, t ∈ [0, 1])。
3.  进行两次线性插值:
    *   **水平插值**:先用`s`在`u00`和`u10`之间插值得到`u0`;再用`s`在`u01`和`u11`之间插值得到`u1`。
    *   **垂直插值**:再用`t`在`u0`和`u1`之间插值,得到最终的颜色值。

线性插值公式为:`lerp(v0, v1, t) = v0 + t * (v1 - v0)`。

通过双线性插值,像素颜色能够在其覆盖的纹理区域内平滑过渡,有效避免了马赛克现象。更高质量但计算量更大的方法还有**双三次插值**,它使用周围16个像素进行插值。

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/5be1398b5ff5229267d27d5e0347268c_12.png>

---

## 4. 纹理过大与缩小问题 🧩

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/5be1398b5ff5229267d27d5e0347268c_14.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/5be1398b5ff5229267d27d5e0347268c_16.png>

当纹理图像分辨率过高时,一个屏幕像素可能覆盖纹理上的一大片区域。此时,如果用像素中心单点采样,相当于用高频信号中的一个样本来代表整个区域的平均值,会造成严重的走样和摩尔纹。

### 问题本质
这本质上是**信号采样频率不足**导致的走样问题。一个解决方案是超采样(如MSAA),即在像素内进行多次采样再平均,但计算开销巨大。

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/5be1398b5ff5229267d27d5e0347268c_18.png>

### 高效方案:Mipmap
Mipmap的核心思想是**避免采样,直接进行快速的范围查询(求平均值)**。它是一种图像金字塔结构。

**Mipmap的构建**:
*   从原始纹理(第0层)开始,每一层图像的长宽都是上一层的一半。
*   第`n`层图像有`(width/2^n) * (height/2^n)`个像素。
*   总层数为`log2(max(width, height))`。
*   额外存储开销仅为原始纹理的**1/3**。

**Mipmap的查询**:
1.  估算屏幕像素在纹理空间中所覆盖区域的近似边长`L`。
2.  计算应在Mipmap的哪一层进行查询:`D = log2(L)`。
3.  在Mipmap的第`D`层图像上,查询对应纹理坐标处的像素值。由于第`D`层的一个像素恰好代表了原始纹理中`L×L`区域的平均值,因此这次查询就快速得到了范围查询的结果。

**三线性插值**:
直接查询离散的`D`层可能导致层与层之间出现不连续的跳跃。为了解决这个问题,我们进行**三线性插值**:
1.  在`D`的上下两层(如`floor(D)`层和`ceil(D)`层)分别进行**双线性插值**,得到两个颜色值`Color_low`和`Color_high`。
2.  再用`D`的小数部分在`Color_low`和`Color_high`之间进行一次**线性插值**,得到最终颜色。

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/5be1398b5ff5229267d27d5e0347268c_20.png>

三线性插值在层内和层间都实现了平滑过渡,是游戏中广泛应用的技术。

**Mipmap的局限性**:它只能快速进行**正方形区域**的近似范围查询。当像素覆盖的纹理区域是细长的矩形时,用正方形去近似会取到过多无关区域的平均值,导致过度模糊。

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/5be1398b5ff5229267d27d5e0347268c_22.png>

---

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/5be1398b5ff5229267d27d5e0347268c_24.png>

## 5. 各向异性过滤 ⚖️

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/5be1398b5ff5229267d27d5e0347268c_26.png>

为了改善Mipmap在处理矩形区域时的过度模糊问题,引入了各向异性过滤。

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/5be1398b5ff5229267d27d5e0347268c_28.png>

**核心思想**:除了构建标准的Mipmap(对角线压缩),还额外预计算一系列在水平或垂直单一方向上压缩的纹理链。
*   这样,对于一个在纹理空间中是`2x8`的矩形区域,我们可以直接在水平压缩2倍、垂直压缩8倍的特定层级纹理上进行快速查询,从而得到更准确的平均值。

**效果与开销**:
*   各向异性过滤能显著改善远处或倾斜表面的纹理清晰度。
*   其存储开销约为原始纹理的**3倍**,但现代显卡显存通常足以承受。
*   它仍然不能完美处理所有不规则形状的区域,更高级的方法如**EWA过滤**通过多次圆形查询来覆盖不规则形状,但计算成本更高。

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/5be1398b5ff5229267d27d5e0347268c_30.png>

在游戏中,开启各向异性过滤(如16x)能大幅提升纹理质量,而对性能影响很小,因此建议在显存足够时开启。

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/5be1398b5ff5229267d27d5e0347268c_32.png>

---

## 总结

本节课我们一起深入学习了纹理映射的高级主题:
1.  我们首先学习了**重心坐标**,这是在任何三角形内部进行属性插值的数学基础。
2.  接着,我们探讨了**纹理过小(放大)** 的问题,并引入了**双线性插值**技术来平滑纹理,避免马赛克。
3.  然后,我们重点分析了**纹理过大(缩小)** 导致的走样问题。为了解决高效的范围查询需求,我们学习了**Mipmap**这一图像金字塔结构,以及为了平滑过渡而使用的**三线性插值**。
4.  最后,我们了解了Mipmap的局限性,并介绍了**各向异性过滤**如何通过预计算更多方向的纹理链,来更好地处理矩形区域,减少过度模糊。

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/5be1398b5ff5229267d27d5e0347268c_34.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/5be1398b5ff5229267d27d5e0347268c_36.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/5be1398b5ff5229267d27d5e0347268c_38.png>

通过这些技术,我们能够在保证渲染效率的同时,显著提升纹理映射的质量。至此,光栅化渲染器的主要技术环节已基本讲解完毕。下一讲我们将进入新的模块——几何。

# GAMES102-几何建模与处理---P1-课程介绍---GAMES-Webinar---BV1NA411E7Yr_note

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/9f32c95cf9f74dd930f0156da1f09270_0.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/9f32c95cf9f74dd930f0156da1f09270_2.png>

在本节课中,我们将学习GAMES102课程的整体介绍,了解几何建模与处理在计算机图形学中的核心地位,并初步探讨函数拟合这一基础建模方法。

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/9f32c95cf9f74dd930f0156da1f09270_4.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/9f32c95cf9f74dd930f0156da1f09270_6.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/9f32c95cf9f74dd930f0156da1f09270_8.png>

## 课程与GAMES平台介绍 🎓

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/9f32c95cf9f74dd930f0156da1f09270_10.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/9f32c95cf9f74dd930f0156da1f09270_12.png>

大家好,我是中国科学技术大学的刘利刚。很高兴在GAMES在线论坛为大家讲解GAMES102这门课程。在101和201两门课程结束后,我将开始讲解关于几何的课程。

首先,我介绍一下本课程的基本情况。

GAMES是“图形学与混合现实在线平台”的缩写。它的主要宗旨是为图形学及相关领域的华人社区提供一个在线交流平台。该平台于2016年4月由专委主任创建,最初是线下活动。2017年6月,我们决定将活动搬到线上,让更多人受益。自2017年6月网站上线运营至今,已举办超过158期在线报告。今年开始,我们创新地推出了系列课程,例如杨林青老师的101入门课程和胡渊鸣同学的201高级课程。下半年由我来讲授几何课程,明年还会有老师讲授202高级课程等。目前社区已发展至11个群,近5400人。如果还未加入,可以扫描屏幕上的二维码。

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/9f32c95cf9f74dd930f0156da1f09270_14.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/9f32c95cf9f74dd930f0156da1f09270_16.png>

GAMES网站(games-cn.org)包含往期报告视频、在线课程资源、线下会议资料以及更多学术会议资源。我们积累了大量资料,旨在让不同方向的同学足不出户就能享受到高端讲座和课程。

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/9f32c95cf9f74dd930f0156da1f09270_18.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/9f32c95cf9f74dd930f0156da1f09270_20.png>

过去三年,我们得到了许多老师的无私付出,特别感谢现任线上运营负责人周晓巍老师以及背后的技术秘书团队。虽然付出了很多时间,但我们也从中收获良多,我也是受益人之一。

关于102课程,更多信息可以访问我的个人主页。在课程注册时,我看到很多网友留言说没有数学几何基础,希望讲一些非常基础的内容。听众的背景可能从未接触数学到有一些几何经验,甚至是非图形专业的同学。因此,我会尽可能讲得通俗易懂。如果对课程有反馈,欢迎给我写邮件。本课程定位为基础课程,后续可能会考虑开设三维几何处理的高级课程。在中国科学技术大学,我们每年都会开设“数字几何处理”课程,相关录屏也可以在B站找到。

本课程将布置5-6个编程作业,难度不会太大,希望大家有时间可以跟着一起做。我们提供了作业提交系统,并建立了两个交流群和一个BBS论坛,助教(我的研究生)会在上面回答问题。课程结束后,我们会向认真完成作业的同学颁发结业证书。

## 图形学中的几何建模 🖼️

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/9f32c95cf9f74dd930f0156da1f09270_22.png>

现在,我们开始讲解课程内容。建模是图形学中一个非常重要的组成部分。

大约七年前,我撰写了一篇介绍图形学的帖子,将图形学分为三大块内容:建模、动画与渲染。GAMES101主要讲渲染,GAMES201讲动画,而我今天的课程将覆盖最后一块——建模。这样,今年的三门课程就涵盖了图形学的三大核心内容。

那么,什么是图像?图像本质上是三维世界投影到我们视网膜或相机感光元件上的成像。由于感光元件是离散的,所以数字图像在计算机中是以离散方式存储的,即由像素组成的栅格图像。图像的分辨率指的是其像素的行列数。

图形则不同,它指的是具有数学表达的几何对象,例如点、线、多边形或曲线。图形也称为矢量图。矢量图存储的是几何元素的数学描述(如顶点坐标),而非像素。因此,矢量图可以无限放大而不失真,因为它会根据数学描述实时重新计算并填充像素,这个过程称为光栅化。而栅格图像放大后则会模糊。

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/9f32c95cf9f74dd930f0156da1f09270_24.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/9f32c95cf9f74dd930f0156da1f09270_26.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/9f32c95cf9f74dd930f0156da1f09270_28.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/9f32c95cf9f74dd930f0156da1f09270_30.png>

人类很早就会通过绘画来创造想象的影像。但若要大规模创造,例如制作动画,靠手绘是不可行的。因此,我们需要通过计算方法来创造图像。

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/9f32c95cf9f74dd930f0156da1f09270_32.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/9f32c95cf9f74dd930f0156da1f09270_34.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/9f32c95cf9f74dd930f0156da1f09270_36.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/9f32c95cf9f74dd930f0156da1f09270_38.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/9f32c95cf9f74dd930f0156da1f09270_40.png>

## 从成像原理到内容创造 💡

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/9f32c95cf9f74dd930f0156da1f09270_42.png>

要计算生成图像,必须理解成像原理。成像需要光源、物体和成像平面。物体表面的颜色能否被看到,取决于光源与其材质的相互作用,反射或折射出的光线进入人眼或相机。这就是图形学渲染的基本物理原理,核心在于解算光照方程。

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/9f32c95cf9f74dd930f0156da1f09270_44.png>

然而,要渲染出逼真的场景,仅有算法是不够的,还需要原材料:场景的几何模型、光源设置、纹理和材质。这些要素共同构成了虚拟世界的内容。在电影和游戏工业中,有专门的美术和技术美术人员负责创建这些内容。

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/9f32c95cf9f74dd930f0156da1f09270_46.png>

对于运动物体,如流体或软体,则需要仿真的科学,即通过解算各种物理方程(如纳维-斯托克斯方程)来模拟运动。仿真就是在做运动计算。

结合强大的建模、仿真与渲染算力,我们可以创造出如《冰雪奇缘》、《流浪地球》等电影中逼真的三维虚拟世界。这就像导演创造了一个真实的平行宇宙。

电影《头号玩家》描绘了虚拟现实(VR)的未来图景:人们通过设备进入一个由规则定义的虚拟世界“绿洲”,并进行社交和活动。这展示了未来虚拟世界的可能性。

## 几何建模:数据的来源与挑战 🧩

但是,创造这些虚拟世界所需的数据从何而来?要渲染出一个逼真的模型,需要建模、UV展开(参数化)、生成法线贴图、位移贴图、材质贴图等一系列复杂数据。这些数据的来源和构建非常困难。

虽然可以依靠美术人员手动创建,但效率低下。本课程的目的就是讲解如何通过工具或程序来构建这些几何数据。

几何建模有多种形式。例如,简单的几何体(方块、球体)可以用简单的数学表达。但工业上制造汽车、飞机所需的曲面必须非常光滑,这就需要连续的数学表达,如样条。在动画中,则可能通过细分和雕刻技术来建模。对于更逼真的效果,如半透明材质、毛发、金属锈迹等,建模手段和表达方式就更复杂。

几何内容的生成至今仍是图形学的瓶颈之一。本课程将重点介绍左侧这些基础的建模手段,右侧的高级建模未来有机会再详谈。

## 函数拟合:连续精准建模入门 📈

现在,我们开始讲解第一个正式内容:函数拟合。我们先从连续的精准建模讲起,建立概念基础后,再理解离散建模会更容易。

我也注意到很多同学在注册时留言,希望考虑到数学基础。因此,我会尽量清楚地讲解数学概念,并从一点点数学开始讲起。完全不讲数学是无法表达后续概念的。大家千万不要害怕数学,它本质上是一种描述规律的语言。

数学来源于实际需求,如计数和土地丈量,后来被欧几里得等人抽象为公理体系,发展成纯粹的演绎科学。我个人更倾向于将数学应用于工程问题。

将实际问题转化为数学模型的过程至关重要:首先用符号表达变量,然后建立优化、方程或统计等模型,最后通过代码实现算法求解。代码是验证想法的必要工具,但更关键的是从问题到模型的建模过程。

数学还要求善于抽象。从幼儿园具体的“苹果相加”,到小学抽象的“数字相加”,再到中学的“代数相加”,概念越来越抽象。

## 必要的数学概念回顾 🔢

以下是后续课程需要的一些基本数学概念回顾,非数学专业的同学也无需担心。

*   **集合**:具有相同性质对象的总体。讨论问题时常限定在特定集合内。
*   **线性空间**:在集合上定义了满足交换律、结合律等性质的运算后,该集合就具有了线性结构。线性空间中的任何元素都可以表示为一组基向量的线性组合,这大大简化了描述。
*   **映射与函数**:映射指一个集合中的每个元素在另一个集合中都有唯一元素与之对应。当两个集合都是实数集时,这种映射称为函数。一元函数的可视化图像是二维平面上的一条曲线。
*   **函数空间**:研究函数时,需要限定在特定的函数集合(空间)内寻找。如果该空间具有线性结构,那么寻找目标函数就转化为寻找一组系数。函数空间的选择很重要,它需要具备足够的表达能力(完备性)来逼近我们想要的函数。例如,魏尔斯特拉斯逼近定理指出,闭区间上的任何连续函数都可以用多项式级数逼近。

## 函数拟合的三部曲 🎯

在许多建模问题中,核心是寻找一个满足要求的函数。这可以归纳为三个步骤:

1.  **在哪找?(模型)**:确定在哪个函数空间中寻找。例如,是在多项式空间还是三角函数空间中找?
2.  **找哪个?(策略)**:定义“好”函数的标准,即损失函数。例如,要求函数必须经过所有数据点(插值),或要求函数与数据点的总体误差最小(逼近)。
3.  **怎么找?(算法)**:根据定义的标准,通过优化或求解方程来找到目标函数。

## 逆向工程与数据拟合实例 🔄

逆向工程是一个典型的拟合问题。例如,我们拿到一个船型的设计图纸,只有离散点,没有方程。为了制造,需要反求出描述船型的函数。

数据拟合(或回归)问题描述如下:给定平面上若干点,寻找一个函数 y = f(x) 来反映这些点的内在规律。

**1. 插值**
如果要求函数必须精确经过所有数据点,这就是插值问题。例如,用n次多项式拟合n+1个点,解一个线性方程组即可。拉格朗日插值多项式是经典解法。但插值可能对数据误差敏感,且可能导致数值不稳定(病态问题)。

**2. 逼近**
如果数据存在测量误差,我们允许函数不一定精确经过每个点,但要求总体误差最小,这就是逼近问题。最常用的误差度量是平方和(L2范数),由此导出的方法称为**最小二乘法**。通过求解目标函数关于系数的偏导数为零得到的方程,称为法方程。

**3. 过拟合与欠拟合**
选择函数空间(如多项式的次数)至关重要。
*   **欠拟合**:函数空间太简单(如用直线拟合曲线),表达能力不足,误差大。
*   **过拟合**:函数空间太复杂(如用高次多项式拟合少量点),虽然对训练数据误差小,但对新数据的预测能力差。为避免过拟合,可采用交叉验证、增加数据、简化模型或添加正则项等方法。

## 正则化与稀疏优化 ⚖️

为了在复杂模型和泛化能力之间取得平衡,可以引入正则项。

*   **岭回归**:在最小二乘法的损失函数中,添加系数的L2范数(模的平方)作为正则项,限制系数的大小,使模型更稳定。
*   **LASSO回归**:使用系数的L1范数(绝对值之和)作为正则项。L1范数倾向于产生稀疏解,即让许多系数为零,从而实现特征选择——从大量基函数中自动挑选出少数重要的。
*   **稀疏优化与压缩感知**:如果一个信号本身是稀疏的(只有少量非零元素),那么可以通过远少于信号长度的观测值,利用稀疏优化算法高概率地精确重建原始信号。这与函数拟合中利用稀疏性选择基函数的思想一脉相承。

## 总结与展望 📝

本节课我们一起学习了GAMES102课程的概况,理解了几何建模在图形学中的重要性,并深入探讨了函数拟合这一基础建模方法的核心思想:通过“模型、策略、算法”三部曲,在选定的函数空间中,根据定义的误差度量,寻找最能描述给定数据的函数。我们还了解了插值与逼近的区别,以及过拟合、欠拟合和正则化的概念。

然而,许多曲线(如一个圆)并不能表示成单值函数 y=f(x)。对于这类更一般的曲线、曲面以及高维复杂函数的拟合问题,我们将在后续课程中探讨。解决思路包括参数化表示、分段拟合并保证段间光滑性(样条)等。

**作业**:实现给定数据点的函数拟合(插值或最小二乘逼近),并可视化结果。观察选择不同次数的多项式时,拟合效果的变化。

**课程计划**:本课程前半部分主要讲解连续的曲线曲面建模(如工业界标准的NURBS),后半部分则转向离散的三角网格曲面处理(如重建、编辑、变形等)。我会尽量讲解核心思想,照顾到不同背景的同学。

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/9f32c95cf9f74dd930f0156da1f09270_48.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/9f32c95cf9f74dd930f0156da1f09270_50.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/9f32c95cf9f74dd930f0156da1f09270_51.png>

本节课就到这里,我们下节课再见!

# GAMES102-几何建模与处理---P10-曲面去噪-采样与剖分---GAMES-Webinar---BV1NA411E7Yr_note

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7450a24b243018315c0904d92dd8d928_1.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7450a24b243018315c0904d92dd8d928_3.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7450a24b243018315c0904d92dd8d928_5.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7450a24b243018315c0904d92dd8d928_7.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7450a24b243018315c0904d92dd8d928_9.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7450a24b243018315c0904d92dd8d928_11.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7450a24b243018315c0904d92dd8d928_13.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7450a24b243018315c0904d92dd8d928_15.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7450a24b243018315c0904d92dd8d928_17.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7450a24b243018315c0904d92dd8d928_19.png>

在本节课中,我们将学习几何处理中的两个核心主题:曲面去噪与网格的采样和剖分。我们将探讨如何去除网格数据中的噪声,以及如何从一组离散点生成高质量的三角网格。

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7450a24b243018315c0904d92dd8d928_21.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7450a24b243018315c0904d92dd8d928_23.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7450a24b243018315c0904d92dd8d928_25.png>

---

## 概述

上一节我们介绍了拉普拉斯算子及其在几何处理中的应用。本节中,我们来看看如何利用这些概念解决实际问题,即如何对带有噪声的曲面进行平滑处理(去噪),以及如何从一组采样点生成结构良好的三角网格(剖分)。这两个过程在计算机图形学、三维重建和有限元分析等领域至关重要。

---

## 第一部分:曲面去噪 🧹

在实际应用中,三维数据通常来自扫描仪或重建算法,由于设备误差或计算误差,数据上常带有噪声。给定一个带噪声的网格曲面,去除噪声的过程称为去噪。

### 噪声的定义与挑战

噪声通常被经验性地描述为高频、小尺度的不规则凸起或高曲率区域。然而,噪声与模型特征之间的界限并不严格。一个核心挑战是在去除噪声的同时,保留模型的尖锐特征(如边和角)。这通常是一个“鸡生蛋”的问题:若能有效去噪,则特征更容易检测;若能准确检测特征,则去噪更容易在保留特征的前提下进行。

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7450a24b243018315c0904d92dd8d928_27.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7450a24b243018315c0904d92dd8d928_29.png>

### 去噪的数学模型

我们可以将问题形式化:输入是一个带噪声的网格 **M**,目标是找到一个干净的网格 **M₀**。假设噪声是加性的,则有:
**M = M₀ + ε**
其中 **ε** 是噪声。这是一个不适定问题,因为 **M₀** 和 **ε** 均未知。

为了简化,我们通常求解每个顶点的新位置 **vᵢ‘**,使其构成的网格更光滑。常假设顶点沿其法向 **nᵢ** 偏移一个距离 **δᵢ**:
**vᵢ‘ = vᵢ + δᵢ * nᵢ**
其中 **δᵢ** 是待求的偏移量,**nᵢ** 可以是当前顶点法向的估计。

### 滤波与卷积

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7450a24b243018315c0904d92dd8d928_31.png>

去噪在数学上常通过滤波实现。滤波的本质是卷积操作,即用一個權重函數對信號進行局部加權平均。對於連續信號,卷積定義為:
**g(t) = ∫ f(τ) h(t - τ) dτ**
其中 **h(t)** 是權重核函數(如高斯函數)。在離散網格上,這意味著用一個頂點鄰域內的其他頂點位置,以某種權重進行平均,來更新該頂點的位置。

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7450a24b243018315c0904d92dd8d928_33.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7450a24b243018315c0904d92dd8d928_35.png>

### 常见的去噪方法

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7450a24b243018315c0904d92dd8d928_37.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7450a24b243018315c0904d92dd8d928_39.png>

以下是几种常见的网格去噪方法:

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7450a24b243018315c0904d92dd8d928_41.png>

1.  **拉普拉斯光顺**:最直接的方法。每个顶点向其邻域顶点的平均位置(即拉普拉斯坐标)移动。更新公式为:
    **vᵢ‘ = vᵢ + λ * L(vᵢ)**
    其中 **L(vᵢ)** 是顶点 **vᵢ** 的拉普拉斯坐标,**λ** 是步长参数。但该方法可能导致网格收缩和特征模糊。

2.  **平均曲率流**:顶点沿其平均曲率法向移动。这比均匀权重的拉普拉斯光顺更具几何意义,能更好地保持体积和特征。其权值使用余切权重。

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7450a24b243018315c0904d92dd8d928_43.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7450a24b243018315c0904d92dd8d928_45.png>

3.  **双边滤波**:从图像处理借鉴的方法。在加权平均时,不仅考虑空间距离(几何接近性),还考虑信号值的差异(特征相似性)。对于网格,信号值可以是顶点位置、法向等。其目的是在平滑时,跨越特征边的点对彼此影响很小。公式核心思想是使用两个高斯核的乘积作为权重。

4.  **法向滤波**:先对网格顶点的法向进行滤波,使其变得光滑,然后根据滤波后的法向来反求新的顶点位置。这通过求解一个线性系统实现,要求每个三角形的新法向与其三条边垂直。

5.  **基于能量优化的方法**:将去噪表述为一个能量最小化问题。最小化的能量通常包含两项:一项要求新网格与原始网格不能相差太远(保真项),另一项要求新网格本身足够光滑(光滑项)。例如:
    **min Σ ||vᵢ‘ - vᵢ||² + μ Σ ||L(vᵢ‘)||²**
    通过添加线性约束(如固定某些特征点),可以在平滑的同时保持特征。

---

## 第二部分:采样与剖分 📍

采样是将连续信号离散化的过程,而剖分是根据离散采样点构建几何单元(如三角形)的过程。高质量的采样和剖分对许多后续计算至关重要。

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7450a24b243018315c0904d92dd8d928_47.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7450a24b243018315c0904d92dd8d928_49.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7450a24b243018315c0904d92dd8d928_51.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7450a24b243018315c0904d92dd8d928_53.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7450a24b243018315c0904d92dd8d928_55.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7450a24b243018315c0904d92dd8d928_57.png>

### 采样定理与质量

根据香农采样定理,采样频率必须高于信号最高频率的两倍,才能无失真地重建信号。对于几何数据,采样不足会导致欠拟合,无法捕捉细节;而用过于复杂的函数去拟合少量采样点,则会导致过拟合。

在平面上,给定一组点,如何将其连接成三角网格?我们追求“质量好”的三角化,通常意味着三角形尽可能接近正三角形,避免出现尖锐的角。

### Voronoi 图与 Delaunay 三角化

给定平面点集,其 **Voronoi 图** 将平面划分为多个区域,每个区域包含离其对应生成点最近的所有点。Voronoi 图的对偶图就是 **Delaunay 三角化**。

Delaunay 三角化拥有许多优良性质:
*   **空圆性质**:任意三角形的外接圆内不包含其他点。
*   **最大化最小角**:在所有可能的三角化中,Delaunay 三角化能够最大化所有三角形中的最小内角,从而避免产生狭长的三角形。
*   其边界构成了点集的凸包。

### 提高网格质量的方法

如果点的分布不佳,即使使用 Delaunay 三角化,网格质量也可能很差。此时需要调整点的位置。

1.  **Lloyd 算法与 CVT**:**Centroidal Voronoi Tessellation (CVT)** 是一种特殊的 Voronoi 图,其中每个生成点恰好位于其对应 Voronoi 单元的重心上。CVT 对应的点分布非常均匀,其对偶的 Delaunay 三角化质量极高。Lloyd 算法是一种迭代方法用于生成 CVT:
    *   给定点集,计算其 Voronoi 图。
    *   将每个点移动到其 Voronoi 单元的重心。
    *   重复上述步骤直至收敛。
    该方法可以推广到曲面上,此时距离需使用测地距离。

2.  **ODT**:Optimal Delaunay Triangulation 是另一种优化能量函数来提高网格质量的方法,在某些方面具有优势。

### 实用工具库

*   **Triangle**:一个功能强大的二维约束 Delaunay 三角化生成库。它可以生成高质量的三角网格,支持指定最小角度、最大面积等约束,并能在必要时自动插入Steiner点(新顶点)以满足要求。
*   **TetGen**:一个专门生成三维四面体网格的库。给定一个封闭曲面,它可以生成高质量的四面体剖分,支持自适应细化。

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7450a24b243018315c0904d92dd8d928_59.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7450a24b243018315c0904d92dd8d928_61.png>

---

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7450a24b243018315c0904d92dd8d928_63.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7450a24b243018315c0904d92dd8d928_65.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7450a24b243018315c0904d92dd8d928_67.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7450a24b243018315c0904d92dd8d928_69.png>

## 总结

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7450a24b243018315c0904d92dd8d928_71.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7450a24b243018315c0904d92dd8d928_73.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7450a24b243018315c0904d92dd8d928_75.png>

本节课我们一起学习了曲面去噪与采样剖分的基础知识。

在去噪部分,我们了解了噪声的定性描述、去噪的数学模型,并介绍了几种核心方法:从简单的拉普拉斯光顺,到更保特征的基于曲率流和双边滤波的方法,再到基于法向滤波和能量优化的高级技术。关键在于在平滑噪声和保持几何特征之间取得平衡。

在采样与剖分部分,我们探讨了如何从离散点生成三角网格。重点介绍了 Voronoi 图、Delaunay 三角化及其优良性质。为了提高网格质量,我们学习了通过移动采样点(如使用 Lloyd 算法生成 CVT)来优化三角化的方法。最后,介绍了一些实用的开源工具库,如 Triangle 和 TetGen。

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7450a24b243018315c0904d92dd8d928_77.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7450a24b243018315c0904d92dd8d928_79.png>

掌握这些基础概念和方法,对于进行几何处理、三维重建和科学计算仿真等任务至关重要。

# GAMES102-几何建模与处理---P11-曲面参数化-曲面简化---GAMES-Webinar---BV1NA411E7Yr_note

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/cbc5a8f5e828af1dcee755948fe9213e_1.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/cbc5a8f5e828af1dcee755948fe9213e_3.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/cbc5a8f5e828af1dcee755948fe9213e_5.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/cbc5a8f5e828af1dcee755948fe9213e_7.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/cbc5a8f5e828af1dcee755948fe9213e_9.png>

在本节课中,我们将学习几何建模与处理中的两个核心主题:曲面参数化与曲面简化。我们将探讨如何将三维曲面映射到二维平面,以及如何简化复杂网格模型以提升处理效率。

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/cbc5a8f5e828af1dcee755948fe9213e_11.png>

---

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/cbc5a8f5e828af1dcee755948fe9213e_13.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/cbc5a8f5e828af1dcee755948fe9213e_15.png>

## 卓越作业情况回顾 📊

首先回顾一下本次卓越作业的完成情况。总体上,提交卓越作业的同学完成情况都比较良好。

以下是几位完成情况较好的同学代表。卓越作业主要要求实现CVT的Lloyd算法,这是一个迭代过程。

这些同学的卓越作业界面设计得比较好。

这里有一个演示。该程序实时生成一些点,并使用Lloyd算法进行迭代。用户可以输入点的数量,也可以修改迭代次数。理论上,迭代次数越多,结果越能收敛,但某些情况下收敛会比较慢。

这是另一位同学的结果。他同样在边界上随机生成一些点,构成Voronoi图,同时显示Delaunay三角剖分并进行迭代。在这个例子中,结果较好,生成了一个比较规整的四边形网格。

这是另一位同学的成果。他同样进行实时迭代,并可以用鼠标交互式地增加点。结果可以实时计算出新的Voronoi图。交互增加点时,Voronoi图会相应更新。当然,Voronoi图也可以实现变密度,密度来源于图像的灰度。这样就能生成一种名为“stippling”的艺术效果,点的密度与图像灰度相关,颜色越深,点的密度越高。使用CVT来实现,效果也不错。

部分同学的优秀代码和卓越作业会挂在卓越作业网站上供大家参考。同学们可以根据这些优秀作业来对比自己的实现效果。

---

## 主题一:曲面参数化 🗺️

上一节我们回顾了卓越作业,本节中我们来看看第一个主题:曲面参数化。

同学们应该在前面的作业中已经体验过参数化。我们一直从映射开始讲解,映射涉及不同维数空间之间的转换。映射本身的维度就是定义域的维数。从二维到二维是平面映射,从二维到三维则是一个曲面,这是正向映射。

三维空间中的参数曲面,实际上是从一个平面区域映射过来的。它看起来是三维空间的一个曲面,但本质上是一个二维流形。这一点我们之前已经非常清楚。

这里引出了另一个问题:给定一张曲面,如何找到它的参数域,即对应的二维区域或定义域?这个问题就叫做参数化,也称为“展开”。形象地说,就是将三维空间的曲面展开成一个平面。其数学本质是寻找一个从R³到R²的映射,使得曲面上的点与平面上的点一一对应。

参数化为什么重要?在之前进行曲面和曲线拟合时,大家已经体会到了。如果参数化不好,会对曲面或曲线的拟合结果产生不良影响。虽然之前是曲线拟合,但曲面拟合同理。如果参数化空间不均匀,会导致拟合出的曲面呈现不好的性质。

参数化还有许多其他应用。例如,地图展开就是一个球面展开成平面的过程。在地图绘制中,也使用了参数化技术,在地理学中称为“球体投影”。在图形学中,最常用的应用是纹理映射。准备一个网格,中间有一条割缝,将其展开后,用一张纹理图与之对应。这样每个顶点就有一个纹理坐标。有了纹理坐标,曲面上的对应点就能获得颜色,从而可以给曲面贴图。艺术家可以基于这张贴图进行绘制,在曲面上画上颜色和图案。这相当于在曲面上绘图,因为有时直接在曲面上操作不方便,可以在平面上进行。这个平面图被称为纹理贴图。

在这个例子中,曲面被分割成若干部分,每一部分分别进行参数化,最终拼接成一个参数化集合,称为“纹理图集”(Atlas)。为什么要分割成若干片?主要是为了使每一片参数化的扭曲较小。分割得越小片,效果通常越好。后面我们会提到这一点。此外,还有许多其他应用也基于参数化的结果,我们后续会陆续展开,这里不详细介绍。

将一个曲面展开成一个二维形状或定义域,我们之前在微分几何中提到过,有一种理想的曲面叫“可展曲面”。可展曲面能够没有任何扭曲地展开成平面。可以这样理解:可展曲面是由一张平面纸,可以没有任何皱褶或挤压而拼成的形状。根据微分几何理论,可展曲面只有三类:柱面、锥面和切线面。它们可以没有任何扭曲地展开。显然,对于非可展曲面,就没有这么好的性质。因此,一般曲面的展开都会产生一些形变或扭曲。

最理想的情况当然是可展曲面。但对于任意曲面,我们需要考虑如何最小化这种扭曲,使得参数化效果尽量好。参数化的性质也包括保持其他几何特性,例如夹角。我们希望夹角尽量保持不变。对于曲面上的夹角,即某点处两条曲线的切线夹角,尽量保持不变的映射称为“共形映射”。此外,还有保持局部面积的映射,以及保持等距关系的映射。

从映射的观点来看,这些保持的性质实际上是映射F的几何量,即其雅可比矩阵的行列式。雅可比行列式的模长(行列式的绝对值)反映了度量保持的性质。如果雅可比行列式等于1,就是局部等距;大于1表示膨胀;小于1表示收缩;小于0则表示发生了翻转。因此,可以用映射F的雅可比行列式来刻画这些性质。

由于我们讨论的曲面主要采用离散表达,即曲面被分割成许多小单元,因此映射F可以分解为一系列定义在这些小单元上的函数。F是这些小单元上函数的拼接,只是拼接需要保持一定的光滑性。所以讨论F可以转化为讨论小单元(在我们这里是三角形)之间的变换。

我们知道,三角形之间的变换在平面上可以用一个相对简单的函数来近似,例如仿射变换或线性变换。也就是说,任何复杂的函数在局部都可以用其一阶部分(线性部分)来近似。

因此,我们将一个从R³到R²的映射简化。首先,将R³中的每个小单元无扭曲地旋转并平铺到一个参考平面R²上。这样,到参数域的映射就变成了从参考平面到参数域的映射。所以我们只需要考虑每个小三角形单元映射到参数域时产生的扭曲,因为从R³空间旋转到R²参考平面的过程没有扭曲,扭曲产生于从参考平面到最终参数域的映射Φ。

由于这是一个仿射变换,变换矩阵就是Φ,可以表示为平移加旋转。使用齐次坐标,变换可以写为 `L * x + T`,其中L是一个2x2的旋转/缩放矩阵,T是平移向量。平移对扭曲没有贡献,因此扭曲通常由这个2x2矩阵L来度量。

如何度量两个三角形之间发生的扭曲程度?在数学上,我们可以对矩阵L进行奇异值分解(SVD)。该分解将任何矩阵(这里为2x2)分解为 `L = U * Σ * V^T` 的形式,其中U和V是正交矩阵,Σ是对角矩阵,其对角线元素σ₁和σ₂称为奇异值,它们是 `L^T * L` 的特征值的平方根。假设σ₂ ≥ σ₁。

其几何意义非常好理解:它将一个单位圆变换成一个椭圆,σ₁和σ₂就是这个椭圆的半短轴和半长轴。σ₂越大,表示拉伸得越扁;如果σ₁=0,则发生退化。因此,我们可以用σ₁和σ₂来度量变换的形变程度。

从图中可以很容易地推导出几种度量:
*   如果σ₁ = σ₂,则为相似变换,即**保角**(共形)。
*   如果σ₁ * σ₂ = 1,则表示单位椭圆与单位圆的面积相等,即**保面积**。
*   如果σ₁ = σ₂ = 1,则圆映射后仍为圆,即**等距**(保刚性)。

对于参数化,还需要考虑如何保持低扭曲。可以看到,不同的参数化产生的扭曲是不同的。有些扭曲较小,有些则拉伸严重。

另一个问题是“翻转”。可以这样判断:如果原始三角形的顶点顺序(例如V1, V2, V3)是顺时针,变换后变成了逆时针,则表示方向(旋向)发生了翻转,这是我们不希望的。因为翻转容易导致纹理映射出现“重叠”或“镜像”等不良现象。如果没有翻转,局部映射是一一对应的,就不会有这些问题。因此,翻转也是参数化需要考虑的一个度量。

对于形变,这里有一个图演示:当一个点逐渐移动时,其σ₁会越来越小。当点跨越某条边界时,σ₁趋近于0。当点继续移动跨越边界后,σ₁可能变为负值,因为此时发生了翻转,即从右手系变成了左手系。因此,要避免翻转,就需要确保σ₁不能跨越0值,即σ₁ > 0。从之前的雅可比行列式描述也可以看出,雅可比值等于σ₁ * σ₂。如果其中有一个值为负,则雅可比值小于0,即发生翻转。

参数化领域多年来产生了大量论文,至今仍是一个非常活跃的课题,每年SIGGRAPH等顶级会议上都有相关论文。我们团队也在此领域进行了十多年的研究,特别是最近几年做了一系列工作,稍后会介绍一些主要成果。

我们将参数化方法分为三类。首先介绍第一类方法:Tutte映射法。

---

### 1. Tutte映射法

Tutte映射法大家都实现过,就是上次作业中实现的Floater方法。它基于Tutte理论并进行了拓展。该方法很简单:对于一个开曲面(有边界),先将边界点映射到平面上的一个凸多边形(可以是圆、矩形或正方形)。然后,内部每个点都是其邻域点的线性组合,组合系数可以自定义,可以是均匀权重,也可以是与几何相关的权重(如余切权重)。

这样,整个系统就形成了一个线性方程组。由于边界点被固定,求解这个方程组即可得到内部点的参数坐标。这种方法有一个非常好的理论保证:如果边界是凸的,那么理论上可以保证结果没有翻转,解是良定的。因此,虽然方法简单,但理论保证很好,至少可以生成一个无翻转的结果。

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/cbc5a8f5e828af1dcee755948fe9213e_17.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/cbc5a8f5e828af1dcee755948fe9213e_19.png>

然而,由于边界是固定的,其结果往往扭曲很大。显然,因为边界不够自由,很多点会挤在一起,导致扭曲非常大。因此,这类方法也有许多人进行改进,最近几年(2015-2017)可以看到相关的工作。

---

### 2. 基于几何优化的方法

另一种改进方向是基于几何度量的优化方法。早年有ABF方法,即基于角度的展开。其出发点是保持每个三角形的角度。如果角度保持好了,三角形的相似性就得以保持。因此,它将角度作为变量来求解参数化网格。

变量就是这些角度。对于一个空间三角形映射到平面后,其周围的角度需要满足一些性质:三角形内角和为π(180度),每个顶点周围的角度和为2π。此外,还有由正弦定理保证的边长与对角正弦值的比例关系。因此,它将参数化网格的角度作为变量进行优化求解。如果解存在,就可以保证没有翻转(因为有强约束)。当然,也可能无解,导致参数化失败。整个方法是将这些约束构建成一个拉格朗日乘子系统进行求解。

这是2008年我早年的一篇文章,引用率较高,也比较知名。其思想是尽量保持每个三角形的旋转刚性。这篇文章读起来或实现起来也不难,有兴趣可以仔细看看。未来我们可能还会介绍这个方法,这里不展开。

这篇文章是我们团队的傅孝明博士在读期间的工作。它的变量是三角形到另一个三角形的变换系数,通过优化这些系数(而不是像之前那样优化角度或旋转)来求得最终的参数化结果。

---

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/cbc5a8f5e828af1dcee755948fe9213e_21.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/cbc5a8f5e828af1dcee755948fe9213e_23.png>

### 3. 严格保证无翻转的方法

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/cbc5a8f5e828af1dcee755948fe9213e_25.png>

今天我们重点介绍第三类方法:能够严格保证无翻转的方法。这个方法实际上与第一类方法有关。第一类方法理论上保证了无翻转,但问题在于扭曲很大。这个方法的思想是:从第一类方法的结果开始,不断优化调整顶点位置,在优化过程中使扭曲逐步减小,直到无法再减小为止,并且在优化过程中始终保持三角形不发生任何退化(即不发生翻转)。这样就能在保持严格无翻转的同时,降低扭曲。

图中颜色条显示,越红表示扭曲越大,越白表示扭曲越小。可以看到,从一个充满红色的结果,慢慢优化出一个几乎没有红色的结果,表示扭曲很小。

具体如何度量扭曲?多年来,人们发明了不少扭曲度量。我们前面提到,σ₂ ≥ σ₁。可以发现,这些扭曲度量都有一个共同特性:较小的奇异值σ₁出现在分母中。我们之前也提到,如果σ₁趋近于零,其倒数将趋近于无穷大。因此,为了避免发生翻转(即避免σ₁趋近于零甚至变为负值),只需最小化那些以σ₁为分母的能量函数。因为一旦σ₁靠近零,目标函数值就会变得非常大。为了避免这种大值,优化过程会倾向于牺牲其他三角形的度量。因此,任何包含σ₁在分母中的度量都可以用来优化。

早年有这种形式。最近几年(2015年)用得比较多的度量是这篇文章提出的“对称狄利克雷能量”。可以看到,σ₁和σ₂在其中对称出现,共同考虑了两个奇异值。我们后面也主要使用这种度量。当然,使用其他度量也可以,但不同度量的优化难度可能不同。

于是,我们将问题形式化为:对每个三角形最小化其扭曲度量。约束条件是雅可比行列式大于0(表示无翻转)。实际上,σ₁和σ₂是矩阵的奇异值,与变量(顶点坐标)呈高度非线性关系。因此,整个系统是一个非常复杂的非线性、非凸优化问题,求解起来比较困难。加上三角形数量可能很多,整个求解效率是需要关心的问题。

对于优化,如果同学们做过优化就清楚,最小化一个能量函数,就是沿着其梯度方向移动。如果使用一阶梯度信息,就是一阶方法(如梯度下降);如果使用海森矩阵(二阶导数)信息,就是二阶方法(如牛顿法)。当然,中间还有一些近似牛顿法等。本质上,二阶方法是在寻找海森矩阵逆与梯度相乘的方向,然后确定步长(走多远)。因此,整个优化过程就是:给定初始值(即Tutte映射的结果),不断更新顶点坐标,沿某个方向移动一定距离。

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/cbc5a8f5e828af1dcee755948fe9213e_27.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/cbc5a8f5e828af1dcee755948fe9213e_29.png>

优化过程中有几个重要量:方向、步长和初始值。近五六年,有许多论文研究如何快速求解这个非线性非凸问题。例如,2015年的这篇文章利用拟牛顿法(L-BFGS)来快速求解;2016年的这篇文章利用牛顿法,用拉普拉斯矩阵近似海森矩阵进行二次逼近来优化;2017年的这篇文章也属于一阶方法,用了另一种近似,用向量场算子逼近海森矩阵。

CM方法是最近几年比较有名的一个方法。它属于二阶方法,因此比一阶方法快。它使用了一个矩阵算子来近似海森矩阵。这是较早(2018年)的一篇文章,使用内点法进行优化,也属于二阶方法。

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/cbc5a8f5e828af1dcee755948fe9213e_31.png>

我想多花点时间介绍一下我们2018年的SIGGRAPH文章。前面几个方法都在寻找如何更好地近似海森矩阵,优化框架类似,只是近似海森矩阵的方式不同,旨在使优化过程更快、更稳定。我们这篇文章的思路稍有不同。

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/cbc5a8f5e828af1dcee755948fe9213e_33.png>

观察这张图:这个模型只有脖子处是边界,边界展开后是一个圆。中间很多头发顶点挤在一起,导致扭曲非常大。扭曲大的原因就在于很多顶点挤在一起。如果直接优化原始能量,会发现中间那些三角形的能量值非常大。从优化观点看,如果目标函数值很大,其下降速度或步长就不能设得太大,下降过程可能不会很快。

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/cbc5a8f5e828af1dcee755948fe9213e_35.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/cbc5a8f5e828af1dcee755948fe9213e_37.png>

我们的想法是:将一个具有极大扭曲的能量值“压下来”。我们不去直接优化原始目标,而是构造一个中间目标函数,该函数的扭曲是有界的。这样,优化过程就会比较快。当然,优化完这个中间目标后,结果并非原始目标的最优解。因此,我们更新目标函数,再次进行优化。虽然需要多次优化,但每次优化过程由于没有非常大的能量值,所以优化速度较快。这是我们方法的一个特色:我们不是像传统方法那样去寻找更好的海森矩阵近似,而是通过修改目标函数本身来使优化变得更快。

这就是我们这篇文章的过程:有一个初始值,然后构造一些参考三角形,使得扭曲不至于太大;接着不断更新参数化结果以及参考三角形,不断优化,最终得到结果。这个过程也始终保持着防止翻转的目标。这里不详细介绍中间细节,大家可以在我们主页上找到当时SIGGRAPH的PPT,里面有非常详细的介绍。我只是向大家介绍我们这篇文章的思路:通过不断更改目标函数来达到对原始问题的求解,思路与原来非常不同。结果也非常好,数据表明至今仍是速度最快的方法之一。

这里我们对比了当时(2018年)的几种方法。可以看到,我们的方法(能量)下降得非常快。红色线是CM方法,收敛相对较慢,时间也较长。我们的方法速度非常快。这是一个非常大型的模型(Lucy),有近百万个顶点。蓝色线是我们的方法,下降很快,迭代94次就达到了非常小的能量值,而其他方法还在不断迭代收敛。

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/cbc5a8f5e828af1dcee755948fe9213e_39.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/cbc5a8f5e828af1dcee755948fe9213e_41.png>

---

### 全局双射参数化

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/cbc5a8f5e828af1dcee755948fe9213e_43.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/cbc5a8f5e828af1dcee755948fe9213e_45.png>

参数化的另一种特性是“全局双射”。局部无翻转是局部双射,而全局双射要求边界在远处也不相交、不碰撞。虽然每个点局部没有翻转,但全局可能发生碰撞,即网格重叠。重叠会导致曲面上的两个点对应同一个纹理坐标,从而产生纹理错乱现象。图中显示,如果没有发生全局自交,就是正常的纹理映射。

全局双射的难点在于:它不仅是映射函数的局部性质,更是一个整体行为。因为要求边界不发生重叠或碰撞,所以它是一个比较难判断的问题。如果将边界看作一个形状,那么就是一个边界不能自交或碰撞的问题,计算量较大。

在我们这项工作之前,只有两篇文章做到了这一点并进行了加速。一篇是2015年的文章,用拟牛顿法加速,但收敛较慢。另一篇是2017年的文章,想法巧妙:在参数化形状外面包裹一层更大的网格。如果这个更大网格不发生自交,就保证了内部网格不会碰撞。但它收敛也比较慢。

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/cbc5a8f5e828af1dcee755948fe9213e_47.png>

我们今年(指课程录制年份)发表在SIGGRAPH的论文解决了这个问题。同样时间下,我们的方法迅速收敛到结果,而其他方法还在不断迭代。2015年的方法更慢。因为这是一个全局非凸问题,不保证解的唯一性,他们可能找到了其他的局部极小值。

这是我们与这两篇全局双射方法的比较,可以看到我们的收敛速度更快,时间仅用5秒,而他们还在运行。前面提到的渐进式方法(Progressive)虽然总体上比我们略快一点,但它不保证全局无自交。我们虽然稍慢一点,但达到了全局双射的结果。可以看到时间对比:0.26秒 vs 2.23秒 vs 11.77秒,我们的方法比这两个方法快了近一个数量级,将问题的求解效率提高了一个数量级。

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/cbc5a8f5e828af1dcee755948fe9213e_49.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/cbc5a8f5e828af1dcee755948fe9213e_51.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/cbc5a8f5e828af1dcee755948fe9213e_53.png>

对于一些比较极端的例子,很多方法都无法收敛,但我们的方法仍能得到非常完美的解。

---

### 封闭曲面与割缝

刚才讨论的是有边界的开曲面参数化。但对于封闭曲面(如球面),要将其展开就必须有一条“割缝”,将其切开才能展开。因此,曲面割缝问题也是一个非常重要的问题。不切开就无法将封闭球面摊平。

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/cbc5a8f5e828af1dcee755948fe9213e_55.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/cbc5a8f5e828af1dcee755948fe9213e_57.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/cbc5a8f5e828af1dcee755948fe9213e_59.png>

割缝问题也有很多研究。早年(2002年)有一篇比较有名的文章叫“几何图像”,它贪婪地寻找参数化中扭曲最大的路径,将其作为割缝,不断寻找直到扭曲可接受为止。我们团队两年前的一位博士生柴双铭也做过

# GAMES102-几何建模与处理---P12-几何映射-几何优化---GAMES-Webinar---BV1NA411E7Yr_note

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/32fe858b9af8e9af270f6a683380ba7e_1.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/32fe858b9af8e9af270f6a683380ba7e_3.png>

## 概述

在本节课中,我们将学习几何映射的核心概念、性质以及如何通过优化方法来求解高质量的映射。几何映射是连接不同几何域(如从三维曲面到二维平面)的关键工具,广泛应用于纹理映射、形状变形等领域。同时,我们也将探讨几何处理中常见的优化问题及其求解思路。

---

## 几何映射的基本概念

上一节我们介绍了曲面参数化,其本质是将三维曲面(二维流形)展开到二维平面。这个过程可以抽象为一个映射 **F**。

这个映射 **F** 是从三维空间到二维空间的一个对应关系。更一般地,我们可以将映射视为从一个域(定义域)到另一个域(值域)的函数。在几何处理中,我们经常处理的是二维平面到二维平面的映射。

对于一个点 **X**(在二维中通常用坐标 (u, v) 表示),映射 **F** 将其映射到像 **F(X)**,它也是一个二维向量。因此,映射可以看作是两个标量函数的组合。

映射有多种表达方式。最常规的是在某个函数空间中进行表达。设有一组基函数 **φᵢ**,则映射 **F** 可以表示为这些基函数的线性组合:

**F(X) = Σᵢ cᵢ φᵢ(X)**

其中,系数 **cᵢ** 是待求的向量(对于二维映射,每个系数包含两个分量)。基函数可以选择径向基函数(RBF)、B样条等。

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/32fe858b9af8e9af270f6a683380ba7e_5.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/32fe858b9af8e9af270f6a683380ba7e_7.png>

在几何处理中,由于曲面通常用离散网格表示,因此映射也常采用分片表达的方式。我们可以将一个复杂的映射分解到各个小片(如三角形)上,用分片线性(仿射)变换来近似。当然,这些分片函数在边界处需要满足一定的连续性和光滑性约束。

---

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/32fe858b9af8e9af270f6a683380ba7e_9.png>

## 几何映射的应用与问题

以下是几何映射的一些典型应用场景:

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/32fe858b9af8e9af270f6a683380ba7e_11.png>

*   **图像与形状变形**:用户通过拖拽几个控制点来改变图像或形状,需要求解内部所有点的变形位置。这本质上是一个插值或拟合问题。
*   **重心坐标变形**:给定一个多边形及其内部点,当多边形边界顶点移动时,利用重心坐标计算内部点的新位置。这也定义了一种从原始形状到变形后形状的映射。

要构造一个好的映射,我们通常关注两个核心性质:

1.  **双射**:映射是一一对应的,即定义域中的每个点唯一对应值域中的一个点,反之亦然。这避免了重叠或折叠现象。
2.  **低扭曲**:映射尽可能地保持局部形状,避免过度的拉伸或压缩。

---

## 映射的性质:双射与局部单射

双射保证了全局的一一对应关系。然而,在实践中,确保全局双射非常困难。我们常常先关注一个更弱的条件:**局部单射**。

局部单射意味着映射在局部邻域内是一一对应的。对于三角形网格上的映射,一个关键的局部现象是 **翻转**。

**翻转** 是指一个三角形在映射后改变了其顶点环绕顺序(例如从逆时针变为顺时针)。这会导致该三角形在参数域中“折叠”起来,破坏了局部的一一对应性。

判断一个三角形是否发生翻转,可以通过计算其有向面积的符号来实现。设原始三角形顶点为 **V₁, V₂, V₃**,映射后顶点为 **U₁, U₂, U₃**。计算映射后三角形的有向面积(例如通过行列式)。如果面积符号由正变负(或反之),则发生了翻转。

**雅可比行列式** 是分析映射局部性质的有力工具。对于映射 **F: ℝ² → ℝ²**,其在点 **X₀** 处的雅可比矩阵 **J** 为:

J = [ ∂u/∂x ∂u/∂y ]

[ ∂v/∂x  ∂v/∂y ]

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/32fe858b9af8e9af270f6a683380ba7e_13.png>

雅可比行列式 **det(J)** 的几何意义是:映射 **F** 将 **X₀** 处一个无穷小区域的面积,放大或缩小的比例因子。

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/32fe858b9af8e9af270f6a683380ba7e_15.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/32fe858b9af8e9af270f6a683380ba7e_17.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/32fe858b9af8e9af270f6a683380ba7e_19.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/32fe858b9af8e9af270f6a683380ba7e_21.png>

*   **det(J) > 0**:保持定向(无翻转),且表示局部面积变化率。
    *   det(J) = 1:局部保面积。
    *   det(J) > 1:局部膨胀。
    *   0 < det(J) < 1:局部收缩。
*   **det(J) = 0**:映射退化,面积收缩为零。
*   **det(J) < 0**:发生了翻转。

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/32fe858b9af8e9af270f6a683380ba7e_23.png>

因此,要保证映射是局部单射(无翻转),一个必要条件是处处满足 **det(J) > 0**。但需要注意的是,处处满足 det(J) > 0(局部单射)并不能保证全局双射,因为可能在远处发生边界重叠。

---

## 映射的扭曲度量与优化模型

为了得到低扭曲的映射,我们需要定义一个度量扭曲的能量函数。通常,我们对雅可比矩阵 **J** 进行奇异值分解(SVD):**J = UΣVᵀ**,其中 **Σ = diag(σ₁, σ₂)**,σ₁, σ₂ 为奇异值(假设 σ₁ ≤ σ₂)。它们代表了主方向上的拉伸系数。

基于奇异值,可以定义多种扭曲能量:

*   **等距能量**:希望映射是刚体运动,即 σ₁ = σ₂ = 1。最小化 **(σ₁ - 1)² + (σ₂ - 1)²**。
*   **保角(相似)能量**:希望映射是相似变换,即 σ₁ = σ₂。最小化 **(σ₁ - σ₂)²** 或 **σ₁/σ₂ + σ₂/σ₁**。
*   **防止翻转的能量**:为了强制 det(J) > 0,常使用如 **σ₁/σ₂ + σ₂/σ₁ + 1/(σ₁σ₂)** 形式的能量,当 σ₁ 趋近于0时,能量会趋于无穷大,从而阻止翻转发生。

一个典型的几何映射优化模型如下:

最小化 E(F) = Σ_三角形T Energy(J_T)

约束条件: det(J_T) > 0, 对于所有三角形 T

      边界条件约束

其中,**Energy(J_T)** 是定义在每个三角形雅可比矩阵上的扭曲能量。变量可以是映射后每个顶点的坐标 **U**。每个三角形的雅可比矩阵 **J_T** 可以根据原始顶点坐标 **V_T** 和目标顶点坐标 **U_T** 解析地表示出来,因此整个优化问题是关于变量 **U** 的。

---

## 优化方法简介

求解上述优化模型需要用到数值优化技术。优化是一个庞大的学科,这里我们仅概述在几何处理中常见的一些概念和方法。

一个优化问题通常表示为:

最小化 f(x)

约束条件: g_i(x) = 0, i = 1,…, m

       h_j(x) ≥ 0, j = 1,..., p

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/32fe858b9af8e9af270f6a683380ba7e_25.png>

其中 **x** 是优化变量,**f(x)** 是目标函数(能量函数),**g_i(x)** 和 **h_j(x)** 分别是等式和不等式约束。

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/32fe858b9af8e9af270f6a683380ba7e_27.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/32fe858b9af8e9af270f6a683380ba7e_29.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/32fe858b9af8e9af270f6a683380ba7e_31.png>

### 无约束优化
当没有约束时,常用方法包括:
*   **梯度下降法**:沿目标函数负梯度方向迭代:**x_{k+1} = x_k - α ∇f(x_k)**,其中 **α** 是步长。
*   **牛顿法**:利用目标函数的二阶信息(海森矩阵)加速收敛,迭代方向为 **-H⁻¹∇f**。
*   **拟牛顿法(如L-BFGS)**:当海森矩阵计算复杂或非正定时,用近似矩阵代替海森矩阵的逆。

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/32fe858b9af8e9af270f6a683380ba7e_33.png>

### 等式约束优化
常用拉格朗日乘子法,将原问题转化为无约束问题:

L(x, λ) = f(x) + Σ λ_i g_i(x)

然后对 **x** 和 **λ** 联合求解。

### 不等式约束优化
更为复杂。常用方法包括:
*   **KKT条件**:最优解需要满足的一组必要条件。
*   **内点法**:通过在目标函数中添加障碍函数,将不等式约束转化为在迭代中自动满足的条件,从而在可行域内部进行优化。

### 特殊结构与现代方法
几何处理中的能量函数常具有可分离结构:**E(x) = Σ E_k(x_k)**,其中 **x_k** 是局部变量(如单个三角形的顶点)。这催生了一些高效方法:
*   **局部-全局交替法**:将问题分解为独立的局部子问题(每个子问题易解)和一个全局缝合问题(通常是一个线性系统),交替迭代求解。前面提到的ARAP参数化方法就是此思想的典型代表。
*   **交替方向乘子法(ADMM)**:通过引入辅助变量和增广拉格朗日函数,将复杂问题分解为多个更易求解的子问题,交替优化。近年来在图形学中应用广泛。

对于特定类型的优化问题(如凸优化、二次规划),存在非常成熟和高效的求解器(如CVX、MOSEK)。在实践中,应根据问题的具体结构(目标函数和约束的形式)选择合适的优化策略或工具。

---

## 总结

本节课我们一起学习了几何映射与几何优化的核心内容。

我们首先明确了几何映射的基本概念,即在不同几何域之间建立对应关系。我们深入探讨了一个“好”映射应具备的两个关键性质:**双射性**(避免重叠折叠)和**低扭曲性**(保持形状)。通过引入**雅可比矩阵**及其**行列式**,我们能够精确地分析映射的局部性质,如面积变化和是否发生翻转。

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/32fe858b9af8e9af270f6a683380ba7e_35.png>

接着,我们介绍了如何将构造理想映射的问题建模为一个**能量最小化问题**,其中能量函数用于度量扭曲(如等距能量、保角能量),并施加**雅可比行列式大于零**的约束以防止翻转。

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/32fe858b9af8e9af270f6a683380ba7e_37.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/32fe858b9af8e9af270f6a683380ba7e_39.png>

最后,由于几何映射的优化模型通常是非线性、非凸的,我们概述了数值优化领域的基本概念和常用方法,包括无约束优化、带约束优化,以及特别适合几何处理问题结构的**局部-全局交替法**和**ADMM**等方法。

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/32fe858b9af8e9af270f6a683380ba7e_41.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/32fe858b9af8e9af270f6a683380ba7e_43.png>

理解几何映射的原理和优化求解的思路,是进行纹理映射、形状变形、参数化等高级几何处理任务的基础。希望本节课能为大家后续的学习和实践提供一个清晰的指引。

# GAMES102-几何建模与处理---P13-曲面重建---GAMES-Webinar---BV1NA411E7Yr_note

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_1.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_3.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_5.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_7.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_9.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_11.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_13.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_15.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_17.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_19.png>

## 概述
在本节课中,我们将学习曲面重建的完整流程。曲面重建是几何处理的核心内容之一,旨在将真实世界中存在的物体,通过数字化手段转化为计算机中的三维模型。我们将从数据采集开始,逐步讲解数据注册、预处理、曲面重建算法以及后处理等关键步骤,并了解该领域面临的挑战与未来展望。

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_21.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_23.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_25.png>

---

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_27.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_29.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_31.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_33.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_35.png>

## 1. 数据采集 📸
上一节我们介绍了课程概述,本节中我们来看看如何获取物体的三维数据,即数据采集。

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_37.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_39.png>

数据采集是指使用传感器设备获取物体表面三维点坐标的过程。根据物体和应用场景的不同,采集的数据类型可以是单个点、轮廓线、截面或整个表面点云。

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_41.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_43.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_45.png>

以下是几种常见的三维数据采集技术:

*   **医学影像**:如CT、MRI,通过采集物体(如人体器官)的一系列横截面图像进行三维重建。
*   **Shape from Shading**:基于渲染方程的逆过程,从单张或多张在已知光照下拍摄的图片中恢复物体的三维形状和材质。
*   **多视角几何**:从不同视角拍摄多张照片,通过特征点匹配和相机参数计算,重建出物体的三维点云。其数学基础是求解一个超定方程组。
    ```数学公式

    x_{img} = K [R|T] X_{world}

    ```
    其中 `K` 是相机内参,`[R|T]` 是相机外参(旋转和平移),`X_{world}` 是世界坐标系下的三维点。
*   **结构光扫描**:使用投影仪向物体投射特定图案(如条纹),通过单个相机捕捉变形后的图案,主动地建立对应关系,从而计算三维坐标。
*   **激光雷达**:主动发射激光并接收反射信号,通过测量光飞行时间或相位差直接计算距离,生成密集的点云。
*   **深度相机**:如微软Kinect、iPhone的LiDAR,能同时捕获RGB图像和深度信息,快速获取物体的2.5维深度图。
*   **视觉外壳法**:从多个视角提取物体的轮廓,将每个轮廓反向投影成空间中的视锥体,这些视锥体的交集即为物体的近似形状。
*   **接触式探针**:通过机械装置接触物体表面并记录探针尖端的坐标,逐点采集,精度高但效率低,可能损伤物体表面。

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_47.png>

<https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_49.png>

---

## 2. 数据注册与配准 🔄
在从不同视角采集到多个局部点云后,我们需要将它们对齐,合并成一个完整的点云,这个过程称为注册或配准。

对于刚性物体,配准问题可以归结为寻找一个最优的刚体变换(旋转 `R` 和平移 `T`),使得两个点云中对应点之间的距离平方和最小。
```数学公式

\min_{R, T} \sum_i ||(R \cdot x_i + T) - y_i||^2

其中 x_iy_i 是来自不同点云的对应点。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_51.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_53.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_55.png

迭代最近点算法 是解决该问题的经典方法:

  1. 为源点云中的每个点,在目标点云中寻找最近邻点作为对应点。
  2. 基于这些对应点,计算最优的刚体变换。
  3. 将变换应用于源点云。
  4. 重复步骤1-3,直到变换收敛或达到最大迭代次数。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_57.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_59.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_61.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_63.png

对于非刚性或分段刚性的物体,需要设计更复杂的能量函数来建模变形。此外,在长时间或环形扫描中,还需解决闭环检测问题,以消除累积误差。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_65.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_67.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_69.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_71.png


https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_73.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_75.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_77.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_79.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_81.png

3. 点云预处理与巩固 🧹

配准后的点云数据往往存在噪声、离群点、采样不均、空洞等问题,直接用于重建效果不佳,因此需要进行预处理,即数据巩固。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_83.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_85.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_87.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_89.png

以下是预处理中常见的任务:

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_91.png

  • 去噪与离群点去除:过滤掉偏离曲面主体、因误差产生的错误点。
  • 法向一致化:确保所有点的法向量方向一致(如都指向曲面外侧),这对后续基于隐式函数的重建方法至关重要。
  • 重采样:使点云在曲面上的分布更均匀,避免局部过密或过疏影响重建质量。
  • 空洞初步修复:利用点云局部信息,对小的缺失区域进行简单填充。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_93.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_95.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_97.png

这些预处理步骤能显著提升输入数据的质量,为后续的曲面重建算法奠定良好基础。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_99.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_101.png


https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_103.png

4. 曲面重建算法 🏗️

点云预处理完成后,核心任务是将离散的点连接成连续的曲面(网格)。重建算法主要分为逼近法离散法两大类。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_105.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_107.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_109.png

4.1 逼近法

逼近法旨在拟合一个函数来表示曲面。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_111.png

  • 参数曲面拟合:使用NURBS或B样条曲面片直接逼近点云,并保证片与片之间的连续性。
  • 隐式函数重建:构造一个三维标量函数 f(x, y, z),使得其零等值面 f(x, y, z) = 0 恰好通过或逼近给定的点云。常用方法有:
    • 径向基函数:使用一系列径向基函数(如高斯函数)的线性组合来拟合一个距离场。
      
      f(\mathbf{p}) = \sum_i w_i \phi(||\mathbf{p} - \mathbf{c}_i||) + P(\mathbf{p})
      
      
      其中 \phi 是径向基函数,\mathbf{c}_i 是中心点,P(\mathbf{p}) 是低次多项式。
    • 泊松重建:通过求解泊松方程来重建指示函数,能更好地处理有向点云。
  • 等值面提取:得到隐式函数后,使用移动立方体算法从其规则网格采样中提取三角网格表面。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_113.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_115.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_117.png

4.2 离散法

离散法不显式构造函数,而是直接基于点云连接成网格。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_119.png

  • Delaunay/Voronoi 类方法:如 Crust 算法及其变种 Power Crust。其核心思想是计算点云的 Voronoi 图,利用其对偶图 Delaunay 三角剖分中的某些边或面来形成重建曲面。这类方法有严格的数学保证,但要求点云采样足够均匀和稠密。
  • 基于优化的方法:将重建问题转化为全局优化问题。例如,L0 网格化 方法同时优化网格顶点的位置和连接关系,最小化原始点云到重建网格的距离。
  • 演化模型法:如“气球膨胀”模型。在物体内部放置一个初始曲面,令其沿法向向外演化,直到接触点云边界;或同时使用内外两个曲面向中间演化,其夹逼的中间面即为重建结果。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_121.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_123.png

5. 后处理与修复 🛠️

重建得到的网格可能仍存在缺陷,需要进行后处理。

  • 网格修复:填补重建后仍存在的空洞。简单方法包括对孔洞边界进行三角剖分;高级方法则借鉴图像修复思想,利用网格的纹理或几何细节进行基于样例的补全。
  • 去噪、光顺与简化:这些是网格处理的基本操作,我们在之前的课程中已经学习过,可用于提升重建网格的质量和效率。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_125.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_127.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_129.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_131.png

6. 动态重建与挑战 🎬

对于运动物体(如人体)的重建称为动态重建。其挑战在于:

  1. 需要高速采集设备(如高帧率深度相机)。
  2. 增加了时间维度的配准问题,即如何将不同时刻的网格进行对齐和跟踪。
  3. 对计算效率要求极高,尤其是实时动态重建。

尽管技术不断进步,但高质量、全自动、鲁棒的曲面重建仍是计算机图形学领域的重大挑战。当前算法的性能严重依赖于输入数据的质量(如采样密度、噪声水平),而实际采集的数据往往不完美。如何突破这些限制,实现便捷高效的三维内容创建,是推动元宇宙、数字孪生等应用发展的关键。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_133.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_135.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_137.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_139.png


https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_141.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_143.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_145.png

7. 作业与课程总结 📚

本节课是曲面重建的导论。我们系统地学习了从真实物体到数字网格的完整管线:

  1. 采集:利用各种传感器获取三维数据。
  2. 注册:将多视角数据对齐合并。
  3. 巩固:对点云进行去噪、重采样等预处理。
  4. 重建:通过逼近或离散方法生成曲面网格。
  5. 后处理:对网格进行修复和优化。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_147.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_149.png

作为本课程最后一次作业,大家可以从以下算法中选择实现,体验曲面重建的过程:

  1. Crust 算法(基于Voronoi图)。
  2. 径向基函数 隐式重建。
  3. 泊松重建

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_151.png

希望大家通过动手实践,加深对曲面重建核心思想的理解。在接下来的课程中,我们将进入几何建模与处理的高级话题,探讨形状分析、匹配及其在机器人、制造等领域的应用。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_153.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7366bae8e489dd4e4935000a8cec27fc_155.png


本节课中我们一起学习了曲面重建的核心流程与主要算法,认识到将现实世界物体转化为高质量数字模型所涉及的技术广度与深度。尽管仍面临诸多挑战,但这一领域的发展无疑是连接物理世界与数字世界的关键桥梁。

GAMES102-几何建模与处理—P14-几何建模—GAMES-Webinar—BV1NA411E7Yr_note

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_0.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_2.png

在本节课中,我们将学习几何建模的核心概念与方法。课程将从重建与设计的区别开始,系统介绍从零开始设计的传统CAD方法(如实体建模)以及对已有模型进行编辑和变形的现代技术。我们将探讨点、线、面等不同层次的编辑代理,并了解基于数据驱动和深度学习的建模新趋势。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_4.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_6.png


https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_8.png

概述

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_10.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_12.png

上节课我们全面介绍了三维重建,从数据采集到点云处理,再到网格重建与后处理。重建的对象是物理世界中已存在的物体。然而,人们常常需要设计全新的物体,或对现有模型进行修改。本节课,我们将聚焦于“设计”这一过程,即几何建模。

建模主要分为两大方向:

  1. 从零开始设计:使用CAD工具凭空创造形状。
  2. 编辑已有模型:对给定的三维模型进行修改和变形。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_14.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_16.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_18.png

我们将依次探讨这两大类方法。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_20.png


从零开始设计:传统CAD建模 🏗️

传统CAD建模源于机械、土木等工程领域,旨在精确地设计和表达零件。以下是几种核心方法。

三视图建模

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_22.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_24.png

三视图建模,或称工程制图,通过物体的三个正交投影视图(顶视图、前视图、侧视图)来唯一确定三维形状。设计者需要具备空间想象能力和几何计算能力,以确保不同视图中的投影关系正确。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_26.png

核心思想:三维形状由其二维投影唯一决定。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_28.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_30.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_32.png

实体建模

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_34.png

实体建模是CAD领域的核心,它直接构建具有体积的实体对象,而不仅仅是表面。以下是几种基本操作:

扫掠
扫掠操作将一个二维截面沿着一条轨迹线移动,扫过的空间即构成实体。

  • 线性扫掠:截面沿直线平移。
    • 实体 = 拉伸(二维截面, 方向, 距离)
  • 旋转扫掠:截面绕一根轴旋转。
    • 实体 = 旋转(二维截面, 旋转轴, 角度)
  • 沿路径扫掠:截面沿一条曲线路径移动,并可保持截面与路径垂直。
  • 放样:在两个或多个不同形状的截面之间进行过渡,生成光滑的实体。

参数化与约束
参数化建模允许通过修改参数(如尺寸、角度)来驱动模型变化。设计约束用于保持特定的几何关系(如平行、垂直、等长),这些约束构成了“设计意图”。

倒角与圆角
对实体的尖锐边缘进行切削或添加圆滑过渡,称为倒角或圆角。

布尔运算
通过并集、交集、差集等布尔操作,组合基本几何体(如立方体、球体、圆柱体)来构建复杂形状。

  • 复杂实体 = 基本体A <布尔操作> 基本体B

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_36.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_38.png

边界表示
实体在计算机内部通常采用边界表示法存储,即记录构成实体边界的所有点、边、面的信息及其拓扑关系。它必须满足欧拉公式以保持流形性。

欧拉操作
一系列低层级的原子操作(如生成边、生成面),用于逐步构造出复杂的边界表示结构。


编辑已有模型:交互式变形与编辑 ✏️

对于动画、游戏和数字艺术等领域,更常见的是对已有模型进行直观的编辑和变形。其核心思想是:通过编辑一个简单的“代理”,来驱动复杂模型的变形

编辑的方法论

编辑过程可以抽象为以下步骤:

  1. 为原始复杂形状 S 找到一个简单、易编辑的代理 P
  2. 用户交互修改代理 P 得到 P‘
  3. 通过一个映射函数 G,将代理的变化传递回原始形状,得到变形后的结果 S‘
    • S‘ = G(P‘)

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_40.png

关键在于寻找合适的代理 P 和定义有效的映射函数 G

基于点的编辑

代理 P 是一组顶点(句柄)。用户拖动少数几个点,并固定一些点,系统自动计算其他顶点的位置,使变形自然。

数学本质:这是一个插值问题。需要找到一个变形函数 F,满足固定点位置不变、拖动点到达目标位置,同时尽可能保持模型的局部细节。

常用方法

  • 径向基函数插值
  • 移动最小二乘法
  • 基于向量场的变形:将模型嵌入到一个连续向量场中,编辑场中的流线来驱动变形,能有效避免自交。
  • 拉普拉斯坐标编辑:保持每个顶点的拉普拉斯坐标(局部细节)不变或相似,通过求解线性系统得到新顶点位置。这是非常经典且有效的方法。

基于线/骨架的编辑

代理 P 是曲线,如模型的骨架、轮廓线或特征线。编辑曲线比编辑大量顶点更直观。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_42.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_44.png

关键问题:定义曲面上每个顶点与骨架/曲线之间的权重关系(蒙皮权重)。当骨架变形时,顶点根据权重混合骨架的变化。

  • 顶点新位置 = Σ(权重_i * 骨骼变换_i * 顶点原位置)

基于体/笼子的编辑

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_46.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_48.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_50.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_52.png

代理 P 是一个包围模型的简单多面体网格(称为“笼子”)。编辑笼子的顶点,模型内部的点通过广义重心坐标随之变形。

  • 内部点坐标 = Σ(重心坐标_i * 笼子顶点坐标_i)

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_54.png

基于简化的编辑

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_56.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_58.png

代理 P 是原始模型的简化版本。在简化模型上编辑后,将简化过程中去除的细节重新添加回去,得到最终的高细节变形结果。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_60.png

基于草图的建模

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_62.png

这是一种“从无到有”的编辑。用户绘制二维草图,系统自动推断并生成三维模型。这大大降低了三维建模的门槛。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_64.png

数据驱动的建模与深度学习

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_66.png

随着三维模型数据集的增长,数据驱动的方法变得流行:

  • 部件组装:从模型库中提取语义部件(如椅腿、椅背),重新组合成新模型。
  • 概率模型:使用贝叶斯网络等模型学习部件之间的搭配概率,指导用户创作或自动生成。
  • 深度学习生成:使用生成对抗网络等深度学习模型,学习三维形状的隐式分布,可以直接生成新的三维模型。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_68.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_70.png


https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_72.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_74.png

形状渐变 🌀

形状渐变解决的是如何在两个给定形状 AB 之间,生成一系列自然的中间过渡形状。它广泛应用于关键帧动画和工业设计。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_76.png

形状渐变分解为两个核心问题:

  1. 对应关系问题:建立形状 AB 上点与点之间的一一映射。
  2. 插值路径问题:在对应关系建立后,如何插值对应点以生成中间形状。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_78.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_80.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_82.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_84.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_86.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_88.png

建立对应关系

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_90.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_92.png

  • 参数化方法:将两个形状参数化到同一个公共域上,在公共域上建立对应,再映射回三维空间。
  • 基于简化:先简化两个模型,在简单的基网格上建立对应,再传递回原始网格。
  • 基于分割:将模型分割成语义部件,在部件级别建立对应。
  • 现代映射方法:将对应问题转化为优化问题,最小化映射的几何扭曲。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_94.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_96.png

插值路径

  • 线性插值:最简单,直接对对应顶点的坐标进行线性插值。可能导致体积收缩和不自然旋转。
  • 非线性插值
    • 插值内在属性:插值边长、夹角等网格内在属性,而非顶点坐标。
    • 仿射变换插值:将每个三角形的变换分解为旋转和缩放,分别插值。
    • 隐函数插值:为两个形状构造符号距离场等隐式函数,插值隐函数,再提取中间等值面作为过渡形状。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_98.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_100.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_102.png

总结

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_104.png

本节课我们一起学习了几何建模的两大支柱:从零开始设计的传统CAD方法和编辑已有模型的现代交互技术。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_106.png

  • CAD建模 侧重于精确性、参数化和制造约束,是工业设计的基石。
  • 模型编辑 侧重于直观性、交互性和艺术表达,其核心思想是通过编辑简单代理来控制复杂模型
  • 形状渐变 是连接设计与动画的重要技术,重点在于建立模型间的合理对应并生成自然的插值路径。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_108.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_110.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_112.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_114.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_116.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e633dbd87368a33494468d6923291677_117.png

尽管已有众多方法,三维内容创作因其高维性和对空间想象力的要求,仍然是一个充满挑战的领域。数据驱动和深度学习等新范式正在为这个领域带来新的活力。希望本课程能为你打开几何建模世界的大门,提供一个继续探索的“指针”。

GAMES102-几何建模与处理—P15-纹理合成-形状分析-课程结语—GAMES-Webinar—BV1NA411E7Yr_note

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_0.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_2.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_4.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_6.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_8.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_10.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_12.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_14.png

在本节课中,我们将学习课程的最后一部分内容:纹理合成与形状分析。我们将探讨如何为几何模型赋予纹理,以及如何从更高层次分析和理解三维形状。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_16.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_18.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_20.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_22.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_24.png


https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_26.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_28.png

作业回顾 📝

上一节我们介绍了曲面重建与建模。本节开始,我们先回顾最后一次作业的情况。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_30.png

总体上交作业的同学表现不错。以下是部分同学的作业结果:

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_32.png

  • 一位同学实现了显示方法(Cross-stitching算法),算法出现一些小问题,例如连接处发生错误。但总体上大部分结果是正确的。顶点加密后可以避免这种错误。
  • 另一位同学使用泊松方法进行重建。泊松方法是一种隐式方法,需要点的法向。如果法向发生错误,重建结果就会出现异常。大部分异常现象是因为法向相反。由于是作业,同学们可能没有太多时间检查法向的正确性,因此结果存在一些错误。
  • 一位同学录制了视频演示。首先展示点云,然后调用Marching Cubes算法重建网格。重建结果不错,因为数据质量较好,法向都正确。
  • 另一位同学进行了比较完整的演示,实现了两种方法:RBF(径向基函数拟合)和泊松拟合。在菜单中可以选择不同方法,并对距离场进行自适应剖分来计算距离值。切换到泊松方法后可以看到,如果顶点不是特别密,重建质量不是特别好,会出现一些小问题。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_34.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_36.png

我们同样会把最后一次作业的报告、代码以及优秀同学的报告代码挂在网上供大家参考。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_38.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_40.png


纹理合成概述 🖼️

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_42.png

回顾前几次课程,我们从曲面重建讲到曲面建模。重建是物体已存在,我们通过设备测量出点,再利用算法重现三维模型。建模是通过用户交互进行设计。这些模型只有顶点数据,没有颜色,看起来不真实。我们需要为模型贴上纹理,使其看起来更真实。

为模型赋予纹理有多种手段。对于重建的模型,物体本身带有颜色,只需采集其RGB颜色并对应到模型顶点即可。对于设计出来的模型,纹理后期需要通过交互手段赋予,例如参考图片并通过参数化结果上色,或直接用手工画笔在平面或曲面上绘制颜色。

今天我们不讲解如何绘制真实纹理,而是关注纹理合成。假设我们已经有一个小的纹理样本,我们能否将这个样本铺满到一个几何模型上?这就是纹理合成要解决的问题。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_44.png

纹理合成的定义是:给定一个小的纹理样本 I,目标是合成一张大的纹理 JJ 看起来像 I,但又不是简单的重复。这个“看起来像”的度量很困难,且需要带有一定的随机性。这个问题在20多年前开始成为研究热点。

纹理合成的用途广泛:

  • 为枯燥的光滑曲面赋予丰富纹理,使其更形象。
  • 图像修补,例如将图片中某块区域去掉,然后用小纹理样本填充空洞。
  • Photoshop中的克隆画笔工具就是一种简单的拷贝,但纹理合成不仅仅是拷贝,还需要带有变化。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_46.png


https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_48.png

纹理的定义与分类 🔍

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_50.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_52.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_54.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_56.png

我们首先需要理解什么是纹理。纹理(Texture)与一般图像(Image)有所不同。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_58.png

纹理通常指物体表面的表现,如木纹、墙砖、草地等,带有重复性。一个关键特征是它具有很多重复的相似模式。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_60.png

如何判断一张图是纹理还是图像?

  • 对于纹理,在任意两个地方取同等大小的框,肉眼看会觉得它们差不多,属于同一种纹理。这种各处都相似的表现称为纹理。
  • 对于图像,在任意两个地方取框,看起来显然不同,没有太多相似性。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_62.png

根据属性,纹理可以分类为:

  • 各项同性:各个方向看起来差不多。
  • 各项异性:不同方向有差异。
  • 规则重复:像砖头一样一块块重复。
  • 随机:看不出明显重复。
  • 介于两者之间

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_64.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_66.png

不同的纹理性质,其合成方法会略有差别。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_68.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_70.png


二维纹理合成方法 🧱

我们先理解二维纹理合成,三维就容易类比。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_72.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_74.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_76.png

简单平铺与目标

最简单的纹理合成就像铺瓷砖,将小样本一块块贴满区域。但这会产生很强的重复特征,看起来太规则,不是纹理合成期望的目标。我们更希望合成结果有一定的随机性,不是完全平铺,但看起来仍然是原始样本的纹理。

纹理合成没有唯一解,很多算法结果都是可接受的,算法通常带有一定的随机性。

核心挑战:量化“看起来像”

纹理合成的难度在于如何捕捉或描述“看起来像”这种视觉感受。这不是一个精确的数学定义,很难量化。解决问题的第一步就是如何将其建模成可量化的东西。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_78.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_80.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_82.png

今天主要讲两种基于样本的方法:参数化方法和非参数化方法。

  • 参数化方法:对纹理进行描述,构建数学模型(函数),然后将函数应用到区域生成纹理。
  • 非参数化方法:从样本中拷贝像素或图块,在过程中产生随机现象。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_84.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_86.png


https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_88.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_90.png

参数化方法 (Parametric Method)

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_92.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_94.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_96.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_98.png

参数化方法在早年应用较多。其思想是对纹理生成一个多分辨率金字塔,在每个分辨率上用一个函数(映射)提取特征,将纹理隐射到一个特征空间,然后再通过函数逆映射回图像。这有点像现在的自编码器(AE)或变分自编码器(VAE)。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_100.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_102.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_104.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_106.png

具体构造映射有不同方法,例如使用卷积或全字塔滤波提取特征。多分辨率方法可以捕捉不同尺度的特征。一个简单的早期算法使用了直方图(颜色分布)进行匹配和迭代。但直方图只体现了颜色分布,没有很好刻画特征,因此合成效果有时不好。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_108.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_110.png


非参数化方法 (Non-parametric Method)

非参数化方法思想更简单,它不用函数描述纹理,而是直接从原始样本中拷贝。拷贝过程中不是从同一地方考,而是可以发生随机现象。这个过程可以从数学上解释为一个马尔可夫随机场:拷贝了某一块后,其周边的像素颜色就不能乱拷贝了,需要根据这一块的特征去样本里搜索最相似的周边图块。这就像一个条件概率过程。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_112.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_114.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_116.png

1. 基于像素的方法 (Pixel-based)

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_118.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_120.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_122.png

这是最简单的逐像素纹理合成方法。

  • 算法步骤:假设右边已经合成到某个位置,当前未知像素 p。取 p 周边已知颜色的 L 型区域。用这个 L 型区域的颜色到样本图像中所有位置进行比对,找到最相似的位置。将该位置 p 点的颜色拷贝过来。以此类推,逐个像素合成。
  • 计算量:最大的计算量在于比对 L 型区域的颜色与样本中所有位置的颜色。度量通常使用 L2 范数(逐像素差异平方和)。这是一个检索问题,需要用数据结构(如 kd-tree、八叉树)组织样本中的特征向量以加速搜索。
  • 窗口大小影响:用于比对的窗口(邻域)大小很重要。窗口太小,合成质量低;窗口合适,才能抓住纹理的结构(pattern)。参数取决于样本中 pattern 的大小。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_124.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_126.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_128.png

2. 基于图块的方法 (Patch-based)

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_130.png

逐像素方法很慢。基于图块的方法一次拷贝很多像素,速度更快。

  • 算法步骤:假设已经合成了一块区域。用这块区域的一个邻域(通常是重叠部分)去样本中搜索最相似的图块。然后将这个最相似的图块拷贝过来。一次操作可以拷贝一个图块(如 10x10 像素),速度比逐像素快很多。
  • 接缝处理:两个图块重叠在一起时,它们可能不完全一致。需要找一条误差最小的接缝,使得拼接后视觉效果更光滑。这可以转化为在误差图上寻找最小代价路径的问题,是一个典型的动态规划问题,在图论中也是最小割/最大流问题。
  • 应用:这种基于图块和最小接缝的技术非常适合自然图像合成,也是当年“内容感知图像缩放”技术的核心原理。内容感知缩放能保持图像明显特征,避免简单缩放带来的扭曲或裁剪导致的内容丢失。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_132.png

3. 其他高级方法

为了保持纹理 pattern 的完整性,避免合成结果破碎,后续研究提出了许多方法:

  • 基于纹理元素:手工或通过视觉方法判断纹理中的基本元素(texel),在合成过程中保持这些元素的结构。
  • 控制局部大小与方向:合成时可以控制纹理图块的大小和方向。通过生成一个向量场来引导合成顺序,可以产生不同朝向的纹理结果。

三维纹理合成 🎯

理解了二维纹理合成,三维可以类比进行。核心思想类似,但需要在三维曲面上定义邻域、方向和参数化。

主要方法分类

  1. 过程式纹理:用一个三维函数 F(x, y, z) 定义纹理特征(颜色值)。将三维模型嵌入到这个场中,模型表面顶点即可获得颜色值。函数可以通过一些方法构造,例如著名的 Perlin 噪声函数,通过扰动和随机生成各种纹理。这种纹理是定义在三维空间中的体纹理,物体内部切开来也有颜色。
  2. 基于样本的曲面纹理合成:给定一个小样本,如何将纹理“长”在曲面上。这需要解决几个关键问题:生成多密的采样点、如何定义曲面上点的邻域、如何定义方向。
    • 思路:类比二维,在曲面上对于一个点,需要朝各个方向走一定距离来采样其邻域。这需要定义一个向量场来指示方向。将局部曲面片参数化到平面,然后在参数域上进行采样和颜色匹配,最后将颜色拷贝回顶点。
    • 多分辨率方法:在网格上也可以使用多分辨率方法,低分辨率捕捉大特征,高分辨率捕捉细节,使匹配更精准。
    • 基于图块的合成:也可以将一个面片(patch)贴到曲面上,然后根据邻域匹配找到最好的图块贴上去,像贴膏药一样。为了保持纹理元素完整,图块形状可能是不规则的,沿着纹理元素边界设置。
    • 向量场的重要性:对于各项异性的纹理,一个好的向量场对合成结果至关重要。向量场需要光滑,并且可能要求与模型的几何特征(如边界)对齐。生成符合要求的向量场本身是几何处理中的一个重要问题,通常可以看作插值问题。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_134.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_136.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_138.png

形状分析与理解 🧠

最后一部分我们简要介绍形状分析与理解。这部分内容属于高级主题,涉及从更高层次理解三维形状。

随着互联网上三维模型越来越多,我们需要组织、理解和检索这些模型。这超出了传统局部几何处理的范围,涉及全局操作和语义理解。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_140.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_142.png

主要研究问题

  • 特征检测:检测模型上的关键点、特征线、显著性区域。
  • 方向归一化:将模型摆正,使其具有一致的朝向,便于后续处理。
  • 分割:将模型分割成有意义的部件。
  • 语义标注:为分割后的部件赋予标签(如头、腿、扶手)。
  • 对称性检测:检测模型的对称性(镜面对称、旋转对称等),用于压缩和编辑。
  • 骨架提取:提取模型的一维骨架,用于抽象表示和分类。
  • 对应关系:找到不同模型之间点、部件或整体的对应关系。
  • 形状检索与分类:基于形状特征从数据库中检索相似模型,或对模型进行分类。
  • 结构分析:分析模型部件的层次结构、连接关系。
  • 功能分析:分析模型部件的功能、运动机构以及人与物体的交互方式。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_144.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_146.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_148.png

形状描述子

解决上述任务的关键是度量形状元素之间的相似性。这就需要形状描述子——将点、面片、部件或整个形状映射到一个高维向量(描述子),通过比较向量间的距离(如 L2 范数)来度量相似性。

  • 人工设计特征:早期工作依赖于人工设计的特征,如曲率、法向、局部面积/体积、测地距离等。这些特征需要针对不同任务和模型类型进行精心设计和选择。
  • 端到端学习:最近5-10年,深度学习方法崛起。通过神经网络,可以直接从输入数据(如点云、网格)学习到适合特定任务的特征描述子,无需人工设计。这本质上是拟合一个复杂的函数,但可解释性较弱。

课程总结与展望 🌟

本节课我们一起学习了纹理合成与形状分析的基础概念和方法。

几何数据随着采集设备发展而日益丰富,成为表达三维世界的新数字媒体。其应用越来越广,但上手难度高于图像处理,因为它涉及点、网格、体素、距离场、函数等多种表达方式,拓扑复杂。

GAMES102 课程至此结束。本课程系统性地介绍了从拟合、参数曲线曲面、细分、离散网格处理到纹理合成的基础知识。虽然时间紧凑,但希望能帮助大家建立几何处理的知识框架。

后续 GAMES 平台将继续推出高质量课程,如《高质量实时渲染》(GAMES202)和《三维视觉与理解》(GAMES203)。此外,也欢迎大家关注图形学相关的开源项目、学术会议和书籍。

感谢各位同学15周以来的陪伴与坚持!学习过程虽有挑战,但成长最快。希望大家在几何处理的道路上继续探索,收获更多。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_150.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_152.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_153.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/a64234e3a3da9296083647ba7f8a7555_154.png

课程结束,感谢大家!

GAMES102-几何建模与处理—P2-数据拟合—GAMES-Webinar—BV1NA411E7Yr_note

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/caa603be1dc2db8ef373a3d00b731652_0.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/caa603be1dc2db8ef373a3d00b731652_2.png

在本节课中,我们将继续学习数据拟合的核心内容。我们将回顾函数映射的基本概念,深入探讨如何寻找一个“好”的函数来拟合给定数据,并理解函数拟合的三个关键步骤:定义函数空间、设定目标函数以及进行优化求解。课程将涵盖多项式插值、最小二乘拟合、径向基函数(RBF)等经典方法,并揭示它们与神经网络之间的内在联系。


回顾与引言 🔄

上一节我们介绍了函数拟合的基本框架。函数映射,即给定一个输入 x 输出一个 y,是我们分析的基础。目前我们限定 xy 为实数,未来可以推广到向量、矩阵甚至张量。例如,一张图片可以看作一个矩阵,因此映射函数可以推广到高维。

我们面临的核心问题是:给定一组 (x, y) 数据对,如何找到一个函数来拟合它们?这个过程分为三步:

  1. 定义什么是“好”的函数。
  2. 确定从哪个函数集合(函数空间)中寻找。
  3. 通过优化目标函数(通常是求梯度)来找到最佳函数。

理解这个框架后,我们就能更好地处理更复杂的拟合问题。


函数拟合的目的与挑战 🎯

我们为什么要进行函数拟合?给定一些观测点(离散数据),拟合一个函数主要有两大好处:

  • 压缩存储:用少量系数存储复杂函数,代替存储大量原始数据。
  • 预测:有了函数模型,可以对新的输入 x 预测其输出 y

然而,定义一个“好”的拟合函数并非易事。以下是几种常见情况及其挑战:

以下是几种常见的拟合思路及其优缺点:

  • 分段线性插值:用直线段连接所有数据点。误差为零,但函数不够光滑(仅 C^0 连续),在连接点处不可导,不利于后续数值计算。
  • 光滑插值:寻找一个经过所有数据点的光滑函数。但若数据含有噪声或异常值,强行插值会导致函数扭曲,预测不可靠。
  • 拟合(逼近):允许函数不精确经过每个点,但要求整体误差较小。这种方法对噪声和异常值有一定鲁棒性。

绝对好的方法并不存在,选择取决于具体应用场景和领域知识。如果对数据背后的规律一无所知,拟合将变得非常困难,通常需要反复“调参”。


拟合方法论三部曲 📝

寻找拟合函数可以系统化为以下三步:

  1. 确定函数空间:我们需要限定函数的搜索范围。通常,我们将目标函数表示为一系列基函数的线性组合:f(x) = Σ λ_i * φ_i(x)。问题转化为求解系数 λ_i。基函数的选择至关重要,它决定了函数空间的表达能力。
  2. 定义目标函数:我们需要一个标准来衡量函数的好坏。目标函数通常包含两部分:
    • 误差项(Data Term):衡量函数预测值 f(x_i) 与真实值 y_i 的差距,常用平方和 Σ (y_i - f(x_i))^2
    • 正则项(Regularization Term):对函数或系数加以约束,防止过拟合或得到病态解。例如,惩罚系数的大小(L1/L2正则化),或惩罚函数的高阶导数(控制光滑度)。
  3. 优化求解:在设定的函数空间中,寻找使目标函数最小的系数。对于平方误差这类形式,求导后可化为线性方程组求解。对于更复杂的目标函数,可能需要梯度下降、牛顿法等优化算法。

多项式插值及其问题 ⚠️

n 次多项式 P_n(x) 插值 n+1 个点,可以通过求解范德蒙德方程组得到系数。拉格朗日插值法和牛顿插值法是两种预先计算基函数、避免重复求解方程组的技巧。

然而,多项式插值存在显著问题:

  • 病态问题:范德蒙德矩阵的条件数随着点数增加而指数级增长,导致方程组对输入数据的微小扰动极其敏感,求解不稳定。
  • 龙格现象:使用等距节点的高次多项式插值,在区间边缘会出现剧烈的振荡。这是因为幂函数基 {1, x, x^2, ...} 在高次时数值性质很差。

因此,高次多项式插值在实践中并不常用。


更好的基函数:伯恩斯坦基 ✨

同一个多项式空间可以用不同的基来表示。伯恩斯坦基函数是一组定义在 [0, 1] 区间上、具有良好数值性质的基函数。

以下是伯恩斯坦基函数的关键性质:

  • 非负性与权性B_i^n(x) >= 0,且对任意 xΣ B_i^n(x) = 1。这组基函数可以看作一组“权”。
  • 数值稳定性:用伯恩斯坦基表示的多项式,即使次数很高(如20次、50次),也不会出现龙格现象,计算稳定。
  • 几何意义:系数可以视为控制顶点,调整顶点位置能直观地改变曲线形状,便于几何设计。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/caa603be1dc2db8ef373a3d00b731652_4.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/caa603be1dc2db8ef373a3d00b731652_6.png

基函数之间的变换由矩阵描述。选择数值性质优良的基函数,是获得稳定算法的基础。


径向基函数(RBF)拟合 🎯

径向基函数是另一种强大的拟合工具。在一维情况下,最典型的RBF是高斯函数:g(x) = exp(-(x-μ)^2 / (2σ^2))

RBF拟合的核心思想是:在每个数据点 x_i 处放置一个高斯函数(或其他RBF),然后对这些基函数进行线性组合来逼近目标函数:f(x) = Σ w_i * g(||x - x_i||)

以下是RBF拟合中的关键点:

  • 参数选择:高斯函数的中心 μ(常取为数据点 x_i)和宽度 σ 需要设定。σ 过小会导致基函数像脉冲,拟合曲线不平滑;σ 过大则过于平滑,可能欠拟合。
  • 稠密性保证:理论上,只要使用足够多的高斯函数,其线性组合可以逼近任意连续函数。
  • 与神经网络的联系:将上述 f(x) 的表达式稍作变形:f(x) = Σ w_i * g(a_i * x + b_i)。这可以看作一个单层神经网络:输入 x 经过仿射变换 a_i*x + b_i,再通过激活函数 g(此处为高斯函数),最后加权求和输出。这里的 w_i, a_i, b_i 都是可学习的参数。

因此,RBF网络是一种特殊的神经网络。优化这些参数是一个非线性优化问题,通常只能找到局部最优解,初始值的选择非常重要。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/caa603be1dc2db8ef373a3d00b731652_8.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/caa603be1dc2db8ef373a3d00b731652_10.png


神经网络的函数视角 🧠

从函数拟合的角度看,神经网络就是一个复杂的函数 f(x; θ),其中 θ 代表所有权重和偏置参数。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/caa603be1dc2db8ef373a3d00b731652_12.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/caa603be1dc2db8ef373a3d00b731652_13.png

  • 万能逼近定理:只要神经网络具有足够多的神经元(即足够大的容量),它可以以任意精度逼近任何连续函数。
  • 本质:神经网络通过多层线性变换与非线性激活函数的复合来构造复杂的函数空间。训练网络就是寻找最优参数 θ,使网络输出 f(x_i; θ) 尽可能接近真实值 y_i
  • 挑战:与所有拟合方法一样,神经网络也面临如何选择网络结构(层数、每层神经元数)、如何设置正则化防止过拟合、以及如何有效优化非凸损失函数等问题。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/caa603be1dc2db8ef373a3d00b731652_15.png

卷积、池化等操作,可以理解为在网络结构中引入了具有特定物理或几何意义的函数变换(如局部平滑、降维)。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/caa603be1dc2db8ef373a3d00b731652_17.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/caa603be1dc2db8ef373a3d00b731652_19.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/caa603be1dc2db8ef373a3d00b731652_21.png


https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/caa603be1dc2db8ef373a3d00b731652_23.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/caa603be1dc2db8ef373a3d00b731652_25.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/caa603be1dc2db8ef373a3d00b731652_27.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/caa603be1dc2db8ef373a3d00b731652_29.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/caa603be1dc2db8ef373a3d00b731652_31.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/caa603be1dc2db8ef373a3d00b731652_33.png

课程总结 🏁

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/caa603be1dc2db8ef373a3d00b731652_35.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/caa603be1dc2db8ef373a3d00b731652_37.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/caa603be1dc2db8ef373a3d00b731652_39.png

本节课我们一起深入学习了数据拟合的核心内容。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/caa603be1dc2db8ef373a3d00b731652_41.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/caa603be1dc2db8ef373a3d00b731652_43.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/caa603be1dc2db8ef373a3d00b731652_45.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/caa603be1dc2db8ef373a3d00b731652_47.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/caa603be1dc2db8ef373a3d00b731652_49.png

我们首先回顾了函数拟合的三部曲方法论:选择函数空间、定义目标函数、优化求解。然后,我们分析了多项式插值的局限性,如病态问题和龙格现象,并介绍了性质更优的伯恩斯坦基函数。

接着,我们探讨了径向基函数(RBF)拟合方法,揭示了其通过基函数的平移与缩放来组合逼近目标函数的本质,并建立了RBF与单层神经网络之间的直接联系。

最后,我们从函数拟合的视角重新审视了神经网络,将其理解为一个通过大量参数定义复杂函数空间的工具,其训练过程就是在该空间中寻找最佳拟合函数。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/caa603be1dc2db8ef373a3d00b731652_51.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/caa603be1dc2db8ef373a3d00b731652_52.png

理解这些方法的共性与差异,掌握从“定义空间”到“优化求解”的完整思维链条,是灵活运用各种拟合技术解决实际问题的关键。在接下来的课程中,我们将把这些关于函数的理解推广到曲线与曲面的建模与处理中。

GAMES102-几何建模与处理—P3-参数曲线拟合—GAMES-Webinar—BV1NA411E7Yr_note

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7389f51b7bfb00ed9b7b624668d7606f_0.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7389f51b7bfb00ed9b7b624668d7606f_2.png

在本节课中,我们将要学习如何将函数拟合的概念从一元函数推广到多元函数,并最终聚焦于参数曲线拟合这一核心主题。我们将理解如何用数学方法描述和拟合空间中的曲线,并探讨参数化的重要性。

课程回顾与引入

上一节我们介绍了单变量函数的拟合问题。回顾前两次课程,我们主要讨论了定义域和值域都是实数的一元函数。理解这种函数形式是基础,因为高维函数可以看作是它的推广。

函数拟合主要涉及三个关键问题:

  1. 函数集合的选择:需要确定从哪个函数集合中寻找目标函数。这个集合需要有良好的结构(如线性结构)和强大的表达能力。
  2. 度量标准:需要定义一个损失函数来度量候选函数与数据之间的逼近程度。除了逼近误差,还可能加入对函数光滑性或系数大小的约束,即正则项。
  3. 求解方法:将拟合问题转化为优化问题求解。如果能量函数是系数的二次型,则变为解线性方程组;如果是复杂的非线性非凸问题,则需使用梯度下降等数值方法寻找局部最优解。

理解了这些,我们就可以将视野扩展到更一般的情况。

从一元到多元函数

本节中,我们来看看当函数的输入变量从一个变为多个时,情况有何变化。多元函数是从 R^n 映射到 R 的函数,例如 z = f(x, y)。我们可以将其可视化:xy 构成平面,f(x, y) 作为高度,形成三维空间中的一个曲面。

对于更高维度的输入(如 g = f(x, y, z)),我们无法直接可视化,但可以研究其数学性质,如偏导和梯度。在实际问题中,变量维度 n 可能非常大(如图像处理中的像素),这时直观理解变得困难,需要依靠数学方法。

多元函数的基函数构造

如何为多元函数定义基函数?最常用的方法是张量积

假设我们有两个一维基函数集合:关于 u{b1(u), b2(u), b3(u)} 和关于 v{b1(v), b2(v), b3(v)}。通过两两相乘,我们可以构造二元基函数:


bij(u, v) = bi(u) * bj(v)

其中 i, j = 1, 2, 3。这样就得到了9个二元基函数,它们的线性组合可以表示一个二元函数。通常,为了简便,两个方向会使用相同的基函数集合。

张量积的优缺点

  • 优点:只需定义好一维基函数,就能自动构造多维基函数。
  • 缺点:基函数数量随变量维度呈平方级增长。例如,100维输入需要约 100^2 = 10000 个基函数,这在计算上难以承受。这就是传统方法处理高维数据时面临的“维数灾难”。

神经网络的启示

神经网络巧妙地绕过了维数灾难问题。它使用统一的激活函数(如 Sigmoid 或 ReLU),通过权重和偏置的线性组合对输入进行仿射变换,再经过激活函数,形成新的基函数。一个简单的单隐层网络可以表示为:


# 伪代码示意:单隐层神经网络前向传播

hidden = sigma(W1 * input + b1)  # 仿射变换 + 激活函数

output = W2 * hidden + b2         # 线性组合输出

其中,sigma 是激活函数,W1, b1, W2, b2 是待学习的参数。隐层节点数 m 控制了模型的表达能力。m 太小会导致欠拟合,太大会导致过拟合,需要通过调参来平衡。深度神经网络则是多个这样的函数复合而成。

神经网络的本质就是用一种参数化的、表达能力强大的函数族来进行拟合,尤其擅长处理高维数据。

向量值函数与参数曲线

现在,我们进入本节课的核心:向量值函数。这类函数的输入是一个实数,输出是一个高维向量,即映射 R → R^m

可以将其理解为 m 个独立的单变量函数:


P(t) = ( x1(t), x2(t), ..., xm(t) )

每个分量 xi(t) 都是关于参数 t 的函数。

几何解释:参数曲线

向量值函数有清晰的几何意义。当 m=2 时,P(t) = (x(t), y(t)) 表示平面中的一条曲线。当 m=3 时,P(t) = (x(t), y(t), z(t)) 表示空间中的一条曲线。参数 t 可以理解为时间,曲线就是质点随时间运动的轨迹。

关键概念:虽然曲线上的点位于高维空间(如三维),但曲线本身的本质维度是1,因为它是由单个参数 t 描述的。我们所在的高维空间称为嵌入空间。参数曲线强大的地方在于,它可以描述非常复杂的、甚至非函数型的曲线(例如一个闭合圆)。

类似地,参数曲面是由两个参数 (u, v) 描述的曲面,其本质维度是2,例如球面。更一般地,一个从 R^n 映射到 R^m 的参数化表示,描述了 n 维流形在 m 维空间中的嵌入。

参数曲线拟合问题

理解了参数曲线,我们现在来解决如何用参数曲线拟合给定的一系列有序点 {P_i = (x_i, y_i)}

问题可以表述为:寻找一个参数曲线 P(t) = (x(t), y(t)) 和一组参数值 {t_i},使得曲线在 t_i 处的值 P(t_i) 尽可能接近数据点 P_i

损失函数可以定义为所有数据点误差的平方和:


Loss = Σ_i || P(t_i) - P_i ||^2

其中 ||.|| 表示向量的模长。x(t)y(t) 可以分别用我们之前学过的基函数组合来表示,例如多项式基函数。

关键挑战:参数化

上述问题中,数据点 P_i 是已知的,但对应的参数值 t_i 是未知的。为每个数据点分配一个参数值 t_i 的过程,就叫做参数化。参数化本质上是将高维数据点降维到一维参数域,且要求这种映射能保留数据的结构信息。

以下是几种常见的参数化方法:

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7389f51b7bfb00ed9b7b624668d7606f_4.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7389f51b7bfb00ed9b7b624668d7606f_6.png

  • 均匀参数化:最简单直接。假设参数 t[0, 1] 区间均匀分布,t_i = i / (n-1)。这种方法忽略了点与点之间的实际距离。
  • 弦长参数化:更符合几何直觉。根据相邻点之间的弦长(欧氏距离)比例来分配参数。
    
    总弦长 L = Σ_i || P_{i+1} - P_i ||
    
    第k点的参数 t_k = (Σ_{i=0}^{k-1} || P_{i+1} - P_i ||) / L
    
    
  • 中心参数化:一种更复杂的参数化方法,旨在产生更光滑的拟合曲线。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7389f51b7bfb00ed9b7b624668d7606f_8.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7389f51b7bfb00ed9b7b624668d7606f_10.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7389f51b7bfb00ed9b7b624668d7606f_12.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7389f51b7bfb00ed9b7b624668d7606f_14.png

参数化的重要性:不同的参数化方法会导致完全不同的拟合结果。均匀参数化在点分布不均匀时容易产生扭曲;弦长参数化通常能产生更自然的曲线;中心参数化可能在某些情况下得到最光滑的结果。选择好的参数化是曲线拟合成功的关键。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7389f51b7bfb00ed9b7b624668d7606f_16.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7389f51b7bfb00ed9b7b624668d7606f_18.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7389f51b7bfb00ed9b7b624668d7606f_20.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7389f51b7bfb00ed9b7b624668d7606f_22.png

参数化的广泛应用

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7389f51b7bfb00ed9b7b624668d7606f_24.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7389f51b7bfb00ed9b7b624668d7606f_26.png

参数化不仅是曲线拟合的核心步骤,在几何处理中还有更广泛的应用:

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7389f51b7bfb00ed9b7b624668d7606f_28.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7389f51b7bfb00ed9b7b624668d7606f_30.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7389f51b7bfb00ed9b7b624668d7606f_32.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7389f51b7bfb00ed9b7b624668d7606f_34.png

  • 曲面参数化:将三维曲面映射到二维平面,同时尽可能保持几何属性(如角度、面积)。这对于纹理映射至关重要。
  • 流形学习:对于高维数据,寻找其低维本质参数(流形结构),类似于自编码器(Autoencoder)的目标。如果降维后的维度低于数据的本质维度,信息将无法无损恢复。
  • 几何设计:在工业设计中(如汽车、飞机叶片),外形通常由艺术家绘制草图,然后需要转化为精确的数学参数曲面进行制造。历史上,设计师使用物理样条(富有弹性的木条或金属条)来绘制光滑曲线,而数学上的样条函数(特别是三次样条)正是由此启发而来,它用分段多项式来拼接出一条整体光滑的曲线。这将是后续课程的重要内容。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7389f51b7bfb00ed9b7b624668d7606f_36.png

课程总结

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7389f51b7bfb00ed9b7b624668d7606f_38.png

本节课中,我们一起学习了参数曲线拟合的核心思想。我们从一元函数拟合出发,推广到多元函数和向量值函数,并理解了参数曲线的几何意义。我们明确了拟合参数曲线的关键步骤:参数化函数拟合,并介绍了均匀、弦长等参数化方法。最后,我们看到了参数化在曲面纹理映射、流形学习以及几何设计中的重要作用。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7389f51b7bfb00ed9b7b624668d7606f_40.png

通过本课,希望大家能建立起一个统一的观点:无论是简单的函数拟合,还是复杂的神经网络、曲线曲面建模,其数学本质都是在某个函数空间中寻找对目标数据的最佳逼近。理解了这一点,就能更好地掌握后续更深入的几何建模与处理方法。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7389f51b7bfb00ed9b7b624668d7606f_42.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7389f51b7bfb00ed9b7b624668d7606f_44.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7389f51b7bfb00ed9b7b624668d7606f_45.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/7389f51b7bfb00ed9b7b624668d7606f_46.png


附:作业三简介
请实现参数曲线拟合。给定一系列有序的二维点,分别使用均匀、弦长参数化方法为点分配参数,然后利用多项式基函数分别拟合 x(t)y(t),最终得到拟合曲线。比较不同参数化方法对拟合结果的影响。

GAMES102-几何建模与处理—P4-三次样条函数—GAMES-Webinar—BV1NA411E7Yr_note

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/0d8a7a55b67596f71c6a639ebbb7f541_0.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/0d8a7a55b67596f71c6a639ebbb7f541_2.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/0d8a7a55b67596f71c6a639ebbb7f541_4.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/0d8a7a55b67596f71c6a639ebbb7f541_5.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/0d8a7a55b67596f71c6a639ebbb7f541_7.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/0d8a7a55b67596f71c6a639ebbb7f541_9.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/0d8a7a55b67596f71c6a639ebbb7f541_11.png

在本节课中,我们将学习三次样条函数。这是一种在几何设计和工业建模中至关重要的数学工具,用于通过一系列控制点生成光滑的曲线。我们将从三次样条的历史背景和力学原理讲起,逐步推导其数学表达,并探讨参数连续性与几何连续性的区别。


https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/0d8a7a55b67596f71c6a639ebbb7f541_13.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/0d8a7a55b67596f71c6a639ebbb7f541_15.png

作业情况回顾 📊

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/0d8a7a55b67596f71c6a639ebbb7f541_17.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/0d8a7a55b67596f71c6a639ebbb7f541_19.png

上一节我们介绍了参数化方法对曲线拟合的影响。本节开始前,先回顾一下作业三的提交情况。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/0d8a7a55b67596f71c6a639ebbb7f541_21.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/0d8a7a55b67596f71c6a639ebbb7f541_23.png

作业三总体提交了41份,内容相对简单,核心是实现有序点列在不同参数化方法下的插值。总体完成效果良好。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/0d8a7a55b67596f71c6a639ebbb7f541_25.png

以下是几位同学的优秀作业展示:

  • 同学 lxt:利用游戏引擎或类似工具制作了交互界面,背后算法由C++实现。可以实时拖动控制点,并生成参数曲线,支持差值执行和B样条等不同方法,不同颜色代表不同参数化方法,结果直观。
  • 同学 常清俊:在报告中清晰展示了相同点列在不同参数化(弦长、中心、均匀、Foley)下的拟合结果。当点分布均匀时,各种方法结果相似;当点分布不均匀时,结果差异显著,例如均匀参数化可能导致曲线出现自交。
  • 另一位同学:使用高斯基函数和RBF神经网络进行拟合。报告展示了对于低维(如一维、二维)数据,可以直观判断拟合好坏;而对于高维数据,则只能通过损失函数值来判断。

部分优秀作业和报告已挂在课程主页,可供参考。


三次样条的起源:从物理样条到数学函数 📐

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/0d8a7a55b67596f71c6a639ebbb7f541_27.png

上一节我们开启了几何设计的主题。在计算机出现之前,设计师使用一种称为“样条”的物理工具来绘制自由曲线。

设计师会先确定一些关键点(形值点),然后用沉重的“压铁”固定这些点。接着,他们将一根富有弹性的软木条(即样条)绕过这些压铁,让其自然弯曲,从而描出一条光滑的曲线。

这就引出了一个核心问题:这条由物理样条自然弯曲形成的曲线,其背后的数学表达式是什么?这正是三次样条函数要解决的问题。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/0d8a7a55b67596f71c6a639ebbb7f541_29.png

从力学角度分析,软木样条可视为一根弹性梁。在小挠度(弯曲角度不太大)的假设下,通过欧拉-伯努利梁方程进行推导,可以得出结论:在两个压铁(形值点)之间,曲线的数学表达式是一个三次多项式。整个样条曲线因此是分段的三次多项式。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/0d8a7a55b67596f71c6a639ebbb7f541_31.png

选择三次多项式是因为:一次函数是直线,表达能力不足;二次函数是抛物线,没有拐点;四次及以上多项式计算不稳定且拐点过多;三次多项式恰好有一个拐点,既能表达丰富形状,又相对稳定。


三次样条函数的数学推导 🔢

既然已知曲线是分段三次函数,那么如何推导其具体方程呢?核心思路是利用已知的形值点和曲线段之间的连续性约束来建立方程组。

假设有 n+1 个形值点,则中间有 n 段曲线。每一段三次多项式有4个未知系数,因此总共有 4n 个未知数。

我们需要建立 4n 个方程来求解:

  1. 插值条件:曲线必须经过每一个形值点。这提供了 n+1 个方程。
  2. 内部连续性条件:为了保证曲线整体光滑,在内部 n-1 个拼接点处,要求相邻两段曲线具有相同的函数值(C⁰连续)、一阶导数值(C¹连续)和二阶导数值(C²连续)。这提供了 3(n-1) 个方程。

目前总方程数为 (n+1) + 3(n-1) = 4n - 2,比未知数 4n 少了2个。因此,需要额外指定两个边界条件,通常在曲线的两个端点处给出。常见的边界条件有:

  • 自然边界:指定端点处的二阶导数为零。
  • 固定切线(夹持)边界:指定端点处的一阶导数(切线方向)。

添加两个边界条件后,我们就得到了一个 4n 阶的线性方程组,可以唯一确定所有系数。

在实际推导中,常引入中间变量简化计算。例如,设每个形值点处的二阶导数值为 m_i。由于每一段的三次函数的二阶导数是线性的,可以表示为两端点二阶导数的线性插值:


y_i''(x) = m_i * (x_{i+1} - x) / h_i + m_{i+1} * (x - x_i) / h_i

其中 h_i = x_{i+1} - x_i。对此式积分两次,并结合插值条件与连续性条件,最终可以得到一个以 m_i 为未知数的线性方程组。因其系数矩阵是三对角且对角占优的,可以使用高效的追赶法求解。这个方程组在样条理论中称为“三弯矩方程”。

类似地,也可以以一阶导数作为未知数推导,得到“三转角方程”。求解思路一致。


从函数到曲线:参数样条 🧵

上一节我们介绍了函数与曲线的联系。三次样条函数是 y = f(x) 的形式,存在多值性问题(一个x对应多个y),无法描述任意曲线。

将其推广到曲线非常直接:将曲线视为一个向量值函数 C(t) = (x(t), y(t), z(t))。对三个坐标分量 x, y, z 分别独立地应用上面推导的三次样条函数方法(基于相同的参数 t 序列),然后将结果组合起来,就得到了三次参数样条曲线

参数 t 的序列(参数化)可以通过弦长参数化、中心参数化等方法获得,这在之前的作业中已经实践过。


连续性的深入:参数连续 vs 几何连续 🔄

我们之前用 C0, C1, C2... 来定义连续性,这称为参数连续性。它要求曲线在拼接点处具有直到n阶的相同的参数导数

然而,参数连续性依赖于具体的参数化方式。一个经典的例子是:将一条直线段用两种不同的参数化方式表示成两段,在拼接点处计算参数导数,结果可能不相等,从而被判定为 C0 连续而非 C1 连续。但这显然与“直线是无限光滑的”几何直觉相悖。

问题在于,参数连续性受参数选择的影响,不能完全反映曲线内在的几何光滑性。

因此,引入了几何连续性的概念。其定义是:如果存在一个参数变换,使得两条曲线在拼接点处达到 Cn 参数连续,则称这两条曲线是 Gn 几何连续的。

几何连续性是曲线本身的内在属性,不依赖于参数化:

  • G0:与 C0 相同,即点连续(端点重合)。
  • G1:切线连续。要求两段曲线在拼接点处具有相同的切线方向,但切线向量的长度可以不同。
  • G2:曲率连续。要求两段曲线在拼接点处具有相同的曲率。曲率是几何不变量。

Gn 的条件比 Cn 更宽松,为设计师提供了更大的灵活性。在许多图形设计软件(如 PowerPoint、Adobe Illustrator)的曲线编辑工具中,调节顶点类型(平滑点、角点)本质上就是在控制曲线的几何连续性(G1 或 G0)。


贝塞尔曲线简介:更直观的设计工具 ✨

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/0d8a7a55b67596f71c6a639ebbb7f541_33.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/0d8a7a55b67596f71c6a639ebbb7f541_35.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/0d8a7a55b67596f71c6a639ebbb7f541_37.png

最后,我们为下节课内容做一个铺垫。之前用幂基 {1, t, t^2, t^3} 表示多项式曲线时,其系数(控制点)与曲线形状的关联不直观,不利于设计。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/0d8a7a55b67596f71c6a639ebbb7f541_39.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/0d8a7a55b67596f71c6a639ebbb7f541_41.png

工程师皮埃尔·贝塞尔发现,使用一组称为伯恩斯坦基的函数作为新的基,来表示同样的多项式空间时,其系数(称为控制顶点)具有极佳的几何意义:

  • 曲线的起点和终点分别与第一个和最后一个控制顶点重合。
  • 曲线的形状被“拉向”中间的控制顶点,整体趋势与控制多边形(依次连接控制顶点形成的折线)相似。

这种用伯恩斯坦基和控制顶点定义的曲线,就是著名的贝塞尔曲线。它使得设计师可以通过直观地拖动控制顶点来预测和调整曲线形状,极大地便利了几何设计。我们将在下节课详细探讨它的性质。


本节课总结 📝

本节课我们一起学习了:

  1. 三次样条函数的起源:从物理样条的力学原理推导出其分段三次多项式的数学本质。
  2. 三次样条的数学推导:通过插值条件、内部连续性条件和边界条件建立方程组,并介绍了以二阶导数为未知数的“三弯矩方程”求解方法。
  3. 参数样条曲线:将三次样条函数应用于各个坐标分量,以生成参数曲线。
  4. 两种连续性:理解了依赖于参数化的参数连续性与反映曲线内在光滑性的几何连续性之间的区别与联系。
  5. 贝塞尔曲线引介:了解了使用伯恩斯坦基函数能带来更直观的几何控制,为后续学习打下基础。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/0d8a7a55b67596f71c6a639ebbb7f541_43.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/0d8a7a55b67596f71c6a639ebbb7f541_45.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/0d8a7a55b67596f71c6a639ebbb7f541_46.png

通过本课,你已掌握了二维矢量图形编辑(如软件中的曲线工具)背后的核心数学原理——三次样条函数。

GAMES102-几何建模与处理—P5-Bezier曲线-B样条曲线—GAMES-Webinar—BV1NA411E7Yr_note

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e0be837432e0c1a1eaac9ad8f19c686e_0.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e0be837432e0c1a1eaac9ad8f19c686e_2.png

在本节课中,我们将要学习计算机图形学中两种核心的曲线表示方法:Bezier曲线和B样条曲线。我们将从函数拟合的基本概念出发,探讨它们如何从数学形式转化为直观的几何设计工具,并重点分析它们各自的性质、优势以及在实际设计中的应用。

概述:从函数拟合到几何设计

上一节我们介绍了函数拟合的基本概念。在实际造型中,有一个重要概念叫“逆向工程”,即通过采集产品表面的点,再通过拟合方法将其外形重建出来。这涉及到曲线拟合,即给定一系列点,寻找一个“好”的函数来逼近它们。

这个“好”的函数通常从一个由“基函数”定义的函数空间(或集合)中寻找。例如,二次函数空间的形式为 f(t) = a*t² + b*t + c,其中a, b, c是待定系数。对于参数曲线,形式为 P(t) = (x(t), y(t)),可以将其写成向量形式,基函数前的系数就成了空间中控制曲线形状的“顶点”。

然而,如果基函数(如幂函数 1, t, t²)选得不好,曲线形状与控制顶点之间的关系会非常不直观。用户调整一个顶点,曲线可能产生难以预料的剧烈变化,这不利于交互式设计。因此,我们需要寻找具有更好几何意义的基函数。

Bezier曲线:直观的几何设计工具 ✏️

上一节我们提到了函数拟合,本节中我们来看看一种革命性的设计工具——Bezier曲线。它的核心在于使用了一组具有优良几何性质的基函数:Bernstein基函数。

Bernstein基函数

Bernstein基函数在数学上已存在数百年,其形式如下:
B_i^n(t) = C(n, i) * t^i * (1-t)^(n-i), 其中 t ∈ [0,1], i = 0, 1, ..., n
这里 C(n, i) 是组合数。n次多项式有n+1个Bernstein基函数,它们构成了不高于n次的多项式空间的一组基,与幂基等价且可以相互转换。

以下是低阶Bernstein基函数的图像示例(此处为描述,实际教程应配图):

  • 0阶: 常数函数1。
  • 1阶: B₀¹(t)=1-t, B₁¹(t)=t,是两个线性函数。
  • 2阶: 三个二次函数,形状类似抛物线。
  • 3阶: 四个三次函数,在[0,1]区间内平滑分布。

这些基函数具有两个关键性质:

  1. 正性: 对于 t ∈ [0,1],所有 B_i^n(t) ≥ 0
  2. 权性(单位分解): 对于任意 t,所有基函数值之和为1,即 Σ B_i^n(t) = 1

Bezier曲线的定义与性质

基于Bernstein基函数,我们定义Bezier曲线。给定n+1个控制顶点 P₀, P₁, ..., P_n,n次Bezier曲线为:
C(t) = Σ B_i^n(t) * P_i, t ∈ [0,1]

控制顶点顺序连接形成的多边形称为控制多边形。Bezier曲线具有以下重要性质,这些性质使其非常适合设计:

  • 端点插值: 曲线经过第一个和最后一个控制顶点,即 C(0)=P₀, C(1)=P_n
  • 凸包性: 由于基函数的正性和权性,曲线上任一点都是控制顶点的凸组合,因此整条曲线位于控制多边形的凸包之内。
  • 端点切向: 曲线在起点处的切向量方向与第一条边 (P₁-P₀) 一致,在终点处的切向量方向与最后一条边 (P_n-P_{n-1}) 一致。对于三次曲线,切向量长度是边长的3倍。
  • 几何不变性: 曲线的形状仅取决于控制顶点的相对位置,与坐标系选择无关。
  • 变差缩减性: 平面Bezier曲线与任意直线的交点个数不多于其控制多边形与该直线的交点个数。

de Casteljau算法:高效的几何求值方法

为了高效、稳定地计算Bezier曲线上任意参数 t 对应的点,我们使用de Casteljau算法。这是一个基于线性插值的递归算法:

算法描述:
给定控制顶点 P_i^0 = P_i (i=0,…,n) 和参数值 t
对于 r = 1 to n:
对于 i = 0 to n-r:
P_i^r = (1-t) * P_i^{r-1} + t * P_{i+1}^{r-1}
最终得到的 P_0^n 即为曲线上参数 t 对应的点 C(t)

这个算法的几何意义非常直观:它通过不断对控制多边形的边进行线性插值和细分,最终收敛到曲线上的点。不仅如此,该算法还将原曲线在 t 处分割成两段子Bezier曲线,并同时给出了这两段子曲线的控制顶点。这为曲线的分割、离散化和求交等操作提供了基础。

Bezier曲线的拼接与样条

单段Bezier曲线通过增加次数(提高阶数)来增加控制顶点,从而描述更复杂的形状,但高次曲线可能产生不必要的震荡,且局部修改会影响整体。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e0be837432e0c1a1eaac9ad8f19c686e_4.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e0be837432e0c1a1eaac9ad8f19c686e_6.png

为了构造复杂曲线,我们通常采用分段低次Bezier曲线进行拼接,形成Bezier样条。关键问题在于如何保证拼接处的连续性。

以下是保证连续性条件的几何解释(以三次Bezier曲线段 [P0,P1,P2,P3][Q0,Q1,Q2,Q3]P3=Q0 处拼接为例):

  • C⁰/G⁰连续(位置连续): 自然满足,只需 P3 = Q0
  • G¹连续(切向连续): 要求 P2, P3(Q0), Q1 三点共线。即切线方向相同,但长度可以不同。
  • C¹连续(参数连续): 在G¹连续的基础上,进一步要求 |P3 - P2| = |Q1 - Q0|。即切线方向相同且长度相等。
  • C²连续(曲率连续): 条件更为复杂,涉及到五个控制顶点 (P1, P2, P3, Q1, Q2) 的关系,要求二阶导数相等。

一种实用的构造C¹连续三次Bezier插值样条的方法是:对于给定的数据点 D_i,在每两个点之间构造一段三次Bezier曲线。中间的两个控制点可以这样确定:在 D_i 处,沿 (D_{i+1} - D_{i-1}) 的方向,在两侧各取 |D_{i+1} - D_{i-1}| / 6 的距离放置控制点。这种方法具有局部性,修改一个数据点只影响相邻的曲线段。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e0be837432e0c1a1eaac9ad8f19c686e_8.png

B样条曲线:兼具局部性与灵活性的强大工具 🔧

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e0be837432e0c1a1eaac9ad8f19c686e_10.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e0be837432e0c1a1eaac9ad8f19c686e_12.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e0be837432e0c1a1eaac9ad8f19c686e_13.png

上一节我们学习了Bezier曲线,它虽然直观,但具有全局性——修改任一控制顶点,整条曲线都会受到影响(尽管影响程度随距离减小)。本节中我们来看看B样条曲线,它通过使用具有局部支撑的基函数,完美解决了这个问题。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e0be837432e0c1a1eaac9ad8f19c686e_15.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e0be837432e0c1a1eaac9ad8f19c686e_17.png

从全局性到局部性的需求

Bezier曲线的全局性源于其Bernstein基函数在整個定义域 [0,1] 内都不恒为零。在设计中,我们常常希望修改曲线的一部分时,远离该部分形状能保持不变,即需要局部可控性

B样条(Basis Spline)曲线正是为此而生。它的核心思想是:构造一组只在部分参数区间非零的基函数(即具有紧支撑),使得每个控制顶点只影响曲线的一部分。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e0be837432e0c1a1eaac9ad8f19c686e_19.png

B样条基函数的定义

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e0be837432e0c1a1eaac9ad8f19c686e_21.png

B样条基函数由一个节点向量 T = [t₀, t₁, ..., t_{m}] 定义,其中 t_i 是单调非减的序列。对于 p 次(或 p 阶,阶数=次数+1)B样条,第 i 个基函数 N_{i,p}(t) 通常由著名的Cox-de Boor递归公式定义:

  1. 零次(p=0)基函数:
    N_{i,0}(t) = { 1, 如果 t_i ≤ t < t_{i+1}; 0, 其他 }

  2. 高次(p>0)基函数:
    N_{i,p}(t) = (t - t_i)/(t_{i+p} - t_i) * N_{i,p-1}(t) + (t_{i+p+1} - t)/(t_{i+p+1} - t_{i+1}) * N_{i+1,p-1}(t)
    规定 0/0 = 0

这个递归定义表明,高次的B样条基函数是由两个低一阶的相邻基函数线性组合而成,从而继承了低阶基函数的性质并提高了光滑性。

B样条曲线的定义与重要性质

给定 n+1 个控制顶点 P₀, P₁, ..., P_n,次数 p,以及节点向量 T = [t₀, t₁, ..., t_{n+p+1}],定义的 p 次B样条曲线为:
C(t) = Σ N_{i,p}(t) * P_i, 其中 t_p ≤ t ≤ t_{n+1}

B样条曲线拥有比Bezier曲线更丰富和灵活的性质:

  • 局部支撑性: 基函数 N_{i,p}(t) 仅在区间 [t_i, t_{i+p+1}) 上非零。因此,控制顶点 P_i 只影响曲线在 [t_i, t_{i+p+1}) 区间内的部分。这是实现局部修改的数学基础。
  • 凸包性: 曲线段 C(t), t ∈ [t_i, t_{i+1}] 位于定义该段的 p+1 个控制顶点 (P_{i-p}, ..., P_i) 的凸包内。整个曲线位于所有控制顶点的凸包内。
  • 连续性: 在节点区间内部,曲线是无限光滑的 C^∞ 多项式。在节点 t_i 处,曲线至少是 C^{p-m_i} 连续的,其中 m_i 是该节点的重数(即在节点向量中重复出现的次数)。通过调整节点重数,可以精确控制曲线的连续性
  • 变差缩减性: 同Bezier曲线。
  • 仿射不变性: 同Bezier曲线。
  • 强凸包性: 比Bezier曲线的凸包性更强,曲线段位于更小的局部凸包内。
  • 灵活性: 通过插入节点或调整节点向量,可以在不改变曲线形状的前提下修改其表达,或进行局部细化。

节点向量与重节点的作用

节点向量 T 是B样条的灵魂。它分为几种类型:

  • 均匀B样条: 节点等距分布,如 [0,1,2,3,4,5]
  • 准均匀B样条: 两端节点具有 p+1 的重度,内部节点均匀分布,如 [0,0,0,1,2,3,4,4,4](对于p=2)。这是最常用的形式,它使曲线插值于首末控制顶点。
  • 非均匀B样条: 节点任意非减分布,提供了最大的灵活性。

重节点的关键作用:

  1. 降低连续性:p 次B样条中,一个 k 重节点处曲线的连续性降至 C^{p-k}。当 k = p 时,曲线在该处仅为 C⁰ 连续(位置连续);当 k = p+1 时,曲线在该处甚至断开(或理解为插值于该控制顶点)。
  2. 插值控制顶点: 使一个控制顶点对应的节点区间长度为零,可以让曲线插值于该控制顶点。通常通过使首末节点为 p+1 重来保证曲线经过首末控制点。
  3. 生成尖锐特征: 在设计中,可以通过插入重节点在曲线上制造尖角直线段

B样条与Bezier的关系

Bezier曲线是B样条曲线的一个特例。一个 n 次的Bezier曲线,等价于一个 n 次的、节点向量为 [0,0,...,0,1,1,...,1](前后各 n+1 个重复节点)的B样条曲线。此时,B样条基函数退化为Bernstein基函数。

总结与展望 🌟

本节课中我们一起学习了计算机图形学中两大核心的曲线模型。

我们首先回顾了函数拟合的基本问题,并指出了用于设计的曲线需要直观的几何意义。由此,我们引入了Bezier曲线,它利用Bernstein基函数将控制顶点以加权平均的方式组合成光滑曲线,具有端点插值、凸包性等优良性质,并通过de Casteljau算法实现了高效的几何求值与分割。我们还探讨了如何将多段Bezier曲线拼接成样条以满足复杂造型需求。

接着,为了克服Bezier曲线全局修改的缺点,我们深入探讨了B样条曲线。B样条通过定义在节点向量上的、具有局部支撑性的基函数,实现了曲线的局部可控性。我们学习了Cox-de Boor递归公式,并详细分析了B样条曲线的性质,特别是节点重数对曲线连续性的精确控制这一强大特性。B样条统一并推广了Bezier曲线,成为工业标准(如NURBS)的基础。

无论是Bezier还是B样条,其核心思想都是:用一组易于控制和理解的“基函数”去组合用户提供的“控制顶点”,从而生成期望的光滑曲线。 基函数决定了曲线的数学性质(如连续性、局部性),而控制顶点提供了直观的几何编辑手段。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e0be837432e0c1a1eaac9ad8f19c686e_23.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e0be837432e0c1a1eaac9ad8f19c686e_25.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e0be837432e0c1a1eaac9ad8f19c686e_27.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/e0be837432e0c1a1eaac9ad8f19c686e_28.png

下节课,我们将探讨有理曲线(NURBS),它通过引入“权因子”的概念,使得曲线能够精确表示圆锥曲线(如圆、椭圆),从而将Bezier和B样条的能力扩展到更广阔的几何领域,最终形成工业界通用的NURBS标准。此后,我们将把曲线理论推广到曲面,并逐步进入离散几何处理的世界。

GAMES102-几何建模与处理—P6-NURBS曲线-细分曲线-隐式曲线-NURBS曲面—GAMES-Webinar—BV1NA411E7Yr_note

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/8228633b83ec1193dbb1520218030ed4_0.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/8228633b83ec1193dbb1520218030ed4_2.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/8228633b83ec1193dbb1520218030ed4_4.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/8228633b83ec1193dbb1520218030ed4_6.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/8228633b83ec1193dbb1520218030ed4_8.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/8228633b83ec1193dbb1520218030ed4_10.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/8228633b83ec1193dbb1520218030ed4_12.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/8228633b83ec1193dbb1520218030ed4_14.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/8228633b83ec1193dbb1520218030ed4_16.png

在本节课中,我们将学习几何建模中几种重要的曲线与曲面表示方法。我们将探讨NURBS曲线、细分曲线、隐式曲线以及NURBS曲面的核心概念、动机和应用。这些内容是现代计算机辅助设计(CAD)和计算机图形学的基础。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/8228633b83ec1193dbb1520218030ed4_18.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/8228633b83ec1193dbb1520218030ed4_20.png


https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/8228633b83ec1193dbb1520218030ed4_22.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/8228633b83ec1193dbb1520218030ed4_24.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/8228633b83ec1193dbb1520218030ed4_26.png

作业回顾与优秀案例展示 📝

上一节我们介绍了样条曲线的构造方法。本节开始前,我们先回顾一下上次的作业。

本次作业涉及求解方程组,特别是推导三转角方程,具有一定难度。总体提交率接近30%,但提交的同学完成得相当出色。

以下是部分优秀作业案例:

  • 案例一: 该作业实现了一个矢量曲线编辑与设计工具。用户可以调节曲线节点及其切线,可以全局求解三次样条以获得处处C²连续的曲线,也可以调节中间节点以获得G¹连续性,甚至产生尖点(C⁰连续)。其交互设计已达到实用程度。
  • 案例二: 该作业界面不同,但同样支持实时叠加、拖动顶点,并可以增加输入点。它也能够改变切线的连续性,设计尖点,功能完善。
  • 案例三: 该作业展示了灵活的设计能力,例如将曲线调整为兔子耳朵的尖点(C⁰连续),或将部分调整为G¹连续以保持圆滑。这些工具为艺术家和设计师提供了强大的灵活性。

这些优秀作业报告将与同学们分享。


NURBS曲线:从Bézier到有理形式 🔄

回顾前五节课,我们从函数拟合到Bézier曲线,本质上都是在为每个控制顶点叠加一个权函数来构造曲线。Bézier曲线使用的Bernstein基函数在定义域[0,1]上是全局非零的,因此修改一个顶点会影响整条曲线,缺乏局部性。

为了获得局部可控性,人们引入了样条曲线,其基函数只在局部节点区间非零。这样,设计师可以分段设计曲线,互不干扰。

然而,Bézier曲线本质上是多项式,无法精确表示圆、椭圆等圆锥曲线,而这在工程中至关重要。为了解决这个问题,人们引入了有理Bézier曲线

其核心思想是:在更高维的空间(投影空间)中定义一条Bézier曲线,然后将其投影回原空间。投影过程引入了除法,从而得到了有理形式。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/8228633b83ec1193dbb1520218030ed4_28.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/8228633b83ec1193dbb1520218030ed4_30.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/8228633b83ec1193dbb1520218030ed4_32.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/8228633b83ec1193dbb1520218030ed4_34.png

有理Bézier曲线的公式为:
[
C(t) = \frac{\sum_{i=0}^{n} w_i P_i B_{i,n}(t)}{\sum_{i=0}^{n} w_i B_{i,n}(t)}
]
其中,( w_i ) 是权因子,( P_i ) 是控制顶点,( B_{i,n}(t) ) 是n次Bernstein基函数。

当所有权因子 ( w_i = 1 ) 时,公式退化为标准的Bézier曲线。权因子 ( w_i ) 可以影响曲线的形状:权值越大,曲线越靠近对应的控制顶点。

引入有理形式后,曲线可以精确表示圆锥曲线。例如,要表示1/4圆,只需设置两端点权值为1,中间权值为 ( \sqrt{2}/2 ) 即可。

NURBSNon-Uniform Rational B-Spline 的缩写,即非均匀有理B样条。它综合了以上概念:

  • Non-Uniform (非均匀):指定义基函数的节点向量可以是非均匀分布的,这提供了更一般的控制能力(如产生尖点)。
  • Rational (有理):指采用了上述有理形式,可以精确表示圆锥曲线。
  • B-Spline (B样条):指其基础是B样条基函数。

因此,NURBS曲线的形状由三个因素共同决定:控制顶点节点向量权因子。它继承了B样条的优良性质(如凸包性、变差缩减性),同时表达范围更广,已成为CAD领域的工业标准数据格式。


细分曲线:通过迭代加细构造光滑曲线 ✂️

细分曲线提供了一种不同于基函数组合的曲线构造方法。其灵感来源于Bézier曲线的de Casteljau作图法,可以看作对一个初始多边形不断“割角”或“补角”以使其光滑的过程。

细分方法的核心在于两个规则:

  1. 拓扑规则 (Topological Rule):如何增加新的顶点(即在哪里加)。
  2. 几何规则 (Geometric Rule):如何计算新顶点的位置(即加到哪)。

细分方法主要分为逼近型和插值型。

1. Chaikin割角法 (逼近型):
这是最早的细分方法之一。对于每条边,取距离端点1/4和3/4处的两个点作为新顶点,连接这些新顶点形成新的、更密的多边形。不断重复此过程,极限曲线是光滑的。

2. 四点插值细分法 (插值型):
这种方法保持所有旧顶点位置不变,只在旧边之间插入新顶点。新顶点的位置由相邻的四个旧顶点加权平均得到。一个著名的公式是:
[
P_{new} = \frac{9}{16}(P_i + P_{i+1}) - \frac{1}{16}(P_{i-1} + P_{i+2})
]
其中,( P_{i-1}, P_i, P_{i+1}, P_{i+2} ) 是四个相邻旧顶点。权值中的参数需要在一定范围内(如 ( \alpha = 1/16 ))才能保证极限曲线光滑,否则可能产生分形曲线。

细分方法的收敛性和光滑性分析通常通过将其过程表示为矩阵乘法,然后分析该细分矩阵的特征值来完成。特征值的性质决定了极限曲线的行为。

作业五将让同学们实现Chaikin细分和四点插值细分,以体验其简单而强大的构造能力。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/8228633b83ec1193dbb1520218030ed4_36.png


https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/8228633b83ec1193dbb1520218030ed4_38.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/8228633b83ec1193dbb1520218030ed4_40.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/8228633b83ec1193dbb1520218030ed4_42.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/8228633b83ec1193dbb1520218030ed4_44.png

隐式曲线:由方程定义的曲线 🎯

之前学习的曲线都是参数曲线,即点的坐标由一个参数t的函数明确给出:( C(t) = (x(t), y(t)) )。

隐式曲线则由一个方程定义:( F(x, y) = 0 )。所有满足该方程的点(x, y)构成了这条曲线。例如,直线 ( ax+by+c=0 ),圆 ( x2+y2-R^2=0 )。

隐式曲线可以看作二元函数 ( z = F(x, y) ) 的图形与平面 ( z=0 ) 的交线。它非常适合表示封闭曲线和处理无序点集。

如何绘制隐式曲线?—— Marching Cubes算法思想(二维即Marching Squares):
对于复杂的 ( F(x, y)=0 ),很难求出显式表达式。Marching Squares算法提供了一种数值化绘制方法:

  1. 用网格覆盖定义域,计算每个网格顶点处的函数值 ( F(x, y) )。
  2. 根据每个网格单元四个角点函数值的正负号(如+或-),判断等值线 ( F=0 ) 是否穿过该单元,以及穿过的可能方式。
  3. 根据预设的几种情况模板,在单元内用直线段近似连接等值点。
  4. 遍历所有网格单元,将线段连接起来,就得到了隐式曲线的多边形近似。

如何从点集重建隐式曲线?
给定一个无序点集(假设来自一条封闭曲线),我们可以拟合一个隐式函数 ( F(x, y) ) 使得:

  • 在点集上,( F(x_i, y_i) = 0 )。
  • 在点集内部,( F(x, y) < 0 );在外部,( F(x, y) > 0 )。
    这可以通过为点集及内外附加点赋予函数值(如0, +1, -1),然后利用前几节课的函数拟合/插值技术(如RBF径向基函数)来求解一个满足这些约束的二元函数 ( F )。最后,提取 ( F=0 ) 的等值线即为重建曲线。著名的“泊松重建”方法就是此思想在三维的推广。

NURBS曲面:从曲线到曲面的张量积推广 🧩

理解了曲线之后,曲面就变得直观。NURBS曲面是NURBS曲线在二维参数域上的直接推广,采用张量积(Tensor Product) 形式构造。

NURBS曲面公式为:
[
S(u, v) = \frac{\sum_{i=0}{m}\sum_{j=0}{n} w_{i,j} P_{i,j} N_{i,p}(u) N_{j,q}(v)}{\sum_{i=0}{m}\sum_{j=0}{n} w_{i,j} N_{i,p}(u) N_{j,q}(v)}
]
其中:

  • ( P_{i,j} ) 是控制顶点网格。
  • ( w_{i,j} ) 是权因子。
  • ( N_{i,p}(u) ) 和 ( N_{j,q}(v) ) 分别是u方向和v方向的p次、q次B样条基函数。
  • 节点向量也分别定义在u和v方向上。

可以将NURBS曲面的构造理解为:先沿一个参数方向(如v方向)构造一系列曲线,再将这些曲线上的点作为新的控制点,沿另一个参数方向(如u方向)构造曲线。曲面的性质(如凸包性、局部性)是曲线性质的直接延伸。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/8228633b83ec1193dbb1520218030ed4_46.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/8228633b83ec1193dbb1520218030ed4_48.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/8228633b83ec1193dbb1520218030ed4_50.png

由于定义域是矩形参数域,对于复杂拓扑曲面(如带洞曲面),通常采用裁剪NURBS(Trimmed NURBS) 技术,即在参数域上定义一条闭合曲线来表征“洞”,然后映射到曲面上进行裁剪。

此外,还有定义在三角域上的曲面片(如Doo-Sabin、Loop细分曲面),适用于非矩形区域的拟合,其基函数通常采用重心坐标的形式。


总结 🎓

本节课我们一起学习了几何建模中四种核心的曲线曲面表示方法:

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/8228633b83ec1193dbb1520218030ed4_52.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/8228633b83ec1193dbb1520218030ed4_54.png

  1. NURBS曲线/曲面:作为工业标准,它通过控制顶点、节点向量和权因子提供了强大且灵活的设计能力,并能精确表示圆锥曲线。
  2. 细分曲线:通过定义简单的迭代加细规则,从粗糙多边形快速生成光滑曲线,概念直观,计算简单。
  3. 隐式曲线:由方程定义,擅长处理无序点集和表示复杂封闭形状,其绘制和重建依赖于数值方法和函数拟合技术。
  4. 曲面构造:NURBS曲面是曲线理论的张量积推广,而三角域上的曲面片则提供了处理非矩形区域的工具。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/8228633b83ec1193dbb1520218030ed4_56.png

所有这些方法背后,函数拟合的思想贯穿始终。无论是选择基函数、设置权值,还是重建隐式函数,本质都是在寻找一个满足特定约束或目标的函数来表达几何形状。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/8228633b83ec1193dbb1520218030ed4_58.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/8228633b83ec1193dbb1520218030ed4_60.png

从下节课开始,我们将进入课程的另一半,学习离散曲面(三角网格) 的表示、处理与分析,这是现代数字几何处理的核心内容。

GAMES102-几何建模与处理—P7-曲线光顺–离散曲线–三角网格—GAMES-Webinar—BV1NA411E7Yr_note

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/1f691bc258cfb13550e2040aec7b099e_0.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/1f691bc258cfb13550e2040aec7b099e_2.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/1f691bc258cfb13550e2040aec7b099e_4.png

在本节课中,我们将学习曲线光顺的概念、离散曲线的必要性以及三角网格的基本知识。课程内容从作业回顾开始,逐步深入到曲线光顺的数学定义、离散化方法,并最终引入三维三角网格的数据结构与处理基础。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/1f691bc258cfb13550e2040aec7b099e_6.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/1f691bc258cfb13550e2040aec7b099e_8.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/1f691bc258cfb13550e2040aec7b099e_10.png


https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/1f691bc258cfb13550e2040aec7b099e_12.png

作业回顾与点评 📝

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/1f691bc258cfb13550e2040aec7b099e_14.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/1f691bc258cfb13550e2040aec7b099e_16.png

上一节我们介绍了曲线细分方法。本节中,我们来看看同学们提交的作业情况。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/1f691bc258cfb13550e2040aec7b099e_18.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/1f691bc258cfb13550e2040aec7b099e_20.png

本次作业主要任务是实现B样条细分和四点细分算法。共收到29份有效提交,其中包含多种编程语言的实现。

以下是部分优秀作业示例:

  • 蔡金细分方法:报告详细阐述了三次细分与二次细分(Doo-Sabin细分)的区别。逼近型与插值型细分均有实现。
  • 参数调整:有同学探索了四点细分中α参数的影响。当α值超过1/8时,曲线会产生分形般的振荡,这验证了参数对结果的重要性。
  • 交互界面:多位同学实现了友好的交互界面,能够实时调整控制点、细分类型(二次/三次/四点)、细分次数,并可视化曲线与细分过程。

这些作业代码与报告将作为学习参考。建议同学们在理解原理的基础上独立实现,以更好地掌握这些工具。


曲线光顺(Fairing)概念 🔍

在宏观曲线设计之外,高精度建模中还有一个重要概念——曲线光顺。这在许多教材中涉及较少,但在工业设计软件(如CATIA)中却是关键工具。

光滑与连续

首先回顾连续性的概念。参数连续(Ck)关注参数导数的连续性,而几何连续(Gk)关注曲线本身的几何性质,与参数化无关,更能反映本质。

什么是光顺?

光顺的英文是“Fairing”,意为“公平的”、“流畅的”。一条曲线可能非常光滑(C^∞),但在微观尺度下,其曲率分布可能仍有剧烈波动。这种波动可能导致:

  • 物理性能下降:如船舶在水中阻力增加,齿轮磨损加剧。
  • 视觉效果不佳:如汽车表面反光出现扭曲。

因此,光顺关注的是曲线曲率变化的“平缓”程度,是一种微观几何性质。

曲率:光顺的核心度量

曲率 k 是描述曲线弯曲程度的本质量,与参数化无关。其定义为密切圆半径 r 的倒数:k = 1/r

  • 直线曲率为0。
  • 圆上各点曲率为常数。
  • 曲率变化平缓的曲线更光顺。

历史上对光顺有多种描述:

  1. 苏步青、刘鼎元:曲线需C²连续,且曲率图没有多余波动。
  2. R. Farin:曲率图单调段不宜过多。
  3. 能量法定义:最小化曲线的总曲率平方积分 ∫ k² ds
  4. 工程经验(中国学者):光顺是大局部问题,需同时满足:
    • 具有C¹或更高连续性。
    • 曲线本身拐点少。
    • 曲率图的拐点少。
    • 曲率变化幅度小。

光顺方法简介

基于上述原则,传统光顺方法通过微调控点来调整曲率图,主要步骤包括:

  1. 粗光顺:调整控制点,减小曲率极值。
  2. 削峰:消除多余的曲率拐点。
  3. 回弹:检查并减少曲率单调段的变化。

这些操作需在保证曲线形状变化极小的前提下进行。优化后的曲线,其曲率图变得更为平缓单调。

从曲线到曲面

曲面光顺更为复杂,因为涉及两个主方向。早期方法将曲面分解为两个方向的曲线进行处理。现代方法则考虑曲面的主曲率,并最小化其能量积分。在工业界,A级曲面(Class-A Surface)要求达到G²甚至G³连续,并通过反射线(Reflection Line)来直观检测光顺度。


离散曲线与计算 📊

所有连续表达在计算机中都必须离散化才能进行计算和渲染。本节我们来看看离散化的必要性与方法。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/1f691bc258cfb13550e2040aec7b099e_22.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/1f691bc258cfb13550e2040aec7b099e_24.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/1f691bc258cfb13550e2040aec7b099e_26.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/1f691bc258cfb13550e2040aec7b099e_28.png

离散化的必要性

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/1f691bc258cfb13550e2040aec7b099e_30.png

离散化主要有三个原因:

  1. 渲染:图形硬件(GPU)主要处理直线段(多边形)。任何曲线都必须采样成折线进行光栅化。
  2. 计算:数值计算(如求导、求交)需要在离散点上进行。用足够密的线段可以逼近原曲线。
  3. 制造:许多数控机床(CNC)只支持直线和圆弧插补,复杂曲线必须离散为这两种基本运动。

采样与误差

根据采样定理,为了从采样点重建原信号,采样频率需至少为原信号最高频率的两倍。对于B样条曲线,可以通过分析控制多边形与弦长的误差,来估计需要细分多少次才能达到指定精度。

离散曲线的几何计算

当只有离散点而无数表达式时,计算几何属性(如法向、曲率)有两种思路:

  1. 拟合法:先用离散点拟合出一条连续曲线(如B样条),再利用该曲线的解析表达式求导。
  2. 差分法:直接用离散点的差分来近似导数。例如,一阶差分近似一阶导数(切线),二阶差分近似二阶导数(曲率)。其本质是泰勒展开的离散形式。

重心坐标与变形应用 🎯

在介绍三角网格前,我们先看一个连接连续与离散表达的重要工具——重心坐标,及其在变形中的应用。

从贝塞尔曲线到代理变形

贝塞尔曲线的核心思想是:用少数控制顶点的线性组合(基函数加权)来定义复杂曲线上的无数点。这启发了“代理”(Proxy)变形的思想:用一个简单几何体(如包围笼)控制一个复杂形状。

重心坐标的定义

关键在于建立内部点与边界控制点之间的定量关系。

  • 三角形重心坐标:对于三角形内任意点 P,存在唯一的重心坐标 (α, β, γ),使得 P = αA + βB + γC,且 α+β+γ=1。几何上,α 等于 P 对边小三角形面积与大三角形面积之比。
  • 多边形重心坐标:不唯一,存在多种定义方式,如均值坐标、谐波坐标等,各有不同的几何性质和适用场景。

应用:图像变形

利用重心坐标,可以实现直观的变形操作:

  1. 用户编辑代理控制点(如一个包围多边形的顶点)。
  2. 对于原始图像/网格内的每个点,计算其相对于旧代理的重心坐标。
  3. 将这些相同的重心坐标应用于新代理的控制点,计算出该点的新位置。
  4. 将旧点的颜色或属性复制到新位置。

这种方法被广泛用于图像扭曲、曲面编辑等。


https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/1f691bc258cfb13550e2040aec7b099e_32.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/1f691bc258cfb13550e2040aec7b099e_34.png

三角网格入门 🕸️

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/1f691bc258cfb13550e2040aec7b099e_36.png

课程的后半部分将重点转向曲面,而三角网格是离散曲面的主要表示形式。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/1f691bc258cfb13550e2040aec7b099e_38.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/1f691bc258cfb13550e2040aec7b099e_40.png

为什么是三角网格?

  1. 渲染需求:GPU硬件高度优化了对三角形的光栅化。
  2. 简化计算:将复杂的曲面求交等问题,转化为简单的平面(三角形)求交问题。
  3. 通用性:任何曲面都可以通过足够密的三角片来逼近(分片线性逼近)。

基本概念与数据结构

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/1f691bc258cfb13550e2040aec7b099e_42.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/1f691bc258cfb13550e2040aec7b099e_44.png

三角网格本质上是附着了3D坐标的图(Graph)。

  • 顶点(Vertex):空间中的点。
  • 边(Edge):连接两个顶点的线段。
  • 面(Face):由三条边首尾相连构成的三角形。
  • 度(Degree):一个顶点所连接的边的数量。
  • 流形(Manifold):网格上任一点的局部邻域拓扑同胚于一个圆盘。非流形情况(如一条边被三个面共享)会给处理带来困难,通常需要预处理。
  • 可定向性(Orientability):所有三角形的顶点绕序(如逆时针)保持一致。莫比乌斯环是不可定向的。

数据结构:半边结构

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/1f691bc258cfb13550e2040aec7b099e_46.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/1f691bc258cfb13550e2040aec7b099e_48.png

高效处理网格需要能快速查询顶点、边、面之间的邻接关系。半边结构(Half-edge)是一种经典表示:

  • 将一条边拆分为两条方向相反的“半边”。
  • 每条半边存储:起点、下一条半边、所属面、对偶半边。
  • 通过这种链接,可以高效遍历一个点的所有邻边,或一个面的所有边。

实践:开始使用网格框架

许多几何处理框架(如课程助教提供的框架)已实现了半边等数据结构。建议初学者先利用框架读入一个OBJ格式的网格文件,并尝试进行简单操作,例如:

  • 计算每个顶点的法向(邻接面法向的平均值)。
  • 沿法向对顶点进行扰动,观察网格变化。
  • 通过UI交互调整扰动参数。

这有助于熟悉网格数据的访问与操作流程,为后续更复杂的算法实现打下基础。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/1f691bc258cfb13550e2040aec7b099e_50.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/1f691bc258cfb13550e2040aec7b099e_52.png


总结 📚

本节课我们一起学习了:

  1. 曲线光顺的概念、意义及其基于曲率的数学描述和优化方法。
  2. 连续曲线离散化的必要性、采样理论及离散几何计算方法。
  3. 重心坐标作为连接连续与离散的桥梁,及其在形状变形中的应用。
  4. 三角网格作为离散曲面表示的基础知识,包括其定义、流形性质及半边数据结构。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/1f691bc258cfb13550e2040aec7b099e_54.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/1f691bc258cfb13550e2040aec7b099e_55.png

从下节课开始,我们将正式进入三角网格处理的核心内容,包括平滑、参数化、简化等算法。请同学们利用本周时间熟悉网格处理框架的基本操作。

GAMES102-几何建模与处理—P8-离散微分几何-Utopia框架介绍—GAMES-Webinar—BV1NA411E7Yr_note

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/d4185f64a49599b0e4f858aaabb3a4b5_0.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/d4185f64a49599b0e4f858aaabb3a4b5_2.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/d4185f64a49599b0e4f858aaabb3a4b5_4.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/d4185f64a49599b0e4f858aaabb3a4b5_0.png

在本节课中,我们将要学习三角网格上的离散微分几何量的计算,特别是曲率的计算。这些计算在后续的几何处理中非常重要。课程的后半部分将介绍我们用于完成作业的Utopia框架。

三角网格曲面概述 🔺

上一节我们介绍了光滑曲面的表达。在实际应用中,特别是随着扫描仪的广泛应用,我们更多地获得的是曲面上点的采样。这些采样点构成了三角网格。

三角网格可以有两种理解方式:

  • 逼近论观点:网格点是从光滑曲面上采样得到的。将相邻点连接成三角形,就构成了一张分片线性的曲面,它是对原光滑曲面的一种逼近。每个三角形是一个平面,因此整个网格是C0连续的。
  • 拓扑学观点:三角网格本质上是一个二维图(Graph)在三维空间中的“提升”(嵌入)。其顶点、边、面的连接关系(拓扑结构)不变,只是顶点的空间位置发生了变化。因此,它本质上是一个二维流形。

无论从哪个角度看,三角网格都是空间曲面的一种离散表达。

数据结构:图与半边结构 🗺️

要操作三角网格,必须掌握其数据结构。在数据结构中,图(Graph)是最复杂的结构之一,由顶点集合和边集合构成。

对于三角网格,我们需要存储顶点、边和面的信息。一个常见的格式是OBJ格式,它主要存储顶点(v)和面(f)的信息,边信息可以从面信息中推导出来。

在图形学中,有多种数据结构来表达网格。本节课介绍一种常用且通用的结构:半边结构(Half-edge Structure)

半边结构的核心思想是将一条物理边拆分为两个有向的“半边”。每个半边存储以下信息:

  • vertex:该半边指向的终点顶点。
  • pair:与该半边配对的另一个半边(代表同一条物理边的相反方向)。
  • face:该半边所属的面。
  • next:在同一面内,该半边的下一条半边。

顶点只需存储其关联的任意一条半边,面只需存储其关联的任意一条半边。

通过这种结构,可以高效地进行邻接关系查询:

  • 由半边找两个顶点:起点 = pair->vertex,终点 = vertex
  • 由半边找两个邻面:一个邻面 = face,另一个邻面 = pair->face
  • 由面找所有半边:从face->halfedge开始,不断访问next,直到回到起点。
  • 由顶点找所有半边:从vertex->halfedge开始,访问其pair->next,循环直到回到起点。

目前有许多优秀的开源几何处理库,如CGAL、libigl、OpenMesh等。本课程推荐使用助教开发的Utopia(无尽)框架,它小巧灵活,易于上手。当然,学员也可以使用自己熟悉的库来完成作业。

微分几何基础回顾 📈

上一节我们回顾了曲线曲面的基本概念,本节我们进一步了解曲面的微分性质。

对于参数曲面 S(u, v),其在点 p 处的偏导 S_uS_v 张成了该点的切平面。切平面的法向,即曲面的法向,可通过叉积得到:

n = (S_u × S_v) / ||S_u × S_v||

过点 p 且包含法向 n 的平面与曲面相交,得到一条平面曲线。该曲线在点 p 处的曲率称为曲面在该切方向上的法曲率

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/d4185f64a49599b0e4f858aaabb3a4b5_6.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/d4185f64a49599b0e4f858aaabb3a4b5_8.png

一个重要的结论是:在点 p 的所有切方向中,存在两个相互垂直的主方向,对应的法曲率分别达到最大值 κ1 和最小值 κ2,称为主曲率。其他任何方向上的法曲率 κ(θ) 都可以通过欧拉公式用主曲率表示:

κ(θ) = κ1 cos²θ + κ2 sin²θ

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/d4185f64a49599b0e4f858aaabb3a4b5_10.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/d4185f64a49599b0e4f858aaabb3a4b5_12.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/d4185f64a49599b0e4f858aaabb3a4b5_14.png

由主曲率可以定义两种常用的曲率:

  • 高斯曲率 (Gaussian Curvature)K = κ1 * κ2
  • 平均曲率 (Mean Curvature)H = (κ1 + κ2) / 2

高斯曲率是内蕴几何量,在等距变换下保持不变。处处高斯曲率为零的曲面称为可展曲面,如平面、圆柱面、圆锥面和切线面。
平均曲率与曲面的面积变化密切相关。处处平均曲率为零的曲面称为极小曲面,如肥皂膜。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/d4185f64a49599b0e4f858aaabb3a4b5_16.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/d4185f64a49599b0e4f858aaabb3a4b5_18.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/d4185f64a49599b0e4f858aaabb3a4b5_20.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/d4185f64a49599b0e4f858aaabb3a4b5_22.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/d4185f64a49599b0e4f858aaabb3a4b5_24.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/d4185f64a49599b0e4f858aaabb3a4b5_26.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/d4185f64a49599b0e4f858aaabb3a4b5_28.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/d4185f64a49599b0e4f858aaabb3a4b5_30.png

离散微分几何 🔲

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/d4185f64a49599b0e4f858aaabb3a4b5_32.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/d4185f64a49599b0e4f858aaabb3a4b5_34.png

我们面对的是分片线性的三角网格,它本身不可微。离散微分几何的目标是通过网格的离散数据,去估计其背后所逼近的光滑曲面的微分属性。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/d4185f64a49599b0e4f858aaabb3a4b5_36.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/d4185f64a49599b0e4f858aaabb3a4b5_38.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/d4185f64a49599b0e4f858aaabb3a4b5_40.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/d4185f64a49599b0e4f858aaabb3a4b5_42.png

估计方法主要有两类:

  1. 连续逼近法:用光滑曲面(如二次曲面)去拟合网格顶点,然后用拟合曲面的属性来近似。
  2. 离散直接法:直接对网格的几何量进行定义和计算。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/d4185f64a49599b0e4f858aaabb3a4b5_44.png

对于法向估计,一个简单有效的方法是:将顶点周围所有相邻面的法向,按面积加权平均,作为该顶点的法向。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/d4185f64a49599b0e4f858aaabb3a4b5_46.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/d4185f64a49599b0e4f858aaabb3a4b5_48.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/d4185f64a49599b0e4f858aaabb3a4b5_50.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/d4185f64a49599b0e4f858aaabb3a4b5_52.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/d4185f64a49599b0e4f858aaabb3a4b5_54.png

对于曲率估计,可以通过离散化微分几何中的定理来推导公式。以下是两个常用的离散化公式(针对顶点 i ):

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/d4185f64a49599b0e4f858aaabb3a4b5_56.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/d4185f64a49599b0e4f858aaabb3a4b5_58.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/d4185f64a49599b0e4f858aaabb3a4b5_60.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/d4185f64a49599b0e4f858aaabb3a4b5_62.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/d4185f64a49599b0e4f858aaabb3a4b5_64.png

  • 离散平均曲率向量(1/(2A_i)) * Σ_{j∈N(i)} (cot α_ij + cot β_ij) (v_j - v_i)
    • N(i):顶点 i 的一环邻域顶点。
    • α_ij, β_ij:边 (i, j) 所对的两个角。
    • A_i:顶点 i 的Voronoi面积或混合面积。
    • 该向量的模长即为平均曲率绝对值,方向为法向。
  • 离散高斯曲率(2π - Σ θ_j) / A_i
    • θ_j:顶点 i 周围第 j 个三角形的内角。
    • A_i:顶点 i 的Voronoi面积。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/d4185f64a49599b0e4f858aaabb3a4b5_66.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/d4185f64a49599b0e4f858aaabb3a4b5_68.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/d4185f64a49599b0e4f858aaabb3a4b5_70.png

计算出的曲率值可以通过颜色映射(Color Map)可视化在网格上,直观展示曲面的弯曲情况。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/d4185f64a49599b0e4f858aaabb3a4b5_72.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/d4185f64a49599b0e4f858aaabb3a4b5_74.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/d4185f64a49599b0e4f858aaabb3a4b5_76.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/d4185f64a49599b0e4f858aaabb3a4b5_78.png

极小曲面与离散平均曲率流 ⭕

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/d4185f64a49599b0e4f858aaabb3a4b5_80.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/d4185f64a49599b0e4f858aaabb3a4b5_82.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/d4185f64a49599b0e4f858aaabb3a4b5_84.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/d4185f64a49599b0e4f858aaabb3a4b5_86.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/d4185f64a49599b0e4f858aaabb3a4b5_88.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/d4185f64a49599b0e4f858aaabb3a4b5_89.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/d4185f64a49599b0e4f858aaabb3a4b5_91.png

平均曲率流是使曲面沿法向以平均曲率为速度移动的演化过程。对于封闭曲面,它会收缩为一个点。如果固定曲面的边界,则内部曲面会演化成极小曲面(平均曲率为零)。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/d4185f64a49599b0e4f858aaabb3a4b5_93.png

我们可以利用离散平均曲率流的思想,通过迭代算法来生成极小曲面:

  1. 识别并固定网格的边界顶点。
  2. 对于每个内部顶点 v_i,计算其向一环邻域重心移动的向量(即离散平均曲率向量)。
  3. 将顶点位置更新为:v_i’ = v_i + λ * 移动向量,其中 λ 是一个较小的正数(如0.1)。
  4. 重复步骤2-3,直到网格变化很小或达到指定迭代次数。

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/d4185f64a49599b0e4f858aaabb3a4b5_95.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/d4185f64a49599b0e4f858aaabb3a4b5_97.png

https://github.com/OpenDocCN/cs-notes-pt3-zh/raw/master/docs/games/img/d4185f64a49599b0e4f858aaabb3a4b5_99.png

这个算法的核心代码逻辑如下:

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐