隐式曲面(代数形式,CSG,距离函数,分型几何)与显式几何

2023-10-30 14:20

本文主要是介绍隐式曲面(代数形式,CSG,距离函数,分型几何)与显式几何,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

计算机图形学:隐式曲面(代数形式,CSG, 距离函数,分型几何)与显式曲面

隐式曲面与显式曲面

1.1隐式曲面的特点

所谓隐式曲面值得是并不会告诉你任何点的信息,只会告诉你该画面上所有点满足的关系。来举个具体的隐式曲面的例子:
在这里插入图片描述
相信读者都能一眼看出来这是一个三维球体的方程,一般地我们会把隐式曲面的代数方程写成在这里插入图片描述
该球体的
对于隐式方程来说因为没有给出任何点的信息,因此如何采样到曲面上具体的点是一个很难的问题,如下图这样一个例子:
在这里插入图片描述
别说找出这样一个圆环上的点,相信不少人都像作者一样,第一眼见到这个代数方程之后连他表现得形状都不知道。
但是考虑到事物的两面性,有坏处自然也有好处。
在这里插入图片描述
如果使用隐式曲面方程,将会十分容易的判断出一点与曲面的关系,这是一种非常具有吸引力的特性(能够轻易的判定光线与物体是否相交)
对于其他具体的隐式曲面稍后再做介绍,首先来看看与之相对的显式曲面的特点。

1.2显式曲面的特点

对于显式曲面来说是与隐式曲面相对应的,所有曲面的点被直接给出,或者可以通过映射关系直接得到,如下图:
在这里插入图片描述
虽然没有直接给出点的数据x,y,z,但是拥有u,v的取值范围以及从(u,v)->(x,y,z)的映射关系,那么只需要将所有的u,v代入自然就可求得x,y,z。

区别隐式曲面与显式曲面的关键就在于是否可以直接表示出所有的点。

在1.1节提到了隐式曲面难以采样曲面上的点,但是可以轻易判断点与曲面的关系,对于显式曲面来回说恰恰相反,我们可以很轻易的采样到所有的点,但是给予你任意一点却很难判断它与曲面的关系。

因此没有哪一种的几何表现方式是更好的,根据具体的任务来选择隐式还是显示才是合理的做法。

2具体的几种隐式曲面

2.1代数曲面

对于该类隐式曲面来说其实正式在第一张中举例说明所运用到的,通过代数表达式可以得到许许多多不同的几何曲面:
在这里插入图片描述
但似乎单纯代数表达式曲面都比较有规则性,那么对于更复杂的几何形体怎么办呢?CSG便应运而生了。

2.2Constructive Solid Geometry(CSG)

CSG指的是可以对各种不同的集合做布尔运算,比如并,交,差:
在这里插入图片描述
通过这些操作可以得出各种更为复杂的几何:
在这里插入图片描述

2.3符号距离函数(Signed Distance Function)

除了对于几何的布尔操作,还可以通过距离函数来得到几何形体混合的效果,如下图:
在这里插入图片描述
如何得到blend的效果,就要从SDF即符号距离函数说明(这里的符号是指距离,可以有正有负)。

首先对于符号距离函数来说本质上就是一种定义距离的函数。如有空间任意一点到各个几何物体表面的距离,对这些距离做各种各样的运算操作最后得到的一个函数就是最终的距离函数。
在这里插入图片描述
对于一个二维平面的例子,定义空间中每一点的SDF为该点到阴影区域右边界的垂直距离,在阴影内部为负,外部为正,因此对于A和B两种阴影来说的SDF分别如上图下半部分所示。有了SDF(A),SDF(B)之后对这两歌距离函数选择项的做一些运算得到最终的距离函数,这里采用最简单的SDF = SDF(A)+SDF(B)来举例,最终得到的SDF为0的点的集合即为blend之后曲面,对该例子来说,就是两道阴影之间中点的一条线。
在这里插入图片描述
因此对于一开始的那个例子来说,只需要合理定义空间中任意一个点的SDF,再令SDF为0即可得到混合的效果了。

(tips:对于几何体混合效果自然不可能像这里简单的两个距离相加就可以得到了,该效果具体实现是找出任一个点到两个几何体表面距离中的最短距离再减去一个变量作为该点最终的SDF,有兴趣的读者可以取油管搜索Coding Adventure:Ray Marching,该视频的讲解很不错)

2.4水平集

水平集的方法其实和SDF很像(像是SDF的一种特殊形式),也是找出函数值为0的地方作为曲线,但不会像SDF会空间中的每一个点有一种严格的数学定义,而是对空间用一个个格子去近似一个函数,如下:
在这里插入图片描述
对该面给的每一个点利用已经定义好的格子值进行双线性插值(在纹理映射一节中解释过)就可以得到任意一点的函数值,找出所有=0的点作为平面。

该方法的好处对于SDF,我们可以更加显示的区空间曲线的形状,该方法 广泛的运用在医学成像和物理模拟之中。

2.5分型几何

分型几何是指许许多多自相似的形体最终组成的几何形状。
如雪花是一个六边形,放大后发现每一个边上又是一个六边形,再放大六边形边上的六边形边上又是六边形,就这样无限套娃,类似于递归。
在这里插入图片描述

3具体的几种显式1曲面

