DirectX学习之-------从零做起

      

     DirectX学习之-------从零做起_第1张图片  

    由于工作的缘故,我从运动控制领域转行到三维图形开发方面,实在是有些讽刺。不过,本人有些不太服气,别人可以学好的,我一样可以。如今要学习DirectX,可以说我还尚未入门,希望各位大虾们切莫笑话。学习DirectX的技术,当然要从基本的计算机图形学基础知识学起。

 

      坐标参照系

    1、二维笛卡尔坐标参照系

二维笛卡尔参照坐标系有两种可能形式:一种是Y轴向上,另一种是Y轴向下。也即坐标原点前一种位于左下角,后者位于左上角。在计算机中,有的将坐标远点置于屏幕左上角,有的置于屏幕中心。

DirectX学习之-------从零做起_第2张图片

   

2、XY平面的极坐标系

常用的非笛卡尔坐标系就是极坐标系。其中,坐标位置由坐标到原点的极径距离r和距水平轴的角位移量θ指定。正角的位移量是逆时针的,负的角位移量是顺时针的。从笛卡尔坐标系到极坐标系的变换公式为:

DirectX学习之-------从零做起_第3张图片

 

 

 角度可由指定度数或弧度给出。θ角的弧度值计算如下:θ=s/r.

 此外还有三维笛卡尔坐标系,这里就需要注意使用的时候是左手坐标系还是右手坐标系。比较常用的就是笛卡尔直角坐标系了,也叫正交坐标系。

  2、  点和向量
             点和向量的概念有根本的区别。点是某参照系以坐标值指定的位置,一个向量(矢量)定义为两个点位置之间的差。它有大小,有方向。对于二维向量来说:

                   

                       V=P2-P1
                       =(x2-x1,y2-y1)
                       =(Vx,Vy)

 

DirectX学习之-------从零做起_第4张图片

 

      Vx,Vy分别是V在X轴和Y轴上的投影,给定两点位置可得任何坐标系下的向量分量。
所以二维向量V的大小便是:
                              ___________      ________________
                          |V|=√ Vx2+Vy2      =√(x2-x1)2+(y2-y1)2

          

 它的方向可以根据离x轴的角位移量给出:
                      α=tan-1(Vy/Vx)

        

   而如果是三维空间向量大小则为:

                              _______________
                      |V|=√ Vx2+Vy2+Vz2
       
         

  V,即是向量的长度也叫做向量的模。
          

 此中向量的方向由方向角α、β、γ给出,其实就是求该向量与各个坐标轴形成的角:

                 

     cosα=Vx / |V|`       cosβ=Vy / |V|`      cosγ=Vz / |V|

          

     cosα、cosβ、cosγ为向量的方向余弦。实际上为指定V的方向,只需两个方向余弦。因为:

                

      cos2α+cos2β+cos2γ=1

         

  2.1  向量相加与定比例相乘

                   

              V1+V2=(V1x+V2x, V1y+V2y, V1z+V2z)
 
               向量与标量相加无意义。因为标量是一个数值,向量可能有多个数值分量。
               

               向量与标量的乘法(数乘):aV=(aVx,aVy,aVz)

   2.2   两个向量的标量积

             

          产生标量的向量乘法:V1*V2=|V1||V2|cosθ               0≤θ≤π
               

 在笛卡尔坐标系中标量积(点乘)的计算:  V1*V2= V1x*V2x  + V1y*V2y + V1z*V2z

  而点积是可以交换的:V1*V2 = V2*V1
  点积(点乘)的关于向量是遵循加法分配律的:V1*(V2+V3)=V1*V2 + V1*V3

  由标量积,我们可知:
  两向量相乘:
                      结果等于0,则两向量互相垂直;
                      结果大于0,则两向量之间的夹角小于90度;
                      结果小于0,则两向量之间的夹角大于90度。

        
    2.3      两向量的向量积 (叉积)

          能产生一个向量的两个向量的乘法:V1  ×(注:叉乘)  V2=u|V1||V2|sinθ               0≤θ≤π

            

        u是垂直与V1  、  V2 的单位向量(1),而u的方向则取决于使用的坐标系是左手还是右手,拇指方向即为u的方向。这个积叫做两个向量的叉积(向量积)。它是垂直与两个向量所在平面的向量,他的大小等于这两个向量与坐标轴形成的平行四边形的面积。

            

       当然,也可以借助指定坐标系的向量分量来表达叉积。笛卡尔坐标系中:
       叉积的分量=V1  ×(叉乘)  V2=(V1y*V2x - V1z*V2y , V1z*V2x - V1x*V2z , V1x*V2y - V1y*V2x)

       如果令ux、uy、uz 表示沿x, y ,z 轴的单位向量, 那借助笛卡尔分量以行列格式写出叉积,则:
                          |   ux     uy     uz      |
          V1 X V2 = | V1x    V1y    V1z   |          
                          |   V2x    V2y    V2z |
   

         任意两个平行向量的叉积是0。这里需要注意叉积并不满足交换律,而是满足反交换律 :V1 X V2 = -(V2 X V1)
          此外,叉积并不满足结合律 V1 X (V2 X V3)≠(V1 X V2) X V3
          不过叉积关于向量的加法还是可以分配的:V1 X (V2 + V3)≠(V1 X V2) +(V1 X V3)

 

