1读取物体名,顶点数和多边形数
2读取顶点列表
3读取每个多边形的定义及其RGB材质颜色信息
缺点是:不能指定多边形是单面还是双面的,不支持纹理映射信息和光照模型信息等,只提供了每个多边形的颜色。
定义了几个值
#define OBJECT4DV1_MAX_VERTICES 1024
#define OBJECT4DV1_MAX_POLYS 1024
//根据坐标系改变或者朝向改变,作如下
#define VERTEX_FLAGS_INVERT_X 1 //反转X轴
#define VERTEX_FLAGS_INVERT_Y 2 //反转Y轴
#define VERTEX_FLAGS_INVERT_Z 4 //反转Z轴
#define VERTEX_FLAGS_SWAP_YZ 8 //从RHS变换为LHS
#define VERTEX_FLAGS_SWAP_XZ 16
#define VERTEX_FLAGS_SWAP_XY 32
#define VERTEX_FLAGS_INVERT_WINDING_ORDER 64 //反转环绕顺序
在调用文件中,
初始化灯光,
#define AMBIENT_LIGHT_INDEX 0
#define INFINITE_LIGHT_INDEX 1
#define POINT_LIGHT_INDEX 2
#define SPOT_LIGHT_INDEX 3
改变摄像机位置
POINT4D cam_pos = {0,0,-250,1};
几个状态变量
int wireframe_mode = -1;
int backface_mode = 1;
int lighting_mode = 1;
int help_mode = 1;
int zsort_mode = 1;
加载3DSMAX的第一个版本用到了模式匹配,希望是正确的,。
int ddraw_liushuixian::Load_OBJECT4DV1_3DSASC(OBJECT4DV1_PTR obj, char * filename, VECTOR4D_PTR scale, VECTOR4D_PTR pos, VECTOR4D_PTR rot, int vertex_flags)
{
CPARSERV1 parser;
char seps[16];
char token_buffer[256]; //缓冲区
char * token; //指向要分析的物体数据文本的指针
int r, g, b;
//先找到物体描述符
//第一步清空和初始化OBJ
memset( obj, 0, sizeof(OBJECT4DV1) );
//将物体状态设置为可见和活动的
obj->state = OBJECT4DV1_STATE_ACTIVE | OBJECT4DV1_STATE_VISIBLE;
if ( pos )
{
//设置物体的位置
obj->world_pos.x = pos->x;
obj->world_pos.y = pos->y;
obj->world_pos.z = pos->z;
obj->world_pos.w = pos->w;
}
else
{
//设置物体的位置
obj->world_pos.x = 0;
obj->world_pos.y = 0;
obj->world_pos.z = 0;
obj->world_pos.w = 1;
}
//第步,读取文件
parser.Open( filename );
//第步,读取物体描述符
while ( 1 )
{
parser.GetLine( PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS );
//检测模式
if( parser.Pattern_Match( parser.buffer, "['Named']['object:']" ) )
{
strcpy( token_buffer, parser.buffer );
strcpy( seps, "\"" );
strtok( token_buffer, seps );
token = strtok( NULL, seps );
strcpy( obj->name, seps );
break;
}
}
//第步,得到我图的顶点数目
while( 1 )
{
parser.GetLine( PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS );
//下一行,寻找Tri-Mesh,Vertices,提取顶点数目
if( parser.Pattern_Match( parser.buffer, "['Tri-mesh,']['Vertices:'][i]['Faces:'][i]" ) )
obj->num_vertices = parser.pints[0];
obj->num_polys = parser.pints[1];
break;
}
}
//第步:加载顶点列表
while( 1 )
{
parser.GetLine( PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS );
//下一行,寻找Tri-Mesh,Vertices,提取顶点数目
if( parser.Pattern_Match( parser.buffer, "['Vertex']['list:']" ) )
{
break;
}
}
//现在读取顶点列表,格式"Vertex:d X:d.d Y:d.d Z:d.d"
for( int vertex = 0; vertex < obj->num_vertices; vertex ++ )
{
while( 1 )
{
parser.GetLine( PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS );
parser.StripChars( parser.buffer, parser.buffer, ":XYZ" );
if( parser.Pattern_Match( parser.buffer, "['Vertex'][i][f][f][f]" ) )
{
obj->vlist_local[vertex].x = parser.pfloats[0];
obj->vlist_local[vertex].y = parser.pfloats[1];
obj->vlist_local[vertex].z = parser.pfloats[2];
obj->vlist_local[vertex].w = 1;
//根据标志位来进行相应的旋转
float temp_f;
if( vertex_flags & VERTEX_FLAGS_INVERT_X )
obj->vlist_local[vertex].x = - obj->vlist_local[vertex].x;
if( vertex_flags & VERTEX_FLAGS_INVERT_Y )
obj->vlist_local[vertex].y = - obj->vlist_local[vertex].y;
if( vertex_flags & VERTEX_FLAGS_INVERT_Z )
obj->vlist_local[vertex].z = - obj->vlist_local[vertex].z;
if( vertex_flags & VERTEX_FLAGS_SWAP_YZ )
SWAP( obj->vlist_local[vertex].y, obj->vlist_local[vertex].z, temp_f );
if( vertex_flags & VERTEX_FLAGS_SWAP_XZ )
SWAP( obj->vlist_local[vertex].x, obj->vlist_local[vertex].z, temp_f );
if( vertex_flags & VERTEX_FLAGS_SWAP_XY )
SWAP( obj->vlist_local[vertex].x, obj->vlist_local[vertex].y, temp_f );
//放缩
if( scale )
{
obj->vlist_local[vertex].x *= scale->x;
obj->vlist_local[vertex].y *= scale->y;
obj->vlist_local[vertex].z *= scale->z;
}
break;
}
}
}
//计算平均和最大半径
Compute_OBJECT4DV1_RADIUS( obj );
//6,,88面表
while( 1 )
{
if( ! parser.GetLine( PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS ) )
{
return ( 0 );
}
if( parser.Pattern_Match( parser.buffer, "['Face']['list:']" ) )
{
break;
}
}
//格式/
//Material:"rdddgdddbddda0"
int poly_surface_desc = 0;
int poly_num_verts = 0;
char tmp_string[8];
int poly = 0;
for( poly = 0; poly < obj->num_polys; poly++ )
{
while ( 1 )
{
if( ! parser.GetLine( PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS ) )
{
return ( 0 );
}
parser.StripChars(parser.buffer, parser.buffer, ":ABC" );
if( parser.Pattern_Match( parser.buffer, "['Face'][i][i][i][i]" ) )
{
//
if( vertex_flags & VERTEX_FLAGS_INVERT_WINDING_ORDER )
{
poly_num_verts = 3;
obj->plist[poly].vert[0] = parser.pints[3];
obj->plist[poly].vert[1] = parser.pints[2];
obj->plist[poly].vert[2] = parser.pints[1];
}
else
{
poly_num_verts = 3;
obj->plist[poly].vert[0] = parser.pints[1];
obj->plist[poly].vert[1] = parser.pints[2];
obj->plist[poly].vert[2] = parser.pints[3];
}
obj->plist[poly].vlist = obj->vlist_local;
break;
}
}
//去除“:ABC”
while( 1 )
{
if( ! parser.GetLine( PARSER_STRIP_EMPTY_LINES | PARSER_STRIP_WS_ENDS ) )
{
return ( 0 );
}
//Material:"rdddgdddbddda0"
//去掉':rgba'去掉
parser.ReplaceChars( parser.buffer, parser.buffer, ":\"rgba",' ' );
if( parser.Pattern_Match( parser.buffer, "[i][i][i]" ) )
{
r = parser.pints[0];
g = parser.pints[1];
b = parser.pints[2];
SET_BIT( obj->plist[poly].attr, POLY4DV1_ATTR_RGB16 );
obj->plist[poly].color = _RGB16BIT565( r, g, b );
SET_BIT( obj->plist[poly].attr, POLY4DV1_ATTR_SHADE_MODE_FLAT );
obj->plist[poly].state = POLY4DV1_STATE_ACTIVE;
break;
}
}
}
return ( 1 );
}
这里只保留16位模式,
看看MAIN()函数这里,如何调用的。
渲染列表是第一个版本的,
RENDERLIST4DV1 render_list;
//几个不同的渲染模型状态变量(虽然用不上,只进行模型加载,)
int wireframe_mode = -1;
int backface_mode = 1;
int lighting_mode = 1;
int help_mode = 1;
int zsort_mode = 1;
int swapyz = 0,
iwinding = 0;
char ascfilename[256]; //加载的文件名
在初始化GAME_INIT()里,将XYZ均扩大到5倍,
math->VECTOR4D_INITXYZ( & vscale, 5.0, 5.0, 5.0 );
加载3DSMAX模型,
liushuixian.Load_OBJECT4DV1_3DSASC( & obj_player, "sphere01.asc", &vscale, &vpos, &vrot, VERTEX_FLAGS_INVERT_WINDING_ORDER | VERTEX_FLAGS_SWAP_YZ );
在初始化时重置灯光
设置几个颜色
RGBAV1 white, gray, black, red, green, blue;
white.rgba = _RGBA32BIT( 255, 255, 255, 0 );
gray.rgba = _RGBA32BIT( 100, 100, 100, 0 );
black.rgba = _RGBA32BIT( 0, 0, 0, 0 );
red.rgba = _RGBA32BIT( 255, 0, 0, 0 );
green.rgba = _RGBA32BIT( 0, 255, 0, 0 );
blue.rgba = _RGBA32BIT( 0, 0, 255, 0 );
加光源:
//环境光
light.Init_Light_LIGHTV1( * math, lightGroup,AMBIENT_LIGHT_INDEX, LIGHTV1_STATE_ON, LIGHTV1_ATTR_AMBIENT, gray, black, black, NULL, NULL, 0, 0, 0, 0, 0, 0 );
//方向光
VECTOR4D dlight_dir = { -1, 0, -1, 0 };
light.Init_Light_LIGHTV1( * math,lightGroup,INFINITE_LIGHT_INDEX, LIGHTV1_STATE_ON, LIGHTV1_ATTR_INFINITE, black, gray, black, NULL, &dlight_dir, 0, 0, 0, 0, 0, 0 );
//点光源
VECTOR4D plight_pos = { 0, 200, 0, 0 };
light.Init_Light_LIGHTV1( *math, lightGroup,POINT_LIGHT_INDEX, LIGHTV1_STATE_ON, LIGHTV1_ATTR_POINT, black, green, black , &plight_pos, NULL, 0, 0.001, 0, 0, 0, 1 );
//聚光灯
VECTOR4D slight_pos = { 0, 200, 0, 0 };
VECTOR4D slight_dir = { -1, 0, -1, 0 };
light.Init_Light_LIGHTV1( SPOT_LIGHT_INDEX, lightGroup, SPOT_LIGHT_INDEX, LIGHTV1_STATE_ON, LIGHTV1_ATTR_SPOLIGHT2, black, red, black, &slight_pos, &slight_dir, 0, 0.001, 0, 0, 0, 1 );
在Game_main()中,
int Game_Main(void *parms)
{
// this is the workhorse of your game it will be called
// continuously in real-time this is like main() in C
// all the calls for you game go here!
static MATRIX4X4 mrot; // general rotation matrix
// these are used to create a circling camera
static float view_angle = 0;
static float camera_distance = 6000;
static VECTOR4D pos = {0,0,0,0};
char work_string[256]; // temp string
int index; // looping var
// start the timing clock
srand( mytool.Start_Clock() );
ddraw->DDraw_Fill_Surface( ddraw->getbackSurface(), 0 );
liushuixian.Reset_RENDERLIST4DV1( &rend_list );
// allow user to move camera
if (obj_player.dir.y > 360)
obj_player.dir.y-=360;
if (obj_player.dir.y < 0)
obj_player.dir.y+=360;
// ambient rotation
obj_player.dir.y++;
// modes and lights
static float plight_ang = 0, slight_ang = 0; // angles for light motion
// move point light source in ellipse around game world
lightGroup[POINT_LIGHT_INDEX].pos.x = 300*cosf(plight_ang);
lightGroup[POINT_LIGHT_INDEX].pos.y = 200;
lightGroup[POINT_LIGHT_INDEX].pos.z = 300*sinf(plight_ang);
if ((plight_ang+=3) > 360)
plight_ang = 0;
// move spot light source in ellipse around game world
lightGroup[SPOT_LIGHT_INDEX].pos.x = 200*cosf(slight_ang);
lightGroup[SPOT_LIGHT_INDEX].pos.y = 200;
lightGroup[SPOT_LIGHT_INDEX].pos.z = 200*sinf(slight_ang);
if ((slight_ang-=5) < 0)
slight_ang = 360;
/
// generate camera matrix
liushuixian.Build_CAM4DV1_Matrix_Euler( *math, & cam, CAM_ROT_SEQ_ZYX );
// insert the player into the world
// reset the object (this only matters for backface and object removal)
liushuixian.Reset_OBJECT4DV1( & obj_player );
// generate rotation matrix around y axis
// Build_XYZ_Rotation_MATRIX4X4(0, obj_player.dir.y, 0, &mrot);
math->Build_XYZ_Rotation_MATRIX4x4( 0, obj_player.dir.y, 0, & mrot );
// rotate the local coords of the object
liushuixian.Transform_OBJECT4DV1( & obj_player, &mrot, TRANSFORM_LOCAL_TO_TRANS, 1, *math );
// perform world transform
liushuixian.Model_To_World_OBJECT4DV1( &obj_player,* math, TRANSFORM_TRANS_ONLY );
// perform lighting
if (lighting_mode==1)
liushuixian.Light_OBJECT4DV1_World16( *math, DD_PIXEL_FORMAT565, &obj_player, & cam, lightGroup, 4 );
// insert the object into render list
liushuixian.Insert_OBJECT4DV1_RENDERLIST4DV12( *math, &rend_list, &obj_player, 0, lighting_mode );
//
// remove backfaces
if (backface_mode==1)
liushuixian.Remove_Backfaces_RENDERLIST4DV1( &rend_list, & cam, * math );
// apply world to camera transform
// World_To_Camera_RENDERLIST4DV1(&rend_list, &cam);
liushuixian.World_To_Camera_RENDERLIST4DV1( * math, &rend_list, &cam );
// sort the polygon list (hurry up!)
if (zsort_mode == 1)
Sort_RENDERLIST4DV1(&rend_list, SORT_POLYLIST_AVGZ);
liushuixian.Camera_To_Perspective_RENDERLIST4DV1( &rend_list, &cam );
liushuixian.Perspective_To_Screen_RENDERLIST4DV1( &rend_list, &cam );
// lock the back buffer
//DDraw_Lock_Back_Surface();
ddraw->DDraw_Lock_Back_Surface();
liushuixian.Draw_RENDERLIST4DV1_Solid16( *math, &rend_list, ddraw->getbackbuffer(), ddraw->getbacklpitch() );
ddraw->DDraw_Unlock_Back_Surface();
ddraw->DDraw_Flip();
// sync to 30ish fps
// Wait_Clock(30);
mytool.Wait_Clock( 30 );
// return success
return(1);
} // end Game_Main
截图如下: