图形学初识--多边形剪裁算法

241 阅读2分钟

@[toc]

前言

前面一些章节主要针对各种矩阵变换,模型变换、视图变换、投影变换、屏幕空间变换等等!这一节咱们补充一下多边形剪裁算法的内容,主要讲解一下为什么需要,以及介绍二、三维下三角形裁剪的基本思路。

正文

为什么需要多边形剪裁算法?

以三角形为例,经过了视图变换和投影变换后,咱们已经将三角形所有的顶点坐标转换成了裁剪空间的坐标,咱们得目标只是为了获得 [1,1]3[-1,1]^3 包围盒内的顶点构成的三角形,但是必定有些三角形的顶点既有在立方体内部的,也有在外部的,这时候必定需要对其进行转化,从而变成内部的!

以二维举例:以下为三角形裁剪的示意图:

在这里插入图片描述

我们发现,其实二维下的三角形的顶点分支大致分为三类情况:

  • (1)三角形的三个顶点都在可视坐标范围内。这种情况不需要裁剪
  • (2)三角形的三个顶点既有可视坐标范围内,也有可视范围外。这种情况就是裁剪算法发挥的地方!
  • (3)三角形的三个顶点都不在可视坐标范围内。这种情况不需要裁剪

我们发现上述的绿色三角形在可视范围内是一个类似楔形的四边形,这时候需要对其分割成两个三角形才行!其他更多情况,大家可自行画示意图理解即可!

前置知识

二维直线

直线方程:

二维空间下,直线方程一般有几种表达形式,如:y=kx+b,ax+byc=0y = kx+b, ax + by - c = 0 等等,但是为了工程方面的应用,可以用向量进行表达,如下:

ax+by=d(ab)(xy)=d\begin{align} ax +by &= d\\ \begin{pmatrix} a\\b \end{pmatrix} \cdot \begin{pmatrix} x\\y \end{pmatrix}&=d \end{align}

n=(ab)\vec{n} = \begin{pmatrix}a\\b\end{pmatrix} 且它为单位向量,p=(xy)\vec{p}=\begin{pmatrix}x\\y\end{pmatrix},则带入上式可得:np=d\vec{n} \cdot \vec{p} = d

上式表达的本质,可理解为:所有满足向 n\vec{n}​ 投影长度为d的点集合,示意图如下:

在这里插入图片描述

距离本质:

当d值变化时,表达的是沿着n\vec n 方向滑动的变化情况,当d>0d>0,往n\vec n 指向的方向进行滑动,当d<0d<0,往反方向滑动,当d==0d==0​ 时,则表达过原点的直线!如下图所示:

在这里插入图片描述

点和直线距离关系:

当我们将空间中任一点 p0=(x0,y0)p_0 = (x_0,y_0),带入上述方程,究竟代表什么含义呢?

其实我们得到的就是 p0p_0n\vec n 上的一个投影,具体如下:

np0d>0,则表示该点在直线的n方向正侧np0d<0,则表示该点在直线的n方向反侧np0d=0,则表示该点就在直线上\vec n \cdot \vec p_0 - d > 0,则表示该点在直线的\vec n 方向正侧\\ \vec n \cdot \vec p_0 - d < 0,则表示该点在直线的\vec n 方向反侧\\ \vec n \cdot \vec p_0 - d = 0,则表示该点就在直线上\\

示意图如下所示:

在这里插入图片描述

三维平面

平面方程

根据二维直线表达,同理在三维中,一个平面方程可表达成:ax+by+cz=dax+by+cz = d,同理记 n=(abc)\vec{n} = \begin{pmatrix}a\\b\\c\end{pmatrix}p=(xyz)\vec{p} = \begin{pmatrix}x\\y\\z\end{pmatrix}

则可得到 np=d\vec n \cdot \vec p = d

