《黑与白》游戏的地形文件格式
- Version 1-2001
注:由于时间的缘故,没有得仔细对照原文进行排版。那就请您自己忙忙咯,去看他们的网站看看E文版(因为GPE兄也没有把E文发给我,前段时间我去找,可惜那公司的服务有问题:(。
原文:Lionhead .LND file format document version 1
作者:Black & White公司: http://www.lionhead.com/ (文章在论坛里?)
版本:Release 1.0
1
、术语:
概念上它是一张512x512的高度地图以块划分。
地图被分成 32 x 32个块,每个块是由16x16的地形单元组成(每个单元被当作一个四边形渲染 - 即2个三角形)。每个块有17x17点(16单元17点)。每个点存在单独的高度值和颜色值。
整个世界存在1024个地图块。但是最多只能允许有255个块是陆地。其中75 % 的地形块是不使用的 (全是海,没有陆地)。另外的25%在文件中被保存,每个被使用的块都有唯一的ID( 1 – 255)来标识。标识0不属于陆地块的范畴。
m_index_block 数组大小为32x32。
“countries”定义陆地主题(沙漠,森林,草,平原, montain ...),地图中的每一个块都使用唯一的256 x 256 的纹理渲染。
“materials”用来与原本的256x256大小的纹理混合,适合每一种类型的块(与Countries,海拔高度等等有关)。
“lores_textures”是一个256X256覆盖4X4的块区域的纹理,并且被用来渲染远处的地面,他们被预处理,并且保存到文件。游戏在运行的时候如果必要就更新,它有4梯度的LOD。游戏中材质经过混合处理后的效果是非常好的(这就是为什么你可以快速的填充4X4的块的纹理到lores texture)
2
、现在开始进入文件格式
这是一个类c风格的结构申明,直接保存到磁盘的时候要注意这信息是可能的。你应该多多试验,因为在内存景象中,大多数指针没有被保存。
first header:
{
// Island Stuff.
SLONG m_count_block;
UBYTE m_index_block[INDEX_BLOCK_COUNT]; // 32*32
// Landscape Stuff
SLONG m_count_material;
SLONG m_count_country;
// Check
SLONG m_check_size_block; // sizeof(LandBlock)
SLONG m_check_size_material; // sizeof(Material)
SLONG m_check_size_country; // sizeof(Country)
ULONG m_count_lores_textures;
}
信息头后面,接着分别是lo-res纹理,地图块,地面数据,材质数据的数组,最后是两个位图:
lorestexture lorestex[m_count_lores_textures]
LandBlock block[m_count_block]
Country country[m_count_country]
Material mat[m_count_material]
then noise map (256x256x8 bit greyscale bitmap)
then bump map (256x256x8 bit greyscale bitmap)
(亮度位图,高度位图用来处理混合过程)
3
、现在解释landblock
……的格式
接下来的部分解释……等被保存在文件的数组结构,在头后面直接接着的就是这些数组:
LH3DTexture* m_texture;
LH3DMaterial* m_material;
SLONG m_sub_texture_count;
SLONG m_id;
then compressed texture data:
SLONG m_size; // size of whole compressed texture data including this header
DIRECTDRAWSURFACEDESC m_ddsd;
UBYTE data[]; // in d3d compressed texture format described by m_ddsd
///////////////////
block format: (basically an image on disk of the memory structure used by b+w)
struct LandBlock
{
enum LandMeshLOD
{
LOD_0 =0,
LOD_1 =1,
LOD_2 =2,
LOD_UNDEF ,
};
enum MeshBlendingMod
{
FULL_0 =0,
BLEND_0_AND_1 =1,
FULL_1 =2,
BLEND_1_AND_2 =3,
FULL_2 =4,
};
enum TextureBlend
{
HIGH_DETAIL = 0,
LOW_DETAIL = 1,
MIXTE_DETAIL = 2,
};
typedef struct {
BOOL m_b_clipped;
ULONG m_frame_visibility;
ULONG m_b_unused;
BOOL m_b_use_small_bump;
BOOL m_force_use_lowres_texture;
LandMeshLOD m_mesh_lod;
MeshLOD::MeshBlendingMod m_mesh_blending;
TextureLOD::TextureBlend m_texture_blend;
MeshLodType m_mesh_lod_type;
TFog m_fog;
} Info;
LandCell m_cells[(17*17 + 4) & ~0x4];
SLONG m_index; // unique id of block
float m_offset_X; // position of block in 512x512 world
float m_offset_Z; // position of block in 512x512 world
SLONG m_line_32; // position of block in 32x32 block array
SLONG m_column_32; // position of block in 32x32 block array
Info m_info; // rendering info
LH3DTexture* m_texture;
LH3DMaterial* m_material;
SLONG m_b_draw_something;
LH3DMaterial *m_special_material_before;
LH3DMaterial *m_special_material_after;
LHMatrix m_transform_uv_before;
LHMatrix m_transform_uv_after;
LandBlock* m_next_sorting;
float m_value_sorting;
LowResTexture* m_low_res_texture;
float m_fu_lrs; // 0.0f <-> 1.0f
float m_fv_lrs;
SLONG m_iu_lrs; // 0 <-> 256
SLONG m_iv_lrs;
BOOL m_b_small_texture_updated;
}
this block format above uses Cells: the cell format is
struct LandCell
{
union
{
ULONG m_light;
struct
{
UBYTE m_blue;
UBYTE m_green;
UBYTE m_red;
UBYTE m_color;
};
};
UBYTE m_altitude;
UBYTE m_save_color;
UWORD m_flags;
// the flags is a bitfield with these values:
// nb split is used to say if the cell's quad is split into triangles this way: / or this way: /
enum
{
MASK_COUNTRY = 0xF,
MASK_WATER = (1<<4),
MASK_COAST = (1<<5),
MASK_TYPE = (MASK_WATER|MASK_COAST),
MASK_SPLIT = (1<<7),
MASK_INVISIBLE = (1<<8), // TODO
MASK_FULLWATER = (1<<9),
SOUND_LAND = 0,
SOUND_SEA = 1,
SOUND_FRESH_WATER = 2,
SOUND_COASTAL = 3,
SOUND_BIT0 = (1<<10),
SOUND_BIT1 = (1<<11),
SOUND_BIT2 = (1<<12),
SOUND_BIT3 = (1<<13),
ROL_SOUND = 10,
MASK_SOUND = SOUND_BIT0|SOUND_BIT1|SOUND_BIT2|SOUND_BIT3,
};
enum TSplit
{
TSPLIT_NORMAL = 0,
TSPLIT_INVERSE = 1,
TSPLIT_MAX = 0xFFFFFFFF,
};
}
//////// country format
struct Country
{
ULONG terrain_type;
typedef struct
{
ULONG index_1;
ULONG index_2;
ULONG coef1;
} TMapMaterial;
TMapMaterial map_material[256];
}
///////////// material format
struct Material
{
UWORD m_terrain_type;
UWORD m_image[256*256];
};
thats all.