天天看點

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

前言

在前面的文章中我們經常提到知道某個三角形三個頂點的屬性,然後就可以求出三角形内部某一點對應的屬性。例如深度緩存的時候,高洛德着色的時候等等,但是我們一直沒有說具體應該如何計算,本文就來介紹一下這一部分内容。

想要計算三角形内部某一點對應的屬性,也就是我們一直說的三角形的插值,就需要用到重心坐标的概念。

直線的重心坐标

在講三角形的重心坐标前,我們先來看一看直線上的重心坐标是怎麼定義的。

求直線上任意一點

設我們有兩個點 A 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

 和 B 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

 ,它們可以連成一條直線。那麼該直線上的任意一點 P 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

 必然滿足:

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

k為一個常數,其值也很好求,取任意軸三個點值進行計算即可:

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

然後我們可得:

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

因為

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

 即 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

而 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

 通過向量的減法,我們可以了解為 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

,同樣的 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

,那麼就可得到 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

 ,然後可以得到

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

,最終簡化可得:

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

而 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

 ,

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

 分别代表的就是 P,A,B三個點的坐标,是以可得

P = (1 - k)A + kB

因為 P = ((1-k)+k)P 是以上面式子可以變為 (1-k)A+kB-((1-k)+k)P=0,化簡為 (1-k)(A-P)+k(B-P),即:

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

幾何意義

前面我們得到 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

,即AP的長度 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

 為 AB的長度 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

 的k倍。而 BP的長度 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

 又等于 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

,是以 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

 的長度為 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

 的 1-k 倍。是以可得:

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

因為長度是沒有正負的,然而實際上k可能為負數,就會導緻上面的公式不對。我們先來看看下面三種情況:

0 <= k <= 1

此時P在AB之間,如下圖

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

可得

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

k < 0

k < 0 ,也就是說

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

 方向和

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

 相反,此時P在AB之外,離A更近一些,如下圖

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

可得

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

k > 0

和前者相反,如下圖

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

可得

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

總結

可以發現我們隻要取絕對值,就可以滿足上面的各種情況了,是以

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

直線上的重心坐标

通過上面的推導,我們就知道直線AB上的任意一點P,都可以由一個k來計算出來的。當然了,也可以通過P來推出k的值,怎麼求上面已經說明過了。

若我們設 j = 1 - k,那麼

P = jA + kB

j + k = 1

這樣的話我們P就可以使用 (j, k) 的方式來表示,這種表示方式就是我們的重心坐标。同時需要注意,因為重心坐标是根據某一條直線的AB兩點所定義的,是以不同的直線各自會有各自的重心坐标。

為什麼叫重心坐标

在生活中想必大家都看過或挑過擔子吧,人們在擔子兩邊挂上重物,然後用肩膀扛起擔子。如果擔子兩邊的物體差不多重,我們要保持擔子的平衡隻需要把肩膀撐在擔子的中間即可。但如果擔子有一頭特别的重,我們需要把肩膀盡可能的往重的那頭靠近,才能保持住擔子的平衡。

我們假設有線段AB(也就是擔子),在A下面挂了品質為 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

 的物體,在B下面挂了品質為

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

 的物體,如下圖:

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

 ,那麼重心P(肩膀的支撐點)應該在哪?自然線段的中心點了,如下圖:

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

 呢 ,那麼P點的位置又應該在哪呢?通過常識我們應該知道,此時P點位置離A點更近一些,如下圖:

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

那麼如果

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

 > 0,

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

 = 0 呢?那不就變得擔子一邊沒有重物,我們隻需要扛有重物的那一邊了,即P在A點上,如下圖:

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

既然可以等于0了,那麼能不能等于負數呢?即 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

 > 0,

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

 < 0,P會在哪呢?之前說 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

 和 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

 代表的品質,那麼我們怎麼了解負數的品質呢,我們知道挑擔子的時候品質會造成向下的重力,那麼負數的品質我們可以了解成在B點有一個向上的力,等于有人在擔子的一邊幫你搭把手,那就變成不是挑擔子了,而是兩個人擡東西了。兩個人要用棍子擡一個東西,那麼東西自然是在兩個人中間了,是以P會在A的左邊,如下圖:

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景
圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

 或 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

 某個值小于0的情況,也就把我們的P的位置從線段AB拓展到直線AB上了。當然了,我們不能

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

 < 0,

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

 < 0,這樣擔子就飛起來了。

