|
|
|
@ -102,6 +102,77 @@ namespace
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void createHeightfield(rcContext& context, rcHeightfield& solid, int width, int height, const float* bmin,
|
|
|
|
|
const float* bmax, const float cs, const float ch)
|
|
|
|
|
{
|
|
|
|
|
const auto result = rcCreateHeightfield(&context, solid, width, height, bmin, bmax, cs, ch);
|
|
|
|
|
|
|
|
|
|
if (!result)
|
|
|
|
|
throw NavigatorException("Failed to create heightfield for navmesh");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void buildCompactHeightfield(rcContext& context, const int walkableHeight, const int walkableClimb,
|
|
|
|
|
rcHeightfield& solid, rcCompactHeightfield& compact)
|
|
|
|
|
{
|
|
|
|
|
const auto result = rcBuildCompactHeightfield(&context, walkableHeight,
|
|
|
|
|
walkableClimb, solid, compact);
|
|
|
|
|
|
|
|
|
|
if (!result)
|
|
|
|
|
throw NavigatorException("Failed to build compact heightfield for navmesh");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void erodeWalkableArea(rcContext& context, int walkableRadius, rcCompactHeightfield& compact)
|
|
|
|
|
{
|
|
|
|
|
const auto result = rcErodeWalkableArea(&context, walkableRadius, compact);
|
|
|
|
|
|
|
|
|
|
if (!result)
|
|
|
|
|
throw NavigatorException("Failed to erode walkable area for navmesh");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void buildDistanceField(rcContext& context, rcCompactHeightfield& compact)
|
|
|
|
|
{
|
|
|
|
|
const auto result = rcBuildDistanceField(&context, compact);
|
|
|
|
|
|
|
|
|
|
if (!result)
|
|
|
|
|
throw NavigatorException("Failed to build distance field for navmesh");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void buildRegions(rcContext& context, rcCompactHeightfield& compact, const int borderSize,
|
|
|
|
|
const int minRegionArea, const int mergeRegionArea)
|
|
|
|
|
{
|
|
|
|
|
const auto result = rcBuildRegions(&context, compact, borderSize, minRegionArea, mergeRegionArea);
|
|
|
|
|
|
|
|
|
|
if (!result)
|
|
|
|
|
throw NavigatorException("Failed to build distance field for navmesh");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void buildContours(rcContext& context, rcCompactHeightfield& compact, const float maxError, const int maxEdgeLen,
|
|
|
|
|
rcContourSet& contourSet, const int buildFlags = RC_CONTOUR_TESS_WALL_EDGES)
|
|
|
|
|
{
|
|
|
|
|
const auto result = rcBuildContours(&context, compact, maxError, maxEdgeLen, contourSet, buildFlags);
|
|
|
|
|
|
|
|
|
|
if (!result)
|
|
|
|
|
throw NavigatorException("Failed to build contours for navmesh");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void buildPolyMesh(rcContext& context, rcContourSet& contourSet, const int maxVertsPerPoly, rcPolyMesh& polyMesh)
|
|
|
|
|
{
|
|
|
|
|
const auto result = rcBuildPolyMesh(&context, contourSet, maxVertsPerPoly, polyMesh);
|
|
|
|
|
|
|
|
|
|
if (!result)
|
|
|
|
|
throw NavigatorException("Failed to build poly mesh for navmesh");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void buildPolyMeshDetail(rcContext& context, const rcPolyMesh& polyMesh, const rcCompactHeightfield& compact,
|
|
|
|
|
const float sampleDist, const float sampleMaxError, rcPolyMeshDetail& polyMeshDetail)
|
|
|
|
|
{
|
|
|
|
|
const auto result = rcBuildPolyMeshDetail(&context, polyMesh, compact, sampleDist, sampleMaxError,
|
|
|
|
|
polyMeshDetail);
|
|
|
|
|
|
|
|
|
|
if (!result)
|
|
|
|
|
throw NavigatorException("Failed to build detail poly mesh for navmesh");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NavMeshData makeNavMeshTileData(const osg::Vec3f& agentHalfExtents, const RecastMesh& recastMesh,
|
|
|
|
|
const std::vector<OffMeshConnection>& offMeshConnections, const int tileX, const int tileY,
|
|
|
|
|
const osg::Vec3f& boundsMin, const osg::Vec3f& boundsMax, const Settings& settings)
|
|
|
|
@ -133,8 +204,7 @@ namespace
|
|
|
|
|
config.bmax[2] += getBorderSize(settings);
|
|
|
|
|
|
|
|
|
|
rcHeightfield solid;
|
|
|
|
|
OPENMW_CHECK_DT_RESULT(rcCreateHeightfield(nullptr, solid, config.width, config.height,
|
|
|
|
|
config.bmin, config.bmax, config.cs, config.ch));
|
|
|
|
|
createHeightfield(context, solid, config.width, config.height, config.bmin, config.bmax, config.cs, config.ch);
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
const auto& chunkyMesh = recastMesh.getChunkyTriMesh();
|
|
|
|
@ -181,7 +251,7 @@ namespace
|
|
|
|
|
areas.data()
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
OPENMW_CHECK_DT_RESULT(rcRasterizeTriangles(
|
|
|
|
|
const auto trianglesRasterized = rcRasterizeTriangles(
|
|
|
|
|
&context,
|
|
|
|
|
recastMesh.getVertices().data(),
|
|
|
|
|
static_cast<int>(recastMesh.getVerticesCount()),
|
|
|
|
@ -190,7 +260,10 @@ namespace
|
|
|
|
|
static_cast<int>(chunk.mSize),
|
|
|
|
|
solid,
|
|
|
|
|
config.walkableClimb
|
|
|
|
|
));
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (!trianglesRasterized)
|
|
|
|
|
throw NavigatorException("Failed to create rasterize triangles from recast mesh for navmesh");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -231,7 +304,7 @@ namespace
|
|
|
|
|
0, 2, 3,
|
|
|
|
|
}};
|
|
|
|
|
|
|
|
|
|
OPENMW_CHECK_DT_RESULT(rcRasterizeTriangles(
|
|
|
|
|
const auto trianglesRasterized = rcRasterizeTriangles(
|
|
|
|
|
&context,
|
|
|
|
|
convertedVertices.data(),
|
|
|
|
|
static_cast<int>(convertedVertices.size() / 3),
|
|
|
|
@ -240,7 +313,10 @@ namespace
|
|
|
|
|
static_cast<int>(areas.size()),
|
|
|
|
|
solid,
|
|
|
|
|
config.walkableClimb
|
|
|
|
|
));
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (!trianglesRasterized)
|
|
|
|
|
throw NavigatorException("Failed to create rasterize water triangles for navmesh");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -254,24 +330,22 @@ namespace
|
|
|
|
|
const PolyMeshDetailStackPtr polyMeshDetailPtr(&polyMeshDetail);
|
|
|
|
|
{
|
|
|
|
|
rcCompactHeightfield compact;
|
|
|
|
|
buildCompactHeightfield(context, config.walkableHeight, config.walkableClimb, solid, compact);
|
|
|
|
|
|
|
|
|
|
OPENMW_CHECK_DT_RESULT(rcBuildCompactHeightfield(&context, config.walkableHeight, config.walkableClimb,
|
|
|
|
|
solid, compact));
|
|
|
|
|
OPENMW_CHECK_DT_RESULT(rcErodeWalkableArea(&context, config.walkableRadius, compact));
|
|
|
|
|
OPENMW_CHECK_DT_RESULT(rcBuildDistanceField(&context, compact));
|
|
|
|
|
OPENMW_CHECK_DT_RESULT(rcBuildRegions(&context, compact, config.borderSize, config.minRegionArea,
|
|
|
|
|
config.mergeRegionArea));
|
|
|
|
|
erodeWalkableArea(context, config.walkableRadius, compact);
|
|
|
|
|
buildDistanceField(context, compact);
|
|
|
|
|
buildRegions(context, compact, config.borderSize, config.minRegionArea, config.mergeRegionArea);
|
|
|
|
|
|
|
|
|
|
rcContourSet contourSet;
|
|
|
|
|
OPENMW_CHECK_DT_RESULT(rcBuildContours(&context, compact, config.maxSimplificationError, config.maxEdgeLen,
|
|
|
|
|
contourSet));
|
|
|
|
|
buildContours(context, compact, config.maxSimplificationError, config.maxEdgeLen, contourSet);
|
|
|
|
|
|
|
|
|
|
if (contourSet.nconts == 0)
|
|
|
|
|
return NavMeshData();
|
|
|
|
|
|
|
|
|
|
OPENMW_CHECK_DT_RESULT(rcBuildPolyMesh(&context, contourSet, config.maxVertsPerPoly, polyMesh));
|
|
|
|
|
OPENMW_CHECK_DT_RESULT(rcBuildPolyMeshDetail(&context, polyMesh, compact, config.detailSampleDist,
|
|
|
|
|
config.detailSampleMaxError, polyMeshDetail));
|
|
|
|
|
buildPolyMesh(context, contourSet, config.maxVertsPerPoly, polyMesh);
|
|
|
|
|
|
|
|
|
|
buildPolyMeshDetail(context, polyMesh, compact, config.detailSampleDist, config.detailSampleMaxError,
|
|
|
|
|
polyMeshDetail);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < polyMesh.npolys; ++i)
|
|
|
|
@ -323,7 +397,10 @@ namespace
|
|
|
|
|
|
|
|
|
|
unsigned char* navMeshData;
|
|
|
|
|
int navMeshDataSize;
|
|
|
|
|
OPENMW_CHECK_DT_RESULT(dtCreateNavMeshData(¶ms, &navMeshData, &navMeshDataSize));
|
|
|
|
|
const auto navMeshDataCreated = dtCreateNavMeshData(¶ms, &navMeshData, &navMeshDataSize);
|
|
|
|
|
|
|
|
|
|
if (!navMeshDataCreated)
|
|
|
|
|
throw NavigatorException("Failed to create navmesh tile data");
|
|
|
|
|
|
|
|
|
|
return NavMeshData(navMeshData, navMeshDataSize);
|
|
|
|
|
}
|
|
|
|
@ -360,7 +437,10 @@ namespace DetourNavigator
|
|
|
|
|
params.maxPolys = maxPolysPerTile;
|
|
|
|
|
|
|
|
|
|
NavMeshPtr navMesh(dtAllocNavMesh(), &dtFreeNavMesh);
|
|
|
|
|
OPENMW_CHECK_DT_STATUS(navMesh->init(¶ms));
|
|
|
|
|
const auto status = navMesh->init(¶ms);
|
|
|
|
|
|
|
|
|
|
if (!dtStatusSucceed(status))
|
|
|
|
|
throw NavigatorException("Failed to init navmesh");
|
|
|
|
|
|
|
|
|
|
return navMesh;
|
|
|
|
|
}
|
|
|
|
|