Normal Transformation(法线变换)
2015-12-31 10:42
253 查看
http://blog.csdn.net/bugrunner/article/details/7285356
关于三维空间法线变换的问题,之前就有看到过,但是一直也木有注意,普通的三维空间中的法线变换还是直接使用模型的变换矩阵来进行。但是,近来又看到了一些这方面相关的东西,因而总结一下。
已经知道不能直接用模型变换矩阵来变换Normal,比如使用某含有非一致性缩放(在x,y,z方向上进行不程度的拉伸)的变换矩阵来变换一球体,则可能得到如下列图示的结果:
左图为原始球体及其表面上的法向分布(2D投影后);中间为直接使用变换矩阵操作后的法向分布,但注意其明显与表面不垂直;右图为正确变换后的法向分布。
为什么直接变换不正确呢?网上有多种说明版本,但是对比了一下感觉还是PBRT上的解释比较好一些。这里假设某一点处的法向量为n,切向量为t,由两者在曲面上的垂直关系可知:
如果对于模型进行空间变换的矩阵为M,变换后在该点得到的新的切向量为
,那么可得
(这里假设切向量并不是由变换矩阵计算得到的,而是直接通过对模型表面进行几何分析计算得到的);变换后在该点得到新的法向量为
,若是得到的正确法向量,则其必定仍然与切向量垂直。假设正确变换得到的法向量是在变换矩阵S下进行的,那么有
,由法、切的垂直关系得:
在上式的最后阶段中可以看出,如果要满足成立条件则有
,直接变换即可得
,所以也就有:
这里就得到了通常我们所说的采用逆的转置矩阵来代替原始变换矩阵来对法向量进行操作。
上述推导中使用的一个依据是切向量与法向量之间的垂直关系,其实这是建立在另外一个基础上,那就是:切向量的计算一般是直接使用顶点与UV来进行,这样的话它就是直接与顶点相关,因而只要直接使用变换矩阵得到的顶点正确那么在此基础上计算而来的切向量也就正确,但是法向量却不是直接通过顶点计算、而是通过变换得到的(当然,如果Normal 也在网格顶点变换之后直接计算,而不是对原始的法向量用变换矩阵作空间变换的话就不会存在这一问题了)
另外,在实际操作中对于变换矩阵(一般为4x4的)并不一定可逆(比如一个由3D到2D的投影矩阵),因而上述S就没法计算,这种情况下更安全的一种方法是只使用原始4x4变换矩阵的左上角3x3矩阵,即不考虑平移部分,其实这也理所当然,平移操作本就不影响法向量。这一部分在Realtime Rendering中也有稍详细的说明。
当然,使用逆的转置来进行Normal变换只是正确方法的一种,不过也有其它的方法,比如从一个变换矩阵中只抽取出Rotation的部分来施加到Normal上,这样就免去了Translation和Scale的影响。矩阵的R, T, S分解也有很多经典的方法,可以参考一个这个帖子:http://www.gamedev.net/topic/441695-transform-matrix-decomposition/(虽然这种方法的效率与复杂度需要另外讨论,但毕竟也是一个途径)
不过一般情况下,我们对于场景中三维模型的变换基本上都是进行三向一致的缩放操作,这样的话M就是一个正交的矩阵,如此一来就有S等于M,因而直接使用M对法向量作变换也不会有什么问题出现(或者有差别也被忽略了^_*)。不过任意的缩放变换是建模工具的一个基本需求,因而在做工具时需要重视这一问题。
关于三维空间法线变换的问题,之前就有看到过,但是一直也木有注意,普通的三维空间中的法线变换还是直接使用模型的变换矩阵来进行。但是,近来又看到了一些这方面相关的东西,因而总结一下。
已经知道不能直接用模型变换矩阵来变换Normal,比如使用某含有非一致性缩放(在x,y,z方向上进行不程度的拉伸)的变换矩阵来变换一球体,则可能得到如下列图示的结果:
左图为原始球体及其表面上的法向分布(2D投影后);中间为直接使用变换矩阵操作后的法向分布,但注意其明显与表面不垂直;右图为正确变换后的法向分布。
为什么直接变换不正确呢?网上有多种说明版本,但是对比了一下感觉还是PBRT上的解释比较好一些。这里假设某一点处的法向量为n,切向量为t,由两者在曲面上的垂直关系可知:
如果对于模型进行空间变换的矩阵为M,变换后在该点得到的新的切向量为
,那么可得
(这里假设切向量并不是由变换矩阵计算得到的,而是直接通过对模型表面进行几何分析计算得到的);变换后在该点得到新的法向量为
,若是得到的正确法向量,则其必定仍然与切向量垂直。假设正确变换得到的法向量是在变换矩阵S下进行的,那么有
,由法、切的垂直关系得:
在上式的最后阶段中可以看出,如果要满足成立条件则有
,直接变换即可得
,所以也就有:
这里就得到了通常我们所说的采用逆的转置矩阵来代替原始变换矩阵来对法向量进行操作。
上述推导中使用的一个依据是切向量与法向量之间的垂直关系,其实这是建立在另外一个基础上,那就是:切向量的计算一般是直接使用顶点与UV来进行,这样的话它就是直接与顶点相关,因而只要直接使用变换矩阵得到的顶点正确那么在此基础上计算而来的切向量也就正确,但是法向量却不是直接通过顶点计算、而是通过变换得到的(当然,如果Normal 也在网格顶点变换之后直接计算,而不是对原始的法向量用变换矩阵作空间变换的话就不会存在这一问题了)
另外,在实际操作中对于变换矩阵(一般为4x4的)并不一定可逆(比如一个由3D到2D的投影矩阵),因而上述S就没法计算,这种情况下更安全的一种方法是只使用原始4x4变换矩阵的左上角3x3矩阵,即不考虑平移部分,其实这也理所当然,平移操作本就不影响法向量。这一部分在Realtime Rendering中也有稍详细的说明。
当然,使用逆的转置来进行Normal变换只是正确方法的一种,不过也有其它的方法,比如从一个变换矩阵中只抽取出Rotation的部分来施加到Normal上,这样就免去了Translation和Scale的影响。矩阵的R, T, S分解也有很多经典的方法,可以参考一个这个帖子:http://www.gamedev.net/topic/441695-transform-matrix-decomposition/(虽然这种方法的效率与复杂度需要另外讨论,但毕竟也是一个途径)
不过一般情况下,我们对于场景中三维模型的变换基本上都是进行三向一致的缩放操作,这样的话M就是一个正交的矩阵,如此一来就有S等于M,因而直接使用M对法向量作变换也不会有什么问题出现(或者有差别也被忽略了^_*)。不过任意的缩放变换是建模工具的一个基本需求,因而在做工具时需要重视这一问题。
相关文章推荐
- Bent Normal (环境法线?)
- spring获取request对象的方式与条件
- vs2015编译gdal出错及解决方案
- Highcharts
- 《需求分析与系统设计》读书笔记3
- DIV水平和垂直居中
- maven_myeclipse_初始化
- HBase 系统架构
- Hikari连接池DEMO
- 关于配置weblogic密匙库信息、SSL,启用HTTPS、禁用HTTP的相关配置文档说明
- Android各国语言对照表
- 基于FBX SDK的FBX模型解析与加载 -(四)
- UILabel 自动换行 及 高度自适应
- Android webview如何上传文件和添加进度条
- 手游动效之美(一)
- java过滤html标签
- Android开发之项目初建时设置minSdkVersion,maxSdkVersion,targetSdkVersion,compile作用
- 程序员最恐怖的噩梦是什么?
- 基于FBX SDK的FBX模型解析与加载 -(三)
- java.lang.NoSuchMethodError: javax.servlet.http.HttpServletRequest.isAsyncStarted()Z 的解决