diff --git a/common/noise/worleynoise.cpp b/common/noise/worleynoise.cpp index b256c8f..7c8633e 100644 --- a/common/noise/worleynoise.cpp +++ b/common/noise/worleynoise.cpp @@ -11,9 +11,25 @@ void WorleyNoise::generateNoise() // Generate random points points.clear(); - for (int i = 0; i < numberOfPoints * 3; i++) + points.reserve(pow(numberOfPoints, 3)); + for (int x = 0; x < numberOfPoints; x++) { - points.emplace_back(getRandomPoint()); + for (int y = 0; y < numberOfPoints; y++) + { + for (int z = 0; z < numberOfPoints; z++) + { + Vector3d point = getRandomPoint(); + + // Scale and translate into subcell + point /= (float) numberOfPoints; + + Vector3d offset = Vector3d(x, y, z); + offset /= (float) numberOfPoints; + point += offset; + + points[x + y * numberOfPoints + z * numberOfPoints * numberOfPoints] = point; + } + } } // Generate getNoise map @@ -28,7 +44,7 @@ void WorleyNoise::generateNoise() { Vector3d point = Vector3d(x, y, z); point /= (float) size; - setNoise(x, y, z, repeatableDistanceToClosestPoint(point)); + setNoise(x, y, z, distanceToClosestPoint(point)); } } } @@ -50,7 +66,7 @@ void WorleyNoise::generateNoise() << duration.count() << " seconds" << std::endl; } -WorleyNoise::WorleyNoise(int size, int numberOfPoints) : numberOfPoints(pow(numberOfPoints, 3)), Noise(size) +WorleyNoise::WorleyNoise(int size, int numberOfPoints) : numberOfPoints(numberOfPoints), Noise(size) { // Init random std::random_device rd; @@ -67,8 +83,11 @@ Vector3d WorleyNoise::getRandomPoint() float WorleyNoise::distanceToClosestPoint(Vector3d point) { + std::vector closePoints = getSubcellPoints(point); + + // Iterate over all subcells float minDistance = INFINITY; - for (Vector3d p: points) + for (Vector3d p: closePoints) { float distance = length(p - point); if (distance < minDistance) @@ -79,22 +98,34 @@ float WorleyNoise::distanceToClosestPoint(Vector3d point) return minDistance; } -float WorleyNoise::repeatableDistanceToClosestPoint(Vector3d point) +std::vector WorleyNoise::getSubcellPoints(Vector3d point) { - std::set distances; + std::vector closePoints; - // Move point around to get distance to closest point in all 27 cells + point.x = std::floor(point.x * numberOfPoints); + point.y = std::floor(point.y * numberOfPoints); + point.z = std::floor(point.z * numberOfPoints); + + // Iterate over all subcells 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)); + Vector3d offset = Vector3d(x, y, z); + Vector3d subcell = point + offset; + + // Wrap around + subcell.x = std::fmod(subcell.x + numberOfPoints, numberOfPoints); + subcell.y = std::fmod(subcell.y + numberOfPoints, numberOfPoints); + subcell.z = std::fmod(subcell.z + numberOfPoints, numberOfPoints); + + // Get points in subcell + int index = subcell.x + subcell.y * numberOfPoints + subcell.z * numberOfPoints * numberOfPoints; + closePoints.push_back(points[index]); } } } - - return *std::min_element(distances.begin(), distances.end()); + return closePoints; } diff --git a/common/noise/worleynoise.h b/common/noise/worleynoise.h index d3a0768..0bba3ed 100644 --- a/common/noise/worleynoise.h +++ b/common/noise/worleynoise.h @@ -14,7 +14,7 @@ public: protected: int numberOfPoints; - std::vector points; // Points in 3D space in [0, 1] + std::vector points; // 3D-Array, each cell represents a subcell. There are numberOfPoints^3 subcells. std::uniform_real_distribution distribution; std::mt19937 generator; @@ -23,9 +23,9 @@ protected: float distanceToClosestPoint(Vector3d point); - float repeatableDistanceToClosestPoint(Vector3d point); - void generateNoise(); + + std::vector getSubcellPoints(Vector3d point); };