向量(也叫矢量,英文叫vector)
向量就是包含大小(长度)和方向的一个量。向量有2维的,也有3维甚至4维的。在DX的所有结构体中,有一个结构体是用来表示3维向量的,它就是D3DVECTOR,这个结构体很简单,只有三个成员:x、y、z。一般来说,如果不涉及到向量运算的话,用这个结构体来定义一个向量就可以了。我们可以它来表示方向以及顶点在3D世界中的位置等。如果你要对那些向量进行一些运算的话,使用D3DVECTOR就很不方便了,因为在D3DVECTOR这个结构体中没有重载任何的运算符,如果想要做一个加法运算,就得分别对结构体中的每一个成员进行运算了。嘿嘿,不用怕,在DX里面有个叫D3DX的东东(包含d3dx.h头文件),它里面定义了很多方便我们进行数学计算的函数和结构。其中就有D3DXVECTOR2,D3DXVECTOR3,D3DXVECTOR4这三个结构体。看它们的名字就应该知道它们的作用了吧。对于2维和4维的结构体这里就不讲了,其实它们也很简单,和D3DXVECTOR3差不多。不过要说明一点的是D3DXVECTOR3是从D3DVECTOR派生过来的,说明它和D3DVECTOR一样,有x、y、z这三个成员,除此之外,D3DXVECTOR3还重载了小部分算术运算符,这样我们就可以像对待整型那样对D3DXVECTOR3的对象进行加减乘除以及判断是否相等的运算了。同时,由于D3DXVECTOR3是从D3DVECTOR派生过来的,所以两者的对象可以互相赋值,在这两种类型中随便转换。
还是简单说一下向量的数学运算吧。矢量的加减法很简单,就是分别把两个向量的各个分量作加减运算。向量的乘除法也很简单,它只能对一个数值进行乘除法,运算的结果就是向量中的各个分量分别对那个数值进行乘除法后得出的结果。向量的模就是向量的长度,就是各个分量的平方的和的开方。向量的标准化就是使得向量的模为1,这对在3D世界中实现光照是很有用的。对于向量的运算,还有两个“乘法”,那就是点乘和叉乘了。点乘的结果就是两个向量的模相乘,然后再与这两个向量的夹角的余弦值相乘。或者说是两个向量的各个分量分别相乘的结果的和。很明显,点乘的结果就是一个数,这个数对我们分析这两个向量的特点很有帮助。如果点乘的结果为0,那么这两个向量互相垂直;如果结果大于0,那么这两个向量的夹角小于90度;如果结果小于0,那么这两个向量的夹角大于90度。对于叉乘,它的运算公式令人头晕,我就不说了,大家看下面的公式自己领悟吧……
//v3 = v1 X v2
v3.x = v1.y*v2.z – v1.z*v2.y
v3.y = v1.z*v2.x – v1.x*v2.z
v3.z = v1.x*v2.y – v1.y*v2.x
是不是很难记啊,如果暂时记不了就算了。其实我们主要还是要知道叉乘的意义。和点乘的结果不一样,叉乘的结果是一个新的向量,这个新的向量与原来两个向量都垂直,至于它的方向嘛,不知大家是否还记得左手定则。来,伸出你的左手,按照第一个向量(v1)指向第二个向量(v2)弯曲你的手掌,这时你的拇指所指向的方向就是新向量(v3)的方向了。通过叉乘,我们很容易就得到某个平面(由两个向量决定的)的法线了。
终于写完了上面的文字,描述数学问题可真是费劲,自己又不愿意画图,辛苦大家了。如果你觉得上面的文字很枯燥,那也没关系。因为上面的不是重点,下面介绍的函数才是希望大家要记住的。
D3DX中有很多很有用的函数,它们可以帮助我们实现上面所讲的所有运算。不过下面我只说和D3DXVECTOR3有关的函数:
计算点乘:FLOAT D3DXVec3Dot(
CONST D3DXVECTOR3* pV1,
CONST D3DXVECTOR3* pV2)
计算叉乘:D3DXVECTOR3* D3DXVec3Cross(
D3DXVECTOR3* pOut,
CONST D3DXVECTOR3* pV1,
CONST D3DXVECTOR3* pV2)
计算模:FLOAT D3DXVec3Length(
CONST D3DXVECTOR3* pV)
标准化向量:D3DXVECTOR3* D3DXVec3Normalize(
D3DXVECTOR3* pOut,
CONST D3DXVECTOR3 pV)
对于D3DXVECTOR3的加减乘除运算,上面已经讲了,用+ - * / 就行了。
矩阵与矩阵运算
什么是矩阵?这个概念还真不好解释,不过学过线性代数的人肯定都知道矩阵长什么样,那我在这里就不解释了。在D3D中,定义矩阵的结构体是D3DMATRIX:
typedef struct _D3DMATRIX {
union {
struct {
float _11, _12, _13, _14;
float _21, _22, _23, _24;
float _31, _32, _33, _34;
float _41, _42, _43, _44;
};
float m[4][4];
};
} D3DMATRIX;
看这个结构的样子,你就应该很清楚怎么使用它来定义一个矩阵了吧。在这里我顺便说一下C++中union的特性吧。像上面定义的结构体所示,在union里面有两个部分,一个是结构体,另一个是二维数组,它有16个元素。在union中,所有的成员都是共用一个内存块的,这是什么意思呢?继续看上面的代码,结构体中的成员_11和成员m数组的第一个元素是共用一个内存空间,即它们的值是一样的,你对_11赋值的同时也对m[0][0]进行了赋值,_11和m[0][0]的值是一样的。这样有什么好处呢?比如你定义了一个矩阵变量D3DMATRIX mat;你想访问矩阵中第三行第四列的元素,可以这样做:mat._34;另外也可以这样:mat.m[2][3](数组是从位置0开始储存的哦)。看起来使用后者比较麻烦,不过当你把中括号里面的数换成i和j,使用mat.m[i][j]来访问矩阵中的元素,你就应该知道它的好处了吧。
实际上直接使用D3DMATRIX的情况不多,因为在D3DX中有个更好的结构体,那就是D3DXMATRIX。和D3DXVECTOR3相似,D3DXMATRIX是从D3DMATRIX继承过来的,它重载了很多运算符,使得矩阵的运算很简单。矩阵的运算方法我不打算多说了,下面只介绍和矩阵性质有关的三个函数。
产生一个单位矩阵:D3DXMATRIX *D3DXMatrixIdentity(
D3DXMATRIX *pout);//返回结果
求转置矩阵:D3DXMATRIX *D3DXMatrixTranspose(
D3DXMATRIX *pOut,//返回的结果
CONST D3DXMATRIX *pM );//目标矩阵
求逆矩阵:D3DXMATRIX *D3DXMatrixInverse(
D3DXMATRIX *pOut,//返回的结果
FLOAT *pDeterminant,//设为0
CONST D3DXMATRIX *pM );//目标矩阵
至于什么是单位矩阵,什么是转置矩阵,什么是逆矩阵我就不说了,可以看一下线性代数的书,一看就明白了。简单的加减乘除法可以使用D3DXMATRIX结构体里面重载的运算符。两个矩阵相乘也可以用函数来实现,这将在接下来的矩阵变换中讲到。
矩阵变换
矩阵的基本变换有三种:平移,旋转和缩放。
平移:
D3DXMATRIX *D3DXMatrixTranslation(
D3DXMATRIX* pOut,//返回的结果
FLOAT x, //X轴上的平移量
FLOAT y, //Y轴上的平移量
FLOAT z) //Z轴上的平移量
绕X轴旋转:
D3DXMATRIX *D3DXMatrixRotationX(
D3DXMATRIX* pOut, //返回的结果
FLOAT Angle //旋转的弧度
);
绕Y轴旋转:
D3DXMATRIX *D3DXMatrixRotationY(
D3DXMATRIX* pOut, //返回的结果
FLOAT Angle //旋转的弧度
);
绕Z轴旋转:
D3DXMATRIX *D3DXMatrixRotationZ(
D3DXMATRIX* pOut, //返回的结果
FLOAT Angle //旋转的弧度
);
绕指定轴旋转:
D3DXMATRIX *D3DXMatrixRotationAxis(
D3DXMATRIX *pOut,//返回的结果
CONST D3DXVECTOR3 *pV,//指定轴的向量
FLOAT Angle//旋转的弧度
);
缩放:
D3DXMATRIX *D3DXMatrixScaling(
D3DXMATRIX* pOut, //返回的结果
FLOAT sx, //X轴上缩放的量
FLOAT sy, //Y轴上缩放的量
FLOAT sz //Z轴上缩放的量
);
向量就是包含大小(长度)和方向的一个量。向量有2维的,也有3维甚至4维的。在DX的所有结构体中,有一个结构体是用来表示3维向量的,它就是D3DVECTOR,这个结构体很简单,只有三个成员:x、y、z。一般来说,如果不涉及到向量运算的话,用这个结构体来定义一个向量就可以了。我们可以它来表示方向以及顶点在3D世界中的位置等。如果你要对那些向量进行一些运算的话,使用D3DVECTOR就很不方便了,因为在D3DVECTOR这个结构体中没有重载任何的运算符,如果想要做一个加法运算,就得分别对结构体中的每一个成员进行运算了。嘿嘿,不用怕,在DX里面有个叫D3DX的东东(包含d3dx.h头文件),它里面定义了很多方便我们进行数学计算的函数和结构。其中就有D3DXVECTOR2,D3DXVECTOR3,D3DXVECTOR4这三个结构体。看它们的名字就应该知道它们的作用了吧。对于2维和4维的结构体这里就不讲了,其实它们也很简单,和D3DXVECTOR3差不多。不过要说明一点的是D3DXVECTOR3是从D3DVECTOR派生过来的,说明它和D3DVECTOR一样,有x、y、z这三个成员,除此之外,D3DXVECTOR3还重载了小部分算术运算符,这样我们就可以像对待整型那样对D3DXVECTOR3的对象进行加减乘除以及判断是否相等的运算了。同时,由于D3DXVECTOR3是从D3DVECTOR派生过来的,所以两者的对象可以互相赋值,在这两种类型中随便转换。
还是简单说一下向量的数学运算吧。矢量的加减法很简单,就是分别把两个向量的各个分量作加减运算。向量的乘除法也很简单,它只能对一个数值进行乘除法,运算的结果就是向量中的各个分量分别对那个数值进行乘除法后得出的结果。向量的模就是向量的长度,就是各个分量的平方的和的开方。向量的标准化就是使得向量的模为1,这对在3D世界中实现光照是很有用的。对于向量的运算,还有两个“乘法”,那就是点乘和叉乘了。点乘的结果就是两个向量的模相乘,然后再与这两个向量的夹角的余弦值相乘。或者说是两个向量的各个分量分别相乘的结果的和。很明显,点乘的结果就是一个数,这个数对我们分析这两个向量的特点很有帮助。如果点乘的结果为0,那么这两个向量互相垂直;如果结果大于0,那么这两个向量的夹角小于90度;如果结果小于0,那么这两个向量的夹角大于90度。对于叉乘,它的运算公式令人头晕,我就不说了,大家看下面的公式自己领悟吧……
//v3 = v1 X v2
v3.x = v1.y*v2.z – v1.z*v2.y
v3.y = v1.z*v2.x – v1.x*v2.z
v3.z = v1.x*v2.y – v1.y*v2.x
是不是很难记啊,如果暂时记不了就算了。其实我们主要还是要知道叉乘的意义。和点乘的结果不一样,叉乘的结果是一个新的向量,这个新的向量与原来两个向量都垂直,至于它的方向嘛,不知大家是否还记得左手定则。来,伸出你的左手,按照第一个向量(v1)指向第二个向量(v2)弯曲你的手掌,这时你的拇指所指向的方向就是新向量(v3)的方向了。通过叉乘,我们很容易就得到某个平面(由两个向量决定的)的法线了。
终于写完了上面的文字,描述数学问题可真是费劲,自己又不愿意画图,辛苦大家了。如果你觉得上面的文字很枯燥,那也没关系。因为上面的不是重点,下面介绍的函数才是希望大家要记住的。
D3DX中有很多很有用的函数,它们可以帮助我们实现上面所讲的所有运算。不过下面我只说和D3DXVECTOR3有关的函数:
计算点乘:FLOAT D3DXVec3Dot(
CONST D3DXVECTOR3* pV1,
CONST D3DXVECTOR3* pV2)
计算叉乘:D3DXVECTOR3* D3DXVec3Cross(
D3DXVECTOR3* pOut,
CONST D3DXVECTOR3* pV1,
CONST D3DXVECTOR3* pV2)
计算模:FLOAT D3DXVec3Length(
CONST D3DXVECTOR3* pV)
标准化向量:D3DXVECTOR3* D3DXVec3Normalize(
D3DXVECTOR3* pOut,
CONST D3DXVECTOR3 pV)
对于D3DXVECTOR3的加减乘除运算,上面已经讲了,用+ - * / 就行了。
矩阵与矩阵运算
什么是矩阵?这个概念还真不好解释,不过学过线性代数的人肯定都知道矩阵长什么样,那我在这里就不解释了。在D3D中,定义矩阵的结构体是D3DMATRIX:
typedef struct _D3DMATRIX {
union {
struct {
float _11, _12, _13, _14;
float _21, _22, _23, _24;
float _31, _32, _33, _34;
float _41, _42, _43, _44;
};
float m[4][4];
};
} D3DMATRIX;
看这个结构的样子,你就应该很清楚怎么使用它来定义一个矩阵了吧。在这里我顺便说一下C++中union的特性吧。像上面定义的结构体所示,在union里面有两个部分,一个是结构体,另一个是二维数组,它有16个元素。在union中,所有的成员都是共用一个内存块的,这是什么意思呢?继续看上面的代码,结构体中的成员_11和成员m数组的第一个元素是共用一个内存空间,即它们的值是一样的,你对_11赋值的同时也对m[0][0]进行了赋值,_11和m[0][0]的值是一样的。这样有什么好处呢?比如你定义了一个矩阵变量D3DMATRIX mat;你想访问矩阵中第三行第四列的元素,可以这样做:mat._34;另外也可以这样:mat.m[2][3](数组是从位置0开始储存的哦)。看起来使用后者比较麻烦,不过当你把中括号里面的数换成i和j,使用mat.m[i][j]来访问矩阵中的元素,你就应该知道它的好处了吧。
实际上直接使用D3DMATRIX的情况不多,因为在D3DX中有个更好的结构体,那就是D3DXMATRIX。和D3DXVECTOR3相似,D3DXMATRIX是从D3DMATRIX继承过来的,它重载了很多运算符,使得矩阵的运算很简单。矩阵的运算方法我不打算多说了,下面只介绍和矩阵性质有关的三个函数。
产生一个单位矩阵:D3DXMATRIX *D3DXMatrixIdentity(
D3DXMATRIX *pout);//返回结果
求转置矩阵:D3DXMATRIX *D3DXMatrixTranspose(
D3DXMATRIX *pOut,//返回的结果
CONST D3DXMATRIX *pM );//目标矩阵
求逆矩阵:D3DXMATRIX *D3DXMatrixInverse(
D3DXMATRIX *pOut,//返回的结果
FLOAT *pDeterminant,//设为0
CONST D3DXMATRIX *pM );//目标矩阵
至于什么是单位矩阵,什么是转置矩阵,什么是逆矩阵我就不说了,可以看一下线性代数的书,一看就明白了。简单的加减乘除法可以使用D3DXMATRIX结构体里面重载的运算符。两个矩阵相乘也可以用函数来实现,这将在接下来的矩阵变换中讲到。
矩阵变换
矩阵的基本变换有三种:平移,旋转和缩放。
平移:
D3DXMATRIX *D3DXMatrixTranslation(
D3DXMATRIX* pOut,//返回的结果
FLOAT x, //X轴上的平移量
FLOAT y, //Y轴上的平移量
FLOAT z) //Z轴上的平移量
绕X轴旋转:
D3DXMATRIX *D3DXMatrixRotationX(
D3DXMATRIX* pOut, //返回的结果
FLOAT Angle //旋转的弧度
);
绕Y轴旋转:
D3DXMATRIX *D3DXMatrixRotationY(
D3DXMATRIX* pOut, //返回的结果
FLOAT Angle //旋转的弧度
);
绕Z轴旋转:
D3DXMATRIX *D3DXMatrixRotationZ(
D3DXMATRIX* pOut, //返回的结果
FLOAT Angle //旋转的弧度
);
绕指定轴旋转:
D3DXMATRIX *D3DXMatrixRotationAxis(
D3DXMATRIX *pOut,//返回的结果
CONST D3DXVECTOR3 *pV,//指定轴的向量
FLOAT Angle//旋转的弧度
);
缩放:
D3DXMATRIX *D3DXMatrixScaling(
D3DXMATRIX* pOut, //返回的结果
FLOAT sx, //X轴上缩放的量
FLOAT sy, //Y轴上缩放的量
FLOAT sz //Z轴上缩放的量
);