类似的当我们保证n\vec n为单位向量时,此关系式可以理解为三维空间中,所有满足向 n\vec{n} 投影长度为d的点集合,其实也就是一个平面,如下图所示:

在这里插入图片描述

距离本质:

当d值变化时,表达的是沿着n\vec n 方向滑动的变化情况,当d>0d>0,往n\vec n 指向的方向进行滑动,当d<0d<0,往反方向滑动,当d==0d==0 时,则表达过平面的点!如下图所示:

在这里插入图片描述

点和直线距离关系:

当我们将空间中任一点 p0=(x0,y0,z0)p_0 = (x_0,y_0,z_0),带入上述方程,究竟代表什么含义呢?

其实我们得到的就是 p0p_0n\vec n 上的一个投影,具体如下:

np0d>0,则表示该点在平面的n方向正侧np0d<0,则表示该点在平面的n方向反侧np0d=0,则表示该点就在平面上\vec n \cdot \vec p_0 - d > 0,则表示该点在平面的\vec n 方向正侧\\ \vec n \cdot \vec p_0 - d < 0,则表示该点在平面的\vec n 方向反侧\\ \vec n \cdot \vec p_0 - d = 0,则表示该点就在平面上\\

示意图如下所示:

在这里插入图片描述

类似的,咱们也可以延伸思维,拓展到高维空间的对应表达形式,从而得出相应的结论!

Suntherland hodgman算法

基本介绍

Sutherland-Hodgman算法是一种用于多边形裁剪的经典计算机图形学算法。它的主要功能是将一个多边形裁剪到一个凸多边形窗口内,输出裁剪后的多边形。该算法由Ivan Sutherland和Gary Hodgman在1974年提出。

基本思想

Suntherland hodgman算法也叫逐边裁剪法,它将待裁剪目标多边形的每条边逐一与裁剪窗口的每条边比较,然后生成新的顶点集合,最终得到裁剪后的多边形。

二维举例

问题描述:

已知多边形有序顶点集合 V={v1,v2,...,vn}V = \{v_1,v_2,...,v_n\} ,几组不同的窗口边线表达方程,如:n1p=d1n2p=d2n3p=d3n4p=d4\vec n_1 * p = d_1,\vec n_2 * p = d_2,\vec n_3 * p = d_3,\vec n_4 * p = d_4

核心思路:

  • 遍历顶点集合的顺序顶点对 p1=(v1,v2),p2=(v2,v3),...,pn=(vn,v1)p_1 = (v_1,v_2),p_2 = (v_2,v_3),...,p_n = (v_n,v_1) ,针对每次顶点对的顶点,带入直线方程进行判定内外情况,从而做出不同的顶点选择
  • 针对每个窗口边线方程,进行迭代,得到最终顶点集。每一轮的输入顶点集为上一轮的输出,首轮迭代的输入为多边形有序顶点集!

遍历顶点对的不同情况

假设我们设顶点对的顶点对 (S,P)(S,P),则有如下几种情况:

在这里插入图片描述

  • 情况1:S外侧,P内侧 => 不选择顶点
  • 情况2:S内侧,P外侧 => 选择交点I
  • 情况3:S外侧,P内侧 => 先选择交点I,然后选择P
  • 情况4:S内侧,P内侧 => 选择顶点P

算法举例1:

输入顶点集合:0、1、2,如下图:

在这里插入图片描述

依次考察右侧边线和顶点对(0,1)(1,2),(2,0)(0,1),(1,2),(2,0) 的关系,然后做出不同的考察,最终得到顶点集 (0,1,1)(0',1,1') ,咱们将这个结果作为输入,针对另外一测边线进行类似的操作,直到四条边线都迭代完成,最终得到的结果就是 (0,1,1)(0',1,1')

算法举例2:

输入顶点集合:0、1、2

先考察上侧边,如下图:

在这里插入图片描述

得到结果顶点集合(0,1,2,2)(0',1,2,2')

然后考察右侧边,如下图:

