# Home    # nevrax.com   
Nevrax
Nevrax.org
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
Docs
 
Documentation  
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  

cloud_scape.cpp

Go to the documentation of this file.
00001 
00007 /* Copyright, 2002 Nevrax Ltd.
00008  *
00009  * This file is part of NEVRAX NEL.
00010  * NEVRAX NEL is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2, or (at your option)
00013  * any later version.
00014 
00015  * NEVRAX NEL is distributed in the hope that it will be useful, but
00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00018  * General Public License for more details.
00019 
00020  * You should have received a copy of the GNU General Public License
00021  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00023  * MA 02111-1307, USA.
00024  */
00025 
00026 #include "std3d.h"
00027 #include "cloud_scape.h"
00028 #include "3d/driver.h"
00029 #include "nel/3d/scissor.h"
00030 #include "nel/3d/viewport.h"
00031 
00032 // ------------------------------------------------------------------------------------------------
00033 using namespace NLMISC;
00034 
00035 namespace NL3D
00036 {
00037 
00038 // ------------------------------------------------------------------------------------------------
00039 #define SQR(x) (x)*(x)
00040 
00041 #define MAX_DIST        400.0f
00042 #define MAX_CLOUDS      256
00043 // QUEUE_SIZE must be at least 2*MAX_CLOUDS
00044 #define QUEUE_SIZE      512 
00045 
00046 // ------------------------------------------------------------------------------------------------
00047 // SCloudTexture3D
00048 // ------------------------------------------------------------------------------------------------
00049 
00050 // ------------------------------------------------------------------------------------------------
00051 SCloudTexture3D::SCloudTexture3D ()
00052 {
00053         Mem = NULL;
00054         ToLight.initUnlit();
00055         ToLight.setShader (CMaterial::Normal);
00056         //ToLight.setTexture (0, Tex);
00057         ToLight.setZFunc (CMaterial::always);
00058         ToLight.setZWrite (false);
00059         ToLight.texEnvOpRGB (0, CMaterial::Replace);
00060         ToLight.texEnvArg0RGB (0, CMaterial::Diffuse, CMaterial::SrcColor);
00061         ToLight.texEnvOpAlpha (0, CMaterial::Replace);
00062         ToLight.texEnvArg0Alpha (0, CMaterial::Texture, CMaterial::InvSrcAlpha);
00063         ToLight.setBlend (true);
00064         ToLight.setBlendFunc (CMaterial::invsrcalpha, CMaterial::srcalpha);
00065         ToLight.setColor (CRGBA(0,0,0,255));
00066 
00067         ToBill.initUnlit();
00068         ToBill.setZFunc (CMaterial::always);
00069         ToBill.setZWrite (false);
00070         ToBill.setDoubleSided(true);
00071 
00072         ToBill.texEnvOpRGB (0, CMaterial::Add);
00073         ToBill.texEnvArg0RGB (0, CMaterial::Texture, CMaterial::SrcColor);
00074         ToBill.texEnvArg1RGB (0, CMaterial::Diffuse, CMaterial::SrcColor);
00075         ToBill.setColor (CRGBA(80,80,80,255));
00076 
00077         ToBill.texEnvOpAlpha (0, CMaterial::Replace);
00078         ToBill.texEnvArg0Alpha (0, CMaterial::Texture, CMaterial::SrcAlpha);
00079 
00080         ToBill.texEnvOpRGB (1, CMaterial::Modulate);
00081         ToBill.texEnvArg0RGB (1, CMaterial::Previous, CMaterial::SrcColor);
00082         ToBill.texEnvArg1RGB (1, CMaterial::Previous, CMaterial::SrcAlpha);
00083         ToBill.texEnvOpAlpha (1, CMaterial::Replace);
00084         ToBill.texEnvArg0Alpha (1, CMaterial::Previous, CMaterial::SrcAlpha);
00085 
00086         ToBill.setBlendFunc (CMaterial::one, CMaterial::invsrcalpha);
00087         ToBill.setBlend (true);
00088 }
00089 
00090 // ------------------------------------------------------------------------------------------------
00091 void SCloudTexture3D::init (uint32 nWidth, uint32 nHeight, uint32 nDepth)
00092 {
00093         if (Mem != NULL)
00094                 return;
00095 
00096         Width = raiseToNextPowerOf2 (nWidth);
00097         Height = raiseToNextPowerOf2 (nHeight);
00098         Depth = raiseToNextPowerOf2 (nDepth);
00099         uint32 vdpo2 = getPowerOf2(Depth);
00100         NbW = 1 << (vdpo2 / 2);
00101         if ((vdpo2 & 1) != 0)
00102                 NbH = 2 << (vdpo2 / 2);
00103         else
00104                 NbH = 1 << (vdpo2 / 2);
00105 
00106         Mem = new uint8[4*NbW*Width*NbH*Height];
00107         Tex = new CTextureMem (Mem, 4*NbW*Width*NbH*Height, true, false, NbW*Width, NbH*Height, CBitmap::RGBA);
00108 
00109         Tex->setWrapS (ITexture::Clamp);
00110         Tex->setWrapT (ITexture::Clamp);
00111         Tex->setFilterMode (ITexture::Linear, ITexture::LinearMipMapOff);
00112         Tex->setReleasable (false);
00113         Tex->generate ();
00114 
00115         ToLight.setTexture (0, Tex);
00116 
00117         ToBill.setTexture(0, Tex);
00118         ToBill.setTexture(1, Tex);
00119 }
00120 
00121 // ------------------------------------------------------------------------------------------------
00122 // SCloudTextureClamp
00123 // ------------------------------------------------------------------------------------------------
00124 
00125 // ------------------------------------------------------------------------------------------------
00126 SCloudTextureClamp::SCloudTextureClamp ()
00127 {
00128         Mem = NULL;
00129         ToClamp.initUnlit();
00130         ToClamp.setShader (CMaterial::Normal);
00131         ToClamp.texEnvOpAlpha (0, CMaterial::Add);
00132         ToClamp.texEnvArg0Alpha (0, CMaterial::Texture, CMaterial::SrcAlpha);
00133         ToClamp.texEnvArg1Alpha (0, CMaterial::Diffuse, CMaterial::SrcAlpha);
00134         ToClamp.setColor (CRGBA(255,255,255,255));
00135         ToClamp.setBlend (true);
00136         ToClamp.setBlendFunc (CMaterial::one, CMaterial::one);
00137         ToClamp.setZFunc (CMaterial::always);
00138         ToClamp.setZWrite (false);
00139 
00140 }
00141 
00142 // ------------------------------------------------------------------------------------------------
00143 void SCloudTextureClamp::init (uint32 nWidth, uint32 nHeight, uint32 nDepth, const std::string &filename)
00144 {
00145         if (Mem != NULL)
00146                 return;
00147         
00148         Width = raiseToNextPowerOf2 (nWidth);
00149         Height = raiseToNextPowerOf2 (nHeight);
00150         Depth = raiseToNextPowerOf2 (nDepth);
00151         uint32 vdpo2 = getPowerOf2(Depth);
00152         NbW = 1 << (vdpo2 / 2);
00153         if ((vdpo2 & 1) != 0)
00154                 NbH = 2 << (vdpo2 / 2);
00155         else
00156                 NbH = 1 << (vdpo2 / 2);
00157 
00158         Mem = new uint8[NbW*Width*NbH*Height];
00159         uint32 i, j;
00160 
00161         if (filename == "")
00162         {
00163                 // No filename so init with default
00164                 for (i = 0; i < NbW; ++i)
00165                 {
00166                         for (j = 0; j < NbH; ++j)
00167                         {
00168                                 uint32 d = i+j*NbW;
00169                                 uint32 k, l;
00170                                 for (k = 0; k < Width; ++k)
00171                                 for (l = 0; l < Height; ++l)
00172                                 {
00173                                         float x = k+0.5f;
00174                                         float y = l+0.5f;
00175                                         float z = d+0.5f;
00176                                         float xc = Width/2.0f;
00177                                         float yc = Height/2.0f;
00178                                         float zc = Depth/2.0f;
00179 
00180                                         float r = (x-xc)*(x-xc)/(Width*Width/4.0f) + (y-yc)*(y-yc)/(Height*Height/4.0f) 
00181                                                         + (z-zc)*(z-zc)/(Depth*Depth/4.0f);
00182 
00183                                         uint8 col = 255;
00184                                         if (r < 1.0f)
00185                                         {
00186                                                 col = (uint8)((r)*223+32);
00187                                         }
00188                                         Mem[i*Width+k + (j*Height+l)*NbW*Width] = col;
00189                                 }
00190                         }
00191                 }
00192         }
00193         else
00194         {
00195                 // Load file TODO !
00196         }
00197 
00198         Tex = new CTextureMem (Mem, NbW*Width*NbH*Height, true, false, NbW*Width, NbH*Height, CBitmap::Alpha);
00199         Tex->setWrapS (ITexture::Repeat);
00200         Tex->setWrapT (ITexture::Repeat);
00201         Tex->setFilterMode (ITexture::Linear, ITexture::LinearMipMapOff);
00202 
00203         Tex->touch();
00204         Tex->setReleasable (false);
00205         Tex->generate();
00206 
00207         ToClamp.setTexture(0, Tex);
00208 
00209 }
00210 
00211 
00212 // ------------------------------------------------------------------------------------------------
00213 // CCloudScape
00214 // ------------------------------------------------------------------------------------------------
00215 
00216 // ------------------------------------------------------------------------------------------------
00217 CCloudScape::CCloudScape (NL3D::IDriver *pDriver) : _Noise3D (pDriver)
00218 {
00219         _Driver = pDriver;
00220         // Misc purpose VB
00221         _VertexBuffer.setVertexFormat (CVertexBuffer::PositionFlag | CVertexBuffer::TexCoord0Flag | CVertexBuffer::TexCoord1Flag);
00222         _VertexBuffer.setNumVertices (4);
00223 
00224         // Material used for cleaning
00225         _MatClear.initUnlit();
00226         _MatClear.setDoubleSided (true);
00227         _MatClear.setZFunc (CMaterial::always);
00228         _MatClear.setZWrite (false);
00229         _MatClear.setBlend (false);
00230 
00231         _MatBill.initUnlit();
00232         _MatBill.setShader (CMaterial::Normal); // not needed
00233 
00234         _MatBill.texEnvOpRGB (0, CMaterial::Replace);
00235         _MatBill.texEnvArg0RGB (0, CMaterial::Texture, CMaterial::SrcColor);
00236 
00237         _MatBill.texEnvOpAlpha (0, CMaterial::Replace);
00238         _MatBill.texEnvArg0Alpha (0, CMaterial::Texture, CMaterial::SrcAlpha);
00239 
00240         _MatBill.texEnvOpRGB (1, CMaterial::InterpolateDiffuse);
00241         _MatBill.texEnvArg0RGB (1, CMaterial::Texture, CMaterial::SrcColor);
00242         _MatBill.texEnvArg1RGB (1, CMaterial::Previous, CMaterial::SrcColor);
00243 
00244         _MatBill.texEnvOpAlpha (1, CMaterial::InterpolateDiffuse);
00245         _MatBill.texEnvArg0Alpha (1, CMaterial::Texture, CMaterial::SrcAlpha);
00246         _MatBill.texEnvArg1Alpha (1, CMaterial::Previous, CMaterial::SrcAlpha);
00247 
00248         _MatBill.setBlend (true);
00249         _MatBill.setBlendFunc(CMaterial::one, CMaterial::invsrcalpha);
00250         _MatBill.setZFunc (CMaterial::always);
00251         _MatBill.setZWrite (false);
00252         _MatBill.setDoubleSided (true);
00253         _MatBill.setAlphaTest(true);
00254         _MatBill.setAlphaTestThreshold(2.0f/256.0f);
00255 
00256         _LODQualityThreshold = 160.0f;
00257         _IsIncomingCSS = false;
00258         _DebugQuad = false;
00259         _NbHalfCloudToUpdate = 1;
00260 }
00261 
00262 // ------------------------------------------------------------------------------------------------
00263 CCloudScape::~CCloudScape ()
00264 {
00265 }
00266 
00267 // ------------------------------------------------------------------------------------------------
00268 void CCloudScape::init (SCloudScapeSetup *pCSS, NL3D::CCamera *pCamera)
00269 {
00270         _ViewerCam = pCamera;
00271         
00272         _Noise3D.init();
00273 
00274         _AllClouds.resize (MAX_CLOUDS, CCloud(this));
00275         _CloudPower.resize (MAX_CLOUDS);
00276         _ShouldProcessCloud.resize (MAX_CLOUDS);
00277 
00278         // For the moment only one clamp texture (generated)
00279         Tex3DTemp.init (64, 32, 32);
00280         TexClamp.init (64, 32, 32,"");
00281 
00282         if (pCSS != NULL)
00283         {
00284                 _CurrentCSS = *pCSS;
00285                 _NewCSS = *pCSS;
00286                 _OldCSS = *pCSS;
00287         }
00288         _IsIncomingCSS = false;
00289         _TimeNewCSS = 60.0*60.0;
00290 
00291         uint32 i;
00292         for (i = 0; i < MAX_CLOUDS; ++i)
00293         {
00294                 float newX, newY, newZ, newSizeX, newSizeY, newSizeZ;
00295 
00296                 CCloud &c = _AllClouds[i];
00297 
00298                 c.setTex3DTemp (Tex3DTemp);
00299                 c.setTexClamp (TexClamp);
00300 
00301                 while (true)
00302                 {
00303                         bool bRecalc = false;
00304                         newX = MAX_DIST*(1.0f-2.0f*(((float)rand())/RAND_MAX));
00305                         newY = MAX_DIST*(1.0f-2.0f*(((float)rand())/RAND_MAX));
00306                         newZ = 85.0f+40.0f*(1.0f-2.0f*(((float)rand())/RAND_MAX));
00307 
00308                         newSizeX = 60.0f+10.0f*(1.0f-2.0f*(((float)rand())/RAND_MAX));
00309                         newSizeY = 30.0f+10.0f*(1.0f-2.0f*(((float)rand())/RAND_MAX));
00310                         newSizeZ = 30.0f+10.0f*(1.0f-2.0f*(((float)rand())/RAND_MAX));
00311                         float f = 0.7f+0.3f*((float)rand())/RAND_MAX;
00312                         newSizeX *= 1.5f*f;
00313                         newSizeY *= 1.5f*f;
00314                         newSizeZ *= 1.5f*f;
00315 
00316                         float d = sqrtf(SQR(newX)+SQR(newY));
00317                         if (d > MAX_DIST) bRecalc = true;
00318 
00319                         float r1 = sqrtf(SQR(newSizeX/2)+SQR(newSizeY/2)+SQR(newSizeZ/2));
00320                         for (uint32 k = 0;k < i; ++k)
00321                         {
00322                                 CCloud &c2 = _AllClouds[k];
00323 
00324                                 if ((fabs(newX-c2.getX()) < (newSizeX/2+c2.getSizeX()/2)) && 
00325                                         (fabs(newY-c2.getY()) < (newSizeY/2+c2.getSizeY()/2)) && 
00326                                         (fabs(newZ-c2.getZ()) < (newSizeZ/2+c2.getSizeZ()/2)))
00327                                         bRecalc = true;
00328                         }
00329                         if (!bRecalc) break;
00330                 }
00331 
00332                 c.init (64, 32, 32, 0.122f, 4);
00333                 c.setX (newX-newSizeX/2);
00334                 c.setY (newY-newSizeY/2);
00335                 c.setZ (newZ-newSizeZ/2);
00336 
00337                 c.setSizeX (newSizeX);
00338                 c.setSizeY (newSizeY);
00339                 c.setSizeZ (newSizeZ);
00340 
00341                 c.Time = 0;
00342                 c.FuturTime = _CurrentCSS.NbCloud * 2 * (0.04/_NbHalfCloudToUpdate);
00343                 if (i < _CurrentCSS.NbCloud)
00344                 {
00345                         _CloudPower[i] = 255;
00346                         _ShouldProcessCloud[i] = true;
00347                 }
00348                 else
00349                 {
00350                         _CloudPower[i] = 0;
00351                         _ShouldProcessCloud[i] = false;
00352                 }
00353         }
00354 
00355         _SortedClouds.resize (MAX_CLOUDS);
00356 
00357         _CloudSchedulerSize = _CurrentCSS.NbCloud;
00358         _CloudSchedulerLastAdded.resize (MAX_CLOUDS);
00359         _FrameCounter = 0;
00360         _CloudScheduler.clear();
00361         for (i = 0; i < MAX_CLOUDS; ++i)
00362                 _CloudSchedulerLastAdded[i].ValidPos = false;
00363 
00364         for (i = 0; i < QUEUE_SIZE; ++i)
00365         {
00366                 sint32 nCloudNb = i%_CurrentCSS.NbCloud;
00367                 SCloudSchedulerEntry cse;
00368                 cse.CloudIndex = nCloudNb;
00369                 if (_CloudSchedulerLastAdded[nCloudNb].ValidPos == true)
00370                 {
00371                         SCloudSchedulerEntry &lastCSE = *_CloudSchedulerLastAdded[nCloudNb].Pos;
00372                         sint32 delta = _FrameCounter - lastCSE.Frame;
00373                         lastCSE.DeltaNextCalc = delta;
00374                 }
00375                 cse.Frame = _FrameCounter;
00376                 cse.Ambient = _CurrentCSS.Ambient;
00377                 cse.Diffuse = _CurrentCSS.Diffuse;
00378                 cse.Power = _CloudPower[cse.CloudIndex];
00379                 _CloudSchedulerLastAdded[nCloudNb].Pos = _CloudScheduler.insert(_CloudScheduler.end(), cse);
00380                 _CloudSchedulerLastAdded[nCloudNb].ValidPos = true;
00381 //              _CloudSchedulerLastAdded[nCloudNb].Pos = _CloudScheduler.end()-1;
00382                 ++_FrameCounter;
00383         }
00384         _GlobalTime = 0.0f;
00385         _DTRest = 0.0f;
00386         _Generate = true;
00387         _AverageFrameRate.init(16);
00388         for (i = 0; i < 16; ++i)
00389                 _AverageFrameRate.addValue (40.0f/1000.0f);
00390 
00391         _ExtrapolatedPriorities.resize (MAX_CLOUDS);
00392 
00393         for (i = 0; i < QUEUE_SIZE; ++i)
00394                 anim (41.0/1000.0, _ViewerCam);
00395 }
00396 
00397 // ------------------------------------------------------------------------------------------------
00398 void CCloudScape::set (SCloudScapeSetup &css)
00399 {
00400         _IncomingCSS = css;
00401         _IsIncomingCSS = true;
00402 }
00403 
00404 // ------------------------------------------------------------------------------------------------
00405 void CCloudScape::anim (double dt, NL3D::CCamera *pCamera)
00406 {
00407         sint32 i;
00408 
00409         _ViewerCam = pCamera;
00410 
00411         // 10 fps -> 200 fps
00412         if (dt > 0.1) dt = 0.1;
00413         if (dt < 0.005) dt = 0.005;
00414 
00415         _DeltaTime = dt;
00416         _GlobalTime += _DeltaTime;
00417         _AverageFrameRate.addValue ((float)_DeltaTime);
00418 
00419         // Animate the CSS
00420         if (_TimeNewCSS > _NewCSS.TimeToChange)
00421         {
00422                 _CurrentCSS = _NewCSS;
00423                 _OldCSS = _NewCSS;
00424                 if (_IsIncomingCSS)
00425                 {
00426                         _IsIncomingCSS = false;
00427                         _NewCSS = _IncomingCSS;
00428                         _TimeNewCSS = 0;
00429                         if (_NewCSS.NbCloud > _OldCSS.NbCloud)
00430                         for (i = 0; i < (sint32)(_NewCSS.NbCloud-_OldCSS.NbCloud); ++i)
00431                         {
00432                                 CCloud &c = _AllClouds[_OldCSS.NbCloud+i];
00433                                 c.CloudPower = 0;
00434                                 _CloudPower[_OldCSS.NbCloud+i] = 0;
00435                         }
00436                 }
00437         }
00438         else
00439         {
00440                 float inter = (float)(_TimeNewCSS / _NewCSS.TimeToChange);
00441                 _CurrentCSS.WindSpeed = (_NewCSS.WindSpeed - _OldCSS.WindSpeed)*inter + _OldCSS.WindSpeed;
00442                 _CurrentCSS.CloudSpeed = (_NewCSS.CloudSpeed - _OldCSS.CloudSpeed)*inter + _OldCSS.CloudSpeed;
00443 
00444                 _CurrentCSS.Ambient.R = (uint8)((_NewCSS.Ambient.R - _OldCSS.Ambient.R)*inter + _OldCSS.Ambient.R);
00445                 _CurrentCSS.Ambient.G = (uint8)((_NewCSS.Ambient.G - _OldCSS.Ambient.G)*inter + _OldCSS.Ambient.G);
00446                 _CurrentCSS.Ambient.B = (uint8)((_NewCSS.Ambient.B - _OldCSS.Ambient.B)*inter + _OldCSS.Ambient.B);
00447                 _CurrentCSS.Ambient.A = (uint8)((_NewCSS.Ambient.A - _OldCSS.Ambient.A)*inter + _OldCSS.Ambient.A);
00448 
00449                 _CurrentCSS.Diffuse.R = (uint8)((_NewCSS.Diffuse.R - _OldCSS.Diffuse.R)*inter + _OldCSS.Diffuse.R);
00450                 _CurrentCSS.Diffuse.G = (uint8)((_NewCSS.Diffuse.G - _OldCSS.Diffuse.G)*inter + _OldCSS.Diffuse.G);
00451                 _CurrentCSS.Diffuse.B = (uint8)((_NewCSS.Diffuse.B - _OldCSS.Diffuse.B)*inter + _OldCSS.Diffuse.B);
00452                 _CurrentCSS.Diffuse.A = (uint8)((_NewCSS.Diffuse.A - _OldCSS.Diffuse.A)*inter + _OldCSS.Diffuse.A);
00453 
00454                 if (_NewCSS.NbCloud > _OldCSS.NbCloud)
00455                 {
00456                         // Add some clouds
00457                         float slice = (_NewCSS.TimeToChange/4) / (_NewCSS.NbCloud-_OldCSS.NbCloud);
00458                         sint32 diffCloud = _NewCSS.NbCloud-_OldCSS.NbCloud;
00459 
00460                         _CurrentCSS.NbCloud = _OldCSS.NbCloud + (1+(uint32)(_TimeNewCSS/slice));
00461                         if (_CurrentCSS.NbCloud > _NewCSS.NbCloud)
00462                                 _CurrentCSS.NbCloud = _NewCSS.NbCloud;
00463 
00464                         for (i = 0; i < diffCloud; ++i)
00465                         {
00466                                 _ShouldProcessCloud[_OldCSS.NbCloud+i] = true;
00467                                 if (_TimeNewCSS < i*slice)
00468                                         _CloudPower[_OldCSS.NbCloud+i] = 1;
00469                                 else if (_TimeNewCSS > (i*slice+3*_NewCSS.TimeToChange/4))
00470                                         _CloudPower[_OldCSS.NbCloud+i] = 255;
00471                                 else
00472                                         _CloudPower[_OldCSS.NbCloud+i] = (uint8)(255*(_TimeNewCSS-i*slice)/(3*_NewCSS.TimeToChange/4));
00473                         }
00474                 }
00475                 else
00476                 {
00477                         // Remove some clouds
00478                         float slice = (_NewCSS.TimeToChange/4) / (_OldCSS.NbCloud-_NewCSS.NbCloud);
00479                         sint32 diffCloud = _OldCSS.NbCloud-_NewCSS.NbCloud;
00480 
00481                         _CurrentCSS.NbCloud = _OldCSS.NbCloud;
00482 
00483                         for (i = 0; i < diffCloud; ++i)
00484                         {
00485                                 if (_TimeNewCSS < i*slice)
00486                                         _CloudPower[_OldCSS.NbCloud-i-1] = 255;
00487                                 else if (_TimeNewCSS > (i*slice+3*_NewCSS.TimeToChange/4))
00488                                         _CloudPower[_OldCSS.NbCloud-i-1] = 0;
00489                                 else
00490                                         _CloudPower[_OldCSS.NbCloud-i-1] = (uint8)(255-255*(_TimeNewCSS-i*slice)/(3*_NewCSS.TimeToChange/4));
00491                         }
00492                 }
00493         }
00494 
00495         // Make the right number of half cloud
00496         _DTRest += dt;
00497 
00498         while (_DTRest > (0.04/_NbHalfCloudToUpdate))
00499         {
00500                 makeHalfCloud ();
00501                 _DTRest -= 0.04/_NbHalfCloudToUpdate;
00502 
00503                 for (i = 0; i < MAX_CLOUDS; ++i)
00504                 {
00505                         CCloud &c = _AllClouds[i];
00506                         c.Time += 0.04/_NbHalfCloudToUpdate;
00507                 }
00508 
00509                 _TimeNewCSS += 0.04/_NbHalfCloudToUpdate;
00510         }
00511 }
00512 
00513 // ------------------------------------------------------------------------------------------------
00514 void CCloudScape::makeHalfCloud ()
00515 {
00516         CVector Viewer = CVector(0,0,0); //_ViewerCam->getMatrix().getPos();
00517 
00518         if (_Generate)
00519         {
00520                 // Find the next cloud in the list
00521                 SCloudSchedulerEntry FrontCSE;
00522 
00523                 FrontCSE = _CloudScheduler.front();
00524 
00525                 // Is the cloud do not have another reference in the list add it now because it should be processed
00526                 sint32 CloudIndexToAdd = -1;
00527                 if ((_ShouldProcessCloud[FrontCSE.CloudIndex] == true) && 
00528                         (       (_CloudSchedulerLastAdded[FrontCSE.CloudIndex].ValidPos == false) ||
00529                                 ((_CloudSchedulerLastAdded[FrontCSE.CloudIndex].ValidPos == true) &&
00530                                 (_CloudSchedulerLastAdded[FrontCSE.CloudIndex].Pos == _CloudScheduler.begin()))
00531                         ))
00532                 {
00533                         // It should be added now !
00534                         CloudIndexToAdd = FrontCSE.CloudIndex;
00535                         FrontCSE.DeltaNextCalc = QUEUE_SIZE;
00536                 }
00537                 else
00538                 {
00539                         // Choose a Cloud Index To Add at the end of the list
00540                         uint32 nPeriodeMax = _CurrentCSS.NbCloud+_CurrentCSS.NbCloud/10;
00541                         sint32 Priority = -10000;
00542                         uint32 i;
00543 
00544                         float sumPrior = 0.0f;
00545                         for (i = 0; i < MAX_CLOUDS; ++i)
00546                         if (_ShouldProcessCloud[i])
00547                         {
00548                                 CCloud &rC = _AllClouds[i];
00549                                 float ExtrapolatedTime = ((0.04f/_NbHalfCloudToUpdate) * QUEUE_SIZE * 2);
00550                                 float x = rC.getLastX () + ExtrapolatedTime * _CurrentCSS.WindSpeed;
00551                                 //float d = sqrtf(SQR(x+rC.getSizeX()/2-Viewer.x)+SQR(rC.getY()+rC.getSizeY()/2-Viewer.y)+
00552                                 //              SQR(rC.getZ()+rC.getSizeZ()/2-Viewer.z));
00553                                 float d = SQR(x+rC.getSizeX()/2-Viewer.x)+SQR(rC.getY()+rC.getSizeY()/2-Viewer.y)+
00554                                                 SQR(rC.getZ()+rC.getSizeZ()/2-Viewer.z);
00555                                 float d05 = sqrtf(d);
00556                                 float d025 = sqrtf(d05);
00557                                 float d075 = d05*d025;
00558 
00559                                 _ExtrapolatedPriorities[i] = 1.0f / d075;
00560                                 sumPrior += _ExtrapolatedPriorities[i];
00561                         }
00562 
00563                         sint32 sumJeton = 0;
00564                         for (i = 0; i < MAX_CLOUDS; ++i)
00565                         if (_ShouldProcessCloud[i])
00566                         {
00567                                 // Normalize priorities
00568                                 float factor = ((float)QUEUE_SIZE) / sumPrior;
00569                                 sint32 nbJeton = (sint32)(0.5f+(factor * _ExtrapolatedPriorities[i]));
00570 
00571                                 if (nbJeton < 1)
00572                                         nbJeton = 1;
00573 
00574                                 _ExtrapolatedPriorities[i] = (float)nbJeton;
00575                                 sumJeton += nbJeton;
00576                         }
00577 
00578                         if (sumJeton > QUEUE_SIZE)
00579                         {
00580                                 do
00581                                 {
00582                                         for (i = 0; i < MAX_CLOUDS; ++i)
00583                                         if (_ShouldProcessCloud[i])
00584                                         {
00585                                                 if (_ExtrapolatedPriorities[i] > 1)
00586                                                 {
00587                                                         _ExtrapolatedPriorities[i] -= 1;
00588                                                         --sumJeton;
00589                                                         if (sumJeton == QUEUE_SIZE) break;
00590                                                 }
00591                                         }
00592                                 }
00593                                 while (sumJeton > QUEUE_SIZE);
00594                         }
00595 
00596                         for (i = 0; i < MAX_CLOUDS; ++i)
00597                         if (_ShouldProcessCloud[i])
00598                         {                               
00599                                 // Cloud Period
00600                                 sint32 newPriority = nPeriodeMax;
00601                                 // Is there a last entry in array ?
00602                                 if (_CloudSchedulerLastAdded[i].ValidPos == true)
00603                                 {
00604                                         SCloudSchedulerEntry &rLastCSE = *_CloudSchedulerLastAdded[i].Pos;
00605                                         newPriority = (sint32)(QUEUE_SIZE/_ExtrapolatedPriorities[i]);
00606                                         newPriority = (_FrameCounter -  rLastCSE.Frame) - newPriority;
00607                                 }
00608                                 else
00609                                 {
00610                                         newPriority = 10000;
00611                                 }
00612                                 if (newPriority > Priority)
00613                                 {
00614                                         Priority = newPriority;
00615                                         CloudIndexToAdd = i;
00616                                 }
00617                         }
00618                         nlassert (CloudIndexToAdd != -1);
00619                 }
00620 
00621                 // Ok now we have a good cloud index to add so make the new cloud entry
00622                 SCloudSchedulerEntry newCSE;
00623 
00624                 newCSE.CloudIndex = CloudIndexToAdd;
00625                 newCSE.Frame = _FrameCounter;
00626                 newCSE.Ambient = _CurrentCSS.Ambient;
00627                 newCSE.Diffuse = _CurrentCSS.Diffuse;
00628                 newCSE.Power = _CloudPower[CloudIndexToAdd];
00629 
00630                 // If the cloud where added previously to the list
00631                 if (_CloudSchedulerLastAdded[CloudIndexToAdd].ValidPos == true)
00632                 {
00633                         // This means that the cloud were added from a long time ago
00634                         SCloudSchedulerEntry &lastCSE = *_CloudSchedulerLastAdded[CloudIndexToAdd].Pos;
00635                         sint32 delta = _FrameCounter - lastCSE.Frame;                   
00636                         lastCSE.DeltaNextCalc = delta;
00637 
00638                         // But the cloud can be removed (if so we have to not process it anymore)
00639                         if (newCSE.Power == 0)
00640                                 _ShouldProcessCloud[CloudIndexToAdd] = false;
00641                 }
00642                 else
00643                 {
00644                         // No the cloud do not appear previously in the list... So its a new one
00645                         _AllClouds[CloudIndexToAdd].reset (_ViewerCam);
00646                 }
00647 
00648                 // If the last cloud occurence of the cloud appear at beginning so no more occurence in list
00649                 if (_CloudSchedulerLastAdded[FrontCSE.CloudIndex].Pos == _CloudScheduler.begin())
00650                         _CloudSchedulerLastAdded[FrontCSE.CloudIndex].ValidPos = false;
00651 
00652                 _CloudSchedulerLastAdded[CloudIndexToAdd].Pos = _CloudScheduler.insert(_CloudScheduler.end(), newCSE);
00653                 _CloudSchedulerLastAdded[CloudIndexToAdd].ValidPos = true;
00654 //              _CloudSchedulerLastAdded[CloudIndexToAdd].Pos = _CloudScheduler.end()-1;
00655                 _CloudScheduler.pop_front ();
00656                 ++_FrameCounter;
00657                 // End of scheduling
00658 
00659                 // Get the cloud to process (this must be the next occurence of front cloud)
00660                 std::list<SCloudSchedulerEntry>::iterator it = _CloudScheduler.begin();
00661                 while (it != _CloudScheduler.end())
00662                 {
00663                         SCloudSchedulerEntry &rCSE = *it;
00664                         if (rCSE.CloudIndex == FrontCSE.CloudIndex)
00665                                 break;
00666                         ++it;
00667                 }
00668 
00669                 SCloudSchedulerEntry CSEToCalc;
00670                 // The cloud is no more present in the list
00671                 if (it == _CloudScheduler.end())
00672                 {
00673                         FrontCSE.DeltaNextCalc = 1;
00674                         CSEToCalc = FrontCSE;
00675                 }
00676                 else
00677                 {
00678                         CSEToCalc = *it;
00679                 }
00680 
00681                 _CurrentCloudInProcess = &_AllClouds[CSEToCalc.CloudIndex];
00682                 CCloud &c = *_CurrentCloudInProcess;
00683 
00684                 // To go from Front cloud to CSEToCalc cloud we should take the front DeltaNextCalc
00685 
00686                 _CurrentCloudInProcessFuturTime = ((0.04/_NbHalfCloudToUpdate) * FrontCSE.DeltaNextCalc * 2);
00687                 c.setX ((float)(c.getLastX() +  _CurrentCloudInProcessFuturTime * _CurrentCSS.WindSpeed));
00688 
00689                 float d2D = sqrtf(SQR(c.getX()+c.getSizeX()/2-Viewer.x)+SQR(c.getY()+c.getSizeY()/2-Viewer.y));
00690 
00691                 if (d2D > MAX_DIST)
00692                         c.CloudDistAtt = 255;
00693                 else if (d2D > (MAX_DIST-100.0f))
00694                         c.CloudDistAtt = (uint8)(255*((d2D-(MAX_DIST-100.0f))/100.0f));
00695                 else
00696                         c.CloudDistAtt = 0;
00697 
00698                 c.LastCloudPower = c.CloudPower;
00699                 c.CloudPower = CSEToCalc.Power;
00700                 c.CloudDiffuse = CSEToCalc.Diffuse;
00701                 c.CloudAmbient = CSEToCalc.Ambient;
00702 
00703                 c.anim (_CurrentCloudInProcessFuturTime*_CurrentCSS.CloudSpeed, 
00704                                 _CurrentCloudInProcessFuturTime*_CurrentCSS.WindSpeed);
00705 
00706                 c.generate (_Noise3D);
00707 
00708         }
00709         else
00710         {
00711                 CCloud &c = *_CurrentCloudInProcess;
00712 
00713                 c.Time = 0;
00714                 c.FuturTime = _CurrentCloudInProcessFuturTime;
00715                 c.light();
00716 
00717                 if (c.getX() > MAX_DIST)
00718                 {
00719                         c.setX (c.getX() - (2 * MAX_DIST));
00720                         c.setLooping ();
00721                 }
00722                 
00723                 float r = sqrtf(SQR(c.getSizeX()/2)+SQR(c.getSizeY()/2)+SQR(c.getSizeZ()/2));
00724                 float d2D = sqrtf(SQR(c.getX()+c.getSizeX()/2-Viewer.x)+SQR(c.getY()+c.getSizeY()/2-Viewer.y));
00725                 float d = sqrtf(SQR(c.getX()+c.getSizeX()/2-Viewer.x)+SQR(c.getY()+c.getSizeY()/2-Viewer.y)+
00726                                                 SQR(c.getZ()+c.getSizeZ()/2-Viewer.z));
00727                 uint32 lookAtSize = (uint32)(_LODQualityThreshold*r/d);
00728                 lookAtSize = raiseToNextPowerOf2 (lookAtSize);
00729                 if (lookAtSize > 128) lookAtSize = 128;
00730 
00731                 c.genBill (_ViewerCam, lookAtSize);
00732         }
00733         _Generate = !_Generate;
00734 }
00735 
00736 // ------------------------------------------------------------------------------------------------
00737 void CCloudScape::render ()
00738 {
00739         uint32 i, j;
00740         
00741         CVector Viewer = CVector (0,0,0);
00742 
00743         CMatrix viewMat;
00744         viewMat = _ViewerCam->getMatrix ();
00745         viewMat.setPos(CVector(0,0,0));
00746         viewMat.invert ();
00747         CScissor s;
00748         s.initFullScreen ();
00749         _Driver->setupScissor (s);
00750         CViewport v;
00751         _Driver->setupViewport (v);
00752         CFrustum f = _ViewerCam->getFrustum();
00753         _Driver->setFrustum (f.Left, f.Right, f.Bottom, f.Top, f.Near, f.Far, f.Perspective);
00754         _Driver->setupViewMatrix (viewMat);
00755         _Driver->setupModelMatrix (CMatrix::Identity);
00756 
00757         uint32 nNbCloudToRender = 0;
00758 
00759         for (i = 0; i < MAX_CLOUDS; ++i)
00760         {
00761                 CCloud &c = _AllClouds[i];
00762                 SSortedCloudEntry &sce = _SortedClouds[nNbCloudToRender];
00763                 sce.Cloud = &c;
00764                 sce.Distance = sqrtf(SQR(c.getX()+c.getSizeX()/2-Viewer.x)+SQR(c.getY()+c.getSizeY()/2-Viewer.y)+
00765                                                 SQR(c.getZ()+c.getSizeZ()/2-Viewer.z));
00766                 nNbCloudToRender++;
00767         }
00768 
00769         for (i = 0; i < nNbCloudToRender-1; ++i)
00770         for (j = i+1; j < nNbCloudToRender; ++j)
00771         {
00772                 if (_SortedClouds[i].Distance < _SortedClouds[j].Distance)
00773                 {
00774                         SSortedCloudEntry sceTmp = _SortedClouds[i];
00775                         _SortedClouds[i] = _SortedClouds[j];
00776                         _SortedClouds[j] = sceTmp;
00777                 }
00778         }
00779 
00780         for (i = 0; i < nNbCloudToRender; ++i)
00781         {
00782                 CCloud *pC = _SortedClouds[i].Cloud;
00783                 if ((pC->CloudPower > 0) || (pC->LastCloudPower > 0))
00784                         pC->dispBill (_ViewerCam);
00785         }
00786 }
00787 
00788 // ------------------------------------------------------------------------------------------------
00789 uint32 CCloudScape::getMemSize()
00790 {
00791         uint32 nMemSize = 0;
00792         for (uint32 i = 0; i < MAX_CLOUDS; ++i)
00793         {
00794                 CCloud &c = _AllClouds[i];
00795                 nMemSize += c.getMemSize();
00796         }
00797         return nMemSize;
00798 }
00799 
00800 } // namespace NL3D
00801