搜索
您的当前位置:首页正文

2013年9月10日星期二(DEMO8_6矩阵)

来源:爱go旅游网

1,把所有的点存储为1*2矩阵

 

         typedef struct MATRIX1X2_TYP

         {

                   float M[2];

         }MATRIX1X2, * MATRIX1X2_PTR;

M     =      |X Y|

,2把所有变换矩阵采用3*2矩阵

typedef struct MATRIX3X2_TYP

         {

                   float M[3][2];

         }MATRIX3X2, * MATRIX3X2_PTR;

分为平移,缩放,旋转3种

(1)        平移

Mt    =       | 1  0  0 |

                   | 0  1  0 |

                   |dx dy  1 |

(2)缩放

                   |sx  0  0 |

MS   =       |0  sy  0 |

                   |0  0   0|

(3)旋转

                   |cosA   sinA    0|

Mr  =       |-sinA   cosA   0|

                   |  0           0       1|

 

平移(矩阵方式)

下面这个函数用来写平移实在是没效率,不过正如作者所说,是个教学目的。不过非常熟悉矩阵了。

int Translate_Polygon2D_Mat( POLYGON2D_PTR poly, int dx, int dy )

{

         if( ! poly )

         {

                   return ( 0 );

         }

         MATRIX3X2 mt;

         Mat_Init_3X2( & mt, 1, 0, 0, 1, dx, dy );

         MATRIX1X2   p0                       = { poly->x0, poly->y0 };

         MATRIX1X2   p1                       = { 0, 0 };

 

         Mat_Mul1X2_3X2( & p0, & mt, & p1 );

 

         poly->x0                              = p1.M[0];

         poly->y0                              = p1.M[1];

         return ( 1 );

}

 

旋转,也是矩阵方式,确实锻炼基础啊。

int Rotate_Polygon2D_Mat(POLYGON2D_PTR poly, int theta)

{

// this function rotates the local coordinates of the polygon

 

// test for valid pointer

if (!poly)

   return(0);

 

// test for negative rotation angle

if (theta < 0)

   theta+=360;

 

MATRIX3X2 mr; // used to hold rotation transform matrix

 

// initialize the matrix with translation values dx dy

Mat_Init_3X2(&mr,cos_look[theta],sin_look[theta],

                 -sin_look[theta],cos_look[theta],

                  0, 0);

 

// loop and rotate each point, very crude, no lookup!!!

for (int curr_vert = 0; curr_vert < poly->num_verts; curr_vert++)

    {

    // create a 1x2 matrix to do the transform

    MATRIX1X2 p0 = {poly->vlist[curr_vert].x, poly->vlist[curr_vert].y};

    MATRIX1X2 p1 = {0,0}; // this will hold result

 

    // now rotate via a matrix multiply

    Mat_Mul1X2_3X2(&p0, &mr, &p1);

 

    // now copy the result back into vertex

    poly->vlist[curr_vert].x = p1.M[0];

    poly->vlist[curr_vert].y = p1.M[1];

 

    } // end for curr_vert

 

// return success

return(1);

 

} // end Rotate_Polygon2D_Mat

 

放缩

int Scale_Polygon2D_Mat(POLYGON2D_PTR poly, float sx, float sy);

{

         if ( !poly )

         {

                   return ( 0 );

         }

 

         MATRIX3X2 ms;

         Mat_Init_3X2( & ms, sx, 0, 0, sy, 0, 0 );

         for ( int curr_vert = 0; curr_vert < poly->num_verts; curr_vert ++ )

         {

                   MATRIX1X2   p0                       = { poly->vlist[curr_vert].x, poly->vlist[curr_vert].y };

                   MATRIX1X2   p1                       = { 0, 0 };

 

                   Mat_Mul1X2_3X2( & p0, & mr, & p1 );

 

                   poly->vlist[curr_vert].x= p1.M[0];

                   poly->vlist[curr_vert].y= p1.M[1];

         }

 

         return ( 1 );

}

矩阵[1][2] * [3][2]

int Mat_Mul1X2_3X2( MATRIX1X2_PTR ma, MATRIX3X2_PTR mb, MATRIX1X2_PTR mprod )

{

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

         {

                   float sum                    = 0;

 

                   for ( int index = 0; index < 2; index++ )

                   {

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

                   }

                   sum                                       += mb->M[index][col];

                   mprod->M[col]                   = sum;

         }

         return ( 1 );

}

