00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 #include <stdlib.h>
00044 #include <stdio.h>
00045 #include <math.h>
00046
00047 #include "OSGConfig.h"
00048 #include "OSGBaseFunctions.h"
00049 #include "OSGTriangleIterator.h"
00050 #include "OSGTileGeometryLoad.h"
00051
00052 OSG_USING_NAMESPACE
00053
00060
00061
00062
00066 TileGeometryLoad::TileGeometryLoad(UInt32 nodeId,
00067 bool useFaceDistribution):
00068 _nodeId(nodeId),
00069 _faces(0),
00070 _useFaceDistribution(useFaceDistribution),
00071 _valid(false)
00072 {
00073 if(_directions.size()==0)
00074 {
00075
00076 _directions.push_back(
00077 Plane(Vec3f( 1, 0, 0) ,Pnt3f(0,0,0)));
00078 _directions.push_back(
00079 Plane(Vec3f( 0, 1, 0) ,Pnt3f(0,0,0)));
00080 _directions.push_back(
00081 Plane(Vec3f( 0, 0, 1) ,Pnt3f(0,0,0)));
00082
00083 _directions.push_back(
00084 Plane(Vec3f( 1, 1, 1)*(1/osgSqrt(3.0f)),Pnt3f(0,0,0)));
00085 _directions.push_back(
00086 Plane(Vec3f(-1, 1, 1)*(1/osgSqrt(3.0f)),Pnt3f(1,0,0)));
00087 _directions.push_back(
00088 Plane(Vec3f( 1,-1, 1)*(1/osgSqrt(3.0f)),Pnt3f(0,1,0)));
00089 _directions.push_back(
00090 Plane(Vec3f( 1, 1,-1)*(1/osgSqrt(3.0f)),Pnt3f(0,0,1)));
00091
00092 _directions.push_back(
00093 Plane(Vec3f( 1, 1, 0)*(1/osgSqrt(2.0f)),Pnt3f(0,0,0)));
00094 _directions.push_back(
00095 Plane(Vec3f( 1,-1, 0)*(1/osgSqrt(2.0f)),Pnt3f(0,1,0)));
00096 _directions.push_back(
00097 Plane(Vec3f( 0, 1, 1)*(1/osgSqrt(2.0f)),Pnt3f(0,0,0)));
00098 _directions.push_back(
00099 Plane(Vec3f( 0,-1, 1)*(1/osgSqrt(2.0f)),Pnt3f(0,1,0)));
00100 _directions.push_back(
00101 Plane(Vec3f( 1, 0, 1)*(1/osgSqrt(2.0f)),Pnt3f(0,0,0)));
00102 _directions.push_back(
00103 Plane(Vec3f(-1, 0, 1)*(1/osgSqrt(2.0f)),Pnt3f(1,0,0)));
00104
00105
00106 }
00107 updateGeometry();
00108 }
00109
00113 TileGeometryLoad::TileGeometryLoad(const TileGeometryLoad &source):
00114 _nodeId(source._nodeId),
00115 _useFaceDistribution(source._useFaceDistribution),
00116 _valid(source._valid)
00117 {
00118 _min[0] = source._min[0];
00119 _min[1] = source._min[1];
00120 _max[0] = source._max[0];
00121 _max[1] = source._max[1];
00122 _faces = source._faces;
00123 _visible = source._visible;
00124 _faceDistribution = source._faceDistribution;
00125 _areaSize = source._areaSize;
00126 }
00127
00128
00129
00130
00133 TileGeometryLoad::~TileGeometryLoad(void)
00134 {
00135 }
00136
00140 void TileGeometryLoad::updateView(Matrix &viewing,
00141 Matrix &projection,
00142 Real32 rNear,
00143 UInt32 width,
00144 UInt32 height)
00145 {
00146 Vec3f vol[2];
00147 Pnt3f pnt;
00148 Real32 minx = 0.0,miny = 0.0;
00149 Real32 maxx = 0.0,maxy = 0.0;
00150 Matrix *p;
00151 Real32 bestScalX;
00152 UInt32 bestDirX = 0;
00153 Real32 bestScalY;
00154 UInt32 bestDirY = 0;
00155
00156 NodePtr node = dynamic_cast<NodePtr>(FieldContainerFactory::the()->getContainer(_nodeId));
00157 if(node == NullFC)
00158 return;
00159
00160
00161 Matrix m=node->getToWorld();
00162 m.multLeft(viewing);
00163
00164 node->updateVolume();
00165 DynamicVolume volume=node->getVolume();
00166
00167
00168
00169
00170
00171
00172
00173
00174 volume.transform(m);
00175
00176 volume.getBounds(vol[0], vol[1]);
00177
00178 if(vol[0][2] > -rNear)
00179 {
00180 _visible=false;
00181 return;
00182 }
00183
00184
00185 if(_useFaceDistribution)
00186 {
00187 Real32 scal;
00188 Vec3f xdir(m[0][0],m[1][0],m[2][0]);
00189 Vec3f ydir(m[0][1],m[1][1],m[2][1]);
00190 xdir.normalize();
00191 ydir.normalize();
00192 bestScalX=bestScalY=0;
00193 for(UInt32 dir=0;dir<_directions.size();++dir)
00194 {
00195 scal=_directions[dir].getNormal()*xdir;
00196 if(scal>bestScalX)
00197 {
00198 bestScalX=scal;
00199 bestDirX =dir*2;
00200 }
00201 if((-scal)>bestScalX)
00202 {
00203 bestScalX=-scal;
00204 bestDirX =dir*2+1;
00205 }
00206 scal=_directions[dir].getNormal()*ydir;
00207 if(scal>bestScalY)
00208 {
00209 bestScalY=scal;
00210 bestDirY =dir*2;
00211 }
00212 if((-scal)>bestScalY)
00213 {
00214 bestScalY=-scal;
00215 bestDirY =dir*2+1;
00216 }
00217 }
00218
00219
00220 _faceDistDirX=bestDirX;
00221 _faceDistDirY=bestDirY;
00222
00223
00224 }
00225
00226 if(vol[1][2] > -rNear)
00227 {
00228
00229 vol[1][2] = -rNear;
00230 p=&projection;
00231 }
00232 else
00233 {
00234
00235 node->getVolume().getBounds(vol[0], vol[1]);
00236 m.multLeft(projection);
00237 p=&m;
00238 }
00239
00240 for(int i=0;i<8;++i)
00241 {
00242 p->multFullMatrixPnt(Pnt3f( vol[ (i )&1 ][0] ,
00243 vol[ (i>>1)&1 ][1] ,
00244 vol[ (i>>2)&1 ][2]) , pnt);
00245 if(i>0)
00246 {
00247 if(minx > pnt[0]) minx = pnt[0];
00248 if(miny > pnt[1]) miny = pnt[1];
00249 if(maxx < pnt[0]) maxx = pnt[0];
00250 if(maxy < pnt[1]) maxy = pnt[1];
00251 }
00252 else
00253 {
00254 maxx = minx = pnt[0];
00255 maxy = miny = pnt[1];
00256 }
00257 }
00258
00259 if(maxx<-1 || maxy<-1 ||
00260 minx> 1 || miny> 1)
00261 {
00262 _visible = false;
00263 }
00264 else
00265 {
00266 minx=width * ( minx + 1.0f ) / 2.0f - .5f;
00267 maxx=width * ( maxx + 1.0f ) / 2.0f + .5f;
00268 miny=height * ( miny + 1.0f ) / 2.0f - .5f;
00269 maxy=height * ( maxy + 1.0f ) / 2.0f + .5f;
00270 _min[0]=(Int32)minx;
00271 _max[0]=(Int32)maxx;
00272 _min[1]=(Int32)miny;
00273 _max[1]=(Int32)maxy;
00274
00275 _areaSize =
00276 (Real32)( _max[0] - _min[0] + 1 ) *
00277 (Real32)( _max[1] - _min[1] + 1 );
00278
00279
00280
00281
00282
00283
00284 _visible = true;
00285 }
00286 }
00287
00296 void TileGeometryLoad::updateGeometry()
00297 {
00298 NodePtr node = dynamic_cast<NodePtr>(FieldContainerFactory::the()->getContainer(_nodeId));
00299 if(node == NullFC)
00300 return;
00301
00302 const OSG::Volume *volume = &(node->getVolume().getInstance());
00303 TriangleIterator f;
00304 int p,s;
00305 Vec3f vmin,vmax;
00306 Pnt3f pos;
00307 Real32 min = 0.0,max = 0.0;
00308 PrimitiveIterator it;
00309 NodeCorePtr core;
00310 GeometryPtr geo;
00311 const Real32 sq2 = osgSqrt(2.0f);
00312 const Real32 sq3 = osgSqrt(3.0f);
00313
00314 _faces = 0;
00315 core=node->getCore();
00316 if(node->getCore() == NullFC)
00317 return;
00318 geo=dynamic_cast<GeometryPtr>(core);
00319 if(geo == NullFC)
00320 return;
00321
00322
00323 volume->getBounds(vmin,vmax);
00324
00325
00326 for(f=geo->beginTriangles() ; f!=geo->endTriangles() ; ++f)
00327 {
00328 ++_faces;
00329 }
00330 if(_useFaceDistribution)
00331 {
00332 _faceDistribution.resize(_directions.size()*2);
00333
00334 for(UInt32 d=0;d<_directions.size();++d)
00335 {
00336
00337 _faceDistribution[d*2 ].resize(FACE_DISTRIBUTION_SAMPLING_COUNT);
00338 _faceDistribution[d*2+1].resize(FACE_DISTRIBUTION_SAMPLING_COUNT);
00339 for(s=0;s<FACE_DISTRIBUTION_SAMPLING_COUNT;++s)
00340 {
00341 _faceDistribution[d*2 ][s]=0;
00342 _faceDistribution[d*2+1][s]=0;
00343 }
00344
00345 for(f=geo->beginTriangles() ;
00346 f!=geo->endTriangles() ;
00347 ++f)
00348 {
00349 for(p=0;p<3;++p)
00350 {
00351
00352 pos=(f.getPosition(p) - vmin);
00353 pos[0]/=vmax[0]-vmin[0];
00354 pos[1]/=vmax[1]-vmin[1];
00355 pos[2]/=vmax[2]-vmin[2];
00356 if(p==0)
00357 {
00358 max=min=_directions[d].distance(pos);
00359 }
00360 else
00361 {
00362 max=osgMax(max,_directions[d].distance(pos));
00363 min=osgMin(min,_directions[d].distance(pos));
00364 }
00365 }
00366 if(d>=7)
00367 {
00368 min/=sq2;
00369 max/=sq2;
00370 }
00371 else if(d>=3)
00372 {
00373 min/=sq3;
00374 max/=sq3;
00375 }
00376 _faceDistribution
00377 [d*2 ]
00378 [(int)(ceil(min*
00379 (FACE_DISTRIBUTION_SAMPLING_COUNT-1)))]++;
00380 _faceDistribution
00381 [d*2+1]
00382 [(int)(ceil((1-max)*
00383 (FACE_DISTRIBUTION_SAMPLING_COUNT-1)))]++;
00384 }
00385 }
00386 for(UInt32 d=0;d<_directions.size();++d)
00387 {
00388 _faceDistribution[d*2 ][0]/=_faces;
00389 _faceDistribution[d*2+1][0]/=_faces;
00390 for(s=1;s<FACE_DISTRIBUTION_SAMPLING_COUNT;++s)
00391 {
00392 _faceDistribution[d*2 ][s]/=_faces;
00393 _faceDistribution[d*2+1][s]/=_faces;
00394 _faceDistribution[d*2 ][s]+=_faceDistribution[d*2 ][s-1];
00395 _faceDistribution[d*2+1][s]+=_faceDistribution[d*2+1][s-1];
00396 }
00397 #if 0
00398 printf("--> ");
00399 for(s=0;s<FACE_DISTRIBUTION_SAMPLING_COUNT;++s)
00400 printf("%4.3f ",_faceDistribution[d*2 ][s]);
00401 printf("\n<-- ");
00402 for(s=0;s<FACE_DISTRIBUTION_SAMPLING_COUNT;++s)
00403 printf("%4.3f ",_faceDistribution[d*2+1][s]);
00404 printf("\n");
00405 #endif
00406 }
00407 }
00408 }
00409
00410
00411
00412
00415 TileGeometryLoad& TileGeometryLoad::operator=(const TileGeometryLoad &source)
00416 {
00417 if(this == &source)
00418 return *this;
00419 _min[0] = source._min[0];
00420 _min[1] = source._min[1];
00421 _max[0] = source._max[0];
00422 _max[1] = source._max[1];
00423 _faces = source._faces;
00424 _visible = source._visible;
00425 _faceDistribution = source._faceDistribution;
00426 _faceDistDirX = source._faceDistDirX;
00427 _faceDistDirY = source._faceDistDirY;
00428 _nodeId = source._nodeId;
00429 _useFaceDistribution = source._useFaceDistribution;
00430 _areaSize = source._areaSize;
00431
00432 return *this;
00433 }
00434
00435
00436
00437
00438 void TileGeometryLoad::dump(void)
00439 {
00440 if(_visible)
00441 {
00442 SLOG << "Min/Max :"
00443 << _min[0] << " " << _min[1] << " / "
00444 << _max[0] << " " << _max[1] << std::endl;
00445 }
00446 else
00447 {
00448 SLOG << "invisible " << std::endl;
00449 }
00450 SLOG << "Faces :" << _faces << std::endl;
00451 }
00452
00453
00454
00455
00458 const Int32 *TileGeometryLoad::getMin()
00459 {
00460 return _min;
00461 }
00462
00465 const Int32 *TileGeometryLoad::getMax()
00466 {
00467 return _max;
00468 }
00469
00472 bool TileGeometryLoad::isVisible() const
00473 {
00474 return _visible;
00475 }
00476
00479 NodePtr TileGeometryLoad::getNode() const
00480 {
00481 return dynamic_cast<NodePtr>(FieldContainerFactory::the()->getContainer(_nodeId));
00482 }
00483
00486 UInt32 TileGeometryLoad::getFaces()
00487 {
00488 return _faces;
00489 }
00490
00493 Real32 TileGeometryLoad::getVisibleFraction( const Int32 wmin[2],
00494 const Int32 wmax[2],
00495 Int32 viswmin[2],
00496 Int32 viswmax[2] )
00497 {
00498 Real32 x,y;
00499
00500 if(_visible==false)
00501 return 0;
00502
00503
00504 if(!getVisibleArea(wmin,wmax,viswmin,viswmax))
00505 {
00506
00507 return 0;
00508 }
00509
00510 if(viswmin[0] == _min[0] &&
00511 viswmin[1] == _min[1] &&
00512 viswmax[0] == _max[0] &&
00513 viswmax[1] == _max[1])
00514 {
00515 return 1;
00516 }
00517
00518 if(_useFaceDistribution)
00519 {
00520 x=1.0f/(_max[0]-_min[0]+1);
00521 y=1.0f/(_max[1]-_min[1]+1);
00522 return
00523 (getFaceDistribution(_faceDistDirX^1,
00524 1.0f - (viswmin[0] - _min[0] ) * x) +
00525 getFaceDistribution(_faceDistDirX,
00526 (viswmax[0] - _min[0] + 1) * x) - 1)
00527 *
00528 (getFaceDistribution(_faceDistDirY^1,
00529 1.0f - (viswmin[1] - _min[1] ) * y) +
00530 getFaceDistribution(_faceDistDirY,
00531 (viswmax[1] - _min[1] + 1) * y) - 1);
00532 }
00533 else
00534 {
00535 return
00536 ((Real32)(viswmax[0] - viswmin[0] + 1) *
00537 (Real32)(viswmax[1] - viswmin[1] + 1)) / _areaSize;
00538 }
00539 }
00540
00543 bool TileGeometryLoad::getVisibleArea( const Int32 wmin[2],
00544 const Int32 wmax[2],
00545 Int32 viswmin[2],
00546 Int32 viswmax[2] )
00547 {
00548 viswmin[0] = osgMax(wmin[0],_min[0]);
00549 viswmin[1] = osgMax(wmin[1],_min[1]);
00550 viswmax[0] = osgMin(wmax[0],_max[0]);
00551 viswmax[1] = osgMin(wmax[1],_max[1]);
00552
00553 if(viswmin[0] > viswmax[0] ||
00554 viswmin[1] > viswmax[1])
00555 return false;
00556 else
00557 return true;
00558 }
00559
00566 bool TileGeometryLoad::checkRegion( Int32 min[2],
00567 Int32 max[2] )
00568 {
00569 if(min[0] > _max[0] ||
00570 max[0] < _min[0] ||
00571 min[1] > _max[1] ||
00572 max[1] < _min[1])
00573 return false;
00574 else
00575 return true;
00576 }
00577
00578 void TileGeometryLoad::setValid(bool s)
00579 {
00580 _valid = s;
00581 }
00582
00583 bool TileGeometryLoad::isInvalid(void)
00584 {
00585 return !_valid;
00586 }
00587
00588
00589
00590
00591 std::vector<Plane> TileGeometryLoad::_directions;