Added NoiseState to maintain the noise offsets in clouds

This commit is contained in:
Michaël Lemaire 2013-12-31 15:50:28 +01:00 committed by Michael Lemaire
parent 123e434b0a
commit e61dae6f0a
24 changed files with 207 additions and 636 deletions

View file

@ -1,381 +0,0 @@
#include "NoiseFunctionNaive.h"
/*
* Naive noise implementation, based on pseudo-random grids.
*/
#include <cstdlib>
#include <cmath>
#include <cstring>
#include "Interpolation.h"
#include "RandomGenerator.h"
#include "PackStream.h"
static int _noise_pool_size;
static double* _noise_pool;
NoiseFunctionNaive::NoiseFunctionNaive()
{
}
void noiseNaiveInit()
{
int i;
_noise_pool_size = 1048576;
_noise_pool = new double[_noise_pool_size];
for (i = 0; i < _noise_pool_size; i++)
{
_noise_pool[i] = RandomGenerator::random() - 0.5;
}
}
void noiseNaiveQuit()
{
delete[] _noise_pool;
}
void noiseNaiveSave(PackStream* stream)
{
int i;
stream->write(&_noise_pool_size);
for (i = 0; i < _noise_pool_size; i++)
{
stream->write(_noise_pool + i);
}
}
void noiseNaiveLoad(PackStream* stream)
{
int i;
stream->read(&_noise_pool_size);
delete[] _noise_pool;
_noise_pool = new double[_noise_pool_size];
for (i = 0; i < _noise_pool_size; i++)
{
stream->read(_noise_pool + i);
}
}
double noiseNaiveGet1DValue(double x)
{
x *= 3.0;
int size = _noise_pool_size;
int xbase = (int)floor(x);
double xinternal = x - (double)xbase;
int x0 = (xbase - 1) % size;
if (x0 < 0)
{
x0 += size;
}
int x1 = xbase % size;
if (x1 < 0)
{
x1 += size;
}
int x2 = (xbase + 1) % size;
if (x2 < 0)
{
x2 += size;
}
int x3 = (xbase + 2) % size;
if (x3 < 0)
{
x3 += size;
}
double buf_cubic_x[4];
buf_cubic_x[0] = _noise_pool[x0 % _noise_pool_size];
buf_cubic_x[1] = _noise_pool[x1 % _noise_pool_size];
buf_cubic_x[2] = _noise_pool[x2 % _noise_pool_size];
buf_cubic_x[3] = _noise_pool[x3 % _noise_pool_size];
return Interpolation::cubic(buf_cubic_x, xinternal) * 0.837 + 0.5;
}
double noiseNaiveGet2DValue(double x, double y)
{
x *= 3.0;
y *= 3.0;
int size = (int)pow(_noise_pool_size, 0.5);
int xbase = (int)floor(x);
int ybase = (int)floor(y);
double xinternal = x - (double)xbase;
double yinternal = y - (double)ybase;
int x0 = (xbase - 1) % size;
if (x0 < 0)
{
x0 += size;
}
int x1 = xbase % size;
if (x1 < 0)
{
x1 += size;
}
int x2 = (xbase + 1) % size;
if (x2 < 0)
{
x2 += size;
}
int x3 = (xbase + 2) % size;
if (x3 < 0)
{
x3 += size;
}
int y0 = (ybase - 1) % size;
if (y0 < 0)
{
y0 += size;
}
int y1 = ybase % size;
if (y1 < 0)
{
y1 += size;
}
int y2 = (ybase + 1) % size;
if (y2 < 0)
{
y2 += size;
}
int y3 = (ybase + 2) % size;
if (y3 < 0)
{
y3 += size;
}
double buf_cubic_x[4];
double buf_cubic_y[4];
buf_cubic_x[0] = _noise_pool[(y0 * size + x0) % _noise_pool_size];
buf_cubic_x[1] = _noise_pool[(y0 * size + x1) % _noise_pool_size];
buf_cubic_x[2] = _noise_pool[(y0 * size + x2) % _noise_pool_size];
buf_cubic_x[3] = _noise_pool[(y0 * size + x3) % _noise_pool_size];
buf_cubic_y[0] = Interpolation::cubic(buf_cubic_x, xinternal);
buf_cubic_x[0] = _noise_pool[(y1 * size + x0) % _noise_pool_size];
buf_cubic_x[1] = _noise_pool[(y1 * size + x1) % _noise_pool_size];
buf_cubic_x[2] = _noise_pool[(y1 * size + x2) % _noise_pool_size];
buf_cubic_x[3] = _noise_pool[(y1 * size + x3) % _noise_pool_size];
buf_cubic_y[1] = Interpolation::cubic(buf_cubic_x, xinternal);
buf_cubic_x[0] = _noise_pool[(y2 * size + x0) % _noise_pool_size];
buf_cubic_x[1] = _noise_pool[(y2 * size + x1) % _noise_pool_size];
buf_cubic_x[2] = _noise_pool[(y2 * size + x2) % _noise_pool_size];
buf_cubic_x[3] = _noise_pool[(y2 * size + x3) % _noise_pool_size];
buf_cubic_y[2] = Interpolation::cubic(buf_cubic_x, xinternal);
buf_cubic_x[0] = _noise_pool[(y3 * size + x0) % _noise_pool_size];
buf_cubic_x[1] = _noise_pool[(y3 * size + x1) % _noise_pool_size];
buf_cubic_x[2] = _noise_pool[(y3 * size + x2) % _noise_pool_size];
buf_cubic_x[3] = _noise_pool[(y3 * size + x3) % _noise_pool_size];
buf_cubic_y[3] = Interpolation::cubic(buf_cubic_x, xinternal);
return Interpolation::cubic(buf_cubic_y, yinternal) * 0.723 + 0.5;
}
double noiseNaiveGet3DValue(double x, double y, double z)
{
x *= 3.0;
y *= 3.0;
z *= 3.0;
int size = (int)pow(_noise_pool_size, 0.33333333333333333);
int xbase = (int)floor(x);
int ybase = (int)floor(y);
int zbase = (int)floor(z);
double xinternal = x - (double)xbase;
double yinternal = y - (double)ybase;
double zinternal = z - (double)zbase;
int x0 = (xbase - 1) % size;
if (x0 < 0)
{
x0 += size;
}
int x1 = xbase % size;
if (x1 < 0)
{
x1 += size;
}
int x2 = (xbase + 1) % size;
if (x2 < 0)
{
x2 += size;
}
int x3 = (xbase + 2) % size;
if (x3 < 0)
{
x3 += size;
}
int y0 = (ybase - 1) % size;
if (y0 < 0)
{
y0 += size;
}
int y1 = ybase % size;
if (y1 < 0)
{
y1 += size;
}
int y2 = (ybase + 1) % size;
if (y2 < 0)
{
y2 += size;
}
int y3 = (ybase + 2) % size;
if (y3 < 0)
{
y3 += size;
}
int z0 = (zbase - 1) % size;
if (z0 < 0)
{
z0 += size;
}
int z1 = zbase % size;
if (z1 < 0)
{
z1 += size;
}
int z2 = (zbase + 1) % size;
if (z2 < 0)
{
z2 += size;
}
int z3 = (zbase + 2) % size;
if (z3 < 0)
{
z3 += size;
}
double buf_cubic_x[4];
double buf_cubic_y[4];
double buf_cubic_z[4];
buf_cubic_x[0] = _noise_pool[(y0 * size * size + x0 * size + z0) % _noise_pool_size];
buf_cubic_x[1] = _noise_pool[(y0 * size * size + x1 * size + z0) % _noise_pool_size];
buf_cubic_x[2] = _noise_pool[(y0 * size * size + x2 * size + z0) % _noise_pool_size];
buf_cubic_x[3] = _noise_pool[(y0 * size * size + x3 * size + z0) % _noise_pool_size];
buf_cubic_y[0] = Interpolation::cubic(buf_cubic_x, xinternal);
buf_cubic_x[0] = _noise_pool[(y1 * size * size + x0 * size + z0) % _noise_pool_size];
buf_cubic_x[1] = _noise_pool[(y1 * size * size + x1 * size + z0) % _noise_pool_size];
buf_cubic_x[2] = _noise_pool[(y1 * size * size + x2 * size + z0) % _noise_pool_size];
buf_cubic_x[3] = _noise_pool[(y1 * size * size + x3 * size + z0) % _noise_pool_size];
buf_cubic_y[1] = Interpolation::cubic(buf_cubic_x, xinternal);
buf_cubic_x[0] = _noise_pool[(y2 * size * size + x0 * size + z0) % _noise_pool_size];
buf_cubic_x[1] = _noise_pool[(y2 * size * size + x1 * size + z0) % _noise_pool_size];
buf_cubic_x[2] = _noise_pool[(y2 * size * size + x2 * size + z0) % _noise_pool_size];
buf_cubic_x[3] = _noise_pool[(y2 * size * size + x3 * size + z0) % _noise_pool_size];
buf_cubic_y[2] = Interpolation::cubic(buf_cubic_x, xinternal);
buf_cubic_x[0] = _noise_pool[(y3 * size * size + x0 * size + z0) % _noise_pool_size];
buf_cubic_x[1] = _noise_pool[(y3 * size * size + x1 * size + z0) % _noise_pool_size];
buf_cubic_x[2] = _noise_pool[(y3 * size * size + x2 * size + z0) % _noise_pool_size];
buf_cubic_x[3] = _noise_pool[(y3 * size * size + x3 * size + z0) % _noise_pool_size];
buf_cubic_y[3] = Interpolation::cubic(buf_cubic_x, xinternal);
buf_cubic_z[0] = Interpolation::cubic(buf_cubic_y, yinternal);
buf_cubic_x[0] = _noise_pool[(y0 * size * size + x0 * size + z1) % _noise_pool_size];
buf_cubic_x[1] = _noise_pool[(y0 * size * size + x1 * size + z1) % _noise_pool_size];
buf_cubic_x[2] = _noise_pool[(y0 * size * size + x2 * size + z1) % _noise_pool_size];
buf_cubic_x[3] = _noise_pool[(y0 * size * size + x3 * size + z1) % _noise_pool_size];
buf_cubic_y[0] = Interpolation::cubic(buf_cubic_x, xinternal);
buf_cubic_x[0] = _noise_pool[(y1 * size * size + x0 * size + z1) % _noise_pool_size];
buf_cubic_x[1] = _noise_pool[(y1 * size * size + x1 * size + z1) % _noise_pool_size];
buf_cubic_x[2] = _noise_pool[(y1 * size * size + x2 * size + z1) % _noise_pool_size];
buf_cubic_x[3] = _noise_pool[(y1 * size * size + x3 * size + z1) % _noise_pool_size];
buf_cubic_y[1] = Interpolation::cubic(buf_cubic_x, xinternal);
buf_cubic_x[0] = _noise_pool[(y2 * size * size + x0 * size + z1) % _noise_pool_size];
buf_cubic_x[1] = _noise_pool[(y2 * size * size + x1 * size + z1) % _noise_pool_size];
buf_cubic_x[2] = _noise_pool[(y2 * size * size + x2 * size + z1) % _noise_pool_size];
buf_cubic_x[3] = _noise_pool[(y2 * size * size + x3 * size + z1) % _noise_pool_size];
buf_cubic_y[2] = Interpolation::cubic(buf_cubic_x, xinternal);
buf_cubic_x[0] = _noise_pool[(y3 * size * size + x0 * size + z1) % _noise_pool_size];
buf_cubic_x[1] = _noise_pool[(y3 * size * size + x1 * size + z1) % _noise_pool_size];
buf_cubic_x[2] = _noise_pool[(y3 * size * size + x2 * size + z1) % _noise_pool_size];
buf_cubic_x[3] = _noise_pool[(y3 * size * size + x3 * size + z1) % _noise_pool_size];
buf_cubic_y[3] = Interpolation::cubic(buf_cubic_x, xinternal);
buf_cubic_z[1] = Interpolation::cubic(buf_cubic_y, yinternal);
buf_cubic_x[0] = _noise_pool[(y0 * size * size + x0 * size + z2) % _noise_pool_size];
buf_cubic_x[1] = _noise_pool[(y0 * size * size + x1 * size + z2) % _noise_pool_size];
buf_cubic_x[2] = _noise_pool[(y0 * size * size + x2 * size + z2) % _noise_pool_size];
buf_cubic_x[3] = _noise_pool[(y0 * size * size + x3 * size + z2) % _noise_pool_size];
buf_cubic_y[0] = Interpolation::cubic(buf_cubic_x, xinternal);
buf_cubic_x[0] = _noise_pool[(y1 * size * size + x0 * size + z2) % _noise_pool_size];
buf_cubic_x[1] = _noise_pool[(y1 * size * size + x1 * size + z2) % _noise_pool_size];
buf_cubic_x[2] = _noise_pool[(y1 * size * size + x2 * size + z2) % _noise_pool_size];
buf_cubic_x[3] = _noise_pool[(y1 * size * size + x3 * size + z2) % _noise_pool_size];
buf_cubic_y[1] = Interpolation::cubic(buf_cubic_x, xinternal);
buf_cubic_x[0] = _noise_pool[(y2 * size * size + x0 * size + z2) % _noise_pool_size];
buf_cubic_x[1] = _noise_pool[(y2 * size * size + x1 * size + z2) % _noise_pool_size];
buf_cubic_x[2] = _noise_pool[(y2 * size * size + x2 * size + z2) % _noise_pool_size];
buf_cubic_x[3] = _noise_pool[(y2 * size * size + x3 * size + z2) % _noise_pool_size];
buf_cubic_y[2] = Interpolation::cubic(buf_cubic_x, xinternal);
buf_cubic_x[0] = _noise_pool[(y3 * size * size + x0 * size + z2) % _noise_pool_size];
buf_cubic_x[1] = _noise_pool[(y3 * size * size + x1 * size + z2) % _noise_pool_size];
buf_cubic_x[2] = _noise_pool[(y3 * size * size + x2 * size + z2) % _noise_pool_size];
buf_cubic_x[3] = _noise_pool[(y3 * size * size + x3 * size + z2) % _noise_pool_size];
buf_cubic_y[3] = Interpolation::cubic(buf_cubic_x, xinternal);
buf_cubic_z[2] = Interpolation::cubic(buf_cubic_y, yinternal);
buf_cubic_x[0] = _noise_pool[(y0 * size * size + x0 * size + z3) % _noise_pool_size];
buf_cubic_x[1] = _noise_pool[(y0 * size * size + x1 * size + z3) % _noise_pool_size];
buf_cubic_x[2] = _noise_pool[(y0 * size * size + x2 * size + z3) % _noise_pool_size];
buf_cubic_x[3] = _noise_pool[(y0 * size * size + x3 * size + z3) % _noise_pool_size];
buf_cubic_y[0] = Interpolation::cubic(buf_cubic_x, xinternal);
buf_cubic_x[0] = _noise_pool[(y1 * size * size + x0 * size + z3) % _noise_pool_size];
buf_cubic_x[1] = _noise_pool[(y1 * size * size + x1 * size + z3) % _noise_pool_size];
buf_cubic_x[2] = _noise_pool[(y1 * size * size + x2 * size + z3) % _noise_pool_size];
buf_cubic_x[3] = _noise_pool[(y1 * size * size + x3 * size + z3) % _noise_pool_size];
buf_cubic_y[1] = Interpolation::cubic(buf_cubic_x, xinternal);
buf_cubic_x[0] = _noise_pool[(y2 * size * size + x0 * size + z3) % _noise_pool_size];
buf_cubic_x[1] = _noise_pool[(y2 * size * size + x1 * size + z3) % _noise_pool_size];
buf_cubic_x[2] = _noise_pool[(y2 * size * size + x2 * size + z3) % _noise_pool_size];
buf_cubic_x[3] = _noise_pool[(y2 * size * size + x3 * size + z3) % _noise_pool_size];
buf_cubic_y[2] = Interpolation::cubic(buf_cubic_x, xinternal);
buf_cubic_x[0] = _noise_pool[(y3 * size * size + x0 * size + z3) % _noise_pool_size];
buf_cubic_x[1] = _noise_pool[(y3 * size * size + x1 * size + z3) % _noise_pool_size];
buf_cubic_x[2] = _noise_pool[(y3 * size * size + x2 * size + z3) % _noise_pool_size];
buf_cubic_x[3] = _noise_pool[(y3 * size * size + x3 * size + z3) % _noise_pool_size];
buf_cubic_y[3] = Interpolation::cubic(buf_cubic_x, xinternal);
buf_cubic_z[3] = Interpolation::cubic(buf_cubic_y, yinternal);
return Interpolation::cubic(buf_cubic_z, zinternal) * 0.794 + 0.5;
}
/*double noiseNaiveGet4DValue(double x, double y, double z, double w)
{
}*/

