Draw a sphere: Difference between revisions
Content added Content deleted
(Stronger D code) |
(→{{header|C}}: noise texture) |
||
Line 154: | Line 154: | ||
eeeeeeeeeeeeeeeeeeeee |
eeeeeeeeeeeeeeeeeeeee |
||
eeeeeeeeeeeee </lang> |
eeeeeeeeeeeee </lang> |
||
===Fun with 3D simplex noise texture=== |
|||
[[file:sphere-perlin.png]] |
|||
<lang c>#include <stdio.h> |
|||
#include <stdlib.h> |
|||
#include <math.h> |
|||
/* see http://www.csee.umbc.edu/~olano/s2002c36/ch02.pdf */ |
|||
static int B[] = {0x15, 0x38, 0x32, 0x2c, 0x0d, 0x13, 0x07, 0x2a}; |
|||
inline int bitmix(int i, int j, int k) |
|||
{ |
|||
inline int b(int i, int j, int k, int n) { |
|||
return B[((i>>n & 1) << 2) | ((j>>n & 1) << 1) | (k>>n & 1)]; |
|||
} |
|||
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 noise(float x, float y, float z) |
|||
{ |
|||
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; |
|||
m = bitmix(i + dir[0], j + dir[1], k + dir[2]); |
|||
dir[d]++; |
|||
if (t < 0) return 0; |
|||
b01 = m & 3; |
|||
b2 = m>>2 & 1, b3 = m>>3 & 1, b4 = m>>4 & 1, b5 = m>>5 & 1; |
|||
switch(b01) { |
|||
case 1: p = x, q = y, r = z; break; |
|||
case 2: p = y, q = z, r = x; break; |
|||
default: p = z, q = x, r = y; break; |
|||
} |
|||
if (b5 == b3) p = -p; |
|||
if (b5 == b4) q = -q; |
|||
if (b5 ^ (b4 ^ b3)) r = -r; |
|||
t *= t; |
|||
return 8 * t * t * (p + (b01 ? b2 ? r : q : q + r)); |
|||
} |
|||
s = (x + y + z)/3; |
|||
i = floorf(x + s), j = floorf(y + s), k = floorf(z + s); |
|||
s = (i + j + k) / 6.0f; |
|||
u = x - i + s; |
|||
v = y - j + s; |
|||
w = z - k + s; |
|||
a = u>=w ? u>=v ? 0 : 1 : v>=w ? 1 : 2; |
|||
b = u< w ? u< v ? 0 : 1 : v< w ? 1 : 2; |
|||
return weight(a) + weight(3 - a - b) + weight(b) + weight(0); |
|||
} |
|||
float getnoise(float *vv) |
|||
{ |
|||
float v[3], r = 0; |
|||
int i; |
|||
for (i = 256; i > 8; i >>= 1) { |
|||
v[0] = vv[0] * 256/i; |
|||
v[1] = vv[1] * 256/i; |
|||
v[2] = vv[2] * 256/i; |
|||
r += noise(v[0], v[1], v[2]) * i / 256; |
|||
} |
|||
r = fmod(r * 2 + 2, 1); |
|||
if (r < .4) return 0; |
|||
r *= -vv[0] + vv[1] + vv[2]; |
|||
if (r < 0) r = .1; else r += .1; |
|||
if (r > 1) r = 1; |
|||
return sqrt(r); |
|||
} |
|||
int main() |
|||
{ |
|||
unsigned char pix[256 * 256], *p = pix; |
|||
float fv[256 * 256], *pf = fv; |
|||
float v[3], x, y, z; |
|||
int i, j; |
|||
FILE *fp; |
|||
for (i = 0; i < 256 * 256; i++) *pf++ = 0, *p++ = 0; |
|||
for (p = pix, i = 0; i < 256; i++) { |
|||
x = (i - 128) / 125.0; |
|||
v[0] = (x + 1) / 2; |
|||
for (j = 0; j < 256; j++, p++) { |
|||
y = (j - 128) / 125.0; |
|||
v[1] = (y + 1) / 2; |
|||
z = x * x + y * y; |
|||
if (z > 1) { *p = 0; continue; } |
|||
z = sqrt(1 - z); |
|||
v[2] = -z; |
|||
*p = getnoise(v) ? 80 : 0; |
|||
v[2] = z; |
|||
z = getnoise(v); |
|||
if (z > 0) *p = z * 128 + 127; |
|||
} |
|||
} |
|||
fp = fopen("out.pgm", "w+"); |
|||
fprintf(fp, "P5\n256 256\n255\n"); |
|||
fwrite(pix, 1, 256 * 256, fp); |
|||
fclose(fp); |
|||
return 0; |
|||
}</lang> |
|||
=={{header|D}}== |
=={{header|D}}== |
||
{{trans|C}} |
{{trans|C}} |