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/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
00068 reset();
00069
00070
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
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
00100 _QuadGridClusterCases.clear();
00101 }
00102
00103
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
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
00131 if(newX0>= oldX0+1)
00132 newX0--;
00133 if(newY0>= oldY0+1)
00134 newY0--;
00135 if(newX1<= oldX1-1)
00136 newX1++;
00137 if(newY1<= oldY1-1)
00138 newY1++;
00139
00140
00141 if(newX0!=oldX0 || newX1!=oldX1 || newY0!=oldY0 || newY1!=oldY1)
00142 {
00143 sint x,y;
00144
00145
00146
00147 for(y=oldY0; y<oldY1; y++)
00148 {
00149 for(x=oldX0; x<oldX1; x++)
00150 {
00151
00152 if(x<newX0 || x>=newX1 || y<newY0 || y>=newY1)
00153 deleteCaseModels(pClipTrav, x,y);
00154 }
00155 }
00156
00157
00158
00159 static vector<CQuadGridClipCluster*> newQuadGridClusterCases;
00160 sint newWidth= newX1-newX0;
00161 sint newHeight= newY1-newY0;
00162 newQuadGridClusterCases.resize(newWidth * newHeight);
00163
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
00171 if(x<oldX0 || x>=oldX1 || y<oldY0 || y>=oldY1)
00172 {
00173
00174 CAABBox pivotBBox;
00175 pivotBBox.setMinMax(
00176 CVector(x*_ClusterSize,y*_ClusterSize,0),
00177 CVector((x+1)*_ClusterSize,(y+1)*_ClusterSize,0) );
00178
00179 newCaseModels(newCase, pivotBBox);
00180 }
00181 else
00182 {
00183
00184 CQuadGridClipCluster *oldCase= _QuadGridClusterCases[ (y-_Y)*_Width + (x-_X) ];
00185
00186 newCase= oldCase;
00187 }
00188 }
00189 }
00190
00191
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
00207 CAABBox box;
00208 pTfmShp->getAABBox (box);
00209
00210
00211 const CMatrix &wm = pTfmShp->getWorldMatrix();
00212
00213 CVector cLocal = box.getCenter();
00214 CVector cWorld = wm * cLocal;
00215
00216 CAABBox worldBBox;
00217 worldBBox.setCenter(cWorld);
00218 CVector hs = box.getHalfSize();
00219
00220
00221 for(uint i=0;i<8;i++)
00222 {
00223 CVector corner;
00224
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
00233 corner = wm * corner;
00234
00235 worldBBox.extend(corner);
00236 }
00237
00238
00239
00240 sint x,y;
00241 x= (sint)floor( cWorld.x / _ClusterSize);
00242 y= (sint)floor( cWorld.y / _ClusterSize);
00243
00244
00245 if( x>=_X && x<_X+_Width && y>=_Y && y<_Y+_Height )
00246 {
00247
00248 CQuadGridClipCluster *cluster= _QuadGridClusterCases[ (y-_Y)*_Width + (x-_X) ];
00249
00250
00251 if( cluster->isEmpty() )
00252 {
00253 _NotEmptyQuadGridClipClusters.insert(cluster, &cluster->ListNode);
00254 }
00255
00256
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
00279 cluster->resetSons(pClipTrav);
00280
00281
00282 delete cluster;
00283
00284
00285 }
00286
00287
00288
00289 void CQuadGridClipManager::newCaseModels(CQuadGridClipCluster *&cluster, const NLMISC::CAABBox &pivotBbox)
00290 {
00291 H_AUTO( NL3D_QuadClip_newCaseModels );
00292
00293
00294 cluster= new CQuadGridClipCluster(_NumDist, _MaxDist, pivotBbox);
00295 }
00296
00297
00298
00299 void CQuadGridClipManager::traverseClip()
00300 {
00301 CClipTrav *pClipTrav= &getOwnerScene()->getClipTrav();
00302
00303
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
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
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
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
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
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
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 }