Draw a sphere: Difference between revisions
Content added Content deleted
(→{{header|C}}: noise texture) |
|||
Line 155: | Line 155: | ||
eeeeeeeeeeeee </lang> |
eeeeeeeeeeeee </lang> |
||
===Fun with 3D |
===Fun with 3D noise texture=== |
||
[[file:sphere-perlin.png]] |
[[file:sphere-perlin.png]] |
||
<lang c>#include <stdio.h> |
<lang c>#include <stdio.h> |
||
Line 161: | Line 161: | ||
#include <math.h> |
#include <math.h> |
||
typedef double FLOAT; |
|||
/* see http://www.csee.umbc.edu/~olano/s2002c36/ch02.pdf */ |
|||
inline FLOAT |
|||
static int B[] = {0x15, 0x38, 0x32, 0x2c, 0x0d, 0x13, 0x07, 0x2a}; |
|||
rnd(int x) { return ((x^0x5555) * 1103515245) / (FLOAT)(1 << 31); } |
|||
inline int bitmix(int i, int j, int k) |
|||
FLOAT nn(int i, int j) |
|||
{ |
{ |
||
return rnd( (i << (j & 10)) - (j << (i & 5))); |
|||
} |
|||
return B[((i>>n & 1) << 2) | ((j>>n & 1) << 1) | (k>>n & 1)]; |
|||
} |
|||
FLOAT noise2(FLOAT x, FLOAT y) |
|||
{ |
|||
int i, j; |
|||
FLOAT u, v, r = 0, r1, r2; |
|||
i = floor(x), j = floor(y); |
|||
u = x - i, v = y - j; |
|||
#if 1 |
|||
u = u * u * (3 - 2 * u); |
|||
v = v * v * (3 - 2 * v); |
|||
#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; |
|||
return r; |
|||
return b(i, j, k, 0) + b(j, k, i, 1) + b(k, i, j, 2) + |
|||
b(i, j, k, 3) + b(j, k, i, 4) + b(k, i, j, 5) + |
|||
b(i, j, k, 6) + b(j, k, i, 7); |
|||
} |
} |
||
FLOAT n3(int i, int j, int k) |
|||
{ |
{ |
||
return rnd( (i << ((j + k) & 10)) - (j << ((k + i) & 5)) + (k << ((i + j) & 15))); |
|||
float s, u, v, w; |
|||
} |
|||
int i, j, k, dir[3] = {0}, a, b; |
|||
float weight(int d) { |
|||
float s = (dir[0] + dir[1] + dir[2]) / 6.0f; |
|||
float x = u - dir[0] + s, y = v - dir[1] + s, z = w - dir[2] + s; |
|||
float t = .6f - (x * x + y * y + z * z); |
|||
float p, q, r; |
|||
int m, b01, b2, b3, b4, b5; |
|||
FLOAT noise3(FLOAT x, FLOAT y, FLOAT z) |
|||
m = bitmix(i + dir[0], j + dir[1], k + dir[2]); |
|||
{ |
|||
dir[d]++; |
|||
int i, j, k; |
|||
FLOAT u, v, w, x1, x2, y1, y2; |
|||
i = floor(x), j = floor(y), k = floor(z); |
|||
if (t < 0) return 0; |
|||
u = x - i, v = y - j, w = z - k; |
|||
#if 1 |
|||
b01 = m & 3; |
|||
u = u * u * (3 - 2 * u); |
|||
v = v * v * (3 - 2 * v); |
|||
switch(b01) { |
|||
w = w * w * (3 - 2 * w); |
|||
#else |
|||
case 2: p = y, q = z, r = x; break; |
|||
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); |
|||
if (b5 == b4) q = -q; |
|||
x2 = interp(n3(i, j + 1, k), n3(i + 1, j + 1, k), u); |
|||
if (b5 ^ (b4 ^ b3)) r = -r; |
|||
y1 = interp(x1, x2, v); |
|||
t *= t; |
|||
return 8 * t * t * (p + (b01 ? b2 ? r : q : q + r)); |
|||
} |
|||
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); |
|||
s = (i + j + k) / 6.0f; |
|||
} |
|||
u = x - i + s; |
|||
v = y - j + s; |
|||
w = z - k + s; |
|||
FLOAT getnoise2(FLOAT x, FLOAT y) |
|||
a = u>=w ? u>=v ? 0 : 1 : v>=w ? 1 : 2; |
|||
{ |
|||
b = u< w ? u< v ? 0 : 1 : v< w ? 1 : 2; |
|||
int i; |
|||
return weight(a) + weight(3 - a - b) + weight(b) + weight(0); |
|||
FLOAT r = 0, w, s = 0; |
|||
for (i = 1; i <= 256; i <<= 1) { |
|||
w = 1./sqrt(i); |
|||
s += w; |
|||
r += noise2(x * i, y * i) * w; |
|||
} |
|||
return r / s / 2 + .5; |
|||
} |
} |
||
FLOAT getnoise(FLOAT x, FLOAT y, FLOAT z) |
|||
{ |
{ |
||
float v[3], r = 0; |
|||
int i; |
int i; |
||
FLOAT r = 0, w, s = 0; |
|||
for (i = 1; i <= 32; i <<= 1) { |
|||
v[0] = vv[0] * 256/i; |
|||
w = 1./i; |
|||
s += w; |
|||
r += |
r += (noise3(x * i, y * i, z * i) * w); |
||
} |
} |
||
r = fmod(r |
r = fmod((r / s + 1) * 2, 1); |
||
if (r < .4) return 0; |
if (r < .4) return 0; |
||
return r; |
|||
r *= -vv[0] + vv[1] + vv[2]; |
|||
if (r < 0) r = .1; else r += .1; |
|||
if (r > 1) r = 1; |
|||
return sqrt(r); |
|||
} |
} |
||
Line 241: | Line 259: | ||
{ |
{ |
||
unsigned char pix[256 * 256], *p = pix; |
unsigned char pix[256 * 256], *p = pix; |
||
FLOAT fv[256 * 256], *pf = fv; |
|||
float v[3], x, y, z; |
|||
int i, j; |
int i, j; |
||
FLOAT x, y, z, r; |
|||
FILE *fp; |
FILE *fp; |
||
for (i = 0; i < 256 * 256; i++) *pf++ = 0, *p++ = 0; |
for (i = 0; i < 256 * 256; i++) *pf++ = 0, *p++ = 0; |
||
for (i = 0, p = pix; i < 256; i++) { |
|||
x = (i - 128) / 120.; |
|||
x = (i - 128) / 125.0; |
|||
v[0] = (x + 1) / 2; |
|||
for (j = 0; j < 256; j++, p++) { |
for (j = 0; j < 256; j++, p++) { |
||
y = (j - 128) / |
y = (j - 128) / 120.; |
||
*p = i * getnoise2(x, y); |
|||
z = x * x + y * y; |
|||
z = 1 - x*x - y*y; |
|||
if (z < 0) { continue; } |
|||
z = sqrt(z); |
|||
*p = getnoise(v) ? 80 : 0; |
|||
r = getnoise(x, y, -z); |
|||
if (r) *p = 50; |
|||
if (z > 0) *p = z * 128 + 127; |
|||
r = getnoise(x, y, z); |
|||
if (r) { |
|||
r = (x + y + z) / 2.3 + .5; |
|||
if (r > 1) r = 1; |
|||
*p = 180 * r + 70; |
|||
} |
|||
} |
} |
||
} |
} |
||
Line 272: | Line 292: | ||
fwrite(pix, 1, 256 * 256, fp); |
fwrite(pix, 1, 256 * 256, fp); |
||
fclose(fp); |
fclose(fp); |
||
return 0; |
return 0; |
||
}</lang> |
}</lang> |