# Home    # nevrax.com   
Nevrax
Nevrax.org
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
Docs
 
Documentation  
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  

quad_grid_clip_manager.cpp

Go to the documentation of this file.
00001 
00007 /* Copyright, 2001 Nevrax Ltd.
00008  *
00009  * This file is part of NEVRAX NEL.
00010  * NEVRAX NEL is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2, or (at your option)
00013  * any later version.
00014 
00015  * NEVRAX NEL is distributed in the hope that it will be useful, but
00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00018  * General Public License for more details.
00019 
00020  * You should have received a copy of the GNU General Public License
00021  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00023  * MA 02111-1307, USA.
00024  */
00025 
00026 #include "std3d.h"
00027 
00028 #include "3d/quad_grid_clip_manager.h"
00029 #include "3d/scene.h"
00030 #include "3d/transform_shape.h"
00031 #include "3d/clip_trav.h"
00032 #include "nel/misc/aabbox.h"
00033 #include "3d/cluster.h"
00034 #include "3d/skip_model.h"
00035 
00036 
00037 using namespace std;
00038 using namespace NLMISC;
00039 
00040 
00041 namespace NL3D 
00042 {
00043 
00044 
00045 // ***************************************************************************
00046 CQuadGridClipManager::CQuadGridClipManager()
00047 {
00048         _Scene= NULL;
00049         _ClusterSize= 0;
00050         _X= _Y= 0;
00051         _Width= _Height= 0;
00052 }
00053 // ***************************************************************************
00054 CQuadGridClipManager::~CQuadGridClipManager()
00055 {
00056         reset();
00057 }
00058 
00059 
00060 // ***************************************************************************
00061 void                            CQuadGridClipManager::init(CScene *scene, float clusterSize, std::vector<float> maxDists, float radiusMax )
00062 {
00063         // reset first.
00064         reset();
00065 
00066         // copy params.
00067         nlassert(clusterSize>0);
00068         _Scene= scene;
00069         _ClusterSize= clusterSize;
00070         _MaxDists= maxDists;
00071         _RadiusMax= radiusMax;
00072 
00073         // verify growing order.
00074         float   prec= 0;
00075         for(uint i=0; i<_MaxDists.size(); i++)
00076         {
00077                 nlassert(_MaxDists[i] > prec);
00078                 prec=_MaxDists[i];
00079         }
00080 }
00081 
00082 // ***************************************************************************
00083 void                            CQuadGridClipManager::reset()
00084 {
00085         // delete the clusters.
00086         if(_Scene)
00087         {
00088                 sint    oldX0, oldX1, oldY0, oldY1;
00089 
00090                 oldX0= _X;
00091                 oldX1= _X+_Width;
00092                 oldY0= _Y;
00093                 oldY1= _Y+_Height;
00094 
00095                 for(sint y=oldY0; y<oldY1; y++)
00096                 {
00097                         for(sint x=oldX0; x<oldX1; x++)
00098                         {
00099                                 deleteCaseModels((CClipTrav*)_Scene->getTrav(ClipTravId), x,y);
00100                         }
00101                 }
00102 
00103                 // clear the grid.
00104                 _QuadGridClusterCases.clear();
00105         }
00106 
00107         // reset others params.
00108         _MaxDists.clear();
00109         _Scene= NULL;
00110         _ClusterSize= 0;
00111         _X= _Y= 0;
00112         _Width= _Height= 0;
00113 }
00114 
00115 // ***************************************************************************
00116 void                            CQuadGridClipManager::updateClustersFromCamera(CClipTrav *pClipTrav, const CVector &camPos)
00117 {
00118         sint    newX0, newX1, newY0, newY1;
00119         sint    oldX0, oldX1, oldY0, oldY1;
00120 
00121         oldX0= _X;
00122         oldX1= _X+_Width;
00123         oldY0= _Y;
00124         oldY1= _Y+_Height;
00125 
00126         // compute the new square of clusters to build.
00127         newX0= (sint)floor( (camPos.x - _RadiusMax) / _ClusterSize);
00128         newX1= (sint)ceil( (camPos.x + _RadiusMax) / _ClusterSize);
00129         newY0= (sint)floor( (camPos.y - _RadiusMax) / _ClusterSize);
00130         newY1= (sint)ceil( (camPos.y + _RadiusMax) / _ClusterSize);
00131 
00132         // keep an histeresis of one cluster: do not delete "young" clusters created before.
00133         if(newX0>= oldX0+1)             // NB: if newX0==oldX0+1, then newX0= _X => no change.
00134                 newX0--;        
00135         if(newY0>= oldY0+1)             // same reasoning.
00136                 newY0--;        
00137         if(newX1<= oldX1-1)             // NB: if newX1==oldX1-1, then newX1= oldX1 => no change.
00138                 newX1++;        
00139         if(newY1<= oldY1-1)             // same reasoning.
00140                 newY1++;
00141 
00142         // Have we got to update the array.
00143         if(newX0!=oldX0 || newX1!=oldX1 || newY0!=oldY0 || newY1!=oldY1)
00144         {
00145                 sint    x,y;
00146 
00147                 // delete olds models.
00148                 // simple: test all cases
00149                 for(y=oldY0; y<oldY1; y++)
00150                 {
00151                         for(x=oldX0; x<oldX1; x++)
00152                         {
00153                                 // if out the new square?
00154                                 if(x<newX0 || x>=newX1 || y<newY0 || y>=newY1)
00155                                         deleteCaseModels(pClipTrav, x,y);
00156                         }
00157                 }
00158 
00159                 // build new array
00160                 // satic for alloc optimisation.
00161                 static  vector<CQuadGridClusterCase>    newQuadGridClusterCases;
00162                 sint    newWidth= newX1-newX0;
00163                 sint    newHeight= newY1-newY0;
00164                 newQuadGridClusterCases.resize(newWidth * newHeight);
00165                 // simple: test all cases
00166                 for(y=newY0; y<newY1; y++)
00167                 {
00168                         for(x=newX0; x<newX1; x++)
00169                         {
00170                                 CQuadGridClusterCase    &newCase= newQuadGridClusterCases[ (y-newY0)*newWidth + (x-newX0) ];
00171 
00172                                 // if out the old square?
00173                                 if(x<oldX0 || x>=oldX1 || y<oldY0 || y>=oldY1)
00174                                 {
00175                                         // build new case. Clusters are empty.
00176                                         newCaseModels(newCase);
00177                                 }
00178                                 else
00179                                 {
00180                                         // copy from old.
00181                                         CQuadGridClusterCase    &oldCase= _QuadGridClusterCases[ (y-_Y)*_Width + (x-_X) ];
00182 
00183                                         newCase= oldCase;
00184                                 }
00185                         }
00186                 }
00187 
00188                 // just copy from new.
00189                 _QuadGridClusterCases= newQuadGridClusterCases;
00190                 _X= newX0;
00191                 _Y= newY0;
00192                 _Width= newWidth;
00193                 _Height= newHeight;
00194         }
00195 }
00196 
00197 
00198 // ***************************************************************************
00199 bool                            CQuadGridClipManager::linkModel(CTransformShape *pTfmShp, CClipTrav *pClipTrav)
00200 {
00201         // use the position to get the cluster to use.
00202         CAABBox box;
00203         pTfmShp->getAABBox (box);
00204         float   distModelMax = pTfmShp->getDistMax();
00205 
00206         // Transform the box in the world
00207         const CMatrix &wm = pTfmShp->getWorldMatrix();
00208         // compute center in world.
00209         CVector cLocal  = box.getCenter();
00210         CVector cWorld  = wm * cLocal;
00211         // prepare bbox.
00212         CAABBox worldBBox;
00213         worldBBox.setCenter(cWorld);
00214         CVector hs = box.getHalfSize();
00215 
00216         // For 8 corners.
00217         for(uint i=0;i<8;i++)
00218         {
00219                 CVector         corner;
00220                 // compute the corner of the bbox.
00221                 corner= cLocal;
00222                 if(i&1)         corner.x+=hs.x;
00223                 else            corner.x-=hs.x;
00224                 if((i/2)&1)     corner.y+=hs.y;
00225                 else            corner.y-=hs.y;
00226                 if((i/4)&1)     corner.z+=hs.z;
00227                 else            corner.z-=hs.z;
00228                 // Transform the corner in world.
00229                 corner = wm * corner;
00230                 // Extend the bbox with it.
00231                 worldBBox.extend(corner);
00232         }
00233 
00234 
00235         // Position in the grid.
00236         sint    x,y;
00237         x= (sint)floor( cWorld.x / _ClusterSize);
00238         y= (sint)floor( cWorld.y / _ClusterSize);
00239 
00240         // verify if IN the current grid of clusters created.
00241         if( x>=_X && x<_X+_Width && y>=_Y && y<_Y+_Height )
00242         {
00243                 CQuadGridClusterCase    &clusterCase= _QuadGridClusterCases[ (y-_Y)*_Width + (x-_X) ];
00244                 nlassert( _MaxDists.size()+1 == clusterCase.QuadGridClipClusters.size() );
00245 
00246                 // search the best cluster.
00247                 uint    bestCluster;
00248                 if(distModelMax==-1)
00249                 {
00250                         bestCluster= clusterCase.QuadGridClipClusters.size()-1;
00251                 }
00252                 else
00253                 {
00254                         nlassert(distModelMax>=0);
00255                         // search in which cluster against we must test.
00256                         uint i;
00257                         for(i=0; i<clusterCase.QuadGridClipClusters.size()-1;i++)
00258                         {
00259                                 if(distModelMax<=_MaxDists[i])
00260                                         break;
00261                         }
00262                         // NB: interval [?? , +oo[,  if i==clusterCase.QuadGridClipClusters.size()-1;
00263                         bestCluster= i;
00264                 }
00265 
00266                 // extend the bbox of this cluster.
00267                 clusterCase.QuadGridClipClusters[bestCluster]->extendCluster(worldBBox);
00268                 // link the model to this cluster.
00269                 pClipTrav->link(clusterCase.QuadGridClipClusters[bestCluster], pTfmShp);
00270 
00271 
00272                 return true;
00273         }
00274         else
00275         {
00276                 return false;
00277         }
00278 
00279 }
00280 
00281 
00282 // ***************************************************************************
00283 void                            CQuadGridClipManager::deleteCaseModels(CClipTrav *pClipTrav, sint x, sint y)
00284 {
00285         nlassert(x>=_X && x<_X+_Width && y>=_Y && y<_Y+_Height);
00286 
00287         CQuadGridClusterCase    &clusterCase= _QuadGridClusterCases[ (y-_Y)*_Width + (x-_X) ];
00288         for(uint j=0; j<clusterCase.QuadGridClipClusters.size(); j++)
00289         {
00290                 CQuadGridClipCluster    *cluster= clusterCase.QuadGridClipClusters[j];
00291 
00292                 // first, unlink all sons from cluster, and link thems to RootCluster.
00293                 IModel  *son= pClipTrav->getFirstChild(cluster);
00294                 while( son != NULL )
00295                 {
00296                         // unlink from us.
00297                         pClipTrav->unlink(cluster, son);
00298                         // link to the rootCluster
00299                         pClipTrav->link(pClipTrav->RootCluster, son);
00300 
00301                         // next son.
00302                         son= pClipTrav->getFirstChild(cluster);
00303                 }
00304 
00305                 // delete the cluster.
00306                 _Scene->deleteModel(cluster);
00307         }
00308 
00309         // NB: do not delete array for alloc/free optimisation.
00310 }
00311 
00312 
00313 // ***************************************************************************
00314 void                            CQuadGridClipManager::newCaseModels(CQuadGridClusterCase &clusterCase)
00315 {
00316         // resize of the number of bbox per distance.
00317         clusterCase.QuadGridClipClusters.resize(_MaxDists.size()+1);
00318 
00319         // create clusters.
00320         for(uint i=0; i<clusterCase.QuadGridClipClusters.size(); i++)
00321         {
00322                 // create the cluster.
00323                 CQuadGridClipCluster    *cluster= (CQuadGridClipCluster*)_Scene->createModel(QuadGridClipClusterId);
00324                 clusterCase.QuadGridClipClusters[i]= cluster;
00325                 // disable it from HRC
00326                 CHrcTrav        *hrcTrav= (CHrcTrav*)_Scene->getTrav(HrcTravId);
00327                 hrcTrav->link(_Scene->getSkipModelRoot(), cluster);
00328                 // NB: disabled from validation in CQuadGridClipCluster::update()
00329                 // Hence it will be never traversed but in ClipTrav.
00330 
00331                 // link it in RootCluster, so it may be clipped in city etc...
00332                 CClipTrav       *clipTrav= (CClipTrav*)_Scene->getTrav(ClipTravId);
00333                 clipTrav->unlink(NULL, cluster);
00334                 clipTrav->link(clipTrav->RootCluster, cluster);
00335 
00336 
00337                 // init distMax
00338                 if(i<_MaxDists.size())
00339                         clusterCase.QuadGridClipClusters[i]->setDistMax(_MaxDists[i]);
00340                 else
00341                         clusterCase.QuadGridClipClusters[i]->setDistMax(-1);
00342         }
00343 }
00344 
00345 
00346 } // NL3D