3D数学相关

这两天有机会重新翻翻之前看过的3D数学方面的书籍,下面简单介绍一下3D数学要点和我的学习轨迹。

 

和很多人一样在刚刚开始接触3D方面的东西时并不是直接看3D数学,毕竟也不是计算机专业出身,没学过计算机图形学。最开始仅仅是找一些关于OpenGL的书籍来看,这些书大多数都是手册性质的(包括什么红宝书之类的),然后照猫画虎照葫芦画瓢照着例子把代码桥进取,这样经过短暂的联系基本上了解了OpenGL,更确切地说是了解了OpenGL绘图常用的那几个函数。接下来动手改改(什么glTranslate,glRotate, glScale什么的),这时问题出现了,经常是该了之后看不到画出来的东西,或者不是自己想象的。问题出在那,那就是3D数学的问题。很多刚刚接触3D的人没能走得更远或者中途放弃了,就是因为遇到了这第一道拦路虎——3D数学。3D数学是没一个图形程序员必须要掌握的,不能熟练的运用在后面会遇到很多问题,同时也决定你的3D水平也只能停留在简单的API调用阶段。

 

好了,言归正传,接下来简单介绍一下3D数学,这里并不想照本宣科的列出各种公式,而是提示各种要点。

从实际项目开发来讲,一般都有现成3D数学库可用,即使没有也可以在网上找到开源的代码,如果在是没有,最不济了找本3D数学方面的书籍,把它上面的公式coding一下也解决了,而且这样的工作基本上就只做一次。

 

下面列出一些需要注意的地方

1. 在那到一个3D引擎或者自己构建3D引擎时首先要搞清楚它的坐标系,左手系还是右手系,她调用的图形API使用的是那个坐标系,如果引擎坐标系和图形API坐标系不一致,这时需要注意以下它的转换,以及开发时直接面对的坐标系。

 

2. vector/position,从形式上看他们都是(x,y,z),但是他们的意义不同,position表示的就是一个空间位置他是相对于(0,0,0)点的,而vector表示的是一个方向,并且有自己的长度,它可以相对于任意一点。

 

3. vector的dot和cross,需要注意的是dot得到的是一个数值,而cross得到的是一个向量,向量的方向取决于坐标系,也就是符合左手定责还是右手定责。

 

3. 矩阵的左程右程,首先矩阵的乘法不满足交换率,因此左程和右程是不一样的。这里讲讲为什么OpenGL要把先进性的变换写在后面。

首先来看一下GL的矩阵形式如下,它是列优先,也就是把平移量放在了第四列,这样他在和向量相程的时候是右程向量。

(从这点可以看出从数学的角度来讲矩阵到底是左程还是右程,关键是看矩阵的平移量放在第四列上还是第四行上,这也是在即知道引擎坐标系之后第二个需要明确的问题)

 -                              -       -

| m00, m01, m02, tx |    |x|

| m10, m11, m12, ty | * |y|

| m20, m21, m22, tz |    |z|

| m30, m31, m32,  1 |    |0|

 -                              -      -

在向量与矩阵相程的时候与向量最近的矩阵是首先变换的也就是说mtxTranslate*mtxRotate*mtxScale*vertex,这代表着顶点变换顺序是Scale->Rotate->Translate。而OpenGL的glTranslate,glRotate,glScale的这些函数他们是把变换矩阵右程到当前的变换矩阵上的。为代码如下

glRotate(axis, angle)

{

    matrix mtxRotate(axis, angle);

    mtxTransform = mtxTransform*mtxRotate;

}

这便是为什么GL中越是先进行的变换在写程序的时候越要写在后面的原因。

 

这里引申说一下,为什么GL使用列优先,那是因为GL的矩阵实际上是一个float[16]得数组,使用列优先可以保证在矩阵于向量相程时矩阵的行向量在内存上是连续的,这样可以提高缓冲命中率。

 

5. 矩阵的几何意义,矩阵的几何意义就是一个坐标系,更具体地说是一个定义在变幻前坐标系中的变幻后坐标系,很难想象是吧。以OpenGL的矩阵为例它的第四列就是这个坐标系他的前三列分别是这个坐标系的x,y,z轴的向量。如何获得?很简单

axisX = matrix*vector(1,0,0)

axisY = matrix*vector(0,1,0)

axisZ = matrix*vector(0,0,1)

 

6. 四元数,四元数这个东西其实没必要深究,只要知道从几何上讲他表示的是一个轴角,他在级联的时候都是右程没有左程,这是因为四元数本身没有什么坐标系。

 

7. 向量与四元数的区别,他们都可以表示方向,但显然向量要比四元数少了一个纬度,这个纬度就是四元数除了能够表示所面对方向还表示了在这个方向上的绕州旋转。

 

8. 旋转矩阵于四元数,它们之间是可以相互转换的。这里要讲的不是如何转换,而是要注意旋转矩阵和四元数都是一个相对量,他们仅表示一个旋转的量,比方说旋转45度,如果从0读开始旋转那么结果就是45度,如果从15度开始旋转,那么结果就是60度。可以看出他们表示的旋转了多少。

 

在掌握这些基本概念之后才能进行更复杂的3D变换,比如镜像等。

 

 

接下来说一下如何构造自己的数学函数库,以及需要注意的地方

正如前面所说,现在网上已经有很多现成的代码,如果你已经是一个老手了,那么直接拿过来用,看清楚坐标系,在看清楚左程右程就行了。如果是一个新手那还是老老实实找本书照着书把公式桥进去多加联系。

在构造自己的数学函数时一定要注意运算效率,数学库算是底层运算性的库。如果用类来实现(比如 class CVector等),那么别些什么get,set之类的,没有必要,而且极大影响效率,能用inline就用。有些计算在不要求高精度的前提下通常有快速算法。

我个人的数学库实际上是一个函数库,没有使用类,而且所有函数都inline

 

 

就这些,欢迎批评指正

 

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值