您的位置:首页 > 其它

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

2016-01-10 18:35 483 查看
转眼间,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_OBJECT4DV2(
ddraw_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};
截图如下:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: