Octree.h 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. // Copyright (c) 2008-2023 the Urho3D project
  2. // License: MIT
  3. #pragma once
  4. #include "../Core/Mutex.h"
  5. #include "../Graphics/Drawable.h"
  6. #include "../Graphics/OctreeQuery.h"
  7. namespace Urho3D
  8. {
  9. class Octree;
  10. static const int NUM_OCTANTS = 8;
  11. static const i32 ROOT_INDEX = NINDEX;
  12. /// %Octree octant.
  13. /// @nobind
  14. class URHO3D_API Octant
  15. {
  16. public:
  17. /// Construct.
  18. Octant(const BoundingBox& box, i32 level, Octant* parent, Octree* root, i32 index = ROOT_INDEX);
  19. /// Destruct. Move drawables to root if available (detach if not) and free child octants.
  20. virtual ~Octant();
  21. /// Return or create a child octant.
  22. Octant* GetOrCreateChild(i32 index);
  23. /// Delete child octant.
  24. void DeleteChild(i32 index);
  25. /// Insert a drawable object by checking for fit recursively.
  26. void InsertDrawable(Drawable* drawable);
  27. /// Check if a drawable object fits.
  28. bool CheckDrawableFit(const BoundingBox& box) const;
  29. /// Add a drawable object to this octant.
  30. void AddDrawable(Drawable* drawable)
  31. {
  32. drawable->SetOctant(this);
  33. drawables_.Push(drawable);
  34. IncDrawableCount();
  35. }
  36. /// Remove a drawable object from this octant.
  37. void RemoveDrawable(Drawable* drawable, bool resetOctant = true)
  38. {
  39. if (drawables_.Remove(drawable))
  40. {
  41. if (resetOctant)
  42. drawable->SetOctant(nullptr);
  43. DecDrawableCount();
  44. }
  45. }
  46. /// Return world-space bounding box.
  47. /// @property
  48. const BoundingBox& GetWorldBoundingBox() const { return worldBoundingBox_; }
  49. /// Return bounding box used for fitting drawable objects.
  50. const BoundingBox& GetCullingBox() const { return cullingBox_; }
  51. /// Return subdivision level.
  52. i32 GetLevel() const { return level_; }
  53. /// Return parent octant.
  54. Octant* GetParent() const { return parent_; }
  55. /// Return octree root.
  56. Octree* GetRoot() const { return root_; }
  57. /// Return number of drawables.
  58. i32 GetNumDrawables() const { return numDrawables_; }
  59. /// Return true if there are no drawable objects in this octant and child octants.
  60. bool IsEmpty() { return numDrawables_ == 0; }
  61. /// Reset root pointer recursively. Called when the whole octree is being destroyed.
  62. void ResetRoot();
  63. /// Draw bounds to the debug graphics recursively.
  64. /// @nobind
  65. void DrawDebugGeometry(DebugRenderer* debug, bool depthTest);
  66. protected:
  67. /// Initialize bounding box.
  68. void Initialize(const BoundingBox& box);
  69. /// Return drawable objects by a query, called internally.
  70. void GetDrawablesInternal(OctreeQuery& query, bool inside) const;
  71. /// Return drawable objects by a ray query, called internally.
  72. void GetDrawablesInternal(RayOctreeQuery& query) const;
  73. /// Return drawable objects only for a threaded ray query, called internally.
  74. void GetDrawablesOnlyInternal(RayOctreeQuery& query, Vector<Drawable*>& drawables) const;
  75. /// Increase drawable object count recursively.
  76. void IncDrawableCount()
  77. {
  78. ++numDrawables_;
  79. if (parent_)
  80. parent_->IncDrawableCount();
  81. }
  82. /// Decrease drawable object count recursively and remove octant if it becomes empty.
  83. void DecDrawableCount()
  84. {
  85. Octant* parent = parent_;
  86. --numDrawables_;
  87. if (!numDrawables_)
  88. {
  89. if (parent)
  90. parent->DeleteChild(index_);
  91. }
  92. if (parent)
  93. parent->DecDrawableCount();
  94. }
  95. /// World bounding box.
  96. BoundingBox worldBoundingBox_;
  97. /// Bounding box used for drawable object fitting.
  98. BoundingBox cullingBox_;
  99. /// Drawable objects.
  100. Vector<Drawable*> drawables_;
  101. /// Child octants.
  102. Octant* children_[NUM_OCTANTS]{};
  103. /// World bounding box center.
  104. Vector3 center_;
  105. /// World bounding box half size.
  106. Vector3 halfSize_;
  107. /// Subdivision level.
  108. i32 level_;
  109. /// Number of drawable objects in this octant and child octants.
  110. i32 numDrawables_{};
  111. /// Parent octant.
  112. Octant* parent_;
  113. /// Octree root.
  114. Octree* root_;
  115. /// Octant index relative to its siblings or ROOT_INDEX for root octant.
  116. i32 index_;
  117. };
  118. /// %Octree component. Should be added only to the root scene node.
  119. class URHO3D_API Octree : public Component, public Octant
  120. {
  121. URHO3D_OBJECT(Octree, Component);
  122. public:
  123. /// Construct.
  124. explicit Octree(Context* context);
  125. /// Destruct.
  126. ~Octree() override;
  127. /// Register object factory.
  128. /// @nobind
  129. static void RegisterObject(Context* context);
  130. /// Visualize the component as debug geometry.
  131. void DrawDebugGeometry(DebugRenderer* debug, bool depthTest) override;
  132. /// Set size and maximum subdivision levels. If octree is not empty, drawable objects will be temporarily moved to the root.
  133. void SetSize(const BoundingBox& box, i32 numLevels);
  134. /// Update and reinsert drawable objects.
  135. void Update(const FrameInfo& frame);
  136. /// Add a drawable manually.
  137. void AddManualDrawable(Drawable* drawable);
  138. /// Remove a manually added drawable.
  139. void RemoveManualDrawable(Drawable* drawable);
  140. /// Return drawable objects by a query.
  141. /// @nobind
  142. void GetDrawables(OctreeQuery& query) const;
  143. /// Return drawable objects by a ray query.
  144. void Raycast(RayOctreeQuery& query) const;
  145. /// Return the closest drawable object by a ray query.
  146. void RaycastSingle(RayOctreeQuery& query) const;
  147. /// Return subdivision levels.
  148. /// @property
  149. i32 GetNumLevels() const { return numLevels_; }
  150. /// Mark drawable object as requiring an update and a reinsertion.
  151. void QueueUpdate(Drawable* drawable);
  152. /// Cancel drawable object's update.
  153. void CancelUpdate(Drawable* drawable);
  154. /// Visualize the component as debug geometry.
  155. void DrawDebugGeometry(bool depthTest);
  156. private:
  157. /// Handle render update in case of headless execution.
  158. void HandleRenderUpdate(StringHash eventType, VariantMap& eventData);
  159. /// Update octree size.
  160. void UpdateOctreeSize() { SetSize(worldBoundingBox_, numLevels_); }
  161. /// Drawable objects that require update.
  162. Vector<Drawable*> drawableUpdates_;
  163. /// Drawable objects that were inserted during threaded update phase.
  164. Vector<Drawable*> threadedDrawableUpdates_;
  165. /// Mutex for octree reinsertions.
  166. Mutex octreeMutex_;
  167. /// Ray query temporary list of drawables.
  168. mutable Vector<Drawable*> rayQueryDrawables_;
  169. /// Subdivision level.
  170. i32 numLevels_;
  171. };
  172. }