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 #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
00044 #define QUEUE_SIZE 512
00045
00046
00047
00048
00049
00050
00051 SCloudTexture3D::SCloudTexture3D ()
00052 {
00053 Mem = NULL;
00054 ToLight.initUnlit();
00055 ToLight.setShader (CMaterial::Normal);
00056
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
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
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
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
00214
00215
00216
00217 CCloudScape::CCloudScape (NL3D::IDriver *pDriver) : _Noise3D (pDriver)
00218 {
00219 _Driver = pDriver;
00220
00221 _VertexBuffer.setVertexFormat (CVertexBuffer::PositionFlag | CVertexBuffer::TexCoord0Flag | CVertexBuffer::TexCoord1Flag);
00222 _VertexBuffer.setNumVertices (4);
00223
00224
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);
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
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
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
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
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
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
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
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);
00517
00518 if (_Generate)
00519 {
00520
00521 SCloudSchedulerEntry FrontCSE;
00522
00523 FrontCSE = _CloudScheduler.front();
00524
00525
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
00534 CloudIndexToAdd = FrontCSE.CloudIndex;
00535 FrontCSE.DeltaNextCalc = QUEUE_SIZE;
00536 }
00537 else
00538 {
00539
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
00552
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
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
00600 sint32 newPriority = nPeriodeMax;
00601
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
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
00631 if (_CloudSchedulerLastAdded[CloudIndexToAdd].ValidPos == true)
00632 {
00633
00634 SCloudSchedulerEntry &lastCSE = *_CloudSchedulerLastAdded[CloudIndexToAdd].Pos;
00635 sint32 delta = _FrameCounter - lastCSE.Frame;
00636 lastCSE.DeltaNextCalc = delta;
00637
00638
00639 if (newCSE.Power == 0)
00640 _ShouldProcessCloud[CloudIndexToAdd] = false;
00641 }
00642 else
00643 {
00644
00645 _AllClouds[CloudIndexToAdd].reset (_ViewerCam);
00646 }
00647
00648
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
00655 _CloudScheduler.pop_front ();
00656 ++_FrameCounter;
00657
00658
00659
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
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
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 }
00801