Octree.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. //
  2. // Urho3D Engine
  3. // Copyright (c) 2008-2011 Lasse Öörni
  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 deal
  7. // in the Software without restriction, including without limitation the rights
  8. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. // 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 FROM,
  20. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. // THE SOFTWARE.
  22. //
  23. #include "Precompiled.h"
  24. #include "Context.h"
  25. #include "DebugRenderer.h"
  26. #include "Profiler.h"
  27. #include "Octree.h"
  28. #include "OctreeQuery.h"
  29. #include "Sort.h"
  30. #include "Log.h"
  31. #include "DebugNew.h"
  32. #ifdef _MSC_VER
  33. #pragma warning(disable:4355)
  34. #endif
  35. static const float DEFAULT_OCTREE_SIZE = 1000.0f;
  36. static const int DEFAULT_OCTREE_LEVELS = 8;
  37. inline bool CompareRayQueryResults(const RayQueryResult& lhs, const RayQueryResult& rhs)
  38. {
  39. return lhs.distance_ < rhs.distance_;
  40. }
  41. Octant::Octant(const BoundingBox& box, unsigned level, Octant* parent, Octree* root) :
  42. worldBoundingBox_(box),
  43. level_(level),
  44. parent_(parent),
  45. root_(root),
  46. numDrawables_(0)
  47. {
  48. Vector3 halfSize = worldBoundingBox_.GetSize() * 0.5f;
  49. cullingBox_ = BoundingBox(worldBoundingBox_.min_ - halfSize, worldBoundingBox_.max_ + halfSize);
  50. for (unsigned i = 0; i < NUM_OCTANTS; ++i)
  51. children_[i] = 0;
  52. }
  53. Octant::~Octant()
  54. {
  55. Release();
  56. }
  57. Octant* Octant::GetOrCreateChild(unsigned index)
  58. {
  59. if (children_[index])
  60. return children_[index];
  61. Vector3 newMin = worldBoundingBox_.min_;
  62. Vector3 newMax = worldBoundingBox_.max_;
  63. Vector3 oldCenter = worldBoundingBox_.GetCenter();
  64. if (index & 1)
  65. newMin.x_ = oldCenter.x_;
  66. else
  67. newMax.x_ = oldCenter.x_;
  68. if (index & 2)
  69. newMin.y_ = oldCenter.y_;
  70. else
  71. newMax.y_ = oldCenter.y_;
  72. if (index & 4)
  73. newMin.z_ = oldCenter.z_;
  74. else
  75. newMax.z_ = oldCenter.z_;
  76. children_[index] = new Octant(BoundingBox(newMin, newMax), level_ + 1, this, root_);
  77. return children_[index];
  78. }
  79. void Octant::DeleteChild(unsigned index)
  80. {
  81. delete children_[index];
  82. children_[index] = 0;
  83. }
  84. void Octant::DeleteChild(Octant* octant)
  85. {
  86. for (unsigned i = 0; i < NUM_OCTANTS; ++i)
  87. {
  88. if (children_[i] == octant)
  89. {
  90. delete octant;
  91. children_[i] = 0;
  92. return;
  93. }
  94. }
  95. }
  96. void Octant::InsertDrawable(Drawable* drawable)
  97. {
  98. // If size OK or outside, stop recursion & insert here
  99. if ((CheckDrawableSize(drawable)) || (cullingBox_.IsInside(drawable->GetWorldBoundingBox()) != INSIDE))
  100. {
  101. if (drawable->octant_ != this)
  102. {
  103. // Add first, then remove, because drawable count going to zero deletes the octree branch in question
  104. Octant* oldOctant = drawable->octant_;
  105. AddDrawable(drawable);
  106. if (oldOctant)
  107. oldOctant->RemoveDrawable(drawable, false);
  108. }
  109. return;
  110. }
  111. Vector3 octantCenter = worldBoundingBox_.GetCenter();
  112. Vector3 drawableCenter = drawable->GetWorldBoundingBox().GetCenter();
  113. unsigned x = drawableCenter.x_ < octantCenter.x_ ? 0 : 1;
  114. unsigned y = drawableCenter.y_ < octantCenter.y_ ? 0 : 2;
  115. unsigned z = drawableCenter.z_ < octantCenter.z_ ? 0 : 4;
  116. GetOrCreateChild(x + y + z)->InsertDrawable(drawable);
  117. }
  118. bool Octant::CheckDrawableSize(Drawable* drawable) const
  119. {
  120. // If max split level, size always OK
  121. if (level_ == root_->GetNumLevels())
  122. return true;
  123. Vector3 octantHalfSize = worldBoundingBox_.GetSize() * 0.5;
  124. Vector3 drawableSize = drawable->GetWorldBoundingBox().GetSize();
  125. return (drawableSize.x_ >= octantHalfSize.x_) || (drawableSize.y_ >= octantHalfSize.y_) || (drawableSize.z_ >=
  126. octantHalfSize.z_);
  127. }
  128. void Octant::ResetRoot()
  129. {
  130. root_ = 0;
  131. for (unsigned i = 0; i < NUM_OCTANTS; ++i)
  132. {
  133. if (children_[i])
  134. children_[i]->ResetRoot();
  135. }
  136. }
  137. void Octant::DrawDebugGeometry(DebugRenderer* debug, bool depthTest)
  138. {
  139. debug->AddBoundingBox(worldBoundingBox_, Color(0.25f, 0.25f, 0.25f), depthTest);
  140. for (unsigned i = 0; i < NUM_OCTANTS; ++i)
  141. {
  142. if (children_[i])
  143. children_[i]->DrawDebugGeometry(debug, depthTest);
  144. }
  145. }
  146. void Octant::GetDrawablesInternal(OctreeQuery& query, unsigned mask) const
  147. {
  148. if (!numDrawables_)
  149. return;
  150. if (mask != M_MAX_UNSIGNED)
  151. {
  152. Intersection res = query.TestOctant(cullingBox_, mask);
  153. if ((res == OUTSIDE) && (this != root_))
  154. // Fully outside, so cull this octant, its children & drawables
  155. return;
  156. if (res == INSIDE)
  157. // Fully inside, no culling checks necessary for children & drawables
  158. mask = M_MAX_UNSIGNED;
  159. }
  160. for (PODVector<Drawable*>::ConstIterator i = drawables_.Begin(); i != drawables_.End(); ++i)
  161. {
  162. Drawable* drawable = *i;
  163. unsigned flags = drawable->GetDrawableFlags();
  164. if ((!(flags & query.drawableFlags_)) || (!drawable->IsVisible()))
  165. continue;
  166. if ((query.occludersOnly_) && (!drawable->IsOccluder()))
  167. continue;
  168. if ((query.shadowCastersOnly_) && (!drawable->GetCastShadows()))
  169. continue;
  170. if (query.TestDrawable(drawable->GetWorldBoundingBox(), mask) != OUTSIDE)
  171. query.result_.Push(drawable);
  172. }
  173. for (unsigned i = 0; i < NUM_OCTANTS; ++i)
  174. {
  175. if (children_[i])
  176. children_[i]->GetDrawablesInternal(query, mask);
  177. }
  178. }
  179. void Octant::GetDrawablesInternal(RayOctreeQuery& query) const
  180. {
  181. if (!numDrawables_)
  182. return;
  183. float octantDist = cullingBox_.GetDistance(query.ray_);
  184. if (octantDist >= query.maxDistance_)
  185. return;
  186. for (PODVector<Drawable*>::ConstIterator i = drawables_.Begin(); i != drawables_.End(); ++i)
  187. {
  188. Drawable* drawable = *i;
  189. unsigned drawableFlags = drawable->GetDrawableFlags();
  190. if ((!(drawableFlags & query.drawableFlags_)) || (!drawable->IsVisible()))
  191. continue;
  192. if ((query.occludersOnly_) && (!drawable->IsOccluder()))
  193. continue;
  194. if ((query.shadowCastersOnly_) && (!drawable->GetCastShadows()))
  195. continue;
  196. float drawableDist = drawable->GetWorldBoundingBox().GetDistance(query.ray_);
  197. // The drawable will possibly do more accurate collision testing, then store the result(s)
  198. if (drawableDist < query.maxDistance_)
  199. drawable->ProcessRayQuery(query, drawableDist);
  200. }
  201. for (unsigned i = 0; i < NUM_OCTANTS; ++i)
  202. {
  203. if (children_[i])
  204. children_[i]->GetDrawablesInternal(query);
  205. }
  206. }
  207. void Octant::Release()
  208. {
  209. if ((root_) && (this != root_))
  210. {
  211. // Remove the drawables (if any) from this octant to the root octant
  212. for (PODVector<Drawable*>::Iterator i = drawables_.Begin(); i != drawables_.End(); ++i)
  213. {
  214. (*i)->SetOctant(root_);
  215. root_->drawables_.Push(*i);
  216. root_->QueueReinsertion(*i);
  217. }
  218. drawables_.Clear();
  219. numDrawables_ = 0;
  220. }
  221. else if (!root_)
  222. {
  223. // If the whole octree is being destroyed, just detach the drawables
  224. for (PODVector<Drawable*>::Iterator i = drawables_.Begin(); i != drawables_.End(); ++i)
  225. (*i)->SetOctant(0);
  226. }
  227. for (unsigned i = 0; i < NUM_OCTANTS; ++i)
  228. DeleteChild(i);
  229. }
  230. OBJECTTYPESTATIC(Octree);
  231. Octree::Octree(Context* context) :
  232. Component(context),
  233. Octant(BoundingBox(-DEFAULT_OCTREE_SIZE, DEFAULT_OCTREE_SIZE), 0, 0, this),
  234. numLevels_(DEFAULT_OCTREE_LEVELS)
  235. {
  236. }
  237. Octree::~Octree()
  238. {
  239. // Reset root pointer from all child octants now so that they do not move their drawables to root
  240. ResetRoot();
  241. }
  242. void Octree::RegisterObject(Context* context)
  243. {
  244. context->RegisterFactory<Octree>();
  245. ATTRIBUTE(Octree, VAR_VECTOR3, "Bounding Box Min", worldBoundingBox_.min_, Vector3(-DEFAULT_OCTREE_SIZE, -DEFAULT_OCTREE_SIZE, -DEFAULT_OCTREE_SIZE));
  246. ATTRIBUTE(Octree, VAR_VECTOR3, "Bounding Box Max", worldBoundingBox_.max_, Vector3(DEFAULT_OCTREE_SIZE, DEFAULT_OCTREE_SIZE, DEFAULT_OCTREE_SIZE));
  247. ATTRIBUTE(Octree, VAR_INT, "Number of Levels", numLevels_, DEFAULT_OCTREE_LEVELS);
  248. }
  249. void Octree::OnSetAttribute(const AttributeInfo& attr, const Variant& value)
  250. {
  251. Serializable::OnSetAttribute(attr, value);
  252. // If any of the size attributes changes, resize the octree
  253. /// \todo This may lead to unnecessary resizing, however it is fast once child nodes have been removed
  254. switch (attr.offset_)
  255. {
  256. case offsetof(Octree, worldBoundingBox_.min_):
  257. case offsetof(Octree, worldBoundingBox_.max_):
  258. case offsetof(Octree, numLevels_):
  259. Resize(worldBoundingBox_, numLevels_);
  260. break;
  261. }
  262. }
  263. void Octree::Resize(const BoundingBox& box, unsigned numLevels)
  264. {
  265. PROFILE(ResizeOctree);
  266. numLevels = Max((int)numLevels, 1);
  267. // If drawables exist, they are temporarily moved to the root
  268. Release();
  269. Vector3 halfSize = box.GetSize() * 0.5f;
  270. worldBoundingBox_ = box;
  271. cullingBox_ = BoundingBox(worldBoundingBox_.min_ - halfSize, worldBoundingBox_.max_ + halfSize);
  272. numDrawables_ = drawables_.Size();
  273. numLevels_ = numLevels;
  274. }
  275. void Octree::Update(const FrameInfo& frame)
  276. {
  277. {
  278. PROFILE(UpdateDrawables);
  279. // Let drawables update themselves before reinsertion
  280. for (Set<Drawable*>::Iterator i = drawableUpdates_.Begin(); i != drawableUpdates_.End(); ++i)
  281. (*i)->Update(frame);
  282. }
  283. {
  284. PROFILE(ReinsertDrawables);
  285. // Reinsert drawables into the octree
  286. for (Set<Drawable*>::Iterator i = drawableReinsertions_.Begin(); i != drawableReinsertions_.End(); ++i)
  287. {
  288. Drawable* drawable = *i;
  289. Octant* octant = drawable->GetOctant();
  290. if (octant)
  291. {
  292. bool reinsert = false;
  293. if (octant == this)
  294. {
  295. // Handle root octant as special case: if outside the root, do not reinsert
  296. if ((GetCullingBox().IsInside(drawable->GetWorldBoundingBox()) == INSIDE) && (!CheckDrawableSize(drawable)))
  297. reinsert = true;
  298. }
  299. else
  300. {
  301. // Otherwise reinsert if outside current octant or if size does not fit octant size
  302. if ((octant->GetCullingBox().IsInside(drawable->GetWorldBoundingBox()) != INSIDE) ||
  303. (!octant->CheckDrawableSize(drawable)))
  304. reinsert = true;
  305. }
  306. if (reinsert)
  307. InsertDrawable(drawable);
  308. }
  309. else
  310. InsertDrawable(drawable);
  311. }
  312. }
  313. drawableUpdates_.Clear();
  314. drawableReinsertions_.Clear();
  315. }
  316. void Octree::GetDrawables(OctreeQuery& query) const
  317. {
  318. PROFILE(OctreeQuery);
  319. query.result_.Clear();
  320. GetDrawablesInternal(query, 0);
  321. }
  322. void Octree::GetDrawables(RayOctreeQuery& query) const
  323. {
  324. PROFILE(Raycast);
  325. query.result_.Clear();
  326. GetDrawablesInternal(query);
  327. Sort(query.result_.Begin(), query.result_.End(), CompareRayQueryResults);
  328. }
  329. void Octree::QueueUpdate(Drawable* drawable)
  330. {
  331. drawableUpdates_.Insert(drawable);
  332. }
  333. void Octree::QueueReinsertion(Drawable* drawable)
  334. {
  335. drawableReinsertions_.Insert(drawable);
  336. }
  337. void Octree::CancelUpdate(Drawable* drawable)
  338. {
  339. drawableUpdates_.Erase(drawable);
  340. }
  341. void Octree::CancelReinsertion(Drawable* drawable)
  342. {
  343. drawableReinsertions_.Erase(drawable);
  344. }
  345. void Octree::DrawDebugGeometry(bool depthTest)
  346. {
  347. PROFILE(OctreeDrawDebug);
  348. DebugRenderer* debug = GetComponent<DebugRenderer>();
  349. if (!debug)
  350. return;
  351. Octant::DrawDebugGeometry(debug, depthTest);
  352. }