paysages : Added naive noise function.

git-svn-id: https://subversion.assembla.com/svn/thunderk/paysages@426 b1fd45b6-86a6-48da-8261-f70d1f35bdcc
This commit is contained in:
Michaël Lemaire 2012-08-28 21:13:35 +00:00 committed by ThunderK
parent 163cca53a9
commit e16dea50eb
8 changed files with 430 additions and 30 deletions

1
TODO
View file

@ -2,7 +2,6 @@ Technology Preview 2 :
- Fully move layer management from BaseForm to BaseFormLayer.
- Replace math.h methods by optimized ones (fastfloor, fastsin...).
- Reimplement perlin noise and custom noise.
- Add ridged noise option (with configurable ridge offset and direction).
- Replace terrain canvas editor by full sculpting editor.
=> Add a generation dialog, with fixed resolution.
=> Store local terrain modifications in fully dynamic canvas.

View file

@ -6,6 +6,7 @@
#include "tools.h"
#include "noisesimplex.h"
#include "noisenaive.h"
#define MAX_LEVEL_COUNT 30
@ -27,20 +28,22 @@ struct NoiseGenerator
void noiseInit()
{
noiseSimplexInit();
noiseNaiveInit();
}
void noiseQuit()
{
noiseNaiveQuit();
}
void noiseSave(PackStream* stream)
{
UNUSED(stream);
noiseNaiveSave(stream);
}
void noiseLoad(PackStream* stream)
{
UNUSED(stream);
noiseNaiveLoad(stream);
}
NoiseGenerator* noiseCreateGenerator()
@ -144,6 +147,9 @@ void noiseValidate(NoiseGenerator* generator)
break;
case NOISE_FUNCTION_NAIVE:
/* TODO */
generator->_func_noise_1d = noiseNaiveGet1DValue;
generator->_func_noise_2d = noiseNaiveGet2DValue;
generator->_func_noise_3d = noiseNaiveGet3DValue;
break;
}

366
lib_paysages/noisenaive.c Normal file
View file

@ -0,0 +1,366 @@
#include "noisenaive.h"
/*
* Naive noise implementation, based on pseudo-random grids.
*/
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "tools.h"
static int _noise_pool_size;
static double* _noise_pool;
void noiseNaiveInit()
{
int i;
_noise_pool_size = 1048576;
_noise_pool = malloc(sizeof(double) * _noise_pool_size);
for (i = 0; i < _noise_pool_size; i++)
{
_noise_pool[i] = toolsRandom() - 0.5;
}
}
void noiseNaiveQuit()
{
free(_noise_pool);
}
void noiseNaiveSave(PackStream* stream)
{
int i;
packWriteInt(stream, &_noise_pool_size);
for (i = 0; i < _noise_pool_size; i++)
{
packWriteDouble(stream, _noise_pool + i);
}
}
void noiseNaiveLoad(PackStream* stream)
{
int i;
packReadInt(stream, &_noise_pool_size);
_noise_pool = realloc(_noise_pool, sizeof(double) * _noise_pool_size);
for (i = 0; i < _noise_pool_size; i++)
{
packReadDouble(stream, _noise_pool + i);
}
}
double noiseNaiveGet1DValue(double x)
{
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 toolsCubicInterpolate(buf_cubic_x, xinternal);
}
double noiseNaiveGet2DValue(double x, double y)
{
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] = toolsCubicInterpolate(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] = toolsCubicInterpolate(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] = toolsCubicInterpolate(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] = toolsCubicInterpolate(buf_cubic_x, xinternal);
return toolsCubicInterpolate(buf_cubic_y, yinternal);
}
double noiseNaiveGet3DValue(double x, double y, double z)
{
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] = toolsCubicInterpolate(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] = toolsCubicInterpolate(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] = toolsCubicInterpolate(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] = toolsCubicInterpolate(buf_cubic_x, xinternal);
buf_cubic_z[0] = toolsCubicInterpolate(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] = toolsCubicInterpolate(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] = toolsCubicInterpolate(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] = toolsCubicInterpolate(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] = toolsCubicInterpolate(buf_cubic_x, xinternal);
buf_cubic_z[1] = toolsCubicInterpolate(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] = toolsCubicInterpolate(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] = toolsCubicInterpolate(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] = toolsCubicInterpolate(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] = toolsCubicInterpolate(buf_cubic_x, xinternal);
buf_cubic_z[2] = toolsCubicInterpolate(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] = toolsCubicInterpolate(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] = toolsCubicInterpolate(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] = toolsCubicInterpolate(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] = toolsCubicInterpolate(buf_cubic_x, xinternal);
buf_cubic_z[3] = toolsCubicInterpolate(buf_cubic_y, yinternal);
return toolsCubicInterpolate(buf_cubic_z, zinternal);
}
/*double noiseNaiveGet4DValue(double x, double y, double z, double w)
{
}*/

23
lib_paysages/noisenaive.h Normal file
View file

@ -0,0 +1,23 @@
#ifndef _PAYSAGES_NOISENAIVE_H_
#define _PAYSAGES_NOISENAIVE_H_
#include "pack.h"
#ifdef __cplusplus
extern "C" {
#endif
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);*/
#ifdef __cplusplus
}
#endif
#endif

View file

