clip_trav.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/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     // search with help of Accel
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     // if not found at all
00091     if (bInWorld)
00092     {
00093         vCluster.push_back (RootCluster);
00094     }
00095     // else must filter to take only the ones that are the lower in the hierarchy (same as in old code)
00096     else
00097     {
00098         uint    i;
00099         std::set<CCluster*>     parentExclude;
00100 
00101         // for each cluster, avoid its parent
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         // reparse to remove clusters presents in the exclude set
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     // Old slow code (up to 5 ms on a 2.4 Ghz, in a big city).
00125     uint32 i, j;
00126     for (i = 0; i < pIG->_ClusterInstances.size(); ++i)
00127     {
00128         for (j = 0; j < pIG->_ClusterInstances[i]->Children.size(); ++j)
00129         {
00130             if (fullSearch (vCluster, pIG->_ClusterInstances[i]->Children[j]->Group, pos))
00131                 return true;
00132         }
00133     }
00134 
00135     for (i = 0; i < pIG->_ClusterInstances.size(); ++i)
00136     {
00137         if (pIG->_ClusterInstances[i]->isIn(pos))
00138             vCluster.push_back (pIG->_ClusterInstances[i]);
00139     }
00140     if (vCluster.size() > 0)
00141         return true;*/
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     // The root must exist
00176     CTransform  *sceneRoot= Scene->getRoot();
00177 
00178     // Increment the current date of the traversal
00179     ++CurrentDate;
00180     // Update Clip infos.
00181     CTravCameraScene::update();
00182 
00183     // Compute pyramid in view basis.
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     // Compute pyramid in World basis.
00216     // The vector transformation M of a plane p is computed as p*M-1.
00217     // Here, ViewMatrix== CamMatrix-1. Hence the following formula.
00218     for (i = 0; i < 6; i++)
00219     {
00220         WorldPyramid[i]= ViewPyramid[i]*ViewMatrix;
00221     }
00222 
00223     // bkup this pyramid (because this one may be modified by the cluster system).
00224     WorldFrustumPyramid= WorldPyramid;
00225 
00226 
00227     // update the QuadGridClipManager.
00228     if(_QuadGridClipManager)
00229     {
00230         _QuadGridClipManager->updateClustersFromCamera(CamPos);
00231     }
00232 
00233     H_BEFORE( NL3D_TravClip_ClearLists );
00234 
00235     // Clear the traversals list.
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     /* For all objects marked visible in preceding render, reset _Visible state here.
00247         NB: must reset _Visible State to false because sometimes traverseClip() are even not executed
00248         (Cluster clip, QuadGridClipManager clip...).
00249         And somes models read this _Visible state. eg: Skins/StickedObjects test the Visible state of
00250         their _AncestorSkeletonModel.
00251     */
00252     for (i=0;i<_CurrentNumVisibleModels;i++)
00253     {
00254         // if the model still exists (see ~CTransform())
00255         if( _VisibleList[i] )
00256         {
00257             // disable his visibility.
00258             _VisibleList[i]->_Visible= false;
00259             // let him know that it is no more in the list.
00260             _VisibleList[i]->_IndexInVisibleList= -1;
00261         }
00262     }
00263     // Clear The visible List.
00264     _CurrentNumVisibleModels= 0;
00265     // Clear the visible cluster list.
00266     _VisibleClusters.clear();
00267 
00268     H_AFTER( NL3D_TravClip_ResetVisible );
00269 
00270     // Found where is the camera
00271     //========================
00272 
00273     H_BEFORE( NL3D_TravClip_FindCameraCluster);
00274 
00275     // Found the cluster where the camera is
00276     static vector<CCluster*> vCluster;
00277 
00278     vCluster.clear();
00279     sceneRoot->clipDelChild(RootCluster);
00280 
00281     // In which cluster is the camera ?
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     // Manage Moving Objects
00324     //=====================
00325 
00326     H_BEFORE( NL3D_TravClip_MovingObjects);
00327 
00328     // Unlink the moving objects from their clusters
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             // Does the father is a cluster ??
00342             if ( pFather->isCluster() )
00343             {
00344                 vModels.push_back (pFather);
00345             }
00346         }
00347         // Remove me from all clusters
00348         for (j = 0; j < vModels.size(); ++j)
00349         {
00350             vModels[j]->clipDelChild(pTfmShp);
00351         }
00352         // Remove me from Root Too
00353         sceneRoot->clipDelChild(pTfmShp);
00354 
00355         // NB: only the SonsOfAncestorSkeletonModelGroup may still be here.
00356     }
00357 
00358     // Affect the moving objects to their clusters
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         // Transform the box in the world
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         // Moving object in the world -> link to root or to the CQuadGridClipManager.
00389         if (bInWorld)
00390         {
00391             if( _QuadGridClipManager && pTfmShp->isQuadGridClipEnabled() )
00392             {
00393                 // try to insert in the best cluster of the _QuadGridClipManager.
00394                 if(!_QuadGridClipManager->linkModel(pTfmShp))
00395                     // if fails, link to "root".
00396                     RootCluster->clipAddChild(pTfmShp);
00397             }
00398             else
00399             {
00400                 RootCluster->clipAddChild(pTfmShp);
00401             }
00402         }
00403     }
00404 
00405     H_AFTER( NL3D_TravClip_MovingObjects);
00406 
00407     // Clip the graph.
00408     //=====================
00409 
00410     H_BEFORE( NL3D_TravClip_Traverse);
00411 
00412 
00413     // Traverse the graph.
00414     sceneRoot->traverseClip();
00415 
00416 
00417     // Unlink the cluster where we are
00418     for (i = 0; i < vCluster.size(); ++i)
00419     {
00420         // reset Camera In Flag.
00421         vCluster[i]->setCameraIn(false);
00422 
00423         // remove from Clip Root
00424         sceneRoot->clipDelChild(vCluster[i]);
00425     }
00426 
00427     H_AFTER( NL3D_TravClip_Traverse);
00428 
00429     // Load Balance the Skeleton CLod state here.
00430     // =========================
00431     /* Can't do it in LoadBalancingTrav because sons with _AncestorSkeletonModel!=NULL may be hiden if a skeleton
00432         is displayed in CLod mode.
00433         So must do it here, then clip all sons of AncestoreSkeletonModelGroup.
00434     */
00435     H_BEFORE( NL3D_TravClip_LoadBalanceCLod);
00436     loadBalanceSkeletonCLod();
00437     H_AFTER( NL3D_TravClip_LoadBalanceCLod);
00438 
00439     H_BEFORE( NL3D_TravClip_SkeletonClip);
00440 
00441     // At the end of the clip traverse, must update clip for Objects which have a skeleton ancestor
00442     // =========================
00443     // those are linked to the SonsOfAncestorSkeletonModelGroup, so traverse it now.
00444     if (Scene->SonsOfAncestorSkeletonModelGroup)
00445         Scene->SonsOfAncestorSkeletonModelGroup->traverseClip();
00446 
00447     // For All Shadow Casters (skeletons + others), clip their ShadowMap possible projection against the frustum only.
00448     // =========================
00449     /*
00450         Done here, because can't do in clip() in case of a Model in a cluster
00451         (We insert in cluster with the Model BBox, not the Model + Shadow BBox).
00452     */
00453     clipShadowCasters();
00454 
00455     // Update Here the Skin render Lists of All visible Skeletons
00456     // =========================
00457     /*
00458         Done here, because AnimDetail and Render need correct lists. NB: important to do it
00459         before Render Traversal, because updateSkinRenderLists() may change the transparency flag!!
00460         NB: can't do it in any traverse() because must be sure that it is done
00461         (traverseHRC not called if SonOfAncestorSkeletonModel, and traverseClip not called if in a cluster).
00462         NB: must do even if clipped because:
00463             1/ maybe used for generateShadow() (through the ancestorSkeletonModel)
00464             2/ the cost of method is 0 all the time (but when true changes)
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     // just ensure it point to NULL
00498     pCluster->AccelIt= CQuadGrid<CCluster*>::CIterator();
00499 }
00500 
00501 
00502 // ***************************************************************************
00503 void CClipTrav::loadBalanceSkeletonCLod()
00504 {
00505     CScene::ItSkeletonModelList     itSkel;
00506     _TmpSortSkeletons.clear();
00507 
00508     // **** compute CLod priority of each skeleton,
00509     for(itSkel= Scene->getSkeletonModelListBegin(); itSkel!=Scene->getSkeletonModelListEnd(); itSkel++)
00510     {
00511         CSkeletonModel  *sm= *itSkel;
00512         float   pr= sm->computeDisplayLodCharacterPriority();
00513         // If valid priority (CLOd enabled, and skeleton visible)
00514         if(pr>0)
00515         {
00516             // if the priority is >1, then display as CLod
00517             if(pr>1)
00518                 sm->setDisplayLodCharacterFlag(true);
00519             // else load balance.
00520             else
00521             {
00522                 CSkeletonKey    key;
00523                 // don't bother OptFastFloor precision. NB: 0<pr<=1 here.
00524                 key.Priority= OptFastFloor(pr*0xFFFFFF00);
00525                 key.SkeletonModel= sm;
00526                 _TmpSortSkeletons.push_back(key);
00527             }
00528         }
00529     }
00530 
00531     // **** sort by priority in ascending order
00532     uint    nMaxSkelsInNotCLodForm= Scene->getMaxSkeletonsInNotCLodForm();
00533     // Optim: need it only if too many skels
00534     if(_TmpSortSkeletons.size()>nMaxSkelsInNotCLodForm)
00535     {
00536         sort(_TmpSortSkeletons.begin(), _TmpSortSkeletons.end());
00537     }
00538 
00539     // **** set CLod flag
00540     uint    n= min(nMaxSkelsInNotCLodForm, (uint)_TmpSortSkeletons.size());
00541     uint    i;
00542     // The lowest priority are displayed in std form
00543     for(i=0;i<n;i++)
00544     {
00545         _TmpSortSkeletons[i].SkeletonModel->setDisplayLodCharacterFlag(false);
00546     }
00547     // the other are displayed in CLod form
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     // enlarge only.
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     // **** First select ShadowCasters that are visible or that may have their shadow visible
00597 
00598     // Lod Models that will cast ShadowMaps.
00599     static std::vector<CFadeShadowMapSort>      aroundCasters;
00600     static std::vector<CFadeShadowMapSort>      screenCasters;
00601     aroundCasters.clear();
00602     screenCasters.clear();
00603 
00604     // For all casters
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         // Binded to an Ancestor skeleton?? If so, don't render since the Ancestor Skeleton render all of his sons
00614         // Additionally, no-op if this caster is hidden in HRC!!
00615         if( sc->_AncestorSkeletonModel==NULL && sc->isHrcVisible() )
00616         {
00617             bool    visible= false;
00618             // if we are already visible, then its ok, we either don't need to test.
00619             if(sc->isClipVisible())
00620                 visible= true;
00621             // else do a bigger test
00622             else
00623             {
00624                 // TODO_SHADOW: Select a better "Caster Sphere".
00625                 // If the model "sc" is a CSkeletonModel, It depends also on Sticked objects/Skeletons.
00626                 // Build the sphere around the caster that can receive shadow.
00627                 CBSphere    sphere;
00628                 // Suppose an Object sphere of 3 meter radius, centered on caster Pos.
00629                 const   float   objectRadius= 3.f;
00630                 sphere.Center= sc->getWorldMatrix().getPos();
00631                 // Add to this sphere the max Depth extent.
00632                 // NB: works because suppose that the Shadow BBox include the model Center.
00633                 sphere.Radius= objectRadius + sc->getShadowMapMaxDepth();
00634 
00635                 // Clip This sphere against the Frustum.
00636                 visible= true;
00637                 for(uint i=0;i<WorldFrustumPyramid.size();i++)
00638                 {
00639                     // if SpherMax OUT return false.
00640                     float   d= WorldFrustumPyramid[i]*sphere.Center;
00641                     if(d>sphere.Radius)
00642                     {
00643                         visible= false;
00644                         break;
00645                     }
00646                 }
00647             }
00648 
00649             // If the ShadowMap is visible, add it to the List Of ShadowMap to Render.
00650             if(visible)
00651                 Scene->getRenderTrav().getShadowMapManager().addShadowCaster(sc);
00652 
00653             // update Fading.
00654             CFadeShadowMapSort  fsms;
00655             fsms.Model= sc;
00656             fsms.Dist= (sc->getWorldMatrix().getPos() - CamPos).norm();
00657             // lod In and Out.
00658             aroundCasters.push_back(fsms);
00659             if(visible)
00660                 screenCasters.push_back(fsms);
00661             // Compute normal Distance fading.
00662             shadowMap->DistanceFade= (fsms.Dist-distFadeStart)*OODeltaDistFade;
00663             // Increment the TemporalFadeOut by default  (see below)
00664             shadowMap->TemporalOutScreenFade+= dFade;
00665             // if !visible, increment the InScreenFadeAccum
00666             if(!visible)
00667                 shadowMap->InScreenFadeAccum+= dFade;
00668         }
00669         // If the model is not visible, or if temporary bound to a AncestorSkeletonModel
00670         else
00671         {
00672             // Increment the TemporalFadeOut. Because since will be hidden (or sticked)
00673             // for a long time, allow the process to free texture.
00674             shadowMap->TemporalOutScreenFade+= dFade;
00675             // Since not visible, increment the InScreenFadeAccum
00676             shadowMap->InScreenFadeAccum+= dFade;
00677         }
00678     }
00679 
00680     // **** Load Balance Models that cast ShadowMaps around,
00681 
00682     sort(aroundCasters.begin(), aroundCasters.end());
00683     sort(screenCasters.begin(), screenCasters.end());
00684 
00685     // For All Around nearest Casters, decrement their fadeOutScreen
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         // Decrement the fade. *2 because default incremented above.
00693         shadowMap->TemporalOutScreenFade-= 2*dFade;
00694     }
00695 
00696     // For InScreen Casters, increment or decrement their fadeInScreen. Also resolve InScreenFadeAccum.
00697     numNearCast= min((uint)screenCasters.size(), maxCastInScreen);
00698     // nearest: decrement fadeInScreen, and remove accum
00699     for(i=0;i<numNearCast;i++)
00700     {
00701         CShadowMap  *shadowMap= screenCasters[i].Model->getShadowMap();
00702         // Decrement the fade.
00703         shadowMap->TemporalInScreenFade-= dFade + shadowMap->InScreenFadeAccum;
00704         // Since visible and resolved, reset accum
00705         shadowMap->InScreenFadeAccum= 0;
00706     }
00707     // farthest: increment fadeInScreen, and append accum
00708     for(i=numNearCast;i<screenCasters.size();i++)
00709     {
00710         CShadowMap  *shadowMap= screenCasters[i].Model->getShadowMap();
00711         // Increment the fade.
00712         shadowMap->TemporalInScreenFade+= dFade + shadowMap->InScreenFadeAccum;
00713         // Since visible and resolved, reset accum
00714         shadowMap->InScreenFadeAccum= 0;
00715     }
00716 
00717 
00718     // clamp values, and release texture where appropriated
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     // **** Use the rendered Skeletons ShadowMap to select the Ones that will be generated this Frame.
00729     Scene->getRenderTrav().getShadowMapManager().selectShadowMapsToGenerate(Scene);
00730 
00731 
00732     /* **** Then for All ShadowCasters not visibles but that will generate their shadowMap,
00733         - we must compute the LightTraversal(for ShadowLight direction)
00734         - for skeleton models only, we must compute the AnimDetailTraversal (for bone animation)
00735         We MUST NOT flag the skeleton as Visible, and we MUST NOT insert in LoadBalancing
00736         (since won't be rendered)
00737         NB: Do nothing for Sons of the Ancestor Skeleton because:
00738             1/ light do nothing with them (see std clip)
00739             2/ animDetail will be called recursively (see std clip and CSkeletonModel::traverseAnimDetail())
00740     */
00741     for(itShadowCaster= Scene->getShadowCasterListBegin(); itShadowCaster!=Scene->getShadowCasterListEnd(); itShadowCaster++)
00742     {
00743         CTransform  *sc= *itShadowCaster;
00744         // compute its shadowMap this frame? and not visible?
00745         if(sc->isGeneratingShadowMap() && !sc->isClipVisible() )
00746         {
00747             nlassert(sc->_AncestorSkeletonModel==NULL);
00748             // Add it only to the lightTrav
00749             if( sc->isLightable() )
00750                 Scene->getLightTrav().addLightedModel(sc);
00751             // If it is a skeleton, add it also to the anim detail
00752             if( sc->isSkeleton() && sc->isAnimDetailable() )
00753                 Scene->getAnimDetailTrav().addVisibleModel(sc);
00754         }
00755     }
00756 }
00757 
00758 
00759 }

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