Perlin.cpp

Go to the documentation of this file.
00001 /*
00002 SagaEngine library
00003 Copyright (c) 2002-2006 Skalden Studio AS
00004 
00005 This software is provided 'as-is', without any express or implied 
00006 warranty. In no event will the authors be held liable for any 
00007 damages arising from the use of this software.
00008 
00009 Permission is granted to distribute the library under the terms of the 
00010 Q Public License version 1.0. Be sure to read and understand the license
00011 before using the library. It should be included here, or you may read it
00012 at http://www.trolltech.com/products/qt/licenses/licensing/qpl
00013 
00014 The original version of this library can be located at:
00015 http://www.sagaengine.com/
00016 
00017 Rune Myrland
00018 rune@skalden.com
00019 */
00020 
00021 
00022 #include "Perlin.hpp"
00023 
00024 namespace se_core {
00025 
00026     const unsigned char Perlin
00027     ::defaultPermutations_[256] = {
00028         151,160,137,91,90,15,131, 13,201,95,96,53,194,233,7,
00029         225,140,36,103,30,69,142,8,99,37,240,21,10,23,190,6,
00030         148,247,120,234,75, 0,26,197, 62,94,252,219,203,117,
00031         35,11,32,57,177,33, 88,237,149,56,87,174,20,125,136,
00032         171,168, 68,175,74,165,71,134,139,48,27,166, 77,146,
00033         158,231,83,111,229,122,60,211,133,230,220,105,92,41,
00034         55,46,245,40,244,102,143,54, 65,25,63,161, 1,216,80,
00035         73,209,76,132,187,208,89,18,169,200,196,135,130,116,
00036         188,159,86,164,100,109,198,173,186, 3,64,52,217,226,
00037         250,124,123, 5,202,38,147,118,126,255,82,85,212,207,
00038         206, 59,227, 47,16,58,17,182,189,28,42, 223,183,170,
00039         213,119,248,152,2,44,154,163,70,221,153,101,155,167,
00040         43,172,9,129,22,39,253,19,98,108,110,79,113,224,232,
00041         178,185, 112,104,218,246,97,228, 251,34,242,193,238,
00042         210,144,12,191,179,162,241,81,51,145,235,249,14,239,
00043         107, 49,192,214, 31,181,199,106,157,184, 84,204,176,
00044         115,121,50,45,127, 4,150,254,138,236,205,93,222,114,
00045         67, 29,24, 72,243,141,128,195,78, 66,215,61,156,180
00046     };
00047 
00048 
00049     Perlin
00050     ::Perlin() {
00051         defaultPermutations();
00052     }
00053 
00054 
00055     Perlin
00056     ::Perlin(const unsigned int seed) {
00057         shufflePermutations(seed);
00058     }
00059 
00060 
00061     void Perlin
00062     ::defaultPermutations() {
00063         for(short i = 0; i < 256; ++i) {
00064             permutations_[i] = permutations_[i + 256] = defaultPermutations_[i];
00065         }
00066     }
00067 
00068 
00069     void Perlin
00070     ::shufflePermutations(const unsigned int seed) {
00071         const unsigned int modseed = (1402024253 * seed + 586950981) >> 24;     // 0 ÷ 255
00072 
00073         for(short i = 0; i < 256; ++i ) {
00074             permutations_[i] = permutations_[i + 256] = defaultPermutations_[(modseed + i) & 255];
00075         }
00076     }
00077 
00078     float Perlin
00079     ::gradient( const int hash, const float x ) {
00080         return (hash & 1) ? x : -x;
00081     }
00082 
00083 
00084     float Perlin
00085     ::gradient( const int hash, const float x, const float y) {
00086         static const float gradients[8][2] = {
00087             {  1.0f,  1.0f }, // 0
00088             {  1.0f, -1.0f }, // 1
00089             { -1.0f,  1.0f }, // 2
00090             { -1.0f, -1.0f }, // 3
00091             {  1.0f,  0.0f }, // 4
00092             { -1.0f,  0.0f }, // 5
00093             {  0.0f,  1.0f }, // 6
00094             {  0.0f, -1.0f }  // 7
00095         };
00096         int h = hash & 7;
00097         return x * gradients[h][0] + y * gradients[h][1];
00098     }
00099 
00100 
00101     float Perlin
00102     ::gradient( const int hash, const float x, const float y, const float z) {
00103         static const float gradients[16][3] = {
00104             {  1.0f,  1.0f,  0.0f }, // 0
00105             { -1.0f,  1.0f,  0.0f }, // 1
00106             {  1.0f, -1.0f,  0.0f }, // 2
00107             { -1.0f, -1.0f,  0.0f }, // 3
00108 
00109             {  1.0f,  0.0f,  1.0f }, // 4
00110             { -1.0f,  0.0f,  1.0f }, // 5
00111             {  1.0f,  0.0f, -1.0f }, // 6
00112             { -1.0f,  0.0f, -1.0f }, // 7
00113 
00114             {  0.0f,  1.0f,  1.0f }, // 8
00115             {  0.0f, -1.0f,  1.0f }, // 9
00116             {  0.0f,  1.0f, -1.0f }, // 10
00117             {  0.0f, -1.0f, -1.0f }, // 11
00118 
00119             // padding from 12 to 16 cases, for explanation
00120             // see Perlin's document on Improved Perlin Noise implementation
00121             {  1.0f,  1.0f,  0.0f }, // 12
00122             {  0.0f, -1.0f,  1.0f }, // 13
00123             { -1.0f,  1.0f,  0.0f }, // 14
00124             {  0.0f, -1.0f, -1.0f }, // 15
00125         };
00126         int h = hash & 15;
00127         return x * gradients[h][0] + y * gradients[h][1] + z * gradients[h][2];
00128     }
00129 
00130 
00131     float Perlin
00132     ::gradient( const int hash, const float x, const float y, const float z, const float w) {
00133         static const float gradients[32][4] = {
00134             { -1.0f, -1.0f, -1.0f,  0.0 }, // 0
00135             { -1.0f, -1.0f,  1.0f,  0.0 }, // 1
00136             { -1.0f,  1.0f, -1.0f,  0.0 }, // 2
00137             { -1.0f,  1.0f,  1.0f,  0.0 }, // 3
00138 
00139             {  1.0f, -1.0f, -1.0f,  0.0 }, // 4
00140             {  1.0f, -1.0f,  1.0f,  0.0 }, // 5
00141             {  1.0f,  1.0f, -1.0f,  0.0 }, // 6
00142             {  1.0f,  1.0f,  1.0f,  0.0 }, // 7
00143 
00144 
00145             { -1.0f, -1.0f,  0.0f, -1.0 }, // 8
00146             { -1.0f,  1.0f,  0.0f, -1.0 }, // 9
00147             {  1.0f, -1.0f,  0.0f, -1.0 }, // 10
00148             {  1.0f,  1.0f,  0.0f, -1.0 }, // 11
00149 
00150             { -1.0f, -1.0f,  0.0f,  1.0 }, // 12
00151             { -1.0f,  1.0f,  0.0f,  1.0 }, // 13
00152             {  1.0f, -1.0f,  0.0f,  1.0 }, // 14
00153             {  1.0f,  1.0f,  0.0f,  1.0 }, // 15
00154 
00155             { -1.0f,  0.0f, -1.0f, -1.0 }, // 16
00156             {  1.0f,  0.0f, -1.0f, -1.0 }, // 17
00157             { -1.0f,  0.0f, -1.0f,  1.0 }, // 18
00158             {  1.0f,  0.0f, -1.0f,  1.0 }, // 19
00159 
00160             { -1.0f,  0.0f, -1.0f,  1.0 }, // 20
00161             {  1.0f,  0.0f, -1.0f,  1.0 }, // 21
00162             { -1.0f,  0.0f,  1.0f,  1.0 }, // 22
00163             {  1.0f,  0.0f,  1.0f,  1.0 }, // 23
00164 
00165             {  0.0f, -1.0f, -1.0f, -1.0 }, // 24
00166             {  0.0f, -1.0f, -1.0f,  1.0 }, // 25
00167             {  0.0f, -1.0f,  1.0f, -1.0 }, // 26
00168             {  0.0f, -1.0f,  1.0f,  1.0 }, // 27
00169 
00170             {  0.0f,  1.0f, -1.0f, -1.0 }, // 28
00171             {  0.0f,  1.0f, -1.0f,  1.0 }, // 29
00172             {  0.0f,  1.0f,  1.0f, -1.0 }, // 30
00173             {  0.0f,  1.0f,  1.0f,  1.0 }, // 31
00174         };
00175         int h = hash & 31;
00176         return x * gradients[h][0] + y * gradients[h][1] + z * gradients[h][2] + w * gradients[h][3];
00177     }
00178 
00179 
00180     int Perlin
00181     ::tileMod( const int index, const unsigned int frequency ) {
00182         return (index < 0) ? abs(index) * (frequency - 1) % frequency : index % frequency;
00183     }
00184 
00185 
00186     float Perlin
00187     ::noise( float x, const unsigned int frequency, const bool tile ) {
00188         int X = floor( x );
00189         x -= X;
00190         X &= 255;
00191 
00192         int X1 = X + 1;
00193         if( tile ) X1 = tileMod( X1, frequency );
00194 
00195         return lerp( fade( x ), gradient( permutations_[ X  ], x),
00196                      gradient( permutations_[ X1 ], x - 1 ));
00197     }
00198 
00199 
00200     float Perlin
00201     ::noise( float x, float y,
00202              const unsigned int frequencyX, const unsigned int frequencyY,
00203              const bool tileX, const bool tileY ) {
00204         int X = floor( x );
00205         int Y = floor( y );
00206 
00207         // fractional parts ( from 0.0 to 1.0 )
00208         x -= X;
00209         y -= Y;
00210 
00211         const float a = fade( x );
00212         const float b = fade( y );
00213 
00214         X &= 255;
00215         Y &= 255;
00216 
00217         int X1 = X + 1; if( tileX ) X1 = tileMod( X1, frequencyX );
00218         int Y1 = Y + 1; if( tileY ) Y1 = tileMod( Y1, frequencyY );
00219 
00220         int AA = permutations_[ X  ] + Y;       // left     bottom
00221         int BA = permutations_[ X1 ] + Y;       // right    bottom
00222         int AB = permutations_[ X  ] + Y1;  // left     top
00223         int BB = permutations_[ X1 ] + Y1;  // right    top
00224 
00225         const float x_1 = x - 1.0f;
00226         const float y_1 = y - 1.0f;
00227 
00228         float gAA = gradient( permutations_[ AA ], x, y);
00229         float gBA = gradient( permutations_[ BA ], x_1, y);
00230         float gAB = gradient( permutations_[ AB ], x, y_1);
00231         float gBB = gradient( permutations_[ BB ], x_1, y_1);
00232 
00233         float r = lerp( b, lerp( a, gAA, gBA), lerp( a, gAB, gBB));
00234         return r;
00235     }
00236 
00237 
00238     float Perlin
00239     ::noise(float x, float y, float z,
00240             const unsigned int frequencyX, const unsigned int frequencyY, const unsigned int frequencyZ,
00241             const bool tileX, const bool tileY, const bool tileZ ) {
00242         int X = floor( x );
00243         int Y = floor( y );
00244         int Z = floor( z );
00245 
00246         // fractional parts ( from 0.0 to 1.0 )
00247         x -= X;
00248         y -= Y;
00249         z -= Z;
00250 
00251         const float a = fade( x );
00252         const float b = fade( y );
00253         const float c = fade( z );
00254 
00255         X &= 255;
00256         Y &= 255;
00257         Z &= 255;
00258 
00259         int X1 = X + 1; if( tileX ) X1 = tileMod( X1, frequencyX );
00260         int Y1 = Y + 1; if( tileY ) Y1 = tileMod( Y1, frequencyY );
00261         int Z1 = Z + 1; if( tileZ ) Z1 = tileMod( Z1, frequencyZ );
00262 
00263         //--------------------------
00264         // indices for 2 noise quads
00265         //--------------------------
00266 
00267         int AA = permutations_[ X  ] + Y;       // left     bottom
00268         int BA = permutations_[ X1 ] + Y;       // right    bottom
00269         int AB = permutations_[ X  ] + Y1;  // left     top
00270         int BB = permutations_[ X1 ] + Y1;  // right    top
00271 
00272         // front-side quad indices
00273         int AAA = permutations_[ AA ] + Z;
00274         int BAA = permutations_[ BA ] + Z;
00275         int ABA = permutations_[ AB ] + Z;
00276         int BBA = permutations_[ BB ] + Z;
00277 
00278         // back-side quad indices
00279         int AAB = permutations_[ AA ] + Z1;
00280         int BAB = permutations_[ BA ] + Z1;
00281         int ABB = permutations_[ AB ] + Z1;
00282         int BBB = permutations_[ BB ] + Z1;
00283 
00284         //-----------------------
00285         // lerp between the quads
00286         //-----------------------
00287 
00288         const float x_1 = x - 1.0f;
00289         const float y_1 = y - 1.0f;
00290         const float z_1 = z - 1.0f;
00291 
00292         return lerp( c, lerp( b, lerp( a, gradient( permutations_[ AAA ], x  , y  , z   ),
00293                                        gradient( permutations_[ BAA ], x_1, y  , z   )),
00294                               lerp( a, gradient( permutations_[ ABA ], x  , y_1, z   ),
00295                                     gradient( permutations_[ BBA ], x_1, y_1, z   ))),
00296                      lerp( b, lerp( a, gradient( permutations_[ AAB ], x  , y  , z_1 ),
00297                                     gradient( permutations_[ BAB ], x_1, y  , z_1 )),
00298                            lerp( a, gradient( permutations_[ ABB ], x  , y_1, z_1 ),
00299                                  gradient( permutations_[ BBB ], x_1, y_1, z_1 ))));
00300     }
00301 
00302 
00303     float Perlin
00304     ::noise(float x, float y, float z, float w,
00305             const unsigned int frequencyX, const unsigned int frequencyY,
00306             const unsigned int frequencyZ, const unsigned int frequencyW,
00307             const bool tileX, const bool tileY, const bool tileZ, const bool tileW )
00308     {
00309         int X = floor( x );
00310         int Y = floor( y );
00311         int Z = floor( z );
00312         int W = floor( w );
00313 
00314         x -= X;
00315         y -= Y;
00316         z -= Z;
00317         w -= W;
00318 
00319         const float a = fade( x );
00320         const float b = fade( y );
00321         const float c = fade( z );
00322         const float d = fade( w );
00323 
00324         X &= 255;
00325         Y &= 255;
00326         Z &= 255;
00327         W &= 255;
00328 
00329         int X1 = X + 1; if( tileX ) X1 = tileMod( X1, frequencyX );
00330         int Y1 = Y + 1; if( tileY ) Y1 = tileMod( Y1, frequencyY );
00331         int Z1 = Z + 1; if( tileZ ) Z1 = tileMod( Z1, frequencyZ );
00332         int W1 = W + 1; if( tileW ) W1 = tileMod( W1, frequencyW );
00333 
00334         //----------------------------
00335         // indices for 2 noise volumes
00336         //----------------------------
00337 
00338         int AA = permutations_[ X  ] + Y;       // left     bottom
00339         int BA = permutations_[ X1 ] + Y;       // right    bottom
00340 
00341         int AB = permutations_[ X  ] + Y1;  // left     top
00342         int BB = permutations_[ X1 ] + Y1;  // right    top
00343 
00344         int AAA = permutations_[ AA ] + Z;  // left     bottom  front
00345         int BAA = permutations_[ BA ] + Z;  // right    bottom  front
00346         int ABA = permutations_[ AB ] + Z;  // left     top     front
00347         int BBA = permutations_[ BB ] + Z;  // right    top     front
00348 
00349         int AAB = permutations_[ AA ] + Z1; // left     bottom  back
00350         int BAB = permutations_[ BA ] + Z1; // right    bottom  back
00351         int ABB = permutations_[ AB ] + Z1; // left     top     back
00352         int BBB = permutations_[ BB ] + Z1; // right    top     back
00353 
00354         int AAAA = permutations_[ AAA ] + W;    // left     bottom  front   volume1
00355         int BAAA = permutations_[ BAA ] + W;    // right    bottom  front   volume1
00356         int ABAA = permutations_[ ABA ] + W;    // left     top     front   volume1
00357         int BBAA = permutations_[ BBA ] + W;    // right    top     front   volume1
00358         int AABA = permutations_[ AAB ] + W;    // left     bottom  back    volume1
00359         int BABA = permutations_[ BAB ] + W;    // right    bottom  back    volume1
00360         int ABBA = permutations_[ ABB ] + W;    // left     top     back    volume1
00361         int BBBA = permutations_[ BBB ] + W;    // right    top     back    volume1
00362 
00363         int AAAB = permutations_[ AAA ] + W1;   // left     bottom  front   volume2
00364         int BAAB = permutations_[ BAA ] + W1;   // right    bottom  front   volume2
00365         int ABAB = permutations_[ ABA ] + W1;   // left     top     front   volume2
00366         int BBAB = permutations_[ BBA ] + W1;   // right    top     front   volume2
00367         int AABB = permutations_[ AAB ] + W1;   // left     bottom  back    volume2
00368         int BABB = permutations_[ BAB ] + W1;   // right    bottom  back    volume2
00369         int ABBB = permutations_[ ABB ] + W1;   // left     top     back    volume2
00370         int BBBB = permutations_[ BBB ] + W1;   // right    top     back    volume2
00371 
00372         //-------------------------
00373         // lerp between the volumes
00374         //-------------------------
00375 
00376         const float x_1 = x - 1.0f;
00377         const float y_1 = y - 1.0f;
00378         const float z_1 = z - 1.0f;
00379         const float w_1 = w - 1.0f;
00380 
00381         return lerp( d, lerp( c, lerp( b, lerp( a,  gradient( permutations_[ AAAA ], x  , y  , z  , w   ),
00382                                                 gradient( permutations_[ BAAA ], x_1, y  , z  , w   )),
00383                                        lerp( a, gradient( permutations_[ ABAA ], x  , y_1, z  , w   ),
00384                                              gradient( permutations_[ BBAA ], x_1, y_1, z  , w   ))),
00385                               lerp( b, lerp( a, gradient( permutations_[ AABA ], x  , y  , z_1, w   ),
00386                                              gradient( permutations_[ BABA ], x_1, y  , z_1, w   )),
00387                                     lerp( a,    gradient( permutations_[ ABBA ], x  , y_1, z_1, w   ),
00388                                           gradient( permutations_[ BBBA ], x_1, y_1, z_1, w   )))),
00389                      lerp( c, lerp( b, lerp( a, gradient( permutations_[ AAAB ], x  , y  , z  , w_1 ),
00390                                              gradient( permutations_[ BAAB ], x_1, y  , z  , w_1 )),
00391                                     lerp( a,    gradient( permutations_[ ABAB ], x  , y_1, z  , w_1 ),
00392                                           gradient( permutations_[ BBAB ], x_1, y_1, z  , w_1 ))),
00393                            lerp( b, lerp( a,    gradient( permutations_[ AABB ], x  , y  , z_1, w_1 ),
00394                                           gradient( permutations_[ BABB ], x_1, y  , z_1, w_1 )),
00395                                  lerp( a,   gradient( permutations_[ ABBB ], x  , y_1, z_1, w_1 ),
00396                                        gradient( permutations_[ BBBB ], x_1, y_1, z_1, w_1 )))));
00397     }
00398 
00399 
00400     float Perlin
00401     ::noise( const Vector3& v, const unsigned int freq, bool tile) {
00402         return noise(CoorT::toFloat(v.x_),
00403                      CoorT::toFloat(v.y_),
00404                      CoorT::toFloat(v.z_),
00405                      freq, freq, freq,
00406                      tile, tile, tile);
00407     }
00408 
00409 
00410 }

Home Page | SagaEngine trunk (updated nightly) reference generated Sun Dec 2 20:06:12 2007 by Doxygen version 1.3.9.1.

SourceForge.net Logo