@ -139,24 +139,24 @@ void noiseSimplexInit()
_G4 = (5.0 - sqrt(5.0)) / 20.0;
}
double noiseSimplexGet1DValue(double xin)
double noiseSimplexGet1DValue(double x)
{
/* TODO Find custom function */
return noiseSimplexGet2DValue(xin, 0.0);
return noiseSimplexGet2DValue(x, 0.0);
}
double noiseSimplexGet2DValue(double xin, double yin)
double noiseSimplexGet2DValue(double x, double y)
{
double n0, n1, n2; /* Noise contributions from the three corners */
/* Skew the input space to determine which simplex cell we're in */
double s = (xin + yin) * _F2; /* Hairy factor for 2D */
int i = _fastfloor(xin + s);
int j = _fastfloor(yin + s);
double s = (x + y) * _F2; /* Hairy factor for 2D */
int i = _fastfloor(x + s);
int j = _fastfloor(y + s);
double t = (i + j) * _G2;
double X0 = i - t; /* Unskew the cell origin back to (x,y) space */
double Y0 = j - t;
double x0 = xin - X0; /* The x,y distances from the cell origin */
double y0 = yin - Y0;
double x0 = x - X0; /* The x,y distances from the cell origin */
double y0 = y - Y0;
/* For the 2D case, the simplex shape is an equilateral triangle.
Determine which simplex we are in. */
int i1, j1; /* Offsets for second (middle) corner of simplex in (i,j) coords */
@ -210,21 +210,21 @@ double noiseSimplexGet2DValue(double xin, double yin)
return 35.0 * (n0 + n1 + n2);
}
double noiseSimplexGet3DValue(double xin, double yin, double zin)
double noiseSimplexGet3DValue(double x, double y, double z)
{
double n0, n1, n2, n3; /* Noise contributions from the four corners */
/* Skew the input space to determine which simplex cell we're in */
double s = (xin + yin + zin) * _F3; /* Very nice and simple skew factor for 3D */
int i = _fastfloor(xin + s);
int j = _fastfloor(yin + s);
int k = _fastfloor(zin + s);
double s = (x + y + z) * _F3; /* Very nice and simple skew factor for 3D */
int i = _fastfloor(x + s);
int j = _fastfloor(y + s);
int k = _fastfloor(z + s);
double t = (i + j + k) * _G3;
double X0 = i - t; /* Unskew the cell origin back to (x,y,z) space */
double Y0 = j - t;
double Z0 = k - t;
double x0 = xin - X0; /* The x,y,z distances from the cell origin */
double y0 = yin - Y0;
double z0 = zin - Z0;
double x0 = x - X0; /* The x,y,z distances from the cell origin */
double y0 = y - Y0;
double z0 = z - Z0;
/* For the 3D case, the simplex shape is a slightly irregular tetrahedron.
Determine which simplex we are in. */
int i1, j1, k1; /* Offsets for second corner of simplex in (i,j,k) coords */

View file

@ -1,14 +1,14 @@
#ifndef _PAYSAGES_SIMPLEXNOISE_H_
#define _PAYSAGES_SIMPLEXNOISE_H_
#ifndef _PAYSAGES_NOISESIMPLEX_H_
#define _PAYSAGES_NOISESIMPLEX_H_
#ifdef __cplusplus
extern "C" {
#endif
void noiseSimplexInit();
double noiseSimplexGet1DValue(double xin);
double noiseSimplexGet2DValue(double xin, double yin);
double noiseSimplexGet3DValue(double xin, double yin, double zin);
double noiseSimplexGet1DValue(double x);
double noiseSimplexGet2DValue(double x, double y);
double noiseSimplexGet3DValue(double x, double y, double z);
double noiseSimplexGet4DValue(double x, double y, double z, double w);
#ifdef __cplusplus

View file

@ -13,21 +13,26 @@ double toolsRandom()
return ((double)rand()) / (double)RAND_MAX;
}
static inline double __cubicInterpolate(double p[4], double x)
static inline double _cubicInterpolate(double p[4], double x)
{
return p[1] + 0.5 * x * (p[2] - p[0] + x * (2.0 * p[0] - 5.0 * p[1] + 4.0 * p[2] - p[3] + x * (3.0 * (p[1] - p[2]) + p[3] - p[0])));
}
double toolsCubicInterpolate(double stencil[4], double x)
{
return _cubicInterpolate(stencil, x);
}
double toolsBicubicInterpolate(double stencil[16], double x, double y)
{
double buf_cubic_y[4];
buf_cubic_y[0] = __cubicInterpolate(stencil, x);
buf_cubic_y[1] = __cubicInterpolate(stencil + 4, x);
buf_cubic_y[2] = __cubicInterpolate(stencil + 8, x);
buf_cubic_y[3] = __cubicInterpolate(stencil + 12, x);
buf_cubic_y[0] = _cubicInterpolate(stencil, x);
buf_cubic_y[1] = _cubicInterpolate(stencil + 4, x);
buf_cubic_y[2] = _cubicInterpolate(stencil + 8, x);
buf_cubic_y[3] = _cubicInterpolate(stencil + 12, x);
return __cubicInterpolate(buf_cubic_y, y);
return _cubicInterpolate(buf_cubic_y, y);
}
void toolsFloat2DMapCopy(double* src, double* dest, int src_xstart, int src_ystart, int dest_xstart, int dest_ystart, int xsize, int ysize, int src_xstep, int src_ystep, int dest_xstep, int dest_ystep)

View file

@ -11,6 +11,7 @@ extern "C" {
#define UNUSED(_x_) ((void)(_x_))
double toolsRandom();
double toolsCubicInterpolate(double stencil[4], double x);
double toolsBicubicInterpolate(double stencil[16], double x, double y);
void toolsFloat2DMapCopy(double* src, double* dest, int src_xstart, int src_ystart, int dest_xstart, int dest_ystart, int xsize, int ysize, int src_xstep, int src_ystep, int dest_xstep, int dest_ystep);
Vector3 toolsGetNormalFromTriangle(Vector3 center, Vector3 bottom, Vector3 right);