00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "std3d.h"
00025
00026 #include "nel/3d/scene.h"
00027 #include "nel/3d/trav_scene.h"
00028 #include "nel/3d/hrc_trav.h"
00029 #include "nel/3d/clip_trav.h"
00030 #include "nel/3d/light_trav.h"
00031 #include "nel/3d/anim_detail_trav.h"
00032 #include "nel/3d/load_balancing_trav.h"
00033 #include "nel/3d/render_trav.h"
00034 #include "nel/3d/transform.h"
00035 #include "nel/3d/camera.h"
00036 #include "nel/3d/landscape_model.h"
00037 #include "nel/3d/driver.h"
00038 #include "nel/3d/transform_shape.h"
00039 #include "nel/3d/mesh_base.h"
00040 #include "nel/3d/mesh_base_instance.h"
00041 #include "nel/3d/mesh_instance.h"
00042 #include "nel/3d/mesh_mrm_instance.h"
00043 #include "nel/3d/mesh_mrm_skinned_instance.h"
00044 #include "nel/3d/mesh_multi_lod_instance.h"
00045 #include "nel/3d/shape_bank.h"
00046 #include "nel/3d/skeleton_model.h"
00047 #include "nel/3d/particle_system_model.h"
00048 #include "nel/3d/coarse_mesh_manager.h"
00049 #include "nel/3d/cluster.h"
00050 #include "nel/3d/scene_group.h"
00051 #include "nel/3d/flare_model.h"
00052 #include "nel/3d/water_model.h"
00053 #include "nel/3d/vegetable_blend_layer_model.h"
00054 #include "nel/3d/root_model.h"
00055 #include "nel/3d/point_light_model.h"
00056 #include "nel/3d/animation.h"
00057 #include "nel/3d/lod_character_manager.h"
00058 #include "nel/3d/seg_remanence.h"
00059 #include "nel/3d/async_texture_manager.h"
00060 #include "nel/3d/water_env_map.h"
00061 #include "nel/3d/skeleton_spawn_script.h"
00062
00063
00064 #include <memory>
00065
00066 #include "nel/misc/time_nl.h"
00067 #include "nel/misc/file.h"
00068 #include "nel/misc/path.h"
00069
00070
00071 #include "nel/misc/system_info.h"
00072
00073 using namespace std;
00074 using namespace NLMISC;
00075
00076 #define NL3D_SCENE_COARSE_MANAGER_TEXTURE "nel_coarse_texture.tga"
00077
00078
00079
00080 const float NL3D_QuadGridClipManagerRadiusMax= 1500;
00081 const float NL3D_QuadGridClipClusterSize= 400;
00082 const uint NL3D_QuadGridClipNumDist= 10;
00083 const float NL3D_QuadGridClipMaxDist= 1000;
00084
00085
00086 #define NL3D_SCENE_DEFAULT_SHADOW_MAP_SIZE 64
00087 #define NL3D_SCENE_DEFAULT_SHADOW_MAP_BLUR_SIZE 2
00088 #define NL3D_SCENE_DEFAULT_SHADOW_MAP_DIST_FADE_START 40
00089 #define NL3D_SCENE_DEFAULT_SHADOW_MAP_DIST_FADE_END 50
00090 #define NL3D_SCENE_DEFAULT_SHADOW_MAP_MAX_CASTER_IN_SCREEN 16
00091 #define NL3D_SCENE_DEFAULT_SHADOW_MAP_MAX_CASTER_AROUND 64
00092
00093
00094 namespace NL3D
00095 {
00096
00097
00098
00099
00100
00101
00102 void CScene::registerBasics()
00103 {
00104 CTransform::registerBasic();
00105 CCamera::registerBasic();
00106 CMeshBaseInstance::registerBasic();
00107 CMeshInstance::registerBasic();
00108 CMeshMRMInstance::registerBasic();
00109 CMeshMRMSkinnedInstance::registerBasic();
00110 CLandscapeModel::registerBasic();
00111 CTransformShape::registerBasic();
00112 CSkeletonModel::registerBasic();
00113 CParticleSystemModel::registerBasic() ;
00114 CMeshMultiLodInstance::registerBasic();
00115 CCluster::registerBasic();
00116 CFlareModel::registerBasic();
00117 CWaterModel::registerBasic();
00118 CWaveMakerModel::registerBasic();
00119 CVegetableBlendLayerModel::registerBasic();
00120 CRootModel::registerBasic();
00121 CPointLightModel::registerBasic();
00122 CSegRemanence::registerBasic();
00123 CQuadGridClipManager::registerBasic();
00124 }
00125
00126
00127
00128
00129
00130
00131
00132 CScene::CScene(bool bSmallScene) : LightTrav(bSmallScene)
00133 {
00134 HrcTrav.Scene= this;
00135 ClipTrav.Scene= this;
00136 LightTrav.Scene= this;
00137 AnimDetailTrav.Scene= this;
00138 LoadBalancingTrav.Scene= this;
00139 RenderTrav.Scene= this;
00140
00141 _ShapeBank = NULL;
00142
00143 Root= NULL;
00144 RootCluster= NULL;
00145 SonsOfAncestorSkeletonModelGroup= NULL;
00146 _QuadGridClipManager= NULL;
00147
00148 _CurrentTime = 0 ;
00149 _EllapsedTime = 0 ;
00150 _RealTime = 0 ;
00151 _FirstAnimateCall = true ;
00152
00153 _LightingSystemEnabled= false;
00154 _CoarseMeshLightingUpdate= 50;
00155
00156 _GlobalWindDirection.set(1,0,0);
00157
00158 _GlobalWindPower= 0.2f;
00159
00160
00161 _LodCharacterManager= NULL;
00162 _AsyncTextureManager= NULL;
00163
00164 _NumRender = 0;
00165
00166 _MaxSkeletonsInNotCLodForm= 20;
00167
00168 _FilterRenderFlags= ~0;
00169
00170 _NextRenderProfile= false;
00171
00172
00173 _CoarseMeshManager= new CCoarseMeshManager;
00174 _CoarseMeshManager->setTextureFile (NL3D_SCENE_COARSE_MANAGER_TEXTURE);
00175
00176
00177 _UpdateModelList= NULL;
00178
00179 _FlareContext = 0;
00180
00181 _ShadowMapTextureSize= NL3D_SCENE_DEFAULT_SHADOW_MAP_SIZE;
00182 _ShadowMapBlurSize= NL3D_SCENE_DEFAULT_SHADOW_MAP_BLUR_SIZE;
00183 _ShadowMapDistFadeStart= NL3D_SCENE_DEFAULT_SHADOW_MAP_DIST_FADE_START;
00184 _ShadowMapDistFadeEnd= NL3D_SCENE_DEFAULT_SHADOW_MAP_DIST_FADE_END;
00185 _ShadowMapMaxCasterInScreen= NL3D_SCENE_DEFAULT_SHADOW_MAP_MAX_CASTER_IN_SCREEN;
00186 _ShadowMapMaxCasterAround= NL3D_SCENE_DEFAULT_SHADOW_MAP_MAX_CASTER_AROUND;
00187 _VisualCollisionManagerForShadow= NULL;
00188
00189 _WaterCallback = NULL;
00190 _PolyDrawingCallback = NULL;
00191 _IsRendering = false;
00192
00193 _FirstFlare = NULL;
00194 _RenderedPart = UScene::RenderNothing;
00195
00196
00197
00198 _WaterEnvMap = NULL;
00199
00200 _GlobalSystemTime= 0.0;
00201 }
00202
00203 void CScene::release()
00204 {
00205
00206 if( _QuadGridClipManager )
00207 _QuadGridClipManager->reset();
00208
00209
00210 set<CTransform*>::iterator it;
00211 it= _Models.begin();
00212 while( it!=_Models.end())
00213 {
00214 CTransform *tr= *it;
00215
00216 if(tr!=Root && tr!=RootCluster && tr!=SonsOfAncestorSkeletonModelGroup)
00217 deleteModel(tr);
00218
00219 else
00220 _Models.erase(it);
00221
00222 it= _Models.begin();
00223 }
00224
00225
00226
00227 if(Root) _Models.insert(Root);
00228 if(RootCluster) _Models.insert(RootCluster);
00229 if(SonsOfAncestorSkeletonModelGroup) _Models.insert(SonsOfAncestorSkeletonModelGroup);
00230
00231 if(SonsOfAncestorSkeletonModelGroup)
00232 {
00233 deleteModel(SonsOfAncestorSkeletonModelGroup);
00234 SonsOfAncestorSkeletonModelGroup= NULL;
00235 }
00236 if(RootCluster)
00237 {
00238 deleteModel(RootCluster);
00239 RootCluster= NULL;
00240 }
00241 if(Root)
00242 {
00243 deleteModel(Root);
00244 Root= NULL;
00245 }
00246
00247
00248 _UpdateModelList= NULL;
00249
00250
00251 _ShapeBank = NULL;
00252 Root= NULL;
00253 RootCluster= NULL;
00254 SonsOfAncestorSkeletonModelGroup= NULL;
00255 CurrentCamera= NULL;
00256 _QuadGridClipManager= NULL;
00257 ClipTrav.setQuadGridClipManager(NULL);
00258
00259
00260
00261
00262
00263
00264 _LodCharacterManager= NULL;
00265
00266
00267 if(_CoarseMeshManager)
00268 {
00269 delete _CoarseMeshManager;
00270 _CoarseMeshManager= NULL;
00271 }
00272
00273 if(_GlobalInstanceGroup)
00274 {
00275 delete _GlobalInstanceGroup;
00276 _GlobalInstanceGroup = NULL;
00277 }
00278
00279
00280 _LMAnimsAuto.deleteAll();
00281 }
00282
00283 CScene::~CScene()
00284 {
00285 release();
00286 }
00287
00288 void CScene::initDefaultRoots()
00289 {
00290
00291 Root= static_cast<CTransform*>(createModel(TransformId));
00292
00293
00294 Root->freeze();
00295
00296
00297 _GlobalInstanceGroup = new CInstanceGroup;
00298 RootCluster= (CCluster*)createModel (ClusterId);
00299
00300 RootCluster->hrcUnlink();
00301 RootCluster->Name = "ClusterRoot";
00302 RootCluster->Group = _GlobalInstanceGroup;
00303 _GlobalInstanceGroup->addCluster (RootCluster);
00304
00305
00306 ClipTrav.RootCluster = RootCluster;
00307
00308
00309 SonsOfAncestorSkeletonModelGroup= static_cast<CRootModel*>(createModel(RootModelId));
00310
00311 SonsOfAncestorSkeletonModelGroup->hrcUnlink();
00312 Root->clipDelChild(SonsOfAncestorSkeletonModelGroup);
00313 }
00314
00315
00316 void CScene::initQuadGridClipManager ()
00317 {
00318
00319 if( !_QuadGridClipManager )
00320 {
00321
00322 _QuadGridClipManager= static_cast<CQuadGridClipManager*>(createModel(QuadGridClipManagerId));
00323
00324
00325 _QuadGridClipManager->hrcUnlink();
00326 _QuadGridClipManager->clipUnlinkFromAll();
00327 RootCluster->clipAddChild(_QuadGridClipManager);
00328
00329
00330 _QuadGridClipManager->init(NL3D_QuadGridClipClusterSize,
00331 NL3D_QuadGridClipNumDist,
00332 NL3D_QuadGridClipMaxDist,
00333 NL3D_QuadGridClipManagerRadiusMax);
00334 }
00335 }
00336
00337
00338
00339 void CScene::render(bool doHrcPass)
00340 {
00341 beginPartRender();
00342 renderPart(UScene::RenderAll, doHrcPass);
00343 endPartRender();
00344 }
00345
00346
00347
00348 void CScene::beginPartRender()
00349 {
00350 nlassert(!_IsRendering);
00351
00352
00353
00354 _IsRendering = true;
00355 _RenderedPart= UScene::RenderNothing;
00356
00357 }
00358
00359
00360
00361 void CScene::endPartRender()
00362 {
00363 nlassert(_IsRendering);
00364
00365
00366 _IsRendering = false;
00367 uint i;
00368 for (i=0; i<_ToDelete.size(); i++)
00369 deleteModel (_ToDelete[i]);
00370 _ToDelete.clear ();
00371
00372
00373 flushSSSModelRequests();
00374
00375
00376
00377 _ParticleSystemManager.refreshModels(ClipTrav.WorldFrustumPyramid, ClipTrav.CamPos);
00378
00379
00380 double deltaT = _DeltaSystemTimeBetweenRender;
00381 clamp (deltaT, 0.01, 0.1);
00382 updateWaitingInstances(deltaT);
00383
00384
00385 _NextRenderProfile= false;
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552 }
00553
00554
00555
00556 void CScene::renderPart(UScene::TRenderPart rp, bool doHrcPass)
00557 {
00558 nlassert(_IsRendering);
00559
00560
00561 if(rp==UScene::RenderNothing)
00562 return;
00563
00564
00565 nlassert((rp & _RenderedPart) == 0);
00566
00567
00568 if (_RenderedPart == UScene::RenderNothing)
00569 {
00570
00571
00572 RenderTrav.clearWaterModelList();
00573 _FirstFlare = NULL;
00574
00575 double fNewGlobalSystemTime = NLMISC::CTime::ticksToSecond(NLMISC::CTime::getPerformanceTime());
00576 if(_GlobalSystemTime==0)
00577 _DeltaSystemTimeBetweenRender= 0.020;
00578 else
00579 _DeltaSystemTimeBetweenRender= fNewGlobalSystemTime - _GlobalSystemTime;
00580 _GlobalSystemTime = fNewGlobalSystemTime;
00581
00582 ++ _NumRender;
00583
00584 nlassert(CurrentCamera);
00585
00586
00587 updateModels();
00588
00589
00590 float left, right, bottom, top, znear, zfar;
00591 CurrentCamera->getFrustum(left, right, bottom, top, znear, zfar);
00592
00593
00594 ClipTrav.setFrustum(left, right, bottom, top, znear, zfar, CurrentCamera->isPerspective());
00595
00596 RenderTrav.setFrustum (left, right, bottom, top, znear, zfar, CurrentCamera->isPerspective());
00597 RenderTrav.setViewport (_Viewport);
00598
00599 LoadBalancingTrav.setFrustum (left, right, bottom, top, znear, zfar, CurrentCamera->isPerspective());
00600
00601
00602
00603 ClipTrav.Camera = CurrentCamera;
00604 ClipTrav.setQuadGridClipManager (_QuadGridClipManager);
00605
00606
00607
00608 if( doHrcPass )
00609 HrcTrav.traverse();
00610
00611
00612 ClipTrav.setCamMatrix(CurrentCamera->getWorldMatrix());
00613 RenderTrav.setCamMatrix (CurrentCamera->getWorldMatrix());
00614 LoadBalancingTrav.setCamMatrix (CurrentCamera->getWorldMatrix());
00615
00616
00617
00618 ClipTrav.traverse();
00619
00620 AnimDetailTrav.traverse();
00621
00622 LoadBalancingTrav.traverse();
00623
00624 _ParticleSystemManager.processAnimate(_EllapsedTime);
00625
00626 LightTrav.traverse();
00627 }
00628
00629
00630 RenderTrav.traverse(rp, _RenderedPart == UScene::RenderNothing);
00631
00632 RenderTrav.getShadowMapManager().clearAllShadowCasters();
00633
00634
00635 if (rp & UScene::RenderFlare)
00636 {
00637 if (_FirstFlare)
00638 {
00639 IDriver *drv = getDriver();
00640 CFlareModel::updateOcclusionQueryBegin(drv);
00641 CFlareModel *currFlare = _FirstFlare;
00642 do
00643 {
00644 currFlare->updateOcclusionQuery(drv);
00645 currFlare = currFlare->Next;
00646 }
00647 while(currFlare);
00648 CFlareModel::updateOcclusionQueryEnd(drv);
00649 }
00650 }
00651 _RenderedPart = (UScene::TRenderPart) (_RenderedPart | rp);
00652 }
00653
00654
00655 void CScene::updateWaitingInstances(double systemTimeEllapsed)
00656 {
00657
00658 double fMaxBytesToUp = 100 * 256 * 256 * systemTimeEllapsed;
00659 _ShapeBank->setMaxBytesToUpload ((uint32)fMaxBytesToUp);
00660
00661 _ShapeBank->processWaitingShapes ();
00662
00663 TWaitingInstancesMMap::iterator wimmIt = _WaitingInstances.begin();
00664 while( wimmIt != _WaitingInstances.end() )
00665 {
00666 CShapeBank::TShapeState st = _ShapeBank->getPresentState (wimmIt->first);
00667 if (st == CShapeBank::AsyncLoad_Error)
00668 {
00669
00670 TWaitingInstancesMMap::iterator itDel= wimmIt;
00671 ++wimmIt;
00672 _WaitingInstances.erase(itDel);
00673 }
00674 else if (st == CShapeBank::Present)
00675 {
00676
00677 *(wimmIt->second) = _ShapeBank->addRef(wimmIt->first)->createInstance (*this);
00678
00679 TWaitingInstancesMMap::iterator itDel= wimmIt;
00680 ++wimmIt;
00681 _WaitingInstances.erase(itDel);
00682 }
00683 else
00684 {
00685 ++wimmIt;
00686 }
00687 }
00688 }
00689
00690
00691 void CScene::setDriver(IDriver *drv)
00692 {
00693 RenderTrav.setDriver(drv);
00694 }
00695
00696
00697 IDriver *CScene::getDriver() const
00698 {
00699 return (const_cast<CScene*>(this))->RenderTrav.getDriver();
00700 }
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711 void CScene::setShapeBank(CShapeBank*pShapeBank)
00712 {
00713 _ShapeBank = pShapeBank;
00714 }
00715
00716
00717
00718 CTransformShape *CScene::createInstance(const string &shapeName)
00719 {
00720
00721
00722 nlassert( _ShapeBank != NULL );
00723
00724
00725 if (_ShapeBank->getPresentState( shapeName ) != CShapeBank::Present)
00726 {
00727
00728 _ShapeBank->load( shapeName );
00729 if (_ShapeBank->getPresentState( shapeName ) != CShapeBank::Present)
00730 {
00731 return NULL;
00732 }
00733 }
00734
00735 CTransformShape *pTShp = _ShapeBank->addRef( shapeName )->createInstance(*this);
00736 if (pTShp) pTShp->setDistMax(pTShp->Shape->getDistMax());
00737
00738
00739 #if defined(__GNUC__) && __GNUC__ < 3
00740 CMeshBase *pMB = (CMeshBase*)((IShape*)(pTShp->Shape));
00741 #else // not GNUC
00742 CMeshBase *pMB = dynamic_cast<CMeshBase*>((IShape*)(pTShp->Shape));
00743 #endif // not GNUC
00744 CMeshBaseInstance *pMBI = dynamic_cast<CMeshBaseInstance*>( pTShp );
00745 if( ( pMB != NULL ) && ( pMBI != NULL ) )
00746 {
00747
00748 pMBI->initAnimatedLightIndex (*this);
00749
00750
00751
00752
00753 if (_AutomaticAnimationSet)
00754 {
00755 if (pMB->getAutoAnim())
00756 {
00757
00758 std::string animName = toLower(CFile::getFilenameWithoutExtension(shapeName));
00759 uint animID = _AutomaticAnimationSet->getAnimationIdByName(animName);
00760 if (animID != CAnimationSet::NotFound)
00761 {
00762 CChannelMixer *chanMix = new CChannelMixer;
00763 chanMix->setAnimationSet((CAnimationSet *) _AutomaticAnimationSet);
00764 chanMix->setSlotAnimation(0, animID);
00765
00766 pMBI->registerToChannelMixer(chanMix, "");
00767
00768 pMBI->setChannelMixerOwnerShip(true);
00769 }
00770 }
00771 }
00772 }
00773
00774 CLandscapeModel *pLM = dynamic_cast<CLandscapeModel*>( pTShp );
00775 if( pLM != NULL )
00776 {
00777
00778 pLM->Landscape.initAnimatedLightIndex (*this);
00779 }
00780
00781 return pTShp;
00782 }
00783
00784
00785
00786 void CScene::createInstanceAsync(const string &shapeName, CTransformShape **pInstance, const NLMISC::CVector &position, uint selectedTexture)
00787 {
00788
00789
00790 nlassert( _ShapeBank != NULL );
00791 *pInstance = NULL;
00792
00793 _WaitingInstances.insert(TWaitingInstancesMMap::value_type(shapeName,pInstance));
00794
00795 if (_ShapeBank->getPresentState( shapeName ) != CShapeBank::Present)
00796 {
00797
00798 _ShapeBank->loadAsync( toLower(shapeName), getDriver(), position, NULL, selectedTexture);
00799 }
00800 }
00801
00802
00803 void CScene::deleteInstance(CTransformShape *pTrfmShp)
00804 {
00805 IShape *pShp = NULL;
00806 if( pTrfmShp == NULL )
00807 return;
00808
00809 pShp = pTrfmShp->Shape;
00810
00811 deleteModel( pTrfmShp );
00812
00813 if (pShp)
00814 {
00815
00816 _ShapeBank->release( pShp );
00817 }
00818
00819 }
00820
00821
00822 void CScene::animate( TGlobalAnimationTime atTime )
00823 {
00824
00825 if (_FirstAnimateCall)
00826 {
00827 _InitTime = atTime;
00828 _RealTime = atTime;
00829
00830 _EllapsedTime = 0.01f ;
00831 _FirstAnimateCall = false ;
00832 }
00833 else
00834 {
00835 _EllapsedTime = (float) (atTime - _RealTime);
00836
00837 if (_EllapsedTime < 0.0f)
00838 _EllapsedTime = 0.01f;
00839 _EllapsedTime = fabsf(_EllapsedTime);
00840 _RealTime = atTime ;
00841 _CurrentTime += _EllapsedTime;
00842 }
00843
00844 _LMAnimsAuto.animate( atTime );
00845
00846
00847
00848
00849
00850 const uint count = _AnimatedLightPtr.size ();
00851 uint i;
00852 for (i=0; i<count; i++)
00853 {
00854
00855 _AnimatedLightPtr[i]->updateGroupColors (*this);
00856 }
00857
00858
00859 ItAnimatedIgSet itAnIgSet;
00860 for(itAnIgSet= _AnimatedIgSet.begin(); itAnIgSet!=_AnimatedIgSet.end(); itAnIgSet++)
00861 {
00862 CInstanceGroup *ig= *itAnIgSet;
00863
00864
00865 ig->setPointLightFactor(*this);
00866 }
00867
00868
00869 _RenderedPart = UScene::RenderNothing;
00870 }
00871
00872
00873
00874 float CScene::getNbFaceAsked () const
00875 {
00876 return LoadBalancingTrav.getNbFaceAsked ();
00877 }
00878
00879
00880
00881 void CScene::setGroupLoadMaxPolygon(const std::string &group, uint nFaces)
00882 {
00883 nFaces= max(nFaces, (uint)1);
00884 LoadBalancingTrav.setGroupNbFaceWanted(group, nFaces);
00885 }
00886
00887 uint CScene::getGroupLoadMaxPolygon(const std::string &group)
00888 {
00889 return LoadBalancingTrav.getGroupNbFaceWanted(group);
00890 }
00891
00892 float CScene::getGroupNbFaceAsked (const std::string &group) const
00893 {
00894 return LoadBalancingTrav.getGroupNbFaceAsked(group);
00895 }
00896
00897
00898
00899
00900 void CScene::setPolygonBalancingMode(TPolygonBalancingMode polBalMode)
00901 {
00902 LoadBalancingTrav.PolygonBalancingMode= (CLoadBalancingGroup::TPolygonBalancingMode)(uint)polBalMode;
00903 }
00904
00905
00906
00907 CScene::TPolygonBalancingMode CScene::getPolygonBalancingMode() const
00908 {
00909 return (CScene::TPolygonBalancingMode)(uint)LoadBalancingTrav.PolygonBalancingMode;
00910 }
00911
00912
00913 void CScene::setLayersRenderingOrder(bool directOrder )
00914 {
00915 RenderTrav.setLayersRenderingOrder(directOrder);
00916 }
00917
00918
00919 bool CScene::getLayersRenderingOrder() const
00920 {
00921 return RenderTrav.getLayersRenderingOrder();
00922 }
00923
00924
00925 CParticleSystemManager &CScene::getParticleSystemManager()
00926 {
00927 return _ParticleSystemManager;
00928 }
00929
00930
00931 void CScene::enableElementRender(UScene::TRenderFilter elt, bool state)
00932 {
00933 if(state)
00934 _FilterRenderFlags|= (uint32)elt;
00935 else
00936 _FilterRenderFlags&= ~(uint32)elt;
00937 }
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948 void CScene::enableLightingSystem(bool enable)
00949 {
00950 _LightingSystemEnabled= enable;
00951
00952
00953 RenderTrav.LightingSystemEnabled= _LightingSystemEnabled;
00954 LightTrav.LightingSystemEnabled= _LightingSystemEnabled;
00955 }
00956
00957
00958
00959 void CScene::setAmbientGlobal(NLMISC::CRGBA ambient)
00960 {
00961 RenderTrav.AmbientGlobal= ambient;
00962 }
00963 void CScene::setSunAmbient(NLMISC::CRGBA ambient)
00964 {
00965 RenderTrav.SunAmbient= ambient;
00966 }
00967 void CScene::setSunDiffuse(NLMISC::CRGBA diffuse)
00968 {
00969 RenderTrav.SunDiffuse= diffuse;
00970 }
00971 void CScene::setSunSpecular(NLMISC::CRGBA specular)
00972 {
00973 RenderTrav.SunSpecular= specular;
00974 }
00975 void CScene::setSunDirection(const NLMISC::CVector &direction)
00976 {
00977 RenderTrav.setSunDirection(direction);
00978 }
00979
00980
00981
00982 NLMISC::CRGBA CScene::getAmbientGlobal() const
00983 {
00984 return RenderTrav.AmbientGlobal;
00985 }
00986 NLMISC::CRGBA CScene::getSunAmbient() const
00987 {
00988 return RenderTrav.SunAmbient;
00989 }
00990 NLMISC::CRGBA CScene::getSunDiffuse() const
00991 {
00992 return RenderTrav.SunDiffuse;
00993 }
00994 NLMISC::CRGBA CScene::getSunSpecular() const
00995 {
00996 return RenderTrav.SunSpecular;
00997 }
00998 NLMISC::CVector CScene::getSunDirection() const
00999 {
01000 return RenderTrav.getSunDirection();
01001 }
01002
01003
01004
01005 void CScene::setMaxLightContribution(uint nlights)
01006 {
01007 LightTrav.LightingManager.setMaxLightContribution(nlights);
01008 }
01009 uint CScene::getMaxLightContribution() const
01010 {
01011 return LightTrav.LightingManager.getMaxLightContribution();
01012 }
01013
01014 void CScene::setLightTransitionThreshold(float lightTransitionThreshold)
01015 {
01016 LightTrav.LightingManager.setLightTransitionThreshold(lightTransitionThreshold);
01017 }
01018 float CScene::getLightTransitionThreshold() const
01019 {
01020 return LightTrav.LightingManager.getLightTransitionThreshold();
01021 }
01022
01023
01024
01025 void CScene::addInstanceGroupForLightAnimation(CInstanceGroup *ig)
01026 {
01027 nlassert( ig );
01028 nlassert( _AnimatedIgSet.find(ig) == _AnimatedIgSet.end() );
01029 _AnimatedIgSet.insert(ig);
01030 }
01031
01032
01033 void CScene::removeInstanceGroupForLightAnimation(CInstanceGroup *ig)
01034 {
01035 nlassert( ig );
01036 ItAnimatedIgSet itIg= _AnimatedIgSet.find(ig);
01037 if ( itIg != _AnimatedIgSet.end() )
01038 _AnimatedIgSet.erase(itIg);
01039 }
01040
01041
01042
01043 void CScene::setCoarseMeshLightingUpdate(uint8 period)
01044 {
01045 _CoarseMeshLightingUpdate= max((uint8)1, period);
01046 }
01047
01048
01049
01050
01052
01053
01054
01055
01056 void CScene::setGlobalWindPower(float gwp)
01057 {
01058 _GlobalWindPower= gwp;
01059 }
01060
01061 void CScene::setGlobalWindDirection(const CVector &gwd)
01062 {
01063 _GlobalWindDirection= gwd;
01064 _GlobalWindDirection.z= 0;
01065 _GlobalWindDirection.normalize();
01066 }
01067
01068
01069
01070
01072
01073
01074
01075
01076 CScene::ItSkeletonModelList CScene::appendSkeletonModelToList(CSkeletonModel *skel)
01077 {
01078 _SkeletonModelList.push_front(skel);
01079 return _SkeletonModelList.begin();
01080 }
01081
01082
01083 void CScene::eraseSkeletonModelToList(CScene::ItSkeletonModelList it)
01084 {
01085 _SkeletonModelList.erase(it);
01086 }
01087
01088
01089 void CScene::registerShadowCasterToList(CTransform *sc)
01090 {
01091 nlassert(sc);
01092 _ShadowCasterList.push_front(sc);
01093 sc->_ItShadowCasterInScene= _ShadowCasterList.begin();
01094 }
01095
01096
01097 void CScene::unregisterShadowCasterToList(CTransform *sc)
01098 {
01099 nlassert(sc);
01100 _ShadowCasterList.erase(sc->_ItShadowCasterInScene);
01101 }
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112 set<CScene::CModelEntry> CScene::_RegModels;
01113
01114
01115
01116 void CScene::registerModel(const CClassId &idModel, const CClassId &idModelBase, CTransform* (*creator)())
01117 {
01118 nlassert(idModel!=CClassId::Null);
01119 nlassert(creator);
01120
01121
01122 CModelEntry e;
01123 e.BaseModelId= idModelBase;
01124 e.ModelId= idModel;
01125 e.Creator= creator;
01126
01127
01128 _RegModels.erase(e);
01129 _RegModels.insert(e);
01130 }
01131
01132
01133
01134 CTransform *CScene::createModel(const CClassId &idModel)
01135 {
01136 nlassert(idModel!=CClassId::Null);
01137
01138 CModelEntry e;
01139 e.ModelId= idModel;
01140 set<CModelEntry>::iterator itModel;
01141 itModel= _RegModels.find(e);
01142
01143 if(itModel==_RegModels.end())
01144 {
01145 nlstop;
01146 return NULL;
01147 }
01148 else
01149 {
01150 CTransform *m= (*itModel).Creator();
01151 if(!m) return NULL;
01152
01153
01154 m->_OwnerScene= this;
01155
01156
01157 if(Root)
01158 {
01159 Root->hrcLinkSon(m);
01160 Root->clipAddChild(m);
01161 }
01162
01163
01164 _Models.insert(m);
01165
01166
01167 m->linkToUpdateList();
01168
01169
01170 m->initModel();
01171
01172
01173 ClipTrav.reserveVisibleList(_Models.size());
01174 AnimDetailTrav.reserveVisibleList(_Models.size());
01175 LoadBalancingTrav.reserveVisibleList(_Models.size());
01176 LightTrav.reserveLightedList(_Models.size());
01177 RenderTrav.reserveRenderList(_Models.size());
01178
01179 return m;
01180 }
01181 }
01182
01183 void CScene::deleteModel(CTransform *model)
01184 {
01185 if(model==NULL)
01186 return;
01187
01188
01189 if (_IsRendering)
01190 {
01191
01192 _ToDelete.push_back (model);
01193
01194
01195
01196 RenderTrav.removeRenderModel(model);
01197 }
01198
01199 else
01200 {
01201 set<CTransform*>::iterator it= _Models.find(model);
01202 if(it!=_Models.end())
01203 {
01204 delete *it;
01205 _Models.erase(it);
01206 }
01207 }
01208 }
01209
01210
01211
01212 void CScene::updateModels()
01213 {
01214
01215 CTransform *model= _UpdateModelList;
01216 CTransform *next;
01217 while( model )
01218 {
01219
01220 next= model->_NextModelToUpdate;
01221
01222
01223 model->update();
01224
01225
01226 model= next;
01227 }
01228 }
01229
01230
01231
01232 void CScene::setLightGroupColor(uint lightmapGroup, NLMISC::CRGBA color)
01233 {
01234
01235 if (lightmapGroup >= _LightGroupColor.size ())
01236 {
01237 _LightGroupColor.resize (lightmapGroup+1, CRGBA::White);
01238 }
01239
01240
01241 _LightGroupColor[lightmapGroup] = color;
01242 }
01243
01244
01245
01246 sint CScene::getAnimatedLightNameToIndex (const std::string &name) const
01247 {
01248 std::map<std::string, uint>::const_iterator ite = _AnimatedLightNameToIndex.find (name);
01249 if (ite != _AnimatedLightNameToIndex.end ())
01250 return (sint)ite->second;
01251 else
01252 return -1;
01253 }
01254
01255
01256
01257 void CScene::setAutomaticAnimationSet(CAnimationSet *as)
01258 {
01259
01260 _AutomaticAnimationSet = as;
01261
01262
01263 _LMAnimsAuto.deleteAll();
01264 _AnimatedLightNameToIndex.clear();
01265 _AnimatedLight.clear();
01266 _AnimatedLightPtr.clear();
01267 _LightGroupColor.clear();
01268
01269
01270 const uint count = _AutomaticAnimationSet->getNumAnimation();
01271 uint i;
01272 for (i=0; i<count; i++)
01273 {
01274
01275 CAnimation *pAnim = _AutomaticAnimationSet->getAnimation(i);
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296 set<string> setTrackNames;
01297 pAnim->getTrackNames( setTrackNames );
01298
01299
01300
01301
01302 set<string>::iterator itSel = setTrackNames.begin();
01303 while ( itSel != setTrackNames.end() )
01304 {
01305 string ate = *itSel;
01306 if( strncmp( itSel->c_str(), "LightmapController.", 19 ) == 0 )
01307 {
01308
01309 const char *lightName = strrchr ((*itSel).c_str (), '.')+1;
01310
01311
01312 if (_AnimatedLightNameToIndex.find (lightName) == _AnimatedLightNameToIndex.end())
01313 {
01314
01315 CChannelMixer *cm = new CChannelMixer();
01316 cm->setAnimationSet( _AutomaticAnimationSet );
01317
01318
01319 _AnimatedLight.push_back ( CAnimatedLightmap (_LightGroupColor.size ()) );
01320 _AnimatedLightPtr.push_back ( &_AnimatedLight.back () );
01321 _AnimatedLightNameToIndex.insert ( std::map<std::string, uint>::value_type (lightName, _AnimatedLightPtr.size ()-1 ) );
01322 CAnimatedLightmap &animLM = _AnimatedLight.back ();
01323 animLM.setName( *itSel );
01324
01325 cm->addChannel( animLM.getName(), &animLM, animLM.getValue(CAnimatedLightmap::FactorValue),
01326 animLM.getDefaultTrack(CAnimatedLightmap::FactorValue), CAnimatedLightmap::FactorValue,
01327 CAnimatedLightmap::OwnerBit, false);
01328
01329
01330 CAnimationPlaylist *pl = new CAnimationPlaylist();
01331 pl->setAnimation( 0, i );
01332 pl->setWrapMode( 0, CAnimationPlaylist::Repeat );
01333 _LMAnimsAuto.addPlaylist(pl,cm);
01334 }
01335 }
01336 ++itSel;
01337 }
01338 }
01339 }
01340
01341
01342
01343
01345
01346
01347
01348
01349 void CScene::profileNextRender()
01350 {
01351 _NextRenderProfile= true;
01352
01353
01354 BenchRes.reset();
01355 }
01356
01357
01358
01359 void CScene::setShadowMapTextureSize(uint size)
01360 {
01361 size= max(size, 2U);
01362 size= raiseToNextPowerOf2(size);
01363 _ShadowMapTextureSize= size;
01364 }
01365
01366
01367 void CScene::setShadowMapBlurSize(uint bs)
01368 {
01369 _ShadowMapBlurSize= bs;
01370 }
01371
01372
01373 void CScene::enableShadowPolySmooth(bool enable)
01374 {
01375 RenderTrav.getShadowMapManager().enableShadowPolySmooth(enable);
01376 }
01377
01378
01379 bool CScene::getEnableShadowPolySmooth() const
01380 {
01381 return RenderTrav.getShadowMapManager().getEnableShadowPolySmooth();
01382 }
01383
01384
01385
01386 void CScene::setShadowMapDistFadeStart(float dist)
01387 {
01388 _ShadowMapDistFadeStart= max(0.f, dist);
01389 }
01390
01391 void CScene::setShadowMapDistFadeEnd(float dist)
01392 {
01393 _ShadowMapDistFadeEnd= max(0.f, dist);
01394 }
01395
01396 void CScene::setShadowMapMaxCasterInScreen(uint num)
01397 {
01398 _ShadowMapMaxCasterInScreen= num;
01399 }
01400
01401 void CScene::setShadowMapMaxCasterAround(uint num)
01402 {
01403 _ShadowMapMaxCasterAround= num;
01404 }
01405
01406
01407 CInstanceGroup *CScene::findCameraClusterSystemFromRay(CInstanceGroup *startClusterSystem,
01408 const NLMISC::CVector &startPos, NLMISC::CVector &endPos)
01409 {
01410 CInstanceGroup *resultCS= NULL;
01411
01412 CClipTrav &clipTrav= getClipTrav();
01413
01414
01415 static vector<CCluster*> vCluster;
01416 vCluster.clear();
01417
01418 bool bInWorld = true;
01419 clipTrav.Accel.select (startPos, startPos);
01420 CQuadGrid<CCluster*>::CIterator itAcc = clipTrav.Accel.begin();
01421 while (itAcc != clipTrav.Accel.end())
01422 {
01423 CCluster *pCluster = *itAcc;
01424 if( pCluster->Group == startClusterSystem &&
01425 pCluster->isIn (startPos) )
01426 {
01427 vCluster.push_back (pCluster);
01428 bInWorld = false;
01429 }
01430 ++itAcc;
01431 }
01432 if (bInWorld)
01433 {
01434 vCluster.push_back (RootCluster);
01435 }
01436
01437
01438 uint i;
01439 static vector<CCluster*> vClusterVisited;
01440 vClusterVisited.clear();
01441 for(i=0;i<vCluster.size();i++)
01442 {
01443 vCluster[i]->cameraRayClip(startPos, endPos, vClusterVisited);
01444 }
01445
01446
01447 static vector<CInstanceGroup*> possibleClusterSystem;
01448 possibleClusterSystem.clear();
01449 for(i=0;i<vClusterVisited.size();i++)
01450 {
01451
01452
01453 if(vClusterVisited[i]->isIn(endPos))
01454 {
01455 CInstanceGroup *cs= vClusterVisited[i]->Group;
01456
01457 uint j;
01458 for(j=0;j<possibleClusterSystem.size();j++)
01459 {
01460 if(possibleClusterSystem[j]==cs)
01461 break;
01462 }
01463 if(j==possibleClusterSystem.size())
01464 possibleClusterSystem.push_back(cs);
01465 }
01466 }
01467
01468
01469
01470 if(possibleClusterSystem.empty())
01471 {
01472 CCluster *bestCluster= NULL;
01473 float shortDist= FLT_MAX;
01474
01475 for(i=0;i<vClusterVisited.size();i++)
01476 {
01477
01478 CVector a= startPos;
01479 CVector b= endPos;
01480 if(vClusterVisited[i]->clipSegment(a, b))
01481 {
01482 float dist= (endPos - b).norm();
01483 if(dist<shortDist)
01484 {
01485 bestCluster= vClusterVisited[i];
01486 shortDist= dist;
01487 }
01488 }
01489 }
01490
01491
01492 if(bestCluster)
01493 {
01494
01495 possibleClusterSystem.push_back(bestCluster->Group);
01496
01497
01498 const float threshold= 0.05f;
01499 shortDist+= threshold;
01500
01501 float rayDist= (startPos - endPos).norm();
01502 shortDist= min(shortDist, rayDist);
01503 endPos+= (startPos - endPos).normed() * shortDist;
01504 }
01505 }
01506
01507
01508
01509
01510
01511
01512 if(possibleClusterSystem.empty())
01513 resultCS= NULL;
01514 else if(possibleClusterSystem.size()==1)
01515 {
01516
01517 if(possibleClusterSystem[0]==RootCluster->getClusterSystem())
01518 resultCS= NULL;
01519
01520 else
01521 resultCS= possibleClusterSystem[0];
01522 }
01523
01524 else
01525 {
01526
01527 CInstanceGroup *highest= NULL;
01528 uint highestLevel= 0;
01529 for(i=0;i<possibleClusterSystem.size();i++)
01530 {
01531 uint level= 0;
01532 CInstanceGroup *ig= possibleClusterSystem[i];
01533 while(ig)
01534 {
01535 ig= ig->getParentClusterSystem();
01536 level++;
01537 }
01538 if(level>=highestLevel)
01539 {
01540 highestLevel= level;
01541 highest= possibleClusterSystem[i];
01542 }
01543 }
01544
01545
01546 resultCS= highest;
01547 }
01548
01549 return resultCS;
01550 }
01551
01552
01553 void CScene::renderOcclusionTestMeshsWithCurrMaterial()
01554 {
01555 for(std::set<CTransform*>::iterator it = _Models.begin(); it != _Models.end(); ++it)
01556 {
01557 if ((*it)->isFlare())
01558 {
01559 CFlareModel *flare = NLMISC::safe_cast<CFlareModel *>(*it);
01560 flare->renderOcclusionTestMesh(*RenderTrav.getDriver());
01561 }
01562 }
01563 }
01564
01565
01566 void CScene::renderOcclusionTestMeshs()
01567 {
01568 nlassert(RenderTrav.getDriver());
01569 RenderTrav.getDriver()->setupViewport(RenderTrav.getViewport());
01570 RenderTrav.getDriver()->activeVertexProgram(NULL);
01571 IDriver::TPolygonMode oldPolygonMode = RenderTrav.getDriver()->getPolygonMode();
01572 CMaterial m;
01573 m.initUnlit();
01574 m.setColor(CRGBA(255, 255, 255, 127));
01575 m.setBlend(true);
01576 m.setDstBlend(CMaterial::invsrcalpha);
01577 m.setSrcBlend(CMaterial::srcalpha);
01578 m.setZWrite(false);
01579 RenderTrav.getDriver()->setupMaterial(m);
01580 getDriver()->setPolygonMode(IDriver::Filled);
01581 renderOcclusionTestMeshsWithCurrMaterial();
01582 m.setColor(CRGBA::Black);
01583 RenderTrav.getDriver()->setupMaterial(m);
01584 getDriver()->setPolygonMode(IDriver::Line);
01585 renderOcclusionTestMeshsWithCurrMaterial();
01586 getDriver()->setPolygonMode(oldPolygonMode);
01587 }
01588
01589
01590
01591 void CScene::updateWaterEnvMaps(TGlobalAnimationTime time)
01592 {
01593 IDriver *drv = getDriver();
01594 nlassert(drv);
01595 if (_WaterEnvMap)
01596 {
01597 _WaterEnvMap->update(time, *drv);
01598 }
01599 }
01600
01601
01602
01603 void CScene::addSSSModelRequest(const class CSSSModelRequest &req)
01604 {
01605 _SSSModelRequests.push_back(req);
01606 }
01607
01608
01609 void CScene::flushSSSModelRequests()
01610 {
01611 for(uint i=0;i<_SSSModelRequests.size();i++)
01612 {
01613 _SSSModelRequests[i].execute();
01614 }
01615 _SSSModelRequests.clear();
01616 }
01617
01618
01619 }
01620
01621
01622
01623
01624
01625
01626
01627
01628
01629
01630
01631
01632
01633
01634
01635
01636
01637
01638
01639
01640