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