changed: gcc8 base update
[opensg.git] / Source / System / NodeCores / Groups / Misc / OSGScreenLOD.cpp
blobfddac95acd9193e8b079024f3c091a6137e19615
1 /*---------------------------------------------------------------------------*\
2 * OpenSG *
3 * *
4 * *
5 * Copyright (C) 2000-2006 by the OpenSG Forum *
6 * *
7 * www.opensg.org *
8 * *
9 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
10 * *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
13 * License *
14 * *
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. *
18 * *
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. *
23 * *
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. *
27 * *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
30 * Changes *
31 * *
32 * *
33 * *
34 * *
35 * *
36 * *
37 \*---------------------------------------------------------------------------*/
39 //---------------------------------------------------------------------------
40 // Includes
41 //---------------------------------------------------------------------------
43 #include <cstdlib>
44 #include <cstdio>
46 #include "OSGConfig.h"
47 #include "OSGRenderAction.h"
49 #include "OSGScreenLOD.h"
50 #include "OSGDrawableStatsAttachment.h"
52 OSG_USING_NAMESPACE
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 /***************************************************************************\
60 * Class variables *
61 \***************************************************************************/
63 /***************************************************************************\
64 * Class methods *
65 \***************************************************************************/
67 void ScreenLOD::initMethod(InitPhase ePhase)
69 Inherited::initMethod(ePhase);
71 if(ePhase == TypeObject::SystemPost)
73 RenderAction::registerEnterDefault(
74 getClassType(),
75 reinterpret_cast<Action::Callback>(&ScreenLOD::renderEnter));
80 /***************************************************************************\
81 * Instance methods *
82 \***************************************************************************/
84 Action::ResultE ScreenLOD::renderEnter(Action *action)
86 RenderAction *ra = dynamic_cast<RenderAction*>(action);
88 Int32 numLevels = action->getNNodes();
89 Int32 index = 0;
91 Int32 numCovOverrides = getMFCoverageOverride()->size32();
92 bool use_overrides(numCovOverrides > 0);
94 if(numLevels > 1)
96 if((ra->getScreenLODCoverageThreshold() > 0.f) || use_overrides)
98 // -- Compute bounding volume screen coverage of current node -- //
99 Matrix worldToScreen;
100 #if 0
101 Camera* cam = ra->getCamera();
102 Viewport* vp = ra->getViewport();
103 cam->getWorldToScreen(worldToScreen, *vp);
104 #else
105 worldToScreen =
106 ra->getActivePartition()->getDrawEnv().getWorldToScreen();
107 #endif
109 const BoxVolume &volume = ra->getActNode()->getVolume();
110 Pnt3f min,max;
111 volume.getBounds(min, max);
112 Pnt3f p[8];
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]);
127 min=p[0];
128 max=p[0];
129 for(UInt32 i = 0; i<8; i++)
131 for(UInt32 j=0; j<2; j++)
133 if(p[i][j] < min[j])
135 min[j] = p[i][j];
137 if(p[i][j] > max[j])
139 max[j] = p[i][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
152 if (!use_overrides)
154 //Get max LOD number of triangles
155 Node *pmax = action->getNode(0);
156 DrawableStatsAttachment *st_max =
157 DrawableStatsAttachment::get(pmax);
159 if(st_max == NULL)
161 DrawableStatsAttachment::addTo(pmax);
162 st_max = DrawableStatsAttachment::get(pmax);
164 st_max->validate();
166 //Get min LOD number of triangles
167 Node *pmin = action->getNode(numLevels-1);
168 DrawableStatsAttachment *st_min =
169 DrawableStatsAttachment::get(pmin);
170 if(st_min == NULL)
172 DrawableStatsAttachment::addTo(pmin);
173 st_min = DrawableStatsAttachment::get(pmin);
175 st_min->validate();
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;
192 index++;
193 if(index >= numLevels)
194 break;
197 // Use override values
198 else
200 unsigned idx_limit = osgMin(numLevels, numCovOverrides);
202 if(cbb > (*(getMFCoverageOverride()))[0]) // If greater then first, use first index
204 index = 0;
206 else if(cbb <= (*(getMFCoverageOverride()))[numCovOverrides-1]) // If greater then max
208 index = (numLevels > numCovOverrides) ? numCovOverrides : (idx_limit-1);
210 else
212 Int32 i = 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] ) ) )
219 i++;
221 index = i; // clamped below
227 if (index >= numLevels)
229 index=numLevels-1;
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)
240 index = lowestLOD;
244 ra->useNodeList();
245 if(ra->isVisible(action->getNode(index)))
247 ra->addNode(action->getNode(index));
250 return Action::Continue;
253 /*-------------------------------------------------------------------------*\
254 - private -
255 \*-------------------------------------------------------------------------*/
257 /*----------------------- constructors & destructors ----------------------*/
259 ScreenLOD::ScreenLOD(void) :
260 Inherited()
264 ScreenLOD::ScreenLOD(const ScreenLOD &source) :
265 Inherited(source)
269 ScreenLOD::~ScreenLOD(void)
273 /*----------------------------- class specific ----------------------------*/
275 void ScreenLOD::changed(ConstFieldMaskArg whichField,
276 UInt32 origin,
277 BitVector details)
279 Inherited::changed(whichField, origin, details);
282 void ScreenLOD::dump( UInt32 ,
283 const BitVector ) const
285 SLOG << "Dump ScreenLOD NI" << std::endl;