上面的例子說明了隻要确定了

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

 和

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

 的值,也就确定了 重心P 的位置,怎麼樣是不是和前面所說的很像?事實上,隻要保證 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

, 我們的 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

 就是前面所說的 j 的值,而 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

 就是 k 的值,是以稱這樣的坐标為重心坐标。

三角形上的重心坐标

定義

與直線上任意一點滿足 P = jA + kB 一樣,在三角形ABC所在平面上的任意一點P同樣滿足

P = iA + jB + kC

i + j + k = 1

那麼P用 (i, j, k) 的方式表示,就是在三角形上的重心坐标。同樣的,因為重心坐标是由三角形的三個頂點所定義的,是以不同的三角形有各自的重心坐标。

同樣的,若點P要在三角形内部或邊上,需要滿足 i >= 0,j >= 0,k >= 0,否則點P在三角形所在平面外。

同樣由于 P = (i+j+k)P = iP+jP+kP,是以我們可得到 iA+jB+kC-iP-jP-kP = 0 即:

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

和直線比喻成擔子類似,對于三角形也是一樣的,我們可以假設有個三角形,它本身是沒有品質的,但是我們在它的三個頂點位置分别懸挂了不同品質的物體,如果我們能找到其中一個點,能夠使三角形保持平衡,那麼這個點就是三角形的重心,如下圖。

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

三角形和直線的關系

我們将三角形ABC的某個頂點(例如C)和三角形内任意一點P連線,并衍生到三角形的某條邊上,設交點為D,如下圖:

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

那麼D點在AB上的位置,我們不就可以用直線的重心坐标表示麼,我們設:D = xA + yB,其中 x + y = 1

知道D點坐标後,那麼P點在CD的坐标我們又可以用直線的重心坐标表示,我們設:P = wC + zD,其中 w + z = 1

把D帶入得:P = wC + z(xA + yB) = zxA + zyB + wC,而 zx + zy + w = z(x + y) + w = z + w = 1

那麼設 i = zx,j = zy,k = w,不就證明了 P = iA + jB + kC 成立。

解i,j,k的值

接下來,我們來看看i,j,k三個值怎麼計算,因為 i+j+k=1,是以k=1-i-j,也就是隻要求兩個未知數i和j即可。那麼我們隻需要找到兩個方程組,解二進制一次方程式即可。

因為 P = iA + jB + kC 是以 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

,從中我們就可以取得兩個方程式:

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

注:取x,y的話,也友善在二維空間中了解,當然也可以去x,z或y,z去計算。

解得

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

去 i ,得

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

此時方程式中隻有一個 j 是變量,我們繼續解,得

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

解得

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

解得

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

去分母,解得

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

即可求得 j 的值:

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

同理可解的 i 的值:

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

至于k的值,1-i-j 即可。

幾何意義

我們将點P和三個頂點分别連線,可以得到三個新的三角形,如下圖:

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

我們設三角形的總面積為 s,三角形PBC的面積為 a,三角形PAB的面積為 c,三角形PCA的面積為 b,那麼可得:

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景
圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景
圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

也就是說重心坐标和每個頂點所相對的三角形(例如A對應的是PBC)的面積比有關。

我們來簡單的推導一下:

前面我們知道

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

而 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

 的值,不就是 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

 的x值麼,我們标記為 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

,其他項也同理,那麼我們可以得到

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

不知道大家對上面的這種 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

式子熟不熟悉,它正是二維向量叉乘的模(不熟悉的可以看下叉乘相關知識)。是以我們可以得到

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

設夾角CBP為 α ,那麼分子 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

 ,同理分母就是三角形ABC的面積,是以 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

 成立,其他也同理。

三角形的重心

我們知道三角形的重心點為三條中線的交點,如下圖:

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

中線即是将三角形分成面積相等的兩部分,例如 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

我們來看下O點的重心坐标是多少,根據前面,我們知道我們可以通過三個三角形 AOB,AOC,BOC的面積比來求得重心坐标。那麼我們就來看看這三個三角形的面積比。

首先因為 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

 而他們的高相等,是以 BD = DC,可得 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

,那麼 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

 。同理我們可得

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

是以三角形的重心坐标即為 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

。同樣的,關于重心O點的坐标我們可以通過下面公式計算:

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

實際應用場景

前面哔哔賴賴了一大堆,我們知道可以通過重心坐标來計算三角形内某點的坐标,即

P = iA + jB + kC

