3D Game Programming withDX11 学习笔记(一) 数学知识总结
在图形学中,数学是不可或缺的一部分,所以本书最开始的部分就是数学知识的复习。在图形学中,最常用的是矢量和矩阵,所以我根据前面三个章节的数学知识,总结一下数学知识。
一、矢量
数学中的矢量,拥有方向和长度。其实矢量和点在坐标系中的表示完全一致(笛卡尔坐标系为准),区分矢量和点的关键,我觉得就是做平移。点是不能用平移操作来保证一致的,比如点A(1,2,3)经过平移矢量(1,2,3)后就是B(2,4,6),此时就是一个新的点。但是矢量经过相同平移操作后,还是矢量(1,2,3),这是因为矢量表示的是 vector head相对于 vector tail的偏移,平移操作并不会改变这种偏移。
在矢量中一个关键就是坐标系,数学中的坐标系主要分为左手坐标系和右手坐标系。我时不时会弄混左手和右手坐标系,后来做了一个快捷的记忆:我的头是y方向,右手伸出来是x方向,那么如果z方向向前是正方向,那我就处于左手坐标系; 如果我的z方向向后是正方向,那我就处于右手坐标系。所以看起来我的脸决定了我的坐标系:)
矢量的数学操作主要是:加、减、乘三种操作,如果算上求模(求长度),那就是四种操作。A=(xa,ya,za), B=(xb,yb,zb)
加:A + B = (xa+xb, ya+yb, za+zb)
减:A - B = (xa-xb, ya-yb, za-zb)
乘:A *B = xaxb+yayb+zazb
模:||A||2= xa2 + ya2+za2
细心的会发现矢量乘的结果变成了一个数,确实,最终的结果就是一个数,其本质就是一种映射或者投影,表示的是A矢量在B矢量方向上的投影长度,矢量的乘可以用公式表示为:
A *B = ||A|| *||B|| * sinθ,其中θ为两个矢量的夹角(由于不熟悉博客的数学公式添加,只有先这写着了,后面熟练了再修改吧)
矢量中最常见的操作就是归一化,比如有一个矢量的序列{V0,v1,V2...},如何将这些矢量归一化为互相垂直的单位矢量?
这儿引入投影的一个表示:projn(V)= v . n/||n||, 表示的是v在n的单位矢量上的投影,那么对于矢量序列,我们可以这样进行正交归一化:
1)v0, v1,v2.......
2) w0 = v0;
3) w1 = v1 - projw0(v1)
4) w2 = v2 - projw0(v2) - projw1(v2)
........
根据上面的规律,可以得到正交化的规律:将当前矢量(第一个除外)去除在前面所有矢量上的分量(投影),得到的就是与前面各个适量正交的矢量。
最后我们将正交化的矢量进行归一化操作,即可得到一组正交归一化矢量序列。
矢量的最后一个知识点是:矢量的叉积,与矢量点积得到一个投影的结果值不同,矢量的叉积得到的是一个矢量,基本公式为:
AXB = (yazb -zayb, zaxb - xazb, xayb - yaxb),
单看公式看不出规律,不过可以这样理解:xyz, yzx, zxy,分别去掉x, y , z,最后的结果就是三个分量的第一项,然后交换得到三个分量需要减去的第二项
矢量的叉积的实际意义,就是求得一个和A/B两个矢量都垂直的矢量,这在图形学中,可以用来求解游戏对象的一些常用矢量, 比如上(up)/下(down)/左(left)/右(right)/前(forward)/后(back)这些矢量都是互相垂直的,可以利用矢量的叉积得到。注意在笛卡尔坐标系中,矢量的叉积都是左手定律决定方向的,所以AXB和BXA是刚好方向相反的两个等长矢量。
二、矩阵
在图形学中,我们会绘制各种各样的游戏实例,这些实例都是用基本的点(verts)和相关的贴图(textures)、材质(material)等共同设置渲染状态的。对于基本的顶点,常常需要做的一个基本操作就是变换:平移、旋转、缩放等。这些变换操作对应的就是矩阵的变换。
矩阵的定义就不再多说,就是一个nxm的同类元素的集合,通常这个元素就是数字(也可以为其他,这儿不再扩展)。
矩阵最基本的操作可以分为: 矩阵的乘, 矩阵的转置, 矩阵的行列式, 矩阵的逆
矩阵的乘积: C = AB ≠BA
C矩阵中的每个元素是Cij是A矩阵的i行和B矩阵j列的对应点积的结果,基于此可以得到A矩阵的列数和B矩阵的行数是相等的(不然怎么做点积....)
矩阵的转置AT,就是将矩阵的行和列对换,说的简单点就是一列一列的变,新的每列是以前矩阵的每行竖着排列(感觉就是重新排队)
矩阵的行列式,是一个比较重要的点,Aij作为行列式的代指,就是去除A矩阵的i行和j列后得到的行列式计算结果,整体的公式为:
detA = ∑j=1n A1j(-1)i+jdetA1j
可以看出矩阵的行列式计算就是一个递归的计算过程,一般在图形学中的计算不会超过4x4的维度,所以可以用笔算的方式来计算这些矩阵的行列式:)
基于行列式,可以得到一个新的矩阵: 邻接矩阵A*,基于基本的矩阵A可以得到一个新的矩阵CA,其中的元素Cij = (-1)i+jdetAij,则可以定义邻接矩阵为:
A* = CAT 基于邻接矩阵,我们可以得到矩阵A的逆矩阵A-1 :A-1 = A*/detA
三、变换矩阵
基于矩阵的定义,我们可以将图形学中的一些常见的变换转化为对应的变换矩阵,这样在对点或者矢量进行变换的时候,其对应的数学操作就是一个变换矩阵的操作。基本的变换矩阵可以分为:缩放矩阵, 平移矩阵,旋转矩阵。
对于变换矩阵对矢量的作用,可以这样理解:u =(x,y,z) = xi + yj + zk, 那么一个变换操作可以表示为τ(u) = τ(xi + yj + zk) = xτ(i) + yτ(j) + zτ(k) = [x y z] [τ(i) τ(j) τ(k)]T = uA
所以说的直白点,就是用矩阵A来表示一种变换操作。那么具体如何表示呢?可以分拆为基本矩阵,然后进行合并即可。
1、缩放矩阵S
拆开用行向量表示为S(i) = (sx .1, sy.0, sz.0), S(j) = (sx .0, sy.1, sz.0),S(k) = (sx .0, sy.0, sz.1)
则缩放矩阵可以表示为S = [si , sj, sk]T, si = (sx,0,0), sj = (0,sy,0), sk = (0,0,sz)
2、旋转矩阵R
其实旋转矩阵是三个矩阵中相对比较难的矩阵,这儿给出一个旋转公式:
Rn(V) = projn(v) + Rn(V⊥)
= (n v) n + cosθ V⊥ + sinθ (n x v)
= cosθ V + (1 - cosθ)(n v)n + sinθ(n x v)
具体的常用的三个旋转矩阵可以列出来:
3、平移矩阵T
平移矩阵比较简单,就不做推算,直接给出结果即可:
综合三种基本矩阵,我们可以进行组合得到一个较为复杂的变换矩阵。不过在图形学的计算中,对于三种矩阵的排序有一定的讲究,一般先用缩放矩阵S对当前的变换对象进行缩放,然后用旋转矩阵R进行旋转操作,最后用平移矩阵T进行平移操作,所以可以归并为SRT矩阵。
总结:经过基本的矢量,矩阵和变换的数学知识总结后,接下来就要进入正式的图形学知识了,我会在后面持续更新~
3D Game Programming withDX11 学习笔记(一) 数学知识总结的更多相关文章
- MyBatis:学习笔记(1)——基础知识
MyBatis:学习笔记(1)--基础知识 引入MyBatis JDBC编程的问题及解决设想 ☐ 数据库连接使用时创建,不使用时就释放,频繁开启和关闭,造成数据库资源浪费,影响数据库性能. ☐ 使用数 ...
- C#学习笔记(基础知识回顾)之值类型与引用类型转换(装箱和拆箱)
一:值类型和引用类型的含义参考前一篇文章 C#学习笔记(基础知识回顾)之值类型和引用类型 1.1,C#数据类型分为在栈上分配内存的值类型和在托管堆上分配内存的引用类型.如果int只不过是栈上的一个4字 ...
- C#学习笔记(基础知识回顾)之值传递和引用传递
一:要了解值传递和引用传递,先要知道这两种类型含义,可以参考上一篇 C#学习笔记(基础知识回顾)之值类型和引用类型 二:给方法传递参数分为值传递和引用传递. 2.1在变量通过引用传递给方法时,被调用的 ...
- C#学习笔记(基础知识回顾)之值类型和引用类型
一:C#把数据类型分为值类型和引用类型 1.1:从概念上来看,其区别是值类型直接存储值,而引用类型存储对值的引用. 1.2:这两种类型在内存的不同地方,值类型存储在堆栈中,而引用类型存储在托管对上.存 ...
- JAVA学习笔记—review基本知识[反射与异常]
JAVA学习笔记—review基本知识[反射与异常] 1.异常: 1.1异常的分类: Java会将所有的异常封装成对象,其根本父类为Throwable. Throwable有两个子类:Error 和E ...
- Quartz学习笔记:基础知识
Quartz学习笔记:基础知识 引入Quartz 关于任务调度 关于任务调度,Java.util.Timer是最简单的一种实现任务调度的方法,简单的使用如下: import java.util.Tim ...
- CUDA Programming Guide 学习笔记
CUDA学习笔记 GPU架构 GPU围绕流式多处理器(SM)的可扩展阵列搭建,每个GPU有多个SM,每个SM支持数百个线程并发执行.目前Nvidia推出了6种GPU架构(按时间顺序,详见下图):Fer ...
- .net学习笔记---xml基础知识
一.XML简介 XML是一种标记语言,用于描述数据,它提供一种标准化的方式来来表示文本数据.XML文档以.xml为后缀.需要彻底注意的是XML是区分大小写的. 先从一个简单的XML例子来了解下xml基 ...
- react学习笔记1--基础知识
什么是react A JAVASCRIPT LIBRARY FOR BUILDING USER INTERFACES[React是一个用于构建用户界面的JavaScript库.] React之所以快, ...
随机推荐
- [转]动态管理视图和函数 (Transact-SQL)
动态管理视图和函数返回可用于监视服务器实例的运行状况.诊断故障以及优化性能的服务器状态信息. 重要提示 动态管理视图和函数返回特定于实现的内部状态数据. 在未来的 SQL Server 版本中,它们的 ...
- Liunx vi编辑器一些指令
最近几天学习了Liunx vi编辑器 的使用,感觉还比较容易.总结的一点心得: vi分为3个模式,命令模式,尾行模式,编辑模式. 1. 命令模式 与 编辑模式切换 a:光标向后移动一位进入编辑模式 i ...
- java对象拷贝和复制
参考文章:http://blog.csdn.net/XIAXIA__/article/details/41652057 解决问题:深拷贝.浅拷贝 和普通的对象赋值有什么区别? 对象复制 例如:Pers ...
- html5+ XMLHttpRequest
XMLHttpRequest 让发送一个HTTP请求变得非常容易.你只需要简单的创建一个请求对象实例,打开一个URL,然后发送这个请求.当传输完毕后,结果的HTTP状态以及返回的响应内容也可以从请求对 ...
- smartClient 1--框架介绍
一.是什么(以下简称SC) smartClient 是一个基于web技术的开发框架,主要包括: 一个无需安装的 Ajax/HTML5 客户端引擎 UI组件和服务(采用富客户端RIA)--- 提 ...
- cocos2d-x安卓应用启动调用过程简析
调用org.cocos2dx.cpp.AppActivity AppActivity是位于proj.android/src下的开发者类(即开发者自定义的类),它继承自org.cocos2dx.lib. ...
- 前端worker之web worker
web worker 背景 众所周知javascript是单线程的,同一时间内只能做一件事情. 这是十分必要的,设想,如果js是多线程的.有个dom元素两个线程同时做了改变,一个display:non ...
- javafx 聊天室WeChat
[toc] 功能和特性 基于socket实现的c/s架构的的通信 服务器和客户心跳连接 gson实现的消息通信机制 注册及登录 支持私聊和群聊. 动态更新用户列表以及用户消息提示 支持emoji表情, ...
- MySQL修改表
一.给表mytablename添加新字段newcolumn alter table mytablename add newcolumn varchar(50) COMMENT '新字段备注信息' 二. ...
- VUE 与其他常见前端框架对比
对比其他框架(转官方文档) 这个页面无疑是最难编写的,但我们认为它也是非常重要的.或许你曾遇到了一些问题并且已经用其他的框架解决了.你来这里的目的是看看 Vue 是否有更好的解决方案.这也是我们在此想 ...