在D3D中,点与向量关系密切。在D3D库中,表示向量的数据结构有:

 D3DXVECTOR2 ,D3DXVECTOR3,D3DXVECTOR4

 

 

1 typedef struct D3DXVECTOR3 : public D3DVECTOR
2 {
3  public:
4
5 D3DXVECTOR3() {};
6 D3DXVECTOR3( CONST FLOAT * );
7 D3DXVECTOR3( CONST D3DVECTOR& );
8 D3DXVECTOR3( CONST D3DXFLOAT16 * );
9 D3DXVECTOR3( FLOAT x, FLOAT y, FLOAT z );
10
11  // casting 类型转换
12  operator FLOAT* ();
13  operator CONST FLOAT* () const;
14
15  // assignment operators 分配运算符
16  D3DXVECTOR3& operator += ( CONST D3DXVECTOR3& );
17 D3DXVECTOR3& operator -= ( CONST D3DXVECTOR3& );
18 D3DXVECTOR3& operator *= ( FLOAT );
19 D3DXVECTOR3& operator /= ( FLOAT );
20
21 // unary operators 一元运算
22 D3DXVECTOR3 operator + () const;
23 D3DXVECTOR3 operator - () const;
24
25 // binary operators 二元运算
26 D3DXVECTOR3 operator + ( CONST D3DXVECTOR3& ) const;
27 D3DXVECTOR3 operator - ( CONST D3DXVECTOR3& ) const;
28 D3DXVECTOR3 operator * ( FLOAT ) const;
29 D3DXVECTOR3 operator / ( FLOAT ) const;
30 friend D3DXVECTOR3 operator * ( FLOAT, CONST struct D3DXVECTOR3& );
31 BOOL operator == ( CONST D3DXVECTOR3& ) const;
32 BOOL operator != ( CONST D3DXVECTOR3& ) const;
33
34 } D3DXVECTOR3, *LPD3DXVECTOR3;
35
36 //D3DXVECTOR3是从D3DVECTOR继承的
37
38 typedef struct _D3DVECTOR {
39 float x, y, z;
40 } D3DVECTOR;
41
42

 

 

   
   
   
   
1
6
7
8 // 计算向量大小:
9
10 FLOAT D3DXVec3Length( // Returns the magnitude.返回大小
11 CONST D3DXVECTOR3 * pV // The vector to compute the length of. 计算向量长度
12 );
13 D3DXVECTOR3 v( 1.0f , 2.0f , 3.0f );
14 float magnitude = D3DXVec3Length( & v ); // = sqrt(14)
15
16
17
18 // 规范(单位)化向量:
19
20 D3DXVECTOR3 * D3DXVec3Normalize(
21 D3DXVECTOR3 * pOut, // Result.
22 CONST D3DXVECTOR3 * pV // The vector to normalize.
23 );
24
25
26
27 // 向量加、减法:
28
29 D3DXVECTOR3 u( 2.0f , 0.0f , 1.0f );
30 D3DXVECTOR3 v( 0.0f , - 1.0f , 5.0f );
31 // (2.0 + 0.0, 0.0 + (-1.0), 1.0 + 5.0)
32 D3DXVECTOR3 sum = u + v; // = (2.0f, -1.0f, 6.0f)
33
34
35 D3DXVECTOR3 u( 2.0f , 0.0f , 1.0f );
36 D3DXVECTOR3 v( 0.0f , - 1.0f , 5.0f );
37 D3DXVECTOR3 difference = u - v; // = (2.0f, 1.0f, -4.0f)
38
39
40
41 // 数乘:
42
43 D3DXVECTOR3 u( 1.0f , 1.0f , - 1.0f );
44 D3DXVECTOR3 scaledVec = u * 10.0f ; // = (10.0f, 10.0f, -10.0f)
45
46
47
48 // 标量积(点积、点乘):
49
50 FLOAT D3DXVec3Dot( // Returns the result.
51 CONST D3DXVECTOR3 * pV1, // Left sided operand.
52 CONST D3DXVECTOR3 * pV2 // Right sided operand.
53 );
54 D3DXVECTOR3 u( 1.0f , - 1.0f , 0.0f );
55 D3DXVECTOR3 v( 3.0f , 2.0f , 1.0f );
56 // 1.0*3.0 + -1.0*2.0 + 0.0*1.0
57 // = 3.0 + -2.0
58 float dot = D3DXVec3Dot( & u, & v ); // = 1.0
59
60
61 // 叉乘:
62
63 D3DXVECTOR3 * D3DXVec3Cross(
64 D3DXVECTOR3 * pOut, // Result.
65 CONST D3DXVECTOR3 * pV1, // Left sided operand.
66 CONST D3DXVECTOR3 * pV2 // Right sided operand.
67 );
68
69


2.4   矩阵

  若干个量组成的长方形队列就是矩阵。这些量自然就是矩阵的元素。这些量可以是数字、函数、数值表达式等,以行数和列数标识。行列相等的矩阵也叫方阵。如一个m*n的矩阵为:

                {a11   a12  ...  a1n }
             A=| a21   a22  ...  a2n  |
                {am1  am2  ...  amn}

            

 ajk的意思是矩阵A的j行,k列元素。也就是说任何元素的第一个下标代表行数,第二个为列数。 矩阵可以认为是行向量或列向量的集合,数学中往往以列矩阵表示向量:

                { Vx }
             V=|  Vy  |
                { Vz }

       

 2.4.1   标量乘法和矩阵加法

              

 标量乘法:
                  若 矩阵A乘以标量S,则:S乘以A中的每一个元素从而得到相乘所得的矩阵。(S*ajx);
              

 矩阵加法:
                  矩阵加法只有在两个矩阵行数和列数都相等才有意义,运算时各元素对应相加即可。矩阵加法满足分配律。

  2.4.2  矩阵乘法

                 矩阵A的列数等于矩阵B的行数时:乘积矩阵C=A的行元素与B的列元素乘积的和  Ex:

        
                { 0  -1 }                     {0*1+(-1)*3         0*2+(-1)*4 }     { -3    -4 }
                 |  5    7  |  * { 1  2 } =  | 5*1+7*3              5*2+7*4    |  =   |  26   38  |
                {-2   8 }     { 3  4 }    {-2*1+8*3             -2*2+8*4 }     { 22   28 }

              

           此外,矩阵乘法并不满足交换律。
                
 2.4.3  矩阵转置

             

      矩阵转置由矩阵的行列元素颠倒得到,即:原有的行元素成为列元素;列元素成为行元素。
      对于矩阵的积,转置遵循以下规则:(AB)T=BTAT

           

2.4.4  矩阵的秩

              

   对于方阵,可以组合矩阵单元以生成数,称为秩。秩的定义是递归的。

               Ex:一个2*2矩阵,二价秩的定义为:

                  | a11  a12 |
                  | a21  a22 | =  a11*a22-a12*a21

                       

     借助较低的秩可以计算较高的秩。计算3价以上的秩的时候可以以n x n矩阵的任意k列,按以下公式计算:
                         

                         n

             det A= ∑    (-1)j+k ajkdetAjk
                         j=1


               detA∫k是从矩阵A删掉第j行和第k列得到的子矩阵.

 

               当计算大矩阵的秩,通常采用数值法。计算秩的一种途径是把矩阵分解成两个因子 A=LU,矩阵L在对角线上的所有元素为0,而矩阵U在对角线以下的所有元素为0 , 计算L和U的积,两积相乘就可以得到detA,

       该方法是基于秩的如下特征:det(AB)=(detA)(detB)

               对于秩不太理解的地方,可以等后面用到时候以实例做参照理解。

          

