Octree.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  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 "DebugRenderer.h"
  25. #include "Deserializer.h"
  26. #include "Profiler.h"
  27. #include "Octree.h"
  28. #include "OctreeQuery.h"
  29. #include "Serializer.h"
  30. #include "XMLElement.h"
  31. #include <algorithm>
  32. #include "DebugNew.h"
  33. #ifdef _MSC_VER
  34. #pragma warning(disable:4355)
  35. #endif
  36. static unsigned excludeFlags = 0;
  37. inline static bool compareRayQueryResults(const RayQueryResult& lhs, const RayQueryResult& rhs)
  38. {
  39. return lhs.mDistance < rhs.mDistance;
  40. }
  41. Octant::Octant(const BoundingBox& box, unsigned level, Octant* parent, Octree* root) :
  42. mWorldBoundingBox(box),
  43. mLevel(level),
  44. mParent(parent),
  45. mRoot(root),
  46. mNumNodes(0)
  47. {
  48. Vector3 halfSize = mWorldBoundingBox.getSize() * 0.5f;
  49. mCullingBox = BoundingBox(mWorldBoundingBox.mMin - halfSize, mWorldBoundingBox.mMax + halfSize);
  50. for (unsigned i = 0; i < NUM_OCTANTS; ++i)
  51. mChildren[i] = 0;
  52. }
  53. Octant::~Octant()
  54. {
  55. release();
  56. }
  57. Octant* Octant::getOrCreateChild(unsigned index)
  58. {
  59. if (mChildren[index])
  60. return mChildren[index];
  61. Vector3 newMin = mWorldBoundingBox.mMin;
  62. Vector3 newMax = mWorldBoundingBox.mMax;
  63. Vector3 oldCenter = mWorldBoundingBox.getCenter();
  64. if (index & 1)
  65. newMin.mX = oldCenter.mX;
  66. else
  67. newMax.mX = oldCenter.mX;
  68. if (index & 2)
  69. newMin.mY = oldCenter.mY;
  70. else
  71. newMax.mY = oldCenter.mY;
  72. if (index & 4)
  73. newMin.mZ = oldCenter.mZ;
  74. else
  75. newMax.mZ = oldCenter.mZ;
  76. mChildren[index] = new Octant(BoundingBox(newMin, newMax), mLevel + 1, this, mRoot);
  77. return mChildren[index];
  78. }
  79. void Octant::deleteChild(unsigned index)
  80. {
  81. delete mChildren[index];
  82. mChildren[index] = 0;
  83. }
  84. void Octant::deleteChild(Octant* octant)
  85. {
  86. for (unsigned i = 0; i < NUM_OCTANTS; ++i)
  87. {
  88. if (mChildren[i] == octant)
  89. {
  90. delete octant;
  91. mChildren[i] = 0;
  92. return;
  93. }
  94. }
  95. }
  96. void Octant::insertNode(VolumeNode* node)
  97. {
  98. // If size OK or outside, stop recursion & insert here
  99. if ((checkNodeSize(node)) || (mCullingBox.isInside(node->getWorldBoundingBox()) != INSIDE))
  100. {
  101. if (node->mOctant != this)
  102. {
  103. if (node->mOctant)
  104. node->mOctant->removeNode(node);
  105. addNode(node);
  106. }
  107. return;
  108. }
  109. Vector3 octantCenter = mWorldBoundingBox.getCenter();
  110. Vector3 nodeCenter = node->getWorldBoundingBox().getCenter();
  111. unsigned x = nodeCenter.mX < octantCenter.mX ? 0 : 1;
  112. unsigned y = nodeCenter.mY < octantCenter.mY ? 0 : 2;
  113. unsigned z = nodeCenter.mZ < octantCenter.mZ ? 0 : 4;
  114. getOrCreateChild(x + y + z)->insertNode(node);
  115. }
  116. bool Octant::checkNodeSize(VolumeNode* node) const
  117. {
  118. // If max split level, size always OK
  119. if (mLevel == mRoot->getNumLevels())
  120. return true;
  121. Vector3 octantHalfSize = mWorldBoundingBox.getSize() * 0.5;
  122. Vector3 nodeSize = node->getWorldBoundingBox().getSize();
  123. return (nodeSize.mX >= octantHalfSize.mX) || (nodeSize.mY >= octantHalfSize.mY) || (nodeSize.mZ >= octantHalfSize.mZ);
  124. }
  125. void Octant::resetRoot()
  126. {
  127. mRoot = 0;
  128. for (unsigned i = 0; i < NUM_OCTANTS; ++i)
  129. {
  130. if (mChildren[i])
  131. mChildren[i]->resetRoot();
  132. }
  133. }
  134. void Octant::getNodesInternal(OctreeQuery& query, unsigned mask) const
  135. {
  136. if (!mNumNodes)
  137. return;
  138. if (mask != M_MAX_UNSIGNED)
  139. {
  140. Intersection res = query.testOctant(mCullingBox, mask);
  141. if ((res == OUTSIDE) && (this != mRoot))
  142. // Fully outside, so cull this octant, its children & nodes
  143. return;
  144. if (res == INSIDE)
  145. // Fully inside, no culling checks necessary for children & nodes
  146. mask = M_MAX_UNSIGNED;
  147. }
  148. for (std::vector<VolumeNode*>::const_iterator i = mNodes.begin(); i != mNodes.end(); ++i)
  149. {
  150. VolumeNode* node = *i;
  151. unsigned nodeFlags = node->getNodeFlags();
  152. if ((!(nodeFlags & query.mNodeFlags)) || (nodeFlags & excludeFlags))
  153. continue;
  154. if (!node->isVisible())
  155. continue;
  156. if ((query.mOccludersOnly) && (!node->isOccluder()))
  157. continue;
  158. if ((query.mShadowCastersOnly) && (!node->getCastShadows()))
  159. continue;
  160. if (query.testNode(node->getWorldBoundingBox(), mask) != OUTSIDE)
  161. query.mResult.push_back(node);
  162. }
  163. for (unsigned i = 0; i < NUM_OCTANTS; ++i)
  164. {
  165. if (mChildren[i])
  166. mChildren[i]->getNodesInternal(query, mask);
  167. }
  168. }
  169. void Octant::getNodesInternal(RayOctreeQuery& query) const
  170. {
  171. if (!mNumNodes)
  172. return;
  173. float octantDist = mCullingBox.getDistance(query.mRay);
  174. if (octantDist >= query.mMaxDistance)
  175. return;
  176. for (std::vector<VolumeNode*>::const_iterator i = mNodes.begin(); i != mNodes.end(); ++i)
  177. {
  178. VolumeNode* node = *i;
  179. unsigned nodeFlags = node->getNodeFlags();
  180. if ((!(nodeFlags & query.mNodeFlags)) || (nodeFlags & excludeFlags))
  181. continue;
  182. if (!node->isVisible())
  183. continue;
  184. if ((query.mOccludersOnly) && (!node->isOccluder()))
  185. continue;
  186. if ((query.mShadowCastersOnly) && (!node->getCastShadows()))
  187. continue;
  188. float nodeDist = node->getWorldBoundingBox().getDistance(query.mRay);
  189. // The node will possibly do more accurate collision testing, then store the result(s)
  190. if (nodeDist < query.mMaxDistance)
  191. node->processRayQuery(query, nodeDist);
  192. }
  193. for (unsigned i = 0; i < NUM_OCTANTS; ++i)
  194. {
  195. if (mChildren[i])
  196. mChildren[i]->getNodesInternal(query);
  197. }
  198. }
  199. void Octant::release()
  200. {
  201. if ((mRoot) && (this != mRoot))
  202. {
  203. // Remove the nodes (if any) from this octant to the root octant
  204. for (std::vector<VolumeNode*>::iterator i = mNodes.begin(); i != mNodes.end(); ++i)
  205. {
  206. (*i)->mOctant = mRoot;
  207. mRoot->markNodeForReinsertion(*i);
  208. }
  209. }
  210. else if (!mRoot)
  211. {
  212. // If the whole octree is being destroyed, just detach the nodes
  213. for (std::vector<VolumeNode*>::iterator i = mNodes.begin(); i != mNodes.end(); ++i)
  214. (*i)->mOctant = 0;
  215. }
  216. mNodes.clear();
  217. mNumNodes = 0;
  218. for (unsigned i = 0; i < NUM_OCTANTS; ++i)
  219. deleteChild(i);
  220. }
  221. Octree::Octree(const BoundingBox& box, unsigned numLevels, bool headless) :
  222. Octant(box, 0, 0, this),
  223. mNumLevels(max((int)numLevels, 1)),
  224. mExcludeFlags(0),
  225. mHeadless(headless)
  226. {
  227. }
  228. Octree::~Octree()
  229. {
  230. // Reset root pointer from all child octants now so that they do not move their scene nodes to root
  231. resetRoot();
  232. }
  233. void Octree::save(Serializer& dest)
  234. {
  235. writeExtensionType(dest);
  236. dest.writeBoundingBox(mWorldBoundingBox);
  237. dest.writeUInt(mNumLevels);
  238. }
  239. void Octree::load(Deserializer& source)
  240. {
  241. checkExtensionType(source);
  242. BoundingBox box = source.readBoundingBox();
  243. unsigned numLevels = source.readUInt();
  244. resize(box, numLevels);
  245. }
  246. void Octree::saveXML(XMLElement& dest)
  247. {
  248. XMLElement octreeElem = dest.createChildElement("octree");
  249. // Write octree properties
  250. octreeElem.setBoundingBox(mWorldBoundingBox);
  251. octreeElem.setInt("levels", mNumLevels);
  252. }
  253. void Octree::loadXML(const XMLElement& source)
  254. {
  255. XMLElement octreeElem = source.getChildElement("octree");
  256. BoundingBox box = octreeElem.getBoundingBox();
  257. unsigned numLevels = octreeElem.getInt("levels");
  258. resize(box, numLevels);
  259. }
  260. void Octree::update(float timeStep)
  261. {
  262. // If in headless mode, run an update now to update and reinsert nodes
  263. if (mHeadless)
  264. {
  265. FrameInfo frame;
  266. frame.mCamera = 0;
  267. frame.mFrameNumber = 0;
  268. frame.mTimeStep = timeStep;
  269. updateOctree(frame);
  270. }
  271. }
  272. void Octree::resize(const BoundingBox& box, unsigned numLevels)
  273. {
  274. numLevels = max((int)numLevels, 1);
  275. if ((numLevels == mNumLevels) && (box.mMin == mWorldBoundingBox.mMin) && (box.mMax == mWorldBoundingBox.mMax))
  276. return;
  277. // If nodes exist, they are temporarily moved to the root
  278. release();
  279. mWorldBoundingBox = box;
  280. mNumLevels = numLevels;
  281. Vector3 halfSize = mWorldBoundingBox.getSize() * 0.5f;
  282. mCullingBox = BoundingBox(mWorldBoundingBox.mMin - halfSize, mWorldBoundingBox.mMax + halfSize);
  283. }
  284. void Octree::setExcludeFlags(unsigned nodeFlags)
  285. {
  286. mExcludeFlags = nodeFlags;
  287. }
  288. void Octree::updateOctree(const FrameInfo& frame)
  289. {
  290. {
  291. PROFILE(Octree_UpdateNodes);
  292. // Let nodes update themselves before reinsertion
  293. for (std::set<VolumeNode*>::iterator i = mNodeUpdates.begin(); i != mNodeUpdates.end(); ++i)
  294. (*i)->updateNode(frame);
  295. }
  296. {
  297. PROFILE(Octree_ReinsertNodes);
  298. // Reinsert nodes into the octree
  299. for (std::set<VolumeNode*>::iterator i = mNodeReinsertions.begin(); i != mNodeReinsertions.end(); ++i)
  300. {
  301. VolumeNode* node = *i;
  302. Octant* octant = node->mOctant;
  303. if (octant)
  304. {
  305. bool reinsert = false;
  306. if (octant == this)
  307. {
  308. // Handle root octant as special case: if outside the root, do not reinsert
  309. if ((getCullingBox().isInside(node->getWorldBoundingBox()) == INSIDE) && (!checkNodeSize(node)))
  310. reinsert = true;
  311. }
  312. else
  313. {
  314. // Otherwise reinsert if outside current octant or if size does not fit octant size
  315. if ((octant->getCullingBox().isInside(node->getWorldBoundingBox()) != INSIDE) || (!octant->checkNodeSize(node)))
  316. reinsert = true;
  317. }
  318. if (reinsert)
  319. {
  320. insertNode(node);
  321. // If old octant (not root) has become empty, delete it
  322. while ((octant != this) && (octant->isEmpty()))
  323. {
  324. Octant* parent = octant->getParent();
  325. parent->deleteChild(octant);
  326. octant = parent;
  327. }
  328. }
  329. }
  330. else
  331. insertNode(node);
  332. }
  333. }
  334. mNodeUpdates.clear();
  335. mNodeReinsertions.clear();
  336. }
  337. void Octree::getNodes(OctreeQuery& query) const
  338. {
  339. PROFILE(Octree_GetNodes);
  340. excludeFlags = mExcludeFlags;
  341. query.mResult.clear();
  342. getNodesInternal(query, 0);
  343. }
  344. void Octree::getNodes(RayOctreeQuery& query) const
  345. {
  346. PROFILE(Octree_Raycast);
  347. excludeFlags = mExcludeFlags;
  348. query.mResult.clear();
  349. getNodesInternal(query);
  350. std::sort(query.mResult.begin(), query.mResult.end(), compareRayQueryResults);
  351. }
  352. void Octree::markNodeForUpdate(VolumeNode* node)
  353. {
  354. mNodeUpdates.insert(node);
  355. }
  356. void Octree::clearNodeUpdate(VolumeNode* node)
  357. {
  358. mNodeUpdates.erase(node);
  359. }
  360. void Octree::markNodeForReinsertion(VolumeNode* node)
  361. {
  362. mNodeReinsertions.insert(node);
  363. }
  364. void Octree::clearNodeReinsertion(VolumeNode* node)
  365. {
  366. mNodeReinsertions.erase(node);
  367. }