sceneZoneSpaceManager.h 12 KB

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