ABCP代表的都是位置資訊,我們可以通過位置資訊求出重心坐标。而重心坐标牛逼就牛逼在,我們可以把ABCD的資訊用别的任何資訊來代替,例如顔色,法線,uv,深度等,然後套用上面的公式即可求出P點對應的屬性。

例如我們A點紅色(1,0,0),B點綠色(0,1,0),C點藍色(0,0,1),那麼三角形内任何點的顔色就等于它的重心坐标,例如重心點顔色為 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

我們可以簡單的用Unity寫個demo驗證一下

首先用下面腳本繪制一個三角形,三角形内部的顔色Unity已經為我們插值好了

[ExecuteInEditMode]
public class Triangle : Graphic
{
    Vector2 positionA = new Vector2(70, 40);
    Vector2 positionB = new Vector2(100, 100);
    Vector2 positionC = new Vector2(40, 70);
    
    protected override void OnPopulateMesh(VertexHelper vh)
    {
        vh.Clear();
 
        vh.AddVert(positionA, Color.red, Vector2.zero);
        vh.AddVert(positionB, Color.green, Vector2.zero);
        vh.AddVert(positionC, Color.blue, Vector2.zero);
        vh.AddTriangle(0, 1, 2);
    }
}
           

效果如下(注意color space要使用gamma的):

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

然後怎麼驗證呢,我們可以創個小Image,然後通過它的坐标和三個頂點的坐标,我們就可以計算出小Image所在點對應的重心坐标,知道重心坐标和三個頂點顔色後,就可以計算出對應顔色,指派給小Image,然後對比下顔色即可。代碼如下:

using UnityEngine;
using UnityEngine.UI;

public class NewBehaviourScript : MonoBehaviour
{
    public Image self;
    
    Vector2 a = new Vector2(70, 40);//red
    Vector2 b = new Vector2(100, 100);//green
    Vector2 c = new Vector2(40, 70);//blue
    
    void Update()
    {
        Vector2 p = transform.position;

        float i = (-(p.x - b.x) * (c.y - b.y) + (p.y - b.y)*(c.x - b.x)) /
                  (-(a.x - b.x)*(c.y - b.y) + (a.y - b.y)*(c.x - b.x));
        float j = (-(p.x - c.x) * (a.y - c.y) + (p.y - c.y)*(a.x - c.x)) /
                  (-(b.x - c.x)*(a.y - c.y) + (b.y - c.y)*(a.x - c.x));
        float k = 1 - i - j;
        Debug.Log($"({i}, {j}, {k})");

        self.color = new Color(i, j, k);
    }
}
           

效果如下:

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

可以看出在三角形内部時,我們計算得到的顔色和Unity做好的插值是一樣的。

至于除了顔色外的其他屬性插值,原理也都是一樣的,隻要了解重心坐标了即可。也就是說我們隻需要先通過四個點的位置資訊算出重心坐标,然後就可以通過重心坐标來計算其他屬性的插值。

重心坐标與投影

前面一套套下來,我們可能會有個疑惑,重心坐标的計算和z軸沒有關系麼?

注:其實更準确的說法是隻和x,y,z中其中任意兩項有關,具體可以看求i,j,k時,我們取的二進制一次方程式是哪兩個軸,當然通常情況下,就是取的x和y。

不考慮z,等于把空間中的三角形去掉z,即投影到平面xy上,即原本的A點 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

,B點 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

,C點 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

變成了A'點 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

,B'點 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

,C'點 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

。原本空間中三角形内的P點

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

,同樣投影變成了 P' 點 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

 。那麼投影前後,P和P' 的重心坐标一樣麼?答案是一樣的!

公式沒考慮z其實就已經告訴我們答案了,那麼幾何上,我們怎麼了解呢,我們可以看個最簡單的例子,就是重心。

我們假設下圖中的三角形是空間中的三角形,也就是ABC的z軸值不同,重心點O的重心坐标自然是

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景
圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

那麼我們看看投影後還是不是

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

就可以了。

很簡單,我們先來看邊BC的投影,如下圖,我們在yz平面看邊BC的投影

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

可以發現投影後 D' 依舊是 B' 和 C' 的中心點(相似三角形原理),也就是說投影後的直線 A'D' 是三角形 A'B'C'的中線。其他中線同理,是以投影後 O' 的還是三角形A'B'C'的重心,其重心坐标還是

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

但是!有一種投影不行,就是透視投影,依舊是上面的三角形的邊BC,我們來看看透視投影會發生什麼,如下圖:

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

