码迷,mamicode.com
首页 > 其他好文 > 详细

游戏中的三维数学

时间:2015-08-31 10:10:53      阅读:186      评论:0      收藏:0      [点我收藏+]

标签:游戏   坐标系   三维数学   

一、点和矢量


(一)坐标系分类

  • 笛卡尔坐标系;
  • 圆柱坐标系;
  • 球坐标系;

通常来说笛卡尔坐标系是我们最常用的坐标系,但我们同样要根据不同的情况来选择合适的坐标系,例如我们在做一些环绕动画的时候,采用圆柱坐标系可以更简单。

在三维笛卡尔坐标系中又分为左右手坐标系,用左右手来方便做记忆,大拇指指向X轴,食指指向Y轴,中指指向Z轴,3指垂直即可建立模型。左右坐标系的转换只需要把一个轴转换,保留另外两个轴的方向不变即可。对于三维图形程序员来说,一般以左手坐标系工作,并且Y轴向上,X轴向右,Z轴远离观察者(摄像机朝向),因此在三维图形渲染至二维屏幕时,Z坐标的增加就会增加景深。

(二)矢量运算

  • 矢量与标量的乘法:
    通常矢量与标量相乘都是保留矢量的方向,对矢量的模进行缩放。当然每个轴上的缩放因子也可以不相同,即非统一缩放,可表示为矢量与缩放矢量的分量积(反射光量可以使用RGB色值的分量积来计算)。

    S x A = (SxAx, SyAy, SzAz)

  • 加减法:
    矢量加减法多用于合成运算,点与方向的运算。

    • 方向 + 方向 = 方向
    • 方向 - 方向 = 方向
    • 点 + 方向 = 点
    • 点 - 点 = 方向
    • 点 + 点 = 无意义

(三)模

矢量的模是个标量,表示矢量在三维空间中的长度。

(四)应用

  • 矢量加减法可以用来刷新运动物体每帧的位置;
  • 球体相交测试的时候用矢量减法,模以及浮点比较来进行判断(在进行模运算的时候,计算平方根通常是费时的操作,所以在不影响准确性的情况下应该尽量改用模的平);

(五)矢量乘法

矢量的乘法有很多种,游戏编程中常见的有2种:

  • 点积:
    两个矢量的点积结果是一个标量,为两个矢量中每对分量乘积之和。

    A · B = AxBx + AyBy + AzBz

    点积也可以写成两个矢量的模相乘再乘以两矢量夹角的余弦。

    A · B = |A||B|cosθ

    点积符合交换律,加法上的分配律,标量乘法的结合律。

    点击判定:点击非常适合用来判断两矢量是否共线或垂直,或测试两矢量是否大致在相同或相反方向。

    • 共线:(A · B) = |A||B| = AB
    • 共线但是相反方向:(A · B) = -AB
    • 垂直:(A · B) = 0
    • 相同方向:(A · B) > 0
    • 相反方向:(A · B) < 0
    • 向量投影:给定两个向量v和n,可以把向量v分解为平行和垂直n的两个分量v1,v2。v1 = n(v·n)/|n|2,v2 = v - v1。
  • 叉积:
    两个矢量的叉积会产生一个垂直于原来两个矢量的矢量,叉积运算只定义在三维空间。
    A x B = [(AyBz - AzBy), (AzBx - AxBz), (AxBy - AyBx)]
    |A x B| = |A||B|sinθ
    若A和B为平行四边形的两条边,其面积为两矢量叉积的模|A x B|。

    叉积可以用来求法向量,力矩等。

    点和矢量的线性插值,用来计算两个已知点的中间点。
    L = LERP(A, B, θ) = (1-θ)A + θB
    = [(1-θ)Ax + θBx, (1-θ)Ay + θBy, (1-θ)Az + θBz]

    LERP函数是两矢量的加权平均。

关于向量相关的类我们可以在很多游戏引擎里面有看过,封装的方法也都是大同小异,这里介绍下封装过程中需要注意的细节:

  • 数据类型:float还是double,根据实际的需求而定;
  • 使用const成员函数;
  • 使用const引用参数传地址避免以值传递调用一次构造提高效率,而且如果函数不是内联的,传值的方式会需要更多的堆栈空间和更长的参数压栈时间。
  • 无缺省初始化:缺省构造函数不执行任何的初始化操作,因为向量类需要在严格要求速度的场合使用,建议不分配资源;
  • 不使用虚函数:1、使用虚函数,优化器不能产生成员函数的内联代码;2、虚函数需要指向虚函数表的指针,向量定义时指针必须初始化,会使对象的大小增加25%,而存储包含向量的大数组是一种很普遍的现象。
  • 全局常量:零
矩阵


4x4矩阵可表示任意三维变换,包括平移、旋转和缩放。仿射矩阵是一种4x4矩阵,它能维持直线在变换前后的平行性以及相对的距离比,但是不一定维持直线在变换前后的绝对长度及角度。

(一)矩阵乘法

P=AB,若A为缩放矩阵,B为旋转矩阵,则P等同于对点或矢量进行缩放和旋转变换。AB≠BA(AB不等于BA),矩阵乘法不符合交换律。

  • 逆矩阵

    矩阵A的逆矩阵能还原矩阵A的变换。若一个矩阵乘以它的逆矩阵,结果必然是单位矩阵。并非所有的矩阵都有逆矩阵。然而所有的仿射矩阵都有逆矩阵,可用高斯消去法或LU分解求之。
    A(Aˉ1) = I
    (ABC)ˉ1 = Cˉ1Bˉ1Aˉ1

  • 转置矩阵

    转置矩阵就是把原来的矩阵以主对角线为对称轴做反射,和逆矩阵相同,矩阵串接的转置为反向串接各个矩阵的转置。

齐次坐标


2x2矩阵来表示二维中的旋转:
技术分享

3x3矩阵来表示三维中的旋转:
技术分享

3x3矩阵是无法表示平移的:R + T = [(Rx + Tx), (Ry + Ty), (Rz + Tz)],虽然矩阵的乘法可以对元素进行相乘和相加,但是没有办法把T的分量放到3x3的矩阵中,使得与R相乘后产生(R+T)的值。

如果采用4x4矩阵就可以获得类似的和:
技术分享

  • 变换方向矢量

    当用矩阵变换一个点时,平移、旋转、缩放都会施于该点上。但是,当用矩阵变换一个方向矢量时,就要忽略矩阵的平移效果。因为方向矢量本身并没有平移,加上平移会改变其模。
    技术分享
    严格地说四维的齐次坐标转换为三维的非齐次坐标的方法是把x,y,z分量除以w分量:

    [x y z w] = [x/w y/w z/w]

此公式表明,可设点的w分量为1,方向矢量的w为0。矢量除以w=1,并不影响点的坐标,矢量除以w=0则会产生无穷大。所以事实上三维空间的纯方向在四维齐次空间是位于无穷远的点。

基础变换矩阵

4x4矩阵可以切割为4个组成部分:
技术分享

  • 左上的3x3矩阵U,代表旋转/缩放
  • 1x3平移矢量t

技术分享

  • 平移
    技术分享
    平移矩阵的逆矩阵就是把t求反(即翻转tx,ty,tz的正负号)

  • 旋转
    技术分享
    纯旋转矩阵的逆矩阵即是该旋转矩阵的转置矩阵。

  • 缩放
    技术分享
    缩放矩阵的逆矩阵就是把Sx,Sy,Sz用倒数代替即可。

  • 4x3矩阵
    4x4的仿射矩阵中最右侧一定是一列[0 0 0 1]的矢量,所以可以略去第4列以节省内存。(在使用GPU做蒙皮的时候,要向顶点着色器传递大量的变换,所以为了节省空间、时间,通常会使用3x4矩阵)

技术分享

版权声明:本文为博主原创文章,未经博主允许不得转载。

游戏中的三维数学

标签:游戏   坐标系   三维数学   

原文地址:http://blog.csdn.net/john_cdy/article/details/48129697

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!