scene.cpp

Go to the documentation of this file.
00001 
00005 /* Copyright, 2000 Nevrax Ltd.
00006  *
00007  * This file is part of NEVRAX NEL.
00008  * NEVRAX NEL is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2, or (at your option)
00011  * any later version.
00012 
00013  * NEVRAX NEL is distributed in the hope that it will be useful, but
00014  * WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00016  * General Public License for more details.
00017 
00018  * You should have received a copy of the GNU General Public License
00019  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00020  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00021  * MA 02111-1307, USA.
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 // The manager is limited to a square of 3000m*3000m around the camera. Beyond, models are clipped individually (bad!!).
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     // Default as Sithikt wants.
00158     _GlobalWindPower= 0.2f;
00159 
00160     // global manager (created in CDriverUser)
00161     _LodCharacterManager= NULL;
00162     _AsyncTextureManager= NULL;
00163 
00164     _NumRender = 0;
00165 
00166     _MaxSkeletonsInNotCLodForm= 20;
00167 
00168     _FilterRenderFlags= ~0;
00169 
00170     _NextRenderProfile= false;
00171 
00172     // Init default _CoarseMeshManager
00173     _CoarseMeshManager= new CCoarseMeshManager;
00174     _CoarseMeshManager->setTextureFile (NL3D_SCENE_COARSE_MANAGER_TEXTURE);
00175 
00176     // Update model list to NULL
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     //_WaterEnvMapRdr = NULL;
00196     //_WaterEnvMap = new CTextureCube;
00197 
00198     _WaterEnvMap = NULL;
00199 
00200     _GlobalSystemTime= 0.0;
00201 }
00202 // ***************************************************************************
00203 void    CScene::release()
00204 {
00205     // reset the _QuadGridClipManager, => unlink models, and delete clusters.
00206     if( _QuadGridClipManager )
00207         _QuadGridClipManager->reset();
00208 
00209     // First, delete models.
00210     set<CTransform*>::iterator  it;
00211     it= _Models.begin();
00212     while( it!=_Models.end())
00213     {
00214         CTransform  *tr= *it;
00215         // Don't delete The Roots, because used, for instance in ~CSkeletonModel()
00216         if(tr!=Root && tr!=RootCluster && tr!=SonsOfAncestorSkeletonModelGroup)
00217             deleteModel(tr);
00218         // temp erase from the list
00219         else
00220             _Models.erase(it);
00221         // NB: important to take begin(), and not it++, cause ~CSkeletonModel() may delete ScriptSpawned models
00222         it= _Models.begin();
00223     }
00224 
00225     // Then delete the roots
00226     // reinsert
00227     if(Root)                                    _Models.insert(Root);
00228     if(RootCluster)                             _Models.insert(RootCluster);
00229     if(SonsOfAncestorSkeletonModelGroup)        _Models.insert(SonsOfAncestorSkeletonModelGroup);
00230     // delete in the reverse order of initDefaultRoots()
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     // No models at all.
00248     _UpdateModelList= NULL;
00249 
00250     // reset ptrs
00251     _ShapeBank = NULL;
00252     Root= NULL;
00253     RootCluster= NULL;
00254     SonsOfAncestorSkeletonModelGroup= NULL;
00255     CurrentCamera= NULL;
00256     _QuadGridClipManager= NULL;
00257     ClipTrav.setQuadGridClipManager(NULL);
00258 
00259     // DON'T reset the _LodCharacterManager, because it can be shared across scenes
00260     /*
00261     if(_LodCharacterManager)
00262         _LodCharacterManager->reset();
00263     */
00264     _LodCharacterManager= NULL;
00265 
00266     // delete the coarseMeshManager
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     // delete the play list
00280     _LMAnimsAuto.deleteAll();
00281 }
00282 // ***************************************************************************
00283 CScene::~CScene()
00284 {
00285     release();
00286 }
00287 // ***************************************************************************
00288 void    CScene::initDefaultRoots()
00289 {
00290     // Create and set root the default models.
00291     Root= static_cast<CTransform*>(createModel(TransformId));
00292 
00293     // The root is always freezed (never move).
00294     Root->freeze();
00295 
00296     // Init the instance group that represent the world
00297     _GlobalInstanceGroup = new CInstanceGroup;
00298     RootCluster= (CCluster*)createModel (ClusterId);
00299     // unlink from hrc.
00300     RootCluster->hrcUnlink();
00301     RootCluster->Name = "ClusterRoot";
00302     RootCluster->Group = _GlobalInstanceGroup;
00303     _GlobalInstanceGroup->addCluster (RootCluster);
00304 
00305     // init the ClipTrav.RootCluster.
00306     ClipTrav.RootCluster = RootCluster;
00307 
00308     // Create a SonsOfAncestorSkeletonModelGroup, for models which have a skeleton ancestor
00309     SonsOfAncestorSkeletonModelGroup= static_cast<CRootModel*>(createModel(RootModelId));
00310     // must unlink it from all traversals, because special, only used in CClipTrav::traverse()
00311     SonsOfAncestorSkeletonModelGroup->hrcUnlink();
00312     Root->clipDelChild(SonsOfAncestorSkeletonModelGroup);
00313 }
00314 
00315 // ***************************************************************************
00316 void    CScene::initQuadGridClipManager ()
00317 {
00318     // Init clip features.
00319     if( !_QuadGridClipManager )
00320     {
00321         // create the model
00322         _QuadGridClipManager= static_cast<CQuadGridClipManager*>(createModel(QuadGridClipManagerId));
00323         // unlink it from hrc, and link it only to RootCluster.
00324         // NB: hence the quadGridClipManager may be clipped by the cluster system
00325         _QuadGridClipManager->hrcUnlink();
00326         _QuadGridClipManager->clipUnlinkFromAll();
00327         RootCluster->clipAddChild(_QuadGridClipManager);
00328 
00329         // init _QuadGridClipManager.
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     // Do not delete model during the rendering
00353     // Also do not create model with CSkeletonSpawnScript model animation
00354     _IsRendering = true;
00355     _RenderedPart= UScene::RenderNothing;
00356 
00357 }
00358 
00359 
00360 // ***************************************************************************
00361 void    CScene::endPartRender()
00362 {
00363     nlassert(_IsRendering);
00364 
00365     // Delete model deleted during the rendering
00366     _IsRendering = false;
00367     uint i;
00368     for (i=0; i<_ToDelete.size(); i++)
00369         deleteModel (_ToDelete[i]);
00370     _ToDelete.clear ();
00371 
00372     // Special for SkeletonSpawnScript animation. create models spawned now
00373     flushSSSModelRequests();
00374 
00375     // Particle system handling (remove the resources of those which are too far, as their clusters may not have been parsed).
00376     // Note that only a few of them are tested at each call
00377     _ParticleSystemManager.refreshModels(ClipTrav.WorldFrustumPyramid, ClipTrav.CamPos);
00378 
00379     // Waiting Instance handling
00380     double deltaT = _DeltaSystemTimeBetweenRender;
00381     clamp (deltaT, 0.01, 0.1);
00382     updateWaitingInstances(deltaT);
00383 
00384     // Reset profiling
00385     _NextRenderProfile= false;
00386 
00387 
00388     /*
00389     uint64 total = PSStatsRegisterPSModelObserver +
00390                   PSStatsRemovePSModelObserver +
00391                   PSStatsUpdateOpacityInfos +
00392                   PSStatsUpdateLightingInfos +
00393                   PSStatsGetAABBox +
00394                   PSStatsReallocRsc +
00395                   PSStatsReleasePSPointer +
00396                   PSStatsRefreshRscDeletion +
00397                   PSStatsReleaseRsc +
00398                   PSStatsReleaseRscAndInvalidate +
00399                   PSStatsGetNumTriangles +
00400                   PSStatsCheckAgainstPyramid +
00401                   PSStatsTraverseAnimDetail +
00402                   PSStatsDoAnimate +
00403                   PSStatsTraverseRender +
00404                   PSStatsTraverseClip +
00405                   PSStatsCheckDestroyCondition +
00406                   PSStatsForceInstanciate +
00407                   PSStatsDoAnimatePart1 +
00408                   PSStatsDoAnimatePart2 +
00409                   PSStatsDoAnimatePart3 +
00410                   PSStatsTraverseAnimDetailPart1 +
00411                   PSStatsTraverseAnimDetailPart2 +
00412                   PSStatsTraverseAnimDetailPart3 +
00413                   PSStatsTraverseAnimDetailPart4 +
00414                   PSAnim1 +
00415                   PSAnim2+
00416                   PSAnim3+
00417                   PSAnim4+
00418                   PSAnim5+
00419                   PSAnim6+
00420                   PSAnim7+
00421                   PSAnim8+
00422                   PSAnim9+
00423                   PSAnim10+
00424                   PSAnim11;
00425 
00426 
00427      if (((double) total / (double) NLMISC::CSystemInfo::getProcessorFrequency()) > 0.01)
00428      {
00429           nlinfo("***** PS STATS ****");
00430           #define PS_STATS(var) \
00431           nlinfo("time for " #var " = %.2f", (float) (1000 * ((double) var / (double) CSystemInfo::getProcessorFrequency())));
00432 
00433           PS_STATS(PSStatsRegisterPSModelObserver)
00434           PS_STATS(PSStatsRemovePSModelObserver)
00435           PS_STATS(PSStatsUpdateOpacityInfos)
00436           PS_STATS(PSStatsUpdateLightingInfos)
00437           PS_STATS(PSStatsGetAABBox)
00438           PS_STATS(PSStatsReallocRsc)
00439           PS_STATS(PSStatsReleasePSPointer)
00440           PS_STATS(PSStatsRefreshRscDeletion)
00441           PS_STATS(PSStatsReleaseRsc)
00442           PS_STATS(PSStatsReleaseRscAndInvalidate)
00443           PS_STATS(PSStatsGetNumTriangles)
00444           PS_STATS(PSStatsCheckAgainstPyramid)
00445           PS_STATS(PSStatsTraverseAnimDetail)
00446           PS_STATS(PSStatsDoAnimate)
00447           PS_STATS(PSStatsTraverseRender)
00448           PS_STATS(PSStatsTraverseClip)
00449           PS_STATS(PSStatsClipSystemInstanciated);
00450           PS_STATS(PSStatsClipSystemNotInstanciated);
00451           PS_STATS(PSStatsClipSystemCheckAgainstPyramid);
00452           PS_STATS(PSStatsInsertInVisibleList);
00453           PS_STATS(PSStatsCheckDestroyCondition)
00454           PS_STATS(PSStatsForceInstanciate)
00455           PS_STATS(PSStatsDoAnimatePart1)
00456           PS_STATS(PSStatsDoAnimatePart2)
00457           PS_STATS(PSStatsDoAnimatePart3)
00458           PS_STATS(PSStatsTraverseAnimDetailPart1)
00459           PS_STATS(PSStatsTraverseAnimDetailPart2)
00460           PS_STATS(PSStatsTraverseAnimDetailPart3)
00461           PS_STATS(PSStatsTraverseAnimDetailPart4)
00462           PS_STATS(PSAnim1)
00463           PS_STATS(PSAnim2)
00464           PS_STATS(PSAnim3)
00465           PS_STATS(PSAnim4)
00466           PS_STATS(PSAnim5)
00467           PS_STATS(PSAnim6)
00468           PS_STATS(PSAnim7)
00469           PS_STATS(PSAnim8)
00470           PS_STATS(PSAnim9)
00471           PS_STATS(PSAnim10)
00472           PS_STATS(PSAnim11)
00473           PS_STATS(PSStatsZonePlane)
00474           PS_STATS(PSStatsZoneSphere)
00475           PS_STATS(PSStatsZoneDisc)
00476           PS_STATS(PSStatsZoneRectangle)
00477           PS_STATS(PSStatsZoneCylinder)
00478           PS_STATS(PSMotion1)
00479           PS_STATS(PSMotion2)
00480           PS_STATS(PSMotion3)
00481           PS_STATS(PSMotion4)
00482           PS_STATS(PSStatCollision)
00483           PS_STATS(PSStatEmit)
00484           PS_STATS(PSStatRender)
00485 
00486 
00487         nlinfo("num do animate = %d", (int) PSStatsNumDoAnimateCalls);
00488 
00489         nlinfo("Max et = %.2f", PSMaxET);
00490         nlinfo("Max ps nb pass = %d", (int) PSMaxNBPass);
00491 
00492         PS_STATS(total)
00493 
00494      }
00495 
00496      PSStatsRegisterPSModelObserver = 0;
00497      PSStatsRemovePSModelObserver = 0;
00498      PSStatsUpdateOpacityInfos = 0;
00499      PSStatsUpdateLightingInfos = 0;
00500      PSStatsGetAABBox = 0;
00501      PSStatsReallocRsc = 0;
00502      PSStatsReleasePSPointer = 0;
00503      PSStatsRefreshRscDeletion = 0;
00504      PSStatsReleaseRsc = 0;
00505      PSStatsReleaseRscAndInvalidate = 0;
00506      PSStatsGetNumTriangles = 0;
00507      PSStatsCheckAgainstPyramid = 0;
00508      PSStatsTraverseAnimDetail = 0;
00509      PSStatsDoAnimate = 0;
00510      PSStatsTraverseRender = 0;
00511      PSStatsTraverseClip = 0;
00512      PSStatsCheckDestroyCondition = 0;
00513      PSStatsForceInstanciate = 0;
00514      PSStatsClipSystemInstanciated = 0;
00515      PSStatsClipSystemNotInstanciated = 0;
00516      PSStatsClipSystemCheckAgainstPyramid = 0;
00517      PSStatsInsertInVisibleList = 0;
00518      PSStatsDoAnimatePart1 = 0;
00519      PSStatsDoAnimatePart2 = 0;
00520      PSStatsDoAnimatePart3 = 0;
00521      PSStatsTraverseAnimDetailPart1 = 0;
00522      PSStatsTraverseAnimDetailPart2 = 0;
00523      PSStatsTraverseAnimDetailPart3 = 0;
00524      PSStatsTraverseAnimDetailPart4 = 0;
00525      PSStatsNumDoAnimateCalls = 0;
00526      PSAnim1 = 0;
00527      PSAnim2 = 0;
00528      PSAnim3 = 0;
00529      PSAnim4 = 0;
00530      PSAnim5 = 0;
00531      PSAnim6 = 0;
00532      PSAnim7 = 0;
00533      PSAnim8 = 0;
00534      PSAnim9 = 0;
00535      PSAnim10 = 0;
00536      PSAnim11 = 0;
00537      PSMaxET = 0.f;
00538      PSMaxNBPass = 0;
00539      PSStatsZonePlane = 0;
00540      PSStatsZoneSphere = 0;
00541      PSStatsZoneDisc = 0;
00542      PSStatsZoneRectangle = 0;
00543      PSStatsZoneCylinder = 0;
00544      PSMotion1 = 0;
00545      PSMotion2 = 0;
00546      PSMotion3 = 0;
00547      PSMotion4 = 0;
00548      PSStatCollision = 0;
00549      PSStatEmit = 0;
00550      PSStatRender = 0;
00551      */
00552 }
00553 
00554 
00555 // ***************************************************************************
00556 void    CScene::renderPart(UScene::TRenderPart rp, bool doHrcPass)
00557 {
00558     nlassert(_IsRendering);
00559 
00560     // if nothing (????), abort
00561     if(rp==UScene::RenderNothing)
00562         return;
00563 
00564     // If part asked already rendered, abort
00565     nlassert((rp & _RenderedPart) == 0); // cannot render the same part twice during a render
00566 
00567     // if first part to be rendered, do the start stuff
00568     if (_RenderedPart == UScene::RenderNothing)
00569     {
00570         // update water envmap
00571         //updateWaterEnvmap();
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         // update models.
00587         updateModels();
00588 
00589         // Use the camera to setup Clip / Render pass.
00590         float left, right, bottom, top, znear, zfar;
00591         CurrentCamera->getFrustum(left, right, bottom, top, znear, zfar);
00592 
00593         // setup basic camera.
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         // Set Infos for cliptrav.
00603         ClipTrav.Camera = CurrentCamera;
00604         ClipTrav.setQuadGridClipManager (_QuadGridClipManager);
00605 
00606 
00607         // **** For all render traversals, traverse them (except the Hrc one), in ascending order.
00608         if( doHrcPass )
00609             HrcTrav.traverse();
00610 
00611         // Set Cam World Matrix for all trav that need it
00612         ClipTrav.setCamMatrix(CurrentCamera->getWorldMatrix());
00613         RenderTrav.setCamMatrix (CurrentCamera->getWorldMatrix());
00614         LoadBalancingTrav.setCamMatrix (CurrentCamera->getWorldMatrix());
00615 
00616 
00617         // clip
00618         ClipTrav.traverse();
00619         // animDetail
00620         AnimDetailTrav.traverse();
00621         // loadBalance
00622         LoadBalancingTrav.traverse();
00623         //
00624         _ParticleSystemManager.processAnimate(_EllapsedTime); // deals with permanently animated particle systems
00625         // Light
00626         LightTrav.traverse();
00627     }
00628 
00629     // render
00630     RenderTrav.traverse(rp, _RenderedPart == UScene::RenderNothing);
00631     // Always must clear shadow caster (if render did not work because of IDriver::isLost())
00632     RenderTrav.getShadowMapManager().clearAllShadowCasters();
00633 
00634     // render flare
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     // First set up max AGP upload
00658     double fMaxBytesToUp = 100 * 256 * 256 * systemTimeEllapsed;
00659     _ShapeBank->setMaxBytesToUpload ((uint32)fMaxBytesToUp);
00660     // Parse all the waiting instance
00661     _ShapeBank->processWaitingShapes ();    // Process waiting shapes load shape, texture, and lightmaps
00662                                             // and upload all maps to VRAM pieces by pieces
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             // Delete the waiting instance - Nobody can be informed of that...
00670             TWaitingInstancesMMap::iterator itDel= wimmIt;
00671             ++wimmIt;
00672             _WaitingInstances.erase(itDel);
00673         }
00674         else if (st == CShapeBank::Present)
00675         {
00676             // Then create a reference to the shape
00677             *(wimmIt->second) = _ShapeBank->addRef(wimmIt->first)->createInstance (*this);
00678             // Delete the waiting instance
00679             TWaitingInstancesMMap::iterator itDel= wimmIt;
00680             ++wimmIt;
00681             _WaitingInstances.erase(itDel);
00682         }
00683         else // st == CShapeBank::NotPresent or loading
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 // Shape mgt.
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     // We must attach a bank to the scene (a ShapeBank handle the shape caches and
00721     // the creation/deletion of the instances)
00722     nlassert( _ShapeBank != NULL );
00723 
00724     // If the shape is not present in the bank
00725     if (_ShapeBank->getPresentState( shapeName ) != CShapeBank::Present)
00726     {
00727         // Load it from file
00728         _ShapeBank->load( shapeName );
00729         if (_ShapeBank->getPresentState( shapeName ) != CShapeBank::Present)
00730         {
00731             return NULL;
00732         }
00733     }
00734     // Then create a reference to the shape
00735     CTransformShape *pTShp = _ShapeBank->addRef( shapeName )->createInstance(*this);
00736     if (pTShp) pTShp->setDistMax(pTShp->Shape->getDistMax());
00737 
00738     // Look if this instance get lightmap information
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         // Init lightmap information
00748         pMBI->initAnimatedLightIndex (*this);
00749 
00750         // Auto animations
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                     // Gives this object ownership of the channel mixer so we don't need to keep track of it
00768                     pMBI->setChannelMixerOwnerShip(true);
00769                 }
00770             }
00771         }
00772     }
00773 
00774     CLandscapeModel *pLM = dynamic_cast<CLandscapeModel*>( pTShp );
00775     if( pLM != NULL )
00776     {
00777         // Init lightmap information
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     // We must attach a bank to the scene (a ShapeBank handle the shape caches and
00789     // the creation/deletion of the instances)
00790     nlassert( _ShapeBank != NULL );
00791     *pInstance = NULL;
00792     // Add the instance request
00793     _WaitingInstances.insert(TWaitingInstancesMMap::value_type(shapeName,pInstance));
00794     // If the shape is not present in the bank
00795     if (_ShapeBank->getPresentState( shapeName ) != CShapeBank::Present)
00796     {
00797         // Load it from file asynchronously
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         // Even if model already deleted by smarptr the release function works
00816         _ShapeBank->release( pShp );
00817     }
00818 
00819 }
00820 
00821 // ***************************************************************************
00822 void CScene::animate( TGlobalAnimationTime atTime )
00823 {
00824     // todo hulud remove
00825     if (_FirstAnimateCall)
00826     {
00827         _InitTime = atTime;
00828         _RealTime = atTime;
00829         // dummy value for first frame
00830         _EllapsedTime = 0.01f ;
00831         _FirstAnimateCall = false ;
00832     }
00833     else
00834     {
00835         _EllapsedTime = (float) (atTime - _RealTime);
00836         //nlassert(_EllapsedTime >= 0);
00837         if (_EllapsedTime < 0.0f)   // NT WorkStation PATCH (Yes you are not dreaming
00838             _EllapsedTime = 0.01f;  // deltaTime can be less than zero!!)
00839         _EllapsedTime = fabsf(_EllapsedTime);
00840         _RealTime = atTime ;
00841         _CurrentTime += _EllapsedTime;
00842     }
00843 
00844     _LMAnimsAuto.animate( atTime );
00845 
00846     // Change PointLightFactors of all pointLights in registered Igs.
00847     //----------------
00848 
00849     // First list all current AnimatedLightmaps (for faster vector iteration per ig)
00850     const uint count = _AnimatedLightPtr.size ();
00851     uint i;
00852     for (i=0; i<count; i++)
00853     {
00854         // Blend final colors
00855         _AnimatedLightPtr[i]->updateGroupColors (*this);
00856     }
00857 
00858     // For all registered igs.
00859     ItAnimatedIgSet     itAnIgSet;
00860     for(itAnIgSet= _AnimatedIgSet.begin(); itAnIgSet!=_AnimatedIgSet.end(); itAnIgSet++)
00861     {
00862         CInstanceGroup  *ig= *itAnIgSet;
00863 
00864         // Set the light factor
00865         ig->setPointLightFactor(*this);
00866     }
00867 
00868     // Rendered part are invalidate
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 /*= true*/)
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 // Lighting Mgt.
00943 // ***************************************************************************
00944 // ***************************************************************************
00945 
00946 
00947 // ***************************************************************************
00948 void            CScene::enableLightingSystem(bool enable)
00949 {
00950     _LightingSystemEnabled= enable;
00951 
00952     // Set to RenderTrav and LightTrav
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 // Old CMOT integrated methods
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     // idModelBase may be Null...
01121 
01122     CModelEntry     e;
01123     e.BaseModelId= idModelBase;
01124     e.ModelId= idModel;
01125     e.Creator= creator;
01126 
01127     // Insert/replace e.
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;         // Warning, CScene::registerBasics () has not been called !
01146         return NULL;
01147     }
01148     else
01149     {
01150         CTransform  *m= (*itModel).Creator();
01151         if(!m)  return NULL;
01152 
01153         // Set the owner for the model.
01154         m->_OwnerScene= this;
01155 
01156         // link model to Root in HRC and in clip. NB: if exist!! (case for the Root and RootCluster :) )
01157         if(Root)
01158         {
01159             Root->hrcLinkSon(m);
01160             Root->clipAddChild(m);
01161         }
01162 
01163         // Insert the model into the set.
01164         _Models.insert(m);
01165 
01166         // By default the model is update() in CScene::updateModels().
01167         m->linkToUpdateList();
01168 
01169         // Once the model is correclty created, finish init him.
01170         m->initModel();
01171 
01172         // Ensure all the Traversals has enough space for visible list.
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     // No model delete during the render
01189     if (_IsRendering)
01190     {
01191         // add ot list of object to delete
01192         _ToDelete.push_back (model);
01193         // remove this object from the RenderTrav, hence it won't be displayed
01194         // still animDetail/Light/LoadBalance it. This is unuseful, but very rare
01195         // and I prefer doing like this than to add a NULL ptr Test in each Traversal (which I then must do in CRenderTrav)
01196         RenderTrav.removeRenderModel(model);
01197     }
01198     // standard delete
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     // check all the models which must be checked.
01215     CTransform  *model= _UpdateModelList;
01216     CTransform  *next;
01217     while( model )
01218     {
01219         // next to update. get next now, because model->update() may remove model from the list.
01220         next= model->_NextModelToUpdate;
01221 
01222         // update the model.
01223         model->update();
01224 
01225         // next.
01226         model= next;
01227     }
01228 }
01229 
01230 
01231 // ***************************************************************************
01232 void    CScene::setLightGroupColor(uint lightmapGroup, NLMISC::CRGBA color)
01233 {
01234     // If too small, resize with white
01235     if (lightmapGroup >= _LightGroupColor.size ())
01236     {
01237         _LightGroupColor.resize (lightmapGroup+1, CRGBA::White);
01238     }
01239 
01240     // Set the color
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     // Backup the animation set
01260     _AutomaticAnimationSet = as;
01261 
01262     // Delete all auto lightmap animations
01263     _LMAnimsAuto.deleteAll();
01264     _AnimatedLightNameToIndex.clear();
01265     _AnimatedLight.clear();
01266     _AnimatedLightPtr.clear();
01267     _LightGroupColor.clear();
01268 
01269     // Register each animation as lightmap
01270     const uint count = _AutomaticAnimationSet->getNumAnimation();
01271     uint i;
01272     for (i=0; i<count; i++)
01273     {
01274         // Pointer on the animation
01275         CAnimation *pAnim = _AutomaticAnimationSet->getAnimation(i);
01276 
01277 /*      uint nAnimNb;
01278         // Reset the automatic animation if no animation wanted
01279         if( pAnim == NULL )
01280         {
01281             _AnimatedLight.clear();
01282             _AnimatedLightPtr.clear();
01283             _AnimatedLightNameToIndex.clear();
01284             nAnimNb = _LightmapAnimations.getAnimationIdByName("Automatic");
01285             if( nAnimNb != CAnimationSet::NotFound )
01286             {
01287                 CAnimation *anim = _LightmapAnimations.getAnimation( nAnimNb );
01288                 delete anim;
01289             }
01290             _LightmapAnimations.reset();
01291             _LMAnimsAuto.deleteAll();
01292             return;
01293         }
01294         */
01295 
01296         set<string> setTrackNames;
01297         pAnim->getTrackNames( setTrackNames );
01298 
01299         // nAnimNb = _LightmapAnimations.addAnimation( "Automatic", pAnim );
01300         // _LightmapAnimations.build();
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                 // The light name
01309                 const char *lightName = strrchr ((*itSel).c_str (), '.')+1;
01310 
01311                 // Light animation doesn't exist ?
01312                 if (_AnimatedLightNameToIndex.find (lightName) == _AnimatedLightNameToIndex.end())
01313                 {
01314                     // Channel mixer for light anim
01315                     CChannelMixer *cm = new CChannelMixer();
01316                     cm->setAnimationSet( _AutomaticAnimationSet );
01317 
01318                     // Add an automatic animation
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                     // Animated lightmap playlist
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     // Reset All Stats.
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     // **** Search all cluster where the startPos is in
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     // **** Do a traverse starting from each start cluser, clipping the ray instead of the camera pyramid
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     // **** From each cluster, select possible clusterSystem
01447     static vector<CInstanceGroup*> possibleClusterSystem;
01448     possibleClusterSystem.clear();
01449     for(i=0;i<vClusterVisited.size();i++)
01450     {
01451         // select only cluster where the EndPos lies in. Important else in landscape, we'll always say
01452         // that we are in a Son Cluster.
01453         if(vClusterVisited[i]->isIn(endPos))
01454         {
01455             CInstanceGroup  *cs= vClusterVisited[i]->Group;
01456             // insert if not exist (NB: 1,2 possible clusterSystem so O(N2) is OK)
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     // If no cluster found, then we may be in a "Data Error case".
01469     // In this case, ensure the Camera position in a cluster
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             // if the ray is at least partially in this cluster
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         // if found
01492         if(bestCluster)
01493         {
01494             // append the best one to the possible Cluster System
01495             possibleClusterSystem.push_back(bestCluster->Group);
01496 
01497             // and modify endPos, so the camera will really lies into this cluster
01498             const float threshold= 0.05f;
01499             shortDist+= threshold;
01500             // must not goes more than startPos!
01501             float   rayDist= (startPos - endPos).norm();
01502             shortDist= min(shortDist, rayDist);
01503             endPos+= (startPos - endPos).normed() * shortDist;
01504         }
01505     }
01506 
01507     // NB: still possible that the possibleClusterSystem is empty, if not in any cluster for instance :)
01508 
01509 
01510     // **** From each possible clusterSystem, select the one that is the lower in hierarchy
01511     // common case
01512     if(possibleClusterSystem.empty())
01513         resultCS= NULL;
01514     else if(possibleClusterSystem.size()==1)
01515     {
01516         // if it is the rootCluster set NULL (should have the same behavior but do like standard case)
01517         if(possibleClusterSystem[0]==RootCluster->getClusterSystem())
01518             resultCS= NULL;
01519         // set this cluster system
01520         else
01521             resultCS= possibleClusterSystem[0];
01522     }
01523     // conflict case
01524     else
01525     {
01526         // compute the hierarchy level of each cluster system, take the highest
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         // set the highest cluster system
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 } // NL3D
01620 
01621 
01622 
01623 
01624 
01625 
01626 
01627 
01628 
01629 
01630 
01631 
01632 
01633 
01634 
01635 
01636 
01637 
01638 
01639 
01640 

Generated on Thu Jan 7 08:26:30 2010 for NeL by  doxygen 1.6.1