轉(zhuǎn)自:http://www.shnenglu.com/mybios/archive/2008/03/09/44046.aspx
天龍八部GridInfo文件的格式已經(jīng)有人公布了,在這里:
http://www.mobilegamebase.com/blog/article.asp?id=17不過,此文中有點(diǎn)筆誤的地方,就是那個(gè)nFirstLayerOP的位標(biāo)記的描述有點(diǎn)錯(cuò)誤,正確的應(yīng)該如下:
// 圖片水平翻轉(zhuǎn),即左右翻轉(zhuǎn)
#define FLIP_HORIZINTAL 1
// 圖片垂直翻轉(zhuǎn),即上下翻轉(zhuǎn)
#define FLIP_VERTICAL 2
// 逆時(shí)針旋轉(zhuǎn)90度
#define ANTICLOCKWISE_90 4
// 以三角形的對角線鏡像,IndexOrder==0時(shí)就把左上的紋理坐標(biāo)復(fù)制到右下,否則把右上的坐標(biāo)復(fù)制到左下
#define FLIP_DIAGONAL 8
具體的讀取源碼如下,使用的是Ogre的資源管理器來讀取,另提供了saveToXML和saveToTGA的功能保存到XML文件和TGA文件:
GridInfos.h
#pragma once
namespace Ogre
{
struct GridHeader
{
DWORD nMagic;
// 版本號
DWORD nVersion;
// 地表寬度(橫向格子數(shù))
int nWidth;
// 地表高度(縱向格子數(shù))
int nHeight;
};
// 圖片水平翻轉(zhuǎn),即左右翻轉(zhuǎn)
#define FLIP_HORIZINTAL 1
// 圖片垂直翻轉(zhuǎn),即上下翻轉(zhuǎn)
#define FLIP_VERTICAL 2
// 逆時(shí)針旋轉(zhuǎn)90度
#define ANTICLOCKWISE_90 4
// 以三角形的對角線鏡像,IndexOrder==0時(shí)就把左上的紋理坐標(biāo)復(fù)制到右下,否則把右上的坐標(biāo)復(fù)制到左下
#define FLIP_DIAGONAL 8
// 單個(gè)網(wǎng)格信息
struct GridInfo
{
// 該值即為pixelmap的索引(第幾個(gè)pixelmap)
short nFirstLayer;
// 對nFirstLayer的操作,取值是上面幾個(gè)定義的宏,可以互相組合
BYTE nFirstLayerOp;
// 該值為pixelmap的索引
//天龍八部的地表最多可以兩層融合,說白了就是每個(gè)點(diǎn)里有兩層UV,這里為第二層pixelmap的索引
short nSecondLayer;
// 對nSecondLayer的操作,取值同nFirstLayerOp
BYTE nSecondLayerOp;
// 對格子的三角形的操作,可能取值如下
// 0正常三角形索引
// 1不同于正常的三角形索引
BYTE IndexOrder;
};
// 整個(gè)地形的網(wǎng)格信息
class GridInfos
{
public:
GridInfos(void);
virtual ~GridInfos(void);
// 打開網(wǎng)格文件
void open(const String &fileName , const String &groupName);
// 保存到XML文件中
void saveToXML(const String &xmlFileName);
// 保存到TGA文件中
void saveToTGA(const String &tgaFileName);
// 完畢并清空網(wǎng)格
void close();
typedef std::vector<GridInfo> GridData;
// 網(wǎng)格信息數(shù)組
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();
}
// 打開網(wǎng)格文件
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,
"打開地形網(wǎng)格文件失敗:" + fileName,
"GridInfos::open");
return ;
}
GridHeader header;
// 讀取文件頭
stream->read(&header , sizeof(header));
m_width = header.nWidth;
m_height = header.nHeight;
bool largeVersion = false;
// 看版本號大于這個(gè),就表示后面跟著有個(gè)標(biāo)記用來表示結(jié)構(gòu)體的大小是7字節(jié)的版本還是5字節(jié)的版本
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");
}
// 完畢并清空網(wǎng)格
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();
}
};