cloudy-raytracer/common/noise/worleynoise.cpp

101 lines
2.7 KiB
C++
Raw Normal View History

#include <chrono>
#include <iostream>
#include <algorithm>
#include <set>
#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<std::chrono::seconds>(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)
{
2023-01-24 06:26:24 +01:00
// Init random
std::random_device rd;
this->generator = std::mt19937(rd());
this->distribution = std::uniform_real_distribution<float>(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<float> 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());
}