#include #include #include #include #include "worleynoise.h" #include "common/vector3d.h" void WorleyNoise::generateNoise() { auto start = std::chrono::high_resolution_clock::now(); // Generate random points points.clear(); for (int i = 0; i < numberOfPoints * 3; i++) { points.emplace_back(getRandomPoint()); } // Generate getNoise map noiseMap.clear(); noiseMap.resize(size * size * size); for (int x = 0; x < size; x++) { for (int y = 0; y < size; y++) { for (int z = 0; z < size; z++) { Vector3d point = Vector3d(x, y, z); point /= (float) size; setNoise(x, y, z, repeatableDistanceToClosestPoint(point)); } } } // Normalize getNoise map to [0, 1] float min = *std::min_element(noiseMap.begin(), noiseMap.end()); float max = *std::max_element(noiseMap.begin(), noiseMap.end()); for (int i = 0; i < noiseMap.size(); i++) { noiseMap[i] = (noiseMap[i] - min) / (max - min); } // Duration of computation auto stop = std::chrono::high_resolution_clock::now(); auto duration = std::chrono::duration_cast(stop - start); std::cout << "Finished computing Worley getNoise for size " << size << " and " << numberOfPoints << " points in " << duration.count() << " seconds" << std::endl; } WorleyNoise::WorleyNoise(int size, int numberOfPoints) : numberOfPoints(pow(numberOfPoints, 3)), Noise(size) { // Init random std::random_device rd; this->generator = std::mt19937(rd()); this->distribution = std::uniform_real_distribution(0.0f, 1.0f); generateNoise(); } Vector3d WorleyNoise::getRandomPoint() { return Vector3d(distribution(generator), distribution(generator), distribution(generator)); } float WorleyNoise::distanceToClosestPoint(Vector3d point) { float minDistance = INFINITY; for (Vector3d p: points) { float distance = length(p - point); if (distance < minDistance) { minDistance = distance; } } return minDistance; } float WorleyNoise::repeatableDistanceToClosestPoint(Vector3d point) { std::set distances; // Move point around to get distance to closest point in all 27 cells for (int x = -1; x <= 1; x++) { for (int y = -1; y <= 1; y++) { for (int z = -1; z <= 1; z++) { Vector3d offsetPoint = point + Vector3d(x, y, z); distances.insert(distanceToClosestPoint(offsetPoint)); } } } return *std::min_element(distances.begin(), distances.end()); }