DirectX12 3D 第一章内容
学习目标
1、学习向量在几何学和数学中的表示方法
2、了解向量的运算定义以及它在几何学中的应用
3、熟悉DirectXMath库中与向量有关的类和方法
1.1 向量
向量是一种兼具大小和方向的量,具有这两种的量都称为向量值物理量,在几何学中我们一般用一条有向线段来表示一个向量
1.1.1 向量与坐标系
前提:计算机无法直接处理以几何方法表示的向量,所以需要寻求一种用数学方法来表示向量
在这里我们会引入一种3D空间坐标系,通过平移操作使向量的尾部位于原点,然后我们就可以通过向量头部的坐标来确定该向量了,可以记作 v = (x,y,z),xyz分别为计算机程序中的浮点数。一个向量如果用数学方法表示的话,它对应的坐标总是相对于某一种参考系而言的,因此,在计算机图形学中,我们会用到较多的参考系,因此我们要记录向量在每一种坐标系中的对应坐标,也需要掌握将向量坐标在不同标架之间进行转换
1.1.2 左手坐标系和右手坐标系
左手坐标系:伸出你的左手,使大拇指,食指和中指之间两两垂直,其中大拇指为x轴正方向,食指为y轴正方向,中指为z轴正方向
右手坐标系:同上。
1.1.3 向量的基本运算
简单的向量加减法
1.2 长度和单位向量
前提:向量大小的几何意义是对应有向线段的长度,3D向量的模长可以通过运用两次毕达哥拉斯定理得出,单位向量是指长度为1的向量
向量的规范化:在某些情况下,我们不关心向量的长度,仅用它来表示方向。对此我们希望此向量的长度为1,所以我们可以将向量的每一个分量/该向量的模长。把一个向量的长度变为单位长度便是向量的规范化了。
1.3 点积
点积的定义点积是一种计算结果为标量值的向量乘法运算,因此也称为标量积。点积就是向量之间对应分量的乘积之和。
点积的几何意义:uv = ||u||||v||*cos0(0为两向量的夹角)。
正交投影:p = (vn)n(p,v,n都是向量,其中p为向量v在向量n上的正交投影,n为单位向量)
利用点积进行正交化:略
1.4 叉积
叉积的计算结果和点积不同,叉积的计算结果也是向量。只有3D向量有叉积,2D向量没有叉积。假设向量u和向量v的叉积为w,则w既正交与u,也正交与v。
计算方式:w = u x v = (UyVz-UzVy,-(UxVz-UzVx),UxVy-UyVx)
叉积不符合交换律,但符合反交换律,即u x v = -v x u
利用叉积进行正交化:略
1.5 点
通过一个处于标准位置的向量就能表示出3D空间中的特定位置,这种向量称为位置向量,在这种情况下,向量箭头的位置才是主要特征,方向和大小都无足轻重。
标准位置:向量通过平移使向量的尾部位于原点的向量。即从原点出发的向量
注意点:位置向量和点这两个术语可以互相替代,但是用向量表示点有缺点也有优点
1.6 利用DirectXMath库进行向量运算
前言:DirectXMath库是一款为Direct3D应用程序专门设计的一个3D数学库,它也是Windows SDK的一部分,该数学库可以利用一条SIMD指令对4个32位浮点数或整数进行运算,可以加大的提高效率。
为了使用DirectXMath库,我们要添加头文件
#include <DirectXMath.h>
为了使用一些相关的数据类型,我们要添加头文件
#include <DirectXPackVector.h>
其中DirectXMath文件的代码都存在DirectX的命名空间中,DirectXPackVector文件中的代码都位于DirectX::packVector的命名空间中。
1.6.1 向量类型
DirectXMath中最核心的数据类型就是XMVECTOR,它会被映射到SIMD硬件寄存器中
1、局部变量和全局变量建议使用XMVECTOR数据类型,因为XMVECTOR类型的数据需要按16字节对齐,在局部变量和全局变量中这都会自动实现
2、对于类中的成员,建议使用XMFLOAT2,XMFLOAT3或者XMFLOAT4.
3、在运算之前,建议使用加载函数将XMFLOATn类型转换为XMVECTOR类型(可以加快运算速率)
4、用XMVECOTR实例进行运算
5、通过存储函数将XMVECTOR类型转换为XMFLOATn类型
1.6.2 加载方法和存储方法
加载方法:
XMMATRIX XM_CALLCONV XMLoadFloatn(const XMFLOATn * pSource);
存储方法:
void XM_CALLCONV XMStoreFloatn(XMFLOATn * pDestination,FXMVECTOR V);
1.6.3 参数的传递
为了提高效率,可以将XMVECTOR类型的值作为函数的参数,直接传送到SSR/SSE2寄存器里,而不存在栈中。单数为了使代码更具通用性,不受到平台和编译器的影响,我们将利用FXMVECTOR,GXMVECTOR,HXMVECTOR和CXMVECTOR类型来传递XMVECTOR类型的参数。
1.6.4 常向量
XMVECTOR类型的常量实例应当用XMVECTORF32类型来表示。例如
static const XMVECTORF32 g_vHaifVector ={ 0.5f,0.5f,0.5f,0.5f };
static const XMVECTORF32 g_vZero = { 0.0f,0.0f,0.0f,0.0f };
基本上我们在运用初始化语法的时候就要使用XMVECTORF32类型了
1.6.5 重载运算符
XMVECTOR类型针对向量的加减运算以及标量的乘法运算都提供了对应的重载运算符
1.6.6 杂项
DirectXMath定义了一组觉pi有关的常用数学常量近似值,如:
XM_CONST float XM_PI= 3.141592654f;
XM_CONST float XM_2PI = 6.283185307f;
XM_CONST float XM_1DIVPI= 0.318309886f;
XM_CONST float XM_1DIV2PI = 0.159154943f;
XM_CONST float XM_PIDIV2= 1.570796327f;
XM_CONST float XM_PIDIV4= 0.785398163f;
还有弧度和角度相互转换的内联函数,求两个数之间最大值和最小值的内联函数等等
1.6.7 Setter函数
DirectXMath库提供了下列函数以设置XMVECTOR类型中的数据
//返回0向量
XMVECTOR XM_CALLCONV XMVectorZero();
//返回(1,1,1,1)向量
XMVECTOR XM_CALLCONV XMVectorSplatone();
//返回(x,y,z,w)向量
XMVECTOR XM_CALLCONV XMVectorSet(float x,float y,float z,float w);
//返回(Value,Value,Value,Value)向量
XMVECTOR XM_CALLCONV XMVectorReplicate(float Value);
//返回(Vx,Vx,Vx,Vx)向量
XMVECTOR XM_CALLCONV XMVectorSplatX(FXMVECTOR V);
//返回(Vy,Vy,Vy,Vy)向量
XMVECTOR XM_CALLCONV XMVectorSplatY(FXMVECTOR V);
//返回(Vz,Vz,Vz,Vz)向量
XMVECTOR XM_CALLCONV XMVectorSplatZ(FXMVECTOR V);
1.6.8 向量函数
DriectXMath库提供了一些函数用来执行各种向量运算,比如计算向量的模长,计算模长的平方,叉积,两向量之间的夹角等等,这里不一一列举函数原型。
1.6.9 浮点数误差
在用计算机处理有关向量的工作时,我们应该要了解,比较浮点数时是存在误差的,在计算机中,相等的两个浮点数时有细微的差别的,比如在数学上规范化的向量的模长是1,但是在计算机上,规范化的向量的模长只能是接近1。
小结
1、向量的几何和数学表达方式
向量可以用来模拟同时具有大小和方向的物理量,在几何学上,我们用有向线段来表示向量,对向量进行标准化(将向量平移至尾部与坐标原点重合的位置)之后,我们便可以把向量的
2、向量的运算
加法,减法,标量乘法,求向量的模(长度),规范化向量,点积,叉积
3、XMVECTOR类型
DirectX一般用DirectXMath库中的XMVECTOR类型来描述向量,这样就可以利用SIMD技术进行高效的运算,对于类中的成员来说,要使用XMFLOAT2,XMFLOAT3,XMFLAOT4等等来表示向量。我们可以通过加载方法和存储方法实现XMFLOATn和XMVECTOR之间的相互转换。如果要使用常向量的初始化语法时,要使用XMVECTORF32类型
4、XMVECTOR类型做函数参数注意点(括号后面的数字为函数中对应的第几个参数)
为了提高效率,当XMVECTOR作为参数时,可以将它直接存入SSE/SSE2寄存器中而不是栈上,如果要使代码与平台无关,我们可以使用FXMVECTOR(1-3),GXMVECTOR(4),HXMVECTOR(5-6)和CXMVECTOR(其余)类型来传递XMVECTOR参数
5、一些常用运算符和方法
XMVECTOR类型重载了一些运算符用来实现向量的加法、减法、标量乘法
DirectXMath库还提供了一些便捷的方法用来计算向量的模、,模的平方、两个向量的点积、两个向量的叉积、对向量进行规范化处理。