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

文章目录

  • 前言
  • 正文
    • 为什么需要多边形剪裁算法?
    • 前置知识
      • 二维直线
        • 直线方程:
        • 距离本质:
        • 点和直线距离关系:
      • 三维平面
        • 平面方程
        • 距离本质:
        • 点和直线距离关系:
    • Suntherland hodgman算法
      • 基本介绍
      • 基本思想
      • 二维举例
        • 问题描述:
        • 核心思路:
        • 算法补充:
      • 三维拓展
  • 结尾:你们的点赞 + 关注就是我创作的最大动力!加油!

前言

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

正文

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

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

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

在这里插入图片描述

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

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

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

前置知识

二维直线

直线方程:

二维空间下,直线方程一般有几种表达形式,如: y = k x + b , a x + b y − c = 0 y = kx+b, ax + by - c = 0 y=kx+b,ax+byc=0 等等,但是为了工程方面的应用,可以用向量进行表达,如下:
a x + b y = d ( a b ) ⋅ ( x y ) = d \begin{align} ax +by &= d\\ \begin{pmatrix} a\\b \end{pmatrix} \cdot \begin{pmatrix} x\\y \end{pmatrix}&=d \end{align} ax+by(ab)(xy)=d=d
n ⃗ = ( a b ) \vec{n} = \begin{pmatrix}a\\b\end{pmatrix} n =(ab) 且它为单位向量, p ⃗ = ( x y ) \vec{p}=\begin{pmatrix}x\\y\end{pmatrix} p =(xy),则带入上式可得: n ⃗ ⋅ p ⃗ = d \vec{n} \cdot \vec{p} = d n p =d

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

在这里插入图片描述

距离本质:

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

在这里插入图片描述

点和直线距离关系:

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

其实我们得到的就是 p 0 p_0 p0 n ⃗ \vec n n 上的一个投影,具体如下:
n ⃗ ⋅ p ⃗ 0 − d > 0 ,则表示该点在直线的 n ⃗ 方向正侧 n ⃗ ⋅ p ⃗ 0 − d < 0 ,则表示该点在直线的 n ⃗ 方向反侧 n ⃗ ⋅ p ⃗ 0 − d = 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,则表示该点就在直线上\\ n p 0d>0,则表示该点在直线的n 方向正侧n p 0d<0,则表示该点在直线的n 方向反侧n p 0d=0,则表示该点就在直线上
示意图如下所示:

在这里插入图片描述

三维平面

平面方程

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

则可得到 n ⃗ ⋅ p ⃗ = d \vec n \cdot \vec p = d n p =d

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

在这里插入图片描述

距离本质:

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

在这里插入图片描述

点和直线距离关系:

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

其实我们得到的就是 p 0 p_0 p0 n ⃗ \vec n n 上的一个投影,具体如下:
n ⃗ ⋅ p ⃗ 0 − d > 0 ,则表示该点在平面的 n ⃗ 方向正侧 n ⃗ ⋅ p ⃗ 0 − d < 0 ,则表示该点在平面的 n ⃗ 方向反侧 n ⃗ ⋅ p ⃗ 0 − d = 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,则表示该点就在平面上\\ n p 0d>0,则表示该点在平面的n 方向正侧n p 0d<0,则表示该点在平面的n 方向反侧n p 0d=0,则表示该点就在平面上
示意图如下所示:

在这里插入图片描述

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

Suntherland hodgman算法

基本介绍

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

基本思想

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

二维举例

问题描述:

已知多边形有序顶点集合 V = { v 1 , v 2 , . . . , v n } V = \{v_1,v_2,...,v_n\} V={v1,v2,...,vn} ,几组不同的窗口边线表达方程,如: n ⃗ 1 ∗ p = d 1 , n ⃗ 2 ∗ p = d 2 , n ⃗ 3 ∗ p = d 3 , n ⃗ 4 ∗ p = d 4 \vec n_1 * p = d_1,\vec n_2 * p = d_2,\vec n_3 * p = d_3,\vec n_4 * p = d_4 n 1p=d1n 2p=d2n 3p=d3n 4p=d4

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

遍历顶点对的不同情况

假设我们设顶点对的顶点对 ( S , P ) (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,2),(2,0) 的关系,然后做出不同的考察,最终得到顶点集 ( 0 ′ , 1 , 1 ′ ) (0',1,1') (0,1,1) ,咱们将这个结果作为输入,针对另外一测边线进行类似的操作,直到四条边线都迭代完成,最终得到的结果就是 ( 0 ′ , 1 , 1 ′ ) (0',1,1') (0,1,1)

