这两天在准备面试,然后复习了下数学的东西,好多东西以前基础不好,就是走马观花的看一下,过了一段时间立马就忘记了,索性记下来的好。这里的3D空间都是右手坐标系,向量为列为主
一,法线变换乘WorldView矩阵的逆的转置
肯定不是直接乘worldView矩阵了,推导其实很简单,(像我这样脑子不行的只能看完了感慨了)设原mesh上一个顶点为v,其法线为n,WorldViewMatrix为Mwv,那么在object space里,满足v dot n == 0,以此我们可以换个形式表示,也就是(v)T * n == 0, (1x4和4x1的矩阵相乘实际就是点乘了),那么在变换之后,设变化后的顶点为v',变换后的法线为n',那么同样也需要满足这个条件,
(v')T * n' == 0, 而v' = Mwv * v,
代入=> (Mwv * v)T * n' == 0 => vT * MwvT * n' == 0, 而n'等于Mn * n(我们要求的),
=>vT * (MwvT * Mn )* n == 0 ,而(v)T * n == 0, 那么中间的(MwvT * Mn )== I => Mn = (MwvT)-1,而因为方阵(当然得有逆的情况。。)的逆的转置等于转置的逆,所以就能证明出来咯~。我刚想了下,应该行为主的结果也是一样的,这里错了话,望纠正。
二,判断点是否在三角形内准备笔试的时候正好看到这道题,以前在ogre代码里也看到过,但原理没深究过,google中文搜了下,貌似没什么讲的很好的,英文一搜就搜到了很多非常详细的。这里就做个整理吧,省得和我一样的搜两次了~~。设三角形ABC,点为P,(向量我就写成行形式了~)
1,面积法,基本上是最直接低效的,点P如果在三角形内,则分割的三个三角形面积和等于ABC面积,这个不说了。
2,网上最常见的,所谓的2D叉乘法,实际上叉乘是不存在于2D空间的,只存在于3D和7D(!。。这个没细看。反正wiki还是哪里看到的),但2D空间里我们可以用一点小技巧,就是假设一个垂直于xy平面的z轴,那么2D平面的z值则一直为0,设 向量B-A为V1(x1,y1,z1),向量P-A为V2(x2,y2,z2),根据3D叉乘公式,(x1,y1,z1) X (x2,y2,z2) = (y1z2 - y2z1, x1z2-x2z1, x1y2-x2y1),由于z为0,那么x,y则为0,所以实际2d叉乘值就是z值,其实我们得到的还是一个向量,它垂直于我们2d空间的xy平面,不管是顺时针还是逆时针,我们只要按一个方向同样再对另外两边做同样的叉乘,只要得到的这三个值符号一致,这就说明点P在三角形三边的同一侧,也就是在三角形内了,其实再想想,只需要确定在两条边的同侧,那么就是在三角形内了。
3,重心法,从二维空间上看,我们可以把p当乘以以三角形一个顶点的两条边向量乘以两个标量权重的和,设这两个权重为u,v,只要u,v大于0,且和小于1,那么P就在三角形内,所以我们下来就是求出u,v了:
=>P = A + u * (C - A)+ v * (B - A), u,v这也就是三角形的重心坐标系坐标,这就是个二元一次方程,这里我们化简下,设P-A为v2, C - A为v0,B - A为v1,
=>v2 = u * v0 + v*v1, 乘v0,v1我们就能得到两个方程
=>v2 * v0 = (u * v0 + v*v1)* v0, (1)
v2 * v1 = (u * v0 + v*v1)* v1, (2)
略化简。。
=>u = ((v1 * v1)(v2 * v0) - (v1 * v0)(v2 * v1))/(((v0 * v0)(v1 * v1) - (v0 * v1)(v1 * v0))
v = ((v0 * v0)(v2 * v1) - (v0 * v1)(v2 * v0))/(((v0 * v0)(v1 * v1) - (v0 * v1)(v1 * v0))