ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/noise3.c
Revision: 2.8
Committed: Mon Aug 4 22:37:53 2003 UTC (20 years, 8 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.7: +5 -3 lines
Log Message:
Added prototype for LIBR function pointer in calcomp.h

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: noise3.c,v 2.7 2003/02/25 02:47:22 greg Exp $";
3 #endif
4 /*
5 * noise3.c - noise functions for random textures.
6 *
7 * Credit for the smooth algorithm goes to Ken Perlin.
8 * (ref. SIGGRAPH Vol 19, No 3, pp 287-96)
9 */
10
11 #include "copyright.h"
12
13 #include "calcomp.h"
14
15 #include <math.h>
16
17 #define A 0
18 #define B 1
19 #define C 2
20 #define D 3
21
22 #define rand3a(x,y,z) frand(67*(x)+59*(y)+71*(z))
23 #define rand3b(x,y,z) frand(73*(x)+79*(y)+83*(z))
24 #define rand3c(x,y,z) frand(89*(x)+97*(y)+101*(z))
25 #define rand3d(x,y,z) frand(103*(x)+107*(y)+109*(z))
26
27 #define hpoly1(t) ((2.0*t-3.0)*t*t+1.0)
28 #define hpoly2(t) (-2.0*t+3.0)*t*t
29 #define hpoly3(t) ((t-2.0)*t+1.0)*t
30 #define hpoly4(t) (t-1.0)*t*t
31
32 #define hermite(p0,p1,r0,r1,t) ( p0*hpoly1(t) + \
33 p1*hpoly2(t) + \
34 r0*hpoly3(t) + \
35 r1*hpoly4(t) )
36
37 static char noise_name[4][8] = {"noise3x", "noise3y", "noise3z", "noise3"};
38 static char fnoise_name[] = "fnoise3";
39 static char hermite_name[] = "hermite";
40
41 double *noise3(), fnoise3(), frand();
42 static interpolate();
43
44 static long xlim[3][2];
45 static double xarg[3];
46
47 #define EPSILON .001 /* error allowed in fractal */
48
49 #define frand3(x,y,z) frand(17*(x)+23*(y)+29*(z))
50
51
52 static double
53 l_noise3(nam) /* compute a noise function */
54 register char *nam;
55 {
56 register int i;
57 double x[3];
58 /* get point */
59 x[0] = argument(1);
60 x[1] = argument(2);
61 x[2] = argument(3);
62 /* make appropriate call */
63 if (nam == fnoise_name)
64 return(fnoise3(x));
65 i = 4;
66 while (i--)
67 if (nam == noise_name[i])
68 return(noise3(x)[i]);
69 eputs(nam);
70 eputs(": called l_noise3!\n");
71 quit(1);
72 }
73
74
75 double
76 l_hermite(char *nm) /* library call for hermite interpolation */
77 {
78 double t;
79
80 t = argument(5);
81 return( hermite(argument(1), argument(2),
82 argument(3), argument(4), t) );
83 }
84
85
86 setnoisefuncs() /* add noise functions to library */
87 {
88 register int i;
89
90 funset(hermite_name, 5, ':', l_hermite);
91 funset(fnoise_name, 3, ':', l_noise3);
92 i = 4;
93 while (i--)
94 funset(noise_name[i], 3, ':', l_noise3);
95 }
96
97
98 double *
99 noise3(xnew) /* compute the noise function */
100 register double xnew[3];
101 {
102 static double x[3] = {-100000.0, -100000.0, -100000.0};
103 static double f[4];
104
105 if (x[0]==xnew[0] && x[1]==xnew[1] && x[2]==xnew[2])
106 return(f);
107 x[0] = xnew[0]; x[1] = xnew[1]; x[2] = xnew[2];
108 xlim[0][0] = floor(x[0]); xlim[0][1] = xlim[0][0] + 1;
109 xlim[1][0] = floor(x[1]); xlim[1][1] = xlim[1][0] + 1;
110 xlim[2][0] = floor(x[2]); xlim[2][1] = xlim[2][0] + 1;
111 xarg[0] = x[0] - xlim[0][0];
112 xarg[1] = x[1] - xlim[1][0];
113 xarg[2] = x[2] - xlim[2][0];
114 interpolate(f, 0, 3);
115 return(f);
116 }
117
118
119 static
120 interpolate(f, i, n)
121 double f[4];
122 register int i, n;
123 {
124 double f0[4], f1[4], hp1, hp2;
125
126 if (n == 0) {
127 f[A] = rand3a(xlim[0][i&1],xlim[1][i>>1&1],xlim[2][i>>2]);
128 f[B] = rand3b(xlim[0][i&1],xlim[1][i>>1&1],xlim[2][i>>2]);
129 f[C] = rand3c(xlim[0][i&1],xlim[1][i>>1&1],xlim[2][i>>2]);
130 f[D] = rand3d(xlim[0][i&1],xlim[1][i>>1&1],xlim[2][i>>2]);
131 } else {
132 n--;
133 interpolate(f0, i, n);
134 interpolate(f1, i | 1<<n, n);
135 hp1 = hpoly1(xarg[n]); hp2 = hpoly2(xarg[n]);
136 f[A] = f0[A]*hp1 + f1[A]*hp2;
137 f[B] = f0[B]*hp1 + f1[B]*hp2;
138 f[C] = f0[C]*hp1 + f1[C]*hp2;
139 f[D] = f0[D]*hp1 + f1[D]*hp2 +
140 f0[n]*hpoly3(xarg[n]) + f1[n]*hpoly4(xarg[n]);
141 }
142 }
143
144
145 double
146 frand(s) /* get random number from seed */
147 register long s;
148 {
149 s = s<<13 ^ s;
150 return(1.0-((s*(s*s*15731+789221)+1376312589)&0x7fffffff)/1073741824.0);
151 }
152
153
154 double
155 fnoise3(p) /* compute fractal noise function */
156 double p[3];
157 {
158 long t[3], v[3], beg[3];
159 double fval[8], fc;
160 int branch;
161 register long s;
162 register int i, j;
163 /* get starting cube */
164 s = (long)(1.0/EPSILON);
165 for (i = 0; i < 3; i++) {
166 t[i] = s*p[i];
167 beg[i] = s*floor(p[i]);
168 }
169 for (j = 0; j < 8; j++) {
170 for (i = 0; i < 3; i++) {
171 v[i] = beg[i];
172 if (j & 1<<i)
173 v[i] += s;
174 }
175 fval[j] = frand3(v[0],v[1],v[2]);
176 }
177 /* compute fractal */
178 for ( ; ; ) {
179 fc = 0.0;
180 for (j = 0; j < 8; j++)
181 fc += fval[j];
182 fc *= 0.125;
183 if ((s >>= 1) == 0)
184 return(fc); /* close enough */
185 branch = 0;
186 for (i = 0; i < 3; i++) { /* do center */
187 v[i] = beg[i] + s;
188 if (t[i] > v[i]) {
189 branch |= 1<<i;
190 }
191 }
192 fc += s*EPSILON*frand3(v[0],v[1],v[2]);
193 fval[~branch & 7] = fc;
194 for (i = 0; i < 3; i++) { /* do faces */
195 if (branch & 1<<i)
196 v[i] += s;
197 else
198 v[i] -= s;
199 fc = 0.0;
200 for (j = 0; j < 8; j++)
201 if (~(j^branch) & 1<<i)
202 fc += fval[j];
203 fc = 0.25*fc + s*EPSILON*frand3(v[0],v[1],v[2]);
204 fval[~(branch^1<<i) & 7] = fc;
205 v[i] = beg[i] + s;
206 }
207 for (i = 0; i < 3; i++) { /* do edges */
208 j = (i+1)%3;
209 if (branch & 1<<j)
210 v[j] += s;
211 else
212 v[j] -= s;
213 j = (i+2)%3;
214 if (branch & 1<<j)
215 v[j] += s;
216 else
217 v[j] -= s;
218 fc = fval[branch & ~(1<<i)];
219 fc += fval[branch | 1<<i];
220 fc = 0.5*fc + s*EPSILON*frand3(v[0],v[1],v[2]);
221 fval[branch^1<<i] = fc;
222 j = (i+1)%3;
223 v[j] = beg[j] + s;
224 j = (i+2)%3;
225 v[j] = beg[j] + s;
226 }
227 for (i = 0; i < 3; i++) /* new cube */
228 if (branch & 1<<i)
229 beg[i] += s;
230 }
231 }