初始化:

int Mat_Init_3X2( MATRIX3X2_PTR ma, float m00, float m01, float m10, float m11, float m20, float m21 )

{

         ma->M[0][0]              = m00;

         ma->M[0][1]              = m01;

         ma->M[1][0]              = m10;

         ma->M[1][1]              = m11;

         ma->M[2][0]              = m20;

         ma->M[2][1]              = m21;

 

         return ( 1 );

}

在game_main()中,

以前是

// test for scale

         if (KEYDOWN('A')) // scale up

                   Scale_Polygon2D(&asteroid, 1.1, 1.1);

         else

                   if (KEYDOWN('S')) // scale down

                            Scale_Polygon2D(&asteroid, 0.9, 0.9);

现在是矩阵形式

 

         // test for scale

         if (KEYDOWN('A')) // scale up

                   Scale_Polygon2D_Mat(&ship, 1.1, 1.1);

         else

                   if (KEYDOWN('S')) // scale down

                            Scale_Polygon2D_Mat(&ship, 0.9, 0.9);

 

再加上旋转和平移

if ( KEYDOWN( 'Z'))

         {

                   Rotate_Polygon2D_Mat( & ship, -5 );

         }

         else

         if ( KEYDOWN( 'X'))

         {

                   Rotate_Polygon2D_Mat( & ship, 5 );

         }

         if ( KEYDOWN( VK_RIGHT))

         {

                   Translate_Polygon2D_Mat( & ship,5, 0 );

         }

         else

         if ( KEYDOWN( VK_LEFT))

         {

                   Translate_Polygon2D_Mat( & ship,-5, 0 );

         }

         if ( KEYDOWN( VK_UP))

         {

                   Translate_Polygon2D_Mat( & ship,0, -5 );

         }

         else

         if ( KEYDOWN( VK_DOWN))

         {

                   Translate_Polygon2D_Mat( & ship,0, 5 );

         }

 

 

在Game_Init()中,

开始时

srand( GetTickCount())

然后改定

         LPPALETTEENTRY color;

         color->peRed             = 255;

         color->peGreen                   = 0;

         color->peBlue            = 0;

         color->peFlags           =  PC_NOCOLLAPSE;

         ddraw->Set_Palette_Entry( 1, color );

 

         LPPALETTEENTRY color2;

         color2->peRed           = 0;

         color2->peGreen                 = 255;

         color2->peBlue                   = 0;

         color2->peFlags                  =  PC_NOCOLLAPSE;

         ddraw->Set_Palette_Entry( 2, color2 );

 

         LPPALETTEENTRY color3;

         color3->peRed           = 0;

         color3->peGreen                 = 0;

         color3->peBlue                   = 255;

         color3->peFlags                  =  PC_NOCOLLAPSE;

         ddraw->Set_Palette_Entry( 3, color3 );

 

                         

// define points of asteroid

         VERTEX2DF ship_vertices[24] =

         {

                   1, 11,

                   2, 8,

                   1, 7,

                   1, -1,

                   3,-1,

                   3,-2,

                   11,-3,

                   11,-6,

                   3,-7,

                   2,-8,

                   1,-8,

                   1,-7,

                   -1,-7,

                   -1,-8,

                   -2,-8,

                   -3,-7,

                   -11,-6,

                   -11,-3,

                   -3,-2,

                   -3,-1,

                   -1,-1,

                   -1,7,-2,8,-1,11

         };

 

 

         // initialize asteroid

         ship.state       = 1;   // turn it on

         ship.num_verts   = 24; 

         ship.x0          = SCREEN_WIDTH/2; // position it

         ship.y0          = SCREEN_HEIGHT/2;

         ship.xv          = 0;

         ship.yv          = 0;

         ship.color       = 2; // white

         ship.vlist       = new VERTEX2DF [ship.num_verts];

 

         for (int index = 0; index < ship.num_verts; index++)

                   ship.vlist[index] = ship_vertices[index];

 

结果如下图:

封装一下。

成员函数

 

int DDRAW_Interface::Translate_Polygon2D_Mat( POLYGON2D_PTR poly, int dx, int dy )

