2014年12月4日星期四(DEMO10-2地形生成函数)


转眼间,2014年快过去了,数了数代码,封装后的代码也有17000行了,但是,还有很多工作量,继续进行最为敬畏的地形生成。

这个DEMO的意思是说,加载256色位图,以位图颜色索引乘以一个缩放因子为高程,将每个单元格分割为三角形,并插入到物体的顶点列表中;当然,还要有一个彩色纹理映射到高程场上。

 

生成地形模式:

#define POLY4DV2_ATTR_8BITCOLOR                 0x0004                    8位

#define POLY4DV2_ATTR_RGB16                              0x0008       16位

 

创建网格后,用两个函数分别计算两种法线:

1,计算多边形法线,(供背面消除和多边形光照计算使用)

Compute_OBJECT4DV2_Poly_Normals( ddraw_mathmath, OBJECT4DV2_PTRobj );

2,计算顶点法线(供Gouraud着色使用)

Compute_OBJECT4DV2_Vertex_Normals( ddraw_mathmath, OBJECT4DV2_PTRobj );

 

要设置着色模式,可以用下述常量之一。

 

#define POLY4DV2_ATTR_SHADE_MODE_EMISSIVE   0x0020

#define POLY4DV2_ATTR_SHADE_MODE_FLAT       0x0040

#define POLY4DV2_ATTR_SHADE_MODE_GOURAUD 0x0080

 

如果要使纹理映射到地形表面,则用POLY4DV2_ATTR_SHADE_MODE_TEXTURE,此时,只能用固定和恒定着色,不能采用Gouraud着色。

 

采用的方法是:计算输入纹理图的纹理坐标,然后将纹理映射到地形图上。

加载函数类似于加载PLG文件

 

 

int DDRAW_LIUSHUIXIAN_TEXTURE::Generate_Terrain_OBJECT4DV2ddraw_math                math,

                                                                  OBJECT4DV2_PTR            obj,              //指向物体的指针

                                                                  float                     twidth,               //世界坐标系中的长度(X轴)

                                                                  float                     theight,          //世界坐标系中的高度(Z轴)

                                                                  float                     vscale,               //最大可能高度值

                                                                  char     *            height_map_file//256色高程图的文件名

                                                                  char     *            texture_map_file, //纹理图的文件名

                                                                  int                       rgbcolor,             //没有纹理时地形的颜色

                                                                  VECTOR4D_PTR          pos,              //初始位置

                                                                  VECTOR4D_PTR          rot,              //初始旋转角度

                                                                  int                       poly_attr)       //着色属性

