320
321
for (int i = 0; i < header.numTiles; ++i)
322
323
NavMeshTileHeader tileHeader;
323
fread(&tileHeader, sizeof(tileHeader), 1, fp);
324
readLen = fread(&tileHeader, sizeof(tileHeader), 1, fp);
324
328
if (!tileHeader.tileRef || !tileHeader.dataSize)
327
331
unsigned char* data = (unsigned char*)dtAlloc(tileHeader.dataSize, DT_ALLOC_PERM);
328
332
if (!data) break;
329
333
memset(data, 0, tileHeader.dataSize);
330
fread(data, tileHeader.dataSize, 1, fp);
334
readLen = fread(data, tileHeader.dataSize, 1, fp);
332
338
mesh->addTile(data, tileHeader.dataSize, DT_TILE_FREE_DATA, tileHeader.tileRef, 0);
936
937
m_cfg.detailSampleDist = m_detailSampleDist < 0.9f ? 0 : m_cellSize * m_detailSampleDist;
937
938
m_cfg.detailSampleMaxError = m_cellHeight * m_detailSampleMaxError;
940
// Expand the heighfield bounding box by border size to find the extents of geometry we need to build this tile.
942
// This is done in order to make sure that the navmesh tiles connect correctly at the borders,
943
// and the obstacles close to the border work correctly with the dilation process.
944
// No polygons (or contours) will be created on the border area.
951
// : | |<--- tile to build
953
// : +-----+ :<-- geometry needed
956
// You should use this bounding box to query your input geometry.
958
// For example if you build a navmesh for terrain, and want the navmesh tiles to match the terrain tile size
959
// you will need to pass in data from neighbour terrain tiles too! In a simple case, just pass in all the 8 neighbours,
960
// or use the bounding box below to only pass in a sliver of each of the 8 neighbours.
939
961
rcVcopy(m_cfg.bmin, bmin);
940
962
rcVcopy(m_cfg.bmax, bmax);
941
963
m_cfg.bmin[0] -= m_cfg.borderSize*m_cfg.cs;
1049
1071
for (int i = 0; i < m_geom->getConvexVolumeCount(); ++i)
1050
1072
rcMarkConvexPolyArea(m_ctx, vols[i].verts, vols[i].nverts, vols[i].hmin, vols[i].hmax, (unsigned char)vols[i].area, *m_chf);
1052
if (m_monotonePartitioning)
1054
// Partition the walkable surface into simple regions without holes.
1055
if (!rcBuildRegionsMonotone(m_ctx, *m_chf, m_cfg.borderSize, m_cfg.minRegionArea, m_cfg.mergeRegionArea))
1057
m_ctx->log(RC_LOG_ERROR, "buildNavigation: Could not build regions.");
1075
// Partition the heightfield so that we can use simple algorithm later to triangulate the walkable areas.
1076
// There are 3 martitioning methods, each with some pros and cons:
1077
// 1) Watershed partitioning
1078
// - the classic Recast partitioning
1079
// - creates the nicest tessellation
1080
// - usually slowest
1081
// - partitions the heightfield into nice regions without holes or overlaps
1082
// - the are some corner cases where this method creates produces holes and overlaps
1083
// - holes may appear when a small obstacles is close to large open area (triangulation can handle this)
1084
// - overlaps may occur if you have narrow spiral corridors (i.e stairs), this make triangulation to fail
1085
// * generally the best choice if you precompute the nacmesh, use this if you have large open areas
1086
// 2) Monotone partioning
1088
// - partitions the heightfield into regions without holes and overlaps (guaranteed)
1089
// - creates long thin polygons, which sometimes causes paths with detours
1090
// * use this if you want fast navmesh generation
1091
// 3) Layer partitoining
1093
// - partitions the heighfield into non-overlapping regions
1094
// - relies on the triangulation code to cope with holes (thus slower than monotone partitioning)
1095
// - produces better triangles than monotone partitioning
1096
// - does not have the corner cases of watershed partitioning
1097
// - can be slow and create a bit ugly tessellation (still better than monotone)
1098
// if you have large open areas with small obstacles (not a problem if you use tiles)
1099
// * good choice to use for tiled navmesh with medium and small sized tiles
1101
if (m_partitionType == SAMPLE_PARTITION_WATERSHED)
1063
1103
// Prepare for region partitioning, by calculating distance field along the walkable surface.
1064
1104
if (!rcBuildDistanceField(m_ctx, *m_chf))
1066
1106
m_ctx->log(RC_LOG_ERROR, "buildNavigation: Could not build distance field.");
1070
1110
// Partition the walkable surface into simple regions without holes.
1071
1111
if (!rcBuildRegions(m_ctx, *m_chf, m_cfg.borderSize, m_cfg.minRegionArea, m_cfg.mergeRegionArea))
1073
m_ctx->log(RC_LOG_ERROR, "buildNavigation: Could not build regions.");
1113
m_ctx->log(RC_LOG_ERROR, "buildNavigation: Could not build watershed regions.");
1117
else if (m_partitionType == SAMPLE_PARTITION_MONOTONE)
1119
// Partition the walkable surface into simple regions without holes.
1120
// Monotone partitioning does not need distancefield.
1121
if (!rcBuildRegionsMonotone(m_ctx, *m_chf, m_cfg.borderSize, m_cfg.minRegionArea, m_cfg.mergeRegionArea))
1123
m_ctx->log(RC_LOG_ERROR, "buildNavigation: Could not build monotone regions.");
1127
else // SAMPLE_PARTITION_LAYERS
1129
// Partition the walkable surface into simple regions without holes.
1130
if (!rcBuildLayerRegions(m_ctx, *m_chf, m_cfg.borderSize, m_cfg.minRegionArea))
1132
m_ctx->log(RC_LOG_ERROR, "buildNavigation: Could not build layer regions.");
1078
1137
// Create contours.
1079
1138
m_cset = rcAllocContourSet();