qboolean BotSetupNav( const botClass_t *botClass, qhandle_t *navHandle ) { cvar_t *maxNavNodes = Cvar_Get( "bot_maxNavNodes", "4096", CVAR_ARCHIVE | CVAR_LATCH ); if ( !numNavData ) { vec3_t clearVec = { 0, 0, 0 }; dtAllocSetCustom( dtAllocCustom, dtFreeCustom ); for ( int i = 0; i < MAX_CLIENTS; i++ ) { // should only init the corridor once if ( !agents[ i ].corridor.getPath() ) { if ( !agents[ i ].corridor.init( MAX_BOT_PATH ) ) { return qfalse; } } agents[ i ].corridor.reset( 0, clearVec ); agents[ i ].clientNum = i; agents[ i ].needReplan = true; agents[ i ].nav = NULL; agents[ i ].offMesh = false; memset( agents[ i ].routeResults, 0, sizeof( agents[ i ].routeResults ) ); } #ifndef DEDICATED NavEditInit(); #endif } if ( numNavData == MAX_NAV_DATA ) { Com_Printf( "^3ERROR: maximum number of navigation meshes exceeded\n" ); return qfalse; } NavData_t *nav = &BotNavData[ numNavData ]; const char *filename = botClass->name; if ( !BotLoadNavMesh( filename, *nav ) ) { BotShutdownNav(); return qfalse; } Q_strncpyz( nav->name, botClass->name, sizeof( nav->name ) ); nav->query = dtAllocNavMeshQuery(); if ( !nav->query ) { Com_Printf( "Could not allocate Detour Navigation Mesh Query for navmesh %s\n", filename ); BotShutdownNav(); return qfalse; } if ( dtStatusFailed( nav->query->init( nav->mesh, maxNavNodes->integer ) ) ) { Com_Printf( "Could not init Detour Navigation Mesh Query for navmesh %s\n", filename ); BotShutdownNav(); return qfalse; } nav->filter.setIncludeFlags( botClass->polyFlagsInclude ); nav->filter.setExcludeFlags( botClass->polyFlagsExclude ); *navHandle = numNavData; numNavData++; return qtrue; }
int main() { rcAllocSetCustom(allocCustom<rcAllocHint>, freeCustom); dtAllocSetCustom(allocCustom<dtAllocHint>, freeCustom); BuildContext ctx; InputGeom geom; geom.load(&ctx, "./geomset.txt"); ArMeshDataBuilder builder(&ctx, &geom, meshProcess); builder.setAgentMaxClimb(1.8f); ArMeshDataPtr data = builder.build(); if (!data) { ctx.log(RC_LOG_ERROR, "Build ArMeshData failed."); return -1; } ctx.log(RC_LOG_PROGRESS, "Total build time: %d ms", ctx.getAccumulatedTime(RC_TIMER_TOTAL)); if (!save(&ctx, data)) { return -1; } FILE* in = fopen("./all_tiles_navmesh.bin", "rb"); if (!in) { ctx.log(RC_LOG_ERROR, "Open all_tiles_navmesh.bin failed."); return -1; } ArMeshDataFileReader reader(in); if (!reader.serialize(*data)) { ctx.log(RC_LOG_ERROR, "Read ArMeshData failed."); fclose(in); return -1; } fclose(in); ArMesh mesh; ArMeshImporter importer(mesh); if (!importer.serialize(*data)) { ctx.log(RC_LOG_ERROR, "Import ArMeshData failed."); return -1; } ArQuery query; if (dtStatusFailed(query.init(&mesh, 2048))) { ctx.log(RC_LOG_ERROR, "Init ArQuery failed."); return -1; } float sp[3]; printf("start: "); scanf("%f%f%f", sp, sp + 1, sp + 2); float ep[3]; printf("end: "); scanf("%f%f%f", ep, ep + 1, ep + 2); float ext[3] = {2, 4, 2}; dtQueryFilter filter; filter.setAreaCost(SAMPLE_POLYAREA_GROUND, 1.0f); filter.setAreaCost(SAMPLE_POLYAREA_WATER, 10.0f); filter.setAreaCost(SAMPLE_POLYAREA_ROAD, 1.0f); filter.setAreaCost(SAMPLE_POLYAREA_DOOR, 1.0f); filter.setAreaCost(SAMPLE_POLYAREA_GRASS, 2.0f); filter.setAreaCost(SAMPLE_POLYAREA_JUMP, 1.5f); dtPolyRef sr; query.backend()->findNearestPoly(sp, ext, &filter, &sr, 0); dtPolyRef er; query.backend()->findNearestPoly(ep, ext, &filter, &er, 0); dtPolyRef polys[256]; int npolys; query.backend()->findPath(sr, er, sp, ep, &filter, polys, &npolys, 256); float path[256 * 3]; dtPolyRef pathPolys[256]; unsigned char pathFlags[256]; int pathLen; query.backend()->findStraightPath(sp, ep, polys, npolys, path, pathFlags, pathPolys, &pathLen, 256, 0); printf("path:\n%d\n", pathLen); for (int i = 0; i < pathLen; ++i) { printf("%f %f %f\n", path[i * 3], path[i * 3 + 1], path[i * 3 + 2]); } if (!exportMesh(&ctx, mesh)) { return -1; } return 0; }