Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

/ray/src/lib/numerics/noise/perlin.cc

Go to the documentation of this file.
00001 /*
00002  * lib/numerics/perlin.cc
00003  * 
00004  * Perlins famous noise function. 
00005  * 
00006  * Copyright (c) 2004 by Klaus Sausen (nicolasius § users.sourceforge.net)
00007  *                   and Wolfgang Wieser ] wwieser (a) gmx <*> de [. 
00008  * 
00009  * This implementation of the "Perlin noise" is a modification of Ken 
00010  * Perlin's original implementation as available on his homepage. 
00011  * 
00012  * This file may be distributed and/or modified under the terms of the 
00013  * GNU General Public License version 2 as published by the Free Software 
00014  * Foundation. (See COPYING.GPL for details.)
00015  * 
00016  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00017  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00018  * 
00019  */
00020 
00021 #include "perlin.h"
00022 
00023 
00024 namespace NUM  // numerics
00025 {
00026 
00027 template<typename T>void NoiseGenerator_Perlin<T>::_init()
00028 {
00029     int i,j;
00030 
00031     for(i=0 ; i<B ; i++)
00032     {
00033         p[i] = i;
00034 
00035         //g1[i] = (T)((rand() % (B + B)) - B) / B;
00036         g1[i] = (T)((rand() & (2*B-1)) - B) / B;
00037 
00038         for(j=0 ; j<2 ; j++)
00039             g2[i][j] = (T)((rand() & (2*B-1)) - B) / B;
00040             //g2[i][j] = (T)((rand() % (B + B)) - B)) / B;
00041 
00042         // Normalize g2[i]:
00043         T s = T(1.0)/hypot(g2[i][0],g2[i][1]);
00044         g2[i][0] *= s;
00045         g2[i][1] *= s;
00046 
00047         for(j=0 ; j<3 ; j++)
00048             g3[i][j] = (T)((rand() & (2*B-1)) - B) / B;
00049             //g3[i][j] = (T)(((rand() % (B + B)) - B) / B);
00050 
00051         // Normalize g3[i]: 
00052         s = T(1.0)/sqrt(sqr(g3[i][0]) + sqr(g3[i][1]) + sqr(g3[i][2]));
00053         g3[i][0] *= s;
00054         g3[i][1] *= s;
00055         g3[i][2] *= s;
00056     }
00057 
00058     // Permutate p[]...
00059     while(--i)
00060     {
00061         int k = p[i];
00062         //p[i] = p[j = rand() % B];
00063         p[i] = p[j = rand() & (B-1)];
00064         p[j] = k;
00065     }
00066     
00067     for(i = 0 ; i < B + 2 ; i++)
00068     {
00069         p[B + i] = p[i];
00070         g1[B + i] = g1[i];
00071         for(j=0 ; j<2 ; j++)
00072             g2[B + i][j] = g2[i][j];
00073         for(j=0 ; j<3 ; j++)
00074             g3[B + i][j] = g3[i][j];
00075     }
00076 }
00077 
00078 
00079 #define s_curve(t)   ( t * t * (T(3.0) - T(2.0) * t) )
00080 
00081 #define lerp(t, a, b)   ( a + t * (b - a) )
00082 
00083 #define setup(i,b0,b1,r0,r1)\
00084     t = vc[i] + N;\
00085     b0 = ((int)t) & (B-1);\
00086     b1 = (b0+1) & (B-1);\
00087     r0 = t - (int)t;\
00088     r1 = r0 - 1.;
00089 
00090 
00091 template<typename T>T NoiseGenerator_Perlin<T>::noise1(T arg) const
00092 {
00093     int bx0, bx1;
00094     T rx0, rx1, sx, t, u, v, vc[1];
00095     
00096     vc[0] = arg;
00097     
00098     setup(0, bx0,bx1, rx0,rx1);
00099     
00100     sx = s_curve(rx0);
00101     
00102     u = rx0 * g1[ p[ bx0 ] ];
00103     v = rx1 * g1[ p[ bx1 ] ];
00104     
00105     return lerp(sx, u, v);
00106 }
00107 
00108 
00109 template<typename T>T NoiseGenerator_Perlin<T>::noise2(const T *vc) const
00110 {
00111     int bx0, bx1, by0, by1, b00, b10, b01, b11;
00112     T rx0, rx1, ry0, ry1, sx, sy, a, b, t, u, v;
00113     const T *q;
00114     register int i, j;
00115     
00116 //#define setup(i,b0,b1,r0,r1)
00117 //  setup(0, bx0,bx1, rx0,rx1);
00118 //  setup(1, by0,by1, ry0,ry1);
00119 
00120     t = vc[0] + N;
00121     bx0 = ((int)t) & (B-1);
00122     bx1 = (bx0+1) & (B-1);
00123     rx0 = t - (int)t;
00124     rx1 = rx0 - T(1.0);
00125 
00126     t = vc[1] + N;
00127     by0 = ((int)t) & (B-1);
00128     by1 = (by0+1) & (B-1);
00129     ry0 = t - (int)t;
00130     ry1 = ry0 - T(1.0);
00131 
00132     i = p[ bx0 ];
00133     j = p[ bx1 ];
00134 
00135     b00 = p[ i + by0 ];
00136     b10 = p[ j + by0 ];
00137     b01 = p[ i + by1 ];
00138     b11 = p[ j + by1 ];
00139 
00140     sx = s_curve(rx0);
00141     sy = s_curve(ry0);
00142 
00143 #define at2(rx,ry) ( rx * q[0] + ry * q[1] )
00144 
00145     q = g2[ b00 ] ; u = at2(rx0,ry0);
00146     q = g2[ b10 ] ; v = at2(rx1,ry0);
00147     a = lerp(sx, u, v);
00148 
00149     q = g2[ b01 ] ; u = at2(rx0,ry1);
00150     q = g2[ b11 ] ; v = at2(rx1,ry1);
00151     b = lerp(sx, u, v);
00152 
00153     return T(lerp(sy, a, b));
00154 }
00155 
00156 
00157 template<typename T>T NoiseGenerator_Perlin<T>::noise3(const T *vc) const
00158 {
00159     int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11;
00160     T rx0, rx1, ry0, ry1, rz0, rz1, sy, sz, a, b, c, d, t, u, v;
00161     const T *q;
00162     register int i, j;
00163 
00164 //  setup(0, bx0,bx1, rx0,rx1);
00165 //  setup(1, by0,by1, ry0,ry1);
00166 //  setup(2, bz0,bz1, rz0,rz1);
00167     t = vc[0] + N;
00168     bx0 = ((int)t) & (B-1);
00169     bx1 = (bx0+1) & (B-1);
00170     rx0 = t - (int)t;
00171     rx1 = rx0 - T(1.0);
00172 
00173     t = vc[1] + N;
00174     by0 = ((int)t) & (B-1);
00175     by1 = (by0+1) & (B-1);
00176     ry0 = t - (int)t;
00177     ry1 = ry0 - T(1.0);
00178 
00179     t = vc[2] + N;
00180     bz0 = ((int)t) & (B-1);
00181     bz1 = (bz0+1) & (B-1);
00182     rz0 = t - (int)t;
00183     rz1 = rz0 - T(1.0);
00184 
00185     i = p[ bx0 ];
00186     j = p[ bx1 ];
00187 
00188     b00 = p[ i + by0 ];
00189     b10 = p[ j + by0 ];
00190     b01 = p[ i + by1 ];
00191     b11 = p[ j + by1 ];
00192 
00193     t  = s_curve(rx0);
00194     sy = s_curve(ry0);
00195     sz = s_curve(rz0);
00196 
00197 #define at3(rx,ry,rz) ( rx * q[0] + ry * q[1] + rz * q[2] )
00198 
00199     q = g3[ b00 + bz0 ] ; u = at3(rx0,ry0,rz0);
00200     q = g3[ b10 + bz0 ] ; v = at3(rx1,ry0,rz0);
00201     a = lerp(t, u, v);
00202 
00203     q = g3[ b01 + bz0 ] ; u = at3(rx0,ry1,rz0);
00204     q = g3[ b11 + bz0 ] ; v = at3(rx1,ry1,rz0);
00205     b = lerp(t, u, v);
00206 
00207     c = lerp(sy, a, b);
00208 
00209     q = g3[ b00 + bz1 ] ; u = at3(rx0,ry0,rz1);
00210     q = g3[ b10 + bz1 ] ; v = at3(rx1,ry0,rz1);
00211     a = lerp(t, u, v);
00212 
00213     q = g3[ b01 + bz1 ] ; u = at3(rx0,ry1,rz1);
00214     q = g3[ b11 + bz1 ] ; v = at3(rx1,ry1,rz1);
00215     b = lerp(t, u, v);
00216 
00217     d = lerp(sy, a, b);
00218 
00219     return T(lerp(sz, c, d));
00220 }
00221 
00222 
00223 void _NoiseGenerator_PerlinInstantiationDummy()
00224 {
00225     {
00226         NoiseGenerator_Perlin<dbl> p;
00227         p.noise1(0);
00228         p.noise2(NULL);
00229         p.noise3(NULL);
00230     }
00231     {
00232         NoiseGenerator_Perlin<flt> p;
00233         p.noise1(0);
00234         p.noise2(NULL);
00235         p.noise3(NULL);
00236     }
00237 }
00238 
00239 }  // end of namespace NUM

Generated on Sat Feb 19 22:33:46 2005 for Ray by doxygen 1.3.5