sceneCullingState.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #ifndef _SCENECULLINGSTATE_H_
  23. #define _SCENECULLINGSTATE_H_
  24. #ifndef _SCENEZONECULLINGSTATE_H_
  25. #include "scene/culling/sceneZoneCullingState.h"
  26. #endif
  27. #ifndef _MATHUTIL_FRUSTUM_H_
  28. #include "math/util/frustum.h"
  29. #endif
  30. #ifndef _TVECTOR_H_
  31. #include "core/util/tVector.h"
  32. #endif
  33. #ifndef _SCENECAMERASTATE_H_
  34. #include "scene/sceneCameraState.h"
  35. #endif
  36. #ifndef _DATACHUNKER_H_
  37. #include "core/dataChunker.h"
  38. #endif
  39. #ifndef _BITVECTOR_H_
  40. #include "core/bitVector.h"
  41. #endif
  42. class SceneObject;
  43. class SceneManager;
  44. /// An object that gathers the culling state for a scene.
  45. class SceneCullingState
  46. {
  47. public:
  48. /// Used to disable the somewhat expensive terrain occlusion testing
  49. /// done in during scene culling.
  50. static bool smDisableTerrainOcclusion;
  51. /// Whether to force zone culling to off by default.
  52. static bool smDisableZoneCulling;
  53. /// @name Occluder Restrictions
  54. /// Size restrictions on occlusion culling volumes. Any occlusion volume
  55. /// that does not meet these minimum requirements is not accepted into the
  56. /// rendering state.
  57. ///
  58. /// Having independent restrictions on both width and height allows filtering
  59. /// out occluders that might have a lot of area but only by covering very thin
  60. /// stretches of the screen.
  61. /// @{
  62. /// If more than this number of occlusion volumes are added to a ZoneState,
  63. /// then the occlusions volumes corresponding to the smallest amount of screen
  64. /// real estate get dropped such as to never exceed this total number of occlusion
  65. /// volumes.
  66. static U32 smMaxOccludersPerZone;
  67. /// Percentage of camera-space frustum near plane height that an occlusion culler must
  68. /// at least fill in order to not be rejected.
  69. /// @note The height computed for occluders is only an estimate.
  70. static F32 smOccluderMinHeightPercentage;
  71. /// Percentage of camera-space frustum near plane width that an occlusion culler must
  72. /// at least fill in order to not be rejected.
  73. /// @note The width computed for occluders is only an estimate.
  74. static F32 smOccluderMinWidthPercentage;
  75. /// @}
  76. protected:
  77. /// Scene which is being culled.
  78. SceneManager* mSceneManager;
  79. /// The viewing state that defines how the scene is being viewed.
  80. SceneCameraState mCameraState;
  81. /// The root culling volume corresponding to the culling frustum.
  82. SceneCullingVolume mRootVolume;
  83. /// The root culling frustum, which may be different from the camera frustum
  84. Frustum mCullingFrustum;
  85. /// Extra planes for culling.
  86. PlaneSetF mExtraPlanesCull;
  87. /// Occluders that have been added to this render state. Adding an occluder does not
  88. /// necessarily result in an occluder volume being added. To not repeatedly try to
  89. /// process the same occluder object, all objects that are added are recorded here.
  90. Vector< SceneObject* > mAddedOccluderObjects;
  91. ///
  92. BitVector mZoneVisibilityFlags;
  93. /// ZoneState entries for all zones in the scene.
  94. Vector< SceneZoneCullingState > mZoneStates;
  95. /// Allocator for culling data that can be freed in one go when
  96. /// the culling state is freed.
  97. DataChunker mDataChunker;
  98. /// If true, occlusion checks will not be done against the terrains
  99. /// in the scene.
  100. bool mDisableTerrainOcclusion;
  101. /// If true, all objects will only be tested against the root
  102. /// frustum.
  103. bool mDisableZoneCulling;
  104. public:
  105. ///
  106. SceneCullingState( SceneManager* sceneManager,
  107. const SceneCameraState& cameraState );
  108. /// Return the scene which is being culled in this state.
  109. SceneManager* getSceneManager() const { return mSceneManager; }
  110. /// Return the root frustum which is used to set up scene visibility.
  111. const Frustum& getCullingFrustum() const { return mCullingFrustum; }
  112. /// Return the root frustum which is used to set up scene visibility.
  113. const Frustum& getCameraFrustum() const { return getCameraState().getFrustum(); }
  114. /// Return the viewing state that defines how the scene is being viewed.
  115. const SceneCameraState& getCameraState() const { return mCameraState; }
  116. /// Return the root culling volume that corresponds to the camera frustum.
  117. /// @note This volume omits the near and far plane of the frustum's polyhedron
  118. /// as these will be tested separately during culling. Testing them repeatedly
  119. /// just wastes time.
  120. const SceneCullingVolume& getRootVolume() const { return mRootVolume; }
  121. /// @name Visibility and Occlusion
  122. /// @{
  123. enum CullOptions
  124. {
  125. /// Cull objects that have their SceneObject::DisableCullingInEditorFlag set.
  126. /// By default, these objects will not get culled if the editor is active.
  127. CullEditorOverrides = BIT( 0 ),
  128. /// Do not cull objects that are render-disabled.
  129. /// @see SceneObject::isRenderEnabled()
  130. DontCullRenderDisabled = BIT( 1 )
  131. };
  132. /// Cull the given list of objects according to the current culling state.
  133. ///
  134. /// @param object Array of objects. This array will be modified in place.
  135. /// @param numObjects Number of objects in @a objects.
  136. /// @param cullOptions Combination of CullOptions.
  137. ///
  138. /// @return Number of objects remaining in the list.
  139. U32 cullObjects( SceneObject** objects, U32 numObjects, U32 cullOptions = 0 ) const;
  140. /// Return true if the given object is culled according to the current culling state.
  141. bool isCulled( SceneObject* object ) const { return ( cullObjects( &object, 1 ) == 0 ); }
  142. /// Return true if the given AABB is culled in any of the given zones.
  143. bool isCulled( const Box3F& aabb, const U32* zones, U32 numZones ) const;
  144. /// Return true if the given OBB is culled in any of the given zones.
  145. bool isCulled( const OrientedBox3F& obb, const U32* zones, U32 numZones ) const;
  146. /// Return true if the given sphere is culled in any of the given zones.
  147. bool isCulled( const SphereF& sphere, const U32* zones, U32 numZones ) const;
  148. /// Return true if the given object is occluded according to the current culling state.
  149. bool isOccluded( SceneObject* object ) const;
  150. /// Return true if the given AABB is occluded according to the current culling state.
  151. bool isOccluded( const Box3F& aabb, const U32* zones, U32 numZones ) const;
  152. /// Return true if the given OBB is occluded according to the current culling state.
  153. bool isOccluded( const OrientedBox3F& obb, const U32* zones, U32 numZones ) const;
  154. /// Return true if the given sphere is occluded according to the current culling state.
  155. bool isOccluded( const SphereF& sphere, const U32* zones, U32 numZones ) const;
  156. /// Add the occlusion information contained in the given object.
  157. ///
  158. /// @note This should only be called after all positive frustums have been added
  159. /// to the zone state.
  160. void addOccluder( SceneObject* object );
  161. /// Test whether the given object is occluded by any of the terrains
  162. /// in the scene.
  163. bool isOccludedByTerrain( SceneObject* object ) const;
  164. /// Set whether isCulled() should do terrain occlusion checks or not.
  165. void setDisableTerrainOcclusion( bool value ) { mDisableTerrainOcclusion = value; }
  166. /// @}
  167. /// @name Zones
  168. /// @{
  169. /// If true, culling will only be performed against the root frustum
  170. /// and not against frustums of individual zones.
  171. ///
  172. /// @note This also disables occluders as these are added to the zone frustums.
  173. bool disableZoneCulling() const { return mDisableZoneCulling; }
  174. void disableZoneCulling( bool value ) { mDisableZoneCulling = value; }
  175. /// Return true if any of the zones that the object is currently are
  176. /// visible.
  177. bool isWithinVisibleZone( SceneObject* object ) const;
  178. /// Return a bit vector with one bit for each zone in the scene. If the bit is set,
  179. /// the zone has includer culling volumes attached to it and thus is visible.
  180. const BitVector& getZoneVisibilityFlags() const { return mZoneVisibilityFlags; }
  181. /// Return the culling state for a particular zone.
  182. /// @param zoneId Numeric ID of zone.
  183. const SceneZoneCullingState& getZoneState( U32 zoneId ) const
  184. {
  185. AssertFatal( zoneId < ( U32 ) mZoneStates.size(), "SceneCullingState::getZoneState - Index out of bounds" );
  186. return mZoneStates[ zoneId ];
  187. }
  188. /// Returns the culling state for a particular zone.
  189. /// @param zoneId Numeric ID of zone.
  190. SceneZoneCullingState& getZoneState( U32 zoneId )
  191. {
  192. return const_cast< SceneZoneCullingState& >( static_cast< const SceneCullingState* >( this )->getZoneState( zoneId ) );
  193. }
  194. /// Add a culling volume to the visibility state of the given zone.
  195. ///
  196. /// @param zoneId ID of zone to which to add the given frustum's visibility information.
  197. /// @param volume A culling volume. Note that the data in the volume must have
  198. /// a lifetime at least as long as the culling state.
  199. ///
  200. /// @return True if the visibility state of the zone has changed, i.e. if the volume
  201. /// was either added in whole or merged with an existing set of planes. If the visibility
  202. /// state of the zone has not changed, returns false.
  203. bool addCullingVolumeToZone( U32 zoneId, const SceneCullingVolume& volume );
  204. /// Copy the data from the given polyhedron to the culling state, create
  205. /// a new culling volume it and add it to the current culling state of the given zone.
  206. ///
  207. /// @param zoneId ID of zone to which to add the given frustum's visibility information.
  208. /// @param type Which type of culling volume to add.
  209. /// @param polyhedron Polyhedron describing the space of the culling volume.
  210. bool addCullingVolumeToZone( U32 zoneId, SceneCullingVolume::Type type, const AnyPolyhedron& polyhedron );
  211. /// Create a new culling volume by extruding the given polygon away from the viewpoint.
  212. ///
  213. /// @param vertices Array of polygon vertices.
  214. /// @param numVertices Number of vertices in @a vertices.
  215. /// @param type Type of culling volume to create.
  216. /// @param outVolume (out) Receives the generated volume, if successful.
  217. ///
  218. /// @return True if a volume could be generated from the given polygon or false if not.
  219. bool createCullingVolume( const Point3F* vertices, U32 numVertices, SceneCullingVolume::Type type, SceneCullingVolume& outVolume );
  220. /// @}
  221. /// @name Memory Management
  222. ///
  223. /// Rather than allocating a lot of individual point and plane data for the culling volumes,
  224. /// it is more efficient to batch allocate chunks of memory and then release all the memory
  225. /// for all culling volumes in one go. This is facilitated by this interface.
  226. ///
  227. /// @{
  228. /// Allocate memory from this culling state. The memory is freed when the
  229. /// culling state is destroyed.
  230. void* allocateData( U32 size ) { return mDataChunker.alloc( size ); }
  231. /// Allocate memory for @a num instances of T from this culling state.
  232. template< typename T >
  233. T* allocateData( U32 num ) { return reinterpret_cast< T* >( allocateData( sizeof( T ) * num ) ); }
  234. /// @}
  235. /// Queue debug visualizations of the culling volumes of all currently selected zones
  236. /// (or, if no zone is selected, all volumes in the outdoor zone) to the debug drawer.
  237. void debugRenderCullingVolumes() const;
  238. /// Set planes for extra culling
  239. void setExtraPlanesCull( const PlaneSetF &cull) { mExtraPlanesCull = cull; }
  240. /// Clear planes for extra culling.
  241. void clearExtraPlanesCull() { mExtraPlanesCull = PlaneSetF(NULL, 0); }
  242. /// Check extra planes culling
  243. bool isOccludedWithExtraPlanesCull(const Box3F &box) const
  244. {
  245. if(mExtraPlanesCull.getNumPlanes())
  246. return mExtraPlanesCull.testPotentialIntersection( box ) == GeometryOutside;
  247. return false;
  248. }
  249. private:
  250. typedef SceneZoneCullingState::CullingTestResult CullingTestResult;
  251. // Helper methods to avoid code duplication.
  252. template< bool OCCLUDERS_ONLY, typename T > CullingTestResult _test( const T& bounds, const U32* zones, U32 numZones ) const;
  253. template< typename T, typename Iter > CullingTestResult _test
  254. ( const T& bounds, Iter iter, const PlaneF& nearPlane, const PlaneF& farPlane ) const;
  255. template< typename T, typename Iter > CullingTestResult _testOccludersOnly( const T& bounds, Iter iter ) const;
  256. };
  257. #endif // !_SCENECULLINGSTATE_H_