ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/noise3.c
Revision: 2.6
Committed: Sat Feb 22 02:07:29 2003 UTC (21 years, 2 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.5: +57 -6 lines
Log Message:
Changes and check-in for 3.5 release
Includes new source files and modifications not recorded for many years
See ray/doc/notes/ReleaseNotes for notes between 3.1 and 3.5 release

File Contents

# User Rev Content
1 greg 1.1 #ifndef lint
2 greg 2.6 static const char RCSid[] = "$Id$";
3 greg 1.1 #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 greg 2.6 */
10    
11     /* ====================================================================
12     * The Radiance Software License, Version 1.0
13     *
14     * Copyright (c) 1990 - 2002 The Regents of the University of California,
15     * through Lawrence Berkeley National Laboratory. All rights reserved.
16     *
17     * Redistribution and use in source and binary forms, with or without
18     * modification, are permitted provided that the following conditions
19     * are met:
20     *
21     * 1. Redistributions of source code must retain the above copyright
22     * notice, this list of conditions and the following disclaimer.
23     *
24     * 2. Redistributions in binary form must reproduce the above copyright
25     * notice, this list of conditions and the following disclaimer in
26     * the documentation and/or other materials provided with the
27     * distribution.
28     *
29     * 3. The end-user documentation included with the redistribution,
30     * if any, must include the following acknowledgment:
31     * "This product includes Radiance software
32     * (http://radsite.lbl.gov/)
33     * developed by the Lawrence Berkeley National Laboratory
34     * (http://www.lbl.gov/)."
35     * Alternately, this acknowledgment may appear in the software itself,
36     * if and wherever such third-party acknowledgments normally appear.
37     *
38     * 4. The names "Radiance," "Lawrence Berkeley National Laboratory"
39     * and "The Regents of the University of California" must
40     * not be used to endorse or promote products derived from this
41     * software without prior written permission. For written
42     * permission, please contact [email protected].
43     *
44     * 5. Products derived from this software may not be called "Radiance",
45     * nor may "Radiance" appear in their name, without prior written
46     * permission of Lawrence Berkeley National Laboratory.
47     *
48     * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
49     * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
50     * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
51     * DISCLAIMED. IN NO EVENT SHALL Lawrence Berkeley National Laboratory OR
52     * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
53     * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
54     * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
55     * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
56     * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
57     * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
58     * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59     * SUCH DAMAGE.
60     * ====================================================================
61 greg 1.1 *
62 greg 2.6 * This software consists of voluntary contributions made by many
63     * individuals on behalf of Lawrence Berkeley National Laboratory. For more
64     * information on Lawrence Berkeley National Laboratory, please see
65     * <http://www.lbl.gov/>.
66 greg 1.1 */
67    
68 greg 2.2 #include <math.h>
69 greg 1.1
70     #define A 0
71     #define B 1
72     #define C 2
73     #define D 3
74    
75     #define rand3a(x,y,z) frand(67*(x)+59*(y)+71*(z))
76     #define rand3b(x,y,z) frand(73*(x)+79*(y)+83*(z))
77     #define rand3c(x,y,z) frand(89*(x)+97*(y)+101*(z))
78     #define rand3d(x,y,z) frand(103*(x)+107*(y)+109*(z))
79    
80 greg 1.7 #define hpoly1(t) ((2.0*t-3.0)*t*t+1.0)
81     #define hpoly2(t) (-2.0*t+3.0)*t*t
82     #define hpoly3(t) ((t-2.0)*t+1.0)*t
83     #define hpoly4(t) (t-1.0)*t*t
84 greg 1.1
85 greg 1.7 #define hermite(p0,p1,r0,r1,t) ( p0*hpoly1(t) + \
86     p1*hpoly2(t) + \
87     r0*hpoly3(t) + \
88     r1*hpoly4(t) )
89    
90 greg 2.5 static char noise_name[4][8] = {"noise3x", "noise3y", "noise3z", "noise3"};
91 greg 1.5 static char fnoise_name[] = "fnoise3";
92     static char hermite_name[] = "hermite";
93 greg 1.1
94 greg 1.5 double *noise3(), fnoise3(), argument(), frand();
95 greg 2.3 static interpolate();
96 greg 1.5
97 greg 1.1 static long xlim[3][2];
98     static double xarg[3];
99    
100 greg 2.4 #define EPSILON .001 /* error allowed in fractal */
101 greg 1.1
102 greg 1.3 #define frand3(x,y,z) frand(17*(x)+23*(y)+29*(z))
103 greg 1.1
104    
105 greg 1.5 static double
106     l_noise3(nam) /* compute a noise function */
107     register char *nam;
108 greg 1.1 {
109 greg 1.5 register int i;
110     double x[3];
111     /* get point */
112     x[0] = argument(1);
113     x[1] = argument(2);
114     x[2] = argument(3);
115     /* make appropriate call */
116     if (nam == fnoise_name)
117     return(fnoise3(x));
118     i = 4;
119     while (i--)
120     if (nam == noise_name[i])
121     return(noise3(x)[i]);
122 greg 1.6 eputs(nam);
123     eputs(": called l_noise3!\n");
124 greg 1.5 quit(1);
125 greg 1.1 }
126    
127    
128     double
129 greg 1.5 l_hermite() /* library call for hermite interpolation */
130 greg 1.1 {
131 greg 1.5 double t;
132    
133     t = argument(5);
134     return( hermite(argument(1), argument(2),
135     argument(3), argument(4), t) );
136 greg 1.1 }
137    
138    
139 greg 1.5 setnoisefuncs() /* add noise functions to library */
140 greg 1.1 {
141 greg 1.5 register int i;
142 greg 1.1
143 greg 1.5 funset(hermite_name, 5, ':', l_hermite);
144     funset(fnoise_name, 3, ':', l_noise3);
145     i = 4;
146     while (i--)
147     funset(noise_name[i], 3, ':', l_noise3);
148 greg 1.1 }
149    
150    
151     double *
152     noise3(xnew) /* compute the noise function */
153     register double xnew[3];
154     {
155     static double x[3] = {-100000.0, -100000.0, -100000.0};
156     static double f[4];
157    
158     if (x[0]==xnew[0] && x[1]==xnew[1] && x[2]==xnew[2])
159     return(f);
160     x[0] = xnew[0]; x[1] = xnew[1]; x[2] = xnew[2];
161     xlim[0][0] = floor(x[0]); xlim[0][1] = xlim[0][0] + 1;
162     xlim[1][0] = floor(x[1]); xlim[1][1] = xlim[1][0] + 1;
163     xlim[2][0] = floor(x[2]); xlim[2][1] = xlim[2][0] + 1;
164     xarg[0] = x[0] - xlim[0][0];
165     xarg[1] = x[1] - xlim[1][0];
166     xarg[2] = x[2] - xlim[2][0];
167     interpolate(f, 0, 3);
168     return(f);
169     }
170    
171    
172     static
173     interpolate(f, i, n)
174     double f[4];
175     register int i, n;
176     {
177 greg 1.7 double f0[4], f1[4], hp1, hp2;
178 greg 1.1
179     if (n == 0) {
180     f[A] = rand3a(xlim[0][i&1],xlim[1][i>>1&1],xlim[2][i>>2]);
181     f[B] = rand3b(xlim[0][i&1],xlim[1][i>>1&1],xlim[2][i>>2]);
182     f[C] = rand3c(xlim[0][i&1],xlim[1][i>>1&1],xlim[2][i>>2]);
183     f[D] = rand3d(xlim[0][i&1],xlim[1][i>>1&1],xlim[2][i>>2]);
184     } else {
185     n--;
186     interpolate(f0, i, n);
187     interpolate(f1, i | 1<<n, n);
188 greg 1.7 hp1 = hpoly1(xarg[n]); hp2 = hpoly2(xarg[n]);
189     f[A] = f0[A]*hp1 + f1[A]*hp2;
190     f[B] = f0[B]*hp1 + f1[B]*hp2;
191     f[C] = f0[C]*hp1 + f1[C]*hp2;
192     f[D] = f0[D]*hp1 + f1[D]*hp2 +
193     f0[n]*hpoly3(xarg[n]) + f1[n]*hpoly4(xarg[n]);
194 greg 1.1 }
195     }
196    
197    
198     double
199     frand(s) /* get random number from seed */
200     register long s;
201     {
202     s = s<<13 ^ s;
203     return(1.0-((s*(s*s*15731+789221)+1376312589)&0x7fffffff)/1073741824.0);
204     }
205    
206    
207     double
208     fnoise3(p) /* compute fractal noise function */
209 greg 1.3 double p[3];
210 greg 1.1 {
211 greg 1.4 long t[3], v[3], beg[3];
212 greg 1.3 double fval[8], fc;
213     int branch;
214 greg 1.4 register long s;
215 greg 1.1 register int i, j;
216     /* get starting cube */
217 greg 1.3 s = (long)(1.0/EPSILON);
218     for (i = 0; i < 3; i++) {
219     t[i] = s*p[i];
220     beg[i] = s*floor(p[i]);
221     }
222 greg 1.1 for (j = 0; j < 8; j++) {
223     for (i = 0; i < 3; i++) {
224     v[i] = beg[i];
225     if (j & 1<<i)
226 greg 1.3 v[i] += s;
227 greg 1.1 }
228     fval[j] = frand3(v[0],v[1],v[2]);
229     }
230     /* compute fractal */
231     for ( ; ; ) {
232 greg 1.4 fc = 0.0;
233     for (j = 0; j < 8; j++)
234     fc += fval[j];
235     fc *= 0.125;
236     if ((s >>= 1) == 0)
237     return(fc); /* close enough */
238 greg 1.1 branch = 0;
239     for (i = 0; i < 3; i++) { /* do center */
240     v[i] = beg[i] + s;
241 greg 1.3 if (t[i] > v[i]) {
242 greg 1.1 branch |= 1<<i;
243 greg 1.3 }
244 greg 1.1 }
245 greg 1.3 fc += s*EPSILON*frand3(v[0],v[1],v[2]);
246 greg 1.1 fval[~branch & 7] = fc;
247     for (i = 0; i < 3; i++) { /* do faces */
248     if (branch & 1<<i)
249     v[i] += s;
250     else
251     v[i] -= s;
252     fc = 0.0;
253     for (j = 0; j < 8; j++)
254     if (~(j^branch) & 1<<i)
255     fc += fval[j];
256 greg 1.3 fc = 0.25*fc + s*EPSILON*frand3(v[0],v[1],v[2]);
257 greg 1.1 fval[~(branch^1<<i) & 7] = fc;
258     v[i] = beg[i] + s;
259     }
260     for (i = 0; i < 3; i++) { /* do edges */
261     j = (i+1)%3;
262     if (branch & 1<<j)
263     v[j] += s;
264     else
265     v[j] -= s;
266     j = (i+2)%3;
267     if (branch & 1<<j)
268     v[j] += s;
269     else
270     v[j] -= s;
271     fc = fval[branch & ~(1<<i)];
272     fc += fval[branch | 1<<i];
273 greg 1.3 fc = 0.5*fc + s*EPSILON*frand3(v[0],v[1],v[2]);
274 greg 1.1 fval[branch^1<<i] = fc;
275     j = (i+1)%3;
276     v[j] = beg[j] + s;
277     j = (i+2)%3;
278     v[j] = beg[j] + s;
279     }
280     for (i = 0; i < 3; i++) /* new cube */
281     if (branch & 1<<i)
282     beg[i] += s;
283     }
284     }