Draw a sphere: Difference between revisions
Content added Content deleted
Line 161: | Line 161: | ||
#include <math.h> |
#include <math.h> |
||
/* Perlin-like noise. Still needs more work. */ |
|||
typedef double FLOAT; |
|||
double hashed(int *data, int len) { |
|||
# define rot(a, d) ((a << (d)) | (a >> (32 - d))) |
|||
unsigned int *d = (void*)data, h = 0x123456, tmp; |
|||
while (len--) { |
|||
inline FLOAT |
|||
tmp = *d++; |
|||
rnd(int x) { return ((x^0x5555) * 1103515245) / (FLOAT)(1 << 31); } |
|||
h += rot(h, 16) ^ (rot(tmp, 5) ^ h); |
|||
} |
|||
h ^= rot(h, 7); |
|||
FLOAT nn(int i, int j) |
|||
h += rot(h, 11); |
|||
{ |
|||
h ^= rot(h, 17); |
|||
return rnd( (i << (j & 10)) - (j << (i & 5))); |
|||
h += rot(h, 25); |
|||
# undef rot |
|||
return (double)(int)h / (1U << 31); |
|||
} |
} |
||
double noise(double x[8], int d) |
|||
{ |
{ |
||
# define sum(s, x) for (s = 0, j = 0; j < d; j++) s += x |
|||
int i, j; |
|||
int i, j, n[8], o[8], t; |
|||
double s, scale, ret, w; |
|||
double u[8], sk[8]; |
|||
sum(s, x[j]); |
|||
scale = 1 / (sqrt(d + 1) + 1); |
|||
s *= scale; |
|||
for (i = 0; i < d; i++) { |
|||
#if 1 |
|||
sk[i] = x[i] + s; |
|||
u = u * u * (3 - 2 * u); |
|||
u[i] = sk[i] - (n[i] = floor(sk[i])); |
|||
o[i] = i; |
|||
#else |
|||
} |
|||
u *= u; u *= (1 - u); |
|||
v *= v; v *= (1 - v); |
|||
#endif |
|||
r1 = nn(i, j) * (1 - v) + nn(i, j + 1) * v; |
|||
r2 = nn(i + 1, j) * (1 - v) + nn(i + 1, j + 1) * v; |
|||
for (i = 0; i < d - 1; i++) |
|||
for (j = i; j < d; j++) |
|||
if (u[o[i]] < u[o[j]]) |
|||
t = o[i], o[i] = o[j], o[j] = t; |
|||
ret = w = 0; |
|||
return r; |
|||
scale /= sqrt(d + 1); |
|||
} |
|||
for (i = 0; i <= d; i++) { |
|||
sum(s, n[j]); |
|||
s *= scale; |
|||
for (j = 0; j < d; j++) u[j] = x[j] - n[j] + s; |
|||
FLOAT n3(int i, int j, int k) |
|||
{ |
|||
return rnd( (i << ((j + k) & 10)) - (j << ((k + i) & 5)) + (k << ((i + j) & 15))); |
|||
} |
|||
sum(s, u[j] * u[j]); |
|||
s = .6 - s; |
|||
if (s > 0) { |
|||
FLOAT noise3(FLOAT x, FLOAT y, FLOAT z) |
|||
s *= s; |
|||
{ |
|||
w += s; |
|||
ret += hashed(n, d) * s; |
|||
FLOAT u, v, w, x1, x2, y1, y2; |
|||
} |
|||
if (i < d) n[o[i]]++; |
|||
i = floor(x), j = floor(y), k = floor(z); |
|||
} |
|||
u = x - i, v = y - j, w = z - k; |
|||
return w ? ret / w : 0; |
|||
#if 1 |
|||
u = u * u * (3 - 2 * u); |
|||
v = v * v * (3 - 2 * v); |
|||
w = w * w * (3 - 2 * w); |
|||
#else |
|||
u *= u; u *= (1 - u); |
|||
v *= v; v *= (1 - v); |
|||
w *= w; w *= (1 - w); |
|||
#endif |
|||
#define interp(a, b, c) a * (1 - c) + b * c |
|||
x1 = interp(n3(i, j, k), n3(i + 1, j, k), u); |
|||
x2 = interp(n3(i, j + 1, k), n3(i + 1, j + 1, k), u); |
|||
y1 = interp(x1, x2, v); |
|||
x1 = interp(n3(i, j, k + 1), n3(i + 1, j, k + 1), u); |
|||
x2 = interp(n3(i, j + 1, k + 1), n3(i + 1, j + 1, k + 1), u); |
|||
y2 = interp(x1, x2, v); |
|||
return interp(y1, y2, w); |
|||
} |
} |
||
double get_noise2(double x, double y) |
|||
{ |
{ |
||
int i; |
int i, j, ws; |
||
double r = 0, v[2]; |
|||
for (i = 1; i <= 256; i <<= 1) { |
|||
for (i = 1, ws = 0; i <= 256; i <<= 1) { |
|||
w = 1./sqrt(i); |
|||
v[0] = x * i, v[1] = y * i; |
|||
s += w; |
|||
r += |
r += noise(v, 2); |
||
ws ++; |
|||
} |
} |
||
r /= ws; |
|||
return r; |
|||
} |
} |
||
double get_noise3(double x, double y, double z) |
|||
{ |
{ |
||
int i; |
int i, j, ws; |
||
double r = 0, v[3], w; |
|||
for (i = 1; i <= 32; i <<= 1) { |
|||
for (i = 1, ws = 0; i <= 256; i <<= 1) { |
|||
w = 1./i; |
|||
v[0] = x * i, v[1] = y * i, v[2] = z * i; |
|||
s += w; |
|||
w = 1./sqrt(i); |
|||
r += (noise3(x * i, y * i, z * i) * w); |
|||
r += noise(v, 3) * w; |
|||
ws += w; |
|||
} |
} |
||
return r / ws; |
|||
r = fmod((r / s + 1) * 2, 1); |
|||
if (r < .4) return 0; |
|||
return r; |
|||
} |
} |
||
int main() |
int main() |
||
{ |
{ |
||
unsigned char pix[256 * 256], *p |
unsigned char pix[256 * 256], *p; |
||
FLOAT fv[256 * 256], *pf = fv; |
|||
int i, j; |
int i, j; |
||
double x, y, z, w; |
|||
FILE *fp; |
FILE *fp; |
||
for (i = 0; i < 256 * 256; i++) |
for (p = pix, i = 0; i < 256 * 256; i++) *p++ = 0; |
||
for (i = 0, p = pix; i < 256; i++) { |
|||
for (p = pix, i = 0; i < 256; i++) { |
|||
y = (i - 128) / 125.; |
|||
for (j = 0; j < 256; j++, p++) { |
for (j = 0; j < 256; j++, p++) { |
||
x = (j - 128) / 125.; |
|||
*p = (get_noise2(i/256., j/256.) + 1) / 6 * i * i / 256; |
|||
*p = i * getnoise2(x, y); |
|||
z = 1- x*x - y*y; |
|||
if (z < 0) continue; |
|||
z = 1 - x*x - y*y; |
|||
if (z < 0) { continue; } |
|||
z = sqrt(z); |
z = sqrt(z); |
||
w = get_noise3(x, y, z) / 2 + .5; |
|||
if (r) *p = 50; |
|||
w = w * (x + y + z) / 2.2; |
|||
if ( |
if (w < 0) w = 0; |
||
*p = w * 255; |
|||
if (r > 1) r = 1; |
|||
*p = 180 * r + 70; |
|||
} |
|||
} |
} |
||
} |
} |