{

         if( ! poly )

         {

                   return ( 0 );

         }

         MATRIX3X2 mt;

         Mat_Init_3X2( & mt, 1, 0, 0, 1, dx, dy );

         MATRIX1X2   p0                       = { poly->x0, poly->y0 };

         MATRIX1X2   p1                       = { 0, 0 };

 

         Mat_Mul1X2_3X2( & p0, & mt, & p1 );

 

         poly->x0                              = p1.M[0];

         poly->y0                              = p1.M[1];

         return ( 1 );

}

int DDRAW_Interface::Rotate_Polygon2D_Mat(POLYGON2D_PTR poly, int theta)

{

         // this function rotates the local coordinates of the polygon

 

         // test for valid pointer

         if (!poly)

                   return(0);

 

         // test for negative rotation angle

         if (theta < 0)

                   theta+=360;

 

         MATRIX3X2 mr; // used to hold rotation transform matrix

 

         // initialize the matrix with translation values dx dy

         Mat_Init_3X2(&mr,cos_look[theta],sin_look[theta],

                   -sin_look[theta],cos_look[theta],

                   0, 0);

 

         // loop and rotate each point, very crude, no lookup!!!

         for (int curr_vert = 0; curr_vert < poly->num_verts; curr_vert++)

         {

                   // create a 1x2 matrix to do the transform

                   MATRIX1X2 p0 = {poly->vlist[curr_vert].x, poly->vlist[curr_vert].y};

                   MATRIX1X2 p1 = {0,0}; // this will hold result

 

                   // now rotate via a matrix multiply

                   Mat_Mul1X2_3X2(&p0, &mr, &p1);

 

                   // now copy the result back into vertex

                   poly->vlist[curr_vert].x = p1.M[0];

                   poly->vlist[curr_vert].y = p1.M[1];

 

         } // end for curr_vert

 

         // return success

         return(1);

 

} // end Rotate_Polygon2D_Mat

int DDRAW_Interface::Scale_Polygon2D_Mat(POLYGON2D_PTR poly, float sx, float sy)

{

         if ( !poly )

         {

                   return ( 0 );

         }

 

         MATRIX3X2 ms;

         Mat_Init_3X2( & ms, sx, 0, 0, sy, 0, 0 );

         for ( int curr_vert = 0; curr_vert < poly->num_verts; curr_vert ++ )

         {

                   MATRIX1X2   p0                       = { poly->vlist[curr_vert].x, poly->vlist[curr_vert].y };

                   MATRIX1X2   p1                       = { 0, 0 };

 

                   Mat_Mul1X2_3X2( & p0, & ms, & p1 );

 

                   poly->vlist[curr_vert].x= p1.M[0];

                   poly->vlist[curr_vert].y= p1.M[1];

         }

 

         return ( 1 );

}

 

int DDRAW_Interface::Mat_Mul1X2_3X2( MATRIX1X2_PTR ma, MATRIX3X2_PTR mb, MATRIX1X2_PTR mprod )

{

         int index;

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

         {

                   float sum                    = 0;

 

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

                   {

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

                   }

                   sum                                       += mb->M[index][col];

                   mprod->M[col]                   = sum;

         }

         return ( 1 );

}

int DDRAW_Interface::Mat_Init_3X2( MATRIX3X2_PTR ma, float m00, float m01, float m10, float m11, float m20, float m21 )

{

         ma->M[0][0]              = m00;

         ma->M[0][1]              = m01;

         ma->M[1][0]              = m10;

         ma->M[1][1]              = m11;

         ma->M[2][0]              = m20;

         ma->M[2][1]              = m21;

 

         return ( 1 );

}

 

Game_init()不变

Game_main()改为

 

         ddraw->Draw_Polygon2D(&ship, ddraw->getbackbuffer(), ddraw->getbacklpitch());

 

        

         // test for scale

         if (KEYDOWN('A')) // scale up

                   ddraw->Scale_Polygon2D_Mat(&ship, 1.1, 1.1);

         else

                   if (KEYDOWN('S')) // scale down

                            ddraw->Scale_Polygon2D_Mat(&ship, 0.9, 0.9);

 

        

                   if ( KEYDOWN( 'Z'))

                   {

                            ddraw->Rotate_Polygon2D_Mat( & ship, -5 );

                   }

                   else

                            if ( KEYDOWN( 'X'))

                            {

                                     ddraw->Rotate_Polygon2D_Mat( & ship, 5 );

                            }

                            if ( KEYDOWN( VK_RIGHT))

                            {

                                      ddraw->Translate_Polygon2D_Mat( & ship,5, 0 );

                            }

                            else

                                     if ( KEYDOWN( VK_LEFT))

                                     {

                                               ddraw->Translate_Polygon2D_Mat( & ship,-5, 0 );

                                     }

                                     if ( KEYDOWN( VK_UP))

                                     {

                                               ddraw->Translate_Polygon2D_Mat( & ship,0, -5 );

                                     }

                                     else

                                               if ( KEYDOWN( VK_DOWN))

                                               {

                                                        ddraw->Translate_Polygon2D_Mat( & ship,0, 5 );

                                               }

 

         // rotate the polygon by 5 degrees

         ddraw->Rotate_Polygon2D(&ship, 5);

 