2.4.5  矩阵的逆矩阵

               对于方阵当且仅当矩阵的秩不为0的时候,我们可以得到它的逆矩阵,一个n x n矩阵的逆矩阵记作A-1,且AA-1=A-1A=I

               I为单位矩阵,其对角线元素为1,其余为0。

               逆矩阵A-1的元素,可以从A的元素计算得来:
                      
                     ajk-1  ={ (-1)j+k detAjk }  /  detA

 

               ajk-1是A-1第j行和第k列的单元 ,  而Ajk 是从A删去第j行和第k列得到的子矩阵。

              

          来看一个例子:

             

          考虑等式p’= pR 并且假设我们知道p’和R想求p。首先找到R–1,一旦求得R–1,我们便能求出p,就象这样:

 

DirectX学习之-------从零做起_第5张图片

 

               由上,简单总结下逆矩阵:
              
                   ● 只有正方形的矩阵(方阵)才能求逆,因此当我们说矩阵求逆,那么它就是方矩阵。
                   ● n×n矩阵A的逆矩阵是一个n×n矩阵表示为A–1
                   ● 不是每个方矩阵都逆矩阵
                   ● 矩阵和它的逆矩阵相乘得到一个单位矩阵:A A–1 = A–1A = I。注意当我们进行这样的操作时矩阵是可交换的。

          

2.4.6  矩阵与D3D

          在D3D中表示1×4的行向量,我们用D3DXVECTOR3和D3DXVECTOR4向量类。当然D3DXVECTOR3只3个成员,不是4个。然而,第4个成员缺省是1或0。
        

  D3D表示4×4矩阵,用D3DXMATRIX类:

 

   
   
   
   
1 typedef struct D3DXMATRIX : public D3DMATRIX {
2 public :
3 D3DXMATRIX() {};
4 D3DXMATRIX( CONST FLOAT * );
5 D3DXMATRIX( CONST D3DMATRIX & );
6 D3DXMATRIX( FLOAT _11, FLOAT _12, FLOAT _13, FLOAT _14,
7 FLOAT _21, FLOAT _22, FLOAT _23, FLOAT _24,
8 FLOAT _31, FLOAT _32, FLOAT _33, FLOAT _34,
9 FLOAT _41, FLOAT _42, FLOAT _43, FLOAT _44 );
10 // access grants
11 FLOAT & operator () ( UINT Row, UINT Col );
12 FLOAT operator () ( UINT Row, UINT Col ) const ;
13
14 // casting operators
15 operator FLOAT * ();
16 operator CONST FLOAT * () const ;
17
18 // assignment operators
19 D3DXMATRIX & operator *= ( CONST D3DXMATRIX & );
20 D3DXMATRIX & operator += ( CONST D3DXMATRIX & );
21 D3DXMATRIX & operator -= ( CONST D3DXMATRIX & );
22 D3DXMATRIX & operator *= ( FLOAT );
23 D3DXMATRIX & operator /= ( FLOAT );
24
25 // unary operators
26 D3DXMATRIX operator + () const ;
27 D3DXMATRIX operator - () const ;
28
29 // binary operators
30 D3DXMATRIX operator * ( CONST D3DXMATRIX & ) const ;
31 D3DXMATRIX operator + ( CONST D3DXMATRIX & ) const ;
32 D3DXMATRIX operator - ( CONST D3DXMATRIX & ) const ;
33 D3DXMATRIX operator * ( FLOAT ) const ;
34 D3DXMATRIX operator / ( FLOAT ) const ;
35 friend D3DXMATRIX operator * ( FLOAT, CONST D3DXMATRIX & );
36 BOOL operator == ( CONST D3DXMATRIX & ) const ;
37 BOOL operator != ( CONST D3DXMATRIX & ) const ;
38 } D3DXMATRIX, * LPD3DXMATRIX;
39
40
41
42
43
44
45 //D3DXMATRIX类是从D3DMATRIX结构继承的:
46
47 typedef struct _D3DMATRIX {
48 union {
49 struct {
50 float _11, _12, _13, _14;
51 float _21, _22, _23, _24;
52 float _31, _32, _33, _34;
53 float _41, _42, _43, _44;
54 };
55 float m[ 4 ][ 4 ];
56 };
57 } D3DMATRIX;
58
59

 

 

 

          D3DXMATRIX类可以发现很多运算符,如检测矩阵相等,相加减,与数相乘,铸造casting,以及非常重要的两个D3DXMATRIXs彼此相乘。
 

   
   
   
   
