- 打卡等级:热心大叔
- 打卡总天数:95
- 打卡月天数:18
- 打卡总奖励:95
- 最近打卡:2025-01-20 23:11:04
|
可以方便地实现天龙二进制的读和写 首先是序列类 #ifndef __CORE_SERIALIZER_UTIL_H__
#define __CORE_SERIALIZER_UTIL_H__
#include <OgreString.h>
#include <OgreDataStream.h>
using namespace Ogre;
namespace Core
{
// Endian routines
extern void flipToLittleEndian(void* pData, size_t size, size_t count = 1);
extern void flipFromLittleEndian(void* pData, size_t size, size_t count = 1);
extern void flipEndian(void * pData, size_t size, size_t count);
extern void flipEndian(void * pData, size_t size);
// Writer
class Writer
{
public:
virtual ~Writer() {}
void writeFloats(const float* pFloat, size_t count = 1);
void writeFloats(const double* pDouble, size_t count = 1);
void writeShorts(const uint16* pShort, size_t count = 1);
void writeInts(const uint32* pInt, size_t count = 1);
void writeBools(const bool* pBool, size_t count = 1);
void writeString(const String& string);
void writeObject(const Ogre::Vector3& v);
void writeObject(const Ogre:uaternion& q);
void writeData(const void* data, size_t size);
protected:
virtual void _write(const void* buf, size_t size, size_t count) = 0;
};
// Reader
class Reader
{
public:
virtual ~Reader() {}
void readFloats(float* pFloat, size_t count = 1);
void readFloats(double* pDouble, size_t count = 1);
void readShorts(uint16* pShort, size_t count = 1);
void readInts(uint32* pInt, size_t count = 1);
void readBools(bool* pBool, size_t count = 1);
String readString(void);
String readString(size_t numChars);
void readObject(Ogre::Vector3& v);
void readObject(Ogre:uaternion& q);
void readData(void* data, size_t size);
protected:
virtual void _read(void* buf, size_t size, size_t count) = 0;
};
// FileWriter
class FileWriter : public Writer
{
private:
FileWriter(const FileWriter&);
FileWriter& operator= (const FileWriter&);
public:
explicit FileWriter(FILE* file, bool adopts = false)
: mFile(file)
, mAdopts(adopts)
{
}
explicit FileWriter(const String& filename)
: mFile(fopen(filename.c_str(), "wb"))
, mAdopts(true)
{
}
~FileWriter()
{
if (mAdopts && mFile)
fclose(mFile);
}
FILE* getFile(void) const
{
return mFile;
}
protected:
FILE* mFile;
bool mAdopts;
void _write(const void* buf, size_t size, size_t count);
};
// DataStreamReader
class DataStreamReader : public Reader
{
private:
DataStreamReader(const DataStreamReader&);
DataStreamReader& operator= (const DataStreamReader&);
public:
explicit DataStreamReader(Ogre:ataStreamPtr& stream)
: mStream(stream)
{
}
Ogre:ataStreamPtr& getStream(void)
{
return mStream;
}
protected:
Ogre:ataStreamPtr mStream;
void _read(void* buf, size_t size, size_t count);
};
}
#endif
#include "CoreSerializerUtil.h"
#include <OgreDataStream.h>
#include <OgreVector3.h>
#include <OgreQuaternion.h>
#include <OgreException.h>
namespace Core
{
//--------------------------------------------------------------------------------------------
void flipToLittleEndian(void* pData, size_t size, size_t count)
{
# if OGRE_ENDIAN == OGRE_ENDIAN_BIG
flipEndian(pData, size, count);
# endif
}
//--------------------------------------------------------------------------------------------
void flipFromLittleEndian(void* pData, size_t size, size_t count)
{
# if OGRE_ENDIAN == OGRE_ENDIAN_BIG
flipEndian(pData, size, count);
# endif
}
//--------------------------------------------------------------------------------------------
void flipEndian(void * pData, size_t size, size_t count)
{
for(size_t index = 0; index < count; index++)
{
flipEndian((void *)((int)pData + (index * size)), size);
}
}
//--------------------------------------------------------------------------------------------
void flipEndian(void * pData, size_t size)
{
char swapByte;
for(size_t byteIndex = 0; byteIndex < size/2; byteIndex++)
{
swapByte = *(char *)((int)pData + byteIndex);
*(char *)((int)pData + byteIndex) = *(char *)((int)pData + size - byteIndex - 1);
*(char *)((int)pData + size - byteIndex - 1) = swapByte;
}
}
//---------------------------------------------------------------------
void Writer::writeFloats(const float* pFloat, size_t count)
{
# if OGRE_ENDIAN == OGRE_ENDIAN_BIG
float * pFloatToWrite = (float *)malloc(sizeof(float) * count);
memcpy(pFloatToWrite, pFloat, sizeof(float) * count);
flipToLittleEndian(pFloatToWrite, sizeof(float), count);
_write(pFloatToWrite, sizeof(float), count);
free(pFloatToWrite);
# else
_write(pFloat, sizeof(float), count);
# endif
}
//---------------------------------------------------------------------
void Writer::writeFloats(const double* pDouble, size_t count)
{
// Convert to float, then write
float* tmp = new float[count];
for (size_t i = 0; i < count; ++i)
{
tmp[i] = static_cast<float>(pDouble[i]);
}
# if OGRE_ENDIAN == OGRE_ENDIAN_BIG
flipToLittleEndian(tmp, sizeof(float), count);
_write(tmp, sizeof(float), count);
# else
_write(tmp, sizeof(float), count);
# endif
delete [] tmp;
}
//---------------------------------------------------------------------
void Writer::writeShorts(const uint16* pShort, size_t count)
{
# if OGRE_ENDIAN == OGRE_ENDIAN_BIG
uint16 * pShortToWrite = (uint16 *)malloc(sizeof(uint16) * count);
memcpy(pShortToWrite, pShort, sizeof(uint16) * count);
flipToLittleEndian(pShortToWrite, sizeof(uint16), count);
_write(pShortToWrite, sizeof(uint16), count);
free(pShortToWrite);
# else
_write(pShort, sizeof(uint16), count);
# endif
}
//---------------------------------------------------------------------
void Writer::writeInts(const uint32* pInt, size_t count)
{
# if OGRE_ENDIAN == OGRE_ENDIAN_BIG
uint32 * pIntToWrite = (uint32 *)malloc(sizeof(uint32) * count);
memcpy(pIntToWrite, pInt, sizeof(uint32) * count);
flipToLittleEndian(pIntToWrite, sizeof(uint32), count);
_write(pIntToWrite, sizeof(uint32), count);
free(pIntToWrite);
# else
_write(pInt, sizeof(uint32), count);
# endif
}
//---------------------------------------------------------------------
void Writer::writeBools(const bool* pBool, size_t count)
{
// no endian flipping for 1-byte bools
// XXX Nasty Hack to convert to 1-byte bools
# if OGRE_PLATFORM == OGRE_PLATFORM_APPLE
char * pCharToWrite = (char *)malloc(sizeof(char) * count);
for(int i = 0; i < count; i++)
{
*(char *)(pCharToWrite + i) = *(bool *)(pBool + i);
}
_write(pCharToWrite, sizeof(char), count);
free(pCharToWrite);
# else
_write(pBool, sizeof(bool), count);
# endif
}
//---------------------------------------------------------------------
void Writer::writeString(const String& string)
{
uint32 numChars = string.length();
writeInts(&numChars);
_write(string.c_str(), sizeof(String::value_type), numChars);
}
//---------------------------------------------------------------------
void Writer::writeObject(const Ogre::Vector3& v)
{
writeFloats(&v.x);
writeFloats(&v.y);
writeFloats(&v.z);
}
//---------------------------------------------------------------------
void Writer::writeObject(const Ogre:uaternion& q)
{
writeFloats(&q.x);
writeFloats(&q.y);
writeFloats(&q.z);
writeFloats(&q.w);
}
//---------------------------------------------------------------------
void Writer::writeData(const void* data, size_t size)
{
_write(data, size, 1);
}
//---------------------------------------------------------------------
void Reader::readFloats(float* pFloat, size_t count)
{
_read(pFloat, sizeof(float), count);
flipFromLittleEndian(pFloat, sizeof(float), count);
}
//---------------------------------------------------------------------
void Reader::readFloats(double* pDouble, size_t count)
{
// Read from float, convert to double
float* tmp = new float[count];
float* ptmp = tmp;
_read(tmp, sizeof(float), count);
flipFromLittleEndian(tmp, sizeof(float), count);
// Convert to doubles (no cast required)
while (count--)
{
*pDouble++ = *ptmp++;
}
delete [] tmp;
}
//---------------------------------------------------------------------
void Reader::readShorts(uint16* pShort, size_t count)
{
_read(pShort, sizeof(uint16), count);
flipFromLittleEndian(pShort, sizeof(uint16), count);
}
//---------------------------------------------------------------------
void Reader::readInts(uint32* pInt, size_t count)
{
_read(pInt, sizeof(uint32), count);
flipFromLittleEndian(pInt, sizeof(uint32), count);
}
//---------------------------------------------------------------------
void Reader::readBools(bool* pBool, size_t count)
{
//XXX Nasty Hack to convert 1 byte bools to 4 byte bools
# if OGRE_PLATFORM == OGRE_PLATFORM_APPLE
char * pTemp = (char *)malloc(1*count); // to hold 1-byte bools
_read(pTemp, sizeof(char), count);
for(int i = 0; i < count; i++)
*(bool *)(pBool + i) = *(char *)(pTemp + i);
free (pTemp);
# else
_read(pBool, sizeof(bool), count);
# endif
//no flipping on 1-byte datatypes
}
//---------------------------------------------------------------------
String Reader::readString(size_t numChars)
{
String str(numChars, '/0');
_read(const_cast<String::value_type*>(str.data()), sizeof(String::value_type), numChars);
return str;
}
//---------------------------------------------------------------------
String Reader::readString(void)
{
uint32 numChars;
readInts(&numChars);
return readString(numChars);
}
//---------------------------------------------------------------------
void Reader::readObject(Ogre::Vector3& v)
{
readFloats(&v.x);
readFloats(&v.y);
readFloats(&v.z);
}
//---------------------------------------------------------------------
void Reader::readObject(Ogre:uaternion& q)
{
readFloats(&q.x);
readFloats(&q.y);
readFloats(&q.z);
readFloats(&q.w);
}
//---------------------------------------------------------------------
void Reader::readData(void* data, size_t size)
{
_read(data, size, 1);
}
//--------------------------------------------------------------------------------------------
void FileWriter::_write(const void* buf, size_t size, size_t count)
{
if (fwrite(buf, size, count, mFile) != count)
{
OGRE_EXCEPT(Ogre::Exception::ERR_CANNOT_WRITE_TO_FILE,
"Can't write data to file",
"FileWriter::_write");
}
}
//--------------------------------------------------------------------------------------------
void DataStreamReader::_read(void* buf, size_t size, size_t count)
{
if (mStream->read(buf, size * count) != size * count)
{
OGRE_EXCEPT(Ogre::Exception::ERR_INTERNAL_ERROR,
"Can't read data from stream",
"DataStreamReader::_read");
}
}
}
怎么用呢,举个例子,我们读取和写入高度图 namespace Core
{
const uint32 TERRAIN_HEIGHTMAP_MAGIC = 'FEHM';
const uint32 TERRAIN_HEIGHTMAP_VERSION = 0x00100000;
//------------------------------------------------------------------------------------------------
void TerrainData::_loadHeightmap(const String& filename, const String& type, const String& groupName)
{
// 分配buffer
mHeightmap.resize((mXSize + 1) * (mZSize + 1));
if (filename.empty())
{
std::fill(mHeightmap.begin(), mHeightmap.end(), (Real)0);
}
else if (type == "image")
{
// 省略
}
else if (type == "standard")
{
Ogre:ataStreamPtr stream = Ogre::ResourceGroupManager::getSingleton().openResource(filename, groupName);
DataStreamReader reader(stream);
// 文件头校验
uint32 header[4];
reader.readInts(header, 4);
if (header[0] != TERRAIN_HEIGHTMAP_MAGIC)
{
// 异常
}
if (header[1] != TERRAIN_HEIGHTMAP_VERSION)
{
// 异常
}
if (header[2] != mXSize+1 || header[3] != mZSize+1)
{
// 异常
}
// 读取高度数据
reader.readFloats(&mHeightmap[0], mHeightmap.size());
// 文件尾校验
if (stream->tell() != stream->size())
{
// 异常
}
}
else
{
assert(type == "raw");
// 省略
}
}
//-----------------------------------------------------------------------------------------------------------------
void TerrainData::_saveHeightmap(const String& filename) const
{
FileWriter writer(filename);
// 写文件头
uint32 header[4];
header[0] = TERRAIN_HEIGHTMAP_MAGIC;
header[1] = TERRAIN_HEIGHTMAP_VERSION;
header[2] = mXSize + 1;
header[3] = mZSize + 1;
writer.writeInts(header, 4);
// 写数据
writer.writeFloats(&mHeightmap[0], mHeightmap.size());
}
}
|
|