结果OK

 

,根据T3DLIB进行,将矩阵为数组和结构体的联合体

 

typedef struct MATRIX3X2_TYP

{

         union

         {

                   float M[3][2];

                   struct

                   {

                            float M00, M01;

                            float M10, M11;

                            float M20, M21;

 

                   };

 

         };

 

}MATRIX3X2, * MATRIX3X2_PTR;

 

 

 

typedef struct MATRIX1X2_TYP

{

         union

         {

                   float M[2];

                   struct

                   {

                            float M00, float M01;

                   };

         };

        

}MATRIX1X2, * MATRIX1X2_PTR;

 

补充个

int DDRAW_Interface::Draw_Polygon2D16( POLYGON2D_PTR poly, UCHAR * vbuffer, int lpitch )

{

         int index = 0;

         if( poly->state )

         {

                   for(index = 0; index < poly->num_verts - 1; index ++ )

                   {

                            Draw_Clip_Line16( poly->vlist[index].x + poly->x0,

                                     poly->vlist[index].y + poly->y0,

                                     poly->vlist[index+1].x + poly->x0,

                                     poly->vlist[index+1].y + poly->y0,

 

                                     poly->color,

                                     vbuffer, lpitch );

                   }

                   Draw_Clip_Line16( poly->vlist[0].x + poly->x0,

                            poly->vlist[0].y + poly->y0,

                            poly->vlist[index].x + poly->x0,

                            poly->vlist[index].y + poly->y0,

                            poly->color,

                            vbuffer, lpitch );

 

                   return ( 1 );

         }

         else

                   return ( 0 );

}

在构造函数中,

         m_dwWidth                                  = SCREEN_WIDTH;

         m_dwHeight                                 = SCREEN_HEIGHT;

         m_dwBPP                                              = SCREEN_BPP;

而不是以前的0.

 

我的思路这里有个问题,就是切换区域实际上应该在成员变量里,因为每个窗口未必一样,应该是个变量,

所以设置成员变量。

         int                                                             m_min_clip_x;

         int                                                             m_min_clip_y;

         int                                                             m_max_clip_x;

         int                                                             m_max_clip_y;

构造函数上初始化

 

         m_max_clip_x                            = SCREEN_WIDTH - 1;

         m_max_clip_y                            = SCREEN_HEIGHT - 1;

         m_min_clip_x                    = 0;

         m_min_clip_y                    = 0;

 

相应地,在ddraw_init()中改为

 

         m_min_clip_x                              = 0;

         m_max_clip_x                                      = width - 1;

         m_min_clip_y                              = 0;

         m_max_clip_y                                      = height - 1;

 

         RECT       screen_rect                          = { 0, 0, width, height };

         m_lpddclipper                              = DDraw_Attach_Clipper( m_lpddsback, 1, & screen_rect );

 

以前遗漏了一个

 

int DDRAW_Interface::Set_Palette( LPPALETTEENTRY set_palette )

{

         memcpy( palette, set_palette, MAX_COLORS_PALETTE * sizeof( PALETTEENTRY ) );

         m_lpddpal->SetEntries( 0, 0, MAX_COLORS_PALETTE, palette );

         return ( 1 );

 

}

再一运行发现有问题,改为以前的。

         m_min_clip_x                              = 0;

         m_max_clip_x                                      = width - 1;

         m_min_clip_y                              = 0;

         m_max_clip_y                                      = height - 1;

 

         RECT       screen_rect                          = { 0, 0, width -1, height - 1 };

         m_lpddclipper                              = DDraw_Attach_Clipper( m_lpddsback, 1, & screen_rect );

恢复正常,看来尽信书不如无书。

因篇幅问题不能全部显示,请点此查看更多更全内容

Top