[GridInfo 5字节版本]
BYTE nFirstLayer 该值即为pixelmap的索引(第几个pixelmap)BYTE nFirstLayerOp
short nSecondLayer现在的问题是如何操作这些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