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 simplex noise texture===
===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)
{
{
inline int b(int i, int j, int k, int n) {
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 noise(float x, float y, float z)
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;
b2 = m>>2 & 1, b3 = m>>3 & 1, b4 = m>>4 & 1, b5 = m>>5 & 1;
u = u * u * (3 - 2 * u);
v = v * v * (3 - 2 * v);
switch(b01) {
case 1: p = x, q = y, r = z; break;
w = w * w * (3 - 2 * w);
#else
case 2: p = y, q = z, r = x; break;
default: p = z, q = x, r = y; break;
u *= u; u *= (1 - u);
v *= v; v *= (1 - v);
}
w *= w; w *= (1 - w);
#endif


if (b5 == b3) p = -p;
#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));
}


s = (x + y + z)/3;
x1 = interp(n3(i, j, k + 1), n3(i + 1, j, k + 1), u);
i = floorf(x + s), j = floorf(y + s), k = floorf(z + s);
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 *vv)
FLOAT getnoise(FLOAT x, FLOAT y, FLOAT z)
{
{
float v[3], r = 0;
int i;
int i;
for (i = 256; i > 8; i >>= 1) {
FLOAT r = 0, w, s = 0;
for (i = 1; i <= 32; i <<= 1) {
v[0] = vv[0] * 256/i;
v[1] = vv[1] * 256/i;
w = 1./i;
v[2] = vv[2] * 256/i;
s += w;
r += noise(v[0], v[1], v[2]) * i / 256;
r += (noise3(x * i, y * i, z * i) * w);
}
}
r = fmod(r * 2 + 2, 1);
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 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++) {

for (p = pix, i = 0; 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) / 125.0;
y = (j - 128) / 120.;
v[1] = (y + 1) / 2;
*p = i * getnoise2(x, y);
z = x * x + y * y;


if (z > 1) { *p = 0; continue; }
z = 1 - x*x - y*y;
z = sqrt(1 - z);
if (z < 0) { continue; }
v[2] = -z;
z = sqrt(z);
*p = getnoise(v) ? 80 : 0;


v[2] = z;
r = getnoise(x, y, -z);
z = getnoise(v);
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>