00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "std3d.h"
00027
00028 #include "3d/noise_value.h"
00029 #include "3d/fast_floor.h"
00030
00031 using namespace NLMISC;
00032
00033 namespace NL3D
00034 {
00035
00036
00037
00038 #define NL3D_NOISE_LEVEL 3
00039 #define NL3D_NOISE_GRID_SIZE_SHIFT 5
00040 #define NL3D_NOISE_GRID_SIZE (1<<NL3D_NOISE_GRID_SIZE_SHIFT)
00041 static const float NL3D_OO255= 1.0f / 255;
00042
00043
00044
00045
00046
00047
00049
00050 {
00051 public:
00052
00053
00054 CRandomGrid3D()
00055 {
00056
00057 srand(0);
00058
00059
00060 for(uint z=0; z<NL3D_NOISE_GRID_SIZE; z++)
00061 {
00062 for(uint y=0; y<NL3D_NOISE_GRID_SIZE; y++)
00063 {
00064 for(uint x=0; x<NL3D_NOISE_GRID_SIZE; x++)
00065 {
00066 uint id= x + (y<<NL3D_NOISE_GRID_SIZE_SHIFT) + (z<<(NL3D_NOISE_GRID_SIZE_SHIFT*2));
00067
00068 uint v= rand() >> 5;
00069 _Texture3d[id]= v&255;
00070 }
00071 }
00072 }
00073
00074
00075 uint i;
00076
00077 float sizeSum=0;
00078 for(i=0; i<NL3D_NOISE_LEVEL; i++)
00079 {
00080 _Sizes[i]= 1.0f / (1<<i);
00081 sizeSum+= _Sizes[i];
00082 }
00083
00084 for(i=0; i<NL3D_NOISE_LEVEL; i++)
00085 {
00086 _Sizes[i]/= sizeSum;
00087 }
00088
00089
00090 for(i=0; i<NL3D_NOISE_LEVEL; i++)
00091 {
00092 _LevelPhase[i].x= frand(NL3D_NOISE_GRID_SIZE);
00093 _LevelPhase[i].y= frand(NL3D_NOISE_GRID_SIZE);
00094 _LevelPhase[i].z= frand(NL3D_NOISE_GRID_SIZE);
00095 }
00096
00097 _LevelPhase[0]= CVector::Null;
00098 }
00099
00100
00101 static inline float evalNearest(const CVector &pos)
00102 {
00103
00104 sint x= OptFastFloor(pos.x);
00105 sint y= OptFastFloor(pos.y);
00106 sint z= OptFastFloor(pos.z);
00107
00108 uint ux= x& (NL3D_NOISE_GRID_SIZE-1);
00109 uint uy= y& (NL3D_NOISE_GRID_SIZE-1);
00110 uint uz= z& (NL3D_NOISE_GRID_SIZE-1);
00111
00112
00113 float turb= lookup(ux,uy,uz);
00114
00115 return turb*NL3D_OO255;
00116 }
00117
00118
00119 static inline float evalBiLinear(const CVector &pos)
00120 {
00121
00122 sint x= OptFastFloor(pos.x);
00123 sint y= OptFastFloor(pos.y);
00124 sint z= OptFastFloor(pos.z);
00125
00126 uint ux= x& (NL3D_NOISE_GRID_SIZE-1);
00127 uint uy= y& (NL3D_NOISE_GRID_SIZE-1);
00128 uint uz= z& (NL3D_NOISE_GRID_SIZE-1);
00129 uint ux2= (x+1)& (NL3D_NOISE_GRID_SIZE-1);
00130 uint uy2= (y+1)& (NL3D_NOISE_GRID_SIZE-1);
00131 uint uz2= (z+1)& (NL3D_NOISE_GRID_SIZE-1);
00132
00133 float dx2;
00134 float dy2;
00135 float dz2;
00136 easeInEaseOut(dx2, pos.x-x);
00137 easeInEaseOut(dy2, pos.y-y);
00138 easeInEaseOut(dz2, pos.z-z);
00139 float dx= 1-dx2;
00140 float dy= 1-dy2;
00141 float dz= 1-dz2;
00142
00143 float turb=0;
00144 float dxdy= dx*dy;
00145 turb+= lookup(ux,uy,uz)* dxdy*dz;
00146 turb+= lookup(ux,uy,uz2)* dxdy*dz2;
00147 float dxdy2= dx*dy2;
00148 turb+= lookup(ux,uy2,uz)* dxdy2*dz;
00149 turb+= lookup(ux,uy2,uz2)* dxdy2*dz2;
00150 float dx2dy= dx2*dy;
00151 turb+= lookup(ux2,uy,uz)* dx2dy*dz;
00152 turb+= lookup(ux2,uy,uz2)* dx2dy*dz2;
00153 float dx2dy2= dx2*dy2;
00154 turb+= lookup(ux2,uy2,uz)* dx2dy2*dz;
00155 turb+= lookup(ux2,uy2,uz2)* dx2dy2*dz2;
00156
00157
00158 return turb*NL3D_OO255;
00159 }
00160
00161
00162
00163 static inline float getLevelSize(uint level)
00164 {
00165 return _Sizes[level];
00166 }
00167
00168
00169 static inline const CVector &getLevelPhase(uint level)
00170 {
00171 return _LevelPhase[level];
00172 }
00173
00174
00175
00176 private:
00177
00178 static uint8 _Texture3d[NL3D_NOISE_GRID_SIZE*NL3D_NOISE_GRID_SIZE*NL3D_NOISE_GRID_SIZE];
00179 static float _Sizes[NL3D_NOISE_LEVEL];
00180 static CVector _LevelPhase[NL3D_NOISE_LEVEL];
00181
00182
00183
00184 static inline float lookup(uint ux, uint uy, uint uz)
00185 {
00186 uint id= ux + (uy<<NL3D_NOISE_GRID_SIZE_SHIFT) + (uz<<(NL3D_NOISE_GRID_SIZE_SHIFT*2));
00187 return _Texture3d[id];
00188 }
00189
00190
00191 static inline void easeInEaseOut(float &y, float x)
00192 {
00193
00194 float x2=x*x;
00195 float x3=x2*x;
00196 y= -2*x3 + 3*x2;
00197 }
00198
00199 };
00200
00201
00202 uint8 CRandomGrid3D::_Texture3d[NL3D_NOISE_GRID_SIZE*NL3D_NOISE_GRID_SIZE*NL3D_NOISE_GRID_SIZE];
00203 float CRandomGrid3D::_Sizes[NL3D_NOISE_LEVEL];
00204 CVector CRandomGrid3D::_LevelPhase[NL3D_NOISE_LEVEL];
00205
00206
00207 static CRandomGrid3D NL3D_RandomGrid3D;
00208
00209
00210
00211
00212
00213
00214
00215
00216 float CNoiseValue::evalRandom(const CVector &pos) const
00217 {
00218 return CRandomGrid3D::evalNearest(pos);
00219 }
00220
00221
00222
00223 float CNoiseValue::noise(const CVector &pos) const
00224 {
00225
00226 float turb;
00227
00228 #if (NL3D_NOISE_LEVEL != 3)
00229 CVector vd= pos;
00230 turb=0;
00231 for(uint level=0;level<NL3D_NOISE_LEVEL;level++)
00232 {
00233
00234 turb+= CRandomGrid3D::getLevelSize(level) *
00235 CRandomGrid3D::evalBiLinear(vd + CRandomGrid3D::getLevelPhase(level) );
00236
00237 vd*= 2;
00238 }
00239 #else
00240
00241
00242 turb= CRandomGrid3D::getLevelSize(0) *
00243 CRandomGrid3D::evalBiLinear(pos);
00244
00245 turb+= CRandomGrid3D::getLevelSize(1) *
00246 CRandomGrid3D::evalBiLinear(pos*2 + CRandomGrid3D::getLevelPhase(1) );
00247
00248 turb+= CRandomGrid3D::getLevelSize(2) *
00249 CRandomGrid3D::evalBiLinear(pos*4 + CRandomGrid3D::getLevelPhase(2) );
00250 #endif
00251
00252 return turb;
00253 }
00254
00255
00256
00257
00258 CNoiseValue::CNoiseValue()
00259 {
00260 Abs= 0;
00261 Rand= 1;
00262 Frequency= 1;
00263 }
00264
00265
00266
00267 CNoiseValue::CNoiseValue(float abs, float rand, float freq)
00268 {
00269 Abs= abs;
00270 Rand= rand;
00271 Frequency= freq;
00272 }
00273
00274
00275
00276 float CNoiseValue::eval(const CVector &posInWorld) const
00277 {
00278
00279
00280 return Abs + Rand * noise(posInWorld*Frequency);
00281 }
00282
00283
00284
00285 float CNoiseValue::evalOneLevelRandom(const CVector &posInWorld) const
00286 {
00287
00288
00289 return Abs + Rand * evalRandom(posInWorld*Frequency);
00290 }
00291
00292
00293
00294 void CNoiseValue::serial(IStream &f)
00295 {
00296 (void)f.serialVersion(0);
00297 f.serial(Abs);
00298 f.serial(Rand);
00299 f.serial(Frequency);
00300 }
00301
00302
00303
00304
00305
00306
00307
00308
00309 void CNoiseColorGradient::eval(const CVector &posInWorld, CRGBAF &result) const
00310 {
00311
00312 uint nGrads= Gradients.size();
00313 if(nGrads==0)
00314 return;
00315
00316 if(nGrads==1)
00317 {
00318 result= Gradients[0];
00319 }
00320 else
00321 {
00322
00323 float f= NoiseValue.eval(posInWorld) * (nGrads-1);
00324 clamp(f, 0.f, (float)(nGrads-1));
00325
00326 uint id= OptFastFloor(f);
00327 clamp(id, 0U, nGrads-2);
00328
00329 f= f-id;
00330 clamp(f, 0, 1);
00331
00332 result= Gradients[id]*(1-f) + Gradients[id+1]*f;
00333 }
00334 }
00335
00336
00337 void CNoiseColorGradient::serial(IStream &f)
00338 {
00339 (void)f.serialVersion(0);
00340 f.serial(NoiseValue);
00341 f.serialCont(Gradients);
00342 }
00343
00344
00345
00346 }