Blender V2.61 - r43446
|
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 #ifdef WITH_FFTW3 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_ */