2013年12月30日星期一(继续流水线--局部坐标->世界坐标)

来源:互联网 发布:美工刀具磨刀生产设备 编辑:程序博客网 时间:2024/06/09 15:52

4X4矩阵相乘是很必要的,

int ddraw_math::Mat_Mul_4X4( MATRIX4X4_PTR ma, MATRIX4X4_PTR mb, MATRIX4X4_PTR mprod )

{

    int index;

    for ( int row = 0; row < 4; row++)

    {

 

         for( int col = 0; col < 4; col ++ )

         {

             float sum             = 0;

 

             for (  index = 0; index < 4; index++ )

             {

                  sum               += ( ma->M[row][index] * mb->M[index][col]);

             }

 

             mprod->M[row][col]    = sum;

         }

    }

    return ( 1 );

}

 

下面就是用旋转X,Y,Z轴来构建矩阵,其实很简单,

绕X轴就是

    Mat_Init_4X4( & mx, 1,            0,          0,       0,

                                   0,         cos_theta, sin_theta,  0,

                                   0,         -sin_theta, cos_theta,  0,

                                   0,          0,          0,       1 );

绕Y轴,就是       Mat_Init_4X4( & my, cos_theta, 0, -sin_theta, 0,

                                    0,          1, 0,       0,

                                   sin_theta, 0, cos_theta,  0,

                                   0,          0, 0,       1 );

绕Z轴就是

         Mat_Init_4X4( & mz, cos_theta,  sin_theta,    0, 0,

                                   -sin_theta, cos_theta,    0, 0,

                                   0,           0,             1, 0,

                                   0,           0,             0, 1 );

 

按照不同的轴旋转顺序,就是挨个级联相乘,

void ddraw_math::Build_XYZ_Rotation_MATRIX4x4(float theta_x,float theta_y,float theta_z, MATRIX4X4_PTR mrot)

