CullSettings 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
  2. *
  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.
  7. *
  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.
  12. */
  13. #ifndef OSG_CULLSETTINGS
  14. #define OSG_CULLSETTINGS 1
  15. #include <iosfwd>
  16. #include <osg/Matrix>
  17. #include <osg/ClearNode>
  18. namespace osg {
  19. // forward declare
  20. class ArgumentParser;
  21. class ApplicationUsage;
  22. class OSG_EXPORT CullSettings
  23. {
  24. public:
  25. CullSettings()
  26. {
  27. setDefaults();
  28. readEnvironmentalVariables();
  29. }
  30. CullSettings(ArgumentParser& arguments)
  31. {
  32. setDefaults();
  33. readEnvironmentalVariables();
  34. readCommandLine(arguments);
  35. }
  36. CullSettings(const CullSettings& cs);
  37. virtual ~CullSettings() {}
  38. CullSettings& operator = (const CullSettings& settings)
  39. {
  40. if (this==&settings) return *this;
  41. setCullSettings(settings);
  42. return *this;
  43. }
  44. virtual void setDefaults();
  45. enum VariablesMask
  46. {
  47. COMPUTE_NEAR_FAR_MODE = (0x1 << 0),
  48. CULLING_MODE = (0x1 << 1),
  49. LOD_SCALE = (0x1 << 2),
  50. SMALL_FEATURE_CULLING_PIXEL_SIZE = (0x1 << 3),
  51. CLAMP_PROJECTION_MATRIX_CALLBACK = (0x1 << 4),
  52. NEAR_FAR_RATIO = (0x1 << 5),
  53. IMPOSTOR_ACTIVE = (0x1 << 6),
  54. DEPTH_SORT_IMPOSTOR_SPRITES = (0x1 << 7),
  55. IMPOSTOR_PIXEL_ERROR_THRESHOLD = (0x1 << 8),
  56. NUM_FRAMES_TO_KEEP_IMPOSTORS_SPRITES = (0x1 << 9),
  57. CULL_MASK = (0x1 << 10),
  58. CULL_MASK_LEFT = (0x1 << 11),
  59. CULL_MASK_RIGHT = (0x1 << 12),
  60. CLEAR_COLOR = (0x1 << 13),
  61. CLEAR_MASK = (0x1 << 14),
  62. LIGHTING_MODE = (0x1 << 15),
  63. LIGHT = (0x1 << 16),
  64. DRAW_BUFFER = (0x1 << 17),
  65. READ_BUFFER = (0x1 << 18),
  66. NO_VARIABLES = 0x00000000,
  67. ALL_VARIABLES = 0x7FFFFFFF
  68. };
  69. typedef int InheritanceMask;
  70. /** Set the inheritance mask used in inheritCullSettings to control which variables get overwritten by the passed in CullSettings object.*/
  71. void setInheritanceMask(InheritanceMask mask) { _inheritanceMask = mask; }
  72. /** Get the inheritance mask used in inheritCullSettings to control which variables get overwritten by the passed in CullSettings object.*/
  73. InheritanceMask getInheritanceMask() const { return _inheritanceMask; }
  74. /** Set the local cull settings values from specified CullSettings object.*/
  75. void setCullSettings(const CullSettings& settings);
  76. /** Inherit the local cull settings variable from specified CullSettings object, according to the inheritance mask.*/
  77. virtual void inheritCullSettings(const CullSettings& settings) { inheritCullSettings(settings, _inheritanceMask); }
  78. /** Inherit the local cull settings variable from specified CullSettings object, according to the inheritance mask.*/
  79. virtual void inheritCullSettings(const CullSettings& settings, unsigned int inheritanceMask);
  80. /** read the environmental variables.*/
  81. void readEnvironmentalVariables();
  82. /** read the commandline arguments.*/
  83. void readCommandLine(ArgumentParser& arguments);
  84. enum InheritanceMaskActionOnAttributeSetting
  85. {
  86. DISABLE_ASSOCIATED_INHERITANCE_MASK_BIT,
  87. DO_NOT_MODIFY_INHERITANCE_MASK
  88. };
  89. void setInheritanceMaskActionOnAttributeSetting(InheritanceMaskActionOnAttributeSetting action) { _inheritanceMaskActionOnAttributeSetting = action; }
  90. InheritanceMaskActionOnAttributeSetting getInheritanceMaskActionOnAttributeSetting() const { return _inheritanceMaskActionOnAttributeSetting; }
  91. /** Apply the action, specified by the InheritanceMaskActionOnAttributeSetting, to apply to the inheritance bit mask.
  92. * This method is called by CullSettings::set*() parameter methods to ensure that CullSettings inheritance mechanisms doesn't overwrite the local parameter settings.*/
  93. inline void applyMaskAction(unsigned int maskBit)
  94. {
  95. if (_inheritanceMaskActionOnAttributeSetting==DISABLE_ASSOCIATED_INHERITANCE_MASK_BIT)
  96. {
  97. _inheritanceMask = _inheritanceMask & (~maskBit);
  98. }
  99. }
  100. /** Switch the creation of Impostors on or off.
  101. * Setting active to false forces the CullVisitor to use the Impostor
  102. * LOD children for rendering. Setting active to true forces the
  103. * CullVisitor to create the appropriate pre-rendering stages which
  104. * render to the ImpostorSprite's texture.*/
  105. void setImpostorsActive(bool active) { _impostorActive = active; applyMaskAction(IMPOSTOR_ACTIVE); }
  106. /** Get whether impostors are active or not. */
  107. bool getImpostorsActive() const { return _impostorActive; }
  108. /** Set the impostor error threshold.
  109. * Used in calculation of whether impostors remain valid.*/
  110. void setImpostorPixelErrorThreshold(float numPixels) { _impostorPixelErrorThreshold=numPixels; applyMaskAction(IMPOSTOR_PIXEL_ERROR_THRESHOLD); }
  111. /** Get the impostor error threshold.*/
  112. float getImpostorPixelErrorThreshold() const { return _impostorPixelErrorThreshold; }
  113. /** Set whether ImpostorSprite's should be placed in a depth sorted bin for rendering.*/
  114. void setDepthSortImpostorSprites(bool doDepthSort) { _depthSortImpostorSprites = doDepthSort; applyMaskAction(DEPTH_SORT_IMPOSTOR_SPRITES); }
  115. /** Get whether ImpostorSprite's are depth sorted bin for rendering.*/
  116. bool getDepthSortImpostorSprites() const { return _depthSortImpostorSprites; }
  117. /** Set the number of frames that an ImpostorSprite is kept whilst not being beyond,
  118. * before being recycled.*/
  119. void setNumberOfFrameToKeepImpostorSprites(int numFrames) { _numFramesToKeepImpostorSprites = numFrames; applyMaskAction(NUM_FRAMES_TO_KEEP_IMPOSTORS_SPRITES); }
  120. /** Get the number of frames that an ImpostorSprite is kept whilst not being beyond,
  121. * before being recycled.*/
  122. int getNumberOfFrameToKeepImpostorSprites() const { return _numFramesToKeepImpostorSprites; }
  123. enum ComputeNearFarMode
  124. {
  125. DO_NOT_COMPUTE_NEAR_FAR = 0,
  126. COMPUTE_NEAR_FAR_USING_BOUNDING_VOLUMES,
  127. COMPUTE_NEAR_FAR_USING_PRIMITIVES,
  128. COMPUTE_NEAR_USING_PRIMITIVES
  129. };
  130. void setComputeNearFarMode(ComputeNearFarMode cnfm) { _computeNearFar=cnfm; applyMaskAction(COMPUTE_NEAR_FAR_MODE); }
  131. ComputeNearFarMode getComputeNearFarMode() const { return _computeNearFar;}
  132. void setNearFarRatio(double ratio) { _nearFarRatio = ratio; applyMaskAction(NEAR_FAR_RATIO); }
  133. double getNearFarRatio() const { return _nearFarRatio; }
  134. enum CullingModeValues
  135. {
  136. NO_CULLING = 0x0,
  137. VIEW_FRUSTUM_SIDES_CULLING = 0x1,
  138. NEAR_PLANE_CULLING = 0x2,
  139. FAR_PLANE_CULLING = 0x4,
  140. VIEW_FRUSTUM_CULLING = VIEW_FRUSTUM_SIDES_CULLING|
  141. NEAR_PLANE_CULLING|
  142. FAR_PLANE_CULLING,
  143. SMALL_FEATURE_CULLING = 0x8,
  144. SHADOW_OCCLUSION_CULLING = 0x10,
  145. CLUSTER_CULLING = 0x20,
  146. DEFAULT_CULLING = VIEW_FRUSTUM_SIDES_CULLING|
  147. SMALL_FEATURE_CULLING|
  148. SHADOW_OCCLUSION_CULLING|
  149. CLUSTER_CULLING,
  150. ENABLE_ALL_CULLING = VIEW_FRUSTUM_CULLING|
  151. SMALL_FEATURE_CULLING|
  152. SHADOW_OCCLUSION_CULLING|
  153. CLUSTER_CULLING
  154. };
  155. typedef int CullingMode;
  156. /** Set the culling mode for the CullVisitor to use.*/
  157. void setCullingMode(CullingMode mode) { _cullingMode = mode; applyMaskAction(CULLING_MODE); }
  158. /** Returns the current CullingMode.*/
  159. CullingMode getCullingMode() const { return _cullingMode; }
  160. void setCullMask(osg::Node::NodeMask nm) { _cullMask = nm; applyMaskAction(CULL_MASK); }
  161. osg::Node::NodeMask getCullMask() const { return _cullMask; }
  162. void setCullMaskLeft(osg::Node::NodeMask nm) { _cullMaskLeft = nm; applyMaskAction(CULL_MASK_LEFT); }
  163. osg::Node::NodeMask getCullMaskLeft() const { return _cullMaskLeft; }
  164. void setCullMaskRight(osg::Node::NodeMask nm) { _cullMaskRight = nm; applyMaskAction(CULL_MASK_RIGHT); }
  165. osg::Node::NodeMask getCullMaskRight() const { return _cullMaskRight; }
  166. /** Set the LOD bias for the CullVisitor to use.*/
  167. void setLODScale(float scale) { _LODScale = scale; applyMaskAction(LOD_SCALE); }
  168. /** Get the LOD bias.*/
  169. float getLODScale() const { return _LODScale; }
  170. /** Threshold at which small features are culled.
  171. \param value Bounding volume size in screen space. Default is 2.0. */
  172. void setSmallFeatureCullingPixelSize(float value) { _smallFeatureCullingPixelSize=value; applyMaskAction(SMALL_FEATURE_CULLING_PIXEL_SIZE); }
  173. /** Get the Small Feature Culling Pixel Size.*/
  174. float getSmallFeatureCullingPixelSize() const { return _smallFeatureCullingPixelSize; }
  175. /** Callback for overriding the CullVisitor's default clamping of the projection matrix to computed near and far values.
  176. * Note, both Matrixf and Matrixd versions of clampProjectionMatrixImplementation must be implemented as the CullVisitor
  177. * can target either Matrix data type, configured at compile time.*/
  178. struct ClampProjectionMatrixCallback : public osg::Referenced
  179. {
  180. virtual bool clampProjectionMatrixImplementation(osg::Matrixf& projection, double& znear, double& zfar) const = 0;
  181. virtual bool clampProjectionMatrixImplementation(osg::Matrixd& projection, double& znear, double& zfar) const = 0;
  182. };
  183. /** set the ClampProjectionMatrixCallback.*/
  184. void setClampProjectionMatrixCallback(ClampProjectionMatrixCallback* cpmc) { _clampProjectionMatrixCallback = cpmc; applyMaskAction(CLAMP_PROJECTION_MATRIX_CALLBACK); }
  185. /** get the non const ClampProjectionMatrixCallback.*/
  186. ClampProjectionMatrixCallback* getClampProjectionMatrixCallback() { return _clampProjectionMatrixCallback.get(); }
  187. /** get the const ClampProjectionMatrixCallback.*/
  188. const ClampProjectionMatrixCallback* getClampProjectionMatrixCallback() const { return _clampProjectionMatrixCallback.get(); }
  189. /** Write out internal settings of CullSettings. */
  190. void write(std::ostream& out);
  191. protected:
  192. InheritanceMask _inheritanceMask;
  193. InheritanceMaskActionOnAttributeSetting _inheritanceMaskActionOnAttributeSetting;
  194. ComputeNearFarMode _computeNearFar;
  195. CullingMode _cullingMode;
  196. float _LODScale;
  197. float _smallFeatureCullingPixelSize;
  198. ref_ptr<ClampProjectionMatrixCallback> _clampProjectionMatrixCallback;
  199. double _nearFarRatio;
  200. bool _impostorActive;
  201. bool _depthSortImpostorSprites;
  202. float _impostorPixelErrorThreshold;
  203. int _numFramesToKeepImpostorSprites;
  204. Node::NodeMask _cullMask;
  205. Node::NodeMask _cullMaskLeft;
  206. Node::NodeMask _cullMaskRight;
  207. };
  208. template<class matrix_type, class value_type>
  209. bool clampProjectionMatrix(matrix_type& projection, double& znear, double& zfar, value_type nearFarRatio)
  210. {
  211. double epsilon = 1e-6;
  212. if (zfar<znear-epsilon)
  213. {
  214. if (zfar != -FLT_MAX || znear != FLT_MAX)
  215. {
  216. OSG_INFO<<"_clampProjectionMatrix not applied, invalid depth range, znear = "<<znear<<" zfar = "<<zfar<<std::endl;
  217. }
  218. return false;
  219. }
  220. if (zfar<znear+epsilon)
  221. {
  222. // znear and zfar are too close together and could cause divide by zero problems
  223. // late on in the clamping code, so move the znear and zfar apart.
  224. double average = (znear+zfar)*0.5;
  225. znear = average-epsilon;
  226. zfar = average+epsilon;
  227. // OSG_INFO << "_clampProjectionMatrix widening znear and zfar to "<<znear<<" "<<zfar<<std::endl;
  228. }
  229. if (fabs(projection(0,3))<epsilon && fabs(projection(1,3))<epsilon && fabs(projection(2,3))<epsilon )
  230. {
  231. // OSG_INFO << "Orthographic matrix before clamping"<<projection<<std::endl;
  232. value_type delta_span = (zfar-znear)*0.02;
  233. if (delta_span<1.0) delta_span = 1.0;
  234. value_type desired_znear = znear - delta_span;
  235. value_type desired_zfar = zfar + delta_span;
  236. // assign the clamped values back to the computed values.
  237. znear = desired_znear;
  238. zfar = desired_zfar;
  239. projection(2,2)=-2.0f/(desired_zfar-desired_znear);
  240. projection(3,2)=-(desired_zfar+desired_znear)/(desired_zfar-desired_znear);
  241. // OSG_INFO << "Orthographic matrix after clamping "<<projection<<std::endl;
  242. }
  243. else
  244. {
  245. // OSG_INFO << "Persepective matrix before clamping"<<projection<<std::endl;
  246. //std::cout << "_computed_znear"<<_computed_znear<<std::endl;
  247. //std::cout << "_computed_zfar"<<_computed_zfar<<std::endl;
  248. value_type zfarPushRatio = 1.02;
  249. value_type znearPullRatio = 0.98;
  250. //znearPullRatio = 0.99;
  251. value_type desired_znear = znear * znearPullRatio;
  252. value_type desired_zfar = zfar * zfarPushRatio;
  253. // near plane clamping.
  254. double min_near_plane = zfar*nearFarRatio;
  255. if (desired_znear<min_near_plane) desired_znear=min_near_plane;
  256. // assign the clamped values back to the computed values.
  257. znear = desired_znear;
  258. zfar = desired_zfar;
  259. value_type trans_near_plane = (-desired_znear*projection(2,2)+projection(3,2))/(-desired_znear*projection(2,3)+projection(3,3));
  260. value_type trans_far_plane = (-desired_zfar*projection(2,2)+projection(3,2))/(-desired_zfar*projection(2,3)+projection(3,3));
  261. value_type ratio = fabs(2.0/(trans_near_plane-trans_far_plane));
  262. value_type center = -(trans_near_plane+trans_far_plane)/2.0;
  263. projection.postMult(osg::Matrix(1.0f,0.0f,0.0f,0.0f,
  264. 0.0f,1.0f,0.0f,0.0f,
  265. 0.0f,0.0f,ratio,0.0f,
  266. 0.0f,0.0f,center*ratio,1.0f));
  267. // OSG_INFO << "Persepective matrix after clamping"<<projection<<std::endl;
  268. }
  269. return true;
  270. }
  271. }
  272. #endif