Zone MMF Implementation (for map files)

This commit is contained in:
Uleat 2016-07-28 22:50:06 -04:00
parent 345f3d6301
commit 84db0ec2c5
8 changed files with 605 additions and 2 deletions

View File

@ -30,6 +30,7 @@
#EQEMU_BUILD_LUA
#EQEMU_SANITIZE_LUA_LIBS
#EQEMU_BUILD_CLIENT_FILES
#EQEMU_USE_MAP_MMFS
#EQEMU_MAP_DIR
#We set a fairly new version (as of 2013) because I found finding perl was a bit... buggy on older ones
@ -275,6 +276,11 @@ IF(EQEMU_BUILD_LUA)
ADD_DEFINITIONS(-DLUA_EQEMU)
ENDIF(EQEMU_BUILD_LUA)
OPTION(EQEMU_USE_MAP_MMFS "Create and use Zone Map MMF files." OFF)
IF(EQEMU_USE_MAP_MMFS)
ADD_DEFINITIONS(-DUSE_MAP_MMFS)
ENDIF(EQEMU_USE_MAP_MMFS)
SET(EQEMU_MAP_DIR "./Maps" CACHE STRING "The dir that maps, water maps, and paths are located in.")
ADD_DEFINITIONS(-DEQDEBUG=${EQEMU_DEBUG_LEVEL})

View File

@ -1,6 +1,18 @@
EQEMu Changelog (Started on Sept 24, 2003 15:50)
-------------------------------------------------------
== 07/25/216 ==
== 07/28/2016 ==
Uleat: Implemented zone memory-mapped file usage
- Zone map files are converted to pre-loaded binary files, bypassing the (sometimes) time-consuming raw data transform process
- There are three ways to convert files:
-- Do nothing! The zone bootup process will check for a mmf file and load it, if found, or create it after the 'normal' transform process is complete
-- Use the command line option: zone convert_map <zone_name>.map (for singular conversions)
-- Drop the 'convert_maps_to_mmfs.pl' into your server directory and execute it for a batch conversion
-- Note: Any zone maps not pre-converted will be processed once a zone is booted up that does not have one
- To enable this feature, you must have the 'USE_MAP_MMFS' option checked in cmake and have built binaries on that
- To disable this feature, or if you encouter problems, disable the 'USE_MAP_MMFS' option and rebuild your binaries
- This feature will test the validity of your zlib library. If you get errors/crashes upon conversion, then your zlib1.dll is most likely suspect (check our forum for solutions)
== 07/25/2016 ==
mackal: Fix up the SpellBuff struct
- THERE MAYBE BUGS
- there shouldn't though, most of the hackery was from badly named fields causing confusion

View File

@ -0,0 +1,34 @@
#!/usr/bin/perl
###########################################################
#::: Automatic (Map-to-MMF) Conversion Script
#::: Author: Uleat
#::: Purpose: To convert existing zone maps to memory-mapped files
###########################################################
use Config;
print("\n");
print("Zone Map-to-MMF Batch convertor\n");
print("===============================\n");
print("\n");
if($Config{osname}=~/freebsd|linux/i){ $OS = "Linux"; }
if($Config{osname}=~/Win|MS/i){ $OS = "Windows"; }
print("Operating System is: $Config{osname}\n");
print("\n");
opendir(D, "maps") || die "Can't find directory maps: $!\n";
my @mapfiles = grep { /\.map$/ && !/_lit/ } readdir(D);
closedir(D);
foreach my $mapfile (@mapfiles) {
my $result = "Unknown action..\n";
print("processing map: '$mapfile'\n");
if($OS eq "Windows"){ $result = `zone convert_map $mapfile`; }
if($OS eq "Linux"){ $result = `./zone convert_map $mapfile`; }
print("-- $result");
}
print("\n");
print("Batch processing complete\n")

View File

