115 lines
3.1 KiB
C++
115 lines
3.1 KiB
C++
#include <cmath>
|
|
#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
|
|
{
|
|
/* // 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;
|
|
}
|