--- ray/src/rt/noise3.c 2011/02/22 16:45:12 2.12 +++ ray/src/rt/noise3.c 2013/10/08 18:59:44 2.13 @@ -1,11 +1,12 @@ #ifndef lint -static const char RCSid[] = "$Id: noise3.c,v 2.12 2011/02/22 16:45:12 greg Exp $"; +static const char RCSid[] = "$Id: noise3.c,v 2.13 2013/10/08 18:59:44 greg Exp $"; #endif /* * noise3.c - noise functions for random textures. * - * Credit for the smooth algorithm goes to Ken Perlin. - * (ref. SIGGRAPH Vol 19, No 3, pp 287-96) + * Credit for the smooth algorithm goes to Ken Perlin, and code + * translation/implementation to Rahul Narain. + * (ref. Improving Noise, Computer Graphics; Vol. 35 No. 3., 2002) */ #include "copyright.h" @@ -13,51 +14,27 @@ static const char RCSid[] = "$Id: noise3.c,v 2.12 2011 #include "ray.h" #include "func.h" -#define A 0 -#define B 1 -#define C 2 -#define D 3 - -#define rand3a(x,y,z) frand(67*(x)+59*(y)+71*(z)) -#define rand3b(x,y,z) frand(73*(x)+79*(y)+83*(z)) -#define rand3c(x,y,z) frand(89*(x)+97*(y)+101*(z)) -#define rand3d(x,y,z) frand(103*(x)+107*(y)+109*(z)) - -#define hpoly1(t) ((2.0*t-3.0)*t*t+1.0) -#define hpoly2(t) (-2.0*t+3.0)*t*t -#define hpoly3(t) ((t-2.0)*t+1.0)*t -#define hpoly4(t) (t-1.0)*t*t - -#define hermite(p0,p1,r0,r1,t) ( p0*hpoly1(t) + \ - p1*hpoly2(t) + \ - r0*hpoly3(t) + \ - r1*hpoly4(t) ) - static char noise_name[4][8] = {"noise3x", "noise3y", "noise3z", "noise3"}; static char fnoise_name[] = "fnoise3"; -static char hermite_name[] = "hermite"; -static long xlim[3][2]; -static double xarg[3]; +#define EPSILON .0005 /* error allowed in fractal */ -#define EPSILON .001 /* error allowed in fractal */ - #define frand3(x,y,z) frand(17*(x)+23*(y)+29*(z)) -static double l_noise3(char *nam); -static double l_hermite(char *nm); -static double * noise3(double xnew[3]); -static void interpolate(double f[4], int i, int n); -static double frand(long s); -static double fnoise3(double p[3]); +static double l_noise3(char *nam); +static double noise3(double xnew[3], int i); +static double noise3partial(double f3, double x[3], int i); +static double perlin_noise (double x, double y, double z); +static double frand(long s); +static double fnoise3(double x[3]); static double l_noise3( /* compute a noise function */ - register char *nam + char *nam ) { - register int i; + int i; double x[3]; /* get point */ x[0] = argument(1); @@ -69,7 +46,7 @@ l_noise3( /* compute a noise function */ i = 4; while (i--) if (nam == noise_name[i]) - return(noise3(x)[i]); + return(noise3(x,i)); eputs(nam); eputs(": called l_noise3!\n"); quit(1); @@ -77,23 +54,11 @@ l_noise3( /* compute a noise function */ } -static double -l_hermite(char *nm) /* library call for hermite interpolation */ -{ - double t; - - t = argument(5); - return( hermite(argument(1), argument(2), - argument(3), argument(4), t) ); -} - - -extern void +void setnoisefuncs(void) /* add noise functions to library */ { - register int i; + int i; - funset(hermite_name, 5, ':', l_hermite); funset(fnoise_name, 3, ':', l_noise3); i = 4; while (i--) @@ -101,59 +66,9 @@ setnoisefuncs(void) /* add noise functions to librar } -static double * -noise3( /* compute the noise function */ - register double xnew[3] -) -{ - static double x[3] = {-100000.0, -100000.0, -100000.0}; - static double f[4]; - - if (x[0]==xnew[0] && x[1]==xnew[1] && x[2]==xnew[2]) - return(f); - x[0] = xnew[0]; x[1] = xnew[1]; x[2] = xnew[2]; - xlim[0][0] = floor(x[0]); xlim[0][1] = xlim[0][0] + 1; - xlim[1][0] = floor(x[1]); xlim[1][1] = xlim[1][0] + 1; - xlim[2][0] = floor(x[2]); xlim[2][1] = xlim[2][0] + 1; - xarg[0] = x[0] - xlim[0][0]; - xarg[1] = x[1] - xlim[1][0]; - xarg[2] = x[2] - xlim[2][0]; - interpolate(f, 0, 3); - return(f); -} - - -static void -interpolate( - double f[4], - register int i, - register int n -) -{ - double f0[4], f1[4], hp1, hp2; - - if (n == 0) { - f[A] = rand3a(xlim[0][i&1],xlim[1][i>>1&1],xlim[2][i>>2]); - f[B] = rand3b(xlim[0][i&1],xlim[1][i>>1&1],xlim[2][i>>2]); - f[C] = rand3c(xlim[0][i&1],xlim[1][i>>1&1],xlim[2][i>>2]); - f[D] = rand3d(xlim[0][i&1],xlim[1][i>>1&1],xlim[2][i>>2]); - } else { - n--; - interpolate(f0, i, n); - interpolate(f1, i | 1<>i & 1)) { + f[i] = noise3partial(f[3], x, i); + gotV |= 1<