在这里插入图片描述

依次类推,另外两边,最终得到结果就是 (1,1,2,0)(1,1',2'',0')

算法补充:

1、三角形重建

上述得到了剪裁后的多边形顶点序列,但在图形学中,渲染基本以三角形为图元,所以一般还需要多一个步骤:三角形重建。

往往我们都是以第一个顶点固定,后两个顶点从后面以此类推。如上算法举例2结果为例,形成三角形(1,1,2)(1,2,0)(1,1',2'')和(1,2'',0')

2、交点插值

当出现将内外侧与边线的交点作为顶点选择的时候,咱们如何计算这个交点的位置?又如何计算它的顶点颜色?uv坐标呢?

其实这个问题,在之前的直线插值早已解释过。如下图所示:

在这里插入图片描述

那么如何计算PS和边线的交点I呢?

已知P点和S点的属性值和位置,假设边线方程为 np=d\vec n \cdot \vec{p} = d ,将外侧顶点S带入,得到有向距离 ds=nSd_s = \vec n \cdot \vec S,同理,也得到内侧顶点P的有向距离dp=nPd_p = \vec n \cdot \vec P

这时候我们知道 ds>0dp<0d_s > 0 且 d_p < 0 ,前面的前置知识已经给出解释过了。这时候就可以利用之前的知识,求出权重 weight=ds/(dsdp) weight = d_s / (d_s - d_p)

从而求出交点的属性,如下:

f(I)=weightf(P)+(1weight)f(S)f(I) = weight * f(P) + (1 - weight) * f(S)

三维拓展

在三维情况下,裁剪边变成了裁剪平面,维度上升而已,其实本质没有变化,这里简单介绍一下图形学中的应用。

一般来说,在透视除法之前,会将剪裁空间坐标系下的坐标,进行剪裁操作。从而保证透视除法后,得到正确的包围盒[1,1]3[-1,1]^3​ 的NDC坐标,并且位于摄像机前方。

因此剪裁空间的坐标必须满足以下不等式:

wc>01<xcwc<11<ycwc<11<zcwc<1w_c > 0\\ -1 < \frac{x_c}{w_c} < 1\\ -1 < \frac{y_c}{w_c} < 1\\ -1 < \frac{z_c}{w_c} < 1\\

由于咱们需要之前类似的方程形式,所以进行转化为高维平面方程形式:

0xc+0yc+0zc+1wc>01xc+0yc+0zc+1wc>01xc+0yc+0zc+1wc>00xc+1yc+0zc+1wc>00xc+1yc+0zc+1wc>00xc+0yc+1zc+1wc>00xc+0yc+1zc+1wc>00*x_c + 0*y_c + 0*z_c + 1 * w_c > 0\\ -1*x_c + 0*y_c + 0*z_c + 1 * w_c > 0\\ 1*x_c + 0*y_c + 0*z_c + 1 * w_c > 0\\ 0*x_c + -1*y_c + 0*z_c + 1 * w_c > 0\\ 0*x_c + 1*y_c + 0*z_c + 1 * w_c > 0\\ 0*x_c + 0*y_c + -1*z_c + 1 * w_c > 0\\ 0*x_c + 0*y_c + 1*z_c + 1 * w_c > 0\\

所以咱们就得到了 np=0\vec n \cdot \vec p = 0 的边界方程表达式,n\vec n 就是上述每一个方程的系数组成的向量,如{0,0,0,1}{1,0,0,1}\{0,0,0,1\},\{-1,0,0,1\}等等,一共7组!

边界方程也有了,需要裁剪的多边形顶点也有了,思路也就类似二维,代码就是体力劳动喽!

结尾:你们的点赞 + 关注就是我创作的最大动力!加油!

希望对各位小伙伴能够有所帮助哦,有任何问题请评论或私信哦,有空一定会回复的哦!永远在学习的道路上伴你而行, 我是航火火,火一般的男人!