仿射变换下的法向量

问题原址:http://topic.csdn.net/u/20080309/16/64b1e2e5-44af-4307-919c-45ead95e69c6.html?seed=1048831947&r=60114068#r_60114068

 

根据原题,这个是顶点着色中常见的问题。

1楼Jiana关于这个说的很明确:“法线不是一般概念的真正向量”。这句话的本意是对的,就是平面(或切平面)的法线不能简单的通过仿射变换矩阵直接得到变换后空间的法线,但并不是像从字面上理解,法线(法向量)就不是向量了。

 

其次链接中讨论了法向量方向的确定,经过下面论证可以发现,还是有必要进行一番工作的。长话短说,以下就交给数学了,所有的算式未加说明采用matlab符号,但等号用'='表示。

 

一般三维平面向量方程:

dot( (p - p0), n )  = 0

但是仿射空间延拓到四维,内积就不为0了,但也不能轻易写dot( (p - p0), n )  = 1,因为这样解出来的显然不是所需要的平面(即使n和p0都归一化),因为这增加的一维增加了自由度。另一方面,仿射空间向量减法不是一般的四维向量减法,它必须在归一化只做后前三分量相减,我们只能记: p[-]p0和n正交,其中[-]表示这种特殊的减法。

 

假设仿射变换为A,

A =

   a11 a12 a13 a14

   a21 a22 a23 a24

   a31 a32 a33 a34

     0   0   0   1

那么经过变换后发现和平面交点p0变为A*p0,平面上任一点p变为A*p,变换后平面的法向量设为m,显然要求有:

A*p [-] A*p0和m正交。设p0和p都是归一化的(以下向量不加说明均为归一化的),并令e4 = [0 0 0 1]',于是有:

A*p [-] A*p0= A*p - A*p0 + e4 = A*(p-p0) + e4 = Ah*(p [-] p0)

其中Ah是A的去除平移分量版本,即a14,a24和a34为0的A。

这样就有:Ah*(p [-] p0)和m正交。令A3=Ah的3x3主子式,p3、n3和m3分别是(p [-] p0)、n和m的的前三分量构成的三维分量(退化的三维向量),根据Ah的性质,可以发现这个正交和前一个正交分别等价于:

(A3 * p3)' * m = 0,p3' * n = 0

上述方程组的解包括:

m = inv(A3)'*n或m = -inv(A3)'*n

上述过程的意义是p [-] p0(即切向量)在仿射变换中应退化到3维空间讨论(与平移无关)。

 

需要注意,其中一个解只保证了和平面的垂直,但是没有保持法向量原有的方向。例如原先在曲面外侧的法向量在变换后应当仍保持在外侧。

法向量的方向保持只有通过以切向量内积求法向量达成。这个过程非常繁琐,而且我们本身知道的是法向量而并没有从切向量出发,因此我们在此只是构造一下,通过比较以找出这个保持方向的正负号。

 

所谓切向量集就是满足平面方程的p [-] p0,我们取其中两个线性无关的分别记做u和v,根据上面讨论,在三维空间中讨论,仿射变换后,他们变为A3*u和A3*v。规定平面法向量是已定的一对切向量的外积,即cross(u,v),这样变换后的法向量为cross(A3*u, A3*v)。下面对这两个外积进行展开,这个过程相对比较繁琐。

n = cross(u, v) = [u2*u3 - u3*v2, u3*v1-u1*v3, u1*v2-u2*v1]'

m = cross(A3*u, A3*v) = [(a2*u)*(a3*v) - (a3*u)*(a2*v), (a3*u)*(a1*v), (a1*u)*(a2*v)-(a2*u)*(a1*v)]'

其中a1、a2和a3分别为A3的第1、2和3行。

简便起见,我们只对m的第一个分量进行展开:

(a2*u)*(a3*v) - (a3*u)*(a2*v)

=  (a21*u1 + a22*u2 + a23*u3)(a31*v1 + a32*v2 + a33*v3)
 - (a21*v1 + a22*v2 + a23*v3)(a31*u1 + a32*u2 + a33*u3)

=  (a22*a33 - a23*a32) * (u2*v3 - u3*v2) 
 + (a23*a31 - a21*a33) * (u3*v1 - u1*v3) 
 + (a21*a32 - a22*a31) * (u1*v2 - u2*v1)

 

再来看算式inv(A3)'*n的展开:

inv(A3)' =  

   1    [ M11 -M12  M13]

------- [-M21  M22 -M23]

det(A3) [ M31 -M32  M33] 

这样,撇开最前面的系数,inv(A3)'*n的第一个分量为:

M11*(u2*v3 - u3*v2) - M12*(u3*v1 - u1*v3) + M13(u1*v2 - u2*v1)

M11 = a22*a33 - a23*a32

-M12 = a23*a31 - a21*a33

M13 = a21*a32 - a22*a31

在预料之中,这个结果和上述的第一分量一致。

但最终inv(A3)'*n和上述的结果相差1/det(A3)系数,我们这里关心正负性,因此在inv(A3)'*n之前需要补偿det(A3)的符号。

因此最终在仿射空间中,这个方向纠正的法向量可以通过 sign(det(Ah))*inv(Ah)'*n得出。

 

 

 

 

 

你可能感兴趣的:(仿射变换下的法向量)