很明顯我們就可以看出來,此時 D' 不再是 B' 和 C' 的中心點。當然了,數學不能光用眼睛看,我們需要推導

為了友善計算,我們設O點為原點,O到投影螢幕的距離為 l (如上圖所示),根據相似三角形可以得到:

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

,即:

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

。同理可得 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

由于D是BC的中心點,根據直線的重心坐标我們可以知道 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

 ,

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

,帶入可得:

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

,而投影後B'C'的中點的y值應該是 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

,可以發現和 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

并不相等。但是有個前提,那就是 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

,否則 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

,上面的式子依舊相等。用圖來看的話更直覺,如下圖(依舊是相似三角形):

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

emmm,好像直接看點D的重心坐标是否改變比看重心的更友善。

而且三角形重心坐标的這個變化同樣适用于直線的重心坐标,事實上我們的舉例就等于在看直線的重心坐标變化。

是以可以得出結論,在空間中的三角形或直線内的某個點,在投影變換前後,其的重心坐标可能會發生改變。是以有些計算,例如深度,一定要在投影變換前做,否則得到的結果可能是不對的。

矯正

但是前面那樣太麻煩了,我們可不可以直接在知道變換前的重心坐标推出變換後的重心坐标,或者反過來呢?當然可以。

我們先從直線的重心坐标投影矯正開始,直接使用之前的圖,如下:

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

此時D不再是BC的中心點了,而是當做BC中的任意一點。根據直線的重心坐标我們可以設: D = iB+(1-i)C,D的重心坐标即為(i, 1-i)。直線BC通過透視投影後得到直線B'C',點D變為D',我們知道透視投影後,重心坐标的值會變,是以我們設:D' = jB'+(1-j)C',D'的重心坐标即為(j, 1-j)。

那麼我們隻需要知道 i 和 j 的相對關系,不就可以在隻知道 i 或 j 中一個的情況下推出另個的值了麼?例如,我們假設 i = 2j,那麼投影前的重心坐标 (0.6, 0.4)在投影後自然變成的了(0.3, 0.7),或者說投影後的重心坐标為(0.1, 0.9),那麼投影前就是(0.2, 0.8)。這樣即使碰見投影變換,我們也可以通過變換後的重心坐标去推導出原本的重心坐标,不用再通過逆變換去求原本的重心坐标了。

當然前面 i = 2j 是我們瞎雞兒說的,我們來看看真正的值是多少。

根據直線的重心坐标,我們可以很容易求得 j 的值: 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

 (其實 i 的值同樣可以直接算出來,然後和 j 一除就知道了,但是我們這邊要推導出一個更簡單的公式)。

通過相似三角形可以得到:

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

 ,

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

,帶入 j 中可得:

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

 。

我們先來看分子項,即 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

,我們知道 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

 ,

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

,帶入分子中,得到:

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

化簡可得:

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

其中的 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

 不就是分母中的那部分嘛,即可抵消掉,j 就可以簡化為:

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

從這個式子也可以看出,z值相同時,則 i = j,重心坐标不變。也說明了之前一大串的 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

 的值其實就是 i 。

做了個簡單的驗證,如下圖,D點的重心坐标确實正好從 (1/3, 2/3) 變成了 (1/6, 5/6)。

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

接下來我們來講講三角形的重心坐标投影矯正

前面我們得到 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

 ,那麼三角形内任意一點P,我們可以看作是AD上的任意一點,我們設 P = wA+(1-w)D,投影後w會變為z,套用上面的公式,我們可以得到

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

因為P = wA+(1-w)D,D = iB+(1-i)C,是以 P = wA+(1-w)(iB+(1-i)C),即:

P = wA+(i-iw)B+(1-i-w+iw)C

也就是P的重心坐标為(w, i-iw, 1-i-w+iw) 後面兩項看着很複雜,我們先不管,寫成 (w, ?, ?),那麼我們就知道投影後重心坐标會變為 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

 。

那後面兩個怎麼算呢?既然我們可以把D看成是BC上的一點,P是AD上的點,那麼是不是可以再把D看成AB或AC上一點,P則是CD或BD上一點來推導上面的公式。

這樣我們又會得到 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

  和 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

是以得出結論,假設在透視投影前,P在三角形ABC的重心坐标為(i, j, k),那麼投影後該坐标會變為 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

,而 

圖形學基礎知識:重心坐标(Barycentric Coordinates)前言直線的重心坐标三角形上的重心坐标實際應用場景

 。

繼續閱讀