Blender  V2.59
INTERPOLATE.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 #ifndef INTERPOLATE_H
00024 #define INTERPOLATE_H
00025 
00026 #include <iostream>
00027 #include <VEC3.h>
00028 
00029 namespace INTERPOLATE {
00030 
00032 // linear interpolators
00034 static inline float lerp(float t, float a, float b) {
00035         return ( a + t * (b - a) );
00036 }
00037 
00038 static inline float lerp(float* field, float x, float y, int res) {
00039         // clamp backtrace to grid boundaries
00040         if (x < 0.5f) x = 0.5f;
00041         if (x > res - 1.5f) x = res - 1.5f;
00042         if (y < 0.5f) y = 0.5f;
00043         if (y > res - 1.5f) y = res - 1.5f;
00044 
00045         const int x0 = (int)x;
00046         const int y0 = (int)y;
00047         x -= x0;
00048         y -= y0;
00049         float d00, d10, d01, d11;
00050 
00051         // lerp the velocities
00052         d00 = field[x0 + y0 * res];
00053         d10 = field[(x0 + 1) + y0 * res];
00054         d01 = field[x0 + (y0 + 1) * res];
00055         d11 = field[(x0 + 1) + (y0 + 1) * res];
00056         return lerp(y, lerp(x, d00, d10),
00057                         lerp(x, d01, d11));
00058 }
00059 
00061 // 3d linear interpolation
00063 static inline float lerp3d(float* field, float x, float y, float z,  int xres, int yres, int zres) {
00064         // clamp pos to grid boundaries
00065         if (x < 0.5) x = 0.5;
00066         if (x > xres - 1.5) x = xres - 1.5;
00067         if (y < 0.5) y = 0.5;
00068         if (y > yres - 1.5) y = yres - 1.5;
00069         if (z < 0.5) z = 0.5;
00070         if (z > zres - 1.5) z = zres - 1.5;
00071 
00072         // locate neighbors to interpolate
00073         const int x0 = (int)x;
00074         const int x1 = x0 + 1;
00075         const int y0 = (int)y;
00076         const int y1 = y0 + 1;
00077         const int z0 = (int)z;
00078         const int z1 = z0 + 1;
00079 
00080         // get interpolation weights
00081         const float s1 = x - (float)x0;
00082         const float s0 = 1.0f - s1;
00083         const float t1 = y - (float)y0;
00084         const float t0 = 1.0f - t1;
00085         const float u1 = z - (float)z0;
00086         const float u0 = 1.0f - u1;
00087 
00088         const int slabSize = xres*yres;
00089         const int i000 = x0 + y0 * xres + z0 * slabSize;
00090         const int i010 = x0 + y1 * xres + z0 * slabSize;
00091         const int i100 = x1 + y0 * xres + z0 * slabSize;
00092         const int i110 = x1 + y1 * xres + z0 * slabSize;
00093         const int i001 = x0 + y0 * xres + z1 * slabSize;
00094         const int i011 = x0 + y1 * xres + z1 * slabSize;
00095         const int i101 = x1 + y0 * xres + z1 * slabSize;
00096         const int i111 = x1 + y1 * xres + z1 * slabSize;
00097 
00098         // interpolate (indices could be computed once)
00099         return ( u0 * (s0 * (t0 * field[i000] +
00100                 t1 * field[i010]) +
00101                 s1 * (t0 * field[i100] +
00102                 t1 * field[i110])) +
00103                 u1 * (s0 * (t0 * field[i001] +
00104                 t1 * field[i011]) +
00105                 s1 * (t0 * field[i101] +
00106                 t1 * field[i111])) );
00107 }
00108 
00110 // convert field entries of type T to floats, then interpolate
00112 template <class T> 
00113 static inline float lerp3dToFloat(T* field1,
00114                 float x, float y, float z,  int xres, int yres, int zres) {
00115         // clamp pos to grid boundaries
00116         if (x < 0.5) x = 0.5;
00117         if (x > xres - 1.5) x = xres - 1.5;
00118         if (y < 0.5) y = 0.5;
00119         if (y > yres - 1.5) y = yres - 1.5;
00120         if (z < 0.5) z = 0.5;
00121         if (z > zres - 1.5) z = zres - 1.5;
00122 
00123         // locate neighbors to interpolate
00124         const int x0 = (int)x;
00125         const int x1 = x0 + 1;
00126         const int y0 = (int)y;
00127         const int y1 = y0 + 1;
00128         const int z0 = (int)z;
00129         const int z1 = z0 + 1;
00130 
00131         // get interpolation weights
00132         const float s1 = x - (float)x0;
00133         const float s0 = 1.0f - s1;
00134         const float t1 = y - (float)y0;
00135         const float t0 = 1.0f - t1;
00136         const float u1 = z - (float)z0;
00137         const float u0 = 1.0f - u1;
00138 
00139         const int slabSize = xres*yres;
00140         const int i000 = x0 + y0 * xres + z0 * slabSize;
00141         const int i010 = x0 + y1 * xres + z0 * slabSize;
00142         const int i100 = x1 + y0 * xres + z0 * slabSize;
00143         const int i110 = x1 + y1 * xres + z0 * slabSize;
00144         const int i001 = x0 + y0 * xres + z1 * slabSize;
00145         const int i011 = x0 + y1 * xres + z1 * slabSize;
00146         const int i101 = x1 + y0 * xres + z1 * slabSize;
00147         const int i111 = x1 + y1 * xres + z1 * slabSize;
00148 
00149         // interpolate (indices could be computed once)
00150         return (float)(
00151                         ( u0 * (s0 * (t0 * (float)field1[i000] +
00152                                 t1 * (float)field1[i010]) +
00153                                 s1 * (t0 * (float)field1[i100] +
00154                                 t1 * (float)field1[i110])) +
00155                                 u1 * (s0 * (t0 * (float)field1[i001] +
00156                                 t1 * (float)field1[i011]) +
00157                                 s1 * (t0 * (float)field1[i101] +
00158                                 t1 * (float)field1[i111])) ) );
00159 }
00160 
00162 // interpolate a vector from 3 fields
00164 static inline Vec3 lerp3dVec(float* field1, float* field2, float* field3, 
00165                 float x, float y, float z,  int xres, int yres, int zres) {
00166         // clamp pos to grid boundaries
00167         if (x < 0.5) x = 0.5;
00168         if (x > xres - 1.5) x = xres - 1.5;
00169         if (y < 0.5) y = 0.5;
00170         if (y > yres - 1.5) y = yres - 1.5;
00171         if (z < 0.5) z = 0.5;
00172         if (z > zres - 1.5) z = zres - 1.5;
00173 
00174         // locate neighbors to interpolate
00175         const int x0 = (int)x;
00176         const int x1 = x0 + 1;
00177         const int y0 = (int)y;
00178         const int y1 = y0 + 1;
00179         const int z0 = (int)z;
00180         const int z1 = z0 + 1;
00181 
00182         // get interpolation weights
00183         const float s1 = x - (float)x0;
00184         const float s0 = 1.0f - s1;
00185         const float t1 = y - (float)y0;
00186         const float t0 = 1.0f - t1;
00187         const float u1 = z - (float)z0;
00188         const float u0 = 1.0f - u1;
00189 
00190         const int slabSize = xres*yres;
00191         const int i000 = x0 + y0 * xres + z0 * slabSize;
00192         const int i010 = x0 + y1 * xres + z0 * slabSize;
00193         const int i100 = x1 + y0 * xres + z0 * slabSize;
00194         const int i110 = x1 + y1 * xres + z0 * slabSize;
00195         const int i001 = x0 + y0 * xres + z1 * slabSize;
00196         const int i011 = x0 + y1 * xres + z1 * slabSize;
00197         const int i101 = x1 + y0 * xres + z1 * slabSize;
00198         const int i111 = x1 + y1 * xres + z1 * slabSize;
00199 
00200         // interpolate (indices could be computed once)
00201         return Vec3(
00202                         ( u0 * (s0 * (t0 * field1[i000] +
00203                                 t1 * field1[i010]) +
00204                                 s1 * (t0 * field1[i100] +
00205                                 t1 * field1[i110])) +
00206                                 u1 * (s0 * (t0 * field1[i001] +
00207                                 t1 * field1[i011]) +
00208                                 s1 * (t0 * field1[i101] +
00209                                 t1 * field1[i111])) ) , 
00210                         ( u0 * (s0 * (t0 * field2[i000] +
00211                                 t1 * field2[i010]) +
00212                                 s1 * (t0 * field2[i100] +
00213                                 t1 * field2[i110])) +
00214                                 u1 * (s0 * (t0 * field2[i001] +
00215                                 t1 * field2[i011]) +
00216                                 s1 * (t0 * field2[i101] +
00217                                 t1 * field2[i111])) ) , 
00218                         ( u0 * (s0 * (t0 * field3[i000] +
00219                                 t1 * field3[i010]) +
00220                                 s1 * (t0 * field3[i100] +
00221                                 t1 * field3[i110])) +
00222                                 u1 * (s0 * (t0 * field3[i001] +
00223                                 t1 * field3[i011]) +
00224                                 s1 * (t0 * field3[i101] +
00225                                 t1 * field3[i111])) ) 
00226                         );
00227 }
00228 
00229 };
00230 #endif