sceneZoneSpaceManager.h
Engine/source/scene/zones/sceneZoneSpaceManager.h
Classes:
class
Object that manages zone spaces in a scene.
class
Iterator for the contents of a given zone.
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 _SCENEZONESPACEMANAGER_H_ 25#define _SCENEZONESPACEMANAGER_H_ 26 27#ifndef _SCENEOBJECT_H_ 28#include "scene/sceneObject.h" 29#endif 30 31#ifndef _TVECTOR_H_ 32#include "core/util/tVector.h" 33#endif 34 35#ifndef _TSIGNAL_H_ 36#include "core/util/tSignal.h" 37#endif 38 39#ifndef _DATACHUNKER_H_ 40#include "core/dataChunker.h" 41#endif 42 43 44 45class SceneContainer; 46class SceneRootZone; 47class SceneZoneSpace; 48 49 50/// Object that manages zone spaces in a scene. 51class SceneZoneSpaceManager 52{ 53 public: 54 55 class ZoneContentIterator; 56 57 friend class SceneZoneSpace; // mZoneLists 58 friend class ZoneContentIterator; // mZoneLists 59 60 /// A signal used to notify that the zone setup of the scene has changed. 61 /// 62 /// @note If you use this signal to maintain state that depends on the zoning 63 /// setup, it's best to not immediately update the sate in response to this 64 /// signal. The reason is that during loading and editing, the signal may 65 /// be fired a lot and continuously updating dependent data may waste a lot 66 /// of time. 67 typedef Signal< void( SceneZoneSpaceManager* ) > ZoningChangedSignal; 68 69 enum : <a href="/coding/file/types_8h/#types_8h_1ac3df7cf3c8cb172a588adec881447d68">U32</a> 70 { 71 /// Zone ID of the exterior zone. 72 RootZoneId = 0, 73 74 /// Constant to indicate an invalid zone ID. 75 InvalidZoneId = 0xFFFFFFFF, 76 }; 77 78 /// Iterator for the contents of a given zone. 79 class ZoneContentIterator 80 { 81 public: 82 83 ZoneContentIterator( SceneZoneSpaceManager* manager, S32 zoneId, bool upToDate = true ) 84 { 85 AssertFatal( zoneId < manager->getNumZones(), "SceneZoneSpaceManager::ZoneContentIterator - Zone ID out of range" ); 86 87 if( upToDate ) 88 { 89 // Since zoning is updated lazily, the zone contents may actually 90 // be out of date. Force an update by triggering rezoning on the 91 // zone object. This is brute-force but this iterator is not meant 92 // to be used for high-frequency code anyway. 93 // 94 // Use the area-based rezoning so that we can also properly iterate 95 // over the contents of SceneRootZone. 96 manager->_rezoneObjects( ( ( SceneObject* ) manager->getZoneOwner( zoneId ) )->getWorldBox() ); 97 } 98 99 mCurrent = manager->mZoneLists[ zoneId ]->nextInBin; // Skip zone object entry. 100 } 101 102 bool isValid() const 103 { 104 return ( mCurrent != NULL ); 105 } 106 bool operator!() const 107 { 108 return ( mCurrent == NULL ); 109 } 110 ZoneContentIterator& operator++() 111 { 112 if( mCurrent ) 113 mCurrent = mCurrent->nextInBin; 114 return *this; 115 } 116 ZoneContentIterator& operator--() 117 { 118 if( mCurrent ) 119 mCurrent = mCurrent->prevInBin; 120 return *this; 121 } 122 SceneObject* operator*() const 123 { 124 AssertFatal( mCurrent != NULL, "SceneManager::ZoneContentIterator::operator* - Invalid iterator" ); 125 return mCurrent->object; 126 } 127 SceneObject* operator->() const 128 { 129 AssertFatal( mCurrent != NULL, "SceneManager::ZoneContentIterator::operator-> - Invalid iterator" ); 130 return mCurrent->object; 131 } 132 133 private: 134 135 SceneObject::ZoneRef* mCurrent; 136 }; 137 138 protected: 139 140 /// The root and outdoor zone of the scene. 141 SceneRootZone* mRootZone; 142 143 /// Scene container that holds the zone spaces we are managing. 144 SceneContainer* mContainer; 145 146 /// Collection of objects that manage zones. 147 Vector< SceneZoneSpace*> mZoneSpaces; 148 149 /// Total number of zones that have been allocated in the scene. 150 U32 mNumTotalAllocatedZones; 151 152 /// Number of zone IDs that are in active use. 153 U32 mNumActiveZones; 154 155 /// Object list for each zone in the scene. 156 /// First entry in the list points back to the zone manager. 157 Vector< SceneObject::ZoneRef*> mZoneLists; 158 159 /// Vector used repeatedly for zone space queries on the container. 160 mutable Vector< SceneObject*> mZoneSpacesQueryList; 161 162 /// Allocator for ZoneRefs. 163 static ClassChunker< SceneObject::ZoneRef> smZoneRefChunker; 164 165 /// @name Dirty Lists 166 /// Updating the zoning state of a scene is done en block rather than 167 /// individually for each object as it changes transforms or size. 168 /// @{ 169 170 /// Area of the scene that needs to be rezoned. 171 Box3F mDirtyArea; 172 173 /// List of zone spaces that have changed state and need updating. 174 Vector< SceneZoneSpace*> mDirtyZoneSpaces; 175 176 /// List of objects (non-zone spaces) that have changed state and need 177 /// updating. 178 Vector< SceneObject*> mDirtyObjects; 179 180 /// @} 181 182 /// Check to see if we have accumulated a lot of unallocate zone IDs and if so, 183 /// compact the zoning lists by reassigning IDs. 184 /// 185 /// @warn This method may alter all zone IDs in the scene! 186 void _compactZonesCheck(); 187 188 /// Return the index into #mZoneSpaces for the given object or -1 if 189 /// @object is not a zone manager. 190 S32 _getZoneSpaceIndex( SceneZoneSpace* object ) const; 191 192 /// Attach zoning state to the given object. 193 void _zoneInsert( SceneObject* object, bool queryListInitialized = false ); 194 195 /// Detach zoning state from the given object. 196 void _zoneRemove( SceneObject* object ); 197 198 /// Add to given object to the zone list of the given zone. 199 void _addToZoneList( U32 zoneId, SceneObject* object ); 200 201 /// Clear all objects assigned to the given zone. 202 /// @note This does not remove the first link in the zone list which is the link 203 /// back to the zone manager. 204 void _clearZoneList( U32 zoneId ); 205 206 /// Find the given object in the zone list of the given zone. 207 SceneObject::ZoneRef* _findInZoneList( U32 zoneId, SceneObject* object ) const; 208 209 /// Assign the given object to the outdoor zone. 210 void _addToOutdoorZone( SceneObject* object ); 211 212 /// Rezone all objects in the given area. 213 void _rezoneObjects( const Box3F& area ); 214 215 /// Update the zoning state of the given object. 216 void _rezoneObject( SceneObject* object ); 217 218 /// Fill #mZoneSpacesQueryList with all ZoneObjectType objects in the given area. 219 void _queryZoneSpaces( const Box3F& area ) const; 220 221 public: 222 223 SceneZoneSpaceManager( SceneContainer* container ); 224 ~SceneZoneSpaceManager(); 225 226 /// Bring the zoning state of the scene up to date. This will cause objects 227 /// that have moved or have been resized to be rezoned and will updated regions 228 /// of the scene that had their zoning setup changed. 229 /// 230 /// @note This method depends on proper use of notifyObjectChanged(). 231 void updateZoningState(); 232 233 /// @name Objects 234 /// @{ 235 236 /// Add zoning state to the given object. 237 void registerObject( SceneObject* object ); 238 239 /// Remove the given object from the zoning state. 240 void unregisterObject( SceneObject* object ); 241 242 /// Let the manager know that state relevant to zoning of the given 243 /// object has changed. 244 void notifyObjectChanged( SceneObject* object ); 245 246 /// Update the zoning state of the given object. 247 void updateObject( SceneObject* object ); 248 249 /// @} 250 251 /// @name Zones 252 /// @{ 253 254 /// Return the root zone of the scene. 255 SceneRootZone* getRootZone() const { return mRootZone; } 256 257 /// Register a zone manager. 258 /// 259 /// @param object SceneZoneSpace object that contains zones. 260 /// @param numZones Number of zones that @a object contains. 261 void registerZones( SceneZoneSpace* object, U32 numZones ); 262 263 /// Unregister a zone manager. 264 /// 265 /// @param object Object that contains zones. 266 void unregisterZones( SceneZoneSpace* object ); 267 268 /// Return true if the given ID belongs to a currently registered zone. 269 bool isValidZoneId( const U32 zoneId ) const 270 { 271 return ( zoneId < mNumTotalAllocatedZones && mZoneLists[ zoneId ] ); 272 } 273 274 /// Get the scene object that contains the zone with the given ID. 275 /// 276 /// @param zoneId ID of the zone. Must be valid. 277 /// @return The zone space that has registered the given zone. 278 SceneZoneSpace* getZoneOwner( const U32 zoneId ) const 279 { 280 AssertFatal( isValidZoneId( zoneId ), "SceneManager::getZoneOwner - Invalid zone ID!"); 281 return ( SceneZoneSpace* ) mZoneLists[ zoneId ]->object; 282 } 283 284 /// Return the total number of zones in the scene. 285 U32 getNumZones() const { return mNumTotalAllocatedZones; } 286 287 /// Return the effective amount of used zone IDs in the scene. 288 U32 getNumActiveZones() const { return mNumActiveZones; } 289 290 /// Return the total number of objects in the scene that manage zones. 291 U32 getNumZoneSpaces() const { return mZoneSpaces.size(); } 292 293 /// Find the zone that contains the given point. 294 /// 295 /// Note that the result can be <em>any</em> zone containing the given 296 /// point. 297 void findZone( const Point3F& point, SceneZoneSpace*& outZoneSpace, U32& outZoneID ) const; 298 299 /// Collect the IDs of all zones that overlap the given area. 300 /// 301 /// @param area AABB of scene space to query. 302 /// @param outZones IDs of all overlapped zones are added to this vector. 303 /// 304 /// @return Number of zones that have been added to @a outZones. Always at least 305 /// 1 as at least the outdoor zone always overlaps the given area (though if another zone 306 /// manager fully contains @a area, the outdoor zone will not be added to the list). 307 U32 findZones( const Box3F& area, Vector< U32>& outZones ) const; 308 309 static ZoningChangedSignal& getZoningChangedSignal() 310 { 311 static ZoningChangedSignal sSignal; 312 return sSignal; 313 } 314 315 /// @name Debugging 316 /// @{ 317 318 /// Verify the current zoning state. This makes sure all the connectivity 319 /// information and all the zone assignments appear to be correct. 320 void verifyState(); 321 322 /// Dump the current state of all zone spaces in the scene to the console. 323 /// @param update If true, zoning state states are updated first; if false, zoning is 324 /// dumped as is. 325 void dumpZoneStates( bool update = true ); 326 327 /// @} 328 329 /// @} 330}; 331 332#endif // !_SCENEZONESPACEMANAGER_H_ 333