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 );
- 2013年12月30日星期一(继续流水线--局部坐标->世界坐标)
- unity中世界坐标与局部坐标
- Unity 世界坐标和局部坐标
- 2013年9月16日星期一(DEMO8_8,多边形)
- 2011年12月5日星期一(oracle读书笔记)
- 2011年12月19日 星期一(oracle读书笔记)
- 2011年12月26日 星期一(oracle读书笔记)
- 2013年9月23日星期一
- 2010年4月12日星期一
- 关于cocos2d中的世界坐标与局部坐标
- 渲染管线—局部坐标到世界坐标的转换
- Unity 的局部坐标转换到世界坐标的接口
- unity3D中 局部坐标,世界坐标以及屏幕坐标,transform变换坐标以及 变换方向心得
- 世界坐标
- 图形学的坐标转换问题(局部到世界坐标系,世界到观察坐标系)
- 2013年1月7日 星期一 GTD 稳
- 2008年12月15日 阴 星期一
- 学习随笔--2009年10月12日星期一
- Delphi中文件名函数-路径、名称、子目录、驱动器、扩展名-
- to_number不了字段-ORA-01722 无效数字
- AsyncTask引发的问题
- 从零开始-边学边做-塔防游戏-七彩三国(八)--强制横屏
- 《Effective C++》学习笔记条款30 透彻了解inlining的里里外外
- 2013年12月30日星期一(继续流水线--局部坐标->世界坐标)
- [零基础学软件开发14]while循环
- excel2003如何删除重复的行
- 黑马程序员 知识点总结-Java集合框架(Map)
- Xcode中查看方法的调用者列表
- [DBNETLIB][ConnectionOpen(Invalid Instance())] 无效的连接 的解决办法
- guide
- C1083: Cannot open include file: ‘stddef.h’: No such file or directory
- org.apache.commons.dbcp.BasicDataSource连接池配备属性