61 bool skipContinents,
bool skipJunkMaps,
bool skipBattlegrounds,
62 bool debugOutput,
bool bigBaseUnit,
int mapid,
char const* offMeshFilePath,
unsigned int threads) :
63 m_terrainBuilder (nullptr),
64 m_debugOutput (debugOutput),
65 m_offMeshFilePath (offMeshFilePath),
67 m_skipContinents (skipContinents),
68 m_skipJunkMaps (skipJunkMaps),
69 m_skipBattlegrounds (skipBattlegrounds),
70 m_skipLiquid (skipLiquid),
71 m_maxWalkableAngle (maxWalkableAngle),
72 m_maxWalkableAngleNotSteep (maxWalkableAngleNotSteep),
73 m_bigBaseUnit (bigBaseUnit),
76 m_totalTilesProcessed(0u),
77 m_rcContext (nullptr),
78 _cancelationToken (false)
115 std::vector<std::string> files;
116 uint32 mapID, tileX, tileY, tileID, count = 0;
118 printf(
"Discovering maps... ");
120 for (
uint32 i = 0; i < files.size(); ++i)
122 mapID =
uint32(atoi(files[i].substr(0,3).c_str()));
132 for (
uint32 i = 0; i < files.size(); ++i)
134 mapID =
uint32(atoi(files[i].substr(0,3).c_str()));
141 printf(
"found %u.\n", count);
144 printf(
"Discovering tiles... ");
145 for (TileList::iterator itr =
m_tiles.begin(); itr !=
m_tiles.end(); ++itr)
147 std::set<uint32>* tiles = (*itr).m_tiles;
148 mapID = (*itr).m_mapId;
152 for (
uint32 i = 0; i < files.size(); ++i)
154 tileX =
uint32(atoi(files[i].substr(7,2).c_str()));
155 tileY =
uint32(atoi(files[i].substr(4,2).c_str()));
158 tiles->insert(tileID);
164 for (
uint32 i = 0; i < files.size(); ++i)
166 tileY =
uint32(atoi(files[i].substr(3,2).c_str()));
167 tileX =
uint32(atoi(files[i].substr(5,2).c_str()));
170 if (tiles->insert(tileID).second)
178 uint32 minX, minY, maxX, maxY;
182 for (
uint32 i = minX; i <= maxX; ++i)
183 for (
uint32 j = minY; j <= maxY; ++j)
188 printf(
"found %u.\n\n", count);
191 for (TileList::iterator it =
m_tiles.begin(); it !=
m_tiles.end(); ++it)
530 int polyBits = DT_POLY_BITS;
532 int maxTiles = tiles->size();
533 int maxPolysPerTile = 1 << polyBits;
537 uint32 tileXMin = 64, tileYMin = 64, tileXMax = 0, tileYMax = 0, tileX, tileY;
538 for (std::set<uint32>::iterator it = tiles->begin(); it != tiles->end(); ++it)
542 if (tileX > tileXMax)
544 else if (tileX < tileXMin)
547 if (tileY > tileYMax)
549 else if (tileY < tileYMin)
554 float bmin[3], bmax[3];
560 dtNavMeshParams navMeshParams;
561 memset(&navMeshParams, 0,
sizeof(dtNavMeshParams));
564 rcVcopy(navMeshParams.orig, bmin);
565 navMeshParams.maxTiles = maxTiles;
566 navMeshParams.maxPolys = maxPolysPerTile;
568 navMesh = dtAllocNavMesh();
569 printf(
"[Map %03i] Creating navMesh...\n", mapID);
570 if (!navMesh->init(&navMeshParams))
572 printf(
"[Map %03i] Failed creating navmesh! \n", mapID);
578 FILE* file = fopen(fileName.c_str(),
"wb");
581 dtFreeNavMesh(navMesh);
582 perror(
Trinity::StringFormat(
"[Map {:03}] Failed to open {} for writing!\n", mapID, fileName).c_str());
587 fwrite(&navMeshParams,
sizeof(dtNavMeshParams), 1, file);
593 MeshData &meshData,
float bmin[3],
float bmax[3],
598 printf(
"%s Building movemap tiles...\n", tileString.c_str());
602 float* tVerts = meshData.
solidVerts.getCArray();
603 int tVertCount = meshData.
solidVerts.size() / 3;
604 int* tTris = meshData.
solidTris.getCArray();
605 int tTriCount = meshData.
solidTris.size() / 3;
610 int lTriCount = meshData.
liquidTris.size() / 3;
619 rcCalcGridSize(config.bmin, config.bmax, config.cs, &config.width, &config.height);
622 Tile* tiles =
new Tile[TILES_PER_MAP * TILES_PER_MAP];
625 rcConfig tileCfg = config;
626 tileCfg.width = config.tileSize + config.borderSize*2;
627 tileCfg.height = config.tileSize + config.borderSize*2;
630 rcPolyMesh** pmmerge =
new rcPolyMesh*[TILES_PER_MAP * TILES_PER_MAP];
631 rcPolyMeshDetail** dmmerge =
new rcPolyMeshDetail*[TILES_PER_MAP * TILES_PER_MAP];
634 for (
int y = 0; y < TILES_PER_MAP; ++y)
636 for (
int x = 0; x < TILES_PER_MAP; ++x)
638 Tile& tile = tiles[x + y * TILES_PER_MAP];
641 tileCfg.bmin[0] = config.bmin[0] + x * float(config.tileSize * config.cs);
642 tileCfg.bmin[2] = config.bmin[2] + y * float(config.tileSize * config.cs);
643 tileCfg.bmax[0] = config.bmin[0] + (x + 1) *
float(config.tileSize * config.cs);
644 tileCfg.bmax[2] = config.bmin[2] + (y + 1) *
float(config.tileSize * config.cs);
646 tileCfg.bmin[0] -= tileCfg.borderSize * tileCfg.cs;
647 tileCfg.bmin[2] -= tileCfg.borderSize * tileCfg.cs;
648 tileCfg.bmax[0] += tileCfg.borderSize * tileCfg.cs;
649 tileCfg.bmax[2] += tileCfg.borderSize * tileCfg.cs;
652 tile.
solid = rcAllocHeightfield();
653 if (!tile.
solid || !rcCreateHeightfield(
m_rcContext, *tile.
solid, tileCfg.width, tileCfg.height, tileCfg.bmin, tileCfg.bmax, tileCfg.cs, tileCfg.ch))
655 printf(
"%s Failed building heightfield! \n", tileString.c_str());
667 unsigned char* triFlags =
new unsigned char[tTriCount];
669 rcClearUnwalkableTriangles(
m_rcContext, tileCfg.walkableSlopeAngle, tVerts, tVertCount, tTris, tTriCount, triFlags);
670 rcMarkWalkableTriangles(
m_rcContext, tileCfg.walkableSlopeAngleNotSteep, tVerts, tVertCount, tTris, tTriCount, triFlags,
NAV_AREA_GROUND);
671 rcRasterizeTriangles(
m_rcContext, tVerts, tVertCount, tTris, triFlags, tTriCount, *tile.
solid, config.walkableClimb);
674 rcFilterLowHangingWalkableObstacles(
m_rcContext, config.walkableClimb, *tile.
solid);
675 rcFilterLedgeSpans(
m_rcContext, tileCfg.walkableHeight, tileCfg.walkableClimb, *tile.
solid);
676 rcFilterWalkableLowHeightSpans(
m_rcContext, tileCfg.walkableHeight, *tile.
solid);
679 rcRasterizeTriangles(
m_rcContext, lVerts, lVertCount, lTris, lTriFlags, lTriCount, *tile.
solid, config.walkableClimb);
682 tile.
chf = rcAllocCompactHeightfield();
683 if (!tile.
chf || !rcBuildCompactHeightfield(
m_rcContext, tileCfg.walkableHeight, tileCfg.walkableClimb, *tile.
solid, *tile.
chf))
685 printf(
"%s Failed compacting heightfield! \n", tileString.c_str());
690 if (!rcErodeWalkableArea(
m_rcContext, config.walkableRadius, *tile.
chf))
692 printf(
"%s Failed eroding area! \n", tileString.c_str());
698 printf(
"%s Failed filtering area! \n", tileString.c_str());
704 printf(
"%s Failed building distance field! \n", tileString.c_str());
708 if (!rcBuildRegions(
m_rcContext, *tile.
chf, tileCfg.borderSize, tileCfg.minRegionArea, tileCfg.mergeRegionArea))
710 printf(
"%s Failed building regions! \n", tileString.c_str());
714 tile.
cset = rcAllocContourSet();
715 if (!tile.
cset || !rcBuildContours(
m_rcContext, *tile.
chf, tileCfg.maxSimplificationError, tileCfg.maxEdgeLen, *tile.
cset))
717 printf(
"%s Failed building contours! \n", tileString.c_str());
722 tile.
pmesh = rcAllocPolyMesh();
725 printf(
"%s Failed building polymesh! \n", tileString.c_str());
729 tile.
dmesh = rcAllocPolyMeshDetail();
730 if (!tile.
dmesh || !rcBuildPolyMeshDetail(
m_rcContext, *tile.
pmesh, *tile.
chf, tileCfg.detailSampleDist, tileCfg.detailSampleMaxError, *tile.
dmesh))
732 printf(
"%s Failed building polymesh detail! \n", tileString.c_str());
739 rcFreeHeightField(tile.
solid);
740 tile.
solid =
nullptr;
741 rcFreeCompactHeightfield(tile.
chf);
743 rcFreeContourSet(tile.
cset);
746 pmmerge[nmerge] = tile.
pmesh;
747 dmmerge[nmerge] = tile.
dmesh;
755 printf(
"%s alloc iv.polyMesh FAILED!\n", tileString.c_str());
766 printf(
"%s alloc m_dmesh FAILED!\n", tileString.c_str());
781 for (
int i = 0; i < iv.
polyMesh->npolys; ++i)
793 dtNavMeshCreateParams
params;
815 params.walkableHeight = BASE_UNIT_DIM*config.walkableHeight;
816 params.walkableRadius = BASE_UNIT_DIM*config.walkableRadius;
817 params.walkableClimb = BASE_UNIT_DIM*config.walkableClimb;
818 params.tileX = (((bmin[0] + bmax[0]) / 2) - navMesh->getParams()->orig[0]) /
GRID_SIZE;
819 params.tileY = (((bmin[2] + bmax[2]) / 2) - navMesh->getParams()->orig[2]) /
GRID_SIZE;
820 rcVcopy(
params.bmin, bmin);
821 rcVcopy(
params.bmax, bmax);
825 params.buildBvTree =
true;
828 unsigned char* navData =
nullptr;
835 if (
params.nvp > DT_VERTS_PER_POLYGON)
837 printf(
"%s Invalid verts-per-polygon value! \n", tileString.c_str());
840 if (
params.vertCount >= 0xffff)
842 printf(
"%s Too many vertices! \n", tileString.c_str());
858 printf(
"%s No polygons to build on tile! \n", tileString.c_str());
863 printf(
"%s No detail mesh to build tile! \n", tileString.c_str());
867 printf(
"%s Building navmesh tile...\n", tileString.c_str());
868 if (!dtCreateNavMeshData(&
params, &navData, &navDataSize))
870 printf(
"%s Failed building navmesh tile! \n", tileString.c_str());
874 dtTileRef tileRef = 0;
875 printf(
"%s Adding tile to navmesh...\n", tileString.c_str());
878 dtStatus dtResult = navMesh->addTile(navData, navDataSize, DT_TILE_FREE_DATA, 0, &tileRef);
879 if (!tileRef || dtResult != DT_SUCCESS)
881 printf(
"%s Failed adding tile to navmesh! \n", tileString.c_str());
887 FILE* file = fopen(fileName.c_str(),
"wb");
890 perror(
Trinity::StringFormat(
"[Map {:03}] Failed to open {} for writing!\n", mapID, fileName).c_str());
891 navMesh->removeTile(tileRef,
nullptr,
nullptr);
895 printf(
"%s Writing to file...\n", tileString.c_str());
909 fwrite(navData,
sizeof(
unsigned char), navDataSize, file);
913 navMesh->removeTile(tileRef,
nullptr,
nullptr);
920 for (
int i = 0; i < iv.
polyMesh->nverts; ++i)
922 unsigned short* v = &iv.
polyMesh->verts[i*3];
923 v[0] += (
unsigned short)config.borderSize;
924 v[2] += (
unsigned short)config.borderSize;
928 iv.
writeIV(mapID, tileX, tileY);