bc0cb70b13
Developer: Roman Shuvalov git-svn-id: svn://kolibrios.org@5235 a494cfbc-eb01-0410-851d-a64ba20cac60
176 lines
5.1 KiB
C
176 lines
5.1 KiB
C
#include "rsnoise.h"
|
|
|
|
#include "rsgame.h"
|
|
|
|
#ifdef RS_USE_C_LIBS
|
|
#include <string.h>
|
|
#include <math.h>
|
|
#else
|
|
#include "rs/rsplatform.h"
|
|
#endif
|
|
|
|
rs_perlin_conf_t rs_perlin_conf;
|
|
|
|
void rs_perlin_configure(float freq, int octaves, float persistence, float seed, int tex_size) {
|
|
rs_perlin_conf.freq = freq;
|
|
rs_perlin_conf.octaves = octaves;
|
|
rs_perlin_conf.persistence = persistence;
|
|
rs_perlin_conf.seed = seed;
|
|
rs_perlin_conf.tex_size = tex_size;
|
|
rs_perlin_conf.period = (int) (0.1 + roundf(freq) ); // *tex_size
|
|
};
|
|
|
|
float rs_noise(int x, int y) {
|
|
// from here, http://www.cplusplus.com/forum/general/85758/
|
|
// koef. changed
|
|
int n = x + y * 57 * 5; // no *2
|
|
n = (n << 13) ^ n;
|
|
int t = (n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff;
|
|
return 1.0 - ((float)t) * 0.931322574615478515625e-9;/// 1073741824.0);
|
|
}
|
|
|
|
float rs_noise_for_perlin(int x, int y) {
|
|
|
|
x %= rs_perlin_conf.period;
|
|
y %= rs_perlin_conf.period;
|
|
|
|
// from here, http://www.cplusplus.com/forum/general/85758/
|
|
// koef. changed
|
|
int n = x + y * 57 * 5; // no *2
|
|
n = (n << 13) ^ n;
|
|
int t = (n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff;
|
|
return 1.0 - ((float)t) * 0.931322574615478515625e-9;/// 1073741824.0);
|
|
}
|
|
|
|
//float rs_noise_periodical(int x, int y, int period) {
|
|
//
|
|
// x %= period;
|
|
// y %= period;
|
|
//
|
|
// // from here, http://www.cplusplus.com/forum/general/85758/
|
|
// // koef. changed
|
|
// int n = x + y * 57 * 5; // no *2
|
|
// n = (n << 13) ^ n;
|
|
// int t = (n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff;
|
|
// return 1.0 - ((float)t) * 0.931322574615478515625e-9;/// 1073741824.0);
|
|
//}
|
|
|
|
float rs_interpolate(float x, float y, float a) {
|
|
float negA = 1.0 - a;
|
|
float negASqr = negA * negA;
|
|
float fac1 = 3.0 * (negASqr) - 2.0 * (negASqr * negA);
|
|
float aSqr = a * a;
|
|
float fac2 = 3.0 * aSqr - 2.0 * (aSqr * a);
|
|
|
|
return x * fac1 + y * fac2; //add the weighted factors
|
|
}
|
|
|
|
float rs_perlin_noise(float x, float y) {
|
|
|
|
// while (x > rs_perlin_conf.tile_period) {
|
|
// x -= rs_perlin_conf.tile_period;
|
|
// };
|
|
//
|
|
// while (y > rs_perlin_conf.tile_period) {
|
|
// y -= rs_perlin_conf.tile_period;
|
|
// };
|
|
|
|
int Xint = (int)x;
|
|
int Yint = (int)y;
|
|
float Xfrac = x - Xint;
|
|
float Yfrac = y - Yint;
|
|
|
|
|
|
//noise values
|
|
float n01= rs_noise_for_perlin(Xint-1, Yint-1);
|
|
float n02= rs_noise_for_perlin(Xint+1, Yint-1);
|
|
float n03= rs_noise_for_perlin(Xint-1, Yint+1);
|
|
float n04= rs_noise_for_perlin(Xint+1, Yint+1);
|
|
float n05= rs_noise_for_perlin(Xint-1, Yint);
|
|
float n06= rs_noise_for_perlin(Xint+1, Yint);
|
|
float n07= rs_noise_for_perlin(Xint, Yint-1);
|
|
float n08= rs_noise_for_perlin(Xint, Yint+1);
|
|
float n09= rs_noise_for_perlin(Xint, Yint);
|
|
|
|
float n12= rs_noise_for_perlin(Xint+2, Yint-1);
|
|
float n14= rs_noise_for_perlin(Xint+2, Yint+1);
|
|
float n16= rs_noise_for_perlin(Xint+2, Yint);
|
|
|
|
float n23= rs_noise_for_perlin(Xint-1, Yint+2);
|
|
float n24= rs_noise_for_perlin(Xint+1, Yint+2);
|
|
float n28= rs_noise_for_perlin(Xint, Yint+2);
|
|
|
|
float n34= rs_noise_for_perlin(Xint+2, Yint+2);
|
|
|
|
//find the noise values of the four corners
|
|
float x0y0 = 0.0625*(n01+n02+n03+n04) + 0.125*(n05+n06+n07+n08) + 0.25*(n09);
|
|
float x1y0 = 0.0625*(n07+n12+n08+n14) + 0.125*(n09+n16+n02+n04) + 0.25*(n06);
|
|
float x0y1 = 0.0625*(n05+n06+n23+n24) + 0.125*(n03+n04+n09+n28) + 0.25*(n08);
|
|
float x1y1 = 0.0625*(n09+n16+n28+n34) + 0.125*(n08+n14+n06+n24) + 0.25*(n04);
|
|
|
|
//interpolate between those values according to the x and y fractions
|
|
float v1 = rs_interpolate(x0y0, x1y0, Xfrac); //interpolate in x direction (y)
|
|
float v2 = rs_interpolate(x0y1, x1y1, Xfrac); //interpolate in x direction (y+1)
|
|
float fin = rs_interpolate(v1, v2, Yfrac); //interpolate in y direction
|
|
|
|
return fin;
|
|
}
|
|
|
|
float rs_perlin(float i, float j) {
|
|
|
|
float t = 0.0f;
|
|
float _amplitude = 1.0;
|
|
|
|
|
|
int k;
|
|
|
|
float amplitude_divider = 0.0;
|
|
for (k = 0; k < rs_perlin_conf.octaves; k++) {
|
|
amplitude_divider += _amplitude;
|
|
_amplitude *= rs_perlin_conf.persistence;
|
|
};
|
|
|
|
_amplitude = 1.0;
|
|
|
|
float freq = rs_perlin_conf.freq;
|
|
|
|
for(k = 0; k < rs_perlin_conf.octaves; k++)
|
|
{
|
|
t += rs_perlin_noise(j * freq / rs_perlin_conf.tex_size + rs_perlin_conf.seed, i * freq / rs_perlin_conf.tex_size + rs_perlin_conf.seed) * _amplitude;
|
|
_amplitude *= rs_perlin_conf.persistence;
|
|
freq *= 2;
|
|
}
|
|
|
|
return t / amplitude_divider;
|
|
};
|
|
|
|
float rs_quad_noise(float i, float j) {
|
|
|
|
float t = 0.0f;
|
|
float _amplitude = 1.0;
|
|
|
|
|
|
int k;
|
|
|
|
float amplitude_divider = 0.0;
|
|
for (k = 0; k < rs_perlin_conf.octaves; k++) {
|
|
amplitude_divider += _amplitude;
|
|
_amplitude *= rs_perlin_conf.persistence;
|
|
};
|
|
|
|
_amplitude = 1.0;
|
|
|
|
float freq = rs_perlin_conf.freq;
|
|
|
|
for(k = 0; k < rs_perlin_conf.octaves; k++)
|
|
{
|
|
t += rs_noise(j * freq / rs_perlin_conf.tex_size + rs_perlin_conf.seed, i * freq / rs_perlin_conf.tex_size + rs_perlin_conf.seed) * _amplitude;
|
|
_amplitude *= rs_perlin_conf.persistence;
|
|
freq *= 2;
|
|
}
|
|
|
|
return t / amplitude_divider;
|
|
};
|
|
|
|
|