00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <iostream>
00012 #include "SeExprBuiltins.h"
00013 namespace{
00014 #include "SeNoiseTables.h"
00015 }
00016 #include "SeNoise.h"
00017 namespace SeExpr{
00018
00020 double s_curve(double t) {
00021 return t * t * t * (t * ( 6 * t - 15 ) + 10 );
00022 }
00023
00025 template<int d> unsigned char hashReduceChar(int index[d])
00026 {
00027 uint32_t seed=0;
00028
00029 for(int k=0;k<d;k++){
00030 static const uint32_t M = 1664525, C = 1013904223;
00031 seed=seed*M+index[k]+C;
00032 }
00033
00034 seed ^= (seed >> 11);
00035 seed ^= (seed << 7) & 0x9d2c5680UL;
00036 seed ^= (seed << 15) & 0xefc60000UL;
00037 seed ^= (seed >> 18);
00038
00039 return (((seed&0xff0000) >> 4)+(seed&0xff))&0xff;
00040 }
00041
00043 template<int d> uint32_t hashReduce(uint32_t index[d])
00044 {
00045 union {
00046 uint32_t i;
00047 unsigned char c[4];
00048 } u1, u2;
00049
00050 u1.i=0;
00051 for(int k=0;k<d;k++){
00052 static const uint32_t M = 1664525, C = 1013904223;
00053 u1.i=u1.i*M+index[k]+C;
00054 }
00055
00056 u1.i ^= (u1.i >> 11);
00057 u1.i ^= (u1.i << 7) & 0x9d2c5680U;
00058 u1.i ^= (u1.i << 15) & 0xefc60000U;
00059 u1.i ^= (u1.i >> 18);
00060
00061 u2.c[3] = p[u1.c[0]];
00062 u2.c[2] = p[u1.c[1]+u2.c[3]];
00063 u2.c[1] = p[u1.c[2]+u2.c[2]];
00064 u2.c[0] = p[u1.c[3]+u2.c[1]];
00065
00066 return u2.i;
00067 }
00068
00070 template<int d_in,int d_out,class T>
00071 void CellNoise(const T* in,T* out)
00072 {
00073 uint32_t index[d_in];
00074 int dim=0;
00075 for(int k=0;k<d_in;k++) index[k]=uint32_t(floor(in[k]));
00076 while(1){
00077 out[dim]=hashReduce<d_in>(index) * (1.0/0xffffffffu);
00078 if(++dim>=d_out) break;
00079 for(int k=0;k<d_in;k++) index[k]+=1000;
00080 }
00081 }
00082
00084 template<int d,class T,bool periodic>
00085 T noiseHelper(const T* X,const int* period=0)
00086 {
00087
00088 T weights[2][d];
00089 int index[d];
00090 for(int k=0;k<d;k++){
00091 T f=floor(X[k]);
00092 index[k]=(int)f;
00093 if(periodic){
00094 index[k]%=period[k];
00095 if(index[k]<0) index[k]+=period[k];
00096 }
00097 weights[0][k]=X[k]-f;
00098 weights[1][k]=weights[0][k]-1;
00099 }
00100
00101 const int num=1<<d;
00102 T vals[num];
00103 for(int dummy=0;dummy<num;dummy++){
00104 int latticeIndex[d];
00105 int offset[d];
00106 for(int k=0;k<d;k++){
00107 offset[k]=((dummy&(1<<k))!=0);
00108 latticeIndex[k]=index[k]+offset[k];
00109 }
00110
00111 int lookup=hashReduceChar<d>(latticeIndex);
00112 T val=0;
00113 for(int k=0;k<d;k++){
00114 double grad=NOISE_TABLES<d>::g[lookup][k];
00115 double weight=weights[offset[k]][k];
00116 val+=grad*weight;
00117 }
00118 vals[dummy]=val;
00119 }
00120
00121 T alphas[d];
00122 for(int k=0;k<d;k++) alphas[k]=s_curve(weights[0][k]);
00123
00124 for(int newd=d-1;newd>=0;newd--){
00125 int newnum=1<<newd;
00126 for(int dummy=0;dummy<newnum;dummy++){
00127 int index=dummy*(1<<(d-newd));
00128 int k=(d-newd-1);
00129 int otherIndex=index+(1<<k);
00130
00131 T alpha=alphas[k];
00132 vals[index]=(1-alpha)*vals[index]+alpha*vals[otherIndex];
00133 }
00134 }
00135
00136 return vals[0];
00137 }
00138
00140 template<int d_in,int d_out,class T> void Noise(const T* in,T* out)
00141 {
00142 T P[d_in];
00143 for(int i=0;i<d_in;i++) P[i]=in[i];
00144
00145 int i=0;
00146 while(1){
00147 out[i]=noiseHelper<d_in,T,false>(P);
00148 if(++i>=d_out) break;
00149 for(int k=0;k<d_out;k++) P[k]+=(T)1000;
00150 }
00151 }
00152
00154 template<int d_in,int d_out,class T> void PNoise(const T* in,const int* period,T* out)
00155 {
00156 T P[d_in];
00157 for(int i=0;i<d_in;i++) P[i]=in[i];
00158
00159 int i=0;
00160 while(1){
00161 out[i]=noiseHelper<d_in,T,true>(P,period);
00162 if(++i>=d_out) break;
00163 for(int k=0;k<d_out;k++) P[k]+=(T)1000;
00164 }
00165 }
00166
00169 template<int d_in,int d_out,bool turbulence,class T>
00170 void FBM(const T* in,T* out,
00171 int octaves,T lacunarity,T gain)
00172 {
00173 T P[d_in];
00174 for(int i=0;i<d_in;i++) P[i]=in[i];
00175
00176 T scale=1;
00177 for(int k=0;k<d_out;k++) out[k]=0;
00178 int octave=0;
00179 while(1){
00180 T localResult[d_out];
00181 Noise<d_in,d_out>(P,localResult);
00182 if(turbulence)
00183 for(int k=0;k<d_out;k++) out[k]+=fabs(localResult[k])*scale;
00184 else
00185 for(int k=0;k<d_out;k++) out[k]+=localResult[k]*scale;
00186 if(++octave>=octaves)break;
00187 scale*=gain;
00188 for(int k=0;k<d_in;k++){
00189 P[k]*=lacunarity;
00190 P[k]+=(T)1234;
00191 }
00192 }
00193 }
00194
00195
00196 template void CellNoise<3,1,double>(const double*,double*);
00197 template void CellNoise<3,3,double>(const double*,double*);
00198 template void Noise<1,1,double>(const double*,double*);
00199 template void Noise<2,1,double>(const double*,double*);
00200 template void Noise<3,1,double>(const double*,double*);
00201 template void PNoise<3,1,double>(const double*,const int *,double*);
00202 template void Noise<4,1,double>(const double*,double*);
00203 template void Noise<3,3,double>(const double*,double*);
00204 template void Noise<4,3,double>(const double*,double*);
00205 template void FBM<3,1,false,double>(const double*,double*,int,double,double);
00206 template void FBM<3,1,true,double>(const double*,double*,int,double,double);
00207 template void FBM<3,3,false,double>(const double*,double*,int,double,double);
00208 template void FBM<3,3,true,double>(const double*,double*,int,double,double);
00209 template void FBM<4,1,false,double>(const double*,double*,int,double,double);
00210 template void FBM<4,3,false,double>(const double*,double*,int,double,double);
00211
00212 }
00213
00214 #ifdef MAINTEST
00215 int main(int argc,char* argv[])
00216 {
00217 typedef double T;
00218 T sum=0;
00219 for(int i=0;i<10000000;i++){
00220 T foo[3]={.3,.3,.3};
00221
00222 sum+=SeExpr::noiseHelper<3,T,false>(foo);
00223
00224 }
00225 }
00226 #endif