{

    MATRIX4X4         mx, my, mz, mtmp;

    float             sin_theta             = 0;

    float             cos_theta             = 0;

    int               rot_seq               = 0;

 

    Mat_IDENTITY_4X4( mrot );

 

   

    if( fabs( theta_x ) > EPSILON_E5 )

         rot_seq                            = rot_seq | 1;

 

    if( fabs( theta_y ) > EPSILON_E5 )

         rot_seq                            = rot_seq | 2;

    if( fabs( theta_z ) > EPSILON_E5 )

         rot_seq                            = rot_seq | 4;

 

    switch( rot_seq )

    {

    case 0:

         {

             //不旋转

             return ;

         }

         break;

 

    case 1:

         {

             //绕X轴旋转

             cos_theta                      = Fast_Cos( theta_x );

             sin_theta                      = Fast_Sin( theta_x );

             Mat_Init_4X4( & mx, 1,            0,          0,       0,

                                   0,         cos_theta, sin_theta,  0,

                                   0,         -sin_theta, cos_theta,  0,

                                   0,          0,          0,       1 );

             MAT_COPY_4X4( & mx, mrot );

 

             return;

         }

         break;

    case 2:

         {

             //绕Y轴旋转

             cos_theta                      = Fast_Cos( theta_y );

             sin_theta                      = Fast_Sin( theta_y );

             Mat_Init_4X4( & my, cos_theta, 0, -sin_theta, 0,

                                   0,          1, 0,       0,

                                   sin_theta, 0, cos_theta,  0,

                                   0,          0, 0,       1 );

             MAT_COPY_4X4( & my, mrot );

 

             return;

         }

         break;

 

    case 3:           //绕XY轴旋转

         {

            

             cos_theta                      = Fast_Cos( theta_x );

             sin_theta                      = Fast_Sin( theta_x );

             Mat_Init_4X4( & mx, 1,            0,          0,       0,

                                   0,         cos_theta, sin_theta,  0,

                                   0,         -sin_theta, cos_theta,  0,

                                   0,          0,          0,       1 );

 

             cos_theta                      = Fast_Cos( theta_y );

             sin_theta                      = Fast_Sin( theta_y );

             Mat_Init_4X4( & my, cos_theta, 0, -sin_theta, 0,

                                   0,          1, 0,       0,

                                   sin_theta, 0, cos_theta,  0,

                                   0,          0, 0,       1 );

            

             Mat_Mul_4X4( & mx, & my, mrot );

            

             return;

         }

         break;

 

    case 4:      //绕z轴旋转

         {

             cos_theta                      = Fast_Cos( theta_z );

             sin_theta                      = Fast_Sin( theta_z );

             Mat_Init_4X4( & mz, cos_theta,  sin_theta,    0, 0,

                                   -sin_theta, cos_theta,    0, 0,

                                   0,           0,             1, 0,

                                   0,           0,             0, 1 );

             MAT_COPY_4X4( & mz, mrot );

 

             return;

         }

         break;

 

    case 5:

         {

             //绕XZ轴旋转

             cos_theta                      = Fast_Cos( theta_x );

             sin_theta                      = Fast_Sin( theta_x );

             Mat_Init_4X4( & mx, 1,            0,          0,       0,

                                   0,         cos_theta, sin_theta,  0,

                                   0,         -sin_theta, cos_theta,  0,

                                   0,          0,          0,       1 );

 

             cos_theta                      = Fast_Cos( theta_z );

             sin_theta                      = Fast_Sin( theta_z );

             Mat_Init_4X4( & mz, cos_theta,  sin_theta,    0, 0,

                                   -sin_theta, cos_theta,    0, 0,

                                   0,           0,             1, 0,

                                   0,           0,             0, 1 );

 

             Mat_Mul_4X4( & mx, & mz, mrot );

            

             return;

         }

         break;

 

    case 6:               //y,z旋转

         {

             cos_theta                      = Fast_Cos( theta_y );

             sin_theta                      = Fast_Sin( theta_y );

             Mat_Init_4X4( & my, cos_theta, 0, -sin_theta, 0,

                                   0,          1, 0,       0,

                                   sin_theta, 0, cos_theta,  0,

                                   0,          0, 0,       1 );

 

             cos_theta                      = Fast_Cos( theta_z );

             sin_theta                      = Fast_Sin( theta_z );

             Mat_Init_4X4( & mz, cos_theta,  sin_theta,    0, 0,

                                   -sin_theta, cos_theta,    0, 0,

                                   0,           0,             1, 0,

                                   0,           0,             0, 1 );

 

             Mat_Mul_4X4( & my, & mz, mrot );

            

             return;

         }

         break;

 

    case 7:      //X,Y,Z旋转

         {

             cos_theta                      = Fast_Cos( theta_x );

             sin_theta                      = Fast_Sin( theta_x );

             Mat_Init_4X4( & mx, 1,            0,          0,       0,

                                   0,         cos_theta, sin_theta,  0,

                                   0,         -sin_theta, cos_theta,  0,

                                   0,          0,          0,       1 );

 

             cos_theta                      = Fast_Cos( theta_y );

             sin_theta                      = Fast_Sin( theta_y );

             Mat_Init_4X4( & my, cos_theta, 0, -sin_theta, 0,

                                   0,          1, 0,       0,

                                   sin_theta, 0, cos_theta,  0,

                                   0,          0, 0,       1 );

 

             cos_theta                      = Fast_Cos( theta_z );

             sin_theta                      = Fast_Sin( theta_z );

             Mat_Init_4X4( & mz, cos_theta,  sin_theta,    0, 0,

                                   -sin_theta, cos_theta,    0, 0,

                                   0,           0,             1, 0,

                                   0,           0,             0, 1 );

 

             Mat_Mul_4X4( &mx, &my, &mtmp );

             Mat_Mul_4X4( &mtmp, &mz, mrot );

         }

         break;

 

    default:

         break;

         }

   

}

继续进行,在每帧中,根据X,Y,Z轴旋转值进行矩阵构建,这里只是按照Y轴旋转

    static MATRIX4X4  mrot;

    static float      ang_y             = 0;

    math.Build_XYZ_Rotation_MATRIX4x4( 0, ang_y, 0, &mrot );

这里还给了个慢慢旋转,每帧1度

    if( ++ang_y >= 360.0 )

         ang_y                              = 0;

 

整理了以前的common.h,过于杂乱了,不好找了,归到各个类中,OK

下一步就是建立一个渲染列表,统一渲染各顶点

 

//变换控制标记

#define  TRANSFORM_LOCAL_ONLY               0                //对局部坐标进行变换

#define  TRANSFORM_TRANS_ONLY               1                //对变换后的坐标进行变换

#define  TRANSFORM_LOCAL_TO_TRANS           2                //对据不做表进行变换,并将结果存储为变换后的坐标

 

