/* Algorithm as describe by: http://devmag.org.za/2009/05/03/poisson-disk-sampling/ */ void NoiseProcessor::poissonDisk(Image *img) { float minDist = size_.get().x; minDist /= poissonDotsAlongX_; //min pixel distance between samples auto minDist2 = minDist*minDist; size2_t gridSize = size2_t(1)+ size2_t(vec2(size_.get()) * (1.0f / minDist)); auto gridImg = util::make_unique<Image>(gridSize, DataVec2INT32::get()); auto grid = gridImg->getColorLayer()->getEditableRepresentation<LayerRAM>(); auto imgData = static_cast<float*>(img->getColorLayer()->getEditableRepresentation<LayerRAM>()->getData()); auto gridData = static_cast<glm::i32vec2*>(grid->getData()); util::IndexMapper2D imgIndex(size_.get()); util::IndexMapper2D gridIndex(gridSize); for (size_t i = 0; i < gridSize.x*gridSize.y; i++) { gridData[i] = glm::i32vec2(-2 * minDist); } std::uniform_int_distribution<int> rx(0, size_.get().x); std::uniform_int_distribution<int> ry(0, size_.get().y); std::uniform_real_distribution<float> rand(0, 1); std::vector<glm::i32vec2> processList; std::vector<glm::i32vec2> samplePoints; auto firstPoint = glm::i32vec2(rx(mt_), ry(mt_)); processList.push_back(firstPoint); samplePoints.push_back(firstPoint); auto toGrid = [minDist](glm::i32vec2 p)->glm::i32vec2 { return glm::i32vec2(vec2(p)/minDist); }; gridData[gridIndex(toGrid(firstPoint))] = firstPoint; int someNumber = 30; while (processList.size() != 0 && samplePoints.size() < static_cast<size_t>(poissonMaxPoints_)) { std::uniform_int_distribution<size_t> ri(0, processList.size()-1); auto i = ri(mt_); auto p = processList[i]; processList.erase(processList.begin() + i); for (int j = 0; j < someNumber; j++) { auto newPoint = generateRandomPointAround(p, minDist, rand, mt_); if (newPoint.x < 0) continue; if (newPoint.y < 0) continue; if (newPoint.x >= size_.get().x) continue; if (newPoint.y >= size_.get().y) continue; auto newGridPoint = toGrid(newPoint); bool neighbourhood = false; int startX = std::max(0, newGridPoint.x - 2); int startY = std::max(0, newGridPoint.y - 2); int endX = std::min(static_cast<int>(gridSize.x) - 1, newGridPoint.x + 2); int endY = std::min(static_cast<int>(gridSize.y) - 1, newGridPoint.y + 2); for (int x = startX; x <= endX && !neighbourhood; x++) { for (int y = startY; y <= endY && !neighbourhood; y++) { auto p2 = gridData[gridIndex(glm::i32vec2(x, y))]; auto dist = glm::distance2(vec2(newPoint), vec2(p2)); if (dist < minDist2) { neighbourhood = true; } } }//*/ if (!neighbourhood) { processList.push_back(newPoint); samplePoints.push_back(newPoint); auto idx = gridIndex(newGridPoint); gridData[idx] = newPoint; imgData[imgIndex(newPoint)] = 1; } } } }
void NavGrid::UnBlockCell(const CU::Vector3f& aWorldPos) { CU::Vector2i gridIndex(static_cast<int>(aWorldPos.x), static_cast<int>(aWorldPos.z)); UnBlockCell(gridIndex); }