quad_grid_clip_manager.cpp

Go to the documentation of this file.
00001 
00005 /* Copyright, 2001 Nevrax Ltd.
00006  *
00007  * This file is part of NEVRAX NEL.
00008  * NEVRAX NEL is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2, or (at your option)
00011  * any later version.
00012 
00013  * NEVRAX NEL is distributed in the hope that it will be useful, but
00014  * WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00016  * General Public License for more details.
00017 
00018  * You should have received a copy of the GNU General Public License
00019  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00020  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00021  * MA 02111-1307, USA.
00022  */
00023 
00024 #include "std3d.h"
00025 
00026 #include "nel/3d/quad_grid_clip_manager.h"
00027 #include "nel/3d/scene.h"
00028 #include "nel/3d/transform_shape.h"
00029 #include "nel/3d/clip_trav.h"
00030 #include "nel/misc/aabbox.h"
00031 #include "nel/3d/cluster.h"
00032 #include "nel/misc/hierarchical_timer.h"
00033 
00034 
00035 using namespace std;
00036 using namespace NLMISC;
00037 
00038 
00039 namespace NL3D
00040 {
00041 
00042 
00043 // ***************************************************************************
00044 void    CQuadGridClipManager::registerBasic()
00045 {
00046     CScene::registerModel(QuadGridClipManagerId, TransformId, CQuadGridClipManager::creator);
00047 }
00048 
00049 
00050 // ***************************************************************************
00051 CQuadGridClipManager::CQuadGridClipManager()
00052 {
00053     _ClusterSize= 0;
00054     _X= _Y= 0;
00055     _Width= _Height= 0;
00056 }
00057 // ***************************************************************************
00058 CQuadGridClipManager::~CQuadGridClipManager()
00059 {
00060     reset();
00061 }
00062 
00063 
00064 // ***************************************************************************
00065 void                CQuadGridClipManager::init(float clusterSize, uint numDist, float maxDist, float radiusMax )
00066 {
00067     // reset first.
00068     reset();
00069 
00070     // copy params.
00071     nlassert(clusterSize>0);
00072     _ClusterSize= clusterSize;
00073     _MaxDist= maxDist;
00074     _NumDist= numDist;
00075     _RadiusMax= radiusMax;
00076 }
00077 
00078 // ***************************************************************************
00079 void                CQuadGridClipManager::reset()
00080 {
00081     // delete the clusters.
00082     if(getOwnerScene())
00083     {
00084         sint    oldX0, oldX1, oldY0, oldY1;
00085 
00086         oldX0= _X;
00087         oldX1= _X+_Width;
00088         oldY0= _Y;
00089         oldY1= _Y+_Height;
00090 
00091         for(sint y=oldY0; y<oldY1; y++)
00092         {
00093             for(sint x=oldX0; x<oldX1; x++)
00094             {
00095                 deleteCaseModels(&getOwnerScene()->getClipTrav(), x,y);
00096             }
00097         }
00098 
00099         // clear the grid.
00100         _QuadGridClusterCases.clear();
00101     }
00102 
00103     // reset others params.
00104     _ClusterSize= 0;
00105     _X= _Y= 0;
00106     _Width= _Height= 0;
00107 }
00108 
00109 // ***************************************************************************
00110 void                CQuadGridClipManager::updateClustersFromCamera(const CVector &camPos)
00111 {
00112     H_AUTO( NL3D_QuadClip_updateClusters );
00113 
00114     CClipTrav *pClipTrav= &getOwnerScene()->getClipTrav();
00115 
00116     sint    newX0, newX1, newY0, newY1;
00117     sint    oldX0, oldX1, oldY0, oldY1;
00118 
00119     oldX0= _X;
00120     oldX1= _X+_Width;
00121     oldY0= _Y;
00122     oldY1= _Y+_Height;
00123 
00124     // compute the new square of clusters to build.
00125     newX0= (sint)floor( (camPos.x - _RadiusMax) / _ClusterSize);
00126     newX1= (sint)ceil( (camPos.x + _RadiusMax) / _ClusterSize);
00127     newY0= (sint)floor( (camPos.y - _RadiusMax) / _ClusterSize);
00128     newY1= (sint)ceil( (camPos.y + _RadiusMax) / _ClusterSize);
00129 
00130     // keep an histeresis of one cluster: do not delete "young" clusters created before.
00131     if(newX0>= oldX0+1)     // NB: if newX0==oldX0+1, then newX0= _X => no change.
00132         newX0--;
00133     if(newY0>= oldY0+1)     // same reasoning.
00134         newY0--;
00135     if(newX1<= oldX1-1)     // NB: if newX1==oldX1-1, then newX1= oldX1 => no change.
00136         newX1++;
00137     if(newY1<= oldY1-1)     // same reasoning.
00138         newY1++;
00139 
00140     // Have we got to update the array.
00141     if(newX0!=oldX0 || newX1!=oldX1 || newY0!=oldY0 || newY1!=oldY1)
00142     {
00143         sint    x,y;
00144 
00145         // delete olds models.
00146         // simple: test all cases
00147         for(y=oldY0; y<oldY1; y++)
00148         {
00149             for(x=oldX0; x<oldX1; x++)
00150             {
00151                 // if out the new square?
00152                 if(x<newX0 || x>=newX1 || y<newY0 || y>=newY1)
00153                     deleteCaseModels(pClipTrav, x,y);
00154             }
00155         }
00156 
00157         // build new array
00158         // satic for alloc optimisation.
00159         static  vector<CQuadGridClipCluster*>   newQuadGridClusterCases;
00160         sint    newWidth= newX1-newX0;
00161         sint    newHeight= newY1-newY0;
00162         newQuadGridClusterCases.resize(newWidth * newHeight);
00163         // simple: test all cases
00164         for(y=newY0; y<newY1; y++)
00165         {
00166             for(x=newX0; x<newX1; x++)
00167             {
00168                 CQuadGridClipCluster    *&newCase= newQuadGridClusterCases[ (y-newY0)*newWidth + (x-newX0) ];
00169 
00170                 // if out the old square?
00171                 if(x<oldX0 || x>=oldX1 || y<oldY0 || y>=oldY1)
00172                 {
00173                     // build the 2D bbox where the models should fit.
00174                     CAABBox     pivotBBox;
00175                     pivotBBox.setMinMax(
00176                         CVector(x*_ClusterSize,y*_ClusterSize,0),
00177                         CVector((x+1)*_ClusterSize,(y+1)*_ClusterSize,0) );
00178                     // build new case. Clusters are empty.
00179                     newCaseModels(newCase, pivotBBox);
00180                 }
00181                 else
00182                 {
00183                     // copy from old.
00184                     CQuadGridClipCluster    *oldCase= _QuadGridClusterCases[ (y-_Y)*_Width + (x-_X) ];
00185 
00186                     newCase= oldCase;
00187                 }
00188             }
00189         }
00190 
00191         // just copy from new.
00192         _QuadGridClusterCases= newQuadGridClusterCases;
00193         _X= newX0;
00194         _Y= newY0;
00195         _Width= newWidth;
00196         _Height= newHeight;
00197     }
00198 }
00199 
00200 
00201 // ***************************************************************************
00202 bool                CQuadGridClipManager::linkModel(CTransformShape *pTfmShp)
00203 {
00204     H_AUTO( NL3D_QuadClip_linkModel );
00205 
00206     // use the position to get the cluster to use.
00207     CAABBox box;
00208     pTfmShp->getAABBox (box);
00209 
00210     // Transform the box in the world
00211     const CMatrix &wm = pTfmShp->getWorldMatrix();
00212     // compute center in world.
00213     CVector cLocal  = box.getCenter();
00214     CVector cWorld  = wm * cLocal;
00215     // prepare bbox.
00216     CAABBox worldBBox;
00217     worldBBox.setCenter(cWorld);
00218     CVector hs = box.getHalfSize();
00219 
00220     // For 8 corners.
00221     for(uint i=0;i<8;i++)
00222     {
00223         CVector     corner;
00224         // compute the corner of the bbox.
00225         corner= cLocal;
00226         if(i&1)     corner.x+=hs.x;
00227         else        corner.x-=hs.x;
00228         if((i/2)&1) corner.y+=hs.y;
00229         else        corner.y-=hs.y;
00230         if((i/4)&1) corner.z+=hs.z;
00231         else        corner.z-=hs.z;
00232         // Transform the corner in world.
00233         corner = wm * corner;
00234         // Extend the bbox with it.
00235         worldBBox.extend(corner);
00236     }
00237 
00238 
00239     // Position in the grid.
00240     sint    x,y;
00241     x= (sint)floor( cWorld.x / _ClusterSize);
00242     y= (sint)floor( cWorld.y / _ClusterSize);
00243 
00244     // verify if IN the current grid of clusters created.
00245     if( x>=_X && x<_X+_Width && y>=_Y && y<_Y+_Height )
00246     {
00247         // add the model and extend the bbox of this cluster.
00248         CQuadGridClipCluster    *cluster= _QuadGridClusterCases[ (y-_Y)*_Width + (x-_X) ];
00249 
00250         // if this cluster is empty, add it now to the list of not empty (do the test before add)
00251         if( cluster->isEmpty() )
00252         {
00253             _NotEmptyQuadGridClipClusters.insert(cluster, &cluster->ListNode);
00254         }
00255 
00256         // add the model => no more empty
00257         cluster->addModel(worldBBox, pTfmShp);
00258 
00259         return true;
00260     }
00261     else
00262     {
00263         return false;
00264     }
00265 
00266 }
00267 
00268 
00269 // ***************************************************************************
00270 void                CQuadGridClipManager::deleteCaseModels(CClipTrav *pClipTrav, sint x, sint y)
00271 {
00272     H_AUTO( NL3D_QuadClip_deleteCaseModels );
00273 
00274     nlassert(x>=_X && x<_X+_Width && y>=_Y && y<_Y+_Height);
00275 
00276     CQuadGridClipCluster    *cluster= _QuadGridClusterCases[ (y-_Y)*_Width + (x-_X) ];
00277 
00278     // first, unlink all sons from cluster, and link thems to RootCluster.
00279     cluster->resetSons(pClipTrav);
00280 
00281     // delete the cluster. NB: auto-unlinked from _NotEmptyQuadGridClipClusters
00282     delete cluster;
00283 
00284     // NB: do not delete array for alloc/free optimisation.
00285 }
00286 
00287 
00288 // ***************************************************************************
00289 void                CQuadGridClipManager::newCaseModels(CQuadGridClipCluster *&cluster, const NLMISC::CAABBox &pivotBbox)
00290 {
00291     H_AUTO( NL3D_QuadClip_newCaseModels );
00292 
00293     // create clusters.
00294     cluster= new CQuadGridClipCluster(_NumDist, _MaxDist, pivotBbox);
00295 }
00296 
00297 
00298 // ***************************************************************************
00299 void                CQuadGridClipManager::traverseClip()
00300 {
00301     CClipTrav *pClipTrav= &getOwnerScene()->getClipTrav();
00302 
00303     // Run All NotEmpty Clusters,
00304     CQuadGridClipCluster    **it;
00305     it= _NotEmptyQuadGridClipClusters.begin();
00306     uint    numClusters= _NotEmptyQuadGridClipClusters.size();
00307     for(;numClusters>0;numClusters--,it++)
00308     {
00309         (*it)->clip(pClipTrav);
00310     }
00311 }
00312 
00313 
00314 // ***************************************************************************
00315 void                CQuadGridClipManager::profile() const
00316 {
00317     nlinfo(" ***** CQuadGridClipManager stats");
00318     nlinfo(" There is %d clusters", _Width*_Height );
00319     sint    numEmptyClusters= 0;
00320     float   minAreaRatio= 1000;
00321     float   maxAreaRatio= 0;
00322     float   meanAreaRatio= 0;
00323 
00324     // test all cases
00325     for(sint y=0;y<_Height;y++)
00326     {
00327         for(sint x=0;x<_Width;x++)
00328         {
00329             const CQuadGridClipCluster  *cluster= _QuadGridClusterCases[y*_Width+x];
00330             if( cluster->isEmpty() )
00331                 numEmptyClusters++;
00332             else
00333             {
00334                 CAABBox bb= cluster->getBBox();
00335                 float   area= (bb.getSize().x*bb.getSize().y) / (_ClusterSize*_ClusterSize);
00336                 meanAreaRatio+= area;
00337                 minAreaRatio= min( minAreaRatio, area);
00338                 maxAreaRatio= max( maxAreaRatio, area);
00339             }
00340         }
00341     }
00342 
00343     // display
00344     if( numEmptyClusters==_Width*_Height )
00345     {
00346         nlinfo( " The ClipManager is completely Empty!!!!");
00347     }
00348     else
00349     {
00350         sint    numClusters= _Width*_Height-numEmptyClusters;
00351         nlinfo( "    This Level has %d clusters not empty over %d", numClusters, _Width*_Height);
00352         meanAreaRatio/= numClusters;
00353         nlinfo("     . minAreaRatio= %f", minAreaRatio);
00354         nlinfo("     . maxAreaRatio= %f", maxAreaRatio);
00355         nlinfo("     . meanAreaRatio= %f", meanAreaRatio);
00356 
00357         // Do Stats per distance setup
00358         for(uint lvl=0;lvl<_NumDist+1;lvl++)
00359         {
00360             nlinfo("    * Stats for Distance up to %f m", lvl<_NumDist?(lvl+1)*_MaxDist/_NumDist:-1.0f);
00361             sint    minNumChildren= 100000000;
00362             sint    maxNumChildren= 0;
00363             float   meanNumChildren= 0;
00364             sint    totalNumChildren= 0;
00365 
00366             // test all cases
00367             for(sint y=0;y<_Height;y++)
00368             {
00369                 for(sint x=0;x<_Width;x++)
00370                 {
00371                     const CQuadGridClipCluster  *cluster= _QuadGridClusterCases[y*_Width+x];
00372                     if( cluster->isEmpty() )
00373                         numEmptyClusters++;
00374                     else
00375                     {
00376                         // count number of sons
00377                         sint    numSons;
00378                         numSons= cluster->profileNumChildren(lvl);
00379                         meanNumChildren+= numSons;
00380                         totalNumChildren+= numSons;
00381                         minNumChildren= min( minNumChildren, numSons);
00382                         maxNumChildren= max( maxNumChildren, numSons);
00383                     }
00384                 }
00385             }
00386 
00387             // display
00388             meanNumChildren/= numClusters;
00389             nlinfo("     . minNumChildren= %d", minNumChildren);
00390             nlinfo("     . maxNumChildren= %d", maxNumChildren);
00391             nlinfo("     . meanNumChildren= %f", meanNumChildren);
00392             nlinfo("     . totalNumChildren= %d", totalNumChildren);
00393         }
00394     }
00395 }
00396 
00397 
00398 } // NL3D

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