LocalFloorfieldViaFM::LocalFloorfieldViaFM(const Room* const roomArg, const Building* buildingArg, const double hxArg, const double hyArg, const double wallAvoidDistance, const bool useDistancefield) { //ctor //_threshold = -1; //negative value means: ignore threshold _threshold = wallAvoidDistance; _building = buildingArg; _room = roomArg; if (hxArg != hyArg) std::cerr << "ERROR: hx != hy <========="; //parse building and create list of walls/obstacles (find xmin xmax, ymin, ymax, and add border?) //Log->Write("INFO: \tStart Parsing: Room %d", roomArg->GetID()); parseRoom(roomArg, hxArg, hyArg); //Log->Write("INFO: \tFinished Parsing: Room %d", roomArg->GetID()); //testoutput("AALineScan.vtk", "AALineScan.txt", dist2Wall); prepareForDistanceFieldCalculation(false); //here we need to draw blocker lines @todo: ar.graf //drawBlockerLines(); //Log->Write("INFO: \tGrid initialized: Walls in room %d", roomArg->GetID()); calculateDistanceField(-1.); //negative threshold is ignored, so all distances get calculated. this is important since distances is used for slowdown/redirect //Log->Write("INFO: \tGrid initialized: Walldistances in room %d", roomArg->GetID()); setSpeed(useDistancefield); //use distance2Wall //Log->Write("INFO: \tGrid initialized: Speed in room %d", roomArg->GetID()); calculateFloorfield(_exitsFromScope, _cost, _neggrad); //Log->Write("INFO: \tFloor field for \"goal -1\" done in room %d", roomArg->GetID()); };
dtStatus dtBuildTileCacheDistanceField(dtTileCacheAlloc* alloc, dtTileCacheLayer& layer, dtTileCacheDistanceField& dfield) { dtAssert(alloc); const int w = (int)layer.header->width; const int h = (int)layer.header->height; dfield.data = (unsigned short*)alloc->alloc(w*h*sizeof(unsigned short)); if (!dfield.data) { return DT_FAILURE | DT_OUT_OF_MEMORY; } dtTileCacheDistanceField tmpField; tmpField.data = (unsigned short*)alloc->alloc(w*h*sizeof(unsigned short)); if (!tmpField.data) { return DT_FAILURE | DT_OUT_OF_MEMORY; } calculateDistanceField(layer, dfield.data, dfield.maxDist); if (boxBlur(layer, 1, dfield.data, tmpField.data) != dfield.data) { dtSwap(dfield.data, tmpField.data); } alloc->free(tmpField.data); return DT_SUCCESS; }
/// @par /// /// This is usually the second to the last step in creating a fully built /// compact heightfield. This step is required before regions are built /// using #rcBuildRegions or #rcBuildRegionsMonotone. /// /// After this step, the distance data is available via the rcCompactHeightfield::maxDistance /// and rcCompactHeightfield::dist fields. /// /// @see rcCompactHeightfield, rcBuildRegions, rcBuildRegionsMonotone bool rcBuildDistanceField(rcContext* ctx, rcCompactHeightfield& chf) { rcAssert(ctx); ctx->startTimer(RC_TIMER_BUILD_DISTANCEFIELD); if (chf.dist) { rcFree(chf.dist); chf.dist = 0; } unsigned short* src = (unsigned short*)rcAlloc(sizeof(unsigned short)*chf.spanCount, RC_ALLOC_TEMP); if (!src) { ctx->log(RC_LOG_ERROR, "rcBuildDistanceField: Out of memory 'src' (%d).", chf.spanCount); return false; } unsigned short* dst = (unsigned short*)rcAlloc(sizeof(unsigned short)*chf.spanCount, RC_ALLOC_TEMP); if (!dst) { ctx->log(RC_LOG_ERROR, "rcBuildDistanceField: Out of memory 'dst' (%d).", chf.spanCount); rcFree(src); return false; } unsigned short maxDist = 0; ctx->startTimer(RC_TIMER_BUILD_DISTANCEFIELD_DIST); calculateDistanceField(chf, src, maxDist); chf.maxDistance = maxDist; ctx->stopTimer(RC_TIMER_BUILD_DISTANCEFIELD_DIST); ctx->startTimer(RC_TIMER_BUILD_DISTANCEFIELD_BLUR); // Blur if (boxBlur(chf, 1, src, dst) != src) rcSwap(src, dst); // Store distance. chf.dist = src; ctx->stopTimer(RC_TIMER_BUILD_DISTANCEFIELD_BLUR); ctx->stopTimer(RC_TIMER_BUILD_DISTANCEFIELD); rcFree(dst); return true; }
/// @par /// /// This is usually the second to the last step in creating a fully built /// compact heightfield. This step is required before regions are built /// using #rcBuildRegions or #rcBuildRegionsMonotone. /// /// After this step, the distance data is available via the rcCompactHeightfield::maxDistance /// and rcCompactHeightfield::dist fields. /// /// @see rcCompactHeightfield, rcBuildRegions, rcBuildRegionsMonotone bool rcBuildDistanceField(rcCompactHeightfield& chf) { if (chf.dist) { rcFree(chf.dist); chf.dist = 0; } unsigned short* src = (unsigned short*)rcAlloc(sizeof(unsigned short)*chf.spanCount, RC_ALLOC_TEMP); if (!src) { return false; } unsigned short* dst = (unsigned short*)rcAlloc(sizeof(unsigned short)*chf.spanCount, RC_ALLOC_TEMP); if (!dst) { rcFree(src); return false; } unsigned short maxDist = 0; calculateDistanceField(chf, src, maxDist); chf.maxDistance = maxDist; // Blur if (boxBlur(chf, 1, src, dst) != src) rcSwap(src, dst); // Store distance. chf.dist = src; rcFree(dst); return true; }
bool rcBuildDistanceField(rcCompactHeightfield& chf) { rcTimeVal startTime = rcGetPerformanceTimer(); unsigned short* dist0 = new unsigned short[chf.spanCount]; if (!dist0) { if (rcGetLog()) rcGetLog()->log(RC_LOG_ERROR, "rcBuildDistanceField: Out of memory 'dist0' (%d).", chf.spanCount); return false; } unsigned short* dist1 = new unsigned short[chf.spanCount]; if (!dist1) { if (rcGetLog()) rcGetLog()->log(RC_LOG_ERROR, "rcBuildDistanceField: Out of memory 'dist1' (%d).", chf.spanCount); delete [] dist0; return false; } unsigned short* src = dist0; unsigned short* dst = dist1; unsigned short maxDist = 0; rcTimeVal distStartTime = rcGetPerformanceTimer(); if (calculateDistanceField(chf, src, dst, maxDist) != src) rcSwap(src, dst); chf.maxDistance = maxDist; rcTimeVal distEndTime = rcGetPerformanceTimer(); rcTimeVal blurStartTime = rcGetPerformanceTimer(); // Blur if (boxBlur(chf, 1, src, dst) != src) rcSwap(src, dst); // Store distance. for (int i = 0; i < chf.spanCount; ++i) chf.spans[i].dist = src[i]; rcTimeVal blurEndTime = rcGetPerformanceTimer(); delete [] dist0; delete [] dist1; rcTimeVal endTime = rcGetPerformanceTimer(); /* if (rcGetLog()) { rcGetLog()->log(RC_LOG_PROGRESS, "Build distance field: %.3f ms", rcGetDeltaTimeUsec(startTime, endTime)/1000.0f); rcGetLog()->log(RC_LOG_PROGRESS, " - dist: %.3f ms", rcGetDeltaTimeUsec(distStartTime, distEndTime)/1000.0f); rcGetLog()->log(RC_LOG_PROGRESS, " - blur: %.3f ms", rcGetDeltaTimeUsec(blurStartTime, blurEndTime)/1000.0f); }*/ if (rcGetBuildTimes()) { rcGetBuildTimes()->buildDistanceField += rcGetDeltaTimeUsec(startTime, endTime); rcGetBuildTimes()->buildDistanceFieldDist += rcGetDeltaTimeUsec(distStartTime, distEndTime); rcGetBuildTimes()->buildDistanceFieldBlur += rcGetDeltaTimeUsec(blurStartTime, blurEndTime); } return true; }