首先先从Bezier说起:
一条直线上有两个端点,P0和P1,那么直线可以写成 y = kx+b ,其实也就是P(t) = (1-t)P0 + P1 (这是个插值函数),(小注,我时常把这两个东西系数写反,其实代入0和1就不会弄错了)T的值范围定义为[0,1]的话,就是这线段上所有的点了(集合)
当然P是(x,y)或(x,y,z)是向量,(1-t)和t是权(高中时候和另外一个同学被椭圆和直线之类的题目折磨的痛不欲生,后来发现了公式,不过自己忘了,反正很有意思的,快速求解数学题目…..)
两个点可以定义一条直线,曲线是什么了,利用微积分的思想,曲线是无穷直线的集合.如何通过几个点,给上0-1的参数求出位于这条曲线上的其他点了?还是老办法,插值.Paul De Casteliau发明了插值方法,是三个点的,加速有P1,P2,P3三点,一方面,我们希望这三个点都应该影响插值后点,但是上面那个式子只是两个点的,于是我们两两求点,然后对中间结果再做插值是再显然不过的了
Temp1 = (1-t)P0+tP1 Temp2 = (1-t)P1+tP2 然后result = (1-t)Temp1 + t Temp2,这是一种很自然的想法,化简下这个式子,把P0,P1,P2整合到同一个式子中:
P(t) = (1-t)^2 P0 + 2t(1-t) P1 + t^2 P2
这是三个点,很显然的,我们可以以此类推,四个点,五个点,系数就是杨辉三角系数,或者C(m,n) ,(a+b)^n a是(1-t) ,b是t ,n是点数-1
(WORD文档不会输入公式,懒得从网上找图,n阶的就不写了)
然后代入t从0到1,生成了一系列的点,结果非常之好啊,如下图:
这东西就是Bezier曲线,这东西有个非常好的特性,假设我们要做对这曲线仿射变换(具体概念请搜索) ,那么有两种方案
第一种,变换原来的点,然后再来进行插值计算
第二种,变换插值计算后的点(数量变多了)
第一种是可行的,因为Bezier的特性保证了,具体证明可代入计算(代入证明即可)
前文已经说过,这只是一种很自然的想法,当然,还有别的插值方法 比如说我们可以利用系数的导数,这也是可行的!
学过高数忘得不太惨的同学,一定能记得求导(微分)出来就是切向量()
P(t)' = d/dt()(P(t)) ,当t=0和1时,分别是P0和P1的切向量(Bezier曲线的切向量)
假设有四个控制点的话,那么
P(0)' = 3(P1-P0)
P(1)' = 3(P3-P2)
我们可以利用这个导数(斜率不是吗) P1和P2可以分别通过P0和P3球
当然,这样球出来的曲线和Bezier曲线是一样的,只是式子不同(最终化简还是一样的)
最关键的是,我们可以自己选择 切向量的求法,比如说用Pi-1和Pi+1之间定义Pi处的切向量
同理,还有Bezier表面,(四个点) 在横向上求两次插值,然后对这两次插值的结果求插值(注意,这里有两个系数,横向用系数u,纵向用系数v)
同理,可以扩展为3X3的点4X4的点
前文已经说完,让我们进入正文,三角形怎么进行插值?系数又有几个了,有一种很自然的思维方式同样存在(重心坐标系)
P = uA+vB+wC; (u+v+w=1) (u,v,w为对应面积比(http://www.cnblogs.com/leohawke/archive/2014/03/08.html 此文已讨论重心坐标)
当定义非共面的三角形时,增加三个点即可(二阶) 三阶为下图这种, 三角形中也存在控制点
PN三角形(point-normal) 是采用Bezier三角形,加上了法线的考虑(来球控制点).假设三角形有三个点(每个点有自己的法线,通过球平均而来,所以可能是不同的)
假设改变上有一点P21 = 2/3 A + 1/3B 即在AB的1/3处,然后将P21投影至A处的切平面(A有切线Na),就可以得到一个控制点P210
切平面垂直于A点,且沿着Na 投影,其实也就是将向量 B-A/3 投影至Na上,我们可以得到投影长度,然后变可以得到在Na上的那部分
为什么要减,我是不清楚的(如图)
图上成的钝角,我们可以设V21 = - (Na*(B-A)/3)Na (钝角乘出来是负的,反之) ,于是控制点
P210 = P21+V21(P21 = 2/3 A + 1/3B)
还有一个控制点,系数自然是2/3,只不过法线是B的法线(更靠近B),同理可以新增加6个点.中间那个点就等于(所有新生成的点相加除以4 减掉 原来的除以6)
设V = A+B+C/3
设E = P210+P120+…./6 中心点P111 = E+ (E-V)/2
P下标的含义很有意思,就是Bezie三次曲线对应的幂 http://www.cnblogs.com/mikewolf2002/archive/2012/08/21/2648421.html 具体代码参加此文
构造法线并没有使用三阶公式,过于复杂,于是只需要生成三个新法线,对点和法线使用同样的参数进行插值就行了
生成控制法线用原来的平均值是个不错的想法,不过有时会造成错误.比如下图:
正确的法线应该是斜的才对,
我们可以求 P1和P2的法线(存在这样一个平面 Np = Norm(P1-P2) )然后将平均法线 视为一个入射光,法线是Np(入射平面是P1和P2所成平面)求出反射向量,即是我们要求得控制法线了
至于求反射,HLSL提供了内置函数