#include /* For printf() */ #include /* For rand() */ #include "shadeop.h" /* * Constants */ #define CELLNUM 2048 /* * Types */ typedef struct { float unif[CELLNUM + CELLNUM]; /* Uniform random distribution */ int perm[CELLNUM + CELLNUM]; /* Random permutation */ } celltables; /* * File globals */ SHADEOP_TABLE(cellrand) = { { "float cellrand_f(float)", "init", "cleanup" }, { "float cellrand_ff(float, float)", "init", "cleanup" }, { "float cellrand_p(point)", "init", "cleanup" }, { "float cellrand_pf(point, float)", "init", "cleanup" }, { "" }, }; SHADEOP_TABLE(printit) = { { "void printit(string)", "", "" }, { "" }, }; /* * One dimensional cellrand method */ SHADEOP(cellrand_f) { int bx0; celltables *t = (celltables *)initdata; float *result = (float *)argv[0]; float x = *(float *)argv[1]; if (x < 0) x--; bx0 = (long)x & (CELLNUM - 1); *result = t->unif[bx0]; return 0; } /* * Two dimensional cellrand method */ SHADEOP(cellrand_ff) { int bx0, by0; celltables *t = (celltables *)initdata; float *result = (float *)argv[0]; float x = *(float *)argv[1]; float y = *(float *)argv[2]; if (x < 0) x--; if (y < 0) y--; bx0 = (long)x & (CELLNUM - 1); by0 = (long)y & (CELLNUM - 1); *result = t->unif[t->perm[bx0] + by0]; return 0; } /* * Three dimensional cellrand method */ SHADEOP(cellrand_p) { int bx0, by0, bz0; float x, y, z; celltables *t = (celltables *)initdata; float *result = (float *)argv[0]; float *p = (float *)argv[1]; x = (p[0] < 0 ? p[0] - 1 : p[0]); y = (p[1] < 0 ? p[1] - 1 : p[1]); z = (p[2] < 0 ? p[2] - 1 : p[2]); bx0 = (long)x & (CELLNUM - 1); by0 = (long)y & (CELLNUM - 1); bz0 = (long)z & (CELLNUM - 1); *result = t->unif[t->perm[t->perm[bx0] + by0] + bz0]; return 0; } /* * Four dimensional cellrand method */ SHADEOP(cellrand_pf) { int bx0, by0, bz0, bw0; float x, y, z; celltables *t = (celltables *)initdata; float *result = (float *)argv[0]; float *p = (float *)argv[1]; float w = *(float *)argv[2]; x = (p[0] < 0 ? p[0] - 1 : p[0]); y = (p[1] < 0 ? p[1] - 1 : p[1]); z = (p[2] < 0 ? p[2] - 1 : p[2]); if (w < 0) w--; bx0 = (long)x & (CELLNUM - 1); by0 = (long)y & (CELLNUM - 1); bz0 = (long)z & (CELLNUM - 1); bw0 = (long)w & (CELLNUM - 1); *result = t->unif[t->perm[t->perm[t->perm[bx0] + by0] + bz0] + bw0]; return 0; } /* * Example of using string arguments */ SHADEOP(printit) { STRING_DESC *sd = (STRING_DESC *)argv[1]; printf("%s\n", sd->s); return 0; } /* * Create the pseudorandom tables as initdata */ SHADEOP_INIT(init) { register int i, j; int tmp; celltables *initdata; initdata = (celltables *)malloc(sizeof(celltables)); if (initdata) { /* * Create an array of pseudorandom numbers uniformly * distributed over the range [0.0, 1.0] */ for (i = 0; i < CELLNUM; i++) { initdata->unif[i] = (float)rand() / RAND_MAX; initdata->perm[i] = i; } /* * Create a pseudorandom permutation of [0..CELLNUM-1] */ for (i = CELLNUM - 1; i > 0; i -= 2) { j = rand() % CELLNUM; if (i != j) { tmp = initdata->perm[i]; initdata->perm[i] = initdata->perm[j]; initdata->perm[j] = tmp; } } /* * Extend unif and perm arrays to allow for faster indexing. */ for (i = 0; i < CELLNUM; i++) { initdata->unif[CELLNUM + i] = initdata->unif[i]; initdata->perm[CELLNUM + i] = initdata->perm[i]; } } return (void *)initdata; } /* * Free the initdata */ SHADEOP_CLEANUP(cleanup) { free((char *)initdata); }