Blender  V2.59
FFT_NOISE.h
Go to the documentation of this file.
00001 
00004 
00005 // This file is part of Wavelet Turbulence.
00006 // 
00007 // Wavelet Turbulence is free software: you can redistribute it and/or modify
00008 // it under the terms of the GNU General Public License as published by
00009 // the Free Software Foundation, either version 3 of the License, or
00010 // (at your option) any later version.
00011 // 
00012 // Wavelet Turbulence is distributed in the hope that it will be useful,
00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 // GNU General Public License for more details.
00016 // 
00017 // You should have received a copy of the GNU General Public License
00018 // along with Wavelet Turbulence.  If not, see <http://www.gnu.org/licenses/>.
00019 // 
00020 // Copyright 2008 Theodore Kim and Nils Thuerey
00021 // 
00023 //
00024 
00025 #ifndef FFT_NOISE_H_
00026 #define FFT_NOISE_H_
00027 
00028 #if FFTW3==1
00029 #include <iostream>
00030 #include <fftw3.h>
00031 #include <MERSENNETWISTER.h>
00032 
00033 #include "WAVELET_NOISE.h"
00034 
00035 #ifndef M_PI
00036 #define M_PI 3.14159265
00037 #endif
00038 
00040 // shift spectrum to the format that FFTW expects
00042 static void shift3D(float*& field, int xRes, int yRes, int zRes)
00043 {
00044   int xHalf = xRes / 2;
00045   int yHalf = yRes / 2;
00046   int zHalf = zRes / 2;
00047  // int slabSize = xRes * yRes;
00048   for (int z = 0; z < zHalf; z++)
00049     for (int y = 0; y < yHalf; y++)
00050       for (int x = 0; x < xHalf; x++)
00051       {
00052         int index = x + y * xRes + z * xRes * yRes;
00053         float temp;
00054         int xSwap = xHalf;
00055         int ySwap = yHalf * xRes;
00056         int zSwap = zHalf * xRes * yRes;
00057         
00058         // [0,0,0] to [1,1,1]
00059         temp = field[index];
00060         field[index] = field[index + xSwap + ySwap + zSwap];
00061         field[index + xSwap + ySwap + zSwap] = temp;
00062 
00063         // [1,0,0] to [0,1,1]
00064         temp = field[index + xSwap];
00065         field[index + xSwap] = field[index + ySwap + zSwap];
00066         field[index + ySwap + zSwap] = temp;
00067 
00068         // [0,1,0] to [1,0,1]
00069         temp = field[index + ySwap];
00070         field[index + ySwap] = field[index + xSwap + zSwap];
00071         field[index + xSwap + zSwap] = temp;
00072         
00073         // [0,0,1] to [1,1,0]
00074         temp = field[index + zSwap];
00075         field[index + zSwap] = field[index + xSwap + ySwap];
00076         field[index + xSwap + ySwap] = temp;
00077       }
00078 }
00079 
00080 static void generatTile_FFT(float* const noiseTileData, std::string filename)
00081 {
00082         if (loadTile(noiseTileData, filename)) return;
00083         
00084         int res = NOISE_TILE_SIZE;
00085         int xRes = res;
00086         int yRes = res;
00087         int zRes = res;
00088         int totalCells = xRes * yRes * zRes;
00089         
00090         // create and shift the filter
00091         float* filter = new float[totalCells];
00092         for (int z = 0; z < zRes; z++)
00093                 for (int y = 0; y < yRes; y++)
00094                         for (int x = 0; x < xRes; x++)
00095                         {
00096                                 int index = x + y * xRes + z * xRes * yRes;
00097                                 float diff[] = {abs(x - xRes/2), 
00098                                 abs(y - yRes/2), 
00099                                 abs(z - zRes/2)};
00100                                 float radius = sqrtf(diff[0] * diff[0] + 
00101                                 diff[1] * diff[1] + 
00102                                 diff[2] * diff[2]) / (xRes / 2);
00103                                 radius *= M_PI;
00104                                 float H = cos((M_PI / 2.0f) * log(4.0f * radius / M_PI) / log(2.0f));
00105                                 H = H * H;
00106                                 float filtered = H;
00107                                 
00108                                 // clamp everything outside the wanted band
00109                                 if (radius >= M_PI / 2.0f)
00110                                         filtered = 0.0f;
00111                                 
00112                                 // make sure to capture all low frequencies
00113                                 if (radius <= M_PI / 4.0f)
00114                                         filtered = 1.0f;
00115                                 
00116                                 filter[index] = filtered;
00117                         }
00118         shift3D(filter, xRes, yRes, zRes);
00119         
00120         // create the noise
00121         float* noise = new float[totalCells];
00122         int index = 0;
00123         MTRand twister;
00124         for (int z = 0; z < zRes; z++)
00125         for (int y = 0; y < yRes; y++)
00126           for (int x = 0; x < xRes; x++, index++)
00127                 noise[index] = twister.randNorm();
00128         
00129         // create padded field
00130         fftw_complex* forward = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * totalCells);
00131         
00132         // init padded field
00133         index = 0;
00134         for (int z = 0; z < zRes; z++)
00135         for (int y = 0; y < yRes; y++)
00136           for (int x = 0; x < xRes; x++, index++)
00137           {
00138                 forward[index][0] = noise[index];
00139                 forward[index][1] = 0.0f;
00140           }
00141         
00142         // forward FFT 
00143         fftw_complex* backward = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * totalCells);
00144         fftw_plan forwardPlan = fftw_plan_dft_3d(xRes, yRes, zRes, forward, backward, FFTW_FORWARD, FFTW_ESTIMATE);  
00145         fftw_execute(forwardPlan);
00146         fftw_destroy_plan(forwardPlan);
00147         
00148         // apply filter
00149         index = 0;
00150         for (int z = 0; z < zRes; z++)
00151                 for (int y = 0; y < yRes; y++)
00152                         for (int x = 0; x < xRes; x++, index++)
00153                         {
00154                                 backward[index][0] *= filter[index];
00155                                 backward[index][1] *= filter[index];
00156                         }
00157         
00158         // backward FFT
00159         fftw_plan backwardPlan = fftw_plan_dft_3d(xRes, yRes, zRes, backward, forward, FFTW_BACKWARD, FFTW_ESTIMATE);  
00160         fftw_execute(backwardPlan);
00161         fftw_destroy_plan(backwardPlan);
00162         
00163         // subtract out the low frequency components
00164         index = 0;
00165         for (int z = 0; z < zRes; z++)
00166                 for (int y = 0; y < yRes; y++)
00167                         for (int x = 0; x < xRes; x++, index++)
00168                                 noise[index] -= forward[index][0] / totalCells;
00169 
00170         // save out the noise tile
00171         saveTile(noise, filename);
00172         
00173         fftw_free(forward);
00174         fftw_free(backward);
00175         delete[] filter;
00176         delete[] noise;
00177 }
00178 
00179 #endif
00180 
00181 #endif /* FFT_NOISE_H_ */