1. 程式人生 > >SDF(Signed-distance-field: 有向距離場)(3): 空間劃分原理(原始碼解釋)

SDF(Signed-distance-field: 有向距離場)(3): 空間劃分原理(原始碼解釋)

下面這是SDF常用的三個函式:

// intersect(求交)
vec2 mult(vec2 tA, vec2 tB) {
    if(tA.x > tB.x) return tA;
    return tB;
}
// union(合併)
vec2 add(vec2 tA, vec2 tB) {
    if(tA.x < tB.x) return tA;
    return tB;
}
// difference(差異)
vec2 subtract(vec2 tA, vec2 tB) {
    tB.x = -tB.x;
    if(tA.x > tB.x) return tA;
    return tB;
}

這三個函式用於計算一個空間點位於一個一個空間分佈函式所描述的空間的"裡面"還是外面,如果是"裡面",那這個點所對應的空間分佈函式所描述的空間的對應位置就可見。

那麼,他們的原理是什麼呢?

先從2D平面說起。一個2D平面,預設是無限大的,但是一條這個平面上的直線可以將它分為兩個部分,也就是兩個空間。如果直線定義了正方向,那麼這兩部分各自就有了正負空間這個稱呼。

這個2D空間中的一個圓或者一個三角形,是由曲線圍起來的一片區域:一個封閉空間,這時候,我們就可以斷定一個2D平面上的點在這個封閉空間裡面還是外面。

這裡可以規定在這個區域裡為負值,在其外面就為正值。

接著看3D空間。在3D空間裡,原本3D空間是無限延伸的。而一個3D空間中的平面(當然也有曲面,這裡先只看平面),將3D空間劃分為兩部分,我們都知道3D空間中的平面需要一個法線n(nx,ny,nz)來描述

可以認為法線的方向上的空間為正空間,反之為負空間。例如一個球體或者長方體,球體是個封閉空間是個曲面,將3D空間分為兩部分,球體裡面和外面,按照上述規定,裡面為負值外面為正值。

同理,長方體也一樣,展開來講只要空間分佈函式(你可以任意構造這個函式)能描述都可以。

因為3D空間中的封閉空間只能由面來決定,所以空間分佈函式的實現只能是面或者曲面的某種集合

現在來看上述三個函式

A.intersect(求交): vec2 mult(vec2 tA, vec2 tB),和乘法類似,因此可以這麼理解:一個空間點,必須同時屬於兩個封閉空間,才能視為可見

B.add(求和): vec2 add(vec2 tA, vec2 tB), 和加法類似,因此可以這麼理解:一個空間點,只要屬於兩個封閉空間中的任何一個,就能視為可見

C.subtract(求差): vec2 subtract(vec2 tA, vec2 tB), 和減法類似,因此可以這麼理解:一個空間點,要屬於封閉空間中A同時有不屬於封閉空間B(也就是封閉空間B的外面),就能視為可見

有了這三個函式,就能通過這三個函式的組合運算實現各種幾何體(封閉空間)