1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2013-2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "nel/3d/scene.h"
23 #include "nel/3d/trav_scene.h"
24 #include "nel/3d/hrc_trav.h"
25 #include "nel/3d/clip_trav.h"
26 #include "nel/3d/light_trav.h"
27 #include "nel/3d/anim_detail_trav.h"
28 #include "nel/3d/load_balancing_trav.h"
29 #include "nel/3d/render_trav.h"
30 #include "nel/3d/transform.h"
31 #include "nel/3d/camera.h"
32 #include "nel/3d/landscape_model.h"
33 #include "nel/3d/driver.h"
34 #include "nel/3d/transform_shape.h"
35 #include "nel/3d/mesh_base.h"
36 #include "nel/3d/mesh_base_instance.h"
37 #include "nel/3d/mesh_instance.h"
38 #include "nel/3d/mesh_mrm_instance.h"
39 #include "nel/3d/mesh_mrm_skinned_instance.h"
40 #include "nel/3d/mesh_multi_lod_instance.h"
41 #include "nel/3d/shape_bank.h"
42 #include "nel/3d/skeleton_model.h"
43 #include "nel/3d/particle_system_model.h"
44 #include "nel/3d/coarse_mesh_manager.h"
45 #include "nel/3d/cluster.h"
46 #include "nel/3d/scene_group.h"
47 #include "nel/3d/flare_model.h"
48 #include "nel/3d/water_model.h"
49 #include "nel/3d/vegetable_blend_layer_model.h"
50 #include "nel/3d/root_model.h"
51 #include "nel/3d/point_light_model.h"
52 #include "nel/3d/animation.h"
53 #include "nel/3d/lod_character_manager.h"
54 #include "nel/3d/seg_remanence.h"
55 #include "nel/3d/async_texture_manager.h"
56 #include "nel/3d/water_env_map.h"
57 #include "nel/3d/skeleton_spawn_script.h"
62 #include "nel/misc/time_nl.h"
63 #include "nel/misc/file.h"
64 #include "nel/misc/path.h"
67 #include "nel/misc/system_info.h"
70 using namespace NLMISC
;
76 #define NL3D_SCENE_COARSE_MANAGER_TEXTURE "nel_coarse_texture.tga"
79 // The manager is limited to a square of 3000m*3000m around the camera. Beyond, models are clipped individually (bad!!).
80 const float NL3D_QuadGridClipManagerRadiusMax
= 1500;
81 const float NL3D_QuadGridClipClusterSize
= 400;
82 const uint NL3D_QuadGridClipNumDist
= 10;
83 const float NL3D_QuadGridClipMaxDist
= 1000;
86 #define NL3D_SCENE_DEFAULT_SHADOW_MAP_SIZE 64
87 #define NL3D_SCENE_DEFAULT_SHADOW_MAP_BLUR_SIZE 2
88 #define NL3D_SCENE_DEFAULT_SHADOW_MAP_DIST_FADE_START 40
89 #define NL3D_SCENE_DEFAULT_SHADOW_MAP_DIST_FADE_END 50
90 #define NL3D_SCENE_DEFAULT_SHADOW_MAP_MAX_CASTER_IN_SCREEN 16
91 #define NL3D_SCENE_DEFAULT_SHADOW_MAP_MAX_CASTER_AROUND 64
97 // ***************************************************************************
98 // ***************************************************************************
99 // ***************************************************************************
102 void CScene::registerBasics()
104 CTransform::registerBasic();
105 CCamera::registerBasic();
106 CMeshBaseInstance::registerBasic();
107 CMeshInstance::registerBasic();
108 CMeshMRMInstance::registerBasic();
109 CMeshMRMSkinnedInstance::registerBasic();
110 CLandscapeModel::registerBasic();
111 CTransformShape::registerBasic();
112 CSkeletonModel::registerBasic();
113 CParticleSystemModel::registerBasic() ;
114 CMeshMultiLodInstance::registerBasic();
115 CCluster::registerBasic();
116 CFlareModel::registerBasic();
117 CWaterModel::registerBasic();
118 CWaveMakerModel::registerBasic();
119 CVegetableBlendLayerModel::registerBasic();
120 CRootModel::registerBasic();
121 CPointLightModel::registerBasic();
122 CSegRemanence::registerBasic();
123 CQuadGridClipManager::registerBasic();
127 // ***************************************************************************
128 // ***************************************************************************
129 // ***************************************************************************
131 // ***************************************************************************
132 CScene::CScene(bool bSmallScene
) : LightTrav(bSmallScene
)
135 ClipTrav
.Scene
= this;
136 LightTrav
.Scene
= this;
137 AnimDetailTrav
.Scene
= this;
138 LoadBalancingTrav
.Scene
= this;
139 RenderTrav
.Scene
= this;
145 SonsOfAncestorSkeletonModelGroup
= NULL
;
146 _QuadGridClipManager
= NULL
;
151 _FirstAnimateCall
= true ;
153 _LightingSystemEnabled
= false;
154 _CoarseMeshLightingUpdate
= 50;
156 _GlobalWindDirection
.set(1,0,0);
157 // Default as Sithikt wants.
158 _GlobalWindPower
= 0.2f
;
160 // global manager (created in CDriverUser)
161 _LodCharacterManager
= NULL
;
162 _AsyncTextureManager
= NULL
;
166 _MaxSkeletonsInNotCLodForm
= 20;
168 _FilterRenderFlags
= std::numeric_limits
<uint32
>::max();
170 _NextRenderProfile
= false;
172 // Init default _CoarseMeshManager
173 _CoarseMeshManager
= new CCoarseMeshManager
;
174 _CoarseMeshManager
->setTextureFile (NL3D_SCENE_COARSE_MANAGER_TEXTURE
);
176 // Update model list to NULL
177 _UpdateModelList
= NULL
;
181 _ShadowMapTextureSize
= NL3D_SCENE_DEFAULT_SHADOW_MAP_SIZE
;
182 _ShadowMapBlurSize
= NL3D_SCENE_DEFAULT_SHADOW_MAP_BLUR_SIZE
;
183 _ShadowMapDistFadeStart
= NL3D_SCENE_DEFAULT_SHADOW_MAP_DIST_FADE_START
;
184 _ShadowMapDistFadeEnd
= NL3D_SCENE_DEFAULT_SHADOW_MAP_DIST_FADE_END
;
185 _ShadowMapMaxCasterInScreen
= NL3D_SCENE_DEFAULT_SHADOW_MAP_MAX_CASTER_IN_SCREEN
;
186 _ShadowMapMaxCasterAround
= NL3D_SCENE_DEFAULT_SHADOW_MAP_MAX_CASTER_AROUND
;
187 _VisualCollisionManagerForShadow
= NULL
;
189 _WaterCallback
= NULL
;
190 _PolyDrawingCallback
= NULL
;
191 _IsRendering
= false;
194 _RenderedPart
= UScene::RenderNothing
;
195 //_WaterEnvMapRdr = NULL;
196 //_WaterEnvMap = new CTextureCube;
200 _GlobalSystemTime
= 0.0;
202 _RequestParticlesAnimate
= false;
204 // ***************************************************************************
205 void CScene::release()
207 // reset the _QuadGridClipManager, => unlink models, and delete clusters.
208 if( _QuadGridClipManager
)
209 _QuadGridClipManager
->reset();
211 // First, delete models.
212 set
<CTransform
*>::iterator it
;
214 while( it
!=_Models
.end())
217 // Don't delete The Roots, because used, for instance in ~CSkeletonModel()
218 if(tr
!=Root
&& tr
!=RootCluster
&& tr
!=SonsOfAncestorSkeletonModelGroup
)
220 // temp erase from the list
223 // NB: important to take begin(), and not it++, cause ~CSkeletonModel() may delete ScriptSpawned models
227 // Then delete the roots
229 if(Root
) _Models
.insert(Root
);
230 if(RootCluster
) _Models
.insert(RootCluster
);
231 if(SonsOfAncestorSkeletonModelGroup
) _Models
.insert(SonsOfAncestorSkeletonModelGroup
);
232 // delete in the reverse order of initDefaultRoots()
233 if(SonsOfAncestorSkeletonModelGroup
)
235 deleteModel(SonsOfAncestorSkeletonModelGroup
);
236 SonsOfAncestorSkeletonModelGroup
= NULL
;
240 deleteModel(RootCluster
);
250 _UpdateModelList
= NULL
;
256 SonsOfAncestorSkeletonModelGroup
= NULL
;
258 _QuadGridClipManager
= NULL
;
259 ClipTrav
.setQuadGridClipManager(NULL
);
261 // DON'T reset the _LodCharacterManager, because it can be shared across scenes
263 if(_LodCharacterManager)
264 _LodCharacterManager->reset();
266 _LodCharacterManager
= NULL
;
268 // delete the coarseMeshManager
269 if(_CoarseMeshManager
)
271 delete _CoarseMeshManager
;
272 _CoarseMeshManager
= NULL
;
275 if(_GlobalInstanceGroup
)
277 delete _GlobalInstanceGroup
;
278 _GlobalInstanceGroup
= NULL
;
281 // delete the play list
282 _LMAnimsAuto
.deleteAll();
284 // ***************************************************************************
289 // ***************************************************************************
290 void CScene::initDefaultRoots()
292 // Create and set root the default models.
293 Root
= static_cast<CTransform
*>(createModel(TransformId
));
295 // The root is always freezed (never move).
298 // Init the instance group that represent the world
299 _GlobalInstanceGroup
= new CInstanceGroup
;
300 RootCluster
= (CCluster
*)createModel (ClusterId
);
302 RootCluster
->hrcUnlink();
303 RootCluster
->Name
= "ClusterRoot";
304 RootCluster
->Group
= _GlobalInstanceGroup
;
305 _GlobalInstanceGroup
->addCluster (RootCluster
);
307 // init the ClipTrav.RootCluster.
308 ClipTrav
.RootCluster
= RootCluster
;
310 // Create a SonsOfAncestorSkeletonModelGroup, for models which have a skeleton ancestor
311 SonsOfAncestorSkeletonModelGroup
= static_cast<CRootModel
*>(createModel(RootModelId
));
312 // must unlink it from all traversals, because special, only used in CClipTrav::traverse()
313 SonsOfAncestorSkeletonModelGroup
->hrcUnlink();
314 Root
->clipDelChild(SonsOfAncestorSkeletonModelGroup
);
317 // ***************************************************************************
318 void CScene::initQuadGridClipManager ()
320 // Init clip features.
321 if( !_QuadGridClipManager
)
324 _QuadGridClipManager
= static_cast<CQuadGridClipManager
*>(createModel(QuadGridClipManagerId
));
325 // unlink it from hrc, and link it only to RootCluster.
326 // NB: hence the quadGridClipManager may be clipped by the cluster system
327 _QuadGridClipManager
->hrcUnlink();
328 _QuadGridClipManager
->clipUnlinkFromAll();
329 RootCluster
->clipAddChild(_QuadGridClipManager
);
331 // init _QuadGridClipManager.
332 _QuadGridClipManager
->init(NL3D_QuadGridClipClusterSize
,
333 NL3D_QuadGridClipNumDist
,
334 NL3D_QuadGridClipMaxDist
,
335 NL3D_QuadGridClipManagerRadiusMax
);
340 // ***************************************************************************
341 void CScene::render(bool doHrcPass
)
344 renderPart(UScene::RenderAll
, doHrcPass
);
349 // ***************************************************************************
350 void CScene::beginPartRender()
352 nlassert(!_IsRendering
);
354 // Do not delete model during the rendering
355 // Also do not create model with CSkeletonSpawnScript model animation
357 _RenderedPart
= UScene::RenderNothing
;
362 // ***************************************************************************
363 void CScene::endPartRender(bool keepTrav
)
365 nlassert(_IsRendering
);
366 _IsRendering
= false;
370 // Delete model deleted during the rendering
372 for (i
=0; i
<_ToDelete
.size(); i
++)
373 deleteModel (_ToDelete
[i
]);
376 // Special for SkeletonSpawnScript animation. create models spawned now
377 flushSSSModelRequests();
379 // Particle system handling (remove the resources of those which are too far, as their clusters may not have been parsed).
380 // Note that only a few of them are tested at each call
381 _ParticleSystemManager
.refreshModels(ClipTrav
.WorldFrustumPyramid
, ClipTrav
.CamPos
);
383 // Waiting Instance handling
384 double deltaT
= _DeltaSystemTimeBetweenRender
;
385 clamp (deltaT
, 0.01, 0.1);
386 updateWaitingInstances(deltaT
);
390 _NextRenderProfile
= false;
392 IDriver
*drv
= getDriver();
393 drv
->activeVertexProgram(NULL
);
394 drv
->activePixelProgram(NULL
);
395 drv
->activeGeometryProgram(NULL
);
397 // Ensure nothing animates on subsequent renders
401 uint64 total = PSStatsRegisterPSModelObserver +
402 PSStatsRemovePSModelObserver +
403 PSStatsUpdateOpacityInfos +
404 PSStatsUpdateLightingInfos +
407 PSStatsReleasePSPointer +
408 PSStatsRefreshRscDeletion +
410 PSStatsReleaseRscAndInvalidate +
411 PSStatsGetNumTriangles +
412 PSStatsCheckAgainstPyramid +
413 PSStatsTraverseAnimDetail +
415 PSStatsTraverseRender +
416 PSStatsTraverseClip +
417 PSStatsCheckDestroyCondition +
418 PSStatsForceInstanciate +
419 PSStatsDoAnimatePart1 +
420 PSStatsDoAnimatePart2 +
421 PSStatsDoAnimatePart3 +
422 PSStatsTraverseAnimDetailPart1 +
423 PSStatsTraverseAnimDetailPart2 +
424 PSStatsTraverseAnimDetailPart3 +
425 PSStatsTraverseAnimDetailPart4 +
439 if (((double) total / (double) NLMISC::CSystemInfo::getProcessorFrequency()) > 0.01)
441 nlinfo("***** PS STATS ****");
442 #define PS_STATS(var) \
443 nlinfo("time for " #var " = %.2f", (float) (1000 * ((double) var / (double) CSystemInfo::getProcessorFrequency())));
445 PS_STATS(PSStatsRegisterPSModelObserver)
446 PS_STATS(PSStatsRemovePSModelObserver)
447 PS_STATS(PSStatsUpdateOpacityInfos)
448 PS_STATS(PSStatsUpdateLightingInfos)
449 PS_STATS(PSStatsGetAABBox)
450 PS_STATS(PSStatsReallocRsc)
451 PS_STATS(PSStatsReleasePSPointer)
452 PS_STATS(PSStatsRefreshRscDeletion)
453 PS_STATS(PSStatsReleaseRsc)
454 PS_STATS(PSStatsReleaseRscAndInvalidate)
455 PS_STATS(PSStatsGetNumTriangles)
456 PS_STATS(PSStatsCheckAgainstPyramid)
457 PS_STATS(PSStatsTraverseAnimDetail)
458 PS_STATS(PSStatsDoAnimate)
459 PS_STATS(PSStatsTraverseRender)
460 PS_STATS(PSStatsTraverseClip)
461 PS_STATS(PSStatsClipSystemInstanciated);
462 PS_STATS(PSStatsClipSystemNotInstanciated);
463 PS_STATS(PSStatsClipSystemCheckAgainstPyramid);
464 PS_STATS(PSStatsInsertInVisibleList);
465 PS_STATS(PSStatsCheckDestroyCondition)
466 PS_STATS(PSStatsForceInstanciate)
467 PS_STATS(PSStatsDoAnimatePart1)
468 PS_STATS(PSStatsDoAnimatePart2)
469 PS_STATS(PSStatsDoAnimatePart3)
470 PS_STATS(PSStatsTraverseAnimDetailPart1)
471 PS_STATS(PSStatsTraverseAnimDetailPart2)
472 PS_STATS(PSStatsTraverseAnimDetailPart3)
473 PS_STATS(PSStatsTraverseAnimDetailPart4)
485 PS_STATS(PSStatsZonePlane)
486 PS_STATS(PSStatsZoneSphere)
487 PS_STATS(PSStatsZoneDisc)
488 PS_STATS(PSStatsZoneRectangle)
489 PS_STATS(PSStatsZoneCylinder)
494 PS_STATS(PSStatCollision)
496 PS_STATS(PSStatRender)
499 nlinfo("num do animate = %d", (int) PSStatsNumDoAnimateCalls);
501 nlinfo("Max et = %.2f", PSMaxET);
502 nlinfo("Max ps nb pass = %d", (int) PSMaxNBPass);
508 PSStatsRegisterPSModelObserver = 0;
509 PSStatsRemovePSModelObserver = 0;
510 PSStatsUpdateOpacityInfos = 0;
511 PSStatsUpdateLightingInfos = 0;
512 PSStatsGetAABBox = 0;
513 PSStatsReallocRsc = 0;
514 PSStatsReleasePSPointer = 0;
515 PSStatsRefreshRscDeletion = 0;
516 PSStatsReleaseRsc = 0;
517 PSStatsReleaseRscAndInvalidate = 0;
518 PSStatsGetNumTriangles = 0;
519 PSStatsCheckAgainstPyramid = 0;
520 PSStatsTraverseAnimDetail = 0;
521 PSStatsDoAnimate = 0;
522 PSStatsTraverseRender = 0;
523 PSStatsTraverseClip = 0;
524 PSStatsCheckDestroyCondition = 0;
525 PSStatsForceInstanciate = 0;
526 PSStatsClipSystemInstanciated = 0;
527 PSStatsClipSystemNotInstanciated = 0;
528 PSStatsClipSystemCheckAgainstPyramid = 0;
529 PSStatsInsertInVisibleList = 0;
530 PSStatsDoAnimatePart1 = 0;
531 PSStatsDoAnimatePart2 = 0;
532 PSStatsDoAnimatePart3 = 0;
533 PSStatsTraverseAnimDetailPart1 = 0;
534 PSStatsTraverseAnimDetailPart2 = 0;
535 PSStatsTraverseAnimDetailPart3 = 0;
536 PSStatsTraverseAnimDetailPart4 = 0;
537 PSStatsNumDoAnimateCalls = 0;
551 PSStatsZonePlane = 0;
552 PSStatsZoneSphere = 0;
554 PSStatsZoneRectangle = 0;
555 PSStatsZoneCylinder = 0;
567 // ***************************************************************************
568 void CScene::renderPart(UScene::TRenderPart rp
, bool doHrcPass
, bool doTrav
, bool keepTrav
)
570 nlassert(_IsRendering
);
572 // if nothing (????), abort
573 if(rp
==UScene::RenderNothing
)
576 // If part asked already rendered, abort
577 nlassert((rp
& _RenderedPart
) == 0); // cannot render the same part twice during a render
579 // if first part to be rendered, do the start stuff
580 if (_RenderedPart
== UScene::RenderNothing
)
582 RenderTrav
.clearWaterModelList();
586 // update water envmap
587 //updateWaterEnvmap();
590 double fNewGlobalSystemTime
= NLMISC::CTime::ticksToSecond(NLMISC::CTime::getPerformanceTime());
591 if(_GlobalSystemTime
==0)
592 _DeltaSystemTimeBetweenRender
= 0.020;
594 _DeltaSystemTimeBetweenRender
= fNewGlobalSystemTime
- _GlobalSystemTime
;
595 _GlobalSystemTime
= fNewGlobalSystemTime
;
600 nlassert(CurrentCamera
);
605 // Use the camera to setup Clip / Render pass.
606 float left
, right
, bottom
, top
, znear
, zfar
;
607 CurrentCamera
->getFrustum(left
, right
, bottom
, top
, znear
, zfar
);
609 // setup basic camera.
610 ClipTrav
.setFrustum(left
, right
, bottom
, top
, znear
, zfar
, CurrentCamera
->isPerspective());
612 RenderTrav
.setFrustum (left
, right
, bottom
, top
, znear
, zfar
, CurrentCamera
->isPerspective());
613 RenderTrav
.setViewport (_Viewport
);
615 LoadBalancingTrav
.setFrustum (left
, right
, bottom
, top
, znear
, zfar
, CurrentCamera
->isPerspective());
618 // Set Infos for cliptrav.
619 ClipTrav
.Camera
= CurrentCamera
;
620 ClipTrav
.setQuadGridClipManager (_QuadGridClipManager
);
623 // **** For all render traversals, traverse them (except the Hrc one), in ascending order.
627 HrcTrav
._MovingObjects
.clear();
629 // Set Cam World Matrix for all trav that need it
630 ClipTrav
.setCamMatrix(CurrentCamera
->getWorldMatrix());
631 RenderTrav
.setCamMatrix (CurrentCamera
->getWorldMatrix());
632 LoadBalancingTrav
.setCamMatrix (CurrentCamera
->getWorldMatrix());
638 AnimDetailTrav
.traverse();
641 LoadBalancingTrav
.traverse();
646 if (_RequestParticlesAnimate
)
648 _ParticleSystemManager
.processAnimate(_EllapsedTime
); // deals with permanently animated particle systems
649 _RequestParticlesAnimate
= false;
654 LightTrav
.traverse();
658 RenderTrav
.traverse(rp
, (_RenderedPart
== UScene::RenderNothing
), doTrav
);
661 // Always must clear shadow caster (if render did not work because of IDriver::isLost())
662 RenderTrav
.getShadowMapManager().clearAllShadowCasters();
666 if (rp
& UScene::RenderFlare
)
672 IDriver
*drv
= getDriver();
673 CFlareModel::updateOcclusionQueryBegin(drv
);
674 CFlareModel
*currFlare
= _FirstFlare
;
677 currFlare
->updateOcclusionQuery(drv
);
678 currFlare
= currFlare
->Next
;
681 CFlareModel::updateOcclusionQueryEnd(drv
);
689 _RenderedPart
= (UScene::TRenderPart
) (_RenderedPart
| rp
);
692 // ***************************************************************************
693 void CScene::updateWaitingInstances(double systemTimeEllapsed
)
695 // First set up max AGP upload
696 double fMaxBytesToUp
= 100 * 256 * 256 * systemTimeEllapsed
;
697 _ShapeBank
->setMaxBytesToUpload ((uint32
)fMaxBytesToUp
);
698 // Parse all the waiting instance
699 _ShapeBank
->processWaitingShapes (); // Process waiting shapes load shape, texture, and lightmaps
700 // and upload all maps to VRAM pieces by pieces
701 TWaitingInstancesMMap::iterator wimmIt
= _WaitingInstances
.begin();
702 while( wimmIt
!= _WaitingInstances
.end() )
704 CShapeBank::TShapeState st
= _ShapeBank
->getPresentState (wimmIt
->first
);
705 if (st
== CShapeBank::AsyncLoad_Error
)
707 // Delete the waiting instance - Nobody can be informed of that...
708 TWaitingInstancesMMap::iterator itDel
= wimmIt
;
710 _WaitingInstances
.erase(itDel
);
712 else if (st
== CShapeBank::Present
)
714 // Then create a reference to the shape
715 *(wimmIt
->second
) = _ShapeBank
->addRef(wimmIt
->first
)->createInstance (*this);
716 // Delete the waiting instance
717 TWaitingInstancesMMap::iterator itDel
= wimmIt
;
719 _WaitingInstances
.erase(itDel
);
721 else // st == CShapeBank::NotPresent or loading
728 // ***************************************************************************
729 void CScene::setDriver(IDriver
*drv
)
731 RenderTrav
.setDriver(drv
);
734 // ***************************************************************************
735 IDriver
*CScene::getDriver() const
737 return (const_cast<CScene
*>(this))->RenderTrav
.getDriver();
741 // ***************************************************************************
742 // ***************************************************************************
744 // ***************************************************************************
745 // ***************************************************************************
747 // ***************************************************************************
749 void CScene::setShapeBank(CShapeBank
*pShapeBank
)
751 _ShapeBank
= pShapeBank
;
754 // ***************************************************************************
756 CTransformShape
*CScene::createInstance(const string
&shapeName
)
758 // We must attach a bank to the scene (a ShapeBank handle the shape caches and
759 // the creation/deletion of the instances)
760 nlassert( _ShapeBank
!= NULL
);
762 // If the shape is not present in the bank
763 if (_ShapeBank
->getPresentState( shapeName
) != CShapeBank::Present
)
766 _ShapeBank
->load( shapeName
);
767 if (_ShapeBank
->getPresentState( shapeName
) != CShapeBank::Present
)
772 // Then create a reference to the shape
773 CTransformShape
*pTShp
= _ShapeBank
->addRef( shapeName
)->createInstance(*this);
774 if (pTShp
) pTShp
->setDistMax(pTShp
->Shape
->getDistMax());
776 // Look if this instance get lightmap information
777 #if defined(__GNUC__) && __GNUC__ < 3
778 CMeshBase
*pMB
= pTShp
? (CMeshBase
*)((IShape
*)(pTShp
->Shape
)) : NULL
;
780 CMeshBase
*pMB
= pTShp
? dynamic_cast<CMeshBase
*>((IShape
*)(pTShp
->Shape
)) : NULL
;
782 CMeshBaseInstance
*pMBI
= dynamic_cast<CMeshBaseInstance
*>( pTShp
);
783 if( ( pMB
!= NULL
) && ( pMBI
!= NULL
) )
785 // Init lightmap information
786 pMBI
->initAnimatedLightIndex (*this);
789 //==========================
791 if (_AutomaticAnimationSet
)
793 if (pMB
->getAutoAnim())
796 std::string animName
= toLowerAscii(CFile::getFilenameWithoutExtension(shapeName
));
797 uint animID
= _AutomaticAnimationSet
->getAnimationIdByName(animName
);
798 if (animID
!= CAnimationSet::NotFound
)
800 CChannelMixer
*chanMix
= new CChannelMixer
;
801 chanMix
->setAnimationSet((CAnimationSet
*) _AutomaticAnimationSet
);
802 chanMix
->setSlotAnimation(0, animID
);
804 pMBI
->registerToChannelMixer(chanMix
, "");
805 // Gives this object ownership of the channel mixer so we don't need to keep track of it
806 pMBI
->setChannelMixerOwnerShip(true);
812 CLandscapeModel
*pLM
= dynamic_cast<CLandscapeModel
*>( pTShp
);
815 // Init lightmap information
816 pLM
->Landscape
.initAnimatedLightIndex (*this);
822 // ***************************************************************************
824 void CScene::createInstanceAsync(const string
&shapeName
, CTransformShape
**pInstance
, const NLMISC::CVector
&position
, uint selectedTexture
)
826 // We must attach a bank to the scene (a ShapeBank handle the shape caches and
827 // the creation/deletion of the instances)
828 nlassert( _ShapeBank
!= NULL
);
830 // Add the instance request
831 _WaitingInstances
.insert(TWaitingInstancesMMap::value_type(shapeName
,pInstance
));
832 // If the shape is not present in the bank
833 if (_ShapeBank
->getPresentState( shapeName
) != CShapeBank::Present
)
835 // Load it from file asynchronously
836 _ShapeBank
->loadAsync( toLowerAscii(shapeName
), getDriver(), position
, NULL
, selectedTexture
);
840 // ***************************************************************************
841 void CScene::deleteInstance(CTransformShape
*pTrfmShp
)
844 if( pTrfmShp
== NULL
)
847 pShp
= pTrfmShp
->Shape
;
849 deleteModel( pTrfmShp
);
853 // Even if model already deleted by smarptr the release function works
854 _ShapeBank
->release( pShp
);
859 // ***************************************************************************
860 void CScene::animate( TGlobalAnimationTime atTime
)
863 if (_FirstAnimateCall
)
867 // dummy value for first frame
868 _EllapsedTime
= 0.01f
;
869 _FirstAnimateCall
= false ;
873 _EllapsedTime
= (float) (atTime
- _RealTime
);
874 //nlassert(_EllapsedTime >= 0);
875 if (_EllapsedTime
< 0.0f
) // NT WorkStation PATCH (Yes you are not dreaming
876 _EllapsedTime
= 0.01f
; // deltaTime can be less than zero!!)
877 _EllapsedTime
= fabsf(_EllapsedTime
);
879 _CurrentTime
+= _EllapsedTime
;
882 _LMAnimsAuto
.animate( atTime
);
884 // Change PointLightFactors of all pointLights in registered Igs.
887 // First list all current AnimatedLightmaps (for faster vector iteration per ig)
888 const uint count
= (uint
)_AnimatedLightPtr
.size ();
890 for (i
=0; i
<count
; i
++)
892 // Blend final colors
893 _AnimatedLightPtr
[i
]->updateGroupColors (*this);
896 // For all registered igs.
897 ItAnimatedIgSet itAnIgSet
;
898 for(itAnIgSet
= _AnimatedIgSet
.begin(); itAnIgSet
!=_AnimatedIgSet
.end(); itAnIgSet
++)
900 CInstanceGroup
*ig
= *itAnIgSet
;
902 // Set the light factor
903 ig
->setPointLightFactor(*this);
906 // Rendered part are invalidate
907 _RenderedPart
= UScene::RenderNothing
;
909 // Particles are animated later due to dependencies
910 _RequestParticlesAnimate
= true;
914 // ***************************************************************************
915 float CScene::getNbFaceAsked () const
917 return LoadBalancingTrav
.getNbFaceAsked ();
921 // ***************************************************************************
922 void CScene::setGroupLoadMaxPolygon(const std::string
&group
, uint nFaces
)
924 nFaces
= max(nFaces
, (uint
)1);
925 LoadBalancingTrav
.setGroupNbFaceWanted(group
, nFaces
);
927 // ***************************************************************************
928 uint
CScene::getGroupLoadMaxPolygon(const std::string
&group
)
930 return LoadBalancingTrav
.getGroupNbFaceWanted(group
);
932 // ***************************************************************************
933 float CScene::getGroupNbFaceAsked (const std::string
&group
) const
935 return LoadBalancingTrav
.getGroupNbFaceAsked(group
);
940 // ***************************************************************************
941 void CScene::setPolygonBalancingMode(TPolygonBalancingMode polBalMode
)
943 LoadBalancingTrav
.PolygonBalancingMode
= (CLoadBalancingGroup::TPolygonBalancingMode
)(uint
)polBalMode
;
947 // ***************************************************************************
948 CScene::TPolygonBalancingMode
CScene::getPolygonBalancingMode() const
950 return (CScene::TPolygonBalancingMode
)(uint
)LoadBalancingTrav
.PolygonBalancingMode
;
953 // ***************************************************************************
954 void CScene::setLayersRenderingOrder(bool directOrder
/*= true*/)
956 RenderTrav
.setLayersRenderingOrder(directOrder
);
959 // ***************************************************************************
960 bool CScene::getLayersRenderingOrder() const
962 return RenderTrav
.getLayersRenderingOrder();
965 // ***************************************************************************
966 CParticleSystemManager
&CScene::getParticleSystemManager()
968 return _ParticleSystemManager
;
971 // ***************************************************************************
972 void CScene::enableElementRender(UScene::TRenderFilter elt
, bool state
)
975 _FilterRenderFlags
|= (uint32
)elt
;
977 _FilterRenderFlags
&= ~(uint32
)elt
;
981 // ***************************************************************************
982 // ***************************************************************************
984 // ***************************************************************************
985 // ***************************************************************************
988 // ***************************************************************************
989 void CScene::enableLightingSystem(bool enable
)
991 _LightingSystemEnabled
= enable
;
993 // Set to RenderTrav and LightTrav
994 RenderTrav
.LightingSystemEnabled
= _LightingSystemEnabled
;
995 LightTrav
.LightingSystemEnabled
= _LightingSystemEnabled
;
999 // ***************************************************************************
1000 void CScene::setAmbientGlobal(NLMISC::CRGBA ambient
)
1002 RenderTrav
.AmbientGlobal
= ambient
;
1004 void CScene::setSunAmbient(NLMISC::CRGBA ambient
)
1006 RenderTrav
.SunAmbient
= ambient
;
1008 void CScene::setSunDiffuse(NLMISC::CRGBA diffuse
)
1010 RenderTrav
.SunDiffuse
= diffuse
;
1012 void CScene::setSunSpecular(NLMISC::CRGBA specular
)
1014 RenderTrav
.SunSpecular
= specular
;
1016 void CScene::setSunDirection(const NLMISC::CVector
&direction
)
1018 RenderTrav
.setSunDirection(direction
);
1022 // ***************************************************************************
1023 NLMISC::CRGBA
CScene::getAmbientGlobal() const
1025 return RenderTrav
.AmbientGlobal
;
1027 NLMISC::CRGBA
CScene::getSunAmbient() const
1029 return RenderTrav
.SunAmbient
;
1031 NLMISC::CRGBA
CScene::getSunDiffuse() const
1033 return RenderTrav
.SunDiffuse
;
1035 NLMISC::CRGBA
CScene::getSunSpecular() const
1037 return RenderTrav
.SunSpecular
;
1039 NLMISC::CVector
CScene::getSunDirection() const
1041 return RenderTrav
.getSunDirection();
1045 // ***************************************************************************
1046 void CScene::setMaxLightContribution(uint nlights
)
1048 LightTrav
.LightingManager
.setMaxLightContribution(nlights
);
1050 uint
CScene::getMaxLightContribution() const
1052 return LightTrav
.LightingManager
.getMaxLightContribution();
1055 void CScene::setLightTransitionThreshold(float lightTransitionThreshold
)
1057 LightTrav
.LightingManager
.setLightTransitionThreshold(lightTransitionThreshold
);
1059 float CScene::getLightTransitionThreshold() const
1061 return LightTrav
.LightingManager
.getLightTransitionThreshold();
1065 // ***************************************************************************
1066 void CScene::addInstanceGroupForLightAnimation(CInstanceGroup
*ig
)
1069 nlassert( _AnimatedIgSet
.find(ig
) == _AnimatedIgSet
.end() );
1070 _AnimatedIgSet
.insert(ig
);
1073 // ***************************************************************************
1074 void CScene::removeInstanceGroupForLightAnimation(CInstanceGroup
*ig
)
1077 ItAnimatedIgSet itIg
= _AnimatedIgSet
.find(ig
);
1078 if ( itIg
!= _AnimatedIgSet
.end() )
1079 _AnimatedIgSet
.erase(itIg
);
1083 // ***************************************************************************
1084 void CScene::setCoarseMeshLightingUpdate(uint8 period
)
1086 _CoarseMeshLightingUpdate
= max((uint8
)1, period
);
1090 // ***************************************************************************
1091 // ***************************************************************************
1093 // ***************************************************************************
1094 // ***************************************************************************
1096 // ***************************************************************************
1097 void CScene::setGlobalWindPower(float gwp
)
1099 _GlobalWindPower
= gwp
;
1101 // ***************************************************************************
1102 void CScene::setGlobalWindDirection(const CVector
&gwd
)
1104 _GlobalWindDirection
= gwd
;
1105 _GlobalWindDirection
.z
= 0;
1106 _GlobalWindDirection
.normalize();
1110 // ***************************************************************************
1111 // ***************************************************************************
1113 // ***************************************************************************
1114 // ***************************************************************************
1116 // ***************************************************************************
1117 CScene::ItSkeletonModelList
CScene::appendSkeletonModelToList(CSkeletonModel
*skel
)
1119 _SkeletonModelList
.push_front(skel
);
1120 return _SkeletonModelList
.begin();
1123 // ***************************************************************************
1124 void CScene::eraseSkeletonModelToList(CScene::ItSkeletonModelList it
)
1126 _SkeletonModelList
.erase(it
);
1129 // ***************************************************************************
1130 void CScene::registerShadowCasterToList(CTransform
*sc
)
1133 _ShadowCasterList
.push_front(sc
);
1134 sc
->_ItShadowCasterInScene
= _ShadowCasterList
.begin();
1137 // ***************************************************************************
1138 void CScene::unregisterShadowCasterToList(CTransform
*sc
)
1141 _ShadowCasterList
.erase(sc
->_ItShadowCasterInScene
);
1145 // ***************************************************************************
1146 // ***************************************************************************
1147 // Old CMOT integrated methods
1148 // ***************************************************************************
1149 // ***************************************************************************
1152 // ***************************************************************************
1153 set
<CScene::CModelEntry
> CScene::_RegModels
;
1156 // ***************************************************************************
1157 void CScene::registerModel(const CClassId
&idModel
, const CClassId
&idModelBase
, CTransform
* (*creator
)())
1159 nlassert(idModel
!=CClassId::Null
);
1161 // idModelBase may be Null...
1164 e
.BaseModelId
= idModelBase
;
1168 // Insert/replace e.
1169 _RegModels
.erase(e
);
1170 _RegModels
.insert(e
);
1174 // ***************************************************************************
1175 CTransform
*CScene::createModel(const CClassId
&idModel
)
1177 nlassert(idModel
!=CClassId::Null
);
1181 set
<CModelEntry
>::iterator itModel
;
1182 itModel
= _RegModels
.find(e
);
1184 if(itModel
==_RegModels
.end())
1186 nlstop
; // Warning, CScene::registerBasics () has not been called !
1191 CTransform
*m
= (*itModel
).Creator();
1194 // Set the owner for the model.
1195 m
->_OwnerScene
= this;
1197 // link model to Root in HRC and in clip. NB: if exist!! (case for the Root and RootCluster :) )
1200 Root
->hrcLinkSon(m
);
1201 Root
->clipAddChild(m
);
1204 // Insert the model into the set.
1207 // By default the model is update() in CScene::updateModels().
1208 m
->linkToUpdateList();
1210 // Once the model is correclty created, finish init him.
1213 // Ensure all the Traversals has enough space for visible list.
1214 ClipTrav
.reserveVisibleList((uint
)_Models
.size());
1215 AnimDetailTrav
.reserveVisibleList((uint
)_Models
.size());
1216 LoadBalancingTrav
.reserveVisibleList((uint
)_Models
.size());
1217 LightTrav
.reserveLightedList((uint
)_Models
.size());
1218 RenderTrav
.reserveRenderList((uint
)_Models
.size());
1223 // ***************************************************************************
1224 void CScene::deleteModel(CTransform
*model
)
1229 // No model delete during the render
1232 // add ot list of object to delete
1233 _ToDelete
.push_back (model
);
1234 // remove this object from the RenderTrav, hence it won't be displayed
1235 // still animDetail/Light/LoadBalance it. This is useless, but very rare
1236 // and I prefer doing like this than to add a NULL ptr Test in each Traversal (which I then must do in CRenderTrav)
1237 RenderTrav
.removeRenderModel(model
);
1242 set
<CTransform
*>::iterator it
= _Models
.find(model
);
1243 if(it
!=_Models
.end())
1252 // ***************************************************************************
1253 void CScene::updateModels()
1255 // check all the models which must be checked.
1256 CTransform
*model
= _UpdateModelList
;
1260 // next to update. get next now, because model->update() may remove model from the list.
1261 next
= model
->_NextModelToUpdate
;
1263 // update the model.
1272 // ***************************************************************************
1273 void CScene::setLightGroupColor(uint lightmapGroup
, NLMISC::CRGBA color
)
1275 // If too small, resize with white
1276 if (lightmapGroup
>= _LightGroupColor
.size ())
1278 _LightGroupColor
.resize (lightmapGroup
+1, CRGBA::White
);
1282 _LightGroupColor
[lightmapGroup
] = color
;
1286 // ***************************************************************************
1287 sint
CScene::getAnimatedLightNameToIndex (const std::string
&name
) const
1289 std::map
<std::string
, uint
>::const_iterator ite
= _AnimatedLightNameToIndex
.find (name
);
1290 if (ite
!= _AnimatedLightNameToIndex
.end ())
1291 return (sint
)ite
->second
;
1297 // ***************************************************************************
1298 void CScene::setAutomaticAnimationSet(CAnimationSet
*as
)
1300 // Backup the animation set
1301 _AutomaticAnimationSet
= as
;
1303 // Delete all auto lightmap animations
1304 _LMAnimsAuto
.deleteAll();
1305 _AnimatedLightNameToIndex
.clear();
1306 _AnimatedLight
.clear();
1307 _AnimatedLightPtr
.clear();
1308 _LightGroupColor
.clear();
1310 // Register each animation as lightmap
1311 const uint count
= _AutomaticAnimationSet
->getNumAnimation();
1313 for (i
=0; i
<count
; i
++)
1315 // Pointer on the animation
1316 CAnimation
*pAnim
= _AutomaticAnimationSet
->getAnimation(i
);
1319 // Reset the automatic animation if no animation wanted
1322 _AnimatedLight.clear();
1323 _AnimatedLightPtr.clear();
1324 _AnimatedLightNameToIndex.clear();
1325 nAnimNb = _LightmapAnimations.getAnimationIdByName("Automatic");
1326 if( nAnimNb != CAnimationSet::NotFound )
1328 CAnimation *anim = _LightmapAnimations.getAnimation( nAnimNb );
1331 _LightmapAnimations.reset();
1332 _LMAnimsAuto.deleteAll();
1337 set
<string
> setTrackNames
;
1338 pAnim
->getTrackNames( setTrackNames
);
1340 // nAnimNb = _LightmapAnimations.addAnimation( "Automatic", pAnim );
1341 // _LightmapAnimations.build();
1343 set
<string
>::iterator itSel
= setTrackNames
.begin();
1344 while ( itSel
!= setTrackNames
.end() )
1346 string ate
= *itSel
;
1347 if( strncmp( itSel
->c_str(), "LightmapController.", 19 ) == 0 )
1350 const char *lightName
= strrchr ((*itSel
).c_str (), '.')+1;
1352 // Light animation doesn't exist ?
1353 if (_AnimatedLightNameToIndex
.find (lightName
) == _AnimatedLightNameToIndex
.end())
1355 // Channel mixer for light anim
1356 CChannelMixer
*cm
= new CChannelMixer();
1357 cm
->setAnimationSet( _AutomaticAnimationSet
);
1359 // Add an automatic animation
1360 _AnimatedLight
.push_back ( CAnimatedLightmap ((uint
)_LightGroupColor
.size ()) );
1361 _AnimatedLightPtr
.push_back ( &_AnimatedLight
.back () );
1362 _AnimatedLightNameToIndex
.insert ( std::map
<std::string
, uint
>::value_type (lightName
, (uint32
)_AnimatedLightPtr
.size ()-1 ) );
1363 CAnimatedLightmap
&animLM
= _AnimatedLight
.back ();
1364 animLM
.setName( *itSel
);
1366 cm
->addChannel( animLM
.getName(), &animLM
, animLM
.getValue(CAnimatedLightmap::FactorValue
),
1367 animLM
.getDefaultTrack(CAnimatedLightmap::FactorValue
), CAnimatedLightmap::FactorValue
,
1368 CAnimatedLightmap::OwnerBit
, false);
1370 // Animated lightmap playlist
1371 CAnimationPlaylist
*pl
= new CAnimationPlaylist();
1372 pl
->setAnimation( 0, i
);
1373 pl
->setWrapMode( 0, CAnimationPlaylist::Repeat
);
1374 _LMAnimsAuto
.addPlaylist(pl
,cm
);
1383 // ***************************************************************************
1384 // ***************************************************************************
1386 // ***************************************************************************
1387 // ***************************************************************************
1389 // ***************************************************************************
1390 void CScene::profileNextRender()
1392 _NextRenderProfile
= true;
1399 // ***************************************************************************
1400 void CScene::setShadowMapTextureSize(uint size
)
1402 size
= max(size
, 2U);
1403 size
= raiseToNextPowerOf2(size
);
1404 _ShadowMapTextureSize
= size
;
1407 // ***************************************************************************
1408 void CScene::setShadowMapBlurSize(uint bs
)
1410 _ShadowMapBlurSize
= bs
;
1413 // ***************************************************************************
1414 void CScene::enableShadowPolySmooth(bool enable
)
1416 RenderTrav
.getShadowMapManager().enableShadowPolySmooth(enable
);
1419 // ***************************************************************************
1420 bool CScene::getEnableShadowPolySmooth() const
1422 return RenderTrav
.getShadowMapManager().getEnableShadowPolySmooth();
1426 // ***************************************************************************
1427 void CScene::setShadowMapDistFadeStart(float dist
)
1429 _ShadowMapDistFadeStart
= max(0.f
, dist
);
1431 // ***************************************************************************
1432 void CScene::setShadowMapDistFadeEnd(float dist
)
1434 _ShadowMapDistFadeEnd
= max(0.f
, dist
);
1436 // ***************************************************************************
1437 void CScene::setShadowMapMaxCasterInScreen(uint num
)
1439 _ShadowMapMaxCasterInScreen
= num
;
1441 // ***************************************************************************
1442 void CScene::setShadowMapMaxCasterAround(uint num
)
1444 _ShadowMapMaxCasterAround
= num
;
1447 // ***************************************************************************
1448 CInstanceGroup
*CScene::findCameraClusterSystemFromRay(CInstanceGroup
*startClusterSystem
,
1449 const NLMISC::CVector
&startPos
, NLMISC::CVector
&endPos
)
1451 CInstanceGroup
*resultCS
= NULL
;
1453 CClipTrav
&clipTrav
= getClipTrav();
1455 // **** Search all cluster where the startPos is in
1456 static vector
<CCluster
*> vCluster
;
1459 bool bInWorld
= true;
1460 clipTrav
.Accel
.select (startPos
, startPos
);
1461 CQuadGrid
<CCluster
*>::CIterator itAcc
= clipTrav
.Accel
.begin();
1462 while (itAcc
!= clipTrav
.Accel
.end())
1464 CCluster
*pCluster
= *itAcc
;
1465 if( pCluster
->Group
== startClusterSystem
&&
1466 pCluster
->isIn (startPos
) )
1468 vCluster
.push_back (pCluster
);
1475 vCluster
.push_back (RootCluster
);
1478 // **** Do a traverse starting from each start cluser, clipping the ray instead of the camera pyramid
1480 static vector
<CCluster
*> vClusterVisited
;
1481 vClusterVisited
.clear();
1482 for(i
=0;i
<vCluster
.size();i
++)
1484 vCluster
[i
]->cameraRayClip(startPos
, endPos
, vClusterVisited
);
1487 // **** From each cluster, select possible clusterSystem
1488 static vector
<CInstanceGroup
*> possibleClusterSystem
;
1489 possibleClusterSystem
.clear();
1490 for(i
=0;i
<vClusterVisited
.size();i
++)
1492 // select only cluster where the EndPos lies in. Important else in landscape, we'll always say
1493 // that we are in a Son Cluster.
1494 if(vClusterVisited
[i
]->isIn(endPos
))
1496 CInstanceGroup
*cs
= vClusterVisited
[i
]->Group
;
1497 // insert if not exist (NB: 1,2 possible clusterSystem so O(N2) is OK)
1499 for(j
=0;j
<possibleClusterSystem
.size();j
++)
1501 if(possibleClusterSystem
[j
]==cs
)
1504 if(j
==possibleClusterSystem
.size())
1505 possibleClusterSystem
.push_back(cs
);
1509 // If no cluster found, then we may be in a "Data Error case".
1510 // In this case, ensure the Camera position in a cluster
1511 if(possibleClusterSystem
.empty())
1513 CCluster
*bestCluster
= NULL
;
1514 float shortDist
= FLT_MAX
;
1516 for(i
=0;i
<vClusterVisited
.size();i
++)
1518 // if the ray is at least partially in this cluster
1519 CVector a
= startPos
;
1521 if(vClusterVisited
[i
]->clipSegment(a
, b
))
1523 float dist
= (endPos
- b
).norm();
1526 bestCluster
= vClusterVisited
[i
];
1535 // append the best one to the possible Cluster System
1536 possibleClusterSystem
.push_back(bestCluster
->Group
);
1538 // and modify endPos, so the camera will really lies into this cluster
1539 const float threshold
= 0.05f
;
1540 shortDist
+= threshold
;
1541 // must not goes more than startPos!
1542 float rayDist
= (startPos
- endPos
).norm();
1543 shortDist
= min(shortDist
, rayDist
);
1544 endPos
+= (startPos
- endPos
).normed() * shortDist
;
1548 // NB: still possible that the possibleClusterSystem is empty, if not in any cluster for instance :)
1551 // **** From each possible clusterSystem, select the one that is the lower in hierarchy
1553 if(possibleClusterSystem
.empty())
1555 else if(possibleClusterSystem
.size()==1)
1557 // if it is the rootCluster set NULL (should have the same behavior but do like standard case)
1558 if(possibleClusterSystem
[0]==RootCluster
->getClusterSystem())
1560 // set this cluster system
1562 resultCS
= possibleClusterSystem
[0];
1567 // compute the hierarchy level of each cluster system, take the highest
1568 CInstanceGroup
*highest
= NULL
;
1569 uint highestLevel
= 0;
1570 for(i
=0;i
<possibleClusterSystem
.size();i
++)
1573 CInstanceGroup
*ig
= possibleClusterSystem
[i
];
1576 ig
= ig
->getParentClusterSystem();
1579 if(level
>=highestLevel
)
1581 highestLevel
= level
;
1582 highest
= possibleClusterSystem
[i
];
1586 // set the highest cluster system
1593 // ***************************************************************************
1594 void CScene::renderOcclusionTestMeshsWithCurrMaterial()
1596 for(std::set
<CTransform
*>::iterator it
= _Models
.begin(); it
!= _Models
.end(); ++it
)
1598 if ((*it
)->isFlare())
1600 CFlareModel
*flare
= NLMISC::safe_cast
<CFlareModel
*>(*it
);
1601 flare
->renderOcclusionTestMesh(*RenderTrav
.getDriver());
1606 // ***************************************************************************
1607 void CScene::renderOcclusionTestMeshs()
1609 nlassert(RenderTrav
.getDriver());
1610 RenderTrav
.getDriver()->setupViewport(RenderTrav
.getViewport());
1611 RenderTrav
.getDriver()->activeVertexProgram(NULL
);
1612 RenderTrav
.getDriver()->activePixelProgram(NULL
);
1613 RenderTrav
.getDriver()->activeGeometryProgram(NULL
);
1614 IDriver::TPolygonMode oldPolygonMode
= RenderTrav
.getDriver()->getPolygonMode();
1617 m
.setColor(CRGBA(255, 255, 255, 127));
1619 m
.setDstBlend(CMaterial::invsrcalpha
);
1620 m
.setSrcBlend(CMaterial::srcalpha
);
1622 RenderTrav
.getDriver()->setupMaterial(m
);
1623 getDriver()->setPolygonMode(IDriver::Filled
);
1624 renderOcclusionTestMeshsWithCurrMaterial();
1625 m
.setColor(CRGBA::Black
);
1626 RenderTrav
.getDriver()->setupMaterial(m
);
1627 getDriver()->setPolygonMode(IDriver::Line
);
1628 renderOcclusionTestMeshsWithCurrMaterial();
1629 getDriver()->setPolygonMode(oldPolygonMode
);
1633 // ***************************************************************************
1634 void CScene::updateWaterEnvMaps(TGlobalAnimationTime time
)
1636 IDriver
*drv
= getDriver();
1640 _WaterEnvMap
->update(time
, *drv
);
1645 // ***************************************************************************
1646 void CScene::addSSSModelRequest(const class CSSSModelRequest
&req
)
1648 _SSSModelRequests
.push_back(req
);
1651 // ***************************************************************************
1652 void CScene::flushSSSModelRequests()
1654 for(uint i
=0;i
<_SSSModelRequests
.size();i
++)
1656 _SSSModelRequests
[i
].execute();
1658 _SSSModelRequests
.clear();