在數學的子學科數值分析里,B-樣條是樣條曲線一種特殊的表示形式。它是B-樣條基曲線的線性組合。B-樣條是貝茲(貝塞爾)曲線的一種一般化,可以進一步推廣為非均勻有理B樣條(NURBS),使得我們能給更多一般的幾何體建造精確的模型。
常數B樣條
常數B樣條是最簡單的樣條。只定義在一個節點距離上,而且不是節點的函數。它只是不同節點段(knot span)的標志函數(indicator function)。
線性B樣條
線性B樣條定義在兩個相鄰的節點段上,在節點連續但不可微。
三次B樣條
一個片斷上的B樣條的表達式可以寫作:
其中Si是第i個B樣條片斷而P是一個控制點集,i和k是局部控制點索引。控制點的集合會是的集合,其中
是比重,當它增加時曲線會被拉向控制點
,在減小時則把曲線遠離該點。
片段的整個集合m-2條曲線()由m+1個控制點(
)定義,作為t上的一個B樣條可以定義為
其中i是控制點數,t是取節點值的全局參數。這個表達式把B樣條表示為B樣條基函數的線性組合,這也是這個名稱的原因。
有兩類B樣條-均勻和非均勻。非均勻B樣條相鄰控制點間的距離不一定要相等。一個一般的形式是區間隨着插入控制點逐步變小到0。
關於插值與樣條的介紹請看:http://www.cnblogs.com/WhyEngine/p/4020294.html
核心代碼:
1 void YcBSpline::BuildWeights() 2 { 3 ClearWeights(); 4 5 for (Yuint i = 0; i < 4; i++) 6 { 7 m_splineWeights[i] = (Yreal*)malloc((m_subD)*sizeof(Yreal)); 8 m_tangentWeights[i] = (Yreal*)malloc((m_subD)*sizeof(Yreal)); 9 } 10 11 Yreal u, u_2, u_3; 12 for (Yuint i = 0; i < m_subD; i++) 13 { 14 u = (float)i / m_subD; 15 u_2 = u * u; 16 u_3 = u_2 * u; 17 18 // 參見"游戲編程精粹1"P331 19 m_splineWeights[0][i] = (-1.0f*u_3 + 3.0f*u_2 - 3.0f*u + 1.0f)/6.0f; 20 m_splineWeights[1][i] = ( 3.0f*u_3 - 6.0f*u_2 + 0.0f*u + 4.0f)/6.0f; 21 m_splineWeights[2][i] = (-3.0f*u_3 + 3.0f*u_2 + 3.0f*u + 1.0f)/6.0f; 22 m_splineWeights[3][i] = ( 1.0f*u_3 + 0.0f*u_2 + 0.0f*u + 0.0f)/6.0f; 23 24 // 參見"游戲編程精粹1"P333 25 m_tangentWeights[0][i] = (-1.0f*u_2 + 2.0f*u - 1.0f)*0.5f; 26 m_tangentWeights[1][i] = ( 3.0f*u_2 - 4.0f*u + 0.0f)*0.5f; 27 m_tangentWeights[2][i] = (-3.0f*u_2 + 2.0f*u + 1.0f)*0.5f; 28 m_tangentWeights[3][i] = ( 1.0f*u_2 + 0.0f*u + 0.0f)*0.5f; 29 } 30 }
切圖:
相關軟件的下載地址為:http://files.cnblogs.com/WhyEngine/TestSpline.zip
最后要注意的是:B樣條曲線不會經過其控制點。靠,我一直以為是經過的。因為B樣條是我唯一在項目中使用過的。我用它來平滑游戲中角色刀光所划出的曲面,不過這種細節也沒必要再去修改了。