1 /*---------------------------------------------------------------------------*\
5 * Copyright (C) 2000-2006 by the OpenSG Forum *
9 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
15 * This library is free software; you can redistribute it and/or modify it *
16 * under the terms of the GNU Library General Public License as published *
17 * by the Free Software Foundation, version 2. *
19 * This library is distributed in the hope that it will be useful, but *
20 * WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
22 * Library General Public License for more details. *
24 * You should have received a copy of the GNU Library General Public *
25 * License along with this library; if not, write to the Free Software *
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
37 \*---------------------------------------------------------------------------*/
39 //---------------------------------------------------------------------------
41 //---------------------------------------------------------------------------
46 #include "OSGConfig.h"
47 #include "OSGRenderAction.h"
49 #include "OSGScreenLOD.h"
50 #include "OSGDrawableStatsAttachment.h"
54 // Documentation for this class is emited in the
55 // OSGScreenLODBase.cpp file.
56 // To modify it, please change the .fcd file (OSGScreenLOD.fcd) and
57 // regenerate the base file.
59 /***************************************************************************\
61 \***************************************************************************/
63 /***************************************************************************\
65 \***************************************************************************/
67 void ScreenLOD::initMethod(InitPhase ePhase
)
69 Inherited::initMethod(ePhase
);
71 if(ePhase
== TypeObject::SystemPost
)
73 RenderAction::registerEnterDefault(
75 reinterpret_cast<Action::Callback
>(&ScreenLOD::renderEnter
));
80 /***************************************************************************\
82 \***************************************************************************/
84 Action::ResultE
ScreenLOD::renderEnter(Action
*action
)
86 RenderAction
*ra
= dynamic_cast<RenderAction
*>(action
);
88 Int32 numLevels
= action
->getNNodes();
91 Int32 numCovOverrides
= getMFCoverageOverride()->size32();
92 bool use_overrides(numCovOverrides
> 0);
96 if((ra
->getScreenLODCoverageThreshold() > 0.f
) || use_overrides
)
98 // -- Compute bounding volume screen coverage of current node -- //
101 Camera
* cam
= ra
->getCamera();
102 Viewport
* vp
= ra
->getViewport();
103 cam
->getWorldToScreen(worldToScreen
, *vp
);
106 ra
->getActivePartition()->getDrawEnv().getWorldToScreen();
109 const BoxVolume
&volume
= ra
->getActNode()->getVolume();
111 volume
.getBounds(min
, max
);
113 p
[0].setValues(min
[0],min
[1],min
[2]);
114 p
[1].setValues(max
[0],min
[1],min
[2]);
115 p
[2].setValues(min
[0],max
[1],min
[2]);
116 p
[3].setValues(min
[0],min
[1],max
[2]);
117 p
[4].setValues(max
[0],max
[1],min
[2]);
118 p
[5].setValues(max
[0],min
[1],max
[2]);
119 p
[6].setValues(min
[0],max
[1],max
[2]);
120 p
[7].setValues(max
[0],max
[1],max
[2]);
122 for(UInt32 i
= 0; i
<8;i
++)
124 ra
->topMatrix().mult (p
[i
], p
[i
]);
125 worldToScreen
.multFull(p
[i
], p
[i
]);
129 for(UInt32 i
= 0; i
<8; i
++)
131 for(UInt32 j
=0; j
<2; j
++)
143 max
[0] = osgClamp(-1.f
, max
[0], 1.f
);
144 max
[1] = osgClamp(-1.f
, max
[1], 1.f
);
145 min
[0] = osgClamp(-1.f
, min
[0], 1.f
);
146 min
[1] = osgClamp(-1.f
, min
[1], 1.f
);
148 // cbb (coverage bounding box) is the percent of the screen real estate this would cover
149 Real32 cbb
= (max
[0] - min
[0]) * (max
[1] - min
[1]) / 4.f
;
151 // Default degredation based computation
154 //Get max LOD number of triangles
155 Node
*pmax
= action
->getNode(0);
156 DrawableStatsAttachment
*st_max
=
157 DrawableStatsAttachment::get(pmax
);
161 DrawableStatsAttachment::addTo(pmax
);
162 st_max
= DrawableStatsAttachment::get(pmax
);
166 //Get min LOD number of triangles
167 Node
*pmin
= action
->getNode(numLevels
-1);
168 DrawableStatsAttachment
*st_min
=
169 DrawableStatsAttachment::get(pmin
);
172 DrawableStatsAttachment::addTo(pmin
);
173 st_min
= DrawableStatsAttachment::get(pmin
);
177 // Find out what the average degradation of triangles is each level
178 Real32 deg_percent
= 1.0 - (st_min
->getTriangles() / st_max
->getTriangles());
179 deg_percent
= deg_percent
/ numLevels
;
180 if(deg_percent
>= 1.0)
182 cbb
= ra
->getScreenLODCoverageThreshold(); //just pick this lod
185 Real32 base_percent
= ra
->getScreenLODCoverageThreshold(); //Above this renders at full res!
186 Real32 user_deg_factor
= ra
->getScreenLODDegradationFactor();
187 // While the screen percentage of the object is less that the percent allowed for the current LOD
188 // move down a LOD and find out the new allowed percentage
189 while(cbb
< base_percent
)
191 base_percent
= base_percent
* deg_percent
* user_deg_factor
;
193 if(index
>= numLevels
)
197 // Use override values
200 unsigned idx_limit
= osgMin(numLevels
, numCovOverrides
);
202 if(cbb
> (*(getMFCoverageOverride()))[0]) // If greater then first, use first index
206 else if(cbb
<= (*(getMFCoverageOverride()))[numCovOverrides
-1]) // If greater then max
208 index
= (numLevels
> numCovOverrides
) ? numCovOverrides
: (idx_limit
-1);
214 // While: more to check && ! (over[i-1] >= cbb > over[i])
215 while( (i
< numCovOverrides
) &&
216 !( (cbb
<= (*(getMFCoverageOverride()))[i
-1]) &&
217 (cbb
> (*(getMFCoverageOverride()))[i
] ) ) )
221 index
= i
; // clamped below
227 if (index
>= numLevels
)
232 //if (!use_overrides)
234 // See if we have a minimum LOD that we want to maintain
235 Int32 lowestLOD
= ra
->getScreenLODNumLevels();
236 if(lowestLOD
!= 0) // if using a minLOD
238 lowestLOD
--; // LODS is 0 based, NumLevels is 1 based
239 if(index
> lowestLOD
)
245 if(ra
->isVisible(action
->getNode(index
)))
247 ra
->addNode(action
->getNode(index
));
250 return Action::Continue
;
253 /*-------------------------------------------------------------------------*\
255 \*-------------------------------------------------------------------------*/
257 /*----------------------- constructors & destructors ----------------------*/
259 ScreenLOD::ScreenLOD(void) :
264 ScreenLOD::ScreenLOD(const ScreenLOD
&source
) :
269 ScreenLOD::~ScreenLOD(void)
273 /*----------------------------- class specific ----------------------------*/
275 void ScreenLOD::changed(ConstFieldMaskArg whichField
,
279 Inherited::changed(whichField
, origin
, details
);
282 void ScreenLOD::dump( UInt32
,
283 const BitVector
) const
285 SLOG
<< "Dump ScreenLOD NI" << std::endl
;