您的位置:首页 > 其它

Ogre 武侠世界 GridInfo文件格式说明

2011-08-09 11:18 295 查看
天龙八部的地表做法与多年前的红警2的极为类似。都是由很多个格子(Title)组成,每个格子四个点,两个三角形。

下面我先给出天龙八部GridInfo文件格式,然后再简要介绍一下实现方式。

[GridInfo file format]

DWORD nVersion 版本号

int nWidth 地表宽度(横向格子数)

int nHeight 地表高度(纵向格子数)

如果版本号大于0x00100002则后面跟一个bool型数据,否则不存在这个bool型数据

bool bLarge GridInfo是否为7字节类型

如果bLarge存在并且值为1,则其后跟的是7字节版本否则为5字节版本

[GridInfo 5字节版本]

BYTE nFirstLayer 该值即为pixelmap的索引(第几个pixelmap)

BYTE nFirstLayerOp 对nFirstLayer的操作,可能取值如下:

0 不变

1 水平翻转

2 垂直翻转

4 向左旋转90度

8 对角线镜像

注意:这些值之间是可以取和的,比如9=1+8说明图片需要水平翻转和对角线镜像

BYTE nSecondLayer 该值为pixelmap的索引

天龙八部的地表最多可以两层融合,说白了就是每个点里有两层UV,这里为第二层pixelmap的索引

BYTE nSecondLayerOp 对nSecondLayer的操作,取值同nFirstLayerOp

BYTE IndexOrder 对格子的三角形的操作,可能取值如下

0正常三角形索引

1不同于正常的三角形索引

如下图,该值主要用在水池啊一类的地方,如果三角形索引不变的话,水池四个角中的两个角就不对了。







本文出自www.MobileGameBase.com

[GridInfo 7字节版本]

short nFirstLayer

读取后需交换高8位与低8位的值,需做如下操作

nFirstLayer = (nFirstLayer<<8)|(nFirstLayer>>8)

BYTE nFirstLayerOp

short nSecondLayer

同nFirstLayer,需交换高8位与低8位的值

BYTE nSecondLayerOp

BYTE IndexOrder

想象一下如果你设好每个点的位置,UV,法线,材质,整个场景不就出来了嘛。

现在的问题是如何操作这些VertexData和IndexData,其实Ogre本身就有大量的类直接这两者,比如Mesh,StaticGeometry,ManualObject等等。

部分源码:



使用的是Ogre的资源管理器来读取,另提供了saveToXML和saveToTGA的功能保存到XML文件和TGA文件:

GridInfos.h
#pragma once
namespace Ogre
{
struct GridHeader
{
DWORD nMagic;
// 版本号
DWORD nVersion;
// 地表宽度(横向格子数)
int nWidth;
// 地表高度(纵向格子数)
int nHeight;
};

// 图片水平翻转,即左右翻转
#define FLIP_HORIZINTAL 1
// 图片垂直翻转,即上下翻转
#define FLIP_VERTICAL 2
// 逆时针旋转90度
#define ANTICLOCKWISE_90 4
// 以三角形的对角线镜像,IndexOrder==0时就把左上的纹理坐标复制到右下,否则把右上的坐标复制到左下
#define FLIP_DIAGONAL 8

// 单个网格信息
struct GridInfo
{
// 该值即为pixelmap的索引(第几个pixelmap)
short    nFirstLayer;
// 对nFirstLayer的操作,取值是上面几个定义的宏,可以互相组合
BYTE    nFirstLayerOp;
// 该值为pixelmap的索引
//天龙八部的地表最多可以两层融合,说白了就是每个点里有两层UV,这里为第二层pixelmap的索引
short    nSecondLayer;
// 对nSecondLayer的操作,取值同nFirstLayerOp
BYTE    nSecondLayerOp;
// 对格子的三角形的操作,可能取值如下
//    0正常三角形索引
//    1不同于正常的三角形索引
BYTE    IndexOrder;
};

// 整个地形的网格信息
class GridInfos
{
public:
GridInfos(void);
virtual ~GridInfos(void);
// 打开网格文件
void open(const String &fileName , const String &groupName);
// 保存到XML文件中
void saveToXML(const String &xmlFileName);
// 保存到TGA文件中
void saveToTGA(const String &tgaFileName);
// 完毕并清空网格
void close();

typedef std::vector<GridInfo> GridData;
// 网格信息数组
GridData m_data;
// 宽高
size_t m_width , m_height;

};

};