在此之前,先进行个四元数和4X4矩阵的乘法,

void ddraw_math::Mat_Mul_VECTOR4D_4X4( VECTOR4D_PTR va, MATRIX4X4_PTR mb, VECTOR4D_PTR vprod )

{

    for( int col = 0; col < 4; col ++ )

    {

         float        sum          = 0;

         for( int row = 0; row < 4; row ++ )

         {

             sum                   += ( va->M[row] * mb->M[row][col] );

         }

         vprod->M[col]             = sum;

    }

}

 

//复制4D向量

void ddraw_math::VECTOR4D_COPY( VECTOR4D_PTR vdst, VECTOR4D_PTR vsrc )

{

    vdst->x                        = vsrc->x;

    vdst->y                        = vsrc->y;

    vdst->z                        = vsrc->z;

    vdst->w                        = vsrc->w;

}

 

渲染列表分这3种情况

 

void ddraw_liushuixian::Transform_RENDERLIST4DV1(RENDERLIST4DV1_PTR rend_list,

                                                      MATRIX4X4_PTR mt,            //变换矩阵

                                                      int coord_select,

                                                      ddraw_math math )            //指定要变换的坐标

{

    switch(  coord_select )

    {

    case TRANSFORM_LOCAL_ONLY:

         {

             for( int poly = 0; poly < rend_list->num_polys; poly++ )

             {

                  //获得当前多边形

                  POLYF4DV1_PTR         curr_poly                 = rend_list->poly_ptrs[poly];

                  //在线框引擎中,当前仅当多边形处于活动状态并可见时对其进行变换

                  if( ( curr_poly   == NULL ) ||

                      ! ( curr_poly->state & POLY4DV1_STATE_ACTIVE ) ||

                      ( curr_poly->state & POLY4DV1_STATE_CLIPPED ) ||

                      ( curr_poly->state & POLY4DV1_STATE_BACKFACE ) )

                      continue;            //进入下一个多边形

 

                  //满足条件,进行变换

                  for( int vertex = 0; vertex < 3; vertex ++ )

                  {

                      //使用矩阵mt对顶点进行变换

                      POINT4D           presult;     //用于暂时存储变换结果

                      math.Mat_Mul_VECTOR4D_4X4( & curr_poly->vlist[vertex], mt, & presult );

                      math.VECTOR4D_COPY( & curr_poly->vlist[vertex], & presult );

                  }

             }

         }

         break;

 

    case TRANSFORM_TRANS_ONLY:

         {

             for( int poly = 0; poly < rend_list->num_polys; poly++ )

             {

                  //获得当前多边形

                  POLYF4DV1_PTR         curr_poly                 = rend_list->poly_ptrs[poly];

                  //在线框引擎中,当前仅当多边形处于活动状态并可见时对其进行变换

                  if( ( curr_poly   == NULL ) ||

                      ! ( curr_poly->state & POLY4DV1_STATE_ACTIVE ) ||

                      ( curr_poly->state & POLY4DV1_STATE_CLIPPED ) ||

                      ( curr_poly->state & POLY4DV1_STATE_BACKFACE ) )

                      continue;            //进入下一个多边形

 

                  //满足条件,进行变换

                  for( int vertex = 0; vertex < 3; vertex ++ )

                  {

                      //使用矩阵mt对顶点进行变换

                      POINT4D           presult;     //用于暂时存储变换结果

                      math.Mat_Mul_VECTOR4D_4X4( & curr_poly->tvlist[vertex], mt, & presult );

                      math.VECTOR4D_COPY( & curr_poly->tvlist[vertex], & presult );

                  }

             }

         }

         break;

 

         case TRANSFORM_LOCAL_TO_TRANS:

         {

             for( int poly = 0; poly < rend_list->num_polys; poly++ )

             {

                  //获得当前多边形

                  POLYF4DV1_PTR         curr_poly                 = rend_list->poly_ptrs[poly];

                  //在线框引擎中,当前仅当多边形处于活动状态并可见时对其进行变换

                  if( ( curr_poly   == NULL ) ||

                      ! ( curr_poly->state & POLY4DV1_STATE_ACTIVE ) ||

                      ( curr_poly->state & POLY4DV1_STATE_CLIPPED ) ||

                      ( curr_poly->state & POLY4DV1_STATE_BACKFACE ) )

                      continue;            //进入下一个多边形

 

                  //满足条件,进行变换

                  for( int vertex = 0; vertex < 3; vertex ++ )

                  {

                      //使用矩阵mt对顶点进行变换

                      math.Mat_Mul_VECTOR4D_4X4( & curr_poly->vlist[vertex], mt, & curr_poly->tvlist[vertex] );

                  }

             }

         }

         break;

 

         default:

             break;

    }

 

}                                                                

 

