00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "std3d.h"
00025
00026 #include "nel/misc/types_nl.h"
00027 #include "nel/3d/clip_trav.h"
00028 #include "nel/3d/hrc_trav.h"
00029 #include "nel/3d/render_trav.h"
00030 #include "nel/3d/anim_detail_trav.h"
00031 #include "nel/3d/load_balancing_trav.h"
00032 #include "nel/3d/cluster.h"
00033 #include "nel/3d/scene_group.h"
00034 #include "nel/3d/transform_shape.h"
00035 #include "nel/3d/camera.h"
00036 #include "nel/3d/quad_grid_clip_cluster.h"
00037 #include "nel/3d/quad_grid_clip_manager.h"
00038 #include "nel/3d/root_model.h"
00039 #include "nel/misc/hierarchical_timer.h"
00040 #include "nel/3d/scene.h"
00041 #include "nel/3d/skeleton_model.h"
00042 #include "nel/misc/fast_floor.h"
00043
00044 using namespace std;
00045 using namespace NLMISC;
00046
00047
00048 namespace NL3D
00049 {
00050
00051
00052
00053 CClipTrav::CClipTrav() : ViewPyramid(6), WorldPyramid(6)
00054 {
00055 _VisibleList.resize(1024);
00056 _CurrentNumVisibleModels= 0;
00057 CurrentDate = 0;
00058 Accel.create (64, 16.0f);
00059
00060 ForceNoFrustumClip= false;
00061 _QuadGridClipManager= NULL;
00062 _TrackClusterVisibility= false;
00063 }
00064
00065
00066 CClipTrav::~CClipTrav()
00067 {
00068 }
00069
00070
00071 bool CClipTrav::fullSearch (vector<CCluster*>& vCluster, const CVector& pos)
00072 {
00073 CQuadGrid<CCluster*>::CIterator itAcc;
00074
00075
00076 bool bInWorld = true;
00077 Accel.select (pos, pos);
00078 itAcc = Accel.begin();
00079 while (itAcc != Accel.end())
00080 {
00081 CCluster *pCluster = *itAcc;
00082 if (pCluster->isIn (pos))
00083 {
00084 vCluster.push_back (pCluster);
00085 bInWorld = false;
00086 }
00087 ++itAcc;
00088 }
00089
00090
00091 if (bInWorld)
00092 {
00093 vCluster.push_back (RootCluster);
00094 }
00095
00096 else
00097 {
00098 uint i;
00099 std::set<CCluster*> parentExclude;
00100
00101
00102 for(i=0;i<vCluster.size();i++)
00103 {
00104 CCluster *cluster= vCluster[i];
00105 while(cluster->Father)
00106 {
00107 cluster= cluster->Father;
00108 parentExclude.insert(cluster);
00109 }
00110 }
00111
00112
00113 std::vector<CCluster*>::iterator it;
00114 for(it=vCluster.begin(); it!=vCluster.end();)
00115 {
00116 if(parentExclude.find(*it)!=parentExclude.end())
00117 it= vCluster.erase(it);
00118 else
00119 it++;
00120 }
00121 }
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143 return true;
00144 }
00145
00147 void CClipTrav::setClusterVisibilityTracking(bool track)
00148 {
00149 _TrackClusterVisibility = track;
00150 }
00152 bool CClipTrav::getClusterVisibilityTracking()
00153 {
00154 return _TrackClusterVisibility;
00155 }
00157 void CClipTrav::addVisibleCluster(CCluster *cluster)
00158 {
00159 _VisibleClusters.push_back(cluster);
00160 }
00164 const std::vector<CCluster*> &CClipTrav::getVisibleClusters()
00165 {
00166 return _VisibleClusters;
00167 }
00168
00169
00170
00171 void CClipTrav::traverse()
00172 {
00173 H_AUTO( NL3D_TravClip );
00174
00175
00176 CTransform *sceneRoot= Scene->getRoot();
00177
00178
00179 ++CurrentDate;
00180
00181 CTravCameraScene::update();
00182
00183
00184 CVector pfoc(0,0,0);
00185 CVector lb(Left, Near, Bottom );
00186 CVector lt(Left, Near, Top );
00187 CVector rb(Right, Near, Bottom );
00188 CVector rt(Right, Near, Top );
00189
00190 CVector lbFar(Left, Far, Bottom);
00191 CVector ltFar(Left, Far, Top );
00192 CVector rbFar(Right, Far, Bottom);
00193 CVector rtFar(Right, Far, Top );
00194
00195 uint32 i, j;
00196
00197 ViewPyramid[NL3D_CLIP_PLANE_NEAR].make(lt, lb, rt);
00198 ViewPyramid[NL3D_CLIP_PLANE_FAR].make(lbFar, ltFar, rtFar);
00199
00200 if(Perspective)
00201 {
00202 ViewPyramid[NL3D_CLIP_PLANE_LEFT].make(pfoc, lt, lb);
00203 ViewPyramid[NL3D_CLIP_PLANE_TOP].make(pfoc, rt, lt);
00204 ViewPyramid[NL3D_CLIP_PLANE_RIGHT].make(pfoc, rb, rt);
00205 ViewPyramid[NL3D_CLIP_PLANE_BOTTOM].make(pfoc, lb, rb);
00206 }
00207 else
00208 {
00209 ViewPyramid[NL3D_CLIP_PLANE_LEFT].make(lt, ltFar, lbFar);
00210 ViewPyramid[NL3D_CLIP_PLANE_TOP].make(lt, rtFar, ltFar);
00211 ViewPyramid[NL3D_CLIP_PLANE_RIGHT].make(rt, rbFar, rtFar);
00212 ViewPyramid[NL3D_CLIP_PLANE_BOTTOM].make(lb, lbFar, rbFar);
00213 }
00214
00215
00216
00217
00218 for (i = 0; i < 6; i++)
00219 {
00220 WorldPyramid[i]= ViewPyramid[i]*ViewMatrix;
00221 }
00222
00223
00224 WorldFrustumPyramid= WorldPyramid;
00225
00226
00227
00228 if(_QuadGridClipManager)
00229 {
00230 _QuadGridClipManager->updateClustersFromCamera(CamPos);
00231 }
00232
00233 H_BEFORE( NL3D_TravClip_ClearLists );
00234
00235
00236 Scene->getAnimDetailTrav().clearVisibleList();
00237 Scene->getLoadBalancingTrav().clearVisibleList();
00238 Scene->getLightTrav().clearLightedList();
00239 Scene->getRenderTrav().clearRenderList();
00240
00241 H_AFTER( NL3D_TravClip_ClearLists );
00242
00243
00244 H_BEFORE( NL3D_TravClip_ResetVisible );
00245
00246
00247
00248
00249
00250
00251
00252 for (i=0;i<_CurrentNumVisibleModels;i++)
00253 {
00254
00255 if( _VisibleList[i] )
00256 {
00257
00258 _VisibleList[i]->_Visible= false;
00259
00260 _VisibleList[i]->_IndexInVisibleList= -1;
00261 }
00262 }
00263
00264 _CurrentNumVisibleModels= 0;
00265
00266 _VisibleClusters.clear();
00267
00268 H_AFTER( NL3D_TravClip_ResetVisible );
00269
00270
00271
00272
00273 H_BEFORE( NL3D_TravClip_FindCameraCluster);
00274
00275
00276 static vector<CCluster*> vCluster;
00277
00278 vCluster.clear();
00279 sceneRoot->clipDelChild(RootCluster);
00280
00281
00282 CQuadGrid<CCluster*>::CIterator itAcc;
00283 if (Camera->getClusterSystem() == (CInstanceGroup*)-1)
00284 {
00285 fullSearch(vCluster, CamPos);
00286 for (i = 0; i < vCluster.size(); ++i)
00287 sceneRoot->clipAddChild(vCluster[i]);
00288 }
00289 else
00290 {
00291 bool bInWorld = true;
00292 Accel.select (CamPos, CamPos);
00293 itAcc = Accel.begin();
00294 while (itAcc != Accel.end())
00295 {
00296 CCluster *pCluster = *itAcc;
00297 if (pCluster->Group == Camera->getClusterSystem())
00298 if (pCluster->isIn (CamPos))
00299 {
00300 sceneRoot->clipAddChild(pCluster);
00301 vCluster.push_back (pCluster);
00302 bInWorld = false;
00303 }
00304 ++itAcc;
00305 }
00306
00307 if (bInWorld)
00308 {
00309 sceneRoot->clipAddChild(RootCluster);
00310 vCluster.push_back (RootCluster);
00311 }
00312 }
00313
00315 for(i=0;i<vCluster.size();i++)
00316 {
00317 vCluster[i]->setCameraIn(true);
00318 }
00319
00320
00321 H_AFTER( NL3D_TravClip_FindCameraCluster);
00322
00323
00324
00325
00326 H_BEFORE( NL3D_TravClip_MovingObjects);
00327
00328
00329 CHrcTrav &hrcTrav= Scene->getHrcTrav();
00330 for (i = 0; i < hrcTrav._MovingObjects.size(); ++i)
00331 {
00332 CTransformShape *pTfmShp = hrcTrav._MovingObjects[i];
00333
00334 static vector<CTransform*> vModels;
00335 vModels.clear();
00336 uint numClipParents= pTfmShp->clipGetNumParents();
00337 for(j=0;j<numClipParents;j++)
00338 {
00339 CTransform *pFather = pTfmShp->clipGetParent(j);
00340
00341
00342 if ( pFather->isCluster() )
00343 {
00344 vModels.push_back (pFather);
00345 }
00346 }
00347
00348 for (j = 0; j < vModels.size(); ++j)
00349 {
00350 vModels[j]->clipDelChild(pTfmShp);
00351 }
00352
00353 sceneRoot->clipDelChild(pTfmShp);
00354
00355
00356 }
00357
00358
00359 for (i = 0; i < hrcTrav._MovingObjects.size(); ++i)
00360 {
00361 CTransformShape *pTfmShp = hrcTrav._MovingObjects[i];
00362
00363 bool bInWorld = true;
00364 CAABBox box;
00365 pTfmShp->getAABBox (box);
00366
00367 CVector c = box.getCenter();
00368 CVector p = box.getCenter()+box.getHalfSize();
00369 const CMatrix &wm = pTfmShp->getWorldMatrix();
00370 c = wm * c;
00371 p = wm * p;
00372 float s = (p - c).norm();
00373
00374 Accel.select (c+CVector(s,s,s), c+CVector(-s,-s,-s));
00375 itAcc = Accel.begin();
00376 while (itAcc != Accel.end())
00377 {
00378 CCluster *pCluster = *itAcc;
00379 if (pCluster->Group == pTfmShp->getClusterSystem())
00380 if (pCluster->isIn (c,s))
00381 {
00382 pCluster->clipAddChild(pTfmShp);
00383 bInWorld = false;
00384 }
00385 ++itAcc;
00386 }
00387
00388
00389 if (bInWorld)
00390 {
00391 if( _QuadGridClipManager && pTfmShp->isQuadGridClipEnabled() )
00392 {
00393
00394 if(!_QuadGridClipManager->linkModel(pTfmShp))
00395
00396 RootCluster->clipAddChild(pTfmShp);
00397 }
00398 else
00399 {
00400 RootCluster->clipAddChild(pTfmShp);
00401 }
00402 }
00403 }
00404
00405 H_AFTER( NL3D_TravClip_MovingObjects);
00406
00407
00408
00409
00410 H_BEFORE( NL3D_TravClip_Traverse);
00411
00412
00413
00414 sceneRoot->traverseClip();
00415
00416
00417
00418 for (i = 0; i < vCluster.size(); ++i)
00419 {
00420
00421 vCluster[i]->setCameraIn(false);
00422
00423
00424 sceneRoot->clipDelChild(vCluster[i]);
00425 }
00426
00427 H_AFTER( NL3D_TravClip_Traverse);
00428
00429
00430
00431
00432
00433
00434
00435 H_BEFORE( NL3D_TravClip_LoadBalanceCLod);
00436 loadBalanceSkeletonCLod();
00437 H_AFTER( NL3D_TravClip_LoadBalanceCLod);
00438
00439 H_BEFORE( NL3D_TravClip_SkeletonClip);
00440
00441
00442
00443
00444 if (Scene->SonsOfAncestorSkeletonModelGroup)
00445 Scene->SonsOfAncestorSkeletonModelGroup->traverseClip();
00446
00447
00448
00449
00450
00451
00452
00453 clipShadowCasters();
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466 CScene::ItSkeletonModelList itSkel;
00467 for(itSkel= Scene->getSkeletonModelListBegin(); itSkel!=Scene->getSkeletonModelListEnd(); itSkel++)
00468 {
00469 CSkeletonModel *sm= *itSkel;
00470 sm->updateSkinRenderLists();
00471 }
00472
00473 H_AFTER( NL3D_TravClip_SkeletonClip);
00474 }
00475
00476
00477
00478 void CClipTrav::setQuadGridClipManager(CQuadGridClipManager *mgr)
00479 {
00480 _QuadGridClipManager= mgr;
00481 }
00482
00483
00484 void CClipTrav::registerCluster (CCluster* pCluster)
00485 {
00486 pCluster->AccelIt = Accel.insert (pCluster->getBBox().getMin(), pCluster->getBBox().getMax(), pCluster);
00487 }
00488
00489
00490 void CClipTrav::unregisterCluster (CCluster* pCluster)
00491 {
00492 if(!pCluster)
00493 return;
00494
00495 Accel.erase(pCluster->AccelIt);
00496
00497
00498 pCluster->AccelIt= CQuadGrid<CCluster*>::CIterator();
00499 }
00500
00501
00502
00503 void CClipTrav::loadBalanceSkeletonCLod()
00504 {
00505 CScene::ItSkeletonModelList itSkel;
00506 _TmpSortSkeletons.clear();
00507
00508
00509 for(itSkel= Scene->getSkeletonModelListBegin(); itSkel!=Scene->getSkeletonModelListEnd(); itSkel++)
00510 {
00511 CSkeletonModel *sm= *itSkel;
00512 float pr= sm->computeDisplayLodCharacterPriority();
00513
00514 if(pr>0)
00515 {
00516
00517 if(pr>1)
00518 sm->setDisplayLodCharacterFlag(true);
00519
00520 else
00521 {
00522 CSkeletonKey key;
00523
00524 key.Priority= OptFastFloor(pr*0xFFFFFF00);
00525 key.SkeletonModel= sm;
00526 _TmpSortSkeletons.push_back(key);
00527 }
00528 }
00529 }
00530
00531
00532 uint nMaxSkelsInNotCLodForm= Scene->getMaxSkeletonsInNotCLodForm();
00533
00534 if(_TmpSortSkeletons.size()>nMaxSkelsInNotCLodForm)
00535 {
00536 sort(_TmpSortSkeletons.begin(), _TmpSortSkeletons.end());
00537 }
00538
00539
00540 uint n= min(nMaxSkelsInNotCLodForm, (uint)_TmpSortSkeletons.size());
00541 uint i;
00542
00543 for(i=0;i<n;i++)
00544 {
00545 _TmpSortSkeletons[i].SkeletonModel->setDisplayLodCharacterFlag(false);
00546 }
00547
00548 for(i=n;i<_TmpSortSkeletons.size();i++)
00549 {
00550 _TmpSortSkeletons[i].SkeletonModel->setDisplayLodCharacterFlag(true);
00551 }
00552
00553 }
00554
00555
00556
00557 void CClipTrav::reserveVisibleList(uint numModels)
00558 {
00559
00560 if(numModels>_VisibleList.size())
00561 _VisibleList.resize(numModels);
00562 }
00563
00564
00565
00566 struct CFadeShadowMapSort
00567 {
00568 CTransform *Model;
00569 float Dist;
00570
00571 bool operator<(const CFadeShadowMapSort &o) const
00572 {
00573 return Dist<o.Dist;
00574 }
00575 };
00576
00577
00578 void CClipTrav::clipShadowCasters()
00579 {
00580 H_AUTO( NL3D_TravClip_ShadowCasters );
00581
00582 CScene::ItShadowCasterList itShadowCaster;
00583
00584 float dFade= NL3D_SMM_FADE_SPEED * Scene->getEllapsedTime();
00585 float distFadeStart= Scene->getShadowMapDistFadeStart();
00586 float distFadeEnd= Scene->getShadowMapDistFadeEnd();
00587 float OODeltaDistFade;
00588 if(distFadeEnd-distFadeStart>0)
00589 OODeltaDistFade= 1.0f/(distFadeEnd-distFadeStart);
00590 else
00591 OODeltaDistFade= 1000000;
00592 uint maxCastInScreen= Scene->getShadowMapMaxCasterInScreen();
00593 uint maxCastAround= Scene->getShadowMapMaxCasterAround();
00594
00595
00596
00597
00598
00599 static std::vector<CFadeShadowMapSort> aroundCasters;
00600 static std::vector<CFadeShadowMapSort> screenCasters;
00601 aroundCasters.clear();
00602 screenCasters.clear();
00603
00604
00605 for(itShadowCaster= Scene->getShadowCasterListBegin(); itShadowCaster!=Scene->getShadowCasterListEnd(); itShadowCaster++)
00606 {
00607 CTransform *sc= *itShadowCaster;
00608 nlassert(sc->canCastShadowMap());
00609
00610 CShadowMap *shadowMap= sc->getShadowMap();
00611 nlassert( shadowMap );
00612
00613
00614
00615 if( sc->_AncestorSkeletonModel==NULL && sc->isHrcVisible() )
00616 {
00617 bool visible= false;
00618
00619 if(sc->isClipVisible())
00620 visible= true;
00621
00622 else
00623 {
00624
00625
00626
00627 CBSphere sphere;
00628
00629 const float objectRadius= 3.f;
00630 sphere.Center= sc->getWorldMatrix().getPos();
00631
00632
00633 sphere.Radius= objectRadius + sc->getShadowMapMaxDepth();
00634
00635
00636 visible= true;
00637 for(uint i=0;i<WorldFrustumPyramid.size();i++)
00638 {
00639
00640 float d= WorldFrustumPyramid[i]*sphere.Center;
00641 if(d>sphere.Radius)
00642 {
00643 visible= false;
00644 break;
00645 }
00646 }
00647 }
00648
00649
00650 if(visible)
00651 Scene->getRenderTrav().getShadowMapManager().addShadowCaster(sc);
00652
00653
00654 CFadeShadowMapSort fsms;
00655 fsms.Model= sc;
00656 fsms.Dist= (sc->getWorldMatrix().getPos() - CamPos).norm();
00657
00658 aroundCasters.push_back(fsms);
00659 if(visible)
00660 screenCasters.push_back(fsms);
00661
00662 shadowMap->DistanceFade= (fsms.Dist-distFadeStart)*OODeltaDistFade;
00663
00664 shadowMap->TemporalOutScreenFade+= dFade;
00665
00666 if(!visible)
00667 shadowMap->InScreenFadeAccum+= dFade;
00668 }
00669
00670 else
00671 {
00672
00673
00674 shadowMap->TemporalOutScreenFade+= dFade;
00675
00676 shadowMap->InScreenFadeAccum+= dFade;
00677 }
00678 }
00679
00680
00681
00682 sort(aroundCasters.begin(), aroundCasters.end());
00683 sort(screenCasters.begin(), screenCasters.end());
00684
00685
00686 uint numNearCast= min((uint)aroundCasters.size(), maxCastAround);
00687 uint i;
00688 for(i=0;i<numNearCast;i++)
00689 {
00690 CTransform *model= aroundCasters[i].Model;
00691 CShadowMap *shadowMap= model->getShadowMap();
00692
00693 shadowMap->TemporalOutScreenFade-= 2*dFade;
00694 }
00695
00696
00697 numNearCast= min((uint)screenCasters.size(), maxCastInScreen);
00698
00699 for(i=0;i<numNearCast;i++)
00700 {
00701 CShadowMap *shadowMap= screenCasters[i].Model->getShadowMap();
00702
00703 shadowMap->TemporalInScreenFade-= dFade + shadowMap->InScreenFadeAccum;
00704
00705 shadowMap->InScreenFadeAccum= 0;
00706 }
00707
00708 for(i=numNearCast;i<screenCasters.size();i++)
00709 {
00710 CShadowMap *shadowMap= screenCasters[i].Model->getShadowMap();
00711
00712 shadowMap->TemporalInScreenFade+= dFade + shadowMap->InScreenFadeAccum;
00713
00714 shadowMap->InScreenFadeAccum= 0;
00715 }
00716
00717
00718
00719 for(itShadowCaster= Scene->getShadowCasterListBegin(); itShadowCaster!=Scene->getShadowCasterListEnd(); itShadowCaster++)
00720 {
00721 CTransform *sc= *itShadowCaster;
00722 nlassert(sc->canCastShadowMap());
00723
00724 CShadowMap *shadowMap= sc->getShadowMap();
00725 shadowMap->processFades();
00726 }
00727
00728
00729 Scene->getRenderTrav().getShadowMapManager().selectShadowMapsToGenerate(Scene);
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741 for(itShadowCaster= Scene->getShadowCasterListBegin(); itShadowCaster!=Scene->getShadowCasterListEnd(); itShadowCaster++)
00742 {
00743 CTransform *sc= *itShadowCaster;
00744
00745 if(sc->isGeneratingShadowMap() && !sc->isClipVisible() )
00746 {
00747 nlassert(sc->_AncestorSkeletonModel==NULL);
00748
00749 if( sc->isLightable() )
00750 Scene->getLightTrav().addLightedModel(sc);
00751
00752 if( sc->isSkeleton() && sc->isAnimDetailable() )
00753 Scene->getAnimDetailTrav().addVisibleModel(sc);
00754 }
00755 }
00756 }
00757
00758
00759 }