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);
}
}


FLOAT noise2(FLOAT x, FLOAT y)
double noise(double x[8], int d)
{
{
# define sum(s, x) for (s = 0, j = 0; j < d; j++) s += x
int i, j;
FLOAT u, v, r = 0, r1, r2;
int i, j, n[8], o[8], t;
double s, scale, ret, w;
double u[8], sk[8];


i = floor(x), j = floor(y);
sum(s, x[j]);
u = x - i, v = y - 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);
v = v * v * (3 - 2 * v);
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;


r = r1 * (1 - u) + r2 * u;
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;
{
int i, j, k;
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);
}
}


FLOAT getnoise2(FLOAT x, FLOAT y)
double get_noise2(double x, double y)
{
{
int i;
int i, j, ws;
FLOAT r = 0, w, s = 0;
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 += noise2(x * i, y * i) * w;
r += noise(v, 2);
ws ++;
}
}
return r / s / 2 + .5;
r /= ws;
return r;
}
}


FLOAT getnoise(FLOAT x, FLOAT y, FLOAT z)
double get_noise3(double x, double y, double z)
{
{
int i;
int i, j, ws;
FLOAT r = 0, w, s = 0;
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 = pix;
unsigned char pix[256 * 256], *p;
FLOAT fv[256 * 256], *pf = fv;
int i, j;
int i, j;
FLOAT x, y, z, r;
double x, y, z, w;

FILE *fp;
FILE *fp;


for (i = 0; i < 256 * 256; i++) *pf++ = 0, *p++ = 0;
for (p = pix, i = 0; i < 256 * 256; i++) *p++ = 0;

for (i = 0, p = pix; i < 256; i++) {
x = (i - 128) / 120.;
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++) {
y = (j - 128) / 120.;
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);


r = getnoise(x, y, -z);
w = get_noise3(x, y, z) / 2 + .5;
if (r) *p = 50;


r = getnoise(x, y, z);
w = w * (x + y + z) / 2.2;
if (r) {
if (w < 0) w = 0;
r = (x + y + z) / 2.3 + .5;
*p = w * 255;
if (r > 1) r = 1;
*p = 180 * r + 70;
}
}
}
}
}