1 D3DXMATRIX A(…); // 初始化矩阵 A
2 D3DXMATRIX B(…); // 初始化矩阵 B
3 D3DXMATRIX C = A * B; // C = AB

 

 


          D3DXMATRIX类另一个重要的运算符是小括号,它允许我们非常方便的为矩阵成员赋值。当用小括号时下标就象数组下标一样是从0开始的。例如,访问矩阵的第ij = 11 成员:

 

   
   
   
   
1 D3DXMATRIX M;
2 M( 0 , 0 ) = 5.0f ; // 设置入口 ij = 11 to 5.0f.

 

 


          D3D库也提供了一些函数:如将D3DXMATRIX转化为单位矩阵,转置D3DXMATRIX矩阵及求逆矩阵。


 

   
   
   
   
1 D3DXMATRIX * D3DXMatrixIdentity(
2 D3DXMATRIX * pout
3 );
4
5 // 参数:
6
7 // pOut 指向D3DXMATRIX结构的返回单位矩阵。
8
9 // 返回值:
10
11 // 指向D3DXMATRIX 结构的单位矩阵。
12
13 D3DXMATRIX M;
14 D3DXMatrixIdentity( & M ); // M = 单位矩阵
15
16 D3DXMATRIX * D3DXMatrixTranspose(
17 D3DXMATRIX * pOut,
18 CONST D3DXMATRIX * pM
19 );
20
21 // 参数:
22 // pOut
23 // 指向D3DXMATRIX 结构的操作结果矩阵。
24 // pM
25 // 指向D3DXMATRIX 结构的源矩阵。
26 // 返回值:
27 // 指向D3DXMATRIX 结构的转置矩阵。
28
29 // 说明:
30 // 函数返回值跟pOut 参数返回值是一样的。这样可以让函数D3DXMatrixTranspose作为其它函数的参数使用。
31
32
33 D3DXMATRIX A(...); // initialize A
34 D3DXMATRIX B;
35 D3DXMatrixTranspose( & B, & A ); // B = transpose(A)
36
37 D3DXMATRIX * D3DXMatrixInverse(
38 D3DXMATRIX * pOut,
39 FLOAT * pDeterminant,
40 CONST D3DXMATRIX * pM
41 );
42
43 // 参数:
44 // pOut
45 // 指向D3DXMATRIX结构的逆矩阵。
46 // pDeterminant
47 // 指向FLOAT 类型的对角线[1,1][2,2][3,3][4,4]积,如果不需要,可以设置为 NULL。
48 // pM
49 // 指向 D3DXMATRIX 结构源矩阵。
50
51 // 返回值:
52 // 指向D3DXMATRIX 结构的逆矩阵。如果没有逆矩阵,就返回NULL值。
53 // 返回值是跟pOut 参数的返回值是一样的,这样可以让本函数成为其它函数的参数。
54
55
56
57

 假如我们将不能求逆的矩阵用求逆函数,那么函数将会返回null.同样的,这本书我们忽视第二个参数,并且总是把它设置为0。

 

 

   
   
   
   
1 D3DXMATRIX A(...); // 初始化 A
2 D3DXMATRIX B;
3 D3DXMatrixInverse( & B, 0 , & A ); // B = 逆(A)

 

 

 

 

   

 

你可能感兴趣的:(数据结构,vector,struct,float,图形,casting)