llperlin.cpp

Go to the documentation of this file.
00001 
00031 #include "linden_common.h"
00032 #include "llmath.h"
00033 
00034 #include "llperlin.h"
00035 
00036 #define B 0x100
00037 #define BM 0xff
00038 #define N 0x1000
00039 #define NF32 (4096.f)
00040 #define NP 12   /* 2^N */
00041 #define NM 0xfff
00042 
00043 static S32 p[B + B + 2];
00044 static F32 g3[B + B + 2][3];
00045 static F32 g2[B + B + 2][2];
00046 static F32 g1[B + B + 2];
00047 
00048 bool LLPerlinNoise::sInitialized = 0;
00049 
00050 static void normalize2(F32 v[2])
00051 {
00052         F32 s = 1.f/(F32)sqrt(v[0] * v[0] + v[1] * v[1]);
00053         v[0] = v[0] * s;
00054         v[1] = v[1] * s;
00055 }
00056 
00057 static void normalize3(F32 v[3])
00058 {
00059         F32 s = 1.f/(F32)sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
00060         v[0] = v[0] * s;
00061         v[1] = v[1] * s;
00062         v[2] = v[2] * s;
00063 }
00064 
00065 static void fast_setup(F32 vec, U8 &b0, U8 &b1, F32 &r0, F32 &r1)
00066 {
00067         S32 t_S32;
00068 
00069         r1      = vec + NF32;
00070         t_S32 = lltrunc(r1);
00071         b0 = (U8)t_S32;
00072         b1 = b0 + 1;
00073         r0 = r1 - t_S32;
00074         r1 = r0 - 1.f;
00075 }
00076 
00077 
00078 void LLPerlinNoise::init(void)
00079 {
00080         int i, j, k;
00081 
00082         for (i = 0 ; i < B ; i++)
00083         {
00084                 p[i] = i;
00085 
00086                 g1[i] = (F32)((rand() % (B + B)) - B) / B;
00087 
00088                 for (j = 0 ; j < 2 ; j++)
00089                         g2[i][j] = (F32)((rand() % (B + B)) - B) / B;
00090                 normalize2(g2[i]);
00091 
00092                 for (j = 0 ; j < 3 ; j++)
00093                         g3[i][j] = (F32)((rand() % (B + B)) - B) / B;
00094                 normalize3(g3[i]);
00095         }
00096 
00097         while (--i)
00098         {
00099                 k = p[i];
00100                 p[i] = p[j = rand() % B];
00101                 p[j] = k;
00102         }
00103 
00104         for (i = 0 ; i < B + 2 ; i++)
00105         {
00106                 p[B + i] = p[i];
00107                 g1[B + i] = g1[i];
00108                 for (j = 0 ; j < 2 ; j++)
00109                         g2[B + i][j] = g2[i][j];
00110                 for (j = 0 ; j < 3 ; j++)
00111                         g3[B + i][j] = g3[i][j];
00112         }
00113 
00114         sInitialized = true;
00115 }
00116 
00117 
00118 //============================================================================
00119 // Noise functions
00120 
00121 #define s_curve(t) ( t * t * (3.f - 2.f * t) )
00122 
00123 #define lerp_m(t, a, b) ( a + t * (b - a) )
00124 
00125 F32 LLPerlinNoise::noise1(F32 x)
00126 {
00127         int bx0, bx1;
00128         F32 rx0, rx1, sx, t, u, v;
00129 
00130         if (!sInitialized)
00131                 init();
00132 
00133         t = x + N;
00134         bx0 = (lltrunc(t)) & BM;
00135         bx1 = (bx0+1) & BM;
00136         rx0 = t - lltrunc(t);
00137         rx1 = rx0 - 1.f;
00138 
00139         sx = s_curve(rx0);
00140 
00141         u = rx0 * g1[ p[ bx0 ] ];
00142         v = rx1 * g1[ p[ bx1 ] ];
00143 
00144         return lerp_m(sx, u, v);
00145 }
00146 
00147 static F32 fast_at2(F32 rx, F32 ry, F32 *q)
00148 {
00149         return rx * q[0] + ry * q[1];
00150 }
00151 
00152 F32 LLPerlinNoise::noise2(F32 x, F32 y)
00153 {
00154         U8 bx0, bx1, by0, by1;
00155         U32 b00, b10, b01, b11;
00156         F32 rx0, rx1, ry0, ry1, *q, sx, sy, a, b, u, v;
00157         S32 i, j;
00158 
00159         if (!sInitialized)
00160                 init();
00161 
00162         fast_setup(x, bx0, bx1, rx0, rx1);
00163         fast_setup(y, by0, by1, ry0, ry1);
00164 
00165         i = *(p + bx0);
00166         j = *(p + bx1);
00167 
00168         b00 = *(p + i + by0);
00169         b10 = *(p + j + by0);
00170         b01 = *(p + i + by1);
00171         b11 = *(p + j + by1);
00172 
00173         sx = s_curve(rx0);
00174         sy = s_curve(ry0);
00175 
00176 
00177         q = *(g2 + b00);
00178         u = fast_at2(rx0, ry0, q);
00179         q = *(g2 + b10); 
00180         v = fast_at2(rx1, ry0, q);
00181         a = lerp_m(sx, u, v);
00182 
00183         q = *(g2 + b01); 
00184         u = fast_at2(rx0,ry1,q);
00185         q = *(g2 + b11); 
00186         v = fast_at2(rx1,ry1,q);
00187         b = lerp_m(sx, u, v);
00188 
00189         return lerp_m(sy, a, b);
00190 }
00191 
00192 static F32 fast_at3(F32 rx, F32 ry, F32 rz, F32 *q)
00193 {
00194         return rx * q[0] + ry * q[1] + rz * q[2];
00195 }
00196 
00197 F32 LLPerlinNoise::noise3(F32 x, F32 y, F32 z)
00198 {
00199         U8 bx0, bx1, by0, by1, bz0, bz1;
00200         S32 b00, b10, b01, b11;
00201         F32 rx0, rx1, ry0, ry1, rz0, rz1, *q, sy, sz, a, b, c, d, t, u, v;
00202         S32 i, j;
00203 
00204         if (!sInitialized)
00205                 init();
00206 
00207         fast_setup(x, bx0,bx1, rx0,rx1);
00208         fast_setup(y, by0,by1, ry0,ry1);
00209         fast_setup(z, bz0,bz1, rz0,rz1);
00210 
00211         i = p[ bx0 ];
00212         j = p[ bx1 ];
00213 
00214         b00 = p[ i + by0 ];
00215         b10 = p[ j + by0 ];
00216         b01 = p[ i + by1 ];
00217         b11 = p[ j + by1 ];
00218 
00219         t  = s_curve(rx0);
00220         sy = s_curve(ry0);
00221         sz = s_curve(rz0);
00222 
00223         q = g3[ b00 + bz0 ]; 
00224         u = fast_at3(rx0,ry0,rz0,q);
00225         q = g3[ b10 + bz0 ];
00226         v = fast_at3(rx1,ry0,rz0,q);
00227         a = lerp_m(t, u, v);
00228 
00229         q = g3[ b01 + bz0 ];
00230         u = fast_at3(rx0,ry1,rz0,q);
00231         q = g3[ b11 + bz0 ];
00232         v = fast_at3(rx1,ry1,rz0,q);
00233         b = lerp_m(t, u, v);
00234 
00235         c = lerp_m(sy, a, b);
00236 
00237         q = g3[ b00 + bz1 ];
00238         u = fast_at3(rx0,ry0,rz1,q);
00239         q = g3[ b10 + bz1 ];
00240         v = fast_at3(rx1,ry0,rz1,q);
00241         a = lerp_m(t, u, v);
00242 
00243         q = g3[ b01 + bz1 ];
00244         u = fast_at3(rx0,ry1,rz1,q);
00245         q = g3[ b11 + bz1 ];
00246         v = fast_at3(rx1,ry1,rz1,q);
00247         b = lerp_m(t, u, v);
00248 
00249         d = lerp_m(sy, a, b);
00250 
00251         return lerp_m(sz, c, d);
00252 }
00253 
00254 F32 LLPerlinNoise::turbulence2(F32 x, F32 y, F32 freq)
00255 {
00256         F32 t, lx, ly;
00257 
00258         for (t = 0.f ; freq >= 1.f ; freq *= 0.5f)
00259         {
00260                 lx = freq * x;
00261                 ly = freq * y;
00262                 t += noise2(lx, ly)/freq;
00263         }
00264         return t;
00265 }
00266 
00267 F32 LLPerlinNoise::turbulence3(F32 x, F32 y, F32 z, F32 freq)
00268 {
00269         F32 t, lx, ly, lz;
00270 
00271         for (t = 0.f ; freq >= 1.f ; freq *= 0.5f)
00272         {
00273                 lx = freq * x;
00274                 ly = freq * y;
00275                 lz = freq * z;
00276                 t += noise3(lx,ly,lz)/freq;
00277 //              t += fabs(noise3(lx,ly,lz)) / freq;                                     // Like snow - bubbly at low frequencies
00278 //              t += sqrt(fabs(noise3(lx,ly,lz))) / freq;                       // Better at low freq
00279 //              t += (noise3(lx,ly,lz)*noise3(lx,ly,lz)) / freq;                
00280         }
00281         return t;
00282 }
00283 
00284 F32 LLPerlinNoise::clouds3(F32 x, F32 y, F32 z, F32 freq)
00285 {
00286         F32 t, lx, ly, lz;
00287 
00288         for (t = 0.f ; freq >= 1.f ; freq *= 0.5f)
00289         {
00290                 lx = freq * x;
00291                 ly = freq * y;
00292                 lz = freq * z;
00293 //              t += noise3(lx,ly,lz)/freq;
00294 //              t += fabs(noise3(lx,ly,lz)) / freq;                                     // Like snow - bubbly at low frequencies
00295 //              t += sqrt(fabs(noise3(lx,ly,lz))) / freq;                       // Better at low freq
00296                 t += (noise3(lx,ly,lz)*noise3(lx,ly,lz)) / freq;                
00297         }
00298         return t;
00299 }

Generated on Thu Jul 1 06:09:00 2010 for Second Life Viewer by  doxygen 1.4.7