arbeit
Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Namespace Members | Compound Members | File Members

PNoise.cpp

Go to the documentation of this file.
00001 //-------------------------------------------------------------------------
00002 //
00003 //   Joe Kniss
00004 //    Perlin Noise Generator
00005 //  PNoise.h Handles basic perlin noise generation, taken from Ken's 
00006 //    original implementaion, adapted for C++  
00007 //     12-9-01
00008 //                   ________    ____   ___ 
00009 //                  |        \  /    | /  /
00010 //                  +---+     \/     |/  /
00011 //                  +--+|  |\    /|     < 
00012 //                  |  ||  | \  / |  |\  \ 
00013 //                  |      |  \/  |  | \  \ 
00014 //                   \_____|      |__|  \__\
00015 //                       Copyright  2001 
00016 //                      Joe Michael Kniss
00017 //               "All Your Base are Belong to Us"
00018 //-------------------------------------------------------------------------
00019 // PNoise.cpp: implementation of the PNoise class.
00020 //
00021 //////////////////////////////////////////////////////////////////////
00022 
00023 #include "PNoise.h"
00024 #include <stdlib.h>
00025 #include <stdio.h>
00026 #include <math.h>
00027 #include <time.h>
00028 
00029 //================ Defines ===========================================
00030 //====================================================================
00031 #define B 0x100
00032 #define BM 0xff
00033 #define N 0x1000
00034 #define NP 12   /* 2^N */
00035 #define NM 0xfff
00036 
00037 #define s_curve(t) ( t * t * (3. - 2. * t) )
00038 #define lerp(t, a, b) ( a + t * (b - a) )
00039 #define setup(i,b0,b1,r0,r1)\
00040    t = vec[i] + N;\
00041    b0 = ((int)t) & BM;\
00042    b1 = (b0+1) & BM;\
00043    r0 = t - (int)t;\
00044    r1 = r0 - 1.;
00045 #define at2(rx,ry) ( rx * q[0] + ry * q[1] )
00046 #define at3(rx,ry,rz) ( rx * q[0] + ry * q[1] + rz * q[2] )
00047 
00048 //////////////////////////////////////////////////////////////////////
00049 // Construction/Destruction
00050 //////////////////////////////////////////////////////////////////////
00051 
00052 PNoise::PNoise()
00053 {
00054    p = new int[B + B + 2];
00055 
00056    g3 = new double*[B + B + 2];
00057    for(int i=0; i<(B + B + 2); ++i){
00058       g3[i] = new double[3];
00059    }
00060 
00061    g2 = new double*[B + B + 2];
00062    for(int i=0; i<(B + B + 2); ++i){
00063       g2[i] = new double[2];
00064    }
00065 
00066    g1 = new double[B + B + 2];
00067 
00068    start = 1;
00069 
00070    _n = 1;
00071    _alpha = 2;
00072    _beta  = 2;
00073 
00074    seed();
00075    init();
00076 }
00077 
00078 PNoise::PNoise(int s)
00079 {
00080    p = new int[B + B + 2];
00081 
00082    g3 = new double*[B + B + 2];
00083    for(int i=0; i<(B + B + 2); ++i){
00084       g3[i] = new double[3];
00085    }
00086 
00087    g2 = new double*[B + B + 2];
00088    for(int i=0; i<(B + B + 2); ++i){
00089       g2[i] = new double[2];
00090    }
00091 
00092    g1 = new double[B + B + 2];
00093 
00094    start = 1;
00095 
00096    _n = 1;
00097    _alpha = 2;
00098    _beta  = 2;
00099 
00100    seed(s);
00101    init();
00102 }
00103 
00104 PNoise::~PNoise()
00105 {
00106    delete[] p;
00107    for(int i=0; i< B+B+2; ++ i)
00108       delete[] g3[i];
00109    delete[] g3;
00110    for(int i=0; i< B+B+2; ++ i)
00111       delete[] g2[i];
00112    delete[] g2;
00113    delete[] g1;
00114 }
00115 
00116 //////////////////////////////////////////////////////////////////////
00117 // Public
00118 //////////////////////////////////////////////////////////////////////
00119 
00120 void PNoise::seed()
00121 {
00122    srand(time(NULL));
00123 }
00124 
00125 void PNoise::seed(int s)
00126 {
00127    srand(s);
00128 }
00129 
00130 
00131 double PNoise::PerlinNoise1D(double x, int n, double alpha,double beta)
00132 {
00133    int i;
00134    double val,sum = 0;
00135    double p,scale = 1;
00136 
00137    p = x;
00138    for (i=0;i<n;i++) {
00139       val = noise1(p);
00140       sum += val / scale;
00141       scale *= alpha;
00142       p *= beta;
00143    }
00144    return(sum);
00145 }
00146 
00147 //======================================================================================
00148 //======================================================================================
00149 double PNoise::PerlinNoise2D(double x,double y, int n, double alpha,double beta)
00150 {
00151    int i;
00152    double val,sum = 0;
00153    double p[2],scale = 1;
00154 
00155    p[0] = x;
00156    p[1] = y;
00157    for (i=0;i<n;i++) {
00158       val = noise2(p);
00159       sum += val / scale;
00160       scale *= alpha;
00161       p[0] *= beta;
00162       p[1] *= beta;
00163    }
00164    return(sum);
00165 }
00166 
00167 //======================================================================================
00168 //======================================================================================
00169 double PNoise::PerlinNoise3D(double x,double y,double z, int n, double alpha,double beta)
00170 {
00171    int i;
00172    double val,sum = 0;
00173    double p[3],scale = 1;
00174 
00175    p[0] = x;
00176    p[1] = y;
00177    p[2] = z;
00178    for (i=0;i<n;i++) {
00179       val = noise3(p);
00180       sum += val / scale;
00181       scale *= alpha;
00182       p[0] *= beta;
00183       p[1] *= beta;
00184       p[2] *= beta;
00185    }
00186    return(sum);
00187 }
00188 
00189 //======================================================================================
00190 //======================================================================================
00191 #ifndef ABS
00192 #define ABS(x) ((x)<0 ? (-x) : (x))
00193 #endif
00194 
00195 double PNoise::PerlinNoise3DABS(double x,double y,double z, int n, double alpha,double beta)
00196 {
00197    int i;
00198    double val,sum = 0;
00199    double p[3],scale = 1;
00200 
00201    p[0] = x;
00202    p[1] = y;
00203    p[2] = z;
00204    for (i=0;i<n;i++) {
00205       val = noise3(p);
00206       val = ABS(val);
00207       sum += val / scale;
00208       scale *= alpha;
00209       p[0] *= beta;
00210       p[1] *= beta;
00211       p[2] *= beta;
00212    }
00213    return(sum);
00214 }
00215 
00216 //======================================================================================
00217 //======================================================================================
00218 void PNoise::setParams(int n, double alpha, double beta)
00219 {
00220    _alpha = alpha;
00221    _beta  = beta;
00222    _n     = n;
00223 }
00224 
00225 //======================================================================================
00226 //======================================================================================
00227 double PNoise::PN1D(double x)
00228 {
00229    return PerlinNoise1D(x,_n,_alpha,_beta);
00230 }
00231 
00232 //======================================================================================
00233 //======================================================================================
00234 double PNoise::PN2D(double x, double y)
00235 {
00236    return PerlinNoise2D(x, y, _n, _alpha, _beta);
00237 }
00238 
00239 //======================================================================================
00240 //======================================================================================
00241 double PNoise::PN3D(double x, double y, double z)
00242 {
00243    return PerlinNoise3D(x,y,z, _n, _alpha, _beta);
00244 }
00245 
00246 //======================================================================================
00247 //======================================================================================
00248 double PNoise::PN3DA(double x, double y, double z)
00249 {
00250    return PerlinNoise3DABS(x,y,z, _n, _alpha, _beta);
00251 }
00252 
00253 
00254 //======================================================================================
00255 //======================================================================================
00256 ////////////////////////////////////////////////////////////////////////////////////////
00257 // Private
00258 ////////////////////////////////////////////////////////////////////////////////////////
00259 //======================================================================================
00260 //======================================================================================
00261 
00262 inline int PNoise::random()
00263 {
00264    return rand();
00265 }
00266 
00267 //======================================================================================
00268 //======================================================================================
00269 double PNoise::noise1(double arg)
00270 {
00271    int bx0, bx1;
00272    double rx0, rx1, sx, t, u, v, vec[1];
00273 
00274    vec[0] = arg;
00275    if (start) {
00276       start = 0;
00277       init();
00278    }
00279 
00280    setup(0,bx0,bx1,rx0,rx1);
00281 
00282    sx = s_curve(rx0);
00283    u = rx0 * g1[ p[ bx0 ] ];
00284    v = rx1 * g1[ p[ bx1 ] ];
00285 
00286    return(lerp(sx, u, v));
00287 }
00288 
00289 //======================================================================================
00290 //======================================================================================
00291 double PNoise::noise2(double vec[2])
00292 {
00293    int bx0, bx1, by0, by1, b00, b10, b01, b11;
00294    double rx0, rx1, ry0, ry1, *q, sx, sy, a, b, t, u, v;
00295    int i, j;
00296 
00297    if (start) {
00298       start = 0;
00299       init();
00300    }
00301 
00302    setup(0, bx0,bx1, rx0,rx1);
00303    setup(1, by0,by1, ry0,ry1);
00304 
00305    i = p[ bx0 ];
00306    j = p[ bx1 ];
00307 
00308    b00 = p[ i + by0 ];
00309    b10 = p[ j + by0 ];
00310    b01 = p[ i + by1 ];
00311    b11 = p[ j + by1 ];
00312 
00313    sx = s_curve(rx0);
00314    sy = s_curve(ry0);
00315 
00316    q = g2[ b00 ] ; u = at2(rx0,ry0);
00317    q = g2[ b10 ] ; v = at2(rx1,ry0);
00318    a = lerp(sx, u, v);
00319 
00320    q = g2[ b01 ] ; u = at2(rx0,ry1);
00321    q = g2[ b11 ] ; v = at2(rx1,ry1);
00322    b = lerp(sx, u, v);
00323 
00324    return lerp(sy, a, b);
00325 }
00326 
00327 //======================================================================================
00328 //======================================================================================
00329 double PNoise::noise3(double vec[3])
00330 {
00331    int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11;
00332    double rx0, rx1, ry0, ry1, rz0, rz1, *q, sy, sz, a, b, c, d, t, u, v;
00333    int i, j;
00334 
00335    if (start) {
00336       start = 0;
00337       init();
00338    }
00339 
00340    setup(0, bx0,bx1, rx0,rx1);
00341    setup(1, by0,by1, ry0,ry1);
00342    setup(2, bz0,bz1, rz0,rz1);
00343 
00344    i = p[ bx0 ];
00345    j = p[ bx1 ];
00346 
00347    b00 = p[ i + by0 ];
00348    b10 = p[ j + by0 ];
00349    b01 = p[ i + by1 ];
00350    b11 = p[ j + by1 ];
00351 
00352    t  = s_curve(rx0);
00353    sy = s_curve(ry0);
00354    sz = s_curve(rz0);
00355 
00356    q = g3[ b00 + bz0 ] ; u = at3(rx0,ry0,rz0);
00357    q = g3[ b10 + bz0 ] ; v = at3(rx1,ry0,rz0);
00358    a = lerp(t, u, v);
00359 
00360    q = g3[ b01 + bz0 ] ; u = at3(rx0,ry1,rz0);
00361    q = g3[ b11 + bz0 ] ; v = at3(rx1,ry1,rz0);
00362    b = lerp(t, u, v);
00363 
00364    c = lerp(sy, a, b);
00365 
00366    q = g3[ b00 + bz1 ] ; u = at3(rx0,ry0,rz1);
00367    q = g3[ b10 + bz1 ] ; v = at3(rx1,ry0,rz1);
00368    a = lerp(t, u, v);
00369 
00370    q = g3[ b01 + bz1 ] ; u = at3(rx0,ry1,rz1);
00371    q = g3[ b11 + bz1 ] ; v = at3(rx1,ry1,rz1);
00372    b = lerp(t, u, v);
00373 
00374    d = lerp(sy, a, b);
00375 
00376    return lerp(sz, c, d);
00377 }
00378 
00379 //======================================================================================
00380 //======================================================================================
00381 void PNoise::normalize2(double v[2])
00382 {
00383    double s;
00384 
00385    s = sqrt(v[0] * v[0] + v[1] * v[1]);
00386    v[0] = v[0] / s;
00387    v[1] = v[1] / s;
00388 }
00389 
00390 //======================================================================================
00391 //======================================================================================
00392 void PNoise::normalize3(double v[3])
00393 {
00394    double s;
00395 
00396    s = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
00397    v[0] = v[0] / s;
00398    v[1] = v[1] / s;
00399    v[2] = v[2] / s;
00400 }
00401 
00402 //======================================================================================
00403 //======================================================================================
00404 void PNoise::init(void)
00405 {
00406    int i, j, k;
00407 
00408    for (i = 0 ; i < B ; i++) {
00409       p[i] = i;
00410       g1[i] = (double)((random() % (B + B)) - B) / B;
00411 
00412       for (j = 0 ; j < 2 ; j++)
00413          g2[i][j] = (double)((random() % (B + B)) - B) / B;
00414       normalize2(g2[i]);
00415 
00416       for (j = 0 ; j < 3 ; j++)
00417          g3[i][j] = (double)((random() % (B + B)) - B) / B;
00418       normalize3(g3[i]);
00419    }
00420 
00421    while (--i) {
00422       k = p[i];
00423       p[i] = p[j = random() % B];
00424       p[j] = k;
00425    }
00426 
00427    for (i = 0 ; i < B + 2 ; i++) {
00428       p[B + i] = p[i];
00429       g1[B + i] = g1[i];
00430       for (j = 0 ; j < 2 ; j++)
00431          g2[B + i][j] = g2[i][j];
00432       for (j = 0 ; j < 3 ; j++)
00433          g3[B + i][j] = g3[i][j];
00434    }
00435 }
00436 
00437 //================================================================
00438 // Gen 2D texture
00439 void gen2DPerlinTexture(float *&data, unsigned int sx, unsigned int sy,
00440                         unsigned int   comp,          /// greyscale, RGBA, how many??
00441                         int   octaves, 
00442                         float frequencyScale,
00443                         float amplitudeScale,
00444                         bool  absNoise)
00445 {
00446    PNoise *parray = new PNoise[comp];
00447    for(unsigned int i=0; i< comp; ++i)
00448    {
00449       parray->seed(i);
00450       parray->setParams(octaves,frequencyScale, amplitudeScale);
00451    }
00452 
00453    data = new float[sx*sy*comp];
00454 
00455    for(unsigned int y=0; y<sy; ++y)
00456    {
00457       for(unsigned int x=0; x<sx; ++x)
00458       {
00459          for(unsigned int c=0; c<comp; ++c)
00460          {
00461             if(absNoise)
00462             {
00463                data[y*sx*comp + x*comp + c] = float(parray[c].PN2D(x/float(sx),y/float(sy))) * .5f + .5f;
00464             }
00465             else
00466             {
00467                data[y*sx*comp + x*comp + c] = float(parray[c].PN3DA(x/float(sx),y/float(sy),0)) * .5f + .5f;
00468             }
00469          }
00470       }
00471    }
00472 
00473 }
00474 
00475 //================================================================
00476 // Gen 3D texture
00477 void gen3DPerlinTexture(float *&data, unsigned int sx, unsigned int sy, unsigned int sz,
00478                         unsigned int   comp,          /// greyscale, RGBA, how many??
00479                         int   octaves, 
00480                         float frequencyScale,
00481                         float amplitudeScale,
00482                         bool  absNoise)        /// absolute value noise
00483 {
00484    PNoise *parray = new PNoise[comp];
00485    for(unsigned int i=0; i< comp; ++i)
00486    {
00487       parray->seed(rand());
00488       parray->setParams(octaves,frequencyScale, amplitudeScale);
00489    }
00490 
00491    data = new float[sx*sy*sz*comp];
00492 
00493    for(unsigned int z=0; z<sz; ++z)
00494    {
00495       for(unsigned int y=0; y<sy; ++y)
00496       {
00497          for(unsigned int x=0; x<sx; ++x)
00498          {
00499             for(unsigned int c=0; c<comp; ++c)
00500             {
00501                if(!absNoise)
00502                {
00503                   data[z*sy*sx*comp + y*sx*comp + x*comp + c] = float(parray[c].PN3D(x/float(sx/8),y/float(sx/8),z/float(sx/8))) * .5f + .5f;
00504                }
00505                else
00506                {
00507                   data[z*sy*sx*comp + y*sx*comp + x*comp + c] = float(parray[c].PN3DA(x/float(sx/8),y/float(sy/8),z/float(sz/8))) * .5f + .5f;
00508                }
00509             }
00510          }
00511       }
00512    }
00513 }
00514 

Send questions, comments, and bug reports to:
jmk