OctTree.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. /***************************************************************************
  2. OctTree.cpp - description
  3. -------------------
  4. begin : Sun Mar 19 2000
  5. copyright : (C) 2000 by Henrik Enqvist
  6. email : henqvist@excite.com
  7. ***************************************************************************/
  8. #include <iostream>
  9. #include "Private.h"
  10. #include "OctTree.h"
  11. #include "Group.h"
  12. #include "CollisionBounds.h"
  13. /* QuadTrees ignore Y axis */
  14. OctTree::OctTree(int depth, float size, float x, float y, float z) {
  15. // m_fR = (float)(rand())/RAND_MAX;
  16. // m_fG = (float)(rand())/RAND_MAX;
  17. // m_fB = (float)(rand())/RAND_MAX;
  18. EmAssert(depth > 0, "Depth must be larger than 0");
  19. EM_COUT("OctTree() size"<< size <<" pos "<< x <<" "<< y <<" "<< z << endl, 0);
  20. m_vtx.x = x;
  21. m_vtx.y = y;
  22. m_vtx.z = z;
  23. m_fSize = size;
  24. if (depth > 1) {
  25. #if EM_USE_QUADTREE
  26. m_vOctTree.reserve(4);
  27. #else
  28. m_vOctTree.reserve(8);
  29. #endif
  30. }
  31. this->split(depth-1);
  32. }
  33. OctTree::~OctTree() {
  34. }
  35. void OctTree::split(int depth) {
  36. if (depth < 1) return;
  37. EM_COUT("OctTree::split() "<< depth << endl, 0);
  38. // TODO: Speed things up by allocating all octtrees as an array
  39. // at the top octtree instead of allocating them one by one
  40. for (int a=-1; a<2; a+=2) {
  41. for (int b=-1; b<2; b+=2) {
  42. #if EM_USE_QUADTREE
  43. OctTree* ot =
  44. new OctTree(depth, m_fSize*0.5, m_vtx.x + a*m_fSize*0.5, 0, m_vtx.z + b*m_fSize*0.5);
  45. m_vOctTree.push_back(ot);
  46. #else
  47. for (int c=-1; c<2; c+=2) {
  48. OctTree* ot =
  49. new OctTree(depth, m_fSize*0.5, m_vtx.x + a*m_fSize*0.5,
  50. m_vtx.y + b*m_fSize*0.5, m_vtx.z + c*m_fSize*0.5);
  51. m_vOctTree.push_back(ot);
  52. }
  53. #endif
  54. }
  55. }
  56. }
  57. void OctTree::clear() {
  58. m_vGroup.clear();
  59. vector<OctTree*>::iterator iter = m_vOctTree.begin();
  60. vector<OctTree*>::iterator end = m_vOctTree.end();
  61. for (; iter != end; iter++) {
  62. (*iter)->clear();
  63. }
  64. }
  65. bool OctTree::insertGroup(Group * g) {
  66. EmAssert(g != NULL, "OctTree::insertGroup() group NULL");
  67. EmAssert(g->p_CollisionBounds, "OctTree::insertGroup() collisionbounds NULL");
  68. if (this->surround(g->p_CollisionBounds)) {
  69. // try to add the group to a child, exit if it was added
  70. vector<OctTree*>::iterator iter = m_vOctTree.begin();
  71. vector<OctTree*>::iterator end = m_vOctTree.end();
  72. for ( ; iter != end; iter++) {
  73. if ((*iter)->insertGroup(g)) {
  74. return true;
  75. }
  76. }
  77. // none of the children surrounded the group, insert it here
  78. m_vGroup.push_back(g);
  79. EM_COUT("OctTree() size " << m_vGroup.size(), 0);
  80. return true;
  81. }
  82. return false;
  83. }
  84. bool OctTree::surround(CollisionBounds * cb) {
  85. EmAssert(cb != NULL, "OctTree::surround() collisionbounds NULL");
  86. // observe factor , loose octtrees if over 1.
  87. #define FACTOR 1.5f
  88. #if EM_USE_QUADTREE
  89. if ((cb->m_vtxTrans.x + cb->m_fRadius) < (m_vtx.x + m_fSize*FACTOR) &&
  90. (cb->m_vtxTrans.x - cb->m_fRadius) > (m_vtx.x - m_fSize*FACTOR) &&
  91. (cb->m_vtxTrans.z + cb->m_fRadius) < (m_vtx.z + m_fSize*FACTOR) &&
  92. (cb->m_vtxTrans.z - cb->m_fRadius) > (m_vtx.z - m_fSize*FACTOR)) {
  93. return true;
  94. }
  95. #else
  96. if ((cb->m_vtxTrans.x + cb->m_fRadius) < (m_vtx.x + m_fSize*FACTOR) &&
  97. (cb->m_vtxTrans.x - cb->m_fRadius) > (m_vtx.x - m_fSize*FACTOR) &&
  98. (cb->m_vtxTrans.y + cb->m_fRadius) < (m_vtx.y + m_fSize*FACTOR) &&
  99. (cb->m_vtxTrans.y - cb->m_fRadius) > (m_vtx.y - m_fSize*FACTOR) &&
  100. (cb->m_vtxTrans.z + cb->m_fRadius) < (m_vtx.z + m_fSize*FACTOR) &&
  101. (cb->m_vtxTrans.z - cb->m_fRadius) > (m_vtx.z - m_fSize*FACTOR)) {
  102. return true;
  103. }
  104. #endif
  105. return false;
  106. }
  107. bool OctTree::collide(CollisionBounds * cb) {
  108. EmAssert(cb != NULL, "OctTree::surround() collisionbounds NULL");
  109. // observe factor , loose octtrees if over 1.
  110. #if EM_USE_QUADTREE
  111. if ((cb->m_vtxTrans.x - cb->m_fRadius) < (m_vtx.x + m_fSize*FACTOR) &&
  112. (cb->m_vtxTrans.x + cb->m_fRadius) > (m_vtx.x - m_fSize*FACTOR) &&
  113. (cb->m_vtxTrans.z - cb->m_fRadius) < (m_vtx.z + m_fSize*FACTOR) &&
  114. (cb->m_vtxTrans.z + cb->m_fRadius) > (m_vtx.z - m_fSize*FACTOR)) {
  115. return true;
  116. }
  117. #else
  118. if ((cb->m_vtxTrans.x - cb->m_fRadius) < (m_vtx.x + m_fSize*FACTOR) &&
  119. (cb->m_vtxTrans.x + cb->m_fRadius) > (m_vtx.x - m_fSize*FACTOR) &&
  120. (cb->m_vtxTrans.y - cb->m_fRadius) < (m_vtx.y + m_fSize*FACTOR) &&
  121. (cb->m_vtxTrans.y + cb->m_fRadius) > (m_vtx.y - m_fSize*FACTOR) &&
  122. (cb->m_vtxTrans.z - cb->m_fRadius) < (m_vtx.z + m_fSize*FACTOR) &&
  123. (cb->m_vtxTrans.z + cb->m_fRadius) > (m_vtx.z - m_fSize*FACTOR)) {
  124. return true;
  125. }
  126. #endif
  127. #undef FACTOR
  128. return false;
  129. }
  130. void OctTree::printTree(int depth) {
  131. for (int a=0; a<depth; a++) {
  132. cerr << " ";
  133. }
  134. cerr << "T: " << m_vGroup.size() << endl;
  135. vector<OctTree*>::iterator iter = m_vOctTree.begin();
  136. vector<OctTree*>::iterator end = m_vOctTree.end();
  137. for (; iter != end; iter++) {
  138. (*iter)->printTree(depth+1);
  139. }
  140. }