GridInfos.cpp
#include "GridInfos.h"
namespace Ogre
{

GridInfos::GridInfos(void)
: m_width(0)
, m_height(0)
{
}

GridInfos::~GridInfos(void)
{
close();
}

// 打开网格文件
void GridInfos::open(const String &fileName , const String &groupName)
{
DataStreamPtr stream = ResourceGroupManager::getSingleton().openResource(fileName , groupName);
if(stream.isNull())
{
OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR,
"打开地形网格文件失败:" + fileName,
"GridInfos::open");
return ;
}
GridHeader header;
// 读取文件头
stream->read(&header , sizeof(header));
m_width = header.nWidth;
m_height = header.nHeight;

bool largeVersion = false;
// 看版本号大于这个,就表示后面跟着有个标记用来表示结构体的大小是7字节的版本还是5字节的版本
if(header.nVersion >= 0x00100001)
{
stream->read(&largeVersion , sizeof(largeVersion));
}

size_t uCount = m_width * m_height;
m_data.resize(uCount);
BYTE byteValue;

for(size_t i = 0 ; i < uCount ; i ++)
{
GridInfo &info = m_data[i];
if(largeVersion)
{
stream->read(&info.nFirstLayer , 2);
}
else
{
stream->read(&byteValue , 1);
info.nFirstLayer = byteValue;
}
info.nFirstLayer--;

stream->read(&info.nFirstLayerOp , 1);
if(largeVersion)
{
stream->read(&info.nSecondLayer , 2);
}
else
{
stream->read(&byteValue , 1);
info.nSecondLayer = byteValue;
}
info.nSecondLayer--;
stream->read(&info.nSecondLayerOp , 1);
stream->read(&info.IndexOrder , 1);
}

//saveToXML(fileName + ".xml");

}

// 完毕并清空网格
void GridInfos::close()
{
m_width = m_height = 0;
m_data.clear();
}
// 保存到TGA文件中
void GridInfos::saveToTGA(const String &tgaFileName)
{
size_t uCount = m_width * m_height;
RGBA *rgb = new RGBA[uCount];
for(size_t i = 0 ; i < uCount ; i ++)
{
rgb[i] = ((ulong)m_data[i].nFirstLayer << 16l) | (ulong)m_data[i].nSecondLayer;
}
Image image;
image.loadDynamicImage((uchar*)rgb , m_width , m_height , 1 , PF_A8R8G8B8);
image.save(tgaFileName);
}
// 保存到XML文件中
void GridInfos::saveToXML(const String &xmlFileName)
{
std::ofstream stream;
stream.open(xmlFileName.c_str());

stream << "<Grids>" << std::endl;
for(size_t i = 0 ; i < m_data.size() ; i ++)
{
GridInfo &info = m_data[i];
stream << "<Grid x=" << i % m_width
<< " z=" << i / m_width
<< " FirstLayer=" << (int)info.nFirstLayer
<< " FirstLayerOp=" << (int)info.nFirstLayerOp
<< " SecondLayer=" << (int)info.nSecondLayer
<< " SecondLayerOp=" << (int)info.nSecondLayerOp
<< " IndexOrder=" << (int)info.IndexOrder
<< "/>"
<< std::endl
;
}
stream << "</Grids>" << std::endl;
stream.close();
}

};


转载自:

http://www.mobilegamebase.com/

http://www.cppblog.com/mybios/archive/2009/07/26/91267.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: