#include #include "noise.h" float Noise::getNoise(Vector3d point) const { return getNoise(point.x, point.y, point.z); } void Noise::generateNoiseMap(int size) { noiseMap.clear(); noiseMap.resize(size * size * size); } void Noise::setNoise(int x, int y, int z, float value) { long int index = x + y * (long int) size + z * size * (long int) size; noiseMap[index] = value; } float Noise::getNoise(float x, float y, float z) const { // Scale to [0, size] x *= size; y *= size; z *= size; // Get corner points of the cube int x_min = (int) fitToNoise(floor(x)); int y_min = (int) fitToNoise(floor(y)); int z_min = (int) fitToNoise(floor(z)); int x_max = fitToNoise(x_min + 1); int y_max = fitToNoise(y_min + 1); int z_max = fitToNoise(z_min + 1); // Get the getNoise values at the corner points float n000 = getCalculatedNoise(x_min, y_min, z_min); float n001 = getCalculatedNoise(x_min, y_min, z_max); float n010 = getCalculatedNoise(x_min, y_max, z_min); float n011 = getCalculatedNoise(x_min, y_max, z_max); float n100 = getCalculatedNoise(x_max, y_min, z_min); float n101 = getCalculatedNoise(x_max, y_min, z_max); float n110 = getCalculatedNoise(x_max, y_max, z_min); float n111 = getCalculatedNoise(x_max, y_max, z_max); // Get fractions float fx = x - floor(x); float fy = y - floor(y); float fz = z - floor(z); // Interpolate float nx00 = interpolate(n000, n100, fx); float nx01 = interpolate(n001, n101, fx); float nx10 = interpolate(n010, n110, fx); float nx11 = interpolate(n011, n111, fx); float nxy0 = interpolate(nx00, nx10, fy); float nxy1 = interpolate(nx01, nx11, fy); float noise = interpolate(nxy0, nxy1, fz); return noise; } float Noise::getCalculatedNoise(int x, int y, int z) const { long int index = x + y * (long int) size + z * size * (long int) size; float noise = noiseMap[index]; if (invert) { noise = 1.0f - noise; } return noise; } Noise::Noise(int size) { this->size = size; generateNoiseMap(size); } /* Function to linearly interpolate between a0 and a1 * Weight w should be in the range [0.0, 1.0] */ float Noise::interpolate(float a0, float a1, float w) const { if (0.0 > w) return a0; if (1.0 < w) return a1; /* // You may want clamping by inserting: * if (0.0 > w) return a0; * if (1.0 < w) return a1; */ return (a1 - a0) * ((w * (w * 6.0 - 15.0) + 10.0) * w * w * w) + a0; return (a1 - a0) * (3.0 - w * 2.0) * w * w + a0; return (a1 - a0) * w + a0; /* // Use this cubic interpolation [[Smoothstep]] instead, for a smooth appearance: * return (a1 - a0) * (3.0 - w * 2.0) * w * w + a0; * * // Use [[Smootherstep]] for an even smoother result with a second derivative equal to zero on boundaries: * return (a1 - a0) * ((w * (w * 6.0 - 15.0) + 10.0) * w * w * w) + a0; */ } float Noise::fitToNoise(float point) const { float remainingValue = fmod(point, size); if (remainingValue < 0) { remainingValue += size; } return remainingValue; }