00001
00002
00003
00004 #include "gtex/gl_extensions.H"
00005 #include "gtex/util.H"
00006
00007 #include "perlin.H"
00008
00009
00010 Perlin* Perlin:: _instance=0;
00011
00012
00013
00014
00015
00016 Perlin::Perlin()
00017 {
00018
00019
00020 if (_instance)
00021 cerr << " Warning: Perlin Texture Generator already exists !! " << endl;
00022
00023 _previous_instance=_instance;
00024 _instance = this;
00025
00026
00027 perlin2d_tex=0;
00028 perlin3d_tex=0;
00029 }
00030
00031 Perlin::~Perlin()
00032 {
00033
00034
00035 _instance = _previous_instance;
00036
00037
00038
00039
00040
00041 }
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061 double
00062 Perlin::noise(unsigned int input)
00063 {
00064 input = (input << 13) ^ input;
00065 return (1.0 - ((input * (input * input *15731 + 789221) + 1376312589) & 0x7fffffff) /1073741824.0);
00066 }
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089 double
00090 Perlin::cubic(double v0, double v1, double v2, double v3, double t)
00091 {
00092 double P = (v3 - v2) - (v0 - v1);
00093 double Q = (v0 - v1) - P;
00094 double R = v2 - v0;
00095 double S = v1;
00096
00097 return P*(t*t*t) + Q*(t*t) + R*t + S;
00098 }
00099
00100 double
00101 Perlin::frac(double x)
00102 {
00103 return (x-int(x));
00104 }
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125 double
00126 Perlin::getval_1D(int freq, double x, unsigned int seed)
00127 {
00128 x=x*freq;
00129
00130
00131
00132
00133
00134 int c0 = (int(x-1)%freq) + seed;
00135 int c1 = (int(x)%freq) + seed;
00136 int c2 = (int(x+1)%freq) + seed;
00137 int c3 = (int(x+2)%freq) + seed;
00138
00139 return cubic(noise(c0),noise(c1),noise(c2),noise(c3),frac(x));
00140 }
00141
00142
00143
00144
00145 double
00146 Perlin::getval_2D(int freq, double x, double y, unsigned int seed)
00147 {
00148 x=x*freq;
00149
00150 unsigned int c0 = (int(x-1)%freq)*freq + seed;
00151 unsigned int c1 = (int(x)%freq)*freq + seed;
00152 unsigned int c2 = (int(x+1)%freq)*freq + seed;
00153 unsigned int c3 = (int(x+2)%freq)*freq + seed;
00154
00155 double v0 = getval_1D(freq, y, c0);
00156 double v1 = getval_1D(freq, y, c1);
00157 double v2 = getval_1D(freq, y, c2);
00158 double v3 = getval_1D(freq, y, c3);
00159
00160 return cubic(v0,v1,v2,v3,frac(x));
00161 }
00162
00163
00164
00165
00166 double
00167 Perlin::getval_3D(int freq, double x, double y, double z, unsigned int seed)
00168 {
00169 x=x*freq;
00170 int fc = freq*freq;
00171
00172 unsigned int c0 = (int(x-1)%freq)*fc + seed;
00173 unsigned int c1 = (int(x)%freq)*fc + seed;
00174 unsigned int c2 = (int(x+1)%freq)*fc + seed;
00175 unsigned int c3 = (int(x+2)%freq)*fc + seed;
00176
00177 double v0 = getval_2D(freq, y, z, c0);
00178 double v1 = getval_2D(freq, y, z, c1);
00179 double v2 = getval_2D(freq, y, z, c2);
00180 double v3 = getval_2D(freq, y, z, c3);
00181
00182 return cubic(v0,v1,v2,v3,frac(x));
00183 }
00184
00185
00186
00187
00188 double
00189 Perlin::getval_4D(int freq, double x, double y, double z, double t, unsigned int seed)
00190 {
00191 x=x*freq;
00192 int fc = freq*freq*freq;
00193
00194 unsigned int c0 = (int(x-1)%freq)*fc + seed;
00195 unsigned int c1 = (int(x)%freq)*fc + seed;
00196 unsigned int c2 = (int(x+1)%freq)*fc + seed;
00197 unsigned int c3 = (int(x+2)%freq)*fc + seed;
00198
00199 double v0 = getval_3D(freq, y, z, t, c0);
00200 double v1 = getval_3D(freq, y, z, t, c1);
00201 double v2 = getval_3D(freq, y, z, t, c2);
00202 double v3 = getval_3D(freq, y, z, t, c3);
00203
00204 return cubic(v0,v1,v2,v3,frac(x));
00205 }
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237 TEXTUREglptr
00238 Perlin::create_perlin_texture3(int tex_stage)
00239 {
00240
00241 if (perlin3d_tex)
00242 return perlin3d_tex;
00243
00244
00245
00246 perlin3d_tex = new TEXTUREgl(GL_TEXTURE_3D,GL_TEXTURE0 + tex_stage);
00247 perlin3d_tex->set_format(GL_RGBA);
00248 perlin3d_tex->set_wrap_r(GL_REPEAT);
00249 perlin3d_tex->set_wrap_s(GL_REPEAT);
00250 perlin3d_tex->set_wrap_t(GL_REPEAT);
00251 perlin3d_tex->set_min_filter(GL_LINEAR);
00252 perlin3d_tex->set_max_filter(GL_LINEAR);
00253
00254
00255
00256 cerr << "Creating 3D Perlin Noise Texture, stage : " << tex_stage << endl;
00257
00258
00259
00260
00261 int noise3DTexSize = 64;
00262 GLubyte *noise3DTexPtr;
00263
00264 int startFrequency = 4;
00265 int numOctaves = 4;
00266 int frequency = startFrequency;
00267 GLubyte *ptr;
00268 double amp = 64.0;
00269
00270 int f, i, j, k, inc;
00271
00272 if ((noise3DTexPtr = new GLubyte[noise3DTexSize*noise3DTexSize*
00273 noise3DTexSize* 4]) == NULL)
00274 {
00275 cerr << "Could not allocate Perlin Noise Texture" << endl;
00276 }
00277 else
00278 cerr << "Texture memory allocated " << endl;
00279
00280
00281 memset(noise3DTexPtr,128,noise3DTexSize*noise3DTexSize*
00282 noise3DTexSize* 4);
00283 ptr=noise3DTexPtr;
00284
00285
00286 cerr << "Generating the 3d noise, it's not crashed just taking its sweet time... " << endl;
00287
00288 for (f = 0; f < numOctaves; f++) {
00289 inc=0;
00290 for(i = 0; i < noise3DTexSize; ++i) {
00291 for(j = 0; j < noise3DTexSize; ++j) {
00292 for(k = 0; k < noise3DTexSize; ++k) {
00293
00294
00295 *(ptr+inc) += static_cast<uchar>(
00296 amp*getval_3D(frequency, double(i)/double(noise3DTexSize),
00297 double(j)/double(noise3DTexSize),
00298 double(k)/double(noise3DTexSize), SEED_1));
00299
00300
00301 *(ptr+inc+1) += static_cast<uchar>(
00302 amp*getval_3D(frequency, double(i)/double(noise3DTexSize),
00303 double(j)/double(noise3DTexSize),
00304 double(k)/double(noise3DTexSize), SEED_2));
00305
00306
00307
00308 *(ptr+inc+2) += static_cast<uchar>(
00309 amp*getval_3D(frequency, double(i)/double(noise3DTexSize),
00310 double(j)/double(noise3DTexSize),
00311 double(k)/double(noise3DTexSize), SEED_3));
00312
00313
00314
00315 *(ptr+inc+3) += static_cast<uchar>(
00316 amp*getval_3D(frequency, double(i)/double(noise3DTexSize),
00317 double(j)/double(noise3DTexSize),
00318 double(k)/double(noise3DTexSize), SEED_4));
00319
00320
00321 inc+=4;
00322 }
00323 }
00324 }
00325 frequency=frequency*2;
00326 amp=amp/2;
00327 }
00328
00329
00330
00331 perlin3d_tex->declare_texture();
00332 perlin3d_tex->apply_texture();
00333
00334
00335 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA,
00336 noise3DTexSize, noise3DTexSize, noise3DTexSize,
00337 0, GL_RGBA, GL_UNSIGNED_BYTE, noise3DTexPtr);
00338
00339 cerr << "Texture copied to hardware " << endl;
00340
00341 GL_VIEW::print_gl_errors("3D perlin noise setup D: ");
00342
00343 delete[] noise3DTexPtr;
00344
00345 return perlin3d_tex;
00346
00347 }
00348
00349
00350
00351
00352 TEXTUREglptr
00353 Perlin::create_perlin_texture2(int tex_stage)
00354 {
00355
00356 if(perlin2d_tex)
00357 return perlin2d_tex;
00358
00359
00360 perlin2d_tex = new TEXTUREgl(GL_TEXTURE_2D,GL_TEXTURE0 + tex_stage);
00361 perlin2d_tex->set_format(GL_RGBA);
00362 perlin2d_tex->set_wrap_r(GL_REPEAT);
00363 perlin2d_tex->set_wrap_s(GL_REPEAT);
00364 perlin2d_tex->set_min_filter(GL_LINEAR);
00365 perlin2d_tex->set_max_filter(GL_LINEAR);
00366
00367
00368
00369 cerr << "Creating 2D Perlin Noise Texture, stage : " << tex_stage << endl;
00370
00371
00372 int noise2DTexSize = 256;
00373 GLubyte *noise2DTexPtr;
00374
00375
00376
00377 int startFrequency = 4;
00378 int numOctaves = 8;
00379 int frequency = startFrequency;
00380 GLubyte *ptr;
00381 int amp = 64;
00382
00383
00384 int f, i, j, inc;
00385
00386
00387 if ((noise2DTexPtr = new GLubyte[noise2DTexSize*noise2DTexSize*4]) == NULL) {
00388 cerr << "Could not allocate Perlin Noise Texture" << endl;
00389 } else
00390 cerr << "Texture memory allocated " << endl;
00391
00392
00393 memset(noise2DTexPtr,128,noise2DTexSize*noise2DTexSize*4);
00394 ptr=noise2DTexPtr;
00395
00396 cerr << "Generating 2D noise... " << endl;
00397
00398 for (f = 0; f < numOctaves; f++) {
00399 inc=0;
00400 for(i = 0; i < noise2DTexSize; ++i) {
00401 for(j = 0; j < noise2DTexSize; ++j) {
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417 *(ptr+inc) += static_cast<uchar>(
00418 amp*getval_2D(frequency, double(i)/double(noise2DTexSize),
00419 double(j)/double(noise2DTexSize), SEED_1));
00420
00421
00422 *(ptr+inc+1) += static_cast<uchar>(
00423 amp*getval_2D(frequency, double(i)/double(noise2DTexSize),
00424 double(j)/double(noise2DTexSize), SEED_2));
00425
00426
00427 *(ptr+inc+2) += static_cast<uchar>(
00428 amp*getval_2D(frequency, double(i)/double(noise2DTexSize),
00429 double(j)/double(noise2DTexSize), SEED_3));
00430
00431
00432 *(ptr+inc+3) += static_cast<uchar>(
00433 amp*getval_2D(frequency, double(i)/double(noise2DTexSize),
00434 double(j)/double(noise2DTexSize), SEED_4));
00435
00436 inc+=4;
00437 }
00438 }
00439 frequency=frequency*2;
00440 amp=amp/2;
00441 }
00442
00443 perlin2d_tex->declare_texture();
00444 perlin2d_tex->apply_texture();
00445
00446 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, noise2DTexSize, noise2DTexSize,
00447 0, GL_RGBA, GL_UNSIGNED_BYTE, noise2DTexPtr);
00448
00449 cerr << "Texture copied to hardware " << endl;
00450
00451 return perlin2d_tex;
00452 }
00453
00454
00455
00456
00457
00458
00459
00460 Vec4
00461 Perlin:: noise1(double x)
00462 {
00463 x = frac(x);
00464
00465 Vec4 output(0.0,0.0,0.0,0.0);
00466 int freq= START_FREQ;
00467 double amp= 0.5;
00468
00469 for(int octave=0; octave<NUM_OCTAVES; octave++)
00470 {
00471 output[0] += amp*getval_1D(freq,x,SEED_1);
00472 output[1] += amp*getval_1D(freq,x,SEED_2);
00473 output[2] += amp*getval_1D(freq,x,SEED_3);
00474 output[3] += amp*getval_1D(freq,x,SEED_4);
00475
00476 amp = amp / double(PRESISTANCE);
00477 freq = freq * PRESISTANCE;
00478 }
00479
00480 return output;
00481 }
00482
00483 Vec4
00484 Perlin:: noise2(double x, double y)
00485 {
00486 x = frac(x);
00487 y = frac(y);
00488
00489 Vec4 output(0.0,0.0,0.0,0.0);
00490 int freq= START_FREQ;
00491 double amp= 0.5;
00492
00493 for(int octave=0; octave<NUM_OCTAVES; octave++)
00494 {
00495 output[0] += amp*getval_2D(freq,x,y,SEED_1);
00496 output[1] += amp*getval_2D(freq,x,y,SEED_2);
00497 output[2] += amp*getval_2D(freq,x,y,SEED_3);
00498 output[3] += amp*getval_2D(freq,x,y,SEED_4);
00499
00500 amp = amp / double(PRESISTANCE);
00501 freq = freq * PRESISTANCE;
00502 }
00503
00504 return output;
00505 }
00506
00507 Vec4
00508 Perlin:: noise3(double x, double y, double z)
00509 {
00510 x = frac(x);
00511 y = frac(y);
00512 z = frac(z);
00513
00514 Vec4 output(0.0,0.0,0.0,0.0);
00515 int freq= START_FREQ;
00516 double amp= 0.5;
00517
00518 for(int octave=0; octave<NUM_OCTAVES; octave++)
00519 {
00520 output[0] += amp*getval_3D(freq,x,y,z,SEED_1);
00521 output[1] += amp*getval_3D(freq,x,y,z,SEED_2);
00522 output[2] += amp*getval_3D(freq,x,y,z,SEED_3);
00523 output[3] += amp*getval_3D(freq,x,y,z,SEED_4);
00524
00525 amp = amp / double(PRESISTANCE);
00526 freq = freq * PRESISTANCE;
00527 }
00528
00529 return output;
00530 }
00531
00532
00533 Vec4
00534 Perlin:: noise4(double x, double y, double z, double t)
00535 {
00536 x = frac(x);
00537 y = frac(y);
00538 z = frac(z);
00539 t = frac(t);
00540
00541 Vec4 output(0.0,0.0,0.0,0.0);
00542 int freq= START_FREQ;
00543 double amp= 0.5;
00544
00545 for(int octave=0; octave<NUM_OCTAVES; octave++)
00546 {
00547 output[0] += amp*getval_4D(freq,x,y,z,t,SEED_1);
00548 output[1] += amp*getval_4D(freq,x,y,z,t,SEED_2);
00549 output[2] += amp*getval_4D(freq,x,y,z,t,SEED_3);
00550 output[3] += amp*getval_4D(freq,x,y,z,t,SEED_4);
00551
00552 amp = amp / double(PRESISTANCE);
00553 freq = freq * PRESISTANCE;
00554 }
00555
00556 return output;
00557 }