{

    char                  buffer[256];                   //工作缓冲区

 

    float                     col_tstep,row_tstep;

    float                     col_vstep,row_vstep;

    int                       columns,rows;

    int                       rgbwhite;

 

    BITMAP_FILE               height_bitmap;                     //存储高程图

    BITMAP_FILE               bitmap16bit;

 

 

    //第一步清空和初始化OBJ

    memset(obj, 0, sizeof(OBJECT4DV2) );

    //将物体状态设置为可见和活动的

    obj->state                                      =OBJECT4DV2_STATE_ACTIVE | OBJECT4DV2_STATE_VISIBLE;

 

    //设置物体的位置

    obj->world_pos.x                            = pos->x;

    obj->world_pos.y                            = pos->y;

    obj->world_pos.z                            = pos->z;

    obj->world_pos.w                            = pos->w;

 

    //以后只用色的模式

    rgbwhite                                    = _RGB16BIT565( 255, 255, 255 );

 

    //设置物体包含的帧数

    obj->num_frames                                 =1;

    obj->curr_frame                                 =0;

    obj->attr                                        = OBJECT4DV2_ATTR_SINGLE_FRAME;

 

    //清空位图

    memset(& height_bitmap, 0, sizeof( BITMAP_FILE) );

    //第步,加载高程图

    ddraw_bitmap  bm;

    bm.Load_Bitmap_File( & height_bitmap,height_map_file );

 

    //计算基本信息

    columns                                         = height_bitmap.bitmapinfoheader.biWidth;

    rows                                        = height_bitmap.bitmapinfoheader.biHeight;

 

    col_vstep                                       = twidth / ( float )( columns - 1 );

    row_vstep                                       = theight / ( float) ( rows - 1 );

 

    sprintf(obj->name,"Terrains:%s%s", height_map_file, texture_map_file);

    obj->num_vertices                           =columns * rows;

    obj->num_polys                                  =( ( columns - 1 ) * ( rows - 1 ) ) * 2;

 

    //存储一些结果,供地形追踪算法使用

    obj->ivar1                                      =columns;

    obj->ivar2                                      =rows;

    obj->fvar1                                      =col_vstep;

    obj->fvar2                                      =row_vstep;

 

 

    //为存储顶点数和多边形数的变量分配内存

    Init_OBJECT4DV2(obj, obj->num_vertices, obj->num_polys, obj->num_frames );

 

    //加载纹理图(如果有的话)

    if(( poly_attr & POLY4DV2_ATTR_SHADE_MODE_TEXTURE) && texture_map_file )

    {

         //从磁盘里加载纹理图

         bm.Load_Bitmap_File( & bitmap16bit,texture_map_file );

 

         //创建一个大小和位深合适的位图

         obj->texture                       =( BITMAP_IMAGE_PTR ) malloc( sizeof( BITMAP_IMAGE ) );

         bm.Create_Bitmap( obj->texture, 0, 0, bitmap16bit.bitmapinfoheader.biWidth,bitmap16bit.bitmapinfoheader.biHeight,

             bitmap16bit.bitmapinfoheader.biBitCount);

 

         //加载位图图像

         bm.Load_Image_Bitmap16( obj->texture, & bitmap16bit,0, 0, BITMAP_EXTRACT_MODE_ABS );

 

         //计算纹理图的步进因子

         col_tstep                              = ( float ) ( bitmap16bit.bitmapinfoheader.biWidth- 1 ) / ( float ) ( columns- 1 );

         row_tstep                              = ( float ) ( bitmap16bit.bitmapinfoheader.biHeight- 1 ) / ( float ) ( rows- 1 );

 

         //指出物体带纹理

         SET_BIT(obj->attr,OBJECT4DV2_ATTR_TEXTURES );

 

         //卸载位图

         bm.Unload_Bitmap_File( & bitmap16bit);

    }

 

 

    //第步:按先行后列的顺序加载顶点列表和纹理坐标列表

 

    for(int curr_row= 0; curr_row < rows;curr_row ++ )

    {

         for(int curr_col= 0; curr_col < columns;curr_col ++ )

         {

             int               vertex                    = ( curr_row* columns ) + curr_col;

             //计算顶点坐标

             obj->vlist_local[vertex].x             =curr_col * col_vstep- ( twidth / 2 );

             obj->vlist_local[vertex].y             =vscale * ( ( float) height_bitmap.buffer[curr_col + ( curr_row* columns )] )/ 255;

             obj->vlist_local[vertex].z             =curr_row * row_vstep- ( theight / 2 );

             obj->vlist_local[vertex].w             =1;

 

             //设置顶点的D

             SET_BIT(obj->vlist_local[vertex].attr, VERTEX4DTV1_ATTR_POINT );

 

             //需要纹理坐标

             if(( poly_attr & POLY4DV2_ATTR_SHADE_MODE_TEXTURE) && texture_map_file )

             {

                  //计算纹理坐标

                  obj->tlist[vertex].x               = curr_col* col_tstep;

                  obj->tlist[vertex].y               = curr_row* row_tstep;

             }

         }

    }

 

    //计算平均半径和最大半径

    Compute_OBJECT4DV2_Radius(obj);

 

    //第步:加载多边形列表

    for(int poly =0; poly < obj->num_polys / 2; poly++)

    {

         //每个单元格有两个三角形,单元格顶点按先行后列的顺序排列

         //如果顶点数组大小为m*n,则多边形列表大小为*(m-1)*(n-1)

         int          base_poly_index                    = ( poly% ( columns - 1 ) )  + ( columns* ( poly / ( columns- 1 ) ) );

 

         //当前单元格的左下多边形

         obj->plist[poly*2].vert[0]                  =base_poly_index;

         obj->plist[poly*2].vert[1]                  =base_poly_index + columns;

         obj->plist[poly*2].vert[2]                  =base_poly_index + columns+ 1;

 

         //当前单元格的右上多边形

         obj->plist[poly*2+1].vert[0]                =base_poly_index;

         obj->plist[poly*2+1].vert[1]                =base_poly_index + columns+ 1;

         obj->plist[poly*2+1].vert[2]                =base_poly_index + 1;

 

         //将多边形顶点列表指向物体的顶点列表

         obj->plist[poly*2].vlist                    =obj->vlist_local;

         obj->plist[poly*2+1].vlist                  =obj->vlist_local;

 

         //设置多边形的颜色

         obj->plist[poly*2].color                    =rgbcolor;

         obj->plist[poly*2+1].color                  =rgbcolor;

 

         //检查着色方法是否是Gouraud或phong,如果是,则需要顶点法线

         if(( obj->plist[poly*2].attr& POLY4DV2_ATTR_SHADE_MODE_GOURAUD ) ||( obj->plist[poly * 2].attr& POLY4DV2_ATTR_SHADE_MODE_PHONG ) )

         {

             //设置顶点的属性,指出它包含法线

             SET_BIT(obj->vlist_local[obj->plist[poly * 2].vert[0]].attr, VERTEX4DTV1_ATTR_NORMAL);

             SET_BIT(obj->vlist_local[obj->plist[poly * 2].vert[1]].attr, VERTEX4DTV1_ATTR_NORMAL);

             SET_BIT(obj->vlist_local[obj->plist[poly * 2].vert[2]].attr, VERTEX4DTV1_ATTR_NORMAL);

 

             SET_BIT(obj->vlist_local[obj->plist[poly * 2 + 1].vert[0]].attr, VERTEX4DTV1_ATTR_NORMAL);

             SET_BIT(obj->vlist_local[obj->plist[poly * 2 + 1].vert[1]].attr, VERTEX4DTV1_ATTR_NORMAL);

             SET_BIT(obj->vlist_local[obj->plist[poly * 2 + 1].vert[2]].attr, VERTEX4DTV1_ATTR_NORMAL);

         }

 

         //如果启用了纹理映射,则计算纹理坐标

         if(poly_attr & POLY4DV2_ATTR_SHADE_MODE_TEXTURE)

         {

             //指定多边形使用的纹理

             obj->plist[poly *2].texture           =obj->texture;

             obj->plist[poly * 2+ 1].texture       =obj->texture;

 

             //设置纹理坐标

             //左下三角形

 

             obj->plist[poly*2].text[0]                  =base_poly_index;

             obj->plist[poly*2].text[1]                  =base_poly_index + columns;

             obj->plist[poly*2].text[2]                  =base_poly_index + columns+ 1;

 

             //当前单元格的右上多边形

             obj->plist[poly*2+1].text[0]                =base_poly_index;

             obj->plist[poly*2+1].text[1]                =base_poly_index + columns+ 1;

             obj->plist[poly*2+1].text[2]                =base_poly_index + 1;   

 

             //重新设置多边形颜色,使其反射率更高

             obj->plist[poly*2].color                    =rgbwhite;

             obj->plist[poly*2+1].color                  =rgbwhite;

 

             //设置纹理坐标属性

             SET_BIT(obj->vlist_local[obj->plist[poly * 2].vert[0]].attr, VERTEX4DTV1_ATTR_TEXTURE);

             SET_BIT(obj->vlist_local[obj->plist[poly * 2].vert[1]].attr, VERTEX4DTV1_ATTR_TEXTURE);

             SET_BIT(obj->vlist_local[obj->plist[poly * 2].vert[2]].attr, VERTEX4DTV1_ATTR_TEXTURE);

 

             SET_BIT(obj->vlist_local[obj->plist[poly * 2 + 1].vert[0]].attr, VERTEX4DTV1_ATTR_TEXTURE);

             SET_BIT(obj->vlist_local[obj->plist[poly * 2 + 1].vert[1]].attr, VERTEX4DTV1_ATTR_TEXTURE);

             SET_BIT(obj->vlist_local[obj->plist[poly * 2 + 1].vert[2]].attr, VERTEX4DTV1_ATTR_TEXTURE);

         }

 

         //将材质模式设置为不使用材质

         SET_BIT(obj->plist[poly * 2].attr,POLY4DV2_ATTR_DISABLE_MATERIAL );

         SET_BIT(obj->plist[poly * 2 + 1].attr,POLY4DV2_ATTR_DISABLE_MATERIAL );

 

         //将三角形的状态设置为活动的

         obj->plist[poly *2].state                      =POLY4DV2_STATE_ACTIVE;

         obj->plist[poly * 2+ 1].state                  =POLY4DV2_STATE_ACTIVE;

 

         //将多边形顶点列表指向物体的顶点列表

         obj->plist[poly *2].vlist                      =obj->vlist_local;

         obj->plist[poly * 2+ 1].vlist                  =obj->vlist_local;

 

         //设置纹理坐标列表

         obj->plist[poly *2].tlist                      =obj->tlist;

         obj->plist[poly * 2+ 1].tlist                  =obj->tlist;

    }

 

 

 

    //计算多边形法线的长度

    Compute_OBJECT4DV2_Poly_Normals(math, obj);

    //计算使用GOURAUD着色的多边形,计算其顶点法线

    Compute_OBJECT4DV2_Vertex_Normals(math, obj);

   

 

    return( 1 );

 

 

 

}

 

演示程序是个沙地汽车,但是我不想去做这个,我只想看看引擎的运用,而不是逻辑,

 

在初始化时加载地形

 

 

    VECTOR4D     terrain_pos           = { 0, 0, 0, 0 };

 

 

         liushuixian_texture.Generate_Terrain_OBJECT4DV2( * math, & obj_work,4000, 3000, 700, "earthheightmap01.bmp","earthcolormap01.bmp",

                                                _RGB16BIT565( 255, 255, 255), & terrain_pos, NULL,POLY4DV2_ATTR_RGB16 | POLY4DV2_ATTR_SHADE_MODE_FLAT | POLY4DV2_ATTR_SHADE_MODE_TEXTURE );

摄像机位置改变

POINT4D  cam_pos    ={0,500,-200,1};

截图如下:



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值