Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

OSGTileGeometryLoad.cpp

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002  *                                OpenSG                                     *
00003  *                                                                           *
00004  *                                                                           *
00005  *             Copyright (C) 2000-2002 by the OpenSG Forum                   *
00006  *                                                                           *
00007  *                            www.opensg.org                                 *
00008  *                                                                           *
00009  *   contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de          *
00010  *                                                                           *
00011 \*---------------------------------------------------------------------------*/
00012 /*---------------------------------------------------------------------------*\
00013  *                                License                                    *
00014  *                                                                           *
00015  * This library is free software; you can redistribute it and/or modify it   *
00016  * under the terms of the GNU Library General Public License as published    *
00017  * by the Free Software Foundation, version 2.                               *
00018  *                                                                           *
00019  * This library is distributed in the hope that it will be useful, but       *
00020  * WITHOUT ANY WARRANTY; without even the implied warranty of                *
00021  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU         *
00022  * Library General Public License for more details.                          *
00023  *                                                                           *
00024  * You should have received a copy of the GNU Library General Public         *
00025  * License along with this library; if not, write to the Free Software       *
00026  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                 *
00027  *                                                                           *
00028 \*---------------------------------------------------------------------------*/
00029 /*---------------------------------------------------------------------------*\
00030  *                                Changes                                    *
00031  *                                                                           *
00032  *                                                                           *
00033  *                                                                           *
00034  *                                                                           *
00035  *                                                                           *
00036  *                                                                           *
00037 \*---------------------------------------------------------------------------*/
00038 
00039 //---------------------------------------------------------------------------
00040 //  Includes
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 /*                            Constructors                                 */
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         // create directions for face distribution
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 /*                             Destructor                                  */
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     // get whole transformation
00155     Matrix m=_node->getToWorld();
00156     m.multLeft(viewing);
00157     // get transformed volume
00158     _node->updateVolume();
00159     DynamicVolume volume=_node->getVolume();
00160     // bug in osg base
00161     /*
00162     if(volume.isEmpty())
00163     {
00164         _visible=false;
00165         return;
00166     }
00167     */
00168     volume.transform(m);
00169     // get min,max
00170     volume.getBounds(vol[0], vol[1]);
00171     // min < rNear
00172     if(vol[0][2] > -rNear)
00173     {
00174         _visible=false;
00175         return;
00176     }
00177 
00178     // find best directon for face distribution
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         // cout << "x " << xdir << " " << _directions[bestDirX>>1].getNormal() << endl;
00213         // cout << "y " << ydir << " " << _directions[bestDirY>>1].getNormal() << endl;
00214         _faceDistDirX=bestDirX;
00215         _faceDistDirY=bestDirY;
00216         // cout << "best X:" << bestDirX << endl;
00217         // cout << "best Y:" << bestDirY << endl;
00218     }
00219 
00220     if(vol[1][2] > -rNear)
00221     {
00222         // volume lays on the fron clipping plane
00223         vol[1][2] = -rNear;
00224         p=&projection;
00225     }
00226     else
00227     {
00228         // volume lays on the visible side of the clipping plane
00229         _node->getVolume().getBounds(vol[0], vol[1]);
00230         m.multLeft(projection);
00231         p=&m;
00232     }
00233     // create corners of a bounding box
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     // visible ?
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         /* Don't clip!
00273         if(_min[0]<0) _min[0]=0;
00274         if(_min[1]<0) _min[1]=0;
00275         if(_max[0]>=width ) _max[0]=width-1;
00276         if(_max[1]>=height) _max[1]=height-1;
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     // get volume min,max
00313     volume->getBounds(vmin,vmax);
00314 
00315     // count faces
00316     for(f=geo->beginTriangles() ; f!=geo->endTriangles() ; ++f)
00317     {
00318         ++_faces;
00319     }
00320     if(_useFaceDistribution)
00321     {
00322         _faceDistribution.resize(_directions.size()*2);
00323         // loop through all directions
00324         for(UInt32 d=0;d<_directions.size();++d)
00325         {
00326             // init dist
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             // loop over all faces
00335             for(f=geo->beginTriangles() ; 
00336                 f!=geo->endTriangles() ;
00337                 ++f)
00338             {
00339                 for(p=0;p<3;++p)
00340                 {
00341                     // get point and rescale
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 /*                             Assignment                                  */
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 /*                             dump                                        */
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 /*                             get                                         */
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     // get visible area
00494     if(!getVisibleArea(wmin,wmax,viswmin,viswmax))
00495     {
00496         // not in region
00497         return 0;
00498     }
00499     // geometry complete in region?
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     // not in region
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 /*                              static                                     */
00570 
00571 std::vector<Plane>    TileGeometryLoad::_directions;
00572 
00573 /*-------------------------------------------------------------------------*/
00574 /*                              cvs id's                                   */
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 }

Generated on Thu Aug 25 04:11:43 2005 for OpenSG by  doxygen 1.4.3