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
00029 #include "3d/landscape.h"
00030 #include "nel/misc/bsphere.h"
00031 #include "3d/texture_file.h"
00032 #include "3d/texture_far.h"
00033 #include "3d/landscape_profile.h"
00034 #include "nel/3d/height_map.h"
00035 #include "3d/tile_noise_map.h"
00036 #include "3d/vegetable_manager.h"
00037 #include "3d/vegetable.h"
00038 #include "3d/landscape_vegetable_block.h"
00039 #include "3d/fast_floor.h"
00040 #include "3d/tile_vegetable_desc.h"
00041 #include "3d/texture_dlm.h"
00042 #include "3d/patchdlm_context.h"
00043 #include "nel/misc/hierarchical_timer.h"
00044
00045
00046 #include "3d/vertex_program.h"
00047
00048
00049
00050 using namespace NLMISC;
00051 using namespace std;
00052
00053
00054 namespace NL3D
00055 {
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069 #define NL3D_TESS_ALLOC_BLOCKSIZE 16000
00070 #define NL3D_TESSRDR_ALLOC_BLOCKSIZE 8000
00071
00072
00073
00074
00075 #define NL3D_REFINE_PLIST_DIST_STEP 0.0625
00076
00077
00078
00079
00080
00081
00082 #define NL3D_REFINE_PLIST_NUM_ENTRIES 2048
00083 #define NL3D_REFINE_PLIST_DIST_MAX_MOD 0.7f
00084
00085 #define NL3D_REFINE_PLIST_SPLIT_NUMQUADRANT 16
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098 const uint CLandscape::_PatchQuadGridSize= 128;
00099
00100 const float CLandscape::_PatchQuadGridEltSize= 16;
00101
00102
00103
00104
00105
00106
00107 class CTextureCross : public ITexture
00108 {
00109 public:
00115 virtual void doGenerate()
00116 {
00117
00118 resize (16, 16);
00119
00120
00121 static const uint32 cross[16*16]=
00122 {
00123
00124 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
00125 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff,
00126 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff,
00127 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff,
00128 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff,
00129 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0xffffffff,
00130 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff,
00131 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff,
00132 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff,
00133 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff,
00134 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff,
00135 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff,
00136 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff,
00137 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff,
00138 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff,
00139 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
00140 };
00141
00142
00143 memcpy (&_Data[0][0], cross, 16*16*4);
00144 }
00145
00146
00147 virtual void serial(NLMISC::IStream &f) throw(NLMISC::EStream) {nlstop;}
00148 NLMISC_DECLARE_CLASS(CTextureCross);
00149 };
00150
00151
00152
00153 const char *EBadBind::what() const throw()
00154 {
00155 sint numErr= 0;
00156 const sint NErrByLines= 4;
00157
00158 _Output= "Landscape Bind Error in (3DSMax indices!! (+1) ): ";
00159
00160 std::list<CBindError>::const_iterator it;
00161 for(it= BindErrors.begin();it!=BindErrors.end(); it++, numErr++)
00162 {
00163 char tmp[256];
00164 sint x= it->ZoneId & 255;
00165 sint y= it->ZoneId >> 8;
00166 sprintf(tmp, "zone%3d_%c%c.patch%3d; ", y+1, (char)('A'+(x/26)), (char)('A'+(x%26)), it->PatchId+1);
00167 if( (numErr%NErrByLines) == 0)
00168 _Output+= "\n";
00169 _Output+= tmp;
00170 }
00171 return _Output.c_str();
00172 }
00173
00174
00175
00176
00177 CLandscape::CLandscape() :
00178 TessFaceAllocator(NL3D_TESS_ALLOC_BLOCKSIZE),
00179 TessVertexAllocator(NL3D_TESS_ALLOC_BLOCKSIZE),
00180 TessNearVertexAllocator(NL3D_TESSRDR_ALLOC_BLOCKSIZE),
00181 TessFarVertexAllocator(NL3D_TESSRDR_ALLOC_BLOCKSIZE),
00182 TileMaterialAllocator(NL3D_TESSRDR_ALLOC_BLOCKSIZE),
00183 TileFaceAllocator(NL3D_TESSRDR_ALLOC_BLOCKSIZE),
00184 _Far0VB(CLandscapeVBAllocator::Far0),
00185 _Far1VB(CLandscapeVBAllocator::Far1),
00186 _TileVB(CLandscapeVBAllocator::Tile)
00187 {
00188 TileInfos.resize(NL3D::NbTilesMax);
00189
00190
00191 _FarRdrPassSetVectorFree.resize (getRdrPassIndexWithSize (NL_MAX_SIZE_OF_TEXTURE_EDGE, NL_MAX_SIZE_OF_TEXTURE_EDGE)+1);
00192
00193
00194 _FarInitialized=false;
00195
00196
00197 setupStaticLight (CRGBA(255,255,255), CRGBA(0,0,0), 1.f);
00198
00199 _PointLightDiffuseMaterial= CRGBA::White;
00200
00201
00202 fill(TileInfos.begin(), TileInfos.end(), (CTileInfo*)NULL);
00203
00204 _FarTransition= 10;
00205 _TileDistNear=100.f;
00206 _Threshold= 0.001f;
00207 _RefineMode=true;
00208
00209 _TileMaxSubdivision= 0;
00210
00211 _NFreeLightMaps= 0;
00212
00213
00214 _AutomaticLighting = false;
00215 _AutomaticLightDir= -CVector::K;
00216
00217
00218 _NoiseEnabled= true;
00219
00220
00221 _VertexShaderOk= false;
00222 _VPThresholdChange= false;
00223
00224 _RenderMustRefillVB= false;
00225
00226
00227 _OldRefineCenterSetuped= false;
00228 _SplitPriorityList.init(NL3D_REFINE_PLIST_DIST_STEP, NL3D_REFINE_PLIST_NUM_ENTRIES, NL3D_REFINE_PLIST_DIST_MAX_MOD, NL3D_REFINE_PLIST_SPLIT_NUMQUADRANT);
00229
00230 _MergePriorityList.init(NL3D_REFINE_PLIST_DIST_STEP, NL3D_REFINE_PLIST_NUM_ENTRIES, NL3D_REFINE_PLIST_DIST_MAX_MOD, 0);
00231
00232 _OldRefineCenter= CVector::Null;
00233
00234
00235 _VegetableManager= new CVegetableManager(NL3D_LANDSCAPE_VEGETABLE_MAX_AGP_VERTEX_UNLIT, NL3D_LANDSCAPE_VEGETABLE_MAX_AGP_VERTEX_LIGHTED);
00236
00237
00238 _VegetableManagerEnabled= false;
00239 _DriverOkForVegetable= false;
00240
00241 _DLMGlobalVegetableColor.set(180, 180, 180);
00242
00243 _PZBModelPosition= CVector::Null;
00244
00245
00246
00247 _ULFrequency= 0;
00248 _ULPrecTimeInit= false;
00249
00250 _ULTotalFarPixels= 0;
00251 _ULFarPixelsToUpdate= 0;
00252 _ULRootTextureFar= NULL;
00253 _ULFarCurrentPatchId= 0;
00254
00255 _ULTotalNearPixels= 0;
00256 _ULNearPixelsToUpdate= 0;
00257 _ULRootNearPatch= NULL;
00258 _ULNearCurrentTessBlockId= 0;
00259
00260
00261
00262 _TextureDLM= new CTextureDLM(NL3D_LANDSCAPE_DLM_WIDTH, NL3D_LANDSCAPE_DLM_HEIGHT);
00263 _PatchDLMContextList= new CPatchDLMContextList;
00264 _DLMMaxAttEnd= 30.f;
00265
00266
00267
00268 if( CLandscapeGlobals::PassTriArray.size() < 1000 )
00269 CLandscapeGlobals::PassTriArray.resize( 1000 );
00270
00271 }
00272
00273 CLandscape::~CLandscape()
00274 {
00275 clear();
00276
00277
00278 delete _VegetableManager;
00279 _VegetableManager= NULL;
00280
00281
00282
00283 _TextureDLM= NULL;
00284 delete _PatchDLMContextList;
00285 _PatchDLMContextList= NULL;
00286 }
00287
00288
00289
00290 void CLandscape::init()
00291 {
00292
00293
00294 FarMaterial.initUnlit();
00295 FarMaterial.setSrcBlend(CMaterial::srcalpha);
00296 FarMaterial.setDstBlend(CMaterial::invsrcalpha);
00297
00298
00299 FarMaterial.texEnvOpAlpha(0, CMaterial::Replace);
00300 FarMaterial.texEnvArg0Alpha(0, CMaterial::Diffuse, CMaterial::SrcAlpha);
00301 FarMaterial.texEnvOpAlpha(1, CMaterial::Replace);
00302 FarMaterial.texEnvArg0Alpha(1, CMaterial::Diffuse, CMaterial::SrcAlpha);
00303
00304 FarMaterial.texEnvOpRGB(0, CMaterial::Replace);
00305 FarMaterial.texEnvArg0RGB(0, CMaterial::Texture, CMaterial::SrcColor);
00306 FarMaterial.texEnvOpRGB(1, CMaterial::Add);
00307 FarMaterial.texEnvArg0RGB(1, CMaterial::Texture, CMaterial::SrcColor);
00308 FarMaterial.texEnvArg1RGB(1, CMaterial::Previous, CMaterial::SrcColor);
00309
00310
00311
00312 TileMaterial.initUnlit();
00313
00314
00315 _PatchQuadGrid.create(_PatchQuadGridSize, _PatchQuadGridEltSize);
00316 }
00317
00318
00319
00320 void CLandscape::setThreshold (float thre)
00321 {
00322 thre= max(thre, 0.f);
00323 if(thre != _Threshold)
00324 {
00325 _Threshold= thre;
00326 _VPThresholdChange= true;
00327 }
00328 }
00329
00330
00331
00332 void CLandscape::setTileNear (float tileNear)
00333 {
00334 tileNear= max(tileNear, _FarTransition);
00335
00336 if(tileNear!=_TileDistNear)
00337 {
00338 _TileDistNear= tileNear;
00339 resetRenderFarAndDeleteVBFV();
00340 }
00341
00342 }
00343
00344
00345
00346 void CLandscape::setTileMaxSubdivision (uint tileDiv)
00347 {
00348 nlassert(tileDiv>=0 && tileDiv<=4);
00349
00350 if(tileDiv!=_TileMaxSubdivision)
00351 {
00352 _TileMaxSubdivision= tileDiv;
00353
00354 forceMergeAtTileLevel();
00355 }
00356 }
00357
00358 uint CLandscape::getTileMaxSubdivision ()
00359 {
00360 return _TileMaxSubdivision;
00361 }
00362
00363
00364
00365 void CLandscape::resetRenderFarAndDeleteVBFV()
00366 {
00367
00368 for(ItZoneMap it= Zones.begin();it!=Zones.end();it++)
00369 {
00370 ((*it).second)->resetRenderFarAndDeleteVBFV();
00371 }
00372 }
00373
00374
00375
00376 void CLandscape::forceMergeAtTileLevel()
00377 {
00378
00379 for(ItZoneMap it= Zones.begin();it!=Zones.end();it++)
00380 {
00381 ((*it).second)->forceMergeAtTileLevel();
00382 }
00383 }
00384
00385
00386
00387 bool CLandscape::addZone(const CZone &newZone)
00388 {
00389
00390 updateGlobalsAndLockBuffers (CVector::Null);
00391
00392
00393 uint16 zoneId= newZone.getZoneId();
00394
00395 if(Zones.find(zoneId)!=Zones.end())
00396 {
00397 unlockBuffers();
00398 return false;
00399 }
00400 CZone *zone= new CZone;
00401
00402
00403 zone->build(newZone);
00404
00405
00406 ItLightGroupColorMap itLGC= _LightGroupColorMap.begin();
00407 while( itLGC != _LightGroupColorMap.end() )
00408 {
00409 zone->_PointLightArray.setPointLightFactor(itLGC->first, itLGC->second);
00410 itLGC++;
00411 }
00412
00413
00414
00415 zone->applyHeightField(*this);
00416
00417
00418 zone->compile(this, Zones);
00419
00420
00421 CAABBox zoneBBForErase= zone->getZoneBB().getAABBox();
00422
00423 zoneBBForErase.setHalfSize( zoneBBForErase.getHalfSize() * 1.1f);
00424
00425
00426 for(sint i= 0; i<zone->getNumPatchs(); i++)
00427 {
00428 const CPatch *pa= ((const CZone*)zone)->getPatch(i);
00429 CPatchIdentEx paId;
00430 paId.ZoneId= zoneId;
00431 paId.PatchId= i;
00432 paId.Patch= pa;
00433 CAABBox bb= pa->buildBBox();
00434 _PatchQuadGrid.insert(bb.getMin(), bb.getMax(), paId);
00435
00436
00437 nlassert(zoneBBForErase.include(bb));
00438 }
00439
00440
00441 unlockBuffers();
00442
00443
00444
00445 updateTessBlocksFaceVector();
00446
00447 return true;
00448 }
00449
00450 bool CLandscape::removeZone(uint16 zoneId)
00451 {
00452
00453 updateGlobalsAndLockBuffers (CVector::Null);
00454
00455
00456
00457 if(Zones.find(zoneId)==Zones.end())
00458 {
00459 unlockBuffers();
00460 return false;
00461 }
00462 CZone *zone= Zones[zoneId];
00463
00464
00465
00466
00467 CAABBox zoneBBForErase= zone->getZoneBB().getAABBox();
00468
00469 zoneBBForErase.setHalfSize( zoneBBForErase.getHalfSize() * 1.1f);
00470
00471 _PatchQuadGrid.clearSelection();
00472 _PatchQuadGrid.select(zoneBBForErase.getMin(), zoneBBForErase.getMax());
00473
00474 CQuadGrid<CPatchIdentEx>::CIterator it;
00475 sint nPatchRemoved= 0;
00476 for(it= _PatchQuadGrid.begin(); it!= _PatchQuadGrid.end();)
00477 {
00478
00479 if( (*it).ZoneId== zone->getZoneId() )
00480 {
00481
00482 it= _PatchQuadGrid.erase(it);
00483 nPatchRemoved++;
00484 }
00485 else
00486 it++;
00487 }
00488
00489 nlassert(nPatchRemoved==zone->getNumPatchs());
00490
00491
00492
00493 zone->release(Zones);
00494 delete zone;
00495
00496
00497 unlockBuffers();
00498
00499
00500 updateTessBlocksFaceVector();
00501
00502 return true;
00503 }
00504
00505 void CLandscape::getZoneList(std::vector<uint16> &zoneIds) const
00506 {
00507 zoneIds.clear();
00508 zoneIds.reserve(Zones.size());
00509 std::map<uint16, CZone*>::const_iterator it;
00510 for(it= Zones.begin();it!=Zones.end();it++)
00511 {
00512 zoneIds.push_back((*it).first);
00513 }
00514 }
00515
00516 void CLandscape::buildZoneName(sint zoneId, std::string &zoneName)
00517 {
00518 char tmp[256];
00519 sint x= zoneId & 255;
00520 sint y= zoneId >> 8;
00521 sprintf(tmp, "%d_%c%c", y+1, (char)('A'+(x/26)), (char)('A'+(x%26)));
00522 zoneName= tmp;
00523 }
00524
00525 void CLandscape::clear()
00526 {
00527
00528 vector<uint16> zoneIds;
00529 getZoneList(zoneIds);
00530
00531
00532 sint i;
00533 for(i=0;i<(sint)zoneIds.size();i++)
00534 {
00535 nlverify(removeZone(zoneIds[i]));
00536 }
00537
00538
00539 _PatchQuadGrid.clear();
00540
00541
00542
00543 _Far0VB.clear();
00544 _Far1VB.clear();
00545 _TileVB.clear();
00546
00547
00548
00549
00550 for(i=0;i<(sint)_FarRdrPassSetVectorFree.size();i++)
00551 {
00552 _FarRdrPassSetVectorFree[i].clear();
00553 }
00554
00555 ItSPRenderPassSet itFar;
00556
00557 while( (itFar= _FarRdrPassSet.begin()) != _FarRdrPassSet.end())
00558 {
00559
00560 eraseFarRenderPassFromSet(*itFar);
00561 }
00562
00563
00564
00565 _Driver= NULL;
00566 }
00567
00568
00569 void CLandscape::setDriver(IDriver *drv)
00570 {
00571 nlassert(drv);
00572 if(_Driver != drv)
00573 {
00574 _Driver= drv;
00575
00576
00577
00578 _VertexShaderOk= (_Driver->isVertexProgramSupported() && !_Driver->isVertexProgramEmulated());
00579
00580
00581
00582
00583 _DriverOkForVegetable= _VertexShaderOk && (_Driver->getMaxVerticesByVertexBufferHard()>=(uint)NL3D_LANDSCAPE_VEGETABLE_MAX_AGP_VERTEX_MAX);
00584
00585 }
00586 }
00587
00588
00589 void CLandscape::clip(const CVector &refineCenter, const std::vector<CPlane> &pyramid)
00590 {
00591
00592 updateGlobalsAndLockBuffers (refineCenter);
00593
00594
00595
00596 for(ItZoneMap it= Zones.begin();it!=Zones.end();it++)
00597 {
00598 (*it).second->clip(pyramid);
00599 }
00600
00601
00602 unlockBuffers();
00603
00604
00605
00606 nlassert(_TessBlockModificationRoot.getNextToModify()==NULL);
00607 updateTessBlocksFaceVector();
00608
00609 }
00610
00611 void CLandscape::refine(const CVector &refineCenter)
00612 {
00613 NL3D_PROFILE_LAND_SET(ProfNRefineFaces, 0);
00614 NL3D_PROFILE_LAND_SET(ProfNRefineComputeFaces, 0);
00615 NL3D_PROFILE_LAND_SET(ProfNRefineLeaves, 0);
00616 NL3D_PROFILE_LAND_SET(ProfNSplits, 0);
00617 NL3D_PROFILE_LAND_SET(ProfNMerges, 0);
00618 NL3D_PROFILE_LAND_SET(ProfNRefineInTileTransition, 0);
00619 NL3D_PROFILE_LAND_SET(ProfNRefineWithLowDistance, 0);
00620 NL3D_PROFILE_LAND_SET(ProfNSplitsPass, 0);
00621
00622 if(!_RefineMode)
00623 return;
00624
00625
00626
00627 CTessFacePListNode rootSplitTessFaceToUpdate;
00628 CTessFacePListNode rootMergeTessFaceToUpdate;
00629 if( !_OldRefineCenterSetuped )
00630 {
00631
00632 _OldRefineCenterSetuped= true;
00633 _OldRefineCenter= refineCenter;
00634
00635
00636 _SplitPriorityList.shiftAll(rootSplitTessFaceToUpdate);
00637 _MergePriorityList.shiftAll(rootMergeTessFaceToUpdate);
00638 }
00639 else
00640 {
00641
00642 CVector diff= refineCenter - _OldRefineCenter;
00643 _OldRefineCenter= refineCenter;
00644
00645
00646 _SplitPriorityList.shift(diff, rootSplitTessFaceToUpdate);
00647 _MergePriorityList.shift(diff, rootMergeTessFaceToUpdate);
00648 }
00649
00650
00651
00652
00653
00654 updateGlobalsAndLockBuffers (refineCenter);
00655
00656
00657
00658 CLandscapeGlobals::CurrentDate++;
00659
00660
00661 OptFastFloorBegin();
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674 while( rootMergeTessFaceToUpdate.nextInPList() != &rootMergeTessFaceToUpdate )
00675 {
00676
00677 CTessFace *face= static_cast<CTessFace*>(rootMergeTessFaceToUpdate.nextInPList());
00678
00679
00680
00681 face->updateRefineMerge();
00682 }
00683
00684
00685
00686 do
00687 {
00688 NL3D_PROFILE_LAND_ADD(ProfNSplitsPass, 1);
00689
00690
00691 rootSplitTessFaceToUpdate.appendPList(_RootNewLeaves);
00692
00693
00694 while( rootSplitTessFaceToUpdate.nextInPList() != &rootSplitTessFaceToUpdate )
00695 {
00696
00697 CTessFace *face= static_cast<CTessFace*>(rootSplitTessFaceToUpdate.nextInPList());
00698
00699
00700 face->updateRefineSplit();
00701 }
00702
00703 }
00704
00705 while( _RootNewLeaves.nextInPList() != &_RootNewLeaves );
00706
00707
00708 OptFastFloorEnd();
00709
00710
00711
00712 {
00713 H_AUTO( NL3D_Vegetable_Update );
00714
00715
00716 OptFastFloorBegin();
00717
00718
00719 CLandscapeVegetableBlock *vegetBlock= _VegetableBlockList.begin();
00720 for(;vegetBlock!=NULL; vegetBlock= (CLandscapeVegetableBlock*)vegetBlock->Next)
00721 {
00722 vegetBlock->update(refineCenter, _VegetableManager);
00723 }
00724
00725
00726 _VegetableManager->updateLighting();
00727
00728
00729 OptFastFloorEnd();
00730 }
00731
00732
00733
00734 unlockBuffers();
00735
00736
00737 updateTessBlocksFaceVector();
00738
00739 }
00740
00741
00742
00743 void CLandscape::refineAll(const CVector &refineCenter)
00744 {
00745
00746 updateGlobalsAndLockBuffers (refineCenter);
00747
00748
00749
00750 CLandscapeGlobals::CurrentDate++;
00751
00752 for(ItZoneMap it= Zones.begin();it!=Zones.end();it++)
00753 {
00754 (*it).second->refineAll();
00755 }
00756
00757
00758 unlockBuffers();
00759
00760
00761 updateTessBlocksFaceVector();
00762 }
00763
00764
00765
00766 void CLandscape::excludePatchFromRefineAll(sint zoneId, uint patch, bool exclude)
00767 {
00768 ItZoneMap it= Zones.find(zoneId);
00769 if(it!=Zones.end())
00770 {
00771 it->second->excludePatchFromRefineAll(patch, exclude);
00772 }
00773
00774 }
00775
00776
00777
00778 void CLandscape::averageTesselationVertices()
00779 {
00780
00781 updateGlobalsAndLockBuffers (CVector::Null);
00782
00783
00784
00785 CLandscapeGlobals::CurrentDate++;
00786
00787 for(ItZoneMap it= Zones.begin();it!=Zones.end();it++)
00788 {
00789 (*it).second->averageTesselationVertices();
00790 }
00791
00792
00793 unlockBuffers();
00794
00795
00796
00797 nlassert(_TessBlockModificationRoot.getNextToModify()==NULL);
00798 updateTessBlocksFaceVector();
00799
00800 }
00801
00802
00803
00804
00805 void CLandscape::updateGlobalsAndLockBuffers (const CVector &refineCenter)
00806 {
00807
00808
00809
00810 CLandscapeGlobals::FarTransition= _FarTransition;
00811
00812
00813 CLandscapeGlobals::TileMaxSubdivision= _TileMaxSubdivision;
00814 CLandscapeGlobals::TileDistNear = _TileDistNear;
00815 CLandscapeGlobals::TileDistFar = CLandscapeGlobals::TileDistNear+20;
00816 CLandscapeGlobals::TileDistNearSqr = sqr(CLandscapeGlobals::TileDistNear);
00817 CLandscapeGlobals::TileDistFarSqr = sqr(CLandscapeGlobals::TileDistFar);
00818 CLandscapeGlobals::OOTileDistDeltaSqr = 1.0f / (CLandscapeGlobals::TileDistFarSqr - CLandscapeGlobals::TileDistNearSqr);
00819
00820
00821
00822 CLandscapeGlobals::TilePixelSize= 128.0f;
00823 CLandscapeGlobals::TilePixelBias128= 0.5f/CLandscapeGlobals::TilePixelSize;
00824 CLandscapeGlobals::TilePixelScale128= 1-1/CLandscapeGlobals::TilePixelSize;
00825 CLandscapeGlobals::TilePixelBias256= 0.5f/(CLandscapeGlobals::TilePixelSize*2);
00826 CLandscapeGlobals::TilePixelScale256= 1-1/(CLandscapeGlobals::TilePixelSize*2);
00827
00828
00829 CLandscapeGlobals::RefineThreshold= _Threshold;
00830
00831 if (_Threshold == 0.0f)
00832 CLandscapeGlobals::OORefineThreshold = FLT_MAX;
00833 else
00834 CLandscapeGlobals::OORefineThreshold = 1.0f / CLandscapeGlobals::RefineThreshold;
00835
00836
00837 CLandscapeGlobals::RefineCenter= refineCenter;
00838 CLandscapeGlobals::TileFarSphere.Center= CLandscapeGlobals::RefineCenter;
00839 CLandscapeGlobals::TileFarSphere.Radius= CLandscapeGlobals::TileDistFar;
00840 CLandscapeGlobals::TileNearSphere.Center= CLandscapeGlobals::RefineCenter;
00841 CLandscapeGlobals::TileNearSphere.Radius= CLandscapeGlobals::TileDistNear;
00842
00843
00844 CLandscapeGlobals::PZBModelPosition= _PZBModelPosition;
00845
00846
00847 CLandscapeGlobals::CurrentFar0VBAllocator= &_Far0VB;
00848 CLandscapeGlobals::CurrentFar1VBAllocator= &_Far1VB;
00849 CLandscapeGlobals::CurrentTileVBAllocator= &_TileVB;
00850
00851
00852 if(_Driver)
00853 {
00854 _Far0VB.updateDriver(_Driver);
00855 _Far1VB.updateDriver(_Driver);
00856 _TileVB.updateDriver(_Driver);
00857
00858
00859 if(_DriverOkForVegetable)
00860 _VegetableManager->updateDriver(_Driver);
00861
00862 lockBuffers ();
00863 }
00864 }
00865
00866
00867
00868 void CLandscape::lockBuffers ()
00869 {
00870 _Far0VB.lockBuffer(CLandscapeGlobals::CurrentFar0VBInfo);
00871 _Far1VB.lockBuffer(CLandscapeGlobals::CurrentFar1VBInfo);
00872 _TileVB.lockBuffer(CLandscapeGlobals::CurrentTileVBInfo);
00873
00874
00875 _VegetableManager->lockBuffers();
00876
00877
00878 CLandscapeGlobals::VertexProgramEnabled= _VertexShaderOk;
00879 }
00880
00881
00882
00883 void CLandscape::unlockBuffers()
00884 {
00885 _Far0VB.unlockBuffer();
00886 _Far1VB.unlockBuffer();
00887 _TileVB.unlockBuffer();
00888
00889
00890 _VegetableManager->unlockBuffers();
00891 }
00892
00893
00894 void CLandscape::synchronizeATIVBHards()
00895 {
00896 _Far0VB.synchronizeATIVBHard();
00897 _Far1VB.synchronizeATIVBHard();
00898 _TileVB.synchronizeATIVBHard();
00899 }
00900
00901
00902 void CLandscape::updateTessBlocksFaceVector()
00903 {
00904
00905 CTessBlock *tb;
00906 while( (tb=_TessBlockModificationRoot.getNextToModify()) !=NULL )
00907 {
00908
00909 CPatch *patch= tb->getPatch();
00910
00911
00912 patch->recreateTessBlockFaceVector(*tb);
00913
00914
00915 tb->removeFromModifyList();
00916 }
00917 }
00918
00919
00920
00921 static inline void initPassTriArray(CPatchRdrPass &pass)
00922 {
00923 uint numIndices= pass.getMaxRenderedFaces()*3;
00924
00925 if( CLandscapeGlobals::PassTriArray.size() < numIndices )
00926 CLandscapeGlobals::PassTriArray.resize( numIndices );
00927
00928 NL3D_LandscapeGlobals_PassTriCurPtr= &CLandscapeGlobals::PassTriArray[0];
00929 }
00930
00931
00932
00933 static inline void drawPassTriArray(CMaterial &mat)
00934 {
00935 if(NL3D_LandscapeGlobals_PassNTri>0)
00936 {
00937 CLandscapeGlobals::PatchCurrentDriver->setupMaterial(mat);
00938 CLandscapeGlobals::PatchCurrentDriver->renderSimpleTriangles(&CLandscapeGlobals::PassTriArray[0], NL3D_LandscapeGlobals_PassNTri);
00939 NL3D_LandscapeGlobals_PassNTri= 0;
00940 }
00941 }
00942
00943
00944
00945 void CLandscape::render(const CVector &refineCenter, const CVector &frontVector, const CPlane pyramid[NL3D_TESSBLOCK_NUM_CLIP_PLANE], bool doTileAddPass)
00946 {
00947 IDriver *driver= _Driver;
00948 nlassert(driver);
00949
00950
00951 CLandscapeGlobals::CurrentRenderDate++;
00952
00953
00954 ItZoneMap it;
00955 sint i;
00956 ItTileRdrPassSet itTile;
00957 ItSPRenderPassSet itFar;
00958
00959
00960 NL3D_PROFILE_LAND_SET(ProfNRdrFar0, 0);
00961 NL3D_PROFILE_LAND_SET(ProfNRdrFar1, 0);
00962 for(i=0;i<NL3D_MAX_TILE_PASS;i++)
00963 {
00964 NL3D_PROFILE_LAND_SET(ProfNRdrTile[i], 0);
00965 }
00966
00967
00968
00969
00970 updateGlobalsAndLockBuffers (refineCenter);
00971
00972
00973
00974
00975
00976
00977
00978 for(itFar= _FarRdrPassSet.begin(); itFar!= _FarRdrPassSet.end(); itFar++)
00979 {
00980 CPatchRdrPass &pass= **itFar;
00981
00982 pass.clearAllRenderList();
00983 }
00984
00985
00986 for(itTile= TileRdrPassSet.begin(); itTile!= TileRdrPassSet.end(); itTile++)
00987 {
00988 CPatchRdrPass &pass= const_cast<CPatchRdrPass&>(*itTile);
00989
00990 pass.clearAllRenderList();
00991 }
00992
00993
00994 for(sint lightRdrPass=0; lightRdrPass<(sint)_TextureNears.size(); lightRdrPass++)
00995 {
00996 CPatchRdrPass &pass= *_TextureNears[lightRdrPass];
00997
00998 pass.clearAllRenderList();
00999 }
01000
01001
01002
01003
01004
01005
01006 for(i=0; i<NL3D_TESSBLOCK_NUM_CLIP_PLANE; i++)
01007 {
01008 CTessBlock::CurrentPyramid[i]= pyramid[i];
01009 }
01010
01011 for(it= Zones.begin();it!=Zones.end();it++)
01012 {
01013 (*it).second->preRender();
01014 }
01015
01016
01017
01018
01019
01020 if( _Far0VB.reallocationOccurs() || _Far1VB.reallocationOccurs() || _TileVB.reallocationOccurs() )
01021 _RenderMustRefillVB= true;
01022
01023
01024
01025 if( _VertexShaderOk && _VPThresholdChange )
01026 {
01027 _VPThresholdChange= false;
01028 _RenderMustRefillVB= true;
01029 }
01030
01031
01032 if(_RenderMustRefillVB )
01033 {
01034
01035 _RenderMustRefillVB= false;
01036
01037
01038 _Far0VB.resetReallocation();
01039 _Far1VB.resetReallocation();
01040 _TileVB.resetReallocation();
01041
01042
01043
01044 unlockBuffers();
01045 lockBuffers();
01046
01047
01048 for(it= Zones.begin();it!=Zones.end();it++)
01049 {
01050 if((*it).second->ClipResult==CZone::ClipOut)
01051 continue;
01052 for(sint i=0;i<(*it).second->getNumPatchs(); i++)
01053 {
01054 CPatch *patch= (*it).second->getPatch(i);
01055 patch->fillVBIfVisible();
01056 }
01057 }
01058 }
01059
01060
01061
01062 if(!_VertexShaderOk)
01063 {
01064
01065 for(it= Zones.begin();it!=Zones.end();it++)
01066 {
01067 if((*it).second->ClipResult==CZone::ClipOut)
01068 continue;
01069 for(sint i=0;i<(*it).second->getNumPatchs(); i++)
01070 {
01071 CPatch *patch= (*it).second->getPatch(i);
01072
01073 patch->computeSoftwareGeomorphAndAlpha();
01074 }
01075 }
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091 }
01092
01093
01094
01095
01096
01097 unlockBuffers();
01098
01099
01100
01101 synchronizeATIVBHards();
01102
01103
01104
01105 if(_VertexShaderOk)
01106 {
01107
01108 driver->setConstantMatrix(0, IDriver::ModelViewProjection, IDriver::Identity);
01109
01110 driver->setConstant(4, 0, 1, 0.5f, 0);
01111
01112 driver->setConstant(5, refineCenter);
01113
01114 driver->setConstant(6, CLandscapeGlobals::TileDistFarSqr, CLandscapeGlobals::OOTileDistDeltaSqr, 0, 0);
01115
01116 driver->setConstantMatrix(8, IDriver::ModelView, IDriver::Identity);
01117
01118 driver->setConstant(12, _PZBModelPosition);
01119 }
01120
01121
01122
01123
01124
01125
01126
01127
01128 CPatchDLMContext *dlmCtxPtr= _PatchDLMContextList->begin();
01129 while(dlmCtxPtr!=NULL)
01130 {
01131
01132 if(dlmCtxPtr->getPatch()->getFar0() == 0
01133 && !dlmCtxPtr->getPatch()->isRenderClipped() )
01134 {
01135
01136
01137 dlmCtxPtr->compileLighting(CPatchDLMContext::ModulateTileColor);
01138 }
01139
01140
01141 dlmCtxPtr= (CPatchDLMContext*)dlmCtxPtr->Next;
01142 }
01143
01144
01145
01146
01147
01148
01149 _TileVB.activate(0);
01150
01151
01152
01153
01154
01155 CLandscapeGlobals::PatchCurrentDriver= driver;
01156
01157
01158
01159
01160 nlassert(NL3D_MAX_TILE_PASS==5);
01161 static sint RenderOrder[NL3D_MAX_TILE_PASS]= {NL3D_TILE_PASS_RGB0, NL3D_TILE_PASS_RGB1, NL3D_TILE_PASS_RGB2,
01162 NL3D_TILE_PASS_LIGHTMAP, NL3D_TILE_PASS_ADD};
01163
01164 for(i=0; i<NL3D_MAX_TILE_PASS; i++)
01165 {
01166 sint passOrder= RenderOrder[i];
01167
01168
01169
01170 if(_VertexShaderOk)
01171 {
01172 if(passOrder == NL3D_TILE_PASS_LIGHTMAP)
01173 {
01174
01175 _TileVB.activate(1);
01176 }
01177 else if(passOrder == NL3D_TILE_PASS_ADD)
01178 {
01179
01180 _TileVB.activate(0);
01181 }
01182 }
01183
01184
01185
01186 if((passOrder==NL3D_TILE_PASS_ADD) && !doTileAddPass)
01187 continue;
01188
01189
01190
01191
01192
01193 TileMaterial.texEnvOpRGB(0, CMaterial::Replace);
01194 TileMaterial.texEnvArg0RGB(0, CMaterial::Texture, CMaterial::SrcColor);
01195 TileMaterial.texEnvOpAlpha(0, CMaterial::Replace);
01196 TileMaterial.texEnvArg0Alpha(0, CMaterial::Texture, CMaterial::SrcAlpha);
01197
01198
01199
01200
01201 TileMaterial.setTexEnvMode(1, TileMaterial.getTexEnvMode(0));
01202
01203
01204 if(passOrder==NL3D_TILE_PASS_RGB0)
01205 {
01206
01207 TileMaterial.setBlend(false);
01208 }
01209 else
01210 {
01211 TileMaterial.setBlend(true);
01212 switch(passOrder)
01213 {
01214 case NL3D_TILE_PASS_RGB1:
01215 case NL3D_TILE_PASS_RGB2:
01216
01217 TileMaterial.setBlendFunc(CMaterial::srcalpha, CMaterial::invsrcalpha);
01218
01219
01220
01221 TileMaterial.texEnvOpRGB(1, CMaterial::Replace);
01222 TileMaterial.texEnvArg0RGB(1, CMaterial::Previous, CMaterial::SrcColor);
01223
01224 TileMaterial.texEnvOpAlpha(1, CMaterial::Replace);
01225 TileMaterial.texEnvArg0Alpha(1, CMaterial::Texture, CMaterial::SrcAlpha);
01226 break;
01227 case NL3D_TILE_PASS_LIGHTMAP:
01228
01229 TileMaterial.setBlendFunc(CMaterial::zero, CMaterial::srccolor);
01230
01231
01232 TileMaterial.texEnvOpRGB(1, CMaterial::Add);
01233 TileMaterial.texEnvArg0RGB(1, CMaterial::Texture, CMaterial::SrcColor);
01234 TileMaterial.texEnvArg1RGB(1, CMaterial::Previous, CMaterial::SrcColor);
01235
01236 break;
01237 case NL3D_TILE_PASS_ADD:
01238
01239 TileMaterial.setBlendFunc(CMaterial::srcalpha, CMaterial::one);
01240
01241
01242 TileMaterial.texEnvOpAlpha(0, CMaterial::Replace);
01243 TileMaterial.texEnvArg0Alpha(0, CMaterial::Constant, CMaterial::SrcAlpha);
01244
01245 TileMaterial.texConstantColor(0, CRGBA(255, 255, 255, 255));
01246
01247
01248
01249
01250 TileMaterial.texEnvOpRGB(1, CMaterial::Replace);
01251 TileMaterial.texEnvArg0RGB(1, CMaterial::Previous, CMaterial::SrcColor);
01252
01253 TileMaterial.texEnvOpAlpha(1, CMaterial::Modulate);
01254 TileMaterial.texEnvArg0Alpha(1, CMaterial::Texture, CMaterial::SrcAlpha);
01255 TileMaterial.texEnvArg1Alpha(1, CMaterial::Previous, CMaterial::SrcAlpha);
01256
01257 break;
01258 default:
01259 nlstop;
01260 };
01261 }
01262
01263 TileMaterial.setTexture(0, NULL);
01264 TileMaterial.setTexture(1, NULL);
01265 TileMaterial.setTexture(2, NULL);
01266
01267
01268
01269
01270
01271 if(passOrder==NL3D_TILE_PASS_RGB0)
01272 {
01273
01274 ItTileRdrPassSet itTile;
01275 for(itTile= TileRdrPassSet.begin(); itTile!= TileRdrPassSet.end(); itTile++)
01276 {
01277
01278
01279 CPatchRdrPass &pass= const_cast<CPatchRdrPass&>(*itTile);
01280
01281
01282 initPassTriArray(pass);
01283
01284
01285 TileMaterial.setTexture(0, pass.TextureDiffuse);
01286
01287
01288 CRdrTileId *tileToRdr= pass.getRdrTileRoot(passOrder);
01289 while(tileToRdr)
01290 {
01291
01292 tileToRdr->TileMaterial->renderTilePassRGB0();
01293 tileToRdr= (CRdrTileId*)tileToRdr->getNext();
01294 }
01295
01296 drawPassTriArray(TileMaterial);
01297 }
01298 }
01299 else if(passOrder==NL3D_TILE_PASS_LIGHTMAP)
01300 {
01301
01302
01303
01304
01305
01306
01307 TileMaterial.setTexture(0, _TextureDLM);
01308
01309
01310 if(!_VertexShaderOk)
01311 {
01312
01313 driver->mapTextureStageToUV(0, 2);
01314 }
01315
01316
01317
01318
01319 for(sint lightRdrPass=0; lightRdrPass<(sint)_TextureNears.size(); lightRdrPass++)
01320 {
01321 CPatchRdrPass &pass= *_TextureNears[lightRdrPass];
01322
01323
01324 initPassTriArray(pass);
01325
01326
01327
01328 TileMaterial.setTexture(1, pass.TextureDiffuse);
01329
01330
01331 CRdrTileId *tileToRdr= pass.getRdrTileRoot(passOrder);
01332 while(tileToRdr)
01333 {
01334
01335 tileToRdr->TileMaterial->renderTilePassLightmap();
01336 tileToRdr= (CRdrTileId*)tileToRdr->getNext();
01337 }
01338
01339 drawPassTriArray(TileMaterial);
01340 }
01341
01342
01343 if(!_VertexShaderOk)
01344 {
01345
01346 driver->mapTextureStageToUV(0, 0);
01347 }
01348 }
01349 else
01350 {
01351
01352
01353
01354
01355 ItTileRdrPassSet itTile;
01356 for(itTile= TileRdrPassSet.begin(); itTile!= TileRdrPassSet.end(); itTile++)
01357 {
01358
01359
01360 CPatchRdrPass &pass= const_cast<CPatchRdrPass&>(*itTile);
01361
01362
01363 initPassTriArray(pass);
01364
01365
01366 CRdrTileId *tileToRdr= pass.getRdrTileRoot(passOrder);
01367 while(tileToRdr)
01368 {
01369
01370 tileToRdr->TileMaterial->renderTile(passOrder);
01371 tileToRdr= (CRdrTileId*)tileToRdr->getNext();
01372 }
01373
01374
01375 if(NL3D_LandscapeGlobals_PassNTri>0)
01376 {
01377
01378
01379 TileMaterial.setTexture(0, pass.TextureDiffuse);
01380
01381
01382
01383 TileMaterial.setTexture(1, pass.TextureAlpha);
01384 }
01385
01386
01387 drawPassTriArray(TileMaterial);
01388 }
01389 }
01390 }
01391
01392
01393
01394
01395
01396
01397
01398
01399 dlmCtxPtr= _PatchDLMContextList->begin();
01400 while(dlmCtxPtr!=NULL)
01401 {
01402
01403 if( (dlmCtxPtr->getPatch()->getFar0()>0 || dlmCtxPtr->getPatch()->getFar1()>0)
01404 && !dlmCtxPtr->getPatch()->isRenderClipped() )
01405 {
01406
01407
01408 dlmCtxPtr->compileLighting(CPatchDLMContext::ModulateTextureFar);
01409 }
01410
01411
01412 dlmCtxPtr= (CPatchDLMContext*)dlmCtxPtr->Next;
01413 }
01414
01415
01416
01417
01418
01419
01420 _Far0VB.activate(0);
01421
01422
01423
01424
01425
01426
01427 FarMaterial.setBlend(false);
01428
01429 FarMaterial.setTexture(1, _TextureDLM);
01430
01431
01432 itFar=_FarRdrPassSet.begin();
01433 while (itFar!=_FarRdrPassSet.end())
01434 {
01435 CPatchRdrPass &pass= **itFar;
01436
01437
01438 initPassTriArray(pass);
01439
01440
01441 FarMaterial.setTexture(0, pass.TextureDiffuse);
01442
01443 if(pass.TextureDiffuse && pass.TextureDiffuse->touched())
01444 driver->setupTexture(*pass.TextureDiffuse);
01445
01446
01447 CRdrPatchId *patchToRdr= pass.getRdrPatchFar0();
01448 while(patchToRdr)
01449 {
01450
01451 patchToRdr->Patch->renderFar0();
01452 patchToRdr= (CRdrPatchId*)patchToRdr->getNext();
01453 }
01454
01455 drawPassTriArray(FarMaterial);
01456
01457
01458 itFar++;
01459 }
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470 _Far1VB.activate(0);
01471
01472
01473
01474
01475
01476
01477 FarMaterial.setBlend(true);
01478
01479 FarMaterial.setTexture(1, _TextureDLM);
01480
01481
01482
01483 itFar=_FarRdrPassSet.begin();
01484 while (itFar!=_FarRdrPassSet.end())
01485 {
01486 CPatchRdrPass &pass= **itFar;
01487
01488
01489 initPassTriArray(pass);
01490
01491
01492 FarMaterial.setTexture(0, pass.TextureDiffuse);
01493
01494 if(pass.TextureDiffuse && pass.TextureDiffuse->touched())
01495 driver->setupTexture(*pass.TextureDiffuse);
01496
01497
01498 CRdrPatchId *patchToRdr= pass.getRdrPatchFar1();
01499 while(patchToRdr)
01500 {
01501
01502 patchToRdr->Patch->renderFar1();
01503 patchToRdr= (CRdrPatchId*)patchToRdr->getNext();
01504 }
01505
01506 drawPassTriArray(FarMaterial);
01507
01508
01509 itFar++;
01510 }
01511
01512
01513
01514
01515 FarMaterial.setTexture(0, NULL);
01516 FarMaterial.setTexture(1, NULL);
01517 FarMaterial.setTexture(2, NULL);
01518 FarMaterial.setTexture(3, NULL);
01519 TileMaterial.setTexture(0, NULL);
01520 TileMaterial.setTexture(1, NULL);
01521 TileMaterial.setTexture(2, NULL);
01522 TileMaterial.setTexture(3, NULL);
01523
01524
01525 CLandscapeGlobals::PatchCurrentDriver= NULL;
01526
01527
01528 if(_VertexShaderOk)
01529 driver->activeVertexProgram (NULL);
01530
01531
01532
01533
01534
01535
01536
01537 if(isVegetableActive())
01538 {
01539
01540
01541
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554 CRGBA vegetDLMCte;
01555
01556 uint v;
01557 v= (_DLMGlobalVegetableColor.R*256) / (_PointLightDiffuseMaterial.R+1);
01558 vegetDLMCte.R= (uint8)min(v, 255U);
01559 v= (_DLMGlobalVegetableColor.G*256) / (_PointLightDiffuseMaterial.G+1);
01560 vegetDLMCte.G= (uint8)min(v, 255U);
01561 v= (_DLMGlobalVegetableColor.B*256) / (_PointLightDiffuseMaterial.B+1);
01562 vegetDLMCte.B= (uint8)min(v, 255U);
01563
01564
01565 dlmCtxPtr= _PatchDLMContextList->begin();
01566 while(dlmCtxPtr!=NULL)
01567 {
01568
01569
01570 if(dlmCtxPtr->getPatch()->getTileMaterialRefCount()>0
01571 && !dlmCtxPtr->getPatch()->isRenderClipped() )
01572 {
01573
01574 dlmCtxPtr->compileLighting(CPatchDLMContext::ModulateConstant, vegetDLMCte);
01575 }
01576
01577
01578 dlmCtxPtr= (CPatchDLMContext*)dlmCtxPtr->Next;
01579 }
01580 }
01581
01582
01583
01584 _VegetableManager->resetNumVegetableFaceRendered();
01585
01586
01587
01588 if(isVegetableActive())
01589 {
01590
01591 vector<CPlane> vegetablePyramid;
01592 vegetablePyramid.resize(NL3D_TESSBLOCK_NUM_CLIP_PLANE);
01593 for(i=0;i<NL3D_TESSBLOCK_NUM_CLIP_PLANE;i++)
01594 {
01595 vegetablePyramid[i]= pyramid[i];
01596 }
01597 _VegetableManager->render(refineCenter, frontVector, vegetablePyramid, _TextureDLM, driver);
01598 }
01599
01600 }
01601
01602
01603
01604
01605
01606
01607
01608
01609
01610
01611 ITexture *CLandscape::findTileTexture(const std::string &textName)
01612 {
01613 ITexture *text;
01614 text= TileTextureMap[textName];
01615
01616
01617
01618
01619 if(!text)
01620 {
01621 TileTextureMap[textName]= text= new CTextureFile(textName);
01622 text->setWrapS(ITexture::Clamp);
01623 text->setWrapT(ITexture::Clamp);
01624 text->setUploadFormat(ITexture::DXTC5);
01625 }
01626 return text;
01627 }
01628
01629
01630
01631 CPatchRdrPass *CLandscape::findTileRdrPass(const CPatchRdrPass &pass)
01632 {
01633 ItTileRdrPassSet it;
01634
01635 it= (TileRdrPassSet.insert(pass)).first;
01636
01637 return const_cast<CPatchRdrPass*>(&(*it));
01638 }
01639
01640
01641
01642 void CLandscape::loadTile(uint16 tileId)
01643 {
01644 CTile *tile;
01645 CTileInfo *tileInfo;
01646 string textName;
01647
01648
01649
01650
01651
01652 if(tileId<TileBank.getTileCount())
01653 tile= TileBank.getTile(tileId);
01654 else
01655 tile= NULL;
01656
01657 nlassert(TileInfos[tileId]==NULL);
01658 TileInfos[tileId]= tileInfo= new CTileInfo;
01659
01660
01661
01662 if(tile)
01663 textName= tile->getRelativeFileName(CTile::additive);
01664 else
01665 textName= "";
01666
01667 if(textName=="")
01668 tileInfo->AdditiveRdrPass= NULL;
01669 else
01670 {
01671
01672 CPatchRdrPass pass;
01673 pass.TextureDiffuse= findTileTexture(TileBank.getAbsPath()+textName);
01674
01675
01676 textName= tile->getRelativeFileName (CTile::alpha);
01677 if(textName!="")
01678 pass.TextureAlpha= findTileTexture(TileBank.getAbsPath()+textName);
01679
01680
01681 tileInfo->AdditiveRdrPass= findTileRdrPass(pass);
01682
01683
01684 tileInfo->AdditiveUvScaleBias.x= 0;
01685 tileInfo->AdditiveUvScaleBias.y= 0;
01686 tileInfo->AdditiveUvScaleBias.z= 1;
01687 }
01688
01689
01690
01691
01692
01693 CPatchRdrPass pass;
01694
01695 if(tile)
01696 {
01697 textName= tile->getRelativeFileName(CTile::diffuse);
01698 if(textName!="")
01699 pass.TextureDiffuse= findTileTexture(TileBank.getAbsPath()+textName);
01700 else
01701 {
01702 pass.TextureDiffuse= new CTextureCross;
01703 nldebug("Missing Tile diffuse texname: %d", tileId);
01704 }
01705 }
01706 else
01707 pass.TextureDiffuse= new CTextureCross;
01708 if(tile)
01709 {
01710 textName= tile->getRelativeFileName (CTile::alpha);
01711 if(textName!="")
01712 pass.TextureAlpha= findTileTexture(TileBank.getAbsPath()+textName);
01713 }
01714
01715
01716
01717 tileInfo->DiffuseRdrPass= findTileRdrPass(pass);
01718
01719
01720 tileInfo->DiffuseUvScaleBias.x= 0;
01721 tileInfo->DiffuseUvScaleBias.y= 0;
01722 tileInfo->DiffuseUvScaleBias.z= 1;
01723 tileInfo->AlphaUvScaleBias.x= 0;
01724 tileInfo->AlphaUvScaleBias.y= 0;
01725 tileInfo->AlphaUvScaleBias.z= 1;
01726
01727 if(tile)
01728 tileInfo->RotAlpha= tile->getRotAlpha();
01729 else
01730 tileInfo->RotAlpha= 0;
01731
01732
01733
01734
01735 if(tileInfo->AdditiveRdrPass)
01736 tileInfo->AdditiveRdrPass->RefCount++;
01737 if(tileInfo->DiffuseRdrPass)
01738 tileInfo->DiffuseRdrPass->RefCount++;
01739
01740 }
01741
01742
01743
01744 void CLandscape::releaseTile(uint16 tileId)
01745 {
01746 CTileInfo *tileInfo;
01747 tileInfo= TileInfos[tileId];
01748 nlassert(tileInfo!=NULL);
01749
01750
01751 if(tileInfo->AdditiveRdrPass)
01752 tileInfo->AdditiveRdrPass->RefCount--;
01753 if(tileInfo->DiffuseRdrPass)
01754 tileInfo->DiffuseRdrPass->RefCount--;
01755
01756 delete tileInfo;
01757 TileInfos[tileId]= NULL;
01758 }
01759
01760
01761
01762 CPatchRdrPass *CLandscape::getTileRenderPass(uint16 tileId, bool additiveRdrPass)
01763 {
01764 CTileInfo *tile= TileInfos[tileId];
01765
01766
01767
01768 if(tile==NULL)
01769 {
01770
01771 loadTile(tileId);
01772
01773 tile= TileInfos[tileId];
01774 nlassert(tile!=NULL);
01775 }
01776
01777
01778
01779 if(additiveRdrPass)
01780 {
01781
01782 return tile->AdditiveRdrPass;
01783 }
01784 else
01785 {
01786 return tile->DiffuseRdrPass;
01787 }
01788 }
01789
01790
01791
01792 void CLandscape::getTileUvScaleBiasRot(uint16 tileId, CTile::TBitmap bitmapType, CVector &uvScaleBias, uint8 &rotAlpha)
01793 {
01794 CTileInfo *tile= TileInfos[tileId];
01795
01796
01797 nlassert(tile);
01798
01799 rotAlpha= 0;
01800 switch(bitmapType)
01801 {
01802 case CTile::diffuse:
01803 uvScaleBias= tile->DiffuseUvScaleBias; break;
01804 case CTile::additive:
01805 uvScaleBias= tile->AdditiveUvScaleBias; break;
01806 case CTile::alpha:
01807 uvScaleBias= tile->AlphaUvScaleBias;
01808 rotAlpha= tile->RotAlpha;
01809 break;
01810 default: break;
01811 }
01812 }
01813
01814
01815
01816 NLMISC::CSmartPtr<ITexture> CLandscape::getTileTexture(uint16 tileId, CTile::TBitmap bitmapType, CVector &uvScaleBias)
01817 {
01818 CPatchRdrPass *pass;
01819 if(bitmapType== CTile::additive)
01820 pass= getTileRenderPass(tileId, true);
01821 else
01822 pass= getTileRenderPass(tileId, false);
01823 if(!pass)
01824 return NULL;
01825 uint8 dummy;
01826 getTileUvScaleBiasRot(tileId, bitmapType, uvScaleBias, dummy);
01827
01828
01829 if(bitmapType==CTile::diffuse || bitmapType==CTile::additive)
01830 return pass->TextureDiffuse;
01831 else
01832 return pass->TextureAlpha;
01833 }
01834
01835
01836
01837 CTileElement *CLandscape::getTileElement(const CPatchIdent &patchId, const CUV &uv)
01838 {
01839
01840 std::map<uint16, CZone*>::const_iterator it= Zones.find((uint16)patchId.ZoneId);
01841 if(it!=Zones.end())
01842 {
01843 sint N= (*it).second->getNumPatchs();
01844
01845 nlassert(patchId.PatchId<N);
01846 CPatch *pa= const_cast<CZone*>((*it).second)->getPatch(patchId.PatchId);
01847 return pa->getTileElement (uv);
01848 }
01849 else
01850
01851 return NULL;
01852 }
01853
01854
01855
01856 void CLandscape::flushTiles(IDriver *drv, uint16 tileStart, uint16 nbTiles)
01857 {
01858
01859 for(sint tileId= tileStart; tileId<tileStart+nbTiles; tileId++)
01860 {
01861 CTileInfo *tile= TileInfos[tileId];
01862 if(tile==NULL)
01863 {
01864 loadTile(tileId);
01865 }
01866 }
01867
01868
01869 ItTileRdrPassSet it;
01870 for(it= TileRdrPassSet.begin(); it!=TileRdrPassSet.end(); it++)
01871 {
01872 const CPatchRdrPass &pass= *it;
01873
01874 if(pass.TextureDiffuse && !pass.TextureDiffuse->setupedIntoDriver())
01875 drv->setupTexture(*pass.TextureDiffuse);
01876
01877 if(pass.TextureAlpha && !pass.TextureAlpha->setupedIntoDriver())
01878 drv->setupTexture(*pass.TextureAlpha);
01879 }
01880 }
01881
01882
01883
01884 void CLandscape::releaseTiles(uint16 tileStart, uint16 nbTiles)
01885 {
01886
01887 for(sint tileId= tileStart; tileId<tileStart+nbTiles; tileId++)
01888 {
01889 CTileInfo *tile= TileInfos[tileId];
01890 if(tile!=NULL)
01891 {
01892 releaseTile(tileId);
01893 }
01894 }
01895
01896
01897 ItTileRdrPassSet it;
01898 for(it= TileRdrPassSet.begin(); it!=TileRdrPassSet.end();)
01899 {
01900
01901 if((*it).RefCount==0)
01902 {
01903 ItTileRdrPassSet itDel=it++;
01904 TileRdrPassSet.erase(itDel);
01905 }
01906 else
01907 it++;
01908 }
01909
01910
01911
01912
01913 }
01914
01915
01916
01917 uint CLandscape::getTileLightMap(CRGBA map[NL_TILE_LIGHTMAP_SIZE*NL_TILE_LIGHTMAP_SIZE], CPatchRdrPass *&lightmapRdrPass)
01918 {
01919 sint textNum;
01920 uint lightMapId;
01921
01922
01923
01924
01925
01926
01927
01928
01929
01930
01931 if(_NFreeLightMaps==0)
01932 {
01933 CTextureNear *text= new CTextureNear(TextureNearSize);
01934 TSPRenderPass newPass= new CPatchRdrPass;
01935
01936 newPass->TextureDiffuse= text;
01937
01938 _TextureNears.push_back(newPass);
01939 _NFreeLightMaps+= text->getNbAvailableTiles();
01940 }
01941
01942
01943
01944 CTextureNear *nearText= NULL;
01945 CPatchRdrPass *nearRdrPass= NULL;
01946 for(textNum=0;textNum<(sint)_TextureNears.size();textNum++)
01947 {
01948 nearRdrPass= _TextureNears[textNum];
01949 nearText= (CTextureNear*)(ITexture*)nearRdrPass->TextureDiffuse;
01950 if(nearText->getNbAvailableTiles()!=0)
01951 break;
01952 }
01953 nlassert(textNum<(sint)_TextureNears.size());
01954
01955 _NFreeLightMaps--;
01956
01957
01958
01959 lightMapId= nearText->getTileAndFillRect(map);
01960
01961 lightMapId= textNum*NbTileLightMapByTexture + lightMapId;
01962
01963
01964
01965
01966
01967 _ULTotalNearPixels+= NL_TILE_LIGHTMAP_SIZE*NL_TILE_LIGHTMAP_SIZE;
01968
01969
01970
01971 lightmapRdrPass= nearRdrPass;
01972 return lightMapId;
01973 }
01974
01975 void CLandscape::getTileLightMapUvInfo(uint tileLightMapId, CVector &uvScaleBias)
01976 {
01977 uint id, s,t;
01978
01979
01980 static const float scale10= (float)NL_TILE_LIGHTMAP_SIZE/TextureNearSize;
01981 static const float scale4= 4.f/TextureNearSize;
01982 static const float scale1= 1.f/TextureNearSize;
01983
01984 uvScaleBias.z= scale4;
01985
01986
01987 id= tileLightMapId%NbTileLightMapByTexture;
01988
01989
01990
01991 s= id%NbTileLightMapByLine;
01992 t= id/NbTileLightMapByLine;
01993
01994 uvScaleBias.x= s*scale10 + scale1;
01995 uvScaleBias.y= t*scale10 + scale1;
01996 }
01997
01998 void CLandscape::releaseTileLightMap(uint tileLightMapId)
01999 {
02000 uint id, textNum;
02001
02002
02003 textNum= tileLightMapId / NbTileLightMapByTexture;
02004 id= tileLightMapId % NbTileLightMapByTexture;
02005 nlassert(textNum>=0 && textNum<_TextureNears.size());
02006
02007
02008 CPatchRdrPass *nearRdrPass= _TextureNears[textNum];
02009 CTextureNear *nearText= (CTextureNear*)(ITexture*)nearRdrPass->TextureDiffuse;
02010 nearText->releaseTile(id);
02011 _NFreeLightMaps++;
02012
02013
02014
02015 _ULTotalNearPixels-= NL_TILE_LIGHTMAP_SIZE*NL_TILE_LIGHTMAP_SIZE;
02016 }
02017
02018
02019
02020 void CLandscape::refillTileLightMap(uint tileLightMapId, CRGBA map[NL_TILE_LIGHTMAP_SIZE*NL_TILE_LIGHTMAP_SIZE])
02021 {
02022 uint id, textNum;
02023
02024
02025 textNum= tileLightMapId / NbTileLightMapByTexture;
02026 id= tileLightMapId % NbTileLightMapByTexture;
02027 nlassert(textNum>=0 && textNum<_TextureNears.size());
02028
02029
02030 CPatchRdrPass *nearRdrPass= _TextureNears[textNum];
02031 CTextureNear *nearText= (CTextureNear*)(ITexture*)nearRdrPass->TextureDiffuse;
02032
02033
02034 nearText->refillRect(id, map);
02035 }
02036
02037
02038
02039
02040
02041
02042
02043
02044
02045
02046
02047 CPatchRdrPass* CLandscape::getFarRenderPass(CPatch* pPatch, uint farIndex, float& farUScale, float& farVScale, float& farUBias, float& farVBias, bool& bRot)
02048 {
02049
02050 nlassert (farIndex>0);
02051
02052
02053 uint width=(pPatch->getOrderS ()*NL_NUM_PIXELS_ON_FAR_TILE_EDGE)>>(farIndex-1);
02054 uint height=(pPatch->getOrderT ()*NL_NUM_PIXELS_ON_FAR_TILE_EDGE)>>(farIndex-1);
02055
02056
02057 _ULTotalFarPixels+= width*height;
02058
02059
02060 uint passIndex=getRdrPassIndexWithSize (width, height);
02061
02062
02063 if (_FarRdrPassSetVectorFree[passIndex].begin()==_FarRdrPassSetVectorFree[passIndex].end())
02064 {
02065
02066 CPatchRdrPass *pass=new CPatchRdrPass;
02067
02068
02069 CTextureFar *pTextureFar=new CTextureFar;
02070
02071
02072 if(_ULRootTextureFar==NULL)
02073 _ULRootTextureFar= pTextureFar;
02074 else
02075 pTextureFar->linkBeforeUL(_ULRootTextureFar);
02076
02077
02078 pTextureFar->_Bank=&TileFarBank;
02079
02080
02081 pass->TextureDiffuse=pTextureFar;
02082
02083
02084 pTextureFar->setSizeOfFarPatch (std::max (width, height), std::min (width, height));
02085
02086
02087 _FarRdrPassSetVectorFree[passIndex].insert (pass);
02088 _FarRdrPassSet.insert (pass);
02089 }
02090
02091
02092 TSPRenderPass pass=*_FarRdrPassSetVectorFree[passIndex].begin();
02093
02094
02095 CTextureFar *pTextureFar=(CTextureFar*)(&*(pass->TextureDiffuse));
02096
02097
02098 if (pTextureFar->addPatch (pPatch, farUScale, farVScale, farUBias, farVBias, bRot))
02099 {
02100
02101 _FarRdrPassSetVectorFree[passIndex].erase (pass);
02102 }
02103
02104
02105 return pass;
02106 }
02107
02108
02109
02110 void CLandscape::freeFarRenderPass (CPatch* pPatch, CPatchRdrPass* pass, uint farIndex)
02111 {
02112
02113 uint width=(pPatch->getOrderS ()*NL_NUM_PIXELS_ON_FAR_TILE_EDGE)>>(farIndex-1);
02114 uint height=(pPatch->getOrderT ()*NL_NUM_PIXELS_ON_FAR_TILE_EDGE)>>(farIndex-1);
02115
02116
02117 _ULTotalFarPixels-= width*height;
02118 nlassert(_ULTotalFarPixels>=0);
02119
02120
02121 uint passIndex=getRdrPassIndexWithSize (width, height);
02122
02123
02124 CTextureFar *pTextureFar=(CTextureFar*)(&*(pass->TextureDiffuse));
02125
02126
02127 if (pTextureFar->removePatch (pPatch))
02128 {
02129
02130 if (_FarRdrPassSetVectorFree[passIndex].begin()==_FarRdrPassSetVectorFree[passIndex].end())
02131 {
02132
02133 _FarRdrPassSetVectorFree[passIndex].insert (pass);
02134 }
02135 else
02136 {
02137
02138 _FarRdrPassSetVectorFree[passIndex].erase (pass);
02139
02140
02141 eraseFarRenderPassFromSet (pass);
02142 }
02143 }
02144 else
02145 {
02146
02147 _FarRdrPassSetVectorFree[passIndex].insert (pass);
02148 }
02149 }
02150
02151
02152
02153 void CLandscape::eraseFarRenderPassFromSet (CPatchRdrPass* pass)
02154 {
02155
02156
02157
02158 CTextureFar *pTextureFar=(CTextureFar*)(&*(pass->TextureDiffuse));
02159
02160
02161 if(_ULRootTextureFar==pTextureFar)
02162 {
02163
02164 _ULRootTextureFar= pTextureFar->getNextUL();
02165
02166 if(_ULRootTextureFar==pTextureFar)
02167 _ULRootTextureFar= NULL;
02168
02169 _ULFarCurrentPatchId= 0;
02170 }
02171
02172
02173 pTextureFar->unlinkUL();
02174
02175
02176
02177 _FarRdrPassSet.erase (pass);
02178 }
02179
02180
02181
02182
02183
02184
02185
02186
02187
02188
02189 CZone* CLandscape::getZone (sint zoneId)
02190 {
02191 TZoneMap::iterator it;
02192 it= Zones.find(zoneId);
02193 if (it!=Zones.end())
02194 return (*it).second;
02195 else
02196 return NULL;
02197 }
02198
02199
02200
02201 const CZone* CLandscape::getZone (sint zoneId) const
02202 {
02203 TZoneMap::const_iterator it;
02204
02205 it= Zones.find(zoneId);
02206 if (it!=Zones.end())
02207 return (*it).second;
02208 else
02209 return NULL;
02210 }
02211
02212
02213
02214
02215 void CLandscape::checkZoneBinds(CZone &curZone, EBadBind &bindError)
02216 {
02217 for(sint i=0;i<curZone.getNumPatchs();i++)
02218 {
02219 const CZone::CPatchConnect &pa= *curZone.getPatchConnect(i);
02220
02221
02222 for(sint j=0;j<4;j++)
02223 {
02224 const CPatchInfo::CBindInfo &bd=pa.BindEdges[j];
02225
02226 if(bd.NPatchs==1)
02227 {
02228 CZone *oZone= getZone(bd.ZoneId);
02229
02230 if(oZone)
02231 {
02232 const CZone::CPatchConnect &po= *(oZone->getPatchConnect(bd.Next[0]));
02233 const CPatchInfo::CBindInfo &bo= po.BindEdges[bd.Edge[0]];
02234 if(bo.NPatchs!=1 || bo.Next[0]!=i || bo.Edge[0]!=j)
02235 bindError.BindErrors.push_back( EBadBind::CBindError(curZone.getZoneId(), i));
02236 }
02237 }
02238 }
02239 }
02240 }
02241
02242
02243
02244 void CLandscape::checkBinds() throw(EBadBind)
02245 {
02246 EBadBind bindError;
02247
02248 for(ItZoneMap it= Zones.begin();it!=Zones.end();it++)
02249 {
02250 CZone &curZone= *(*it).second;
02251 checkZoneBinds(curZone, bindError);
02252 }
02253
02254 if(!bindError.BindErrors.empty())
02255 throw bindError;
02256 }
02257
02258
02259
02260 void CLandscape::checkBinds(uint16 zoneId) throw(EBadBind)
02261 {
02262 EBadBind bindError;
02263
02264 ItZoneMap it= Zones.find(zoneId);
02265 if(it!= Zones.end())
02266 {
02267 CZone &curZone= *(*it).second;
02268 checkZoneBinds(curZone, bindError);
02269 if(!bindError.BindErrors.empty())
02270 throw bindError;
02271 }
02272 }
02273
02274
02275
02276
02277 void CLandscape::addTrianglesInBBox(const CPatchIdentEx &paIdEx, const CAABBox &bbox, std::vector<CTrianglePatch> &triangles, uint8 tileTessLevel) const
02278 {
02279
02280 const CPatch *pa= paIdEx.Patch;
02281
02282 CPatchIdent paId;
02283 paId.ZoneId= paIdEx.ZoneId;
02284 paId.PatchId= paIdEx.PatchId;
02285 pa->addTrianglesInBBox(paId, bbox, triangles, tileTessLevel);
02286 }
02287
02288
02289
02290 void CLandscape::buildTrianglesInBBox(const CAABBox &bbox, std::vector<CTrianglePatch> &triangles, uint8 tileTessLevel)
02291 {
02292
02293 triangles.clear();
02294
02295
02296 _PatchQuadGrid.clearSelection();
02297 _PatchQuadGrid.select(bbox.getMin(), bbox.getMax());
02298 CQuadGrid<CPatchIdentEx>::CIterator it;
02299
02300
02301 for(it= _PatchQuadGrid.begin(); it!= _PatchQuadGrid.end(); it++)
02302 {
02303 addTrianglesInBBox((*it), bbox, triangles, tileTessLevel);
02304 }
02305 }
02306
02307
02308
02309
02310 void CLandscape::addPatchBlocksInBBox(const CPatchIdentEx &paIdEx, const CAABBox &bbox, std::vector<CPatchBlockIdent> &paBlockIds)
02311 {
02312
02313 const CPatch *pa= paIdEx.Patch;
02314
02315 CPatchIdent paId;
02316 paId.ZoneId= paIdEx.ZoneId;
02317 paId.PatchId= paIdEx.PatchId;
02318 pa->addPatchBlocksInBBox(paId, bbox, paBlockIds);
02319 }
02320
02321
02322
02323 void CLandscape::buildPatchBlocksInBBox(const CAABBox &bbox, std::vector<CPatchBlockIdent> &paBlockIds)
02324 {
02325
02326 paBlockIds.clear();
02327
02328
02329 _PatchQuadGrid.clearSelection();
02330 _PatchQuadGrid.select(bbox.getMin(), bbox.getMax());
02331 CQuadGrid<CPatchIdentEx>::CIterator it;
02332
02333
02334 for(it= _PatchQuadGrid.begin(); it!= _PatchQuadGrid.end(); it++)
02335 {
02336 addPatchBlocksInBBox((*it), bbox, paBlockIds);
02337 }
02338 }
02339
02340
02341
02342 void CLandscape::fillPatchQuadBlock(CPatchQuadBlock &quadBlock) const
02343 {
02344 sint zoneId= quadBlock.PatchBlockId.PatchId.ZoneId;
02345 sint patchId= quadBlock.PatchBlockId.PatchId.PatchId;
02346 std::map<uint16, CZone*>::const_iterator it= Zones.find(zoneId);
02347 if(it!=Zones.end())
02348 {
02349 sint N= (*it).second->getNumPatchs();
02350
02351 nlassert(patchId>=0);
02352 nlassert(patchId<N);
02353
02354 const CPatch *pa= const_cast<const CZone*>((*it).second)->getPatch(patchId);
02355 pa->fillPatchQuadBlock(quadBlock);
02356 }
02357 }
02358
02359
02360
02361
02362
02363 void CLandscape::buildCollideFaces(const CAABBoxExt &bbox, vector<CTriangle> &faces, bool faceClip)
02364 {
02365 CBSphere bsWanted(bbox.getCenter(), bbox.getRadius());
02366
02367 faces.clear();
02368
02369 for(ItZoneMap it= Zones.begin();it!=Zones.end();it++)
02370 {
02371 const CAABBoxExt &bb= (*it).second->getZoneBB();
02372 CBSphere bs(bb.getCenter(), bb.getRadius());
02373
02374
02375 if(bs.intersect(bsWanted))
02376 {
02377
02378 sint N= (*it).second->getNumPatchs();
02379 for(sint i=0;i<N;i++)
02380 {
02381 const CPatch *pa= const_cast<const CZone*>((*it).second)->getPatch(i);
02382
02383
02384
02385 if(bsWanted.intersect(pa->getBSphere()))
02386 {
02387
02388
02389 sint ordS= pa->getOrderS();
02390 sint ordT= pa->getOrderT();
02391 sint x,y,j;
02392 vector<CTriangle> tmpFaces;
02393 tmpFaces.reserve(ordS*ordT);
02394 float OOS= 1.0f/ordS;
02395 float OOT= 1.0f/ordT;
02396 for(y=0;y<ordT;y++)
02397 {
02398 for(x=0;x<ordS;x++)
02399 {
02400 CTriangle f;
02401 f.V0= pa->computeVertex(x*OOS, y*OOT);
02402 f.V1= pa->computeVertex(x*OOS, (y+1)*OOT);
02403 f.V2= pa->computeVertex((x+1)*OOS, (y+1)*OOT);
02404 tmpFaces.push_back(f);
02405 f.V0= pa->computeVertex(x*OOS, y*OOT);
02406 f.V1= pa->computeVertex((x+1)*OOS, (y+1)*OOT);
02407 f.V2= pa->computeVertex((x+1)*OOS, y*OOT);
02408 tmpFaces.push_back(f);
02409 }
02410 }
02411
02412
02413
02414 if(faceClip)
02415 {
02416
02417 for(j=0;j<(sint)tmpFaces.size();j++)
02418 {
02419 CTriangle &f= tmpFaces[j];
02420 if(bbox.intersect(f.V0, f.V1, f.V2))
02421 {
02422 faces.push_back(f);
02423 }
02424 }
02425 }
02426 else
02427 {
02428
02429 faces.insert(faces.end(), tmpFaces.begin(), tmpFaces.end());
02430 }
02431 }
02432 }
02433 }
02434 }
02435 }
02436
02437
02438
02439 void CLandscape::buildCollideFaces(sint zoneId, sint patch, std::vector<CTriangle> &faces)
02440 {
02441 faces.clear();
02442
02443 ItZoneMap it= Zones.find(zoneId);
02444 if(it!=Zones.end())
02445 {
02446
02447 sint N= (*it).second->getNumPatchs();
02448 nlassert(patch>=0);
02449 nlassert(patch<N);
02450 const CPatch *pa= const_cast<const CZone*>((*it).second)->getPatch(patch);
02451
02452
02453
02454 sint ordS= pa->getOrderS();
02455 sint ordT= pa->getOrderT();
02456 sint x,y;
02457 float OOS= 1.0f/ordS;
02458 float OOT= 1.0f/ordT;
02459 for(y=0;y<ordT;y++)
02460 {
02461 for(x=0;x<ordS;x++)
02462 {
02463 CTriangle f;
02464 f.V0= pa->computeVertex(x*OOS, y*OOT);
02465 f.V1= pa->computeVertex(x*OOS, (y+1)*OOT);
02466 f.V2= pa->computeVertex((x+1)*OOS, (y+1)*OOT);
02467 faces.push_back(f);
02468 f.V0= pa->computeVertex(x*OOS, y*OOT);
02469 f.V1= pa->computeVertex((x+1)*OOS, (y+1)*OOT);
02470 f.V2= pa->computeVertex((x+1)*OOS, y*OOT);
02471 faces.push_back(f);
02472 }
02473 }
02474 }
02475 }
02476
02477
02478
02479 CVector CLandscape::getTesselatedPos(const CPatchIdent &patchId, const CUV &uv) const
02480 {
02481
02482
02483
02484 CLandscapeGlobals::VertexProgramEnabled= _VertexShaderOk;
02485
02486
02487 if( CLandscapeGlobals::VertexProgramEnabled )
02488 {
02489
02490
02491
02492
02493
02494
02495
02496
02497 CLandscapeGlobals::TileDistNear = _TileDistNear;
02498 CLandscapeGlobals::TileDistFar = CLandscapeGlobals::TileDistNear+20;
02499 CLandscapeGlobals::TileDistNearSqr = sqr(CLandscapeGlobals::TileDistNear);
02500 CLandscapeGlobals::TileDistFarSqr = sqr(CLandscapeGlobals::TileDistFar);
02501 CLandscapeGlobals::OOTileDistDeltaSqr = 1.0f / (CLandscapeGlobals::TileDistFarSqr - CLandscapeGlobals::TileDistNearSqr);
02502
02503
02504 CLandscapeGlobals::RefineThreshold= _Threshold;
02505 CLandscapeGlobals::OORefineThreshold= 1.0f / CLandscapeGlobals::RefineThreshold;
02506
02507
02508
02509 CLandscapeGlobals::RefineCenter= _OldRefineCenter;
02510 }
02511
02512
02513
02514 std::map<uint16, CZone*>::const_iterator it= Zones.find((uint16)patchId.ZoneId);
02515 if(it!=Zones.end())
02516 {
02517 sint N= (*it).second->getNumPatchs();
02518
02519 nlassert(patchId.PatchId<N);
02520 const CPatch *pa= const_cast<const CZone*>((*it).second)->getPatch(patchId.PatchId);
02521
02522 return pa->getTesselatedPos(uv);
02523 }
02524 else
02525 return CVector::Null;
02526 }
02527
02528
02529
02530 uint CLandscape::getRdrPassIndexWithSize (uint width, uint height)
02531 {
02532
02533 nlassert (width);
02534 nlassert (height);
02535
02536
02537 int orderWidth=0;
02538 while (!(width&(1<<orderWidth)))
02539 orderWidth++;
02540
02541
02542 int orderHeight=0;
02543 while (!(height&(1<<orderHeight)))
02544 orderHeight++;
02545
02546 if (orderWidth>orderHeight)
02547 {
02548 return NL_MAX_SIZE_OF_TEXTURE_EDGE_SHIFT*orderHeight+orderWidth;
02549 }
02550 else
02551 {
02552 return NL_MAX_SIZE_OF_TEXTURE_EDGE_SHIFT*orderWidth+orderHeight;
02553 }
02554 }
02555
02556 #define NL_TILE_FAR_SIZE_ORDER0 (NL_NUM_PIXELS_ON_FAR_TILE_EDGE*NL_NUM_PIXELS_ON_FAR_TILE_EDGE)
02557 #define NL_TILE_FAR_SIZE_ORDER1 ((NL_NUM_PIXELS_ON_FAR_TILE_EDGE>>1)*(NL_NUM_PIXELS_ON_FAR_TILE_EDGE>>1))
02558 #define NL_TILE_FAR_SIZE_ORDER2 ((NL_NUM_PIXELS_ON_FAR_TILE_EDGE>>2)*(NL_NUM_PIXELS_ON_FAR_TILE_EDGE>>2))
02559
02560
02561
02562 bool CLandscape::eraseTileFarIfNotGood (uint tileNumber, uint sizeOrder0, uint sizeOrder1, uint sizeOrder2)
02563 {
02564
02565 bool bSame=true;
02566
02567
02568 if (TileFarBank.getTile (tileNumber)->isFill (CTileFarBank::diffuse))
02569 {
02570
02571 if (
02572 (TileFarBank.getTile (tileNumber)->getSize (CTileFarBank::diffuse, CTileFarBank::order0) != sizeOrder0) ||
02573 (TileFarBank.getTile (tileNumber)->getSize (CTileFarBank::diffuse, CTileFarBank::order1) != sizeOrder1) ||
02574 (TileFarBank.getTile (tileNumber)->getSize (CTileFarBank::diffuse, CTileFarBank::order2) != sizeOrder2)
02575 )
02576 {
02577 TileFarBank.getTile (tileNumber)->erasePixels (CTileFarBank::diffuse);
02578 bSame=false;
02579 }
02580 }
02581
02582
02583 if (TileFarBank.getTile (tileNumber)->isFill (CTileFarBank::additive))
02584 {
02585
02586 if (
02587 (TileFarBank.getTile (tileNumber)->getSize (CTileFarBank::additive, CTileFarBank::order0) != sizeOrder0) ||
02588 (TileFarBank.getTile (tileNumber)->getSize (CTileFarBank::additive, CTileFarBank::order1) != sizeOrder1) ||
02589 (TileFarBank.getTile (tileNumber)->getSize (CTileFarBank::additive, CTileFarBank::order2) != sizeOrder2)
02590 )
02591 {
02592 TileFarBank.getTile (tileNumber)->erasePixels (CTileFarBank::additive);
02593 bSame=false;
02594 }
02595 }
02596
02597
02598 return bSame;
02599 }
02600
02601
02602 bool CLandscape::initTileBanks ()
02603 {
02604
02605 _FarInitialized=false;
02606
02607
02608 bool bCompatibility=true;
02609
02610
02611 if (TileBank.getTileCount()==TileFarBank.getNumTile())
02612 {
02613
02614 for (int tileSet=0; tileSet<TileBank.getTileSetCount(); tileSet++)
02615 {
02616
02617 int tile;
02618 for (tile=0; tile<TileBank.getTileSet(tileSet)->getNumTile128(); tile++)
02619 {
02620
02621 uint tileNumber=TileBank.getTileSet(tileSet)->getTile128(tile);
02622
02623
02624 bCompatibility&=eraseTileFarIfNotGood (tileNumber, NL_TILE_FAR_SIZE_ORDER0, NL_TILE_FAR_SIZE_ORDER1, NL_TILE_FAR_SIZE_ORDER2);
02625 }
02626
02627
02628 for (tile=0; tile<TileBank.getTileSet(tileSet)->getNumTile256(); tile++)
02629 {
02630
02631 uint tileNumber=TileBank.getTileSet(tileSet)->getTile256(tile);
02632
02633
02634 bCompatibility&=eraseTileFarIfNotGood (tileNumber, NL_TILE_FAR_SIZE_ORDER0<<2, NL_TILE_FAR_SIZE_ORDER1<<2, NL_TILE_FAR_SIZE_ORDER2<<2);
02635 }
02636
02637
02638 for (tile=0; tile<CTileSet::count; tile++)
02639 {
02640
02641 uint tileNumber=TileBank.getTileSet(tileSet)->getTransition(tile)->getTile();
02642
02643
02644 bCompatibility&=eraseTileFarIfNotGood (tileNumber, NL_TILE_FAR_SIZE_ORDER0, NL_TILE_FAR_SIZE_ORDER1, NL_TILE_FAR_SIZE_ORDER2);
02645 }
02646 }
02647
02648
02649 _FarInitialized=true;
02650 }
02651
02652
02653 TileBank.initTileVegetableDescs(_VegetableManager);
02654
02655 return bCompatibility;
02656 }
02657
02658
02659
02660 void CLandscape::setupStaticLight (const CRGBA &diffuse, const CRGBA &ambiant, float multiply)
02661 {
02662 sint nMultiply=(sint)(256.f*multiply);
02663 for (int i=0; i<256; i++)
02664 {
02665 sint max=0;
02666 sint r=(((nMultiply*diffuse.R*i)>>8)+ambiant.R*(256-i))>>8;
02667 if (r>max)
02668 max=r;
02669 sint g=(((nMultiply*diffuse.G*i)>>8)+ambiant.G*(256-i))>>8;
02670 if (g>max)
02671 max=g;
02672 sint b=(((nMultiply*diffuse.B*i)>>8)+ambiant.B*(256-i))>>8;
02673 if (b>max)
02674 max=b;
02675 r<<=8;
02676 g<<=8;
02677 b<<=8;
02678 max=std::max(max, 256);
02679 r/=max;
02680 g/=max;
02681 b/=max;
02682 clamp (r, 0, 255);
02683 clamp (g, 0, 255);
02684 clamp (b, 0, 255);
02685 _LightValue[i].R=r;
02686 _LightValue[i].G=g;
02687 _LightValue[i].B=b;
02688 _LightValue[i].A=255;
02689 }
02690 }
02691
02692
02693 void CLandscape::enableAutomaticLighting(bool enable)
02694 {
02695 _AutomaticLighting= enable;
02696 }
02697
02698
02699 void CLandscape::setupAutomaticLightDir(const CVector &lightDir)
02700 {
02701 _AutomaticLightDir= lightDir;
02702 _AutomaticLightDir.normalize();
02703 }
02704
02705
02706
02707 CVector CLandscape::getHeightFieldDeltaZ(float x, float y) const
02708 {
02709 if(_HeightField.ZPatchs.size()==0)
02710 return CVector::Null;
02711
02712
02713 x-= _HeightField.OriginX;
02714 y-= _HeightField.OriginY;
02715 x*= _HeightField.OOSizeX;
02716 y*= _HeightField.OOSizeY;
02717
02718 sint ix, iy;
02719 ix= (sint)floor(x);
02720 iy= (sint)floor(y);
02721
02722 if( ix<0 || ix>=(sint)_HeightField.Width || iy<0 || iy>=(sint)_HeightField.Height)
02723 return CVector::Null;
02724
02725
02726 const CBezierPatchZ &paz= _HeightField.ZPatchs[iy*_HeightField.Width + ix];
02727
02728
02729 CVector ret=CVector::Null;
02730 ret.x= 0;
02731 ret.y= 0;
02732 ret.z= paz.eval(x-ix, y-iy);
02733
02734 return ret;
02735 }
02736
02737
02738
02739
02740 void CLandscape::CBezierPatchZ::makeInteriors()
02741 {
02742 float &a = Vertices[0];
02743 float &b = Vertices[1];
02744 float &c = Vertices[2];
02745 float &d = Vertices[3];
02746 Interiors[0] = Tangents[7] + Tangents[0] - a;
02747 Interiors[1] = Tangents[1] + Tangents[2] - b;
02748 Interiors[2] = Tangents[3] + Tangents[4] - c;
02749 Interiors[3] = Tangents[5] + Tangents[6] - d;
02750 }
02751
02752 float CLandscape::CBezierPatchZ::eval(float ps, float pt) const
02753 {
02754 float p;
02755
02756 float ps2 = ps * ps;
02757 float ps1 = 1.0f - ps;
02758 float ps12 = ps1 * ps1;
02759 float s0 = ps12 * ps1;
02760 float s1 = 3.0f * ps * ps12;
02761 float s2 = 3.0f * ps2 * ps1;
02762 float s3 = ps2 * ps;
02763 float pt2 = pt * pt;
02764 float pt1 = 1.0f - pt;
02765 float pt12 = pt1 * pt1;
02766 float t0 = pt12 * pt1;
02767 float t1 = 3.0f * pt * pt12;
02768 float t2 = 3.0f * pt2 * pt1;
02769 float t3 = pt2 * pt;
02770
02771 p = Vertices[0] * s0 * t0 +
02772 Tangents[7] * s1 * t0 +
02773 Tangents[6] * s2 * t0 +
02774 Vertices[3] * s3 * t0;
02775 p+= Tangents[0] * s0 * t1 +
02776 Interiors[0]* s1 * t1 +
02777 Interiors[3]* s2 * t1 +
02778 Tangents[5] * s3 * t1;
02779 p+= Tangents[1] * s0 * t2 +
02780 Interiors[1]* s1 * t2 +
02781 Interiors[2]* s2 * t2 +
02782 Tangents[4] * s3 * t2;
02783 p+= Vertices[1] * s0 * t3 +
02784 Tangents[2] * s1 * t3 +
02785 Tangents[3] * s2 * t3 +
02786 Vertices[2] * s3 * t3;
02787
02788 return p;
02789 }
02790
02791
02792
02793 void CLandscape::setHeightField(const CHeightMap &hf)
02794 {
02795 if(hf.getWidth()<2)
02796 return;
02797 if(hf.getHeight()<2)
02798 return;
02799
02800
02801 _HeightField.OriginX= hf.OriginX;
02802 _HeightField.OriginY= hf.OriginY;
02803 _HeightField.SizeX= hf.SizeX;
02804 _HeightField.SizeY= hf.SizeY;
02805 _HeightField.OOSizeX= 1/hf.SizeX;
02806 _HeightField.OOSizeY= 1/hf.SizeY;
02807 uint w= hf.getWidth()-1;
02808 uint h= hf.getHeight()-1;
02809 _HeightField.Width= w;
02810 _HeightField.Height= h;
02811 _HeightField.ZPatchs.resize(w * h);
02812
02813
02814 sint x,y;
02815
02816
02817 for(y=0;y<(sint)h;y++)
02818 {
02819 for(x=0;x<(sint)w;x++)
02820 {
02821 CBezierPatchZ &paz= _HeightField.ZPatchs[y*w+x];
02822
02823 paz.Vertices[0]= hf.getZ(x, y);
02824 paz.Vertices[1]= hf.getZ(x, y+1);
02825 paz.Vertices[2]= hf.getZ(x+1, y+1);
02826 paz.Vertices[3]= hf.getZ(x+1, y);
02827 }
02828 }
02829
02830
02831 for(y=0;y<(sint)h;y++)
02832 {
02833 for(x=0;x<(sint)w;x++)
02834 {
02835 CBezierPatchZ &paz= _HeightField.ZPatchs[y*w+x];
02836 sint tg;
02837
02838 struct CDeltaPos
02839 {
02840 sint ox,oy;
02841 sint dx1,dy1;
02842 sint dx2,dy2;
02843 };
02844 static CDeltaPos deltas[8]= {
02845 {0,0, 0,1, 0,-1} ,
02846 {0,1, 0,0, 0,2} ,
02847 {0,1, 1,1, -1,1} ,
02848 {1,1, 0,1, 2,1} ,
02849 {1,1, 1,0, 1,2} ,
02850 {1,0, 1,1, 1,-1} ,
02851 {1,0, 0,0, 2,0} ,
02852 {0,0, 1,0, -1,0} ,
02853 };
02854
02855
02856 for(tg=0; tg<8;tg++)
02857 {
02858 sint x0,y0;
02859 sint x1,y1;
02860 sint x2,y2;
02861 x0= x+deltas[tg].ox; y0= y+deltas[tg].oy;
02862 x1= x+deltas[tg].dx1; y1= y+deltas[tg].dy1;
02863 x2= x+deltas[tg].dx2; y2= y+deltas[tg].dy2;
02864
02865
02866 if(x2<0 || x2>=(sint)hf.getWidth() || y2<0 || y2>=(sint)hf.getHeight())
02867 {
02868 float v,dv;
02869
02870 v= hf.getZ(x0,y0);
02871
02872 dv= hf.getZ(x1,y1) - v;
02873
02874 paz.Tangents[tg]= v+dv/3;
02875 }
02876
02877 else
02878 {
02879 float v,dv;
02880
02881 v= hf.getZ(x0,y0);
02882
02883 dv= hf.getZ(x1,y1) - v;
02884
02885 dv+= -(hf.getZ(x2,y2) - v);
02886 dv/=2;
02887
02888 paz.Tangents[tg]= v+dv/3;
02889 }
02890 }
02891 }
02892 }
02893
02894
02895 for(y=0;y<(sint)h;y++)
02896 {
02897 for(x=0;x<(sint)w;x++)
02898 {
02899 CBezierPatchZ &paz= _HeightField.ZPatchs[y*w+x];
02900 paz.makeInteriors();
02901 }
02902 }
02903
02904 }
02905
02906
02907
02908 void CLandscape::getTessellationLeaves(std::vector<const CTessFace*> &leaves) const
02909 {
02910 leaves.clear();
02911
02912 std::map<uint16, CZone*>::const_iterator it;
02913 for(it= Zones.begin();it!=Zones.end();it++)
02914 {
02915
02916 sint N= (*it).second->getNumPatchs();
02917 for(sint i=0;i<N;i++)
02918 {
02919 const CPatch *pa= const_cast<const CZone*>((*it).second)->getPatch(i);
02920
02921 pa->appendTessellationLeaves(leaves);
02922 }
02923 }
02924
02925 }
02926
02927
02928
02929 void CLandscape::setPZBModelPosition(const CVector &pos)
02930 {
02931 _PZBModelPosition= pos;
02932 }
02933
02934
02935
02936
02937
02938
02939
02940
02941
02942
02943
02944 CTessFace *CLandscape::newTessFace()
02945 {
02946
02947 CTessFace *face= TessFaceAllocator.allocate();
02948
02949
02950 face->linkInPList(_RootNewLeaves);
02951
02952 return face;
02953 }
02954
02955
02956 CTessVertex *CLandscape::newTessVertex()
02957 {
02958 return TessVertexAllocator.allocate();
02959 }
02960
02961
02962 CTessNearVertex *CLandscape::newTessNearVertex()
02963 {
02964 return TessNearVertexAllocator.allocate();
02965 }
02966
02967
02968 CTessFarVertex *CLandscape::newTessFarVertex()
02969 {
02970 return TessFarVertexAllocator.allocate();
02971 }
02972
02973
02974 CTileMaterial *CLandscape::newTileMaterial()
02975 {
02976 return TileMaterialAllocator.allocate();
02977 }
02978
02979
02980 CTileFace *CLandscape::newTileFace()
02981 {
02982 return TileFaceAllocator.allocate();
02983 }
02984
02985
02986 void CLandscape::deleteTessFace(CTessFace *f)
02987 {
02988
02989 f->unlinkInPList();
02990
02991 TessFaceAllocator.free(f);
02992 }
02993
02994
02995 void CLandscape::deleteTessVertex(CTessVertex *v)
02996 {
02997 TessVertexAllocator.free(v);
02998 }
02999
03000
03001 void CLandscape::deleteTessNearVertex(CTessNearVertex *v)
03002 {
03003 TessNearVertexAllocator.free(v);
03004 }
03005
03006
03007 void CLandscape::deleteTessFarVertex(CTessFarVertex *v)
03008 {
03009 TessFarVertexAllocator.free(v);
03010 }
03011
03012
03013 void CLandscape::deleteTileMaterial(CTileMaterial *tm)
03014 {
03015 TileMaterialAllocator.free(tm);
03016 }
03017
03018
03019 void CLandscape::deleteTileFace(CTileFace *tf)
03020 {
03021 TileFaceAllocator.free(tf);
03022 }
03023
03024
03025
03026
03027
03028
03029
03030
03031
03032
03033
03034 void CLandscape::setNoiseMode(bool enable)
03035 {
03036 _NoiseEnabled= enable;
03037 }
03038
03039
03040 bool CLandscape::getNoiseMode() const
03041 {
03042 return _NoiseEnabled;
03043 }
03044
03045
03046
03047
03048
03049
03050
03051
03052
03053
03054 void CLandscape::enableVegetable(bool enable)
03055 {
03056 _VegetableManagerEnabled= enable;
03057
03058
03059 if(!_VegetableManagerEnabled)
03060 {
03061
03062
03063 for(ItZoneMap it= Zones.begin();it!=Zones.end();it++)
03064 {
03065
03066 sint N= (*it).second->getNumPatchs();
03067 for(sint i=0;i<N;i++)
03068 {
03069
03070 CPatch *pa= ((*it).second)->getPatch(i);
03071 pa->deleteAllVegetableIgs();
03072 }
03073
03074 }
03075 }
03076
03077 else
03078 {
03079
03080 TileBank.initTileVegetableDescs(_VegetableManager);
03081
03082
03083
03084
03085 for(ItZoneMap it= Zones.begin();it!=Zones.end();it++)
03086 {
03087
03088 sint N= (*it).second->getNumPatchs();
03089 for(sint i=0;i<N;i++)
03090 {
03091
03092 CPatch *pa= ((*it).second)->getPatch(i);
03093 pa->recreateAllVegetableIgs();
03094 }
03095
03096 }
03097 }
03098
03099 }
03100
03101
03102 bool CLandscape::isVegetableActive() const
03103 {
03104 return _VegetableManagerEnabled && _DriverOkForVegetable;
03105 }
03106
03107
03108 void CLandscape::loadVegetableTexture(const string &textureFileName)
03109 {
03110
03111 _VegetableManager->loadTexture(textureFileName);
03112 }
03113
03114
03115 void CLandscape::setupVegetableLighting(const CRGBA &ambient, const CRGBA &diffuse, const CVector &directionalLight)
03116 {
03117
03118 _VegetableManager->setDirectionalLight(ambient, diffuse, directionalLight);
03119 }
03120
03121
03122 void CLandscape::setVegetableWind(const CVector &windDir, float windFreq, float windPower, float windBendMin)
03123 {
03124
03125 _VegetableManager->setWind(windDir, windFreq, windPower, windBendMin);
03126 }
03127
03128
03129
03130 void CLandscape::setVegetableTime(double time)
03131 {
03132
03133 _VegetableManager->setTime(time);
03134 }
03135
03136
03137 void CLandscape::setVegetableUpdateLightingTime(double time)
03138 {
03139
03140 _VegetableManager->setUpdateLightingTime(time);
03141 }
03142
03143
03144
03145 uint CLandscape::getNumVegetableFaceRendered() const
03146 {
03147 return _VegetableManager->getNumVegetableFaceRendered();
03148 }
03149
03150
03151
03152 const CTileVegetableDesc &CLandscape::getTileVegetableDesc(uint16 tileId)
03153 {
03154 return TileBank.getTileVegetableDesc(tileId);
03155 }
03156
03157
03158
03159 void CLandscape::createVegetableBlendLayersModels(CScene *scene)
03160 {
03161 _VegetableManager->createVegetableBlendLayersModels(scene);
03162 }
03163
03164
03165
03166 void CLandscape::setVegetableUpdateLightingFrequency(float freq)
03167 {
03168 _VegetableManager->setUpdateLightingFrequency(freq);
03169 }
03170
03171
03172 void CLandscape::setupColorsFromTileFlags(const NLMISC::CRGBA colors[4])
03173 {
03174 for (TZoneMap::iterator it = Zones.begin(); it != Zones.end(); ++it)
03175 {
03176 it->second->setupColorsFromTileFlags(colors);
03177 }
03178 }
03179
03180
03181
03182
03183
03184
03185
03186
03187
03188 uint8 CLandscape::getLumel(const CPatchIdent &patchId, const CUV &uv) const
03189 {
03190
03191 std::map<uint16, CZone*>::const_iterator it= Zones.find((uint16)patchId.ZoneId);
03192 if(it!=Zones.end())
03193 {
03194 sint N= (*it).second->getNumPatchs();
03195
03196 nlassert(patchId.PatchId<N);
03197 const CPatch *pa= const_cast<const CZone*>((*it).second)->getPatch(patchId.PatchId);
03198
03199 return pa->getLumel(uv);
03200 }
03201 else
03202
03203 return 255;
03204 }
03205
03206
03207 void CLandscape::appendTileLightInfluences(const CPatchIdent &patchId, const CUV &uv,
03208 std::vector<CPointLightInfluence> &pointLightList) const
03209 {
03210
03211 std::map<uint16, CZone*>::const_iterator it= Zones.find((uint16)patchId.ZoneId);
03212 if(it!=Zones.end())
03213 {
03214 sint N= (*it).second->getNumPatchs();
03215
03216 nlassert(patchId.PatchId<N);
03217 const CPatch *pa= const_cast<const CZone*>((*it).second)->getPatch(patchId.PatchId);
03218
03219 pa->appendTileLightInfluences(uv, pointLightList);
03220 }
03221 }
03222
03223
03224
03225
03226
03227
03228
03229
03230
03231
03232 void CLandscape::removeAllPointLights()
03233 {
03234 for(ItZoneMap it= Zones.begin();it!=Zones.end();it++)
03235 {
03236
03237 sint N= (*it).second->getNumPatchs();
03238 for(sint i=0;i<N;i++)
03239 {
03240
03241 CPatch *pa= ((*it).second)->getPatch(i);
03242 pa->resetTileLightInfluences();
03243 }
03244
03245
03246 (*it).second->_PointLightArray.clear();
03247 }
03248
03249 }
03250
03251
03252
03253 void CLandscape::setPointLightFactor(const std::string &lightGroupName, NLMISC::CRGBA nFactor)
03254 {
03255
03256 _LightGroupColorMap[lightGroupName]= nFactor;
03257
03258
03259 for(ItZoneMap it= Zones.begin();it!=Zones.end();it++)
03260 {
03261 (*it).second->_PointLightArray.setPointLightFactor(lightGroupName, nFactor);
03262 }
03263 }
03264
03265
03266
03267 void CLandscape::updateLighting(double time)
03268 {
03269 _ULTime= time;
03270
03271
03272 if(!_ULPrecTimeInit)
03273 {
03274 _ULPrecTimeInit= true;
03275 _ULPrecTime= _ULTime;
03276 }
03277
03278 float dt= float(_ULTime - _ULPrecTime);
03279 _ULPrecTime= _ULTime;
03280
03281
03282
03283 if(_ULFrequency)
03284 {
03285
03286 updateLightingTextureFar(dt * _ULFrequency);
03287 updateLightingTextureNear(dt * _ULFrequency);
03288 }
03289
03290 }
03291
03292
03293
03294 void CLandscape::updateLightingAll()
03295 {
03296
03297
03298 updateLightingTextureFar(1);
03299 updateLightingTextureNear(1);
03300
03301
03302
03303
03304
03305
03306 updateGlobalsAndLockBuffers (CVector::Null);
03307
03308
03309 OptFastFloorBegin();
03310
03311
03312 _VegetableManager->updateLightingAll();
03313
03314
03315 OptFastFloorEnd();
03316
03317
03318 unlockBuffers();
03319 }
03320
03321
03322
03323 void CLandscape::setUpdateLightingFrequency(float freq)
03324 {
03325 freq= max(freq, 0.f);
03326 _ULFrequency= freq;
03327 }
03328
03329
03330
03331 void CLandscape::linkPatchToNearUL(CPatch *patch)
03332 {
03333
03334 if(_ULRootNearPatch==NULL)
03335 _ULRootNearPatch= patch;
03336 else
03337 patch->linkBeforeNearUL(_ULRootNearPatch);
03338 }
03339
03340
03341 void CLandscape::unlinkPatchFromNearUL(CPatch *patch)
03342 {
03343
03344 if(_ULRootNearPatch==patch)
03345 {
03346
03347 _ULRootNearPatch= patch->getNextNearUL();
03348
03349 if(_ULRootNearPatch==patch)
03350 _ULRootNearPatch= NULL;
03351
03352 _ULNearCurrentTessBlockId= 0;
03353 }
03354
03355
03356 patch->unlinkNearUL();
03357 }
03358
03359
03360
03361 void CLandscape::updateLightingTextureFar(float ratio)
03362 {
03363
03364 _ULFarPixelsToUpdate+= ratio * _ULTotalFarPixels;
03365
03366 _ULFarPixelsToUpdate= min(_ULFarPixelsToUpdate, (float)_ULTotalFarPixels);
03367
03368
03369
03370
03371
03372
03373
03374
03375
03376 while(_ULFarPixelsToUpdate > 0 && _ULRootTextureFar)
03377 {
03378
03379 _ULFarPixelsToUpdate-= _ULRootTextureFar->touchPatch(_ULFarCurrentPatchId);
03380
03381 _ULFarCurrentPatchId++;
03382
03383
03384 if(_ULFarCurrentPatchId>=NL_NUM_FAR_PATCHES_BY_TEXTURE)
03385 {
03386
03387 _ULRootTextureFar= _ULRootTextureFar->getNextUL();
03388
03389 _ULFarCurrentPatchId=0;
03390 }
03391 }
03392
03393
03394 }
03395
03396
03397
03398 void CLandscape::updateLightingTextureNear(float ratio)
03399 {
03400
03401 _ULNearPixelsToUpdate+= ratio * _ULTotalNearPixels;
03402
03403 _ULNearPixelsToUpdate= min(_ULNearPixelsToUpdate, (float)_ULTotalNearPixels);
03404
03405
03406
03407 while(_ULNearPixelsToUpdate > 0 && _ULRootNearPatch)
03408 {
03409
03410 _ULNearPixelsToUpdate-= _ULRootNearPatch->updateTessBlockLighting(_ULNearCurrentTessBlockId);
03411
03412 _ULNearCurrentTessBlockId++;
03413
03414
03415 if(_ULNearCurrentTessBlockId>=_ULRootNearPatch->getNumNearTessBlocks())
03416 {
03417
03418 _ULRootNearPatch= _ULRootNearPatch->getNextNearUL();
03419
03420 _ULNearCurrentTessBlockId=0;
03421 }
03422 }
03423
03424 }
03425
03426
03427
03428 void CLandscape::computeDynamicLighting(const std::vector<CPointLight*> &pls)
03429 {
03430 uint i;
03431
03432
03433
03434 updateGlobalsAndLockBuffers (CVector::Null);
03435
03436
03437
03438
03439
03440 CPatchDLMContext *ctxPtr= _PatchDLMContextList->begin();
03441 while(ctxPtr!=NULL)
03442 {
03443
03444 ctxPtr->getPatch()->beginDLMLighting();
03445
03446
03447 ctxPtr= (CPatchDLMContext*)ctxPtr->Next;
03448 }
03449
03450
03451
03452
03453 static vector<CPatchDLMPointLight> dlmPls;
03454 dlmPls.resize(pls.size());
03455 for(i=0;i<dlmPls.size();i++)
03456 {
03457
03458 dlmPls[i].compile(*pls[i], _PointLightDiffuseMaterial, _DLMMaxAttEnd);
03459 }
03460
03461
03462
03463
03464 for(i=0;i<dlmPls.size();i++)
03465 {
03466 CPatchDLMPointLight &pl= dlmPls[i];
03467
03468
03469 _PatchQuadGrid.clearSelection();
03470 _PatchQuadGrid.select(pl.BBox.getMin(), pl.BBox.getMax());
03471 CQuadGrid<CPatchIdentEx>::CIterator it;
03472
03473
03474 for(it= _PatchQuadGrid.begin(); it!= _PatchQuadGrid.end(); it++)
03475 {
03476
03477 const CPatch *pa= (*it).Patch;
03478
03479
03480 if( pa->getBSphere().intersect( pl.BSphere ) )
03481 {
03482
03483 const_cast<CPatch*>(pa)->processDLMLight(pl);
03484 }
03485 }
03486
03487 }
03488
03489
03490
03491
03492 ctxPtr= _PatchDLMContextList->begin();
03493 while(ctxPtr!=NULL)
03494 {
03495
03496 CPatchDLMContext *next= (CPatchDLMContext*)ctxPtr->Next;
03497
03498
03499 ctxPtr->getPatch()->endDLMLighting();
03500
03501
03502 ctxPtr= next;
03503 }
03504
03505
03506
03507
03508 unlockBuffers();
03509
03510 }
03511
03512
03513
03514 void CLandscape::setDynamicLightingMaxAttEnd(float maxAttEnd)
03515 {
03516 maxAttEnd= max(maxAttEnd, 1.f);
03517 _DLMMaxAttEnd= maxAttEnd;
03518 }
03519
03520
03521
03522 uint CLandscape::getDynamicLightingMemoryLoad() const
03523 {
03524 uint mem= 0;
03525
03526 mem= NL3D_LANDSCAPE_DLM_WIDTH * NL3D_LANDSCAPE_DLM_HEIGHT * sizeof(CRGBA);
03527
03528
03529 CPatchDLMContext *ctxPtr= _PatchDLMContextList->begin();
03530 while(ctxPtr!=NULL)
03531 {
03532
03533 mem+= ctxPtr->getMemorySize();
03534
03535
03536 ctxPtr= (CPatchDLMContext*)ctxPtr->Next;
03537 }
03538
03539 return mem;
03540 }
03541
03542
03543
03544 void CLandscape::setDLMGlobalVegetableColor(CRGBA gvc)
03545 {
03546 _DLMGlobalVegetableColor= gvc;
03547 }
03548
03549
03550
03551 void CLandscape::setPointLightDiffuseMaterial(CRGBA diffuse)
03552 {
03553 _PointLightDiffuseMaterial= diffuse;
03554 }
03555
03556
03557 }