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(NodePtr node,
00067 bool useFaceDistribution):
00068 _node(node),
00069 _faces(0),
00070 _useFaceDistribution(useFaceDistribution)
00071 {
00072 if(_directions.size()==0)
00073 {
00074
00075 _directions.push_back(
00076 Plane(Vec3f( 1, 0, 0) ,Pnt3f(0,0,0)));
00077 _directions.push_back(
00078 Plane(Vec3f( 0, 1, 0) ,Pnt3f(0,0,0)));
00079 _directions.push_back(
00080 Plane(Vec3f( 0, 0, 1) ,Pnt3f(0,0,0)));
00081
00082 _directions.push_back(
00083 Plane(Vec3f( 1, 1, 1)*(1/osgsqrt(3.0f)),Pnt3f(0,0,0)));
00084 _directions.push_back(
00085 Plane(Vec3f(-1, 1, 1)*(1/osgsqrt(3.0f)),Pnt3f(1,0,0)));
00086 _directions.push_back(
00087 Plane(Vec3f( 1,-1, 1)*(1/osgsqrt(3.0f)),Pnt3f(0,1,0)));
00088 _directions.push_back(
00089 Plane(Vec3f( 1, 1,-1)*(1/osgsqrt(3.0f)),Pnt3f(0,0,1)));
00090
00091 _directions.push_back(
00092 Plane(Vec3f( 1, 1, 0)*(1/osgsqrt(2.0f)),Pnt3f(0,0,0)));
00093 _directions.push_back(
00094 Plane(Vec3f( 1,-1, 0)*(1/osgsqrt(2.0f)),Pnt3f(0,1,0)));
00095 _directions.push_back(
00096 Plane(Vec3f( 0, 1, 1)*(1/osgsqrt(2.0f)),Pnt3f(0,0,0)));
00097 _directions.push_back(
00098 Plane(Vec3f( 0,-1, 1)*(1/osgsqrt(2.0f)),Pnt3f(0,1,0)));
00099 _directions.push_back(
00100 Plane(Vec3f( 1, 0, 1)*(1/osgsqrt(2.0f)),Pnt3f(0,0,0)));
00101 _directions.push_back(
00102 Plane(Vec3f(-1, 0, 1)*(1/osgsqrt(2.0f)),Pnt3f(1,0,0)));
00103
00104
00105 }
00106 updateGeometry();
00107 }
00108
00112 TileGeometryLoad::TileGeometryLoad(const TileGeometryLoad &source):
00113 _node(source._node),
00114 _useFaceDistribution(source._useFaceDistribution)
00115 {
00116 _min[0] = source._min[0];
00117 _min[1] = source._min[1];
00118 _max[0] = source._max[0];
00119 _max[1] = source._max[1];
00120 _faces = source._faces;
00121 _visible = source._visible;
00122 _faceDistribution = source._faceDistribution;
00123 _areaSize = source._areaSize;
00124 }
00125
00126
00127
00128
00131 TileGeometryLoad::~TileGeometryLoad(void)
00132 {
00133 }
00134
00138 void TileGeometryLoad::updateView(Matrix &viewing,
00139 Matrix &projection,
00140 Real32 rNear,
00141 UInt32 width,
00142 UInt32 height)
00143 {
00144 Vec3f vol[2];
00145 Pnt3f pnt;
00146 Real32 minx = 0.0,miny = 0.0;
00147 Real32 maxx = 0.0,maxy = 0.0;
00148 Matrix *p;
00149 Real32 bestScalX;
00150 UInt32 bestDirX = 0;
00151 Real32 bestScalY;
00152 UInt32 bestDirY = 0;
00153
00154
00155 Matrix m=_node->getToWorld();
00156 m.multLeft(viewing);
00157
00158 _node->updateVolume();
00159 DynamicVolume volume=_node->getVolume();
00160
00161
00162
00163
00164
00165
00166
00167
00168 volume.transform(m);
00169
00170 volume.getBounds(vol[0], vol[1]);
00171
00172 if(vol[0][2] > -rNear)
00173 {
00174 _visible=false;
00175 return;
00176 }
00177
00178
00179 if(_useFaceDistribution)
00180 {
00181 Real32 scal;
00182 Vec3f xdir(m[0][0],m[1][0],m[2][0]);
00183 Vec3f ydir(m[0][1],m[1][1],m[2][1]);
00184 xdir.normalize();
00185 ydir.normalize();
00186 bestScalX=bestScalY=0;
00187 for(UInt32 dir=0;dir<_directions.size();++dir)
00188 {
00189 scal=_directions[dir].getNormal()*xdir;
00190 if(scal>bestScalX)
00191 {
00192 bestScalX=scal;
00193 bestDirX =dir*2;
00194 }
00195 if((-scal)>bestScalX)
00196 {
00197 bestScalX=-scal;
00198 bestDirX =dir*2+1;
00199 }
00200 scal=_directions[dir].getNormal()*ydir;
00201 if(scal>bestScalY)
00202 {
00203 bestScalY=scal;
00204 bestDirY =dir*2;
00205 }
00206 if((-scal)>bestScalY)
00207 {
00208 bestScalY=-scal;
00209 bestDirY =dir*2+1;
00210 }
00211 }
00212
00213
00214 _faceDistDirX=bestDirX;
00215 _faceDistDirY=bestDirY;
00216
00217
00218 }
00219
00220 if(vol[1][2] > -rNear)
00221 {
00222
00223 vol[1][2] = -rNear;
00224 p=&projection;
00225 }
00226 else
00227 {
00228
00229 _node->getVolume().getBounds(vol[0], vol[1]);
00230 m.multLeft(projection);
00231 p=&m;
00232 }
00233
00234 for(int i=0;i<8;++i)
00235 {
00236 p->multFullMatrixPnt(Pnt3f( vol[ (i )&1 ][0] ,
00237 vol[ (i>>1)&1 ][1] ,
00238 vol[ (i>>2)&1 ][2]) , pnt);
00239 if(i>0)
00240 {
00241 if(minx > pnt[0]) minx = pnt[0];
00242 if(miny > pnt[1]) miny = pnt[1];
00243 if(maxx < pnt[0]) maxx = pnt[0];
00244 if(maxy < pnt[1]) maxy = pnt[1];
00245 }
00246 else
00247 {
00248 maxx = minx = pnt[0];
00249 maxy = miny = pnt[1];
00250 }
00251 }
00252
00253 if(maxx<-1 || maxy<-1 ||
00254 minx> 1 || miny> 1)
00255 {
00256 _visible = false;
00257 }
00258 else
00259 {
00260 minx=width * ( minx + 1.0f ) / 2.0f - .5f;
00261 maxx=width * ( maxx + 1.0f ) / 2.0f + .5f;
00262 miny=height * ( miny + 1.0f ) / 2.0f - .5f;
00263 maxy=height * ( maxy + 1.0f ) / 2.0f + .5f;
00264 _min[0]=(Int32)minx;
00265 _max[0]=(Int32)maxx;
00266 _min[1]=(Int32)miny;
00267 _max[1]=(Int32)maxy;
00268
00269 _areaSize =
00270 (Real32)( _max[0] - _min[0] + 1 ) *
00271 (Real32)( _max[1] - _min[1] + 1 );
00272
00273
00274
00275
00276
00277
00278 _visible = true;
00279 }
00280 }
00281
00290 void TileGeometryLoad::updateGeometry()
00291 {
00292 const OSG::Volume *volume = &(_node->getVolume().getInstance());
00293 TriangleIterator f;
00294 int p,s;
00295 Vec3f vmin,vmax;
00296 Pnt3f pos;
00297 Real32 min = 0.0,max = 0.0;
00298 PrimitiveIterator it;
00299 NodeCorePtr core;
00300 GeometryPtr geo;
00301 const Real32 sq2=osgsqrt(2.0f);
00302 const Real32 sq3=osgsqrt(3.0f);
00303
00304 _faces = 0;
00305 core=_node->getCore();
00306 if(_node->getCore() == NullFC)
00307 return;
00308 geo=GeometryPtr::dcast(core);
00309 if(geo == NullFC)
00310 return;
00311
00312
00313 volume->getBounds(vmin,vmax);
00314
00315
00316 for(f=geo->beginTriangles() ; f!=geo->endTriangles() ; ++f)
00317 {
00318 ++_faces;
00319 }
00320 if(_useFaceDistribution)
00321 {
00322 _faceDistribution.resize(_directions.size()*2);
00323
00324 for(UInt32 d=0;d<_directions.size();++d)
00325 {
00326
00327 _faceDistribution[d*2 ].resize(FACE_DISTRIBUTION_SAMPLING_COUNT);
00328 _faceDistribution[d*2+1].resize(FACE_DISTRIBUTION_SAMPLING_COUNT);
00329 for(s=0;s<FACE_DISTRIBUTION_SAMPLING_COUNT;++s)
00330 {
00331 _faceDistribution[d*2 ][s]=0;
00332 _faceDistribution[d*2+1][s]=0;
00333 }
00334
00335 for(f=geo->beginTriangles() ;
00336 f!=geo->endTriangles() ;
00337 ++f)
00338 {
00339 for(p=0;p<3;++p)
00340 {
00341
00342 pos=(f.getPosition(p) - vmin);
00343 pos[0]/=vmax[0]-vmin[0];
00344 pos[1]/=vmax[1]-vmin[1];
00345 pos[2]/=vmax[2]-vmin[2];
00346 if(p==0)
00347 {
00348 max=min=_directions[d].distance(pos);
00349 }
00350 else
00351 {
00352 max=osgMax(max,_directions[d].distance(pos));
00353 min=osgMin(min,_directions[d].distance(pos));
00354 }
00355 }
00356 if(d>=7)
00357 {
00358 min/=sq2;
00359 max/=sq2;
00360 }
00361 else if(d>=3)
00362 {
00363 min/=sq3;
00364 max/=sq3;
00365 }
00366 _faceDistribution
00367 [d*2 ]
00368 [(int)(ceil(min*
00369 (FACE_DISTRIBUTION_SAMPLING_COUNT-1)))]++;
00370 _faceDistribution
00371 [d*2+1]
00372 [(int)(ceil((1-max)*
00373 (FACE_DISTRIBUTION_SAMPLING_COUNT-1)))]++;
00374 }
00375 }
00376 for(UInt32 d=0;d<_directions.size();++d)
00377 {
00378 _faceDistribution[d*2 ][0]/=_faces;
00379 _faceDistribution[d*2+1][0]/=_faces;
00380 for(s=1;s<FACE_DISTRIBUTION_SAMPLING_COUNT;++s)
00381 {
00382 _faceDistribution[d*2 ][s]/=_faces;
00383 _faceDistribution[d*2+1][s]/=_faces;
00384 _faceDistribution[d*2 ][s]+=_faceDistribution[d*2 ][s-1];
00385 _faceDistribution[d*2+1][s]+=_faceDistribution[d*2+1][s-1];
00386 }
00387 #if 0
00388 printf("--> ");
00389 for(s=0;s<FACE_DISTRIBUTION_SAMPLING_COUNT;++s)
00390 printf("%4.3f ",_faceDistribution[d*2 ][s]);
00391 printf("\n<-- ");
00392 for(s=0;s<FACE_DISTRIBUTION_SAMPLING_COUNT;++s)
00393 printf("%4.3f ",_faceDistribution[d*2+1][s]);
00394 printf("\n");
00395 #endif
00396 }
00397 }
00398 }
00399
00400
00401
00402
00405 TileGeometryLoad& TileGeometryLoad::operator=(const TileGeometryLoad &source)
00406 {
00407 if(this == &source)
00408 return *this;
00409 _min[0] = source._min[0];
00410 _min[1] = source._min[1];
00411 _max[0] = source._max[0];
00412 _max[1] = source._max[1];
00413 _faces = source._faces;
00414 _visible = source._visible;
00415 _faceDistribution = source._faceDistribution;
00416 _faceDistDirX = source._faceDistDirX;
00417 _faceDistDirY = source._faceDistDirY;
00418 _node = source._node;
00419 _useFaceDistribution = source._useFaceDistribution;
00420 _areaSize = source._areaSize;
00421
00422 return *this;
00423 }
00424
00425
00426
00427
00428 void TileGeometryLoad::dump(void)
00429 {
00430 if(_visible)
00431 {
00432 SLOG << "Min/Max :"
00433 << _min[0] << " " << _min[1] << " / "
00434 << _max[0] << " " << _max[1] << std::endl;
00435 }
00436 else
00437 {
00438 SLOG << "invisible " << std::endl;
00439 }
00440 SLOG << "Faces :" << _faces << std::endl;
00441 }
00442
00443
00444
00445
00448 const Int32 *TileGeometryLoad::getMin()
00449 {
00450 return _min;
00451 }
00452
00455 const Int32 *TileGeometryLoad::getMax()
00456 {
00457 return _max;
00458 }
00459
00462 bool TileGeometryLoad::isVisible() const
00463 {
00464 return _visible;
00465 }
00466
00469 NodePtr TileGeometryLoad::getNode() const
00470 {
00471 return _node;
00472 }
00473
00476 UInt32 TileGeometryLoad::getFaces()
00477 {
00478 return _faces;
00479 }
00480
00483 Real32 TileGeometryLoad::getVisibleFraction( const Int32 wmin[2],
00484 const Int32 wmax[2],
00485 Int32 viswmin[2],
00486 Int32 viswmax[2] )
00487 {
00488 Real32 x,y;
00489
00490 if(_visible==false)
00491 return 0;
00492
00493
00494 if(!getVisibleArea(wmin,wmax,viswmin,viswmax))
00495 {
00496
00497 return 0;
00498 }
00499
00500 if(viswmin[0] == _min[0] &&
00501 viswmin[1] == _min[1] &&
00502 viswmax[0] == _max[0] &&
00503 viswmax[1] == _max[1])
00504 {
00505 return 1;
00506 }
00507
00508 if(_useFaceDistribution)
00509 {
00510 x=1.0f/(_max[0]-_min[0]+1);
00511 y=1.0f/(_max[1]-_min[1]+1);
00512 return
00513 (getFaceDistribution(_faceDistDirX^1,
00514 1.0f - (viswmin[0] - _min[0] ) * x) +
00515 getFaceDistribution(_faceDistDirX,
00516 (viswmax[0] - _min[0] + 1) * x) - 1)
00517 *
00518 (getFaceDistribution(_faceDistDirY^1,
00519 1.0f - (viswmin[1] - _min[1] ) * y) +
00520 getFaceDistribution(_faceDistDirY,
00521 (viswmax[1] - _min[1] + 1) * y) - 1);
00522 }
00523 else
00524 {
00525 return
00526 ((Real32)(viswmax[0] - viswmin[0] + 1) *
00527 (Real32)(viswmax[1] - viswmin[1] + 1)) / _areaSize;
00528 }
00529 }
00530
00533 bool TileGeometryLoad::getVisibleArea( const Int32 wmin[2],
00534 const Int32 wmax[2],
00535 Int32 viswmin[2],
00536 Int32 viswmax[2] )
00537 {
00538 viswmin[0] = osgMax(wmin[0],_min[0]);
00539 viswmin[1] = osgMax(wmin[1],_min[1]);
00540 viswmax[0] = osgMin(wmax[0],_max[0]);
00541 viswmax[1] = osgMin(wmax[1],_max[1]);
00542
00543 if(viswmin[0] > viswmax[0] ||
00544 viswmin[1] > viswmax[1])
00545 return false;
00546 else
00547 return true;
00548 }
00549
00556 bool TileGeometryLoad::checkRegion( Int32 min[2],
00557 Int32 max[2] )
00558 {
00559 if(min[0] > _max[0] ||
00560 max[0] < _min[0] ||
00561 min[1] > _max[1] ||
00562 max[1] < _min[1])
00563 return false;
00564 else
00565 return true;
00566 }
00567
00568
00569
00570
00571 std::vector<Plane> TileGeometryLoad::_directions;
00572
00573
00574
00575
00576 #ifdef __sgi
00577 #pragma set woff 1174
00578 #endif
00579
00580 #ifdef OSG_LINUX_ICC
00581 #pragma warning( disable : 177 )
00582 #endif
00583
00584 namespace
00585 {
00586 static Char8 cvsid_cpp[] = "@(#)$Id:$";
00587 static Char8 cvsid_hpp[] = OSGTILEGEOMETRYLOAD_HEADER_CVSID;
00588 static Char8 cvsid_inl[] = OSGTILEGEOMETRYLOAD_INLINE_CVSID;
00589 }