}
-///////////////////////// [ New perlin stuff ] ////////////////////////////
+///////////////////////// [ New noise ] ////////////////////////////
-Noise::Noise(NoiseParams *np, int seed, int sx, int sy, int sz)
+float NoisePerlin2D(NoiseParams *np, float x, float y, int seed)
{
- this->np = np;
+ float a = 0;
+ float f = 1.0;
+ float g = 1.0;
+
+ x /= np->spread.X;
+ y /= np->spread.Y;
+ seed += np->seed;
+
+ for (size_t i = 0; i < np->octaves; i++) {
+ float noiseval = noise2d_gradient(x * f, y * f, seed + i,
+ np->flags & (NOISE_FLAG_DEFAULTS | NOISE_FLAG_EASED));
+
+ if (np->flags & NOISE_FLAG_ABSVALUE)
+ noiseval = fabs(noiseval);
+
+ a += g * noiseval;
+ f *= np->lacunarity;
+ g *= np->persist;
+ }
+
+ return np->offset + a * np->scale;
+}
+
+
+float NoisePerlin3D(NoiseParams *np, float x, float y, float z, int seed)
+{
+ float a = 0;
+ float f = 1.0;
+ float g = 1.0;
+
+ x /= np->spread.X;
+ y /= np->spread.Y;
+ z /= np->spread.Z;
+ seed += np->seed;
+
+ for (size_t i = 0; i < np->octaves; i++) {
+ float noiseval = noise3d_gradient(x * f, y * f, z * f, seed + i,
+ np->flags & NOISE_FLAG_EASED);
+
+ if (np->flags & NOISE_FLAG_ABSVALUE)
+ noiseval = fabs(noiseval);
+
+ a += g * noiseval;
+ f *= np->lacunarity;
+ g *= np->persist;
+ }
+
+ return np->offset + a * np->scale;
+}
+
+
+Noise::Noise(NoiseParams *np_, int seed, int sx, int sy, int sz)
+{
+ memcpy(&np, np_, sizeof(np));
this->seed = seed;
this->sx = sx;
this->sy = sy;
this->gradient_buf = NULL;
this->result = NULL;
- if (np->flags & NOISE_FLAG_DEFAULTS) {
- // By default, only 2d noise is eased.
- if (sz <= 1)
- np->flags |= NOISE_FLAG_EASED;
- }
-
allocBuffers();
}
void Noise::setSpreadFactor(v3f spread)
{
- this->np->spread = spread;
+ this->np.spread = spread;
resizeNoiseBuf(sz > 1);
}
void Noise::setOctaves(int octaves)
{
- this->np->octaves = octaves;
+ this->np.octaves = octaves;
resizeNoiseBuf(sz > 1);
}
float ofactor;
//maximum possible spread value factor
- ofactor = (float)(1 << (np->octaves - 1));
+ ofactor = pow(np.lacunarity, np.octaves - 1);
//noise lattice point count
//(int)(sz * spread * ofactor) is # of lattice points crossed due to length
// + 2 for the two initial endpoints
// + 1 for potentially crossing a boundary due to offset
- nlx = (int)(sx * ofactor / np->spread.X) + 3;
- nly = (int)(sy * ofactor / np->spread.Y) + 3;
- nlz = is3d ? (int)(sz * ofactor / np->spread.Z) + 3 : 1;
+ nlx = (int)ceil(sx * ofactor / np.spread.X) + 3;
+ nly = (int)ceil(sy * ofactor / np.spread.Y) + 3;
+ nlz = is3d ? (int)ceil(sz * ofactor / np.spread.Z) + 3 : 1;
delete[] noise_buf;
try {
int index, i, j, x0, y0, noisex, noisey;
int nlx, nly;
- Interp2dFxn interpolate = (np->flags & NOISE_FLAG_EASED) ?
+ bool eased = np.flags & (NOISE_FLAG_DEFAULTS | NOISE_FLAG_EASED);
+ Interp2dFxn interpolate = eased ?
biLinearInterpolation : biLinearInterpolationNoEase;
x0 = floor(x);
int index, i, j, k, x0, y0, z0, noisex, noisey, noisez;
int nlx, nly, nlz;
- Interp3dFxn interpolate = (np->flags & NOISE_FLAG_EASED) ?
+ Interp3dFxn interpolate = (np.flags & NOISE_FLAG_EASED) ?
triLinearInterpolation : triLinearInterpolationNoEase;
x0 = floor(x);
float f = 1.0, g = 1.0;
size_t bufsize = sx * sy;
- x /= np->spread.X;
- y /= np->spread.Y;
+ x /= np.spread.X;
+ y /= np.spread.Y;
memset(result, 0, sizeof(float) * bufsize);
persist_buf[i] = 1.0;
}
- for (size_t oct = 0; oct < np->octaves; oct++) {
+ for (size_t oct = 0; oct < np.octaves; oct++) {
gradientMap2D(x * f, y * f,
- f / np->spread.X, f / np->spread.Y,
- seed + np->seed + oct);
+ f / np.spread.X, f / np.spread.Y,
+ seed + np.seed + oct);
updateResults(g, persist_buf, persistence_map, bufsize);
- f *= np->lacunarity;
- g *= np->persist;
+ f *= np.lacunarity;
+ g *= np.persist;
+ }
+
+ if (fabs(np.offset - 0.f) > 0.00001 || fabs(np.scale - 1.f) > 0.00001) {
+ for (size_t i = 0; i != bufsize; i++)
+ result[i] = result[i] * np.scale + np.offset;
}
return result;
float f = 1.0, g = 1.0;
size_t bufsize = sx * sy * sz;
- x /= np->spread.X;
- y /= np->spread.Y;
- z /= np->spread.Z;
+ x /= np.spread.X;
+ y /= np.spread.Y;
+ z /= np.spread.Z;
memset(result, 0, sizeof(float) * bufsize);
persist_buf[i] = 1.0;
}
- for (size_t oct = 0; oct < np->octaves; oct++) {
+ for (size_t oct = 0; oct < np.octaves; oct++) {
gradientMap3D(x * f, y * f, z * f,
- f / np->spread.X, f / np->spread.Y, f / np->spread.Z,
- seed + np->seed + oct);
+ f / np.spread.X, f / np.spread.Y, f / np.spread.Z,
+ seed + np.seed + oct);
updateResults(g, persist_buf, persistence_map, bufsize);
- f *= np->lacunarity;
- g *= np->persist;
+ f *= np.lacunarity;
+ g *= np.persist;
+ }
+
+ if (fabs(np.offset - 0.f) > 0.00001 || fabs(np.scale - 1.f) > 0.00001) {
+ for (size_t i = 0; i != bufsize; i++)
+ result[i] = result[i] * np.scale + np.offset;
}
return result;
{
// This looks very ugly, but it is 50-70% faster than having
// conditional statements inside the loop
- if (np->flags & NOISE_FLAG_ABSVALUE) {
+ if (np.flags & NOISE_FLAG_ABSVALUE) {
if (persistence_map) {
for (size_t i = 0; i != bufsize; i++) {
result[i] += gmap[i] * fabs(gradient_buf[i]);
}
}
}
-
-
-void Noise::transformNoiseMap()
-{
- // Because sx, sy, and sz are object members whose values may conceivably be
- // modified in other threads. gcc (at least) will consider the buffer size
- // computation as invalidated between loop comparisons, resulting in a ~2x
- // slowdown even with -O2. To prevent this, store the value in a local.
- size_t bufsize = sx * sy * sz;
- for (size_t i = 0; i != bufsize; i++)
- result[i] = result[i] * np->scale + np->offset;
-}
-