127 std::ranges::copy(meshData.
liquidVerts, allVerts.begin());
131 float bmin[3], bmax[3];
132 getTileBounds(tileX, tileY, allVerts.data(), allVerts.size() / 3, bmin, bmax);
147 MeshData& meshData,
float (&bmin)[3],
float (&bmax)[3],
148 dtNavMeshParams
const* navMeshParams, std::string_view fileNameSuffix)
152 TC_LOG_INFO(
"maps.mmapgen",
"{} Building movemap tile...", tileString);
159 int tVertCount = meshData.
solidVerts.size() / 3;
161 int tTriCount = meshData.
solidTris.size() / 3;
166 int lTriCount = meshData.
liquidTris.size() / 3;
175 rcCalcGridSize(config.bmin, config.bmax, config.cs, &config.width, &config.height);
178 std::unique_ptr<Tile[]> tiles = std::make_unique<Tile[]>(TILES_PER_MAP * TILES_PER_MAP);
181 rcConfig tileCfg = config;
182 tileCfg.width = config.tileSize + config.borderSize * 2;
183 tileCfg.height = config.tileSize + config.borderSize * 2;
186 std::unique_ptr<rcPolyMesh*[]> pmmerge = std::make_unique<rcPolyMesh*[]>(TILES_PER_MAP * TILES_PER_MAP);
187 std::unique_ptr<rcPolyMeshDetail*[]> dmmerge = std::make_unique<rcPolyMeshDetail*[]>(TILES_PER_MAP * TILES_PER_MAP);
190 for (
int y = 0; y < TILES_PER_MAP; ++y)
192 for (
int x = 0; x < TILES_PER_MAP; ++x)
194 Tile& tile = tiles[x + y * TILES_PER_MAP];
197 tileCfg.bmin[0] = config.bmin[0] + x * float(config.tileSize * config.cs);
198 tileCfg.bmin[2] = config.bmin[2] + y * float(config.tileSize * config.cs);
199 tileCfg.bmax[0] = config.bmin[0] + (x + 1) *
float(config.tileSize * config.cs);
200 tileCfg.bmax[2] = config.bmin[2] + (y + 1) *
float(config.tileSize * config.cs);
202 tileCfg.bmin[0] -= tileCfg.borderSize * tileCfg.cs;
203 tileCfg.bmin[2] -= tileCfg.borderSize * tileCfg.cs;
204 tileCfg.bmax[0] += tileCfg.borderSize * tileCfg.cs;
205 tileCfg.bmax[2] += tileCfg.borderSize * tileCfg.cs;
208 tile.solid = rcAllocHeightfield();
209 if (!tile.solid || !rcCreateHeightfield(&
m_rcContext, *tile.solid, tileCfg.width, tileCfg.height, tileCfg.bmin, tileCfg.bmax, tileCfg.cs, tileCfg.ch))
211 TC_LOG_ERROR(
"maps.mmapgen",
"{} Failed building heightfield!", tileString);
223 std::unique_ptr<unsigned char[]> triFlags = std::make_unique<unsigned char[]>(tTriCount);
225 rcClearUnwalkableTriangles(&
m_rcContext, tileCfg.walkableSlopeAngle, tVerts, tVertCount, tTris, tTriCount, triFlags.get());
226 rcMarkWalkableTriangles(&
m_rcContext, tileCfg.walkableSlopeAngleNotSteep, tVerts, tVertCount, tTris, tTriCount, triFlags.get(),
NAV_AREA_GROUND);
227 rcRasterizeTriangles(&
m_rcContext, tVerts, tVertCount, tTris, triFlags.get(), tTriCount, *tile.solid, config.walkableClimb);
229 rcFilterLowHangingWalkableObstacles(&
m_rcContext, config.walkableClimb, *tile.solid);
230 rcFilterLedgeSpans(&
m_rcContext, tileCfg.walkableHeight, tileCfg.walkableClimb, *tile.solid);
231 rcFilterWalkableLowHeightSpans(&
m_rcContext, tileCfg.walkableHeight, *tile.solid);
234 rcRasterizeTriangles(&
m_rcContext, lVerts, lVertCount, lTris, lTriFlags, lTriCount, *tile.solid, config.walkableClimb);
237 tile.chf = rcAllocCompactHeightfield();
238 if (!tile.chf || !rcBuildCompactHeightfield(&
m_rcContext, tileCfg.walkableHeight, tileCfg.walkableClimb, *tile.solid, *tile.chf))
240 TC_LOG_ERROR(
"maps.mmapgen",
"{} Failed compacting heightfield!", tileString);
245 if (!rcErodeWalkableArea(&
m_rcContext, config.walkableRadius, *tile.chf))
247 TC_LOG_ERROR(
"maps.mmapgen",
"{} Failed eroding area!", tileString);
251 if (!rcMedianFilterWalkableArea(&
m_rcContext, *tile.chf))
253 TC_LOG_ERROR(
"maps.mmapgen",
"{} Failed filtering area!", tileString);
257 if (!rcBuildDistanceField(&
m_rcContext, *tile.chf))
259 TC_LOG_ERROR(
"maps.mmapgen",
"{} Failed building distance field!", tileString);
263 if (!rcBuildRegions(&
m_rcContext, *tile.chf, tileCfg.borderSize, tileCfg.minRegionArea, tileCfg.mergeRegionArea))
265 TC_LOG_ERROR(
"maps.mmapgen",
"{} Failed building regions!", tileString);
269 tile.cset = rcAllocContourSet();
270 if (!tile.cset || !rcBuildContours(&
m_rcContext, *tile.chf, tileCfg.maxSimplificationError, tileCfg.maxEdgeLen, *tile.cset))
272 TC_LOG_ERROR(
"maps.mmapgen",
"{} Failed building contours!", tileString);
277 tile.pmesh = rcAllocPolyMesh();
278 if (!tile.pmesh || !rcBuildPolyMesh(&
m_rcContext, *tile.cset, tileCfg.maxVertsPerPoly, *tile.pmesh))
280 TC_LOG_ERROR(
"maps.mmapgen",
"{} Failed building polymesh!", tileString);
284 tile.dmesh = rcAllocPolyMeshDetail();
285 if (!tile.dmesh || !rcBuildPolyMeshDetail(&
m_rcContext, *tile.pmesh, *tile.chf, tileCfg.detailSampleDist, tileCfg.detailSampleMaxError, *tile.dmesh))
287 TC_LOG_ERROR(
"maps.mmapgen",
"{} Failed building polymesh detail!", tileString);
294 rcFreeHeightField(tile.solid);
295 tile.solid =
nullptr;
296 rcFreeCompactHeightfield(tile.chf);
298 rcFreeContourSet(tile.cset);
301 pmmerge[nmerge] = tile.pmesh;
302 dmmerge[nmerge] = tile.dmesh;
310 TC_LOG_ERROR(
"maps.mmapgen",
"{} alloc iv.polyMesh FAILED!", tileString);
318 TC_LOG_ERROR(
"maps.mmapgen",
"{} alloc m_dmesh FAILED!", tileString);
330 for (
int i = 0; i < iv.
polyMesh->npolys; ++i)
342 dtNavMeshCreateParams
params = {};
363 params.walkableHeight = BASE_UNIT_DIM * config.walkableHeight;
364 params.walkableRadius = BASE_UNIT_DIM * config.walkableRadius;
365 params.walkableClimb = BASE_UNIT_DIM * config.walkableClimb;
366 params.tileX = (((bmin[0] + bmax[0]) / 2) - navMeshParams->orig[0]) /
GRID_SIZE;
367 params.tileY = (((bmin[2] + bmax[2]) / 2) - navMeshParams->orig[2]) /
GRID_SIZE;
368 rcVcopy(
params.bmin, bmin);
369 rcVcopy(
params.bmax, bmax);
373 params.buildBvTree =
true;
376 unsigned char* navData =
nullptr;
379 [borderSize =
static_cast<unsigned short>(config.borderSize),
384 for (std::ptrdiff_t i = 0; i < intermediate->
polyMesh->nverts; ++i)
386 unsigned short* v = &intermediate->
polyMesh->verts[i * 3];
391 intermediate->
generateObjFile(*outputDir, fileNameSuffix, mapID, tileX, tileY, meshData);
392 intermediate->
writeIV(*outputDir, fileNameSuffix, mapID, tileX, tileY);
397 if (
params.nvp > DT_VERTS_PER_POLYGON)
399 TC_LOG_ERROR(
"maps.mmapgen",
"{} Invalid verts-per-polygon value!", tileString);
403 if (
params.vertCount >= 0xffff)
405 TC_LOG_ERROR(
"maps.mmapgen",
"{} Too many vertices!", tileString);
423 TC_LOG_ERROR(
"maps.mmapgen",
"{} No polygons to build on tile!", tileString);
429 TC_LOG_ERROR(
"maps.mmapgen",
"{} No detail mesh to build tile!", tileString);
433 TC_LOG_DEBUG(
"maps.mmapgen",
"{} Building navmesh tile...", tileString);
434 if (!dtCreateNavMeshData(&
params, &navData, &tileResult.
size))
436 TC_LOG_ERROR(
"maps.mmapgen",
"{} Failed building navmesh tile!", tileString);
440 tileResult.
data.reset(navData);