00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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
00064 reset();
00065
00066
00067 nlassert(clusterSize>0);
00068 _Scene= scene;
00069 _ClusterSize= clusterSize;
00070 _MaxDists= maxDists;
00071 _RadiusMax= radiusMax;
00072
00073
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
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
00104 _QuadGridClusterCases.clear();
00105 }
00106
00107
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
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
00133 if(newX0>= oldX0+1)
00134 newX0--;
00135 if(newY0>= oldY0+1)
00136 newY0--;
00137 if(newX1<= oldX1-1)
00138 newX1++;
00139 if(newY1<= oldY1-1)
00140 newY1++;
00141
00142
00143 if(newX0!=oldX0 || newX1!=oldX1 || newY0!=oldY0 || newY1!=oldY1)
00144 {
00145 sint x,y;
00146
00147
00148
00149 for(y=oldY0; y<oldY1; y++)
00150 {
00151 for(x=oldX0; x<oldX1; x++)
00152 {
00153
00154 if(x<newX0 || x>=newX1 || y<newY0 || y>=newY1)
00155 deleteCaseModels(pClipTrav, x,y);
00156 }
00157 }
00158
00159
00160
00161 static vector<CQuadGridClusterCase> newQuadGridClusterCases;
00162 sint newWidth= newX1-newX0;
00163 sint newHeight= newY1-newY0;
00164 newQuadGridClusterCases.resize(newWidth * newHeight);
00165
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
00173 if(x<oldX0 || x>=oldX1 || y<oldY0 || y>=oldY1)
00174 {
00175
00176 newCaseModels(newCase);
00177 }
00178 else
00179 {
00180
00181 CQuadGridClusterCase &oldCase= _QuadGridClusterCases[ (y-_Y)*_Width + (x-_X) ];
00182
00183 newCase= oldCase;
00184 }
00185 }
00186 }
00187
00188
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
00202 CAABBox box;
00203 pTfmShp->getAABBox (box);
00204 float distModelMax = pTfmShp->getDistMax();
00205
00206
00207 const CMatrix &wm = pTfmShp->getWorldMatrix();
00208
00209 CVector cLocal = box.getCenter();
00210 CVector cWorld = wm * cLocal;
00211
00212 CAABBox worldBBox;
00213 worldBBox.setCenter(cWorld);
00214 CVector hs = box.getHalfSize();
00215
00216
00217 for(uint i=0;i<8;i++)
00218 {
00219 CVector corner;
00220
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
00229 corner = wm * corner;
00230
00231 worldBBox.extend(corner);
00232 }
00233
00234
00235
00236 sint x,y;
00237 x= (sint)floor( cWorld.x / _ClusterSize);
00238 y= (sint)floor( cWorld.y / _ClusterSize);
00239
00240
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
00247 uint bestCluster;
00248 if(distModelMax==-1)
00249 {
00250 bestCluster= clusterCase.QuadGridClipClusters.size()-1;
00251 }
00252 else
00253 {
00254 nlassert(distModelMax>=0);
00255
00256 uint i;
00257 for(i=0; i<clusterCase.QuadGridClipClusters.size()-1;i++)
00258 {
00259 if(distModelMax<=_MaxDists[i])
00260 break;
00261 }
00262
00263 bestCluster= i;
00264 }
00265
00266
00267 clusterCase.QuadGridClipClusters[bestCluster]->extendCluster(worldBBox);
00268
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
00293 IModel *son= pClipTrav->getFirstChild(cluster);
00294 while( son != NULL )
00295 {
00296
00297 pClipTrav->unlink(cluster, son);
00298
00299 pClipTrav->link(pClipTrav->RootCluster, son);
00300
00301
00302 son= pClipTrav->getFirstChild(cluster);
00303 }
00304
00305
00306 _Scene->deleteModel(cluster);
00307 }
00308
00309
00310 }
00311
00312
00313
00314 void CQuadGridClipManager::newCaseModels(CQuadGridClusterCase &clusterCase)
00315 {
00316
00317 clusterCase.QuadGridClipClusters.resize(_MaxDists.size()+1);
00318
00319
00320 for(uint i=0; i<clusterCase.QuadGridClipClusters.size(); i++)
00321 {
00322
00323 CQuadGridClipCluster *cluster= (CQuadGridClipCluster*)_Scene->createModel(QuadGridClipClusterId);
00324 clusterCase.QuadGridClipClusters[i]= cluster;
00325
00326 CHrcTrav *hrcTrav= (CHrcTrav*)_Scene->getTrav(HrcTravId);
00327 hrcTrav->link(_Scene->getSkipModelRoot(), cluster);
00328
00329
00330
00331
00332 CClipTrav *clipTrav= (CClipTrav*)_Scene->getTrav(ClipTravId);
00333 clipTrav->unlink(NULL, cluster);
00334 clipTrav->link(clipTrav->RootCluster, cluster);
00335
00336
00337
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 }