1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
3 * This library is open source and may be redistributed and/or modified under
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version. The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * OpenSceneGraph Public License for more details.
14#ifndef OSG_CULLSETTINGS
15#define OSG_CULLSETTINGS 1
19#include <osg/ClearNode>
25class ApplicationUsage;
27class OSG_EXPORT CullSettings
34 readEnvironmentalVariables();
37 CullSettings(ArgumentParser& arguments)
40 readEnvironmentalVariables();
41 readCommandLine(arguments);
44 CullSettings(const CullSettings& cs);
46 virtual ~CullSettings() {}
48 CullSettings& operator = (const CullSettings& settings)
50 if (this==&settings) return *this;
51 setCullSettings(settings);
56 virtual void setDefaults();
61 COMPUTE_NEAR_FAR_MODE = (0x1 << 0),
62 CULLING_MODE = (0x1 << 1),
63 LOD_SCALE = (0x1 << 2),
64 SMALL_FEATURE_CULLING_PIXEL_SIZE = (0x1 << 3),
65 CLAMP_PROJECTION_MATRIX_CALLBACK = (0x1 << 4),
66 NEAR_FAR_RATIO = (0x1 << 5),
67 IMPOSTOR_ACTIVE = (0x1 << 6),
68 DEPTH_SORT_IMPOSTOR_SPRITES = (0x1 << 7),
69 IMPOSTOR_PIXEL_ERROR_THRESHOLD = (0x1 << 8),
70 NUM_FRAMES_TO_KEEP_IMPOSTORS_SPRITES = (0x1 << 9),
71 CULL_MASK = (0x1 << 10),
72 CULL_MASK_LEFT = (0x1 << 11),
73 CULL_MASK_RIGHT = (0x1 << 12),
74 CLEAR_COLOR = (0x1 << 13),
75 CLEAR_MASK = (0x1 << 14),
76 LIGHTING_MODE = (0x1 << 15),
78 DRAW_BUFFER = (0x1 << 17),
79 READ_BUFFER = (0x1 << 18),
81 NO_VARIABLES = 0x00000000,
82 ALL_VARIABLES = 0x7FFFFFFF
85 typedef int InheritanceMask;
87 /** Set the inheritance mask used in inheritCullSettings to control which variables get overwritten by the passed in CullSettings object.*/
88 void setInheritanceMask(InheritanceMask mask) { _inheritanceMask = mask; }
90 /** Get the inheritance mask used in inheritCullSettings to control which variables get overwritten by the passed in CullSettings object.*/
91 InheritanceMask getInheritanceMask() const { return _inheritanceMask; }
93 /** Set the local cull settings values from specified CullSettings object.*/
94 void setCullSettings(const CullSettings& settings);
96 /** Inherit the local cull settings variable from specified CullSettings object, according to the inheritance mask.*/
97 virtual void inheritCullSettings(const CullSettings& settings) { inheritCullSettings(settings, _inheritanceMask); }
99 /** Inherit the local cull settings variable from specified CullSettings object, according to the inheritance mask.*/
100 virtual void inheritCullSettings(const CullSettings& settings, unsigned int inheritanceMask);
102 /** read the environmental variables.*/
103 void readEnvironmentalVariables();
105 /** read the commandline arguments.*/
106 void readCommandLine(ArgumentParser& arguments);
109 enum InheritanceMaskActionOnAttributeSetting
111 DISABLE_ASSOCIATED_INHERITANCE_MASK_BIT,
112 DO_NOT_MODIFY_INHERITANCE_MASK
115 void setInheritanceMaskActionOnAttributeSetting(InheritanceMaskActionOnAttributeSetting action) { _inheritanceMaskActionOnAttributeSetting = action; }
116 InheritanceMaskActionOnAttributeSetting getInheritanceMaskActionOnAttributeSetting() const { return _inheritanceMaskActionOnAttributeSetting; }
118 /** Apply the action, specified by the InheritanceMaskActionOnAttributeSetting, to apply to the inheritance bit mask.
119 * This method is called by CullSettings::set*() parameter methods to ensure that CullSettings inheritance mechanisms doesn't overwrite the local parameter settings.*/
120 inline void applyMaskAction(unsigned int maskBit)
122 if (_inheritanceMaskActionOnAttributeSetting==DISABLE_ASSOCIATED_INHERITANCE_MASK_BIT)
124 _inheritanceMask = _inheritanceMask & (~maskBit);
129 /** Switch the creation of Impostors on or off.
130 * Setting active to false forces the CullVisitor to use the Impostor
131 * LOD children for rendering. Setting active to true forces the
132 * CullVisitor to create the appropriate pre-rendering stages which
133 * render to the ImpostorSprite's texture.*/
134 void setImpostorsActive(bool active) { _impostorActive = active; applyMaskAction(IMPOSTOR_ACTIVE); }
136 /** Get whether impostors are active or not. */
137 bool getImpostorsActive() const { return _impostorActive; }
139 /** Set the impostor error threshold.
140 * Used in calculation of whether impostors remain valid.*/
141 void setImpostorPixelErrorThreshold(float numPixels) { _impostorPixelErrorThreshold=numPixels; applyMaskAction(IMPOSTOR_PIXEL_ERROR_THRESHOLD); }
143 /** Get the impostor error threshold.*/
144 float getImpostorPixelErrorThreshold() const { return _impostorPixelErrorThreshold; }
146 /** Set whether ImpostorSprite's should be placed in a depth sorted bin for rendering.*/
147 void setDepthSortImpostorSprites(bool doDepthSort) { _depthSortImpostorSprites = doDepthSort; applyMaskAction(DEPTH_SORT_IMPOSTOR_SPRITES); }
149 /** Get whether ImpostorSprite's are depth sorted bin for rendering.*/
150 bool getDepthSortImpostorSprites() const { return _depthSortImpostorSprites; }
152 /** Set the number of frames that an ImpostorSprite is kept whilst not being beyond,
153 * before being recycled.*/
154 void setNumberOfFrameToKeepImpostorSprites(int numFrames) { _numFramesToKeepImpostorSprites = numFrames; applyMaskAction(NUM_FRAMES_TO_KEEP_IMPOSTORS_SPRITES); }
156 /** Get the number of frames that an ImpostorSprite is kept whilst not being beyond,
157 * before being recycled.*/
158 int getNumberOfFrameToKeepImpostorSprites() const { return _numFramesToKeepImpostorSprites; }
160 enum ComputeNearFarMode
162 DO_NOT_COMPUTE_NEAR_FAR = 0,
163 COMPUTE_NEAR_FAR_USING_BOUNDING_VOLUMES,
164 COMPUTE_NEAR_FAR_USING_PRIMITIVES,
165 COMPUTE_NEAR_USING_PRIMITIVES
168 void setComputeNearFarMode(ComputeNearFarMode cnfm) { _computeNearFar=cnfm; applyMaskAction(COMPUTE_NEAR_FAR_MODE); }
169 ComputeNearFarMode getComputeNearFarMode() const { return _computeNearFar;}
171 void setNearFarRatio(double ratio) { _nearFarRatio = ratio; applyMaskAction(NEAR_FAR_RATIO); }
172 double getNearFarRatio() const { return _nearFarRatio; }
174 enum CullingModeValues
177 VIEW_FRUSTUM_SIDES_CULLING = 0x1,
178 NEAR_PLANE_CULLING = 0x2,
179 FAR_PLANE_CULLING = 0x4,
180 VIEW_FRUSTUM_CULLING = VIEW_FRUSTUM_SIDES_CULLING|
183 SMALL_FEATURE_CULLING = 0x8,
184 SHADOW_OCCLUSION_CULLING = 0x10,
185 CLUSTER_CULLING = 0x20,
186 DEFAULT_CULLING = VIEW_FRUSTUM_SIDES_CULLING|
187 SMALL_FEATURE_CULLING|
188 SHADOW_OCCLUSION_CULLING|
190 ENABLE_ALL_CULLING = VIEW_FRUSTUM_CULLING|
191 SMALL_FEATURE_CULLING|
192 SHADOW_OCCLUSION_CULLING|
196 typedef int CullingMode;
198 /** Set the culling mode for the CullVisitor to use.*/
199 void setCullingMode(CullingMode mode) { _cullingMode = mode; applyMaskAction(CULLING_MODE); }
201 /** Returns the current CullingMode.*/
202 CullingMode getCullingMode() const { return _cullingMode; }
205 void setCullMask(osg::Node::NodeMask nm) { _cullMask = nm; applyMaskAction(CULL_MASK); }
206 osg::Node::NodeMask getCullMask() const { return _cullMask; }
208 void setCullMaskLeft(osg::Node::NodeMask nm) { _cullMaskLeft = nm; applyMaskAction(CULL_MASK_LEFT); }
209 osg::Node::NodeMask getCullMaskLeft() const { return _cullMaskLeft; }
211 void setCullMaskRight(osg::Node::NodeMask nm) { _cullMaskRight = nm; applyMaskAction(CULL_MASK_RIGHT); }
212 osg::Node::NodeMask getCullMaskRight() const { return _cullMaskRight; }
214 /** Set the LOD bias for the CullVisitor to use.*/
215 void setLODScale(float scale) { _LODScale = scale; applyMaskAction(LOD_SCALE); }
217 /** Get the LOD bias.*/
218 float getLODScale() const { return _LODScale; }
220 /** Threshold at which small features are culled.
221 \param value Bounding volume size in screen space. Default is 2.0. */
222 void setSmallFeatureCullingPixelSize(float value) { _smallFeatureCullingPixelSize=value; applyMaskAction(SMALL_FEATURE_CULLING_PIXEL_SIZE); }
224 /** Get the Small Feature Culling Pixel Size.*/
225 float getSmallFeatureCullingPixelSize() const { return _smallFeatureCullingPixelSize; }
229 /** Callback for overriding the CullVisitor's default clamping of the projection matrix to computed near and far values.
230 * Note, both Matrixf and Matrixd versions of clampProjectionMatrixImplementation must be implemented as the CullVisitor
231 * can target either Matrix data type, configured at compile time.*/
232 struct ClampProjectionMatrixCallback : public osg::Referenced
234 virtual bool clampProjectionMatrixImplementation(osg::Matrixf& projection, double& znear, double& zfar) const = 0;
235 virtual bool clampProjectionMatrixImplementation(osg::Matrixd& projection, double& znear, double& zfar) const = 0;
238 /** set the ClampProjectionMatrixCallback.*/
239 void setClampProjectionMatrixCallback(ClampProjectionMatrixCallback* cpmc) { _clampProjectionMatrixCallback = cpmc; applyMaskAction(CLAMP_PROJECTION_MATRIX_CALLBACK); }
240 /** get the non const ClampProjectionMatrixCallback.*/
241 ClampProjectionMatrixCallback* getClampProjectionMatrixCallback() { return _clampProjectionMatrixCallback.get(); }
242 /** get the const ClampProjectionMatrixCallback.*/
243 const ClampProjectionMatrixCallback* getClampProjectionMatrixCallback() const { return _clampProjectionMatrixCallback.get(); }
246 /** Write out internal settings of CullSettings. */
247 void write(std::ostream& out);
251 InheritanceMask _inheritanceMask;
252 InheritanceMaskActionOnAttributeSetting _inheritanceMaskActionOnAttributeSetting;
254 ComputeNearFarMode _computeNearFar;
255 CullingMode _cullingMode;
257 float _smallFeatureCullingPixelSize;
259 ref_ptr<ClampProjectionMatrixCallback> _clampProjectionMatrixCallback;
260 double _nearFarRatio;
261 bool _impostorActive;
262 bool _depthSortImpostorSprites;
263 float _impostorPixelErrorThreshold;
264 int _numFramesToKeepImpostorSprites;
266 Node::NodeMask _cullMask;
267 Node::NodeMask _cullMaskLeft;
268 Node::NodeMask _cullMaskRight;
273template<class matrix_type, class value_type>
274bool clampProjectionMatrix(matrix_type& projection, double& znear, double& zfar, value_type nearFarRatio)
276 double epsilon = 1e-6;
277 if (zfar<znear-epsilon)
279 if (zfar != -FLT_MAX || znear != FLT_MAX)
281 OSG_INFO<<"_clampProjectionMatrix not applied, invalid depth range, znear = "<<znear<<" zfar = "<<zfar<<std::endl;
286 if (zfar<znear+epsilon)
288 // znear and zfar are too close together and could cause divide by zero problems
289 // late on in the clamping code, so move the znear and zfar apart.
290 double average = (znear+zfar)*0.5;
291 znear = average-epsilon;
292 zfar = average+epsilon;
293 // OSG_INFO << "_clampProjectionMatrix widening znear and zfar to "<<znear<<" "<<zfar<<std::endl;
296 if (fabs(projection(0,3))<epsilon && fabs(projection(1,3))<epsilon && fabs(projection(2,3))<epsilon )
298 // OSG_INFO << "Orthographic matrix before clamping"<<projection<<std::endl;
300 value_type delta_span = (zfar-znear)*0.02;
301 if (delta_span<1.0) delta_span = 1.0;
302 value_type desired_znear = znear - delta_span;
303 value_type desired_zfar = zfar + delta_span;
305 // assign the clamped values back to the computed values.
306 znear = desired_znear;
309 projection(2,2)=-2.0f/(desired_zfar-desired_znear);
310 projection(3,2)=-(desired_zfar+desired_znear)/(desired_zfar-desired_znear);
312 // OSG_INFO << "Orthographic matrix after clamping "<<projection<<std::endl;
317 // OSG_INFO << "Persepective matrix before clamping"<<projection<<std::endl;
319 //std::cout << "_computed_znear"<<_computed_znear<<std::endl;
320 //std::cout << "_computed_zfar"<<_computed_zfar<<std::endl;
322 value_type zfarPushRatio = 1.02;
323 value_type znearPullRatio = 0.98;
325 //znearPullRatio = 0.99;
327 value_type desired_znear = znear * znearPullRatio;
328 value_type desired_zfar = zfar * zfarPushRatio;
330 // near plane clamping.
331 double min_near_plane = zfar*nearFarRatio;
332 if (desired_znear<min_near_plane) desired_znear=min_near_plane;
334 // assign the clamped values back to the computed values.
335 znear = desired_znear;
338 value_type trans_near_plane = (-desired_znear*projection(2,2)+projection(3,2))/(-desired_znear*projection(2,3)+projection(3,3));
339 value_type trans_far_plane = (-desired_zfar*projection(2,2)+projection(3,2))/(-desired_zfar*projection(2,3)+projection(3,3));
341 value_type ratio = fabs(2.0/(trans_near_plane-trans_far_plane));
342 value_type center = -(trans_near_plane+trans_far_plane)/2.0;
344 projection.postMult(osg::Matrix(1.0f,0.0f,0.0f,0.0f,
346 0.0f,0.0f,ratio,0.0f,
347 0.0f,0.0f,center*ratio,1.0f));
349 // OSG_INFO << "Persepective matrix after clamping"<<projection<<std::endl;