@ -12,6 +12,48 @@
#include <vector>
#include <zlib.h>
uint32 EstimateDeflateBuffer(uint32_t len) {
z_stream zstream;
memset(&zstream, 0, sizeof(zstream));
zstream.zalloc = Z_NULL;
zstream.zfree = Z_NULL;
zstream.opaque = Z_NULL;
if (deflateInit(&zstream, Z_FINISH) != Z_OK)
return 0;
return deflateBound(&zstream, len);
}
uint32_t DeflateData(const char *buffer, uint32_t len, char *out_buffer, uint32_t out_len_max) {
z_stream zstream;
memset(&zstream, 0, sizeof(zstream));
int zerror;
zstream.next_in = const_cast<unsigned char*>(reinterpret_cast<const unsigned char*>(buffer));
zstream.avail_in = len;
zstream.zalloc = Z_NULL;
zstream.zfree = Z_NULL;
zstream.opaque = Z_NULL;
deflateInit(&zstream, Z_FINISH);
zstream.next_out = reinterpret_cast<unsigned char*>(out_buffer);
zstream.avail_out = out_len_max;
zerror = deflate(&zstream, Z_FINISH);
if (zerror == Z_STREAM_END)
{
deflateEnd(&zstream);
return (uint32_t)zstream.total_out;
}
else
{
zerror = deflateEnd(&zstream);
return 0;
}
}
uint32 InflateData(const char* buffer, uint32 len, char* out_buffer, uint32 out_len_max) {
z_stream zstream;
int zerror = 0;
@ -241,7 +283,16 @@ Map *Map::LoadMapFile(std::string file) {
return nullptr;
}
bool Map::Load(std::string filename) {
#ifdef USE_MAP_MMFS
bool Map::Load(std::string filename, bool force_mmf_overwrite)
{
if (LoadMMF(filename, force_mmf_overwrite))
return true;
#else
bool Map::Load(std::string filename)
{
#endif /*USE_MAP_MMFS*/
FILE *f = fopen(filename.c_str(), "rb");
if(f) {
uint32 version;
@ -253,10 +304,22 @@ bool Map::Load(std::string filename) {
if(version == 0x01000000) {
bool v = LoadV1(f);
fclose(f);
#ifdef USE_MAP_MMFS
if (v)
return SaveMMF(filename, force_mmf_overwrite);
#endif /*USE_MAP_MMFS*/
return v;
} else if(version == 0x02000000) {
bool v = LoadV2(f);
fclose(f);
#ifdef USE_MAP_MMFS
if (v)
return SaveMMF(filename, force_mmf_overwrite);
#endif /*USE_MAP_MMFS*/
return v;
} else {
fclose(f);
@ -897,3 +960,199 @@ void Map::TranslateVertex(glm::vec3 &v, float tx, float ty, float tz) {
v.y = v.y + ty;
v.z = v.z + tz;
}
#ifdef USE_MAP_MMFS
inline void strip_map_extension(std::string& map_file_name)
{
auto ext_off = map_file_name.find(".map");
if (ext_off != std::string::npos)
map_file_name.erase(ext_off, strlen(".map"));
}
inline bool add_mmf_extension(std::string& mmf_file_name)
{
if (mmf_file_name.empty())
return false;
mmf_file_name.append(".mmf");
size_t dot_check = std::count(mmf_file_name.begin(), mmf_file_name.end(), '.');
return (dot_check == 1);
}
bool Map::LoadMMF(const std::string& map_file_name, bool force_mmf_overwrite)
{
if (force_mmf_overwrite)
return false;
std::string mmf_file_name = map_file_name;
strip_map_extension(mmf_file_name);
if (!add_mmf_extension(mmf_file_name)) {
Log.Out(Logs::General, Logs::Zone_Server, "Failed to load Map MMF file: '%s'", mmf_file_name.c_str());
return false;
}
FILE *f = fopen(mmf_file_name.c_str(), "rb");
if (!f) {
Log.Out(Logs::General, Logs::Zone_Server, "Failed to load Map MMF file: '%s' - could not open file", mmf_file_name.c_str());
return false;
}
uint32 file_version;
if (fread(&file_version, sizeof(uint32), 1, f) != 1) {
fclose(f);
Log.Out(Logs::General, Logs::Zone_Server, "Failed to load Map MMF file: '%s' - f@file_version", mmf_file_name.c_str());
return false;
}
uint32 rm_buffer_size;
if (fread(&rm_buffer_size, sizeof(uint32), 1, f) != 1) {
fclose(f);
Log.Out(Logs::General, Logs::Zone_Server, "Failed to load Map MMF file: '%s' - f@rm_buffer_size", mmf_file_name.c_str());
return false;
}
uint32 rm_buffer_crc32;
if (fread(&rm_buffer_crc32, sizeof(uint32), 1, f) != 1) {
fclose(f);
Log.Out(Logs::General, Logs::Zone_Server, "Failed to load Map MMF file: '%s' - f@rm_buffer_crc32", mmf_file_name.c_str());
return false;
}
if (rm_buffer_crc32 != /*crc32_check*/ 0) {
fclose(f);
Log.Out(Logs::General, Logs::Zone_Server, "Failed to load Map MMF file: '%s' - bad rm_buffer checksum", mmf_file_name.c_str());
return false;
}
uint32 mmf_buffer_size;
if (fread(&mmf_buffer_size, sizeof(uint32), 1, f) != 1) {
fclose(f);
Log.Out(Logs::General, Logs::Zone_Server, "Failed to load Map MMF file: '%s' - f@mmf_buffer_size", mmf_file_name.c_str());
return false;
}
std::vector<char> mmf_buffer(mmf_buffer_size);
if (fread(mmf_buffer.data(), mmf_buffer_size, 1, f) != 1) {
fclose(f);
Log.Out(Logs::General, Logs::Zone_Server, "Failed to load Map MMF file: '%s' - f@mmf_buffer", mmf_file_name.c_str());
return false;
}
fclose(f);
std::vector<char> rm_buffer(rm_buffer_size);
uint32 v = InflateData(mmf_buffer.data(), mmf_buffer_size, rm_buffer.data(), rm_buffer_size);
if (imp) {
imp->rm->release();
imp->rm = nullptr;
}
else {
imp = new impl;
}
bool load_success = false;
imp->rm = loadRaycastMesh(rm_buffer, load_success);
if (imp->rm && !load_success) {
imp->rm->release();
imp->rm = nullptr;
}
if (!imp->rm) {
delete imp;
imp = nullptr;
Log.Out(Logs::General, Logs::Zone_Server, "Failed to load Map MMF file: '%s' - null RaycastMesh", mmf_file_name.c_str());
return false;
}
return true;
}
bool Map::SaveMMF(const std::string& map_file_name, bool force_mmf_overwrite)
{
if (!imp || !imp->rm) {
Log.Out(Logs::General, Logs::Zone_Server, "Failed to save Map MMF file - No implementation (map_file_name: '%s')", map_file_name.c_str());
return false;
}
std::string mmf_file_name = map_file_name;
strip_map_extension(mmf_file_name);
if (!add_mmf_extension(mmf_file_name)) {
Log.Out(Logs::General, Logs::Zone_Server, "Failed to save Map MMF file: '%s'", mmf_file_name.c_str());
return false;
}
FILE* f = fopen(mmf_file_name.c_str(), "rb");
if (f) {
fclose(f);
if (!force_mmf_overwrite)
return true;
}
std::vector<char> rm_buffer; // size set in MyRaycastMesh::serialize()
serializeRaycastMesh(imp->rm, rm_buffer);
if (rm_buffer.empty()) {
Log.Out(Logs::General, Logs::Zone_Server, "Failed to save Map MMF file: '%s' - empty RaycastMesh buffer", mmf_file_name.c_str());
return false;
}
uint32 rm_buffer_size = rm_buffer.size();
uint32 mmf_buffer_size = EstimateDeflateBuffer(rm_buffer.size());
std::vector<char> mmf_buffer(mmf_buffer_size);
mmf_buffer_size = DeflateData(rm_buffer.data(), rm_buffer.size(), mmf_buffer.data(), mmf_buffer.size());
if (!mmf_buffer_size) {
Log.Out(Logs::General, Logs::Zone_Server, "Failed to save Map MMF file: '%s' - null MMF buffer size", mmf_file_name.c_str());
return false;
}
f = fopen(mmf_file_name.c_str(), "wb");
if (!f) {
Log.Out(Logs::General, Logs::Zone_Server, "Failed to save Map MMF file: '%s' - could not open file", mmf_file_name.c_str());
return false;
}
uint32 file_version = 0;
if (fwrite(&file_version, sizeof(uint32), 1, f) != 1) {
fclose(f);
std::remove(mmf_file_name.c_str());
Log.Out(Logs::General, Logs::Zone_Server, "Failed to save Map MMF file: '%s' - f@file_version", mmf_file_name.c_str());
return false;
}
if (fwrite(&rm_buffer_size, sizeof(uint32), 1, f) != 1) {
fclose(f);
std::remove(mmf_file_name.c_str());
Log.Out(Logs::General, Logs::Zone_Server, "Failed to save Map MMF file: '%s' - f@rm_buffer_size", mmf_file_name.c_str());
return false;
}
uint32 rm_buffer_crc32 = 0;
if (fwrite(&rm_buffer_crc32, sizeof(uint32), 1, f) != 1) {
fclose(f);
std::remove(mmf_file_name.c_str());
Log.Out(Logs::General, Logs::Zone_Server, "Failed to save Map MMF file: '%s' - f@rm_buffer_crc32", mmf_file_name.c_str());
return false;
}
if (fwrite(&mmf_buffer_size, sizeof(uint32), 1, f) != 1) {
fclose(f);
std::remove(mmf_file_name.c_str());
Log.Out(Logs::General, Logs::Zone_Server, "Failed to save Map MMF file: '%s' - f@mmf_buffer_size", mmf_file_name.c_str());
return false;
}
if (fwrite(mmf_buffer.data(), mmf_buffer_size, 1, f) != 1) {
fclose(f);
std::remove(mmf_file_name.c_str());
Log.Out(Logs::General, Logs::Zone_Server, "Failed to save Map MMF file: '%s' - f@mmf_buffer", mmf_file_name.c_str());
return false;
}
fclose(f);
return true;
}
#endif /*USE_MAP_MMFS*/

View File

@ -42,7 +42,13 @@ public:
bool LineIntersectsZone(glm::vec3 start, glm::vec3 end, float step, glm::vec3 *result) const;
bool LineIntersectsZoneNoZLeaps(glm::vec3 start, glm::vec3 end, float step_mag, glm::vec3 *result) const;
bool CheckLoS(glm::vec3 myloc, glm::vec3 oloc) const;
#ifdef USE_MAP_MMFS
bool Load(std::string filename, bool force_mmf_overwrite = false);
#else
bool Load(std::string filename);
#endif
static Map *LoadMapFile(std::string file);
private:
void RotateVertex(glm::vec3 &v, float rx, float ry, float rz);
@ -51,6 +57,11 @@ private:
bool LoadV1(FILE *f);
bool LoadV2(FILE *f);
#ifdef USE_MAP_MMFS
bool LoadMMF(const std::string& map_file_name, bool force_mmf_overwrite);
bool SaveMMF(const std::string& map_file_name, bool force_mmf_overwrite);
#endif /*USE_MAP_MMFS*/
struct impl;
impl *imp;
};

View File

@ -116,6 +116,27 @@ int main(int argc, char** argv) {
Log.LoadLogSettingsDefaults();
set_exception_handler();
#ifdef USE_MAP_MMFS
if (argc == 3 && strcasecmp(argv[1], "convert_map") == 0) {
if (!ZoneConfig::LoadConfig())
return 1;
Config = ZoneConfig::get();
std::string mapfile = argv[2];
std::transform(mapfile.begin(), mapfile.end(), mapfile.begin(), ::tolower);
std::string filename = Config->MapDir;
filename += mapfile;
auto m = new Map();
auto success = m->Load(filename, true);
delete m;
std::cout << mapfile.c_str() << " conversion " << (success ? "succeeded" : "failed") << std::endl;
return 0;
}
#endif /*USE_MAP_MMFS*/
QServ = new QueryServ;
Log.Out(Logs::General, Logs::Zone_Server, "Loading server configuration..");

View File

@ -914,6 +914,11 @@ public:
RmUint32 mMaxNodeCount;
NodeAABB *mNodes;
TriVector mLeafTriangles;
#ifdef USE_MAP_MMFS
MyRaycastMesh(std::vector<char>& rm_buffer);
void serialize(std::vector<char>& rm_buffer);
#endif /*USE_MAP_MMFS*/
};
};
@ -936,4 +941,253 @@ RaycastMesh * createRaycastMesh(RmUint32 vcount, // The number of vertices in t
return static_cast< RaycastMesh * >(m);
}
#ifdef USE_MAP_MMFS
RaycastMesh* loadRaycastMesh(std::vector<char>& rm_buffer, bool& load_success)
{
if (rm_buffer.empty())
return nullptr;
auto m = new MyRaycastMesh(rm_buffer);
load_success = (m->mNodes != nullptr);
return static_cast<RaycastMesh*>(m);
}
void serializeRaycastMesh(RaycastMesh* rm, std::vector<char>& rm_buffer)
{
if (!rm) {
rm_buffer.clear();
return;
}
static_cast<MyRaycastMesh*>(rm)->serialize(rm_buffer);
}
MyRaycastMesh::MyRaycastMesh(std::vector<char>& rm_buffer)
{
mVcount = 0;
mVertices = nullptr;
mTcount = 0;
mIndices = nullptr;
mRaycastTriangles = nullptr;
mFaceNormals = nullptr;
mRaycastFrame = 0;
mMaxNodeCount = 0;
mNodeCount = 0;
mNodes = nullptr;
mRoot = nullptr;
size_t chunk_size = 0;
size_t bytes_read = 0;
size_t rm_buffer_size_ = rm_buffer.size();
if (!rm_buffer_size_)
return;
char* buf = rm_buffer.data();
chunk_size = sizeof(RmUint32);
memcpy(&mVcount, buf, chunk_size);
buf += chunk_size;
bytes_read += chunk_size;
chunk_size = (sizeof(RmReal) * (3 * mVcount));
mVertices = (RmReal *)::malloc(chunk_size);
memcpy(mVertices, buf, chunk_size);
buf += chunk_size;
bytes_read += chunk_size;
chunk_size = sizeof(RmUint32);
memcpy(&mTcount, buf, chunk_size);
buf += chunk_size;
bytes_read += chunk_size;
chunk_size = (sizeof(RmUint32) * (3 * mTcount));
mIndices = (RmUint32 *)::malloc(chunk_size);
memcpy(mIndices, buf, chunk_size);
buf += chunk_size;
bytes_read += chunk_size;
chunk_size = (sizeof(RmUint32) * mTcount);
mRaycastTriangles = (RmUint32 *)::malloc(chunk_size);
memcpy(mRaycastTriangles, buf, chunk_size);
buf += chunk_size;
bytes_read += chunk_size;
chunk_size = (sizeof(RmReal) * (3 * mTcount));
mFaceNormals = (RmReal *)::malloc(chunk_size);
memcpy(mFaceNormals, buf, chunk_size);
buf += chunk_size;
bytes_read += chunk_size;
chunk_size = sizeof(RmUint32);
memcpy(&mRaycastFrame, buf, chunk_size);
buf += chunk_size;
bytes_read += chunk_size;
RmUint32 lt_size;
chunk_size = sizeof(RmUint32);
memcpy(&lt_size, buf, chunk_size);
buf += chunk_size;
bytes_read += chunk_size;
if (lt_size) {
mLeafTriangles.resize(lt_size);
chunk_size = (sizeof(RmUint32) * lt_size);
memcpy(&mLeafTriangles[0], buf, chunk_size);
buf += chunk_size;
bytes_read += chunk_size;
}
chunk_size = sizeof(RmUint32);
memcpy(&mNodeCount, buf, chunk_size);
buf += chunk_size;
bytes_read += chunk_size;
mMaxNodeCount = mNodeCount;
mNodes = new NodeAABB[mMaxNodeCount];
mRoot = &mNodes[0];
for (int index = 0; index < mNodeCount; ++index) {
chunk_size = (sizeof(RmReal) * 3);
memcpy(&mNodes[index].mBounds.mMin, buf, chunk_size);
buf += chunk_size;
bytes_read += chunk_size;
chunk_size = (sizeof(RmReal) * 3);
memcpy(&mNodes[index].mBounds.mMax, buf, chunk_size);
buf += chunk_size;
bytes_read += chunk_size;
chunk_size = sizeof(RmUint32);
memcpy(&mNodes[index].mLeafTriangleIndex, buf, chunk_size);
buf += chunk_size;
bytes_read += chunk_size;
RmUint32 lNodeIndex;
chunk_size = sizeof(RmUint32);
memcpy(&lNodeIndex, buf, chunk_size);
if (lNodeIndex != TRI_EOF)
mNodes[index].mLeft = &mNodes[lNodeIndex];
buf += chunk_size;
bytes_read += chunk_size;
RmUint32 rNodeIndex;
chunk_size = sizeof(RmUint32);
memcpy(&rNodeIndex, buf, chunk_size);
if (rNodeIndex != TRI_EOF)
mNodes[index].mRight = &mNodes[rNodeIndex];
buf += chunk_size;
bytes_read += chunk_size;
}
if (bytes_read != rm_buffer_size_) {
delete[] mNodes;
::free(mVertices);
::free(mIndices);
::free(mFaceNormals);
::free(mRaycastTriangles);
mVcount = 0;
mVertices = nullptr;
mTcount = 0;
mIndices = nullptr;
mRaycastTriangles = nullptr;
mFaceNormals = nullptr;
mRaycastFrame = 0;
mLeafTriangles.clear();
mMaxNodeCount = 0;
mNodeCount = 0;
mNodes = nullptr;
mRoot = nullptr;
}
}
void MyRaycastMesh::serialize(std::vector<char>& rm_buffer)
{
rm_buffer.clear();
size_t rm_buffer_size_ = 0;
rm_buffer_size_ += sizeof(RmUint32); // mVcount
rm_buffer_size_ += (sizeof(RmReal) * (3 * mVcount)); // mVertices
rm_buffer_size_ += sizeof(RmUint32); // mTcount
rm_buffer_size_ += (sizeof(RmUint32) * (3 * mTcount)); // mIndices
rm_buffer_size_ += (sizeof(RmUint32) * mTcount); // mRaycastTriangles
rm_buffer_size_ += (sizeof(RmReal) * (3 * mTcount)); // mFaceNormals
rm_buffer_size_ += sizeof(RmUint32); // mRaycastFrame
rm_buffer_size_ += sizeof(RmUint32); // mLeafTriangles.size()
rm_buffer_size_ += (sizeof(RmUint32) * (RmUint32)mLeafTriangles.size()); // mLeafTriangles
rm_buffer_size_ += sizeof(RmUint32); // mNodeCount
rm_buffer_size_ += (sizeof(RmReal) * (3 * mNodeCount)); // mNodes.mBounds.mMin
rm_buffer_size_ += (sizeof(RmReal) * (3 * mNodeCount)); // mNodes.mBounds.mMax
rm_buffer_size_ += (sizeof(RmUint32) * mNodeCount); // mNodes.mLeafTriangleIndex
rm_buffer_size_ += (sizeof(RmUint32) * mNodeCount); // mNodes.mLeft[Index]
rm_buffer_size_ += (sizeof(RmUint32) * mNodeCount); // mNodes.mRight[Index]
rm_buffer.resize(rm_buffer_size_);
char* buf = rm_buffer.data();
memcpy(buf, &mVcount, sizeof(RmUint32));
buf += sizeof(RmUint32);
memcpy(buf, mVertices, (sizeof(RmReal) * (3 * mVcount)));
buf += (sizeof(RmReal) * (3 * mVcount));
memcpy(buf, &mTcount, sizeof(RmUint32));
buf += sizeof(RmUint32);
memcpy(buf, mIndices, (sizeof(RmUint32) * (3 * mTcount)));
buf += (sizeof(RmUint32) * (3 * mTcount));
memcpy(buf, mRaycastTriangles, (sizeof(RmUint32) * mTcount));
buf += (sizeof(RmUint32) * mTcount);
if (!mFaceNormals) {
RmReal save_face[3];
getFaceNormal(0, &save_face[0]);
}
memcpy(buf, mFaceNormals, (sizeof(RmReal) * (3 * mTcount)));
buf += (sizeof(RmReal) * (3 * mTcount));
memcpy(buf, &mRaycastFrame, sizeof(RmUint32));
buf += sizeof(RmUint32);
RmUint32 lt_size = (RmUint32)mLeafTriangles.size();
memcpy(buf, &lt_size, sizeof(RmUint32));
buf += sizeof(RmUint32);
if (lt_size) {
memcpy(buf, &mLeafTriangles[0], (sizeof(RmUint32) * lt_size));
buf += (sizeof(RmUint32) * lt_size);
}
memcpy(buf, &mNodeCount, sizeof(RmUint32));
buf += sizeof(RmUint32);
for (RmUint32 index = 0; index < mNodeCount; ++index) {
memcpy(buf, &mNodes[index].mBounds.mMin, (sizeof(RmReal) * 3));
buf += (sizeof(RmReal) * 3);
memcpy(buf, &mNodes[index].mBounds.mMax, (sizeof(RmReal) * 3));
buf += (sizeof(RmReal) * 3);
memcpy(buf, &mNodes[index].mLeafTriangleIndex, sizeof(RmUint32));
buf += sizeof(RmUint32);
RmUint32 lNodeIndex = TRI_EOF;
if (mNodes[index].mLeft)
lNodeIndex = ((RmUint32)mNodes[index].mLeft - (RmUint32)mNodes) / sizeof(NodeAABB);
memcpy(buf, &lNodeIndex, sizeof(RmUint32));
buf += sizeof(RmUint32);
RmUint32 rNodeIndex = TRI_EOF;
if (mNodes[index].mRight)
rNodeIndex = ((RmUint32)mNodes[index].mRight - (RmUint32)mNodes) / sizeof(NodeAABB);
memcpy(buf, &rNodeIndex, sizeof(RmUint32));
buf += sizeof(RmUint32);
}
}
#endif /*USE_MAP_MMFS*/

View File

@ -56,5 +56,11 @@ RaycastMesh * createRaycastMesh(RmUint32 vcount, // The number of vertices in t
RmReal minAxisSize=0.01f // once a particular axis is less than this size, stop sub-dividing.
);
#ifdef USE_MAP_MMFS
#include <vector>
RaycastMesh* loadRaycastMesh(std::vector<char>& rm_buffer, bool& load_success);
void serializeRaycastMesh(RaycastMesh* rm, std::vector<char>& rm_buffer);
#endif /*USE_MAP_MMFS*/
#endif