View file

@ -1,30 +0,0 @@
#ifndef NOISEFUNCTIONNAIVE_H
#define NOISEFUNCTIONNAIVE_H
#include "basics_global.h"
namespace paysages {
namespace system {
class PackStream;
}
namespace basics {
class NoiseFunctionNaive
{
public:
NoiseFunctionNaive();
};
}
}
void noiseNaiveInit();
void noiseNaiveQuit();
void noiseNaiveSave(PackStream* stream);
void noiseNaiveLoad(PackStream* stream);
double noiseNaiveGet1DValue(double x);
double noiseNaiveGet2DValue(double x, double y);
double noiseNaiveGet3DValue(double x, double y, double z);
/*double noiseNaiveGet4DValue(double x, double y, double z, double w);*/
#endif // NOISEFUNCTIONNAIVE_H

View file

@ -153,7 +153,7 @@ static void _normalize3(double v[3])
v[2] = v[2] / s;
}
void noisePerlinInit(void)
static int noisePerlinInit(void)
{
int i, j, k;
@ -185,4 +185,8 @@ void noisePerlinInit(void)
for (j = 0 ; j < 3 ; j++)
g3[B + i][j] = g3[i][j];
}
return 1;
}
static int _inited = noisePerlinInit();

View file

@ -4,9 +4,6 @@
#include "basics_global.h"
namespace paysages {
namespace system {
class PackStream;
}
namespace basics {
class NoiseFunctionPerlin
@ -18,7 +15,6 @@ public:
}
}
void noisePerlinInit();
double noisePerlinGet1DValue(double x);
double noisePerlinGet2DValue(double x, double y);
double noisePerlinGet3DValue(double x, double y, double z);

View file

@ -10,10 +10,6 @@
#include <cmath>
#include <cstring>
NoiseFunctionSimplex::NoiseFunctionSimplex()
{
}
typedef struct
{
double x;
@ -123,7 +119,7 @@ static inline double _dot4(Grad4 g, double x, double y, double z, double w)
return g.x * x + g.y * y + g.z * z + g.w * w;
}
void noiseSimplexInit()
static int noiseSimplexInit()
{
int i;
@ -141,8 +137,12 @@ void noiseSimplexInit()
_G3 = 1.0 / 6.0;
_F4 = (sqrt(5.0) - 1.0) / 4.0;
_G4 = (5.0 - sqrt(5.0)) / 20.0;
return 1;
}
static int _inited = noiseSimplexInit();
double noiseSimplexGet1DValue(double x)
{
/* TODO Find custom function */

View file

@ -4,9 +4,6 @@
#include "basics_global.h"
namespace paysages {
namespace system {
class PackStream;
}
namespace basics {
class NoiseFunctionSimplex
@ -18,7 +15,6 @@ public:
}
}
void noiseSimplexInit();
double noiseSimplexGet1DValue(double x);
double noiseSimplexGet2DValue(double x, double y);
double noiseSimplexGet3DValue(double x, double y, double z);

View file

@ -1,66 +1,16 @@
#include "NoiseGenerator.h"
#include "NoiseFunctionNaive.h"
#include "NoiseFunctionPerlin.h"
#include "NoiseFunctionSimplex.h"
#include "PackStream.h"
#include "RandomGenerator.h"
#include "NoiseState.h"
#include <cmath>
#include <cstdlib>
#include <cstring>
#define MAX_LEVEL_COUNT 30
/* Global noise state */
void noiseQuit()
{
noiseNaiveQuit();
}
int noiseInit()
{
noiseSimplexInit();
noisePerlinInit();
noiseNaiveInit();
/* Noise stats */
/*NoiseGenerator* noise;
int x;
double min, max, value;
noise = noiseCreateGenerator();
noiseSetFunctionParams(noise, NOISE_FUNCTION_NAIVE, 0.0);
noiseAddLevelSimple(noise, 1.0, 0.0, 1.0);
min = 100000.0;
max = -100000.0;
for (x = 0; x < 1000000; x++)
{
value = noiseGet1DTotal(noise, toolsRandom() * 10000.0);
value = noiseGet2DTotal(noise, toolsRandom() * 10000.0, toolsRandom() * 10000.0);
value = noiseGet3DTotal(noise, toolsRandom() * 10000.0, toolsRandom() * 10000.0, toolsRandom() * 10000.0);
if (value < min) min = value;
if (value > max) max = value;
}
printf("%f %f\n", min, max);
noiseDeleteGenerator(noise);*/
atexit(noiseQuit);
return 1;
}
static int inited = noiseInit();
void noiseSave(PackStream* stream)
{
noiseNaiveSave(stream);
}
void noiseLoad(PackStream* stream)
{
noiseNaiveLoad(stream);
}
/* NoiseGenerator class */
NoiseGenerator::NoiseGenerator()
@ -98,10 +48,9 @@ void NoiseGenerator::save(PackStream* stream)
stream->write(&level->wavelength);
stream->write(&level->amplitude);
stream->write(&level->minvalue);
stream->write(&level->xoffset);
stream->write(&level->yoffset);
stream->write(&level->zoffset);
}
state.save(stream);
}
void NoiseGenerator::load(PackStream* stream)
@ -123,11 +72,10 @@ void NoiseGenerator::load(PackStream* stream)
stream->read(&level->wavelength);
stream->read(&level->amplitude);
stream->read(&level->minvalue);
stream->read(&level->xoffset);
stream->read(&level->yoffset);
stream->read(&level->zoffset);
}
state.load(stream);
validate();
}
@ -139,6 +87,8 @@ void NoiseGenerator::copy(NoiseGenerator* destination)
memcpy(destination->levels, levels, sizeof(NoiseLevel) * destination->level_count);
state.copy(&destination->state);
validate();
}
@ -146,26 +96,21 @@ void NoiseGenerator::validate()
{
int x;
if (function.algorithm < 0 || function.algorithm > NOISE_FUNCTION_NAIVE)
if (function.algorithm < 0 || function.algorithm > NOISE_FUNCTION_SIMPLEX)
{
function.algorithm = NOISE_FUNCTION_SIMPLEX;
}
switch (function.algorithm)
{
case NOISE_FUNCTION_SIMPLEX:
_func_noise_1d = noiseSimplexGet1DValue;
_func_noise_2d = noiseSimplexGet2DValue;
_func_noise_3d = noiseSimplexGet3DValue;
break;
case NOISE_FUNCTION_PERLIN:
_func_noise_1d = noisePerlinGet1DValue;
_func_noise_2d = noisePerlinGet2DValue;
_func_noise_3d = noisePerlinGet3DValue;
break;
case NOISE_FUNCTION_NAIVE:
_func_noise_1d = noiseNaiveGet1DValue;
_func_noise_2d = noiseNaiveGet2DValue;
_func_noise_3d = noiseNaiveGet3DValue;
case NOISE_FUNCTION_SIMPLEX:
_func_noise_1d = noiseSimplexGet1DValue;
_func_noise_2d = noiseSimplexGet2DValue;
_func_noise_3d = noiseSimplexGet3DValue;
break;
}
@ -195,18 +140,17 @@ void NoiseGenerator::validate()
}
}
void NoiseGenerator::randomizeOffsets()
void NoiseGenerator::setState(const NoiseState &state)
{
int i;
for (i = 0; i < MAX_LEVEL_COUNT; i++)
{
levels[i].xoffset = RandomGenerator::random();
levels[i].yoffset = RandomGenerator::random();
levels[i].zoffset = RandomGenerator::random();
}
state.copy(&this->state);
}
NoiseFunction NoiseGenerator::getFunction()
void NoiseGenerator::randomizeOffsets()
{
state.randomizeOffsets();
}
NoiseGenerator::NoiseFunction NoiseGenerator::getFunction()
{
return function;
}
@ -254,19 +198,10 @@ void NoiseGenerator::clearLevels()
validate();
}
void NoiseGenerator::addLevel(NoiseLevel level, int protect_offsets)
void NoiseGenerator::addLevel(NoiseLevel level)
{
if (level_count < MAX_LEVEL_COUNT)
{
NoiseLevel baselevel = levels[level_count];
if (protect_offsets)
{
level.xoffset = baselevel.xoffset;
level.yoffset = baselevel.yoffset;
level.zoffset = baselevel.zoffset;
}
levels[level_count] = level;
level_count++;
validate();
@ -281,7 +216,7 @@ void NoiseGenerator::addLevelSimple(double scaling, double minvalue, double maxv
level.minvalue = minvalue;
level.amplitude = maxvalue - minvalue;
addLevel(level, 1);
addLevel(level);
}
void NoiseGenerator::addLevels(int level_count, NoiseLevel start_level, double scaling_factor, double amplitude_factor, double center_factor)
@ -290,7 +225,7 @@ void NoiseGenerator::addLevels(int level_count, NoiseLevel start_level, double s
for (i = 0; i < level_count; i++)
{
addLevel(start_level, 1);
addLevel(start_level);
start_level.minvalue += start_level.amplitude * (1.0 - amplitude_factor) * center_factor;
start_level.wavelength *= scaling_factor;
start_level.amplitude *= amplitude_factor;
@ -333,19 +268,10 @@ int NoiseGenerator::getLevel(int level, NoiseLevel* params)
}
}
void NoiseGenerator::setLevel(int index, NoiseLevel level, int protect_offsets)
void NoiseGenerator::setLevel(int index, NoiseLevel level)
{
if (index >= 0 && index < level_count)
{
NoiseLevel baselevel = levels[index];
if (protect_offsets)
{
level.xoffset = baselevel.xoffset;
level.yoffset = baselevel.yoffset;
level.zoffset = baselevel.zoffset;
}
levels[index] = level;
validate();
}
@ -359,7 +285,7 @@ void NoiseGenerator::setLevelSimple(int index, double scaling, double minvalue,
level.minvalue = minvalue;
level.amplitude = maxvalue - minvalue;
setLevel(index, level, 1);
setLevel(index, level);
}
void NoiseGenerator::normalizeAmplitude(double minvalue, double maxvalue, int adjust_scaling)
@ -440,16 +366,16 @@ static inline double _fixValue(double value, double ridge, double curve)
inline double NoiseGenerator::_get1DLevelValue(NoiseLevel* level, double x)
inline double NoiseGenerator::_get1DLevelValue(NoiseLevel* level, const NoiseState::NoiseOffset &offset, double x)
{
return level->minvalue + _fixValue(_func_noise_1d(x / level->wavelength + level->xoffset), function.ridge_factor, function.curve_factor) * level->amplitude;
return level->minvalue + _fixValue(_func_noise_1d(x / level->wavelength + offset.x), function.ridge_factor, function.curve_factor) * level->amplitude;
}
double NoiseGenerator::get1DLevel(int level, double x)
{
if (level >= 0 && level < level_count)
{
return _get1DLevelValue(levels + level, x);
return _get1DLevelValue(levels + level, state.level_offsets[level], x);
}
else
{
@ -465,7 +391,7 @@ double NoiseGenerator::get1DTotal(double x)
result = 0.0;
for (level = 0; level < level_count; level++)
{
result += _get1DLevelValue(levels + level, x);
result += _get1DLevelValue(levels + level, state.level_offsets[level], x);
}
return result + height_offset;
}
@ -489,7 +415,7 @@ double NoiseGenerator::get1DDetail(double x, double detail)
factor = (detail * 0.5 - height) / 0.25;
}
result += _get1DLevelValue(levels + level, x) * factor;
result += _get1DLevelValue(levels + level, state.level_offsets[level], x) * factor;
}
return result + height_offset;
}
@ -497,16 +423,16 @@ double NoiseGenerator::get1DDetail(double x, double detail)
inline double NoiseGenerator::_get2DLevelValue(NoiseLevel* level, double x, double y)
inline double NoiseGenerator::_get2DLevelValue(NoiseLevel* level, const NoiseState::NoiseOffset &offset, double x, double y)
{
return level->minvalue + _fixValue(_func_noise_2d(x / level->wavelength + level->xoffset, y / level->wavelength + level->yoffset), function.ridge_factor, function.curve_factor) * level->amplitude;
return level->minvalue + _fixValue(_func_noise_2d(x / level->wavelength + offset.x, y / level->wavelength + offset.y), function.ridge_factor, function.curve_factor) * level->amplitude;
}
double NoiseGenerator::get2DLevel(int level, double x, double y)
{
if (level >= 0 && level < level_count)
{
return _get2DLevelValue(levels + level, x, y);
return _get2DLevelValue(levels + level, state.level_offsets[level], x, y);
}
else
{
@ -522,7 +448,7 @@ double NoiseGenerator::get2DTotal(double x, double y)
result = 0.0;
for (level = 0; level < level_count; level++)
{
result += _get2DLevelValue(levels + level, x, y);
result += _get2DLevelValue(levels + level, state.level_offsets[level], x, y);
}
return result + height_offset;
}
@ -546,7 +472,7 @@ double NoiseGenerator::get2DDetail(double x, double y, double detail)
factor = (detail * 0.5 - height) / 0.25;
}
result += _get2DLevelValue(levels + level, x, y) * factor;
result += _get2DLevelValue(levels + level, state.level_offsets[level], x, y) * factor;
}
return result + height_offset;
}
@ -554,16 +480,16 @@ double NoiseGenerator::get2DDetail(double x, double y, double detail)
inline double NoiseGenerator::_get3DLevelValue(NoiseLevel* level, double x, double y, double z)
inline double NoiseGenerator::_get3DLevelValue(NoiseLevel* level, const NoiseState::NoiseOffset &offset, double x, double y, double z)
{
return level->minvalue + _fixValue(_func_noise_3d(x / level->wavelength + level->xoffset, y / level->wavelength + level->yoffset, z / level->wavelength + level->zoffset), function.ridge_factor, function.curve_factor) * level->amplitude;
return level->minvalue + _fixValue(_func_noise_3d(x / level->wavelength + offset.x, y / level->wavelength + offset.y, z / level->wavelength + offset.z), function.ridge_factor, function.curve_factor) * level->amplitude;
}
double NoiseGenerator::get3DLevel(int level, double x, double y, double z)
{
if (level >= 0 && level < level_count)
{
return _get3DLevelValue(levels + level, x, y, z);
return _get3DLevelValue(levels + level, state.level_offsets[level], x, y, z);
}
else
{
@ -579,7 +505,7 @@ double NoiseGenerator::get3DTotal(double x, double y, double z)
result = 0.0;
for (level = 0; level < level_count; level++)
{
result += _get3DLevelValue(levels + level, x, y, z);
result += _get3DLevelValue(levels + level, state.level_offsets[level], x, y, z);
}
return result + height_offset;
}
@ -603,7 +529,7 @@ double NoiseGenerator::get3DDetail(double x, double y, double z, double detail)
factor = (detail * 0.5 - height) / 0.25;
}
result += _get3DLevelValue(levels + level, x, y, z) * factor;
result += _get3DLevelValue(levels + level, state.level_offsets[level], x, y, z) * factor;
}
return result + height_offset;
}