首先,同样在第一章中所用的类似参数方程的方法间接得到所有点方法是一种显示曲面的类型。

3.1点云(point cloud)

在这里插入图片描述

顾名思义,就是很多很多的点构成的曲面,直接有着所有点的信息,没什么太多可讲的,多裹点多模型细节就多,点少模型细节就少。

3.2多边形网格(Polygon Mesh)

在这里插入图片描述
对于多边形网格来说,相信读者并不陌生,该方法广泛应用计算机图形学中,简单的数通过定义各个多边形面的顶点以及顶点之间的连接关系就可以得到许许多多的三角形面或者是四边形面,再通过这个面来近似表现出我们想要的模型效果。

例如比较著名的.obj文件,其格式如下:
在这里插入图片描述
这是一个立方体的模型数据例子
3-10行定义了立方体的8个顶点信息,12-25行定义了这些顶点的纹理坐标信息(每个面4个点,共6个面所以最多有24种不同的纹理坐标信息,这里有一些纹理对于不同面上的点是公用的)。27-34行定义了6个面的法线信息,为什么有8个是因为建模软件输出的精度问题不必在意,其中有两个是重复的。

最重要的就是36-47行了,f代表一个面,其中x/x/x的第一维表示是哪个顶点,第二位表示该顶点纹理坐标是第几个,第三位表示法线信息是第几个。3个x/x/x表示3个顶点的信息构成了一个面。

这篇关于隐式曲面(代数形式,CSG,距离函数,分型几何)与显式几何的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/308493

相关文章

hdu1171(母函数或多重背包)

题意:把物品分成两份,使得价值最接近 可以用背包,或者是母函数来解,母函数(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v) 其中指数为价值,每一项的数目为(该物品数+1)个 代码如下: #include<iostream>#include<algorithm>

uva 10387 Billiard(简单几何)

题意是一个球从矩形的中点出发,告诉你小球与矩形两条边的碰撞次数与小球回到原点的时间,求小球出发时的角度和小球的速度。 简单的几何问题,小球每与竖边碰撞一次,向右扩展一个相同的矩形;每与横边碰撞一次,向上扩展一个相同的矩形。 可以发现,扩展矩形的路径和在当前矩形中的每一段路径相同,当小球回到出发点时,一条直线的路径刚好经过最后一个扩展矩形的中心点。 最后扩展的路径和横边竖边恰好组成一个直

poj 1113 凸包+简单几何计算

题意: 给N个平面上的点,现在要在离点外L米处建城墙,使得城墙把所有点都包含进去且城墙的长度最短。 解析: 韬哥出的某次训练赛上A出的第一道计算几何,算是大水题吧。 用convexhull算法把凸包求出来,然后加加减减就A了。 计算见下图: 好久没玩画图了啊好开心。 代码: #include <iostream>#include <cstdio>#inclu

uva 1342 欧拉定理(计算几何模板)

题意: 给几个点,把这几个点用直线连起来,求这些直线把平面分成了几个。 解析: 欧拉定理: 顶点数 + 面数 - 边数= 2。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#inc

XTU 1237 计算几何

题面: Magic Triangle Problem Description: Huangriq is a respectful acmer in ACM team of XTU because he brought the best place in regional contest in history of XTU. Huangriq works in a big compa

poj 3304 几何

题目大意:给出n条线段两个端点的坐标,问所有线段投影到一条直线上,如果这些所有投影至少相交于一点就输出Yes!,否则输出No!。 解题思路:如果存在这样的直线,过投影相交点(或投影相交区域中的点)作直线的垂线,该垂线(也是直线)必定与每条线段相交,问题转化为问是否存在一条直线和所有线段相交。 若存在一条直线与所有线段相交,此时该直线必定经过这些线段的某两个端点,所以枚举任意两个端点即可。

POJ 2318 几何 POJ 2398

给出0 , 1 , 2 ... n 个盒子, 和m个点, 统计每个盒子里面的点的个数。 const double eps = 1e-10 ;double add(double x , double y){if(fabs(x+y) < eps*(fabs(x) + fabs(y))) return 0 ;return x + y ;}struct Point{double x , y

poj 2653 几何

按顺序给一系列的线段,问最终哪些线段处在顶端(俯视图是完整的)。 const double eps = 1e-10 ;double add(double x , double y){if(fabs(x+y) < eps*(fabs(x) + fabs(y))) return 0 ;return x + y ;}struct Point{double x , y ;Point(){}Po

C++操作符重载实例(独立函数)

C++操作符重载实例,我们把坐标值CVector的加法进行重载,计算c3=c1+c2时,也就是计算x3=x1+x2,y3=y1+y2,今天我们以独立函数的方式重载操作符+(加号),以下是C++代码: c1802.cpp源代码: D:\YcjWork\CppTour>vim c1802.cpp #include <iostream>using namespace std;/*** 以独立函数

函数式编程思想

我们经常会用到各种各样的编程思想,例如面向过程、面向对象。不过笔者在该博客简单介绍一下函数式编程思想. 如果对函数式编程思想进行概括,就是f(x) = na(x) , y=uf(x)…至于其他的编程思想,可能是y=a(x)+b(x)+c(x)…,也有可能是y=f(x)=f(x)/a + f(x)/b+f(x)/c… 面向过程的指令式编程 面向过程,简单理解就是y=a(x)+b(x)+c(x)