bool dtNavMeshHeaderSwapEndian(unsigned char* data, const int /*dataSize*/) { dtMeshHeader* header = (dtMeshHeader*)data; int swappedMagic = DT_NAVMESH_MAGIC; int swappedVersion = DT_NAVMESH_VERSION; dtSwapEndian(&swappedMagic); dtSwapEndian(&swappedVersion); if ((header->magic != DT_NAVMESH_MAGIC || header->version != DT_NAVMESH_VERSION) && (header->magic != swappedMagic || header->version != swappedVersion)) { return false; } dtSwapEndian(&header->magic); dtSwapEndian(&header->version); dtSwapEndian(&header->x); dtSwapEndian(&header->y); dtSwapEndian(&header->layer); dtSwapEndian(&header->userId); dtSwapEndian(&header->polyCount); dtSwapEndian(&header->vertCount); dtSwapEndian(&header->maxLinkCount); dtSwapEndian(&header->detailMeshCount); dtSwapEndian(&header->detailVertCount); dtSwapEndian(&header->detailTriCount); dtSwapEndian(&header->bvNodeCount); dtSwapEndian(&header->offMeshConCount); dtSwapEndian(&header->offMeshBase); dtSwapEndian(&header->walkableHeight); dtSwapEndian(&header->walkableRadius); dtSwapEndian(&header->walkableClimb); dtSwapEndian(&header->bmin[0]); dtSwapEndian(&header->bmin[1]); dtSwapEndian(&header->bmin[2]); dtSwapEndian(&header->bmax[0]); dtSwapEndian(&header->bmax[1]); dtSwapEndian(&header->bmax[2]); dtSwapEndian(&header->bvQuantFactor); // Freelist index and pointers are updated when tile is added, no need to swap. return true; }
/// @par /// /// @warning This function assumes that the header is in the correct endianess already. /// Call #dtNavMeshHeaderSwapEndian() first on the data if the data is expected to be in wrong endianess /// to start with. Call #dtNavMeshHeaderSwapEndian() after the data has been swapped if converting from /// native to foreign endianess. bool dtNavMeshDataSwapEndian(unsigned char* data, const int /*dataSize*/) { // Make sure the data is in right format. dtMeshHeader* header = (dtMeshHeader*)data; if (header->magic != DT_NAVMESH_MAGIC) return false; if (header->version != DT_NAVMESH_VERSION) return false; // Patch header pointers. const int headerSize = dtAlign4(sizeof(dtMeshHeader)); const int vertsSize = dtAlign4(sizeof(float)*3*header->vertCount); const int polysSize = dtAlign4(sizeof(dtPoly)*header->polyCount); const int linksSize = dtAlign4(sizeof(dtLink)*(header->maxLinkCount)); const int detailMeshesSize = dtAlign4(sizeof(dtPolyDetail)*header->detailMeshCount); const int detailVertsSize = dtAlign4(sizeof(float)*3*header->detailVertCount); const int detailTrisSize = dtAlign4(sizeof(unsigned char)*4*header->detailTriCount); const int bvtreeSize = dtAlign4(sizeof(dtBVNode)*header->bvNodeCount); const int offMeshLinksSize = dtAlign4(sizeof(dtOffMeshConnection)*header->offMeshConCount); unsigned char* d = data + headerSize; float* verts = (float*)d; d += vertsSize; dtPoly* polys = (dtPoly*)d; d += polysSize; /*dtLink* links = (dtLink*)d;*/ d += linksSize; dtPolyDetail* detailMeshes = (dtPolyDetail*)d; d += detailMeshesSize; float* detailVerts = (float*)d; d += detailVertsSize; /*unsigned char* detailTris = (unsigned char*)d;*/ d += detailTrisSize; dtBVNode* bvTree = (dtBVNode*)d; d += bvtreeSize; dtOffMeshConnection* offMeshCons = (dtOffMeshConnection*)d; d += offMeshLinksSize; // Vertices for (int i = 0; i < header->vertCount*3; ++i) { dtSwapEndian(&verts[i]); } // Polys for (int i = 0; i < header->polyCount; ++i) { dtPoly* p = &polys[i]; // poly->firstLink is update when tile is added, no need to swap. for (int j = 0; j < DT_VERTS_PER_POLYGON; ++j) { dtSwapEndian(&p->verts[j]); dtSwapEndian(&p->neis[j]); } dtSwapEndian(&p->flags); } // Links are rebuild when tile is added, no need to swap. // Detail meshes for (int i = 0; i < header->detailMeshCount; ++i) { dtPolyDetail* pd = &detailMeshes[i]; dtSwapEndian(&pd->vertBase); dtSwapEndian(&pd->triBase); } // Detail verts for (int i = 0; i < header->detailVertCount*3; ++i) { dtSwapEndian(&detailVerts[i]); } // BV-tree for (int i = 0; i < header->bvNodeCount; ++i) { dtBVNode* node = &bvTree[i]; for (int j = 0; j < 3; ++j) { dtSwapEndian(&node->bmin[j]); dtSwapEndian(&node->bmax[j]); } dtSwapEndian(&node->i); } // Off-mesh Connections. for (int i = 0; i < header->offMeshConCount; ++i) { dtOffMeshConnection* con = &offMeshCons[i]; for (int j = 0; j < 6; ++j) dtSwapEndian(&con->pos[j]); dtSwapEndian(&con->rad); dtSwapEndian(&con->poly); } return true; }
/// @par /// /// @warning This function assumes that the header is in the correct endianess already. /// Call #dtNavMeshHeaderSwapEndian() first on the data if the data is expected to be in wrong endianess /// to start with. Call #dtNavMeshHeaderSwapEndian() after the data has been swapped if converting from /// native to foreign endianess. bool dtNavMeshDataSwapEndian(unsigned char* data, const int /*dataSize*/) { // Make sure the data is in right format. dtMeshHeader* header = (dtMeshHeader*)data; if (header->magic != DT_NAVMESH_MAGIC) return false; if (header->version != DT_NAVMESH_VERSION) return false; // Patch header pointers. const int headerSize = dtAlign4(sizeof(dtMeshHeader)); const int vertsSize = dtAlign4(sizeof(float)*3*header->vertCount); const int polysSize = dtAlign4(sizeof(dtPoly)*header->polyCount); const int linksSize = dtAlign4(sizeof(dtLink)*(header->maxLinkCount)); const int detailMeshesSize = dtAlign4(sizeof(dtPolyDetail)*header->detailMeshCount); const int detailVertsSize = dtAlign4(sizeof(float)*3*header->detailVertCount); const int detailTrisSize = dtAlign4(sizeof(unsigned char)*4*header->detailTriCount); const int bvtreeSize = dtAlign4(sizeof(dtBVNode)*header->bvNodeCount); const int offMeshLinksSize = dtAlign4(sizeof(dtOffMeshConnection)*header->offMeshConCount); unsigned char* d = data + headerSize; float* verts = dtGetThenAdvanceBufferPointer<float>(d, vertsSize); dtPoly* polys = dtGetThenAdvanceBufferPointer<dtPoly>(d, polysSize); d += linksSize; // Ignore links; they technically should be endian-swapped but all their data is overwritten on load anyway. //dtLink* links = dtGetThenAdvanceBufferPointer<dtLink>(d, linksSize); dtPolyDetail* detailMeshes = dtGetThenAdvanceBufferPointer<dtPolyDetail>(d, detailMeshesSize); float* detailVerts = dtGetThenAdvanceBufferPointer<float>(d, detailVertsSize); d += detailTrisSize; // Ignore detail tris; single bytes can't be endian-swapped. //unsigned char* detailTris = dtGetThenAdvanceBufferPointer<unsigned char>(d, detailTrisSize); dtBVNode* bvTree = dtGetThenAdvanceBufferPointer<dtBVNode>(d, bvtreeSize); dtOffMeshConnection* offMeshCons = dtGetThenAdvanceBufferPointer<dtOffMeshConnection>(d, offMeshLinksSize); // Vertices for (int i = 0; i < header->vertCount*3; ++i) { dtSwapEndian(&verts[i]); } // Polys for (int i = 0; i < header->polyCount; ++i) { dtPoly* p = &polys[i]; // poly->firstLink is update when tile is added, no need to swap. for (int j = 0; j < DT_VERTS_PER_POLYGON; ++j) { dtSwapEndian(&p->verts[j]); dtSwapEndian(&p->neis[j]); } dtSwapEndian(&p->flags); } // Links are rebuild when tile is added, no need to swap. // Detail meshes for (int i = 0; i < header->detailMeshCount; ++i) { dtPolyDetail* pd = &detailMeshes[i]; dtSwapEndian(&pd->vertBase); dtSwapEndian(&pd->triBase); } // Detail verts for (int i = 0; i < header->detailVertCount*3; ++i) { dtSwapEndian(&detailVerts[i]); } // BV-tree for (int i = 0; i < header->bvNodeCount; ++i) { dtBVNode* node = &bvTree[i]; for (int j = 0; j < 3; ++j) { dtSwapEndian(&node->bmin[j]); dtSwapEndian(&node->bmax[j]); } dtSwapEndian(&node->i); } // Off-mesh Connections. for (int i = 0; i < header->offMeshConCount; ++i) { dtOffMeshConnection* con = &offMeshCons[i]; for (int j = 0; j < 6; ++j) dtSwapEndian(&con->pos[j]); dtSwapEndian(&con->rad); dtSwapEndian(&con->poly); } return true; }