修正一下,改为如下:

 

typedef struct POLYF4DV1_TYP

{

    int                                state;      //状态信息

    int                                attr;       //多边形的物理属性,如材质等

    int                                color;      //多边形的颜色

 

    POINT4D                            vlist[3];    //顶点列表

    POINT4D                            tvlist[3];   //变换后的顶点

    POLYF4DV1_TYP         *            next;        //指向列表中下一个多边形的指针

    POLYF4DV1_TYP         *            prev;        //指向列表中前一个多边形的指针

}POLYF4DV1, * POLYF4DV1_PTR;

 

下面,继续进行模型坐标系到世界坐标系。因为三角形没有放缩,平移过了,所以这一步只需要平移即可。

 

 

VECTOR4D ddraw_math::VECTOR4D_ADD(VECTOR4D_PTR va, VECTOR4D_PTR vb)

{

    VECTOR4D     vsum;

 

    vsum.x                                 = va->x + vb->x;

    vsum.y                                 = va->y + vb->y;

    vsum.z                                 = va->z + vb->z;

    vsum.w                                 = 1;

 

    return vsum;

 

}

以及另外一种方式

 

void ddraw_math::VECTOR4D_ADD( VECTOR4D_PTR va, VECTOR4D_PTR vb, VECTOR4D_PTR vsum )

{

    vsum.x                                 = va->x + vb->x;

    vsum.y                                 = va->y + vb->y;

    vsum.z                                 = va->z + vb->z;

    vsum.w                                 = 1;

 

}

这里用渲染列表进行局部坐标到世界坐标

 

void ddraw_liushuixian::Model_To_World_RENDERLIST4DV1(RENDERLIST4DV1_PTR rend_list, POINT4D_PTR world_pos,int coord_select, ddraw_math math )

{

    if( coord_select == TRANSFORM_LOCAL_TO_TRANS )

    {

         for( int poly = 0; poly < rend_list->num_polys; poly++ )

         {

             //获得当前多边形

             POLYF4DV1_PTR         curr_poly                 = rend_list->poly_ptrs[poly];

 

             //当且仅当多边形没有被剔除或者裁剪掉,同时处于活动状态且可见时,才对其进行变换)

             if( ( curr_poly == NULL ) ||

                  !( curr_poly->state & POLY4DV1_STATE_ACTIVE ) ||

                  ( curr_poly->state & POLY4DV1_STATE_CLIPPED ) ||

                  ( curr_poly->state & POLY4DV1_STATE_BACKFACE ) )

                  continue;    //进入下一个多边形

 

             //满足条件,对其进行变换

             for( int vertex = 0; vertex < 3; vertex ++ )

             {

                  //平移顶点

                  math.VECTOR4D_ADD( & curr_poly->vlist[vertex], world_pos, & curr_poly->tvlist[vertex] );

             }

         }

    }

    else

    {

         for( int poly = 0; poly < rend_list->num_polys; poly++ )

         {

             //获得当前多边形

             POLYF4DV1_PTR         curr_poly                 = rend_list->poly_ptrs[poly];

 

             //当且仅当多边形没有被剔除或者裁剪掉,同时处于活动状态且可见时,才对其进行变换)

             if( ( curr_poly == NULL ) ||

                  !( curr_poly->state & POLY4DV1_STATE_ACTIVE ) ||

                  ( curr_poly->state & POLY4DV1_STATE_CLIPPED ) ||

                  ( curr_poly->state & POLY4DV1_STATE_BACKFACE ) )

                  continue;    //进入下一个多边形

 

             //满足条件,对其进行变换

             for( int vertex = 0; vertex < 3; vertex ++ )

             {

                  //平移顶点

                  math.VECTOR4D_ADD( & curr_poly->tvlist[vertex], world_pos, & curr_poly->tvlist[vertex] );

             }

         }

    }                

 

 

每帧

    liushuixian.Model_To_World_RENDERLIST4DV1( & rend_list, & poly1_pos, TRANSFORM_LOCAL_TO_TRANS, math );

0 0
原创粉丝点击