View file

@ -4,37 +4,34 @@
#include "basics_global.h"
#define MAX_LEVEL_COUNT 30
typedef enum
{
NOISE_FUNCTION_SIMPLEX,
NOISE_FUNCTION_PERLIN,
NOISE_FUNCTION_NAIVE
} NoiseFunctionAlgorithm;
typedef struct
{
NoiseFunctionAlgorithm algorithm;
double ridge_factor; /* -0.5;0.5 */
double curve_factor; /* -1.0;1.0 */
} NoiseFunction;
typedef struct
{
double wavelength;
double amplitude;
double minvalue;
double xoffset;
double yoffset;
double zoffset;
} NoiseLevel;
#include "NoiseState.h"
namespace paysages {
namespace system {class PackStream;}
namespace basics {
class BASICSSHARED_EXPORT NoiseGenerator
{
public:
typedef enum
{
NOISE_FUNCTION_PERLIN,
NOISE_FUNCTION_SIMPLEX
} NoiseFunctionAlgorithm;
typedef struct
{
NoiseFunctionAlgorithm algorithm;
double ridge_factor; /* -0.5;0.5 */
double curve_factor; /* -1.0;1.0 */
} NoiseFunction;
typedef struct
{
double wavelength;
double amplitude;
double minvalue;
} NoiseLevel;
public:
NoiseGenerator();
virtual ~NoiseGenerator();
@ -44,6 +41,9 @@ public:
virtual void copy(NoiseGenerator* destination);
virtual void validate();
inline const NoiseState &getState() const {return state;}
void setState(const NoiseState &state);
void randomizeOffsets();
NoiseFunction getFunction();
void setCustomFunction(double (*func1d)(double x), double (*func2d)(double x, double y), double (*func3d)(double x, double y, double z));
@ -53,13 +53,13 @@ public:
void getRange(double* minvalue, double* maxvalue);
int getLevelCount();
void clearLevels();
void addLevel(NoiseLevel level, int protect_offsets);
void addLevel(NoiseLevel level);
void addLevelSimple(double scaling, double minvalue, double maxvalue);
void addLevels(int level_count, NoiseLevel start_level, double scaling_factor, double amplitude_factor, double center_factor);
void addLevelsSimple(int level_count, double scaling, double minvalue, double maxvalue, double center_factor);
void removeLevel(int level);
int getLevel(int level, NoiseLevel* params);
void setLevel(int index, NoiseLevel level, int protect_offsets);
void setLevel(int index, NoiseLevel level);
void setLevelSimple(int index, double scaling, double minvalue, double maxvalue);
void normalizeAmplitude(double minvalue, double maxvalue, int adjust_scaling);
double get1DLevel(int level, double x);
@ -73,15 +73,17 @@ public:
double get3DDetail(double x, double y, double z, double detail);
private:
double _get1DLevelValue(NoiseLevel* level, double x);
double _get2DLevelValue(NoiseLevel* level, double x, double y);
double _get3DLevelValue(NoiseLevel* level, double x, double y, double z);
double _get1DLevelValue(NoiseLevel* level, const NoiseState::NoiseOffset &offset, double x);
double _get2DLevelValue(NoiseLevel* level, const NoiseState::NoiseOffset &offset, double x, double y);
double _get3DLevelValue(NoiseLevel* level, const NoiseState::NoiseOffset &offset, double x, double y, double z);
NoiseFunction function;
double height_offset;
int level_count;
NoiseLevel levels[MAX_LEVEL_COUNT];
NoiseState state;
double _min_value;
double _max_value;
double (*_func_noise_1d)(double x);
@ -92,7 +94,4 @@ private:
}
}
BASICSSHARED_EXPORT void noiseSave(PackStream* stream);
BASICSSHARED_EXPORT void noiseLoad(PackStream* stream);
#endif // NOISEGENERATOR_H

55
src/basics/NoiseState.cpp Normal file
View file

@ -0,0 +1,55 @@
#include "NoiseState.h"
#include "PackStream.h"
#include "RandomGenerator.h"
NoiseState::NoiseState()
{
for (int i = 0; i < 30; i++)
{
level_offsets.push_back(NoiseOffset());
}
randomizeOffsets();
}
void NoiseState::save(PackStream *stream) const
{
int levels = level_offsets.size();
stream->write(&levels);
for (const auto &level_offset:level_offsets)
{
stream->write(&level_offset.x);
stream->write(&level_offset.y);
stream->write(&level_offset.z);
}
}
void NoiseState::load(PackStream *stream)
{
int levels;
stream->read(&levels);
level_offsets.clear();
for (int i = 0; i < levels; i++)
{
NoiseOffset level_offset;
stream->read(&level_offset.x);
stream->read(&level_offset.y);
stream->read(&level_offset.z);
level_offsets.push_back(level_offset);
}
}
void NoiseState::copy(NoiseState *destination) const
{
destination->level_offsets = level_offsets;
}
void NoiseState::randomizeOffsets()
{
for (auto &level_offset:level_offsets)
{
level_offset.x = RandomGenerator::random();
level_offset.y = RandomGenerator::random();
level_offset.z = RandomGenerator::random();
}
}

41
src/basics/NoiseState.h Normal file
View file

@ -0,0 +1,41 @@
#ifndef NOISESTATE_H
#define NOISESTATE_H
#include "basics_global.h"
namespace paysages {
namespace basics {
/*!
* Fractal noise state, that can be saved to a file.
*
* This state contains the noise offsets for noise layers.
*/
class BASICSSHARED_EXPORT NoiseState
{
public:
typedef struct {
double x;
double y;
double z;
} NoiseOffset;
public:
NoiseState();
void save(PackStream* stream) const;
void load(PackStream* stream);
void copy(NoiseState* destination) const;
void randomizeOffsets();
private:
std::vector<NoiseOffset> level_offsets;
friend class NoiseGenerator;
};
}
}
#endif // NOISESTATE_H

View file

@ -15,7 +15,6 @@ include(../common.pri)
SOURCES += \
NoiseGenerator.cpp \
NoiseFunctionNaive.cpp \
NoiseFunctionPerlin.cpp \
NoiseFunctionSimplex.cpp \
Interpolation.cpp \
@ -32,12 +31,12 @@ SOURCES += \
Geometry.cpp \
Texture2D.cpp \
Texture3D.cpp \
Texture4D.cpp
Texture4D.cpp \
NoiseState.cpp
HEADERS +=\
basics_global.h \
NoiseGenerator.h \
NoiseFunctionNaive.h \
NoiseFunctionPerlin.h \
NoiseFunctionSimplex.h \
Interpolation.h \
@ -52,7 +51,8 @@ HEADERS +=\
Geometry.h \
Texture2D.h \
Texture3D.h \
Texture4D.h
Texture4D.h \
NoiseState.h
unix:!symbian {
maemo5 {

View file

@ -18,6 +18,7 @@ namespace basics {
class SpaceSegment;
class Color;
class NoiseGenerator;
class NoiseState;
class Curve;
class ColorProfile;
class Texture2D;

View file

@ -42,6 +42,8 @@ void CloudLayerDefinition::save(PackStream* stream) const
stream->write(&altitude);
stream->write(&scaling);
stream->write(&coverage);
noise_state.save(stream);
}
void CloudLayerDefinition::load(PackStream* stream)
@ -56,6 +58,8 @@ void CloudLayerDefinition::load(PackStream* stream)
stream->read(&scaling);
stream->read(&coverage);
noise_state.load(stream);
validate();
}
@ -69,6 +73,8 @@ void CloudLayerDefinition::copy(BaseDefinition* _destination) const
destination->altitude = altitude;
destination->scaling = scaling;
destination->coverage = coverage;
noise_state.copy(&destination->noise_state);
}
void CloudLayerDefinition::validate()

View file

@ -5,6 +5,8 @@
#include "BaseDefinition.h"
#include "NoiseState.h"
namespace paysages {
namespace definition {
@ -14,6 +16,8 @@ public:
CloudLayerDefinition(BaseDefinition* parent);
virtual ~CloudLayerDefinition();
inline const NoiseState &getNoiseState() const {return noise_state;}
static CloudLayerDefinition* newCopy(const CloudLayerDefinition& other, BaseDefinition* parent);
CloudLayerDefinition* newCopy(BaseDefinition* parent) const;
@ -40,6 +44,7 @@ public:
public:
CloudsType type;
NoiseState noise_state;
double altitude;
double scaling;
double coverage;

View file

@ -3,7 +3,6 @@
#include <ctime>
#include <map>
#include "NoiseGenerator.h"
#include "PackStream.h"
#include "AtmosphereDefinition.h"
#include "CameraDefinition.h"
@ -26,22 +25,6 @@ Scenery::Scenery():
addChild(water = new WaterDefinition(this));
}
void Scenery::save(PackStream* stream) const
{
BaseDefinition::save(stream);
noiseSave(stream);
}
void Scenery::load(PackStream* stream)
{
BaseDefinition::load(stream);
noiseLoad(stream);
validate();
}
void Scenery::copy(BaseDefinition *destination_) const
{
Scenery* destination = (Scenery*)destination_;

View file

@ -28,9 +28,6 @@ public:
public:
Scenery();
virtual void save(PackStream* stream) const override;
virtual void load(PackStream* stream) override;
virtual void validate() override;
virtual void copy(BaseDefinition *destination) const override;

View file

@ -148,7 +148,7 @@ void TerrainDefinition::applyPreset(TerrainPreset preset)
_height_noise->addLevelSimple(pow(2.0, resolution + 1), -1.0, 1.0);
_height_noise->addLevelsSimple(resolution - 2, pow(2.0, resolution - 1), -0.7, 0.7, 0.5);
_height_noise->normalizeAmplitude(-1.0, 1.0, 0);
_height_noise->setFunctionParams(NOISE_FUNCTION_SIMPLEX, 0.0, 0.0);
_height_noise->setFunctionParams(NoiseGenerator::NOISE_FUNCTION_SIMPLEX, 0.0, 0.0);
scaling = 1.0;
height = 30.0;
shadow_smoothing = 0.03;

View file

@ -113,7 +113,7 @@ void WaterDefinition::validate()
{
_waves_noise->addLevelsSimple(3, scaling * 0.1, -detail_height * scaling * 0.015, detail_height * scaling * 0.015, 0.5);
}
_waves_noise->setFunctionParams(NOISE_FUNCTION_SIMPLEX, -turbulence, 0.0);
_waves_noise->setFunctionParams(NoiseGenerator::NOISE_FUNCTION_SIMPLEX, -turbulence, 0.0);
_waves_noise->validate();
material->validate();

View file

@ -245,7 +245,7 @@ void DialogNoise::revertToCurrent()
{
int i, n;
int selected;
NoiseFunction function;
NoiseGenerator::NoiseFunction function;
selected = levels->currentRow();
@ -279,12 +279,12 @@ void DialogNoise::revertToCurrent()
void DialogNoise::addLevel()
{
NoiseLevel level;
NoiseGenerator::NoiseLevel level;
level.amplitude = 0.1;
level.wavelength = 0.1;
_current->addLevel(level, 1);
_current->addLevel(level);
revertToCurrent();
@ -310,9 +310,9 @@ void DialogNoise::removeLevel()
void DialogNoise::functionChanged()
{
NoiseFunction function;
NoiseGenerator::NoiseFunction function;
function.algorithm = (NoiseFunctionAlgorithm)function_algo->currentIndex();
function.algorithm = (NoiseGenerator::NoiseFunctionAlgorithm)function_algo->currentIndex();
function.ridge_factor = (double)function_ridge->value() * 0.05;
_current->setFunction(&function);
@ -338,7 +338,7 @@ void DialogNoise::levelChanged(int row)
void DialogNoise::heightChanged(int value)
{
_current_level_params.amplitude = ((double)value) / 1000.0;
_current->setLevel(_current_level, _current_level_params, 1);
_current->setLevel(_current_level, _current_level_params);
previewLevel->redraw();
previewTotal->redraw();
}
@ -346,7 +346,7 @@ void DialogNoise::heightChanged(int value)
void DialogNoise::scalingChanged(int value)
{
_current_level_params.wavelength = ((double)value) / 1000.0;
_current->setLevel(_current_level, _current_level_params, 1);
_current->setLevel(_current_level, _current_level_params);
previewLevel->redraw();
previewTotal->redraw();
}

View file

@ -39,7 +39,7 @@ private:
NoiseGenerator* _base;
NoiseGenerator* _current;
int _current_level;
NoiseLevel _current_level_params;
NoiseGenerator::NoiseLevel _current_level_params;
BasePreview* previewLevel;
BasePreview* previewTotal;
QComboBox* function_algo;

View file

@ -70,32 +70,6 @@ void OpenGLSkybox::render()
program->drawTriangleStrip(vertices, 14);
}
void OpenGLSkybox::alterDayTime(double delta)
{
#if 0
Scenery* scenery = renderer->getScenery();
AtmosphereDefinition* definition = scenery->getAtmosphere()->definition;
daytime = fmod(daytime + delta * 0.001, 1.0);
// TEMP
if (daytime > 0.8)
{
daytime -= 0.6;
}
if (daytime < 0.2)
{
daytime += 0.6;
}
definition->hour = (int)(daytime * 24.0);
definition->minute = (int)((daytime - (((double)definition->hour) / 24.0)) * 1440.0);
AtmosphereDefinitionClass.validate(definition);
// TODO Update only the sun
updateScenery(scenery, true);
#endif
}
void OpenGLSkybox::setVertex(int i, float x, float y, float z)
{
vertices[i * 3] = x;

View file

@ -18,8 +18,6 @@ public:
virtual void update() override;
virtual void render() override;
void alterDayTime(double delta);
private:
void setVertex(int i, float x, float y, float z);

View file

@ -33,6 +33,7 @@ void CloudModelStratoCumulus::update()
noise->addLevelSimple(1.0 / 800.0, -0.003, 0.003);
noise->addLevelSimple(1.0 / 1000.0, -0.0015, 0.0015);
noise->normalizeAmplitude(-3.0, 3.0, 0);
noise->setState(layer->getNoiseState());
}
void CloudModelStratoCumulus::getAltitudeRange(double *min_altitude, double *max_altitude) const

View file

@ -31,8 +31,8 @@ protected:
terrain->height = 3.0;
terrain->scaling = 1.0;
terrain->_height_noise->clearLevels();
NoiseLevel level = {1.0, 2.0, -1.0, 0.0, 0.0, 0.0};
terrain->_height_noise->addLevel(level, 0);
NoiseGenerator::NoiseLevel level = {1.0, 2.0, -1.0};
terrain->_height_noise->addLevel(level);
terrain->_height_noise->setCustomFunction(_noise1dMock, _noise2dMock, _noise3dMock);
}