OSGScreenLOD.cpp

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002  *                                OpenSG                                     *
00003  *                                                                           *
00004  *                                                                           *
00005  *               Copyright (C) 2000-2006 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 <cstdlib>
00044 #include <cstdio>
00045
00046 #include "OSGConfig.h"
00047 #include "OSGRenderAction.h"
00048
00049 #include "OSGScreenLOD.h"
00050 #include "OSGDrawableStatsAttachment.h"
00051
00052 OSG_USING_NAMESPACE
00053
00054 // Documentation for this class is emited in the
00055 // OSGScreenLODBase.cpp file.
00056 // To modify it, please change the .fcd file (OSGScreenLOD.fcd) and
00057 // regenerate the base file.
00058
00059 /***************************************************************************\
00060  *                           Class variables                               *
00061 \***************************************************************************/
00062
00063 /***************************************************************************\
00064  *                           Class methods                                 *
00065 \***************************************************************************/
00066
00067 void ScreenLOD::initMethod(InitPhase ePhase)
00068 {
00069     Inherited::initMethod(ePhase);
00070
00071     if(ePhase == TypeObject::SystemPost)
00072     {
00073         typedef ActionBase::ResultE (ScreenLOD::*Callback)(Action *);
00074
00075         Callback enter = &ScreenLOD::renderEnter;
00076
00077         RenderAction::registerEnterDefault(
00078             getClassType(),
00079             reinterpret_cast<Action::Callback>(enter));
00080     }
00081 }
00082
00083
00084 /***************************************************************************\
00085  *                           Instance methods                              *
00086 \***************************************************************************/
00087
00088 ActionBase::ResultE ScreenLOD::renderEnter(Action *action)
00089 {
00090     RenderAction  *ra        = dynamic_cast<RenderAction*>(action);
00091
00092     Int32           numLevels = action->getNNodes();
00093     Int32           index     = 0;
00094
00095     Int32           numCovOverrides = getMFCoverageOverride()->size();
00096     bool            use_overrides(numCovOverrides > 0);
00097
00098     if(numLevels > 1)
00099     {
00100         if((ra->getScreenLODCoverageThreshold() > 0.f) || use_overrides)
00101         {
00102             // -- Compute bounding volume screen coverage of current node -- //
00103             Matrixr worldToScreen;
00104 #if 1 
00105             Camera* cam = ra->getCamera();
00106             Viewport* vp = ra->getViewport();
00107             cam->getWorldToScreen(worldToScreen, *vp);
00108 #else
00109             worldToScreen = da->getDrawEnv()->getWorldToScreen();
00110 #endif
00111 
00112             const BoxVolume &volume = ra->getActNode()->getVolume();
00113             Pnt3r min,max;
00114             volume.getBounds(min, max);
00115             Pnt3r p[8];
00116             p[0].setValues(min[0],min[1],min[2]);
00117             p[1].setValues(max[0],min[1],min[2]);
00118             p[2].setValues(min[0],max[1],min[2]);
00119             p[3].setValues(min[0],min[1],max[2]);
00120             p[4].setValues(max[0],max[1],min[2]);
00121             p[5].setValues(max[0],min[1],max[2]);
00122             p[6].setValues(min[0],max[1],max[2]);
00123             p[7].setValues(max[0],max[1],max[2]);
00124
00125             for(UInt32 i = 0; i<8;i++)
00126             {
00127                 ra->topMatrix().mult    (p[i], p[i]);
00128                 worldToScreen  .multFull(p[i], p[i]);
00129             }
00130             min=p[0];
00131             max=p[0];
00132             for(UInt32 i = 0; i<8; i++)
00133             {
00134                for(UInt32 j=0; j<2; j++)
00135                {
00136                   if(p[i][j] < min[j])
00137                   {
00138                     min[j] = p[i][j];
00139                   }
00140                   if(p[i][j] > max[j])
00141                   {
00142                     max[j] = p[i][j];
00143                   }
00144                }
00145             }
00146             max[0] = osgClamp(-1.f, max[0], 1.f);
00147             max[1] = osgClamp(-1.f, max[1], 1.f);
00148             min[0] = osgClamp(-1.f, min[0], 1.f);
00149             min[1] = osgClamp(-1.f, min[1], 1.f);
00150
00151             // cbb (coverage bounding box) is the percent of the screen real estate this would cover
00152             Real32 cbb = (max[0] - min[0]) * (max[1] - min[1]) / 4.f;
00153
00154             // Default degredation based computation
00155             if (!use_overrides)
00156             {
00157                //Get max LOD number of triangles
00158                Node *pmax = action->getNode(0);
00159                DrawableStatsAttachment *st_max =
00160                    DrawableStatsAttachment::get(pmax);
00161
00162                if(st_max == NULL)
00163                {
00164                   DrawableStatsAttachment::addTo(pmax);
00165                   st_max = DrawableStatsAttachment::get(pmax);
00166                }
00167                st_max->validate();
00168
00169                //Get min LOD number of triangles
00170                Node *pmin = action->getNode(numLevels-1);
00171                DrawableStatsAttachment *st_min =
00172                    DrawableStatsAttachment::get(pmin);
00173                if(st_min == NULL)
00174                {
00175                   DrawableStatsAttachment::addTo(pmin);
00176                   st_min = DrawableStatsAttachment::get(pmin);
00177                }
00178                st_min->validate();
00179
00180                // Find out what the average degradation of triangles is each level
00181                Real32 deg_percent = 1.0 - (st_min->getTriangles() / st_max->getTriangles());
00182                deg_percent = deg_percent / numLevels;
00183                if(deg_percent >= 1.0)
00184                {
00185                    cbb = ra->getScreenLODCoverageThreshold(); //just pick this lod
00186                }
00187
00188                Real32 base_percent = ra->getScreenLODCoverageThreshold(); //Above this renders at full res!
00189                Real32 user_deg_factor = ra->getScreenLODDegradationFactor();
00190                // While the screen percentage of the object is less that the percent allowed for the current LOD
00191                // move down a LOD and find out the new allowed percentage
00192                while(cbb < base_percent)
00193                {
00194                    base_percent= base_percent * deg_percent * user_deg_factor;
00195                    index++;
00196                    if(index >= numLevels)
00197                        break;
00198                }
00199             }
00200             // Use override values
00201             else
00202             {
00203                 unsigned idx_limit = osgMin(numLevels, numCovOverrides);
00204
00205                 if(cbb > (*(getMFCoverageOverride()))[0])      // If greater then first, use first index
00206                 {
00207                     index = 0;
00208                 }
00209                 else if(cbb <= (*(getMFCoverageOverride()))[numCovOverrides-1])    // If greater then max
00210                 {
00211                     index = (numLevels > numCovOverrides) ? numCovOverrides : (idx_limit-1);
00212                 }
00213                 else
00214                 {
00215                     Int32 i = 1;
00216
00217                     // While: more to check && ! (over[i-1] >= cbb > over[i])
00218                     while( (i < numCovOverrides) &&
00219                            !( (cbb <= (*(getMFCoverageOverride()))[i-1]) &&
00220                               (cbb >  (*(getMFCoverageOverride()))[i]  )   ) )
00221                     {
00222                         i++;
00223                     }
00224                     index = i;      // clamped below
00225                 }
00226             }
00227         }
00228     }
00229
00230     if (index >= numLevels)
00231     {
00232         index=numLevels-1;
00233     }
00234
00235     //if (!use_overrides)
00236     //{
00237        // See if we have a minimum LOD that we want to maintain
00238        Int32 lowestLOD = ra->getScreenLODNumLevels();
00239        if(lowestLOD != 0) // if using a minLOD
00240        {
00241          lowestLOD--; // LODS is 0 based, NumLevels is 1 based
00242          if(index > lowestLOD)
00243             index = lowestLOD;
00244        }
00245     //}
00246
00247     ra->useNodeList();
00248     if(ra->isVisible(action->getNode(index)))
00249     {
00250         ra->addNode(action->getNode(index));
00251     }
00252
00253     return ActionBase::Continue;
00254 }
00255
00256 /*-------------------------------------------------------------------------*\
00257  -  private                                                                 -
00258 \*-------------------------------------------------------------------------*/
00259
00260 /*----------------------- constructors & destructors ----------------------*/
00261
00262 ScreenLOD::ScreenLOD(void) :
00263     Inherited()
00264 {
00265 }
00266
00267 ScreenLOD::ScreenLOD(const ScreenLOD &source) :
00268     Inherited(source)
00269 {
00270 }
00271
00272 ScreenLOD::~ScreenLOD(void)
00273 {
00274 }
00275
00276 /*----------------------------- class specific ----------------------------*/
00277
00278 void ScreenLOD::changed(ConstFieldMaskArg whichField,
00279                         UInt32            origin,
00280                         BitVector         details)
00281 {
00282     Inherited::changed(whichField, origin, details);
00283 }
00284
00285 void ScreenLOD::dump(      UInt32    ,
00286                          const BitVector ) const
00287 {
00288     SLOG << "Dump ScreenLOD NI" << std::endl;
00289 }