算法举例2:

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

先考察上侧边,如下图:

在这里插入图片描述

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

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

在这里插入图片描述

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

算法补充:

1、三角形重建

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

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

2、交点插值

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

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

在这里插入图片描述

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

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

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

从而求出交点的属性,如下:
f ( I ) = w e i g h t ∗ f ( P ) + ( 1 − w e i g h t ) ∗ f ( S ) f(I) = weight * f(P) + (1 - weight) * f(S) f(I)=weightf(P)+(1weight)f(S)

三维拓展

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

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

因此剪裁空间的坐标必须满足以下不等式:
w c > 0 − 1 < x c w c < 1 − 1 < y c w c < 1 − 1 < z c w c < 1 w_c > 0\\ -1 < \frac{x_c}{w_c} < 1\\ -1 < \frac{y_c}{w_c} < 1\\ -1 < \frac{z_c}{w_c} < 1\\ wc>01<wcxc<11<wcyc<11<wczc<1

由于咱们需要之前类似的方程形式,所以进行转化为高维平面方程形式:
0 ∗ 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 0*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\\ 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>0

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

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

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/672850.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

mysql中EXPLAIN详解

大家好。众所周知&#xff0c;MySQL 查询优化器的各种基于成本和规则的优化会后生成一个所谓的执行计划&#xff0c;这个执行计划展示了接下来具体执行查询的方式。在日常工作过程中&#xff0c;我们可以使用EXPLAIN语句来查看某个查询语句的具体执行计划&#xff0c; 今天我们…

椭圆轨道的周期性运动轨道

一、背景介绍 本节将从轨道六根数的角度&#xff0c;探究目标星为椭圆轨道&#xff0c;追踪星周期性环绕目标的必要条件。根据航天动力学的原理&#xff0c;对于一个椭圆轨道&#xff0c;其轨道能量为 对于能够不产生漂移的情况&#xff0c;绕飞编队的能量。对于追踪星到目标星…

(2024,扩散,去噪调度,维度,误差,收敛速度)适应基于分数的扩散模型中的未知低维结构

Adapting to Unknown Low-Dimensional Structures in Score-Based Diffusion Models 公和众和号&#xff1a;EDPJ&#xff08;进 Q 交流群&#xff1a;922230617 或加 VX&#xff1a;CV_EDPJ 进 V 交流群&#xff09; 目录 0. 摘要 1. 引言 1.1 扩散模型 1.2 现有结果的不…

Xilinx RFSOC 47DR 8收8发 信号处理板卡

系统资源如图所示&#xff1a;  FPGA采用XCZU47DR 1156芯片&#xff0c;PS端搭载一组64Bit DDR4,容量为4GB,最高支持速率&#xff1a;2400MT/s;  PS端挂载两片QSPI X4 FLASH&#xff1b;  PS支持一路NVME存储&#xff1b;  PS端挂载SD接口&#xff0c;用于存储程序&…

图解大模型分布式并行各种通信原语

背景 在分布式集群上执行大模型任务时候&#xff0c;往往使用到数据并行&#xff0c;流水线并行&#xff0c;张量并行等技术&#xff0c;这些技术本质上也就是对数据进行各种方案的切分&#xff0c;然后放到不同的节点上运算。不同节点在计算的过程中需要对数据分发或者同步等…

LeetCode刷题之HOT100之在排序数组中查找元素的第一个和最后一个位置

下午雨变小了&#xff0c;但我并未去实验室&#xff0c;难得的一天呆在宿舍。有些无聊&#xff0c;看看这个&#xff0c;弄弄那个&#xff0c;听听歌&#xff0c;消磨时间。不知觉中时间指针蹦到了九点&#xff0c;做题啦&#xff01;朋友推荐了 Eason 的 2010-DUO 演唱会&…

一文了解经典报童模型的扩展问题

文章目录 1 引言2 经典报童模型3 综述文章4 模型扩展4.1 扩展目标函数4.2 增加约束条件4.3 增加优化变量4.4 扩展模型参数4.5 扩展问题场景 5 总结6 相关阅读 1 引言 时间过的真快呀&#xff0c;已经6月份了。距离上一篇文章发表&#xff0c;已经过去了将近一个月&#xff0c;…

JS(DOM、事件)

DOM 概念:Document Object Model&#xff0c;文档对象模型。将标记语言的各个组成部分封装为对应的对象: Document:整个文档对象Element:元素对象Attribute:属性对象Text:文本对象Comment:注释对象 JavaScript通过DOM&#xff0c;就能够对HTML进行操作: 改变 HTML 元素的内…

系统操作规约(System Operation Contract)

领域建模补充 问题&#xff1a; 联系有方向性 属性有类型 领域模型尽量避免出现界面相关的东西 习题 问题 考察点 系统操作规约 示例 A) Operation: MakeSale() Cross References: UC&#xff1a;Purchase Preconditions: User has logged in Postconditions: An ProductLis…

集成算法实验与分析(软投票与硬投票)

概述 目的&#xff1a;让机器学习效果更好&#xff0c;单个不行&#xff0c;集成多个 集成算法 Bagging&#xff1a;训练多个分类器取平均 f ( x ) 1 / M ∑ m 1 M f m ( x ) f(x)1/M\sum^M_{m1}{f_m(x)} f(x)1/M∑m1M​fm​(x) Boosting&#xff1a;从弱学习器开始加强&am…

Fiddler抓包工具的使用

目录 1、抓包原理&#xff1a;&#x1f447; 2、抓包结果&#x1f447; 1&#xff09;如何查看一个http请求的原始摸样&#xff1a; 2&#xff09;分析数据格式&#xff1a; 3、请求格式分析&#x1f447; 4、响应格式分析&#x1f447; 官网下载&#xff1a;安装过程比较…

win11+vmware16.0+Ubuntu22.04+开机蓝屏

总结 本机系统 vm虚拟机下载 参考链接 1. 小白必看的Ubuntu20.04安装教程&#xff08;图文讲解&#xff09; 2. 软件目录【火星】——VM下载 3. Win11使用VMware15/16启动虚拟机直接蓝屏的爬坑记录 VMware16.0

C++一个StringBad类

设计一个字符串类,下面的代码是一个不好的设计,起名StringBad。 //stringbad.h #pragma once //一个设计有问题的string类 #include <iostream> using namespace std;class StringBad { public:StringBad();//默认构造函数StringBad(const char* s);//构造函数~StringBa…

执法装备管理系统DW-S304的概念与特点

执法装备管理系统&#xff08;DW-S304&#xff09;适用于多种警务和安保场景&#xff0c;如警察局、特警队、边防检查站、监狱管理系统、生态环境局、执法大队等。它可以帮助这些机构提高对装备的控制能力&#xff0c;确保装备在需要时能够迅速到位&#xff0c;同时也减少了因装…

C++ 习题精选(2)

目录 1. 验证回文串2. 字符串相乘 1. 验证回文串 题目描述&#xff1a;如果在将所有大写字符转换为小写字符、并移除所有非字母数字字符之后&#xff0c;短语正着读和反着读都一样。则可以认为该短语是一个 回文串 。字母和数字都属于字母数字字符。给你一个字符串 s&#xff…

测试基础09:缺陷(bug)生命周期、定位方式和管理规范

课程大纲 1、缺陷&#xff08;bug&#xff09;生命周期 2、缺陷&#xff08;bug&#xff09;提交规范 2.1 宗旨 简洁、清晰、可视化&#xff0c;减少沟通成本。 2.2 bug格式和内容 ① 标题&#xff1a;一级功能-二级功能-三级功能_&#xff08;一句话描述bug&#xff1a;&…

linux命令:调试必备工具dmesg

在服务器上进行芯片调试时&#xff0c;我们会遇到各种各样的问题&#xff0c;很多问题与操作系统相关。此时就需要了解操作系统发生了哪些事件。 dmesg 是linux系统中用来打印或控制内核缓冲区内容的命令。这个环形缓冲区记录了系统启动以来发生的各种事件消息&#xff0c;包括…

远程自动锁定平面

目录 Ubuntu 系统上 方法一&#xff1a;使用 SSH 重新连接 方法二&#xff1a;解锁当前会话 方法三&#xff1a;通过 SSH 解锁会话 方法四&#xff1a;禁用自动锁屏&#xff08;如果合适&#xff09; windows系统 方法三&#xff1a;修改组策略设置 Ubuntu 系统上 远程…

派生类中调用基类的__init__()方法

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 在派生类中定义__init__()方法时&#xff0c;不会自动调用基类的__init__()方法。例如&#xff0c;定义一个Fruit类&#xff0c;在__init__()方法中创…

java并发常见问题

1.死锁&#xff1a;当两个或多个线程无限期地等待对方释放锁时发生死锁。为了避免这种情况&#xff0c;你应该尽量减少锁定资源的时间&#xff0c;按顺序获取锁&#xff0c;并使用定时锁尝试。 2.竞态条件&#xff1a;当程序的行为依赖于线程的执行顺序或输入数据到达的顺序时…