修改ETM,用Ogre实现《天龙八部》地形与部分场景详解(附源码)

本文主要讲的是《天龙八部》游戏的地形和一部分场景的具体实现,使用C++, Ogre1.6,我摸索了段时间,可能方法用的并不是最好的,但好歹实现了。文章可能讲得有点罗嗦,很多简单的东西都讲了。我是修改了ETM(Editable Terrain Manager)实现的地形,其实单单实现天龙八部的地形场景等的载入根本不需要使用ETM,直接用Ogre的顶点->索引->纹理就可以搞定地形,但我要做的是可以实时编辑的,所以用了ETM,场景其由于很重要的粒子和model等部分我还没去看,所以等以后看了再详细写关于场景的部分,但这个Demo已经实现了基本的场景的载入。光,雾,环境,静态物等都能载入。

修改过的ETM和这个场景的Demo代码可以通过文章底下的链接下载。

Demo截图如下:(少林)

修改ETM,用Ogre实现《天龙八部》地形与部分场景详解(附源码)_第1张图片

这个Demo比较简单,只能移动摄像机看看场景。

我研究这些的动机是当前在学校做一个网游项目,想做得类似于《Second Life》,苦于没有游戏美工,最近有马上要二期验收了,为了让游戏看上去光鲜一点,无奈之下只好借《天龙八部》的资源来用了。看了不少大牛的博客,将得感觉都有点不是很详细,只是大概把文件格式讲了一下而已,具体怎么实现说得不多(可能是觉得实现太容易,懒得多说了吧...)最主要的是,似乎没看到有人发完整的代码。

实际项目中用的程序代码我就不放出来了,场景部分差不多,只是多了个内建的编辑器,人物移动和网络通信部分等。

编辑器的截图晒一下,功能还不全 :-)

修改ETM,用Ogre实现《天龙八部》地形与部分场景详解(附源码)_第2张图片

 

言归正传,先简单地说一下载入一个天龙八部场景的大致过程:

  • 读取.Scene文件
  • 根据读取.Terrain文件
  • 读取地砖大小() 地形大小(xsize, ysize),缩放值(),地图中心坐标(
    )。
  • 读取所有要用的地形贴图(中各项)。
  • 读取.gridinfo 文件,此文件中存放着每个格子对应的纹理坐标。
  • 根据3,4,5步的信息用修改过的ETM创建Terrain。
  • 读取lightmap, 是png格式的预处理的场景阴影图。
  • 读取场景中的各种模型等,并插入到场景Root中。

(注:天龙八部的场景包含很多个文件,用“劒蚩”的资源提取工具提取出来,文件夹下的基本都是,但我暂时不考虑寻路,碰撞等,所以就地形来讲只研究.Terrain文件,.Gridinfo文件。 资源提取的问题可访问http://www.cnitblog.com/sword/category/5167.htmlScene )

 

下面我分几个部分来具体讲如何实现天龙八部的场景Demo。

读取高度图

做地形首先肯定是要读取高度图,《天龙八部》的高度图是保存在.Heightmap文件中,读取的方法是跳过前面8个字节,读地形的width和height,然后读取width*height个float型数据,上面说到.Terrain文件中有地形大小(xsize, ysize),缩放值(),地图中心坐标(

),中有xyz 3个值(一般情况下是100,100,100),分别是x,y,z轴的放大系数,用ETM创建地形的时候,直接用读取到的float型数据作为高度图数据,然后再用上面那些值作为参数,定义地形的大小,缩放值,和偏移。

这是读取高度图的代码,heightMapData是float型的数组,存放原始的高度图信息。

void TileTerrainInfo::LoadHightMap( const char* fileName, const char* type )
{
    FILE* pf = fopen( fileName, "rb" );
    fseek( pf, 8, SEEK_SET );
    int height, width;
    fread( &width, 4,1, pf );
    fread( &height, 4,1, pf );

    assert( height = this->height+1 );
    assert( width == this->width+1 );

    if( heightMapData )
        delete []heightMapData;
    
    heightMapData = new float[height*width];
    for( int i = 0; i < height; ++i )
    {
        for( int j  = 0; j < width; ++j )
        {
            float data;
            fread( &data, 4,1,pf );
            heightMapData[i*width+j] = data;
        }    
    }

    fclose( pf );
}
 

材质文件的分析

我想先讲一下地形的材质,因为用别人的资源,首先要知道怎么用这些资源,一般情况下材质信息可以明显地反映出如何使用纹理资源(不排除有可能用代码动态生成材质)。

在每个.Terrain文件的最下面,有这些内容。