ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/noise3.c
Revision: 2.4
Committed: Mon Aug 9 10:03:45 1993 UTC (30 years, 8 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.3: +1 -1 lines
Log Message:
relaxed error on fractal noise function -- wasn't helping

File Contents

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