DirectX12 3D 游戏开发与实战第三章内容
变换
学习目标
- 理解如何使用矩阵表示线性变换和仿射变换
- 学习对几何体进行缩放、旋转和平移的坐标变换
- 根据矩阵之间的乘法运算性质,将多个变换矩阵合并为一个单独的净变换矩阵
- 找寻不同坐标系之间的坐标转换方法,并利用矩阵来表示此坐标变换
- 熟悉DirectXMath库中专门为构建变换矩阵所提供的相关函数
3.1线性变换
3.1.1定义
如果有一个函数t可以使
t(u + v) = t(u) + t(v)
t(ku) = tk(u)
成立,则函数t称为线性函数,也称为线性变换。其中u和v为3D向量,k为标量。(非3D向量也可以作为线性变换的输入和输出,不过在3D图形学中我们一般讨论3D向量的线性变换)
3.1.2矩阵表示法(重点)
略()
3.1.3缩放
缩放(比例变换)是指改变物体的大小,我们一般把缩放定义
S(x,y,z) = (s1x,s2y,s3z)
s1,s2,s3分别代表S的三个分量
此变换将相对于当前坐标系中的原点,令向量在x,y,z轴上分别以系数s1,s2,s3进行缩放,S是一种线性变换,这里不做证明
- 关于缩放变换 S的矩阵表示
S(i) = (s11,s20,s3*0);
S(j) = (s10,s21,s3*0);
S(k) = (s10,s20,s3*1);
所以缩放矩阵S的矩阵表示为
{
s1,0,0,
0,s2,0,
0,0,s3
}
例子:如果要将一个正方形在x轴上缩小0.5,在y轴上方法2.0倍,在z轴上保持不变,可以采用缩放矩阵S
{
0.5,0,0,
0,2,0,
0,0,0
}
将该矩阵S分别与正方形的最小点坐标、正方形的最大点坐标相乘即可
3.1.4旋转
本节将用数学的方式来描述向量v绕轴n以角theta进行旋转,我们首先会将向量v分解为两部分,一部分平行于n,另一部分正交于n,在旋转的过程中,平行于n的部分是保持不变的,所以我们只需要考虑正交于n的部分。
推导过程:略
旋转变换也是一种线性变换,所以也可以转换为矩阵表示。旋转变换的矩阵表示为:
{
c+(1-c)x^2 (1-c)xy + sz (1-c)xz-sy
(1-c)xy-sz c+(1-c)y^2 (1-c)yz+sx
(1-c)xz+sy (1-c)yz-sx c+(1-c)z^2
}
其中x,y,z表示旋转轴n的(x,y,z),s和c分别表示sin(theta)和cos(theta)
例子:略
3.2仿射变换
3.2.1齐次坐标
在下一节中我们可以看到,仿射变换是由一个线性变换和一个平移变换组合而成的,对于向量而言,平移操作使没有意义的,因为向量只描述大小的方向,和位置无关。所以,平移操作只能应用于点(即位置向量)。在采用齐次坐标所提供的表示机制中,我们可以方便地对点和向量进行统一的处理,在齐次坐标中,坐标将被扩充为四元组,第四个坐标的值将根据被描述对象是点还是向量而定,具体来说
- (x,y,z,0)表示向量
- (x,y,z,1)表示点
3.2.2仿射变换的定义及其矩阵表示
线性变换并不能表示出我们需要的所有变换,因此我们需要把它扩充为一种称为仿射变换的映射范围更广的函数类,仿射变换为一个线性变换+一个平移向量即
a(u) = t(u) + b
也可以用矩阵表示法表示:
{
A1 A2 A3 0
A4 A5 A6 0
A7 A8 A9 0
Bx By Bz 1
}
其中An为线性变换的矩阵表示,Bx,By,Bz为平移向量b
3.2.3平移
恒等变换是一种直接返回其输入参数的线性变换,即t(u) = u;不难看出,线性变换t的矩阵表示为单位矩阵。现将平移变换定义为仿射变换,其中的线性变换即是一种恒等变换,所以平移变换的仿射公式为
t(u) = uI + b = u + b
其中I为单位矩阵。
平移变换的矩阵表达为:
{
1 0 0 0
0 1 0 0
0 0 1 0
Bx By Bz 1
}
其中Bx,By,Bz分别为平移向量b的各分量
3.2.4缩放和旋转的仿射矩阵
将缩放矩阵和旋转矩阵扩充为4x4矩阵,即将每一个行向量的w值设为0,同时加上平移向量b(0,0,0,1)即可
仿射变换矩阵的几何意义
略
变换的复合(变换的组合)
问题:假设有一个缩放矩阵S,旋转矩阵R,平移矩阵T,现在有一个由8个顶点构成的立方体,现想将这3中变换相继应用到正方体的每一个顶点上,则可以
((Vi S) R) T //其中Vi为正方体的每一个顶点
由于矩阵乘法满足结合律,所以可以令矩阵C = SRT;即提前将这3中变换封装成一个净变换矩阵,这样便于我们操作,同时也可以提高性能
3.4坐标变换(坐标系变换)
在后续的学习中,我们要面对不同的标架来转换点或向量的坐标,我们把不同标架间的转换称之为坐标变换
在坐标变换的过程中,几何体本身并没有发生变换,坐标变换改变的只是物体的参考系。相比之下,我们可以认为缩放,旋转,平移这些操作才使几何体发生了实质性的改变
在计算机图形学中,我们会用到许多不同的坐标系,因此需要了解他们之间相互转换的方法,由于位置是点的属性,与向量无关,所以点和向量的坐标转换时不同的,下面我们会分开来介绍。
3.4.1向量的坐标变换
思考:其中有一向量p分别位于标架1和标架2中,设向量p在标架1中的坐标为P1 = (x,y,z);那如何求得向量p在标架2中的对应坐标?
解答过程:略(主要应用平移的方法)
答案:P2 = xu + yv + zw
u,v,w分别表示指向标架1中x轴,y轴和z轴正方向上的单位向量(在标架2中进行表示)
3.4.2点的坐标变换
点与向量的坐标变换有点不一样,因为位置是点的一个重要属性,因而不能把向量和点混为一谈,也不能简单的把向量平移的方法应用到点上
解答过程:略
转换公式:P2 = xu + yv + zw + Q
u,v,w分别表示指向标架1中x轴,y轴和z轴正方向上的单位向量(在标架2中进行表示),Q表示标架1中的原点在标架2中的坐标
3.4.3坐标变换的矩阵表示
在上两节中,我们已经介绍了向量和点的坐标变换
(x',y',z') = xu + yv + zw //对于向量而言
(x',y',z') = xu + yv + zw + Q //对于点而言
如果使用齐次坐标,可以将上面的两个公式合并成一个公式,即:
(x',y',z',w) = xu + yv + zw + Q
在上面的坐标变换公式中,如果w = 0;则表示向量,w = 1则表示点,这样便可以只记忆一条公式了。上述公式的矩阵表示为:
{
u1 u2 u3 0
v1 v2 v3 0
w1 w2 w3 0
Q1 Q2 Q3 1
}
此矩阵称为坐标变换矩阵或标架变换矩阵
3.4.4坐标变换矩阵及其结合律
问题:假设有3个标架,分别为1、2、3,且已知三个标架的标架变换矩阵分别为A、B、C,在标架1中有一个向量的坐标为P,如果想要求出此向量在标架3中对应的坐标,则可以
(PB)C = p';
但是这样的计算效率不高,因为矩阵的乘法满足结合律,所以我们可以令H = BC;然后可以使用PH = P';便可以完成变换
3.4.5坐标变换矩阵及其逆矩阵
略
3.5变换矩阵与坐标变换矩阵
在前面的小结中,我们强调了“使几何体本身发生改变”的变换(缩放,旋转和平移)和坐标变换的区分,不过,在本节中,我们将证明:从数学角度上来看,两者是等价的。
证明过程:略
3.6DirectXMath库提供的变换函数
本节我们将对DirectXMath库中和变换相关的函数进行总结,以便以以后进行参考。
//构建一个缩放矩阵
XMMATRIX XM_CALLCONV XMMatrixScaling(
float ScaleX, //缩放系数
float ScaleY, //缩放系数
flaot ScaleZ //缩放系数
)
//用一个3D向量中的分量来构建一个缩放矩阵
XMMATRIX XM_CALLCONV XMMatrixScalingFromVector(
FXMVECTOR Scale; //缩放系数(Sx,Sy,Sz)
);
//构建一个绕x轴旋转的旋转矩阵
XMMATRIX XM_CALLCONV XMMatrixRotationX(
float Angle //以顺时间方向旋转Angle弧度
);
//构建一个绕y轴旋转的旋转矩阵
XMMATRIX XM_CALLCONV XMMatrixRotationY(
float Angle //以顺时间方向旋转Angle弧度
);
//构建一个绕z轴旋转的旋转矩阵
XMMATRIX XM_CALLCONV XMMatrixRotationZ(
float Angle //以顺时间方向旋转Angle弧度
);
//构建一个绕任意轴旋转的矩阵
XMMATRIX XM_CALLCONV XMMatrixRotationAxis(
FXMVECTOR Axis, //旋转轴n
float Angle //沿n轴正方向看,以顺时针方向按弧度Angle进行旋转
);
//构建一个平移矩阵
XMMATRIX XM_CALLCONV XMMatrixTranslation(
float OffsetX, //平移系数
float OffsetY, //平移系数
float OffsetZ //平移系数
);
//用一个3D向量中的分量来构建平移矩阵
XMMATRIX XM_CALLCONV XMMatrixTranslationFromVector(
FXMVECTOR Offset //平移系数(Sx,Sy,Sz)
);
//计算向量和矩阵的乘积VM,此函数默认w = 1;即针对点计算
XMVECTOR XM_CALLCONV XMVector3TransformCoord(
FXMVECTOR V, //输入向量V
CXMMATRIX M //输入矩阵M
);
//计算向量和矩阵的乘积VM,此函数默认w = 0;即针对向量计算
XMVECTOR XM_CALLCONV XMVector3TransformNormal(
FXMVECTOR V, //输入向量V
CXMMATRIX M //输入矩阵M
);
小结
1、缩放、平移和旋转这3种基础操作的变换矩阵分别为:
S =
{
Sx 0 0 0
0 Sy 0 0
0 0 Sz 0
0 0 0 1
};
T =
{
1 0 0 0
0 1 0 0
0 0 1 0
b1 b2 b3 1
};
R =
{
c+(1-c)x^2 (1-c)xy + sz (1-c)xz-sy
(1-c)xy-sz c+(1-c)y^2 (1-c)yz+sx
(1-c)xz+sy (1-c)yz-sx c+(1-c)z^2
}
2、在使用齐次坐标表示变换时,我们用1 x 4齐次坐标来描述点和向量。当把第四个分量w设置为0时,则表示向量,w = 1时,则表示点。这样可以使平移操作只应用于点,而不会影响向量
3、如果一个矩阵中所用的行向量都是单位长度而且两两正交,则该矩阵称为正交矩阵,正交矩阵的逆矩阵和转置矩阵相等,正交矩阵对应的逆矩阵很容易计算。所有的旋转矩阵都是正交矩阵
4、由于矩阵的乘法运算满足结合律,所以我们一般把若干种变换矩阵合并为一个矩阵,这样可以提高运算效率
5、设Q,u,v,w分别表示标架1中的原点,x轴,y轴,z轴相对于标架2的坐标,如果一个向量p在标架1中的对应坐标为(x,y,z),则该向量相对于标架2的坐标为
p' = xu + yv + zw; //针对向量
p' = xu + yv + zw + Q; //针对点(位置向量)
6、由于矩阵的乘法运算满足结合律,所以对于多个标架之间的转换,我们可以把多个标架变换矩阵合并成一个矩阵,可以提高运算效率
7、如果矩阵A可以将坐标从标架1映射到标架2中,那么A的逆矩阵可以把坐标从标架2映射到标架1中
DirectX12 3D 游戏开发与实战第三章内容的更多相关文章
- DirectX12 3D 游戏开发与实战第五章内容
渲染流水线 学习目标: 了解用于在2D图像中表现出场景立体感和空间深度感等真实效果的关键因素 探索如何用Direct3D表示3D对象 学习如何建立虚拟摄像机 理解渲染流水线,根据给定的3D场景的几何描 ...
- DirectX12 3D 游戏开发与实战第四章内容(上)
Direct3D的初始化(上) 学习目标 了解Direct3D在3D编程中相对于硬件所扮演的角色 理解组件对象模型COM在Direct3D中的作用 掌握基础的图像学概念,例如2D图像的存储方式,页面翻 ...
- DirectX12 3D 游戏开发与实战第四章内容(下)
Direct3D的初始化(下) 学习目标 了解Direct3D在3D编程中相对于硬件所扮演的角色 理解组件对象模型COM在Direct3D中的作用 掌握基础的图像学概念,例如2D图像的存储方式,页面翻 ...
- DirectX12 3D 游戏开发与实战第七章内容(上)
利用Direct3D绘制几何体(续) 学习目标 学会一种无须每帧都要刷新命令队列的渲染流程,以此来优化性能 了解另外两种根签名参数类型:根常量和根描述符 探索如何在程序中生成和绘制常见的几何体:如栅格 ...
- DirectX12 3D 游戏开发与实战第十一章内容
仅供个人学习使用,请勿转载.谢谢! 11.模板 模板缓冲区(stencil buffer)是一种"离屏"(off-screen)缓冲区,我们可以利用它来实现一些效果.模板缓冲区.后 ...
- DirectX12 3D 游戏开发与实战第七章内容(下)
利用Direct3D绘制几何体(续) 学习目标 学会一种无须每帧都要刷新命令队列的渲染流程,由此来优化程序的性能 了解另外两种跟签名参数类型:根描述符和根常量 探索如何在程序中生成和绘制常见的几何体, ...
- DirectX12 3D 游戏开发与实战第六章内容
利用Direct3D绘制几何体 学习目标 探索用于定义.存储和绘制几何体数据的Direct接口和方法 学习编写简单的顶点着色器和像素着色器 了解如何用渲染流水线状态对象来配置渲染流水线 理解怎样创建常 ...
- DirectX12 3D 游戏开发与实战第八章内容(下)
DirectX12 3D 游戏开发与实战第八章内容(下) 8.9.材质的实现 下面是材质结构体的部分代码: // 简单的结构体来表示我们所演示的材料 struct Material { // 材质唯一 ...
- DirectX12 3D 游戏开发与实战第八章内容(上)
8.光照 学习目标 对光照和材质的交互有基本的了解 了解局部光照和全局光照的区别 探究如何用数学来描述位于物体表面上某一点的"朝向",以此来确定入射光照射到表面的角度 学习如何正确 ...
随机推荐
- SpringCloud微服务小白入门之Eureka注册中心和服务中心搭建示例
一.注册中心配置文件 代码复制区域: spring: application: name: spring-cloud-server server: port: 7000 eureka: instanc ...
- 纯前端下载pdf链接文件,而不是打开预览的解决方案
纯前端下载pdf链接文件,而不是打开预览的解决方案 一,介绍与需求 1.1,介绍 XMLHttpRequest 用于在后台与服务器交换数据.这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行 ...
- 实现API管理系统的几个重要关键词
管理API的需求源自于Web API开展业务.从2006年开始,然后逐渐成熟,并在2016年之前进入市场.无论是通过代理现有API的管理网关.本身作为用于部署API本身的网关的一部分,还是作为连接层在 ...
- Gitment评论插件的使用
前言 继上一篇的 GitPages部署自己的网站 现在开始添加博客的评论插件Gitment.这里的话我是使用hexo添加gitment插件,如果不是使用hexo,请到官网指定这里. 开始 第一步 注册 ...
- net start mysql
net start mysql 解决的方法: 如何以管理员身份打开黑窗口 左下角开始菜单,找到小娜,cmd 回车, 命令提示符右击,以管理员身份打开 依次输入下面两行代码 mysqld -instal ...
- Spring-Boot:Profile简单示例
//Resources目录下创建 application.properties spring.profiles.active=prod //Resources目录下创建 application-pro ...
- mybatis多表查询之多对多关系查询的实现-xml方式
Mybatis对于多对多关系下的查询提供了集合(collection)的概念来解决,collection属性是resultMap高级结果映射的子集,首先,在本例中我们使用的是集合元素来解决多对多的查询 ...
- N*N矩阵的旋转 不开辟新空间
/* N*N矩阵的旋转 不开辟新空间 programmer:qpz time:2014-11-09 */ #include <iostream> using namespace std; ...
- Selenium3 + Python3自动化测试系列六——等待方式
等待 一.等待是什么,为什么要等待 在做自动化测试,设计测试用例的时候,有时下一步的操作会依赖上一步的结果或者内容,上一步操作成功之后才能进行下一步操作等, 这时候,我们就需要使用等待,来判断上一步操 ...
- 2013-2014 ACM-ICPC Pacific Northwest Regional Contest D.Delta Quadrant
题意略. 思路: 由于这是一颗无根树,我们可以贪心地来删去边. 详见代码: #include<bits/stdc++.h> using namespace std; typedef lon ...