CollisionBounds.cpp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. /***************************************************************************
  2. CollisionBounds.cpp - description
  3. -------------------
  4. begin : Sun Mar 19 2000
  5. copyright : (C) 2000 by
  6. email :
  7. ***************************************************************************/
  8. #include "Private.h"
  9. #include "CollisionBounds.h"
  10. #include "Polygon.h"
  11. #include "Shape3D.h"
  12. #include "Group.h"
  13. #define BOUNDS_OVERLAP 1.0f
  14. /* */
  15. CollisionBounds::CollisionBounds(float size, float x, float y, float z) {
  16. EM_COUT("CollisionBounds() size"<< size <<" pos "<< x <<" "<< y <<" "<< z << endl, 0);
  17. m_vtxSrc.x = x;
  18. m_vtxSrc.y = y;
  19. m_vtxSrc.z = z;
  20. m_vtxTrans.x = x;
  21. m_vtxTrans.y = y;
  22. m_vtxTrans.z = z;
  23. m_fBoxSize = size;
  24. m_fRadius = size*EM_SQRT_3*BOUNDS_OVERLAP;
  25. p_Parent = NULL;
  26. m_bHasShape3D = false;
  27. }
  28. CollisionBounds::~CollisionBounds() {
  29. // the shape and polygon are borrowed from the group
  30. // so the group will delete them
  31. }
  32. /* Adds a polygon to the collision bound.
  33. * If the the collision bound has children the polygon is
  34. * added to all of the children. If a leaf collision bounds
  35. * surrounds a polygon, there is no need to add it to
  36. * neighbouring bounds. This function returns true if
  37. * if a leaf fully surrounds a polygon. */
  38. bool CollisionBounds::addSurround(Polygon3D* p) {
  39. EmAssert(p != NULL, "CollisionBounds::add polygon NULL");
  40. EM_COUT("CollisionBounds::add" << endl, 0);
  41. // add polygons only to leafs
  42. if (m_vCollisionBounds.size() > 0) {
  43. vector<CollisionBounds*>::iterator iter = m_vCollisionBounds.begin();
  44. vector<CollisionBounds*>::iterator end = m_vCollisionBounds.end();
  45. for (; iter != end; ++iter) {
  46. if ((*iter)->addSurround(p)) return true;
  47. }
  48. } else {
  49. // add surrounded polygon to bounds
  50. if (this->surround(p) == 2) {
  51. m_vPolygon.push_back(p);
  52. return true;
  53. }
  54. }
  55. return false;
  56. }
  57. void CollisionBounds::addIntersect(Polygon3D* p) {
  58. EmAssert(p != NULL, "CollisionBounds::add polygon NULL");
  59. EM_COUT("CollisionBounds::add" << endl, 0);
  60. // add polygons only to leafs
  61. if (m_vCollisionBounds.size() > 0) {
  62. vector<CollisionBounds*>::iterator iter = m_vCollisionBounds.begin();
  63. vector<CollisionBounds*>::iterator end = m_vCollisionBounds.end();
  64. for (; iter != end; ++iter) {
  65. (*iter)->addIntersect(p);
  66. }
  67. } else {
  68. // add intersection polygon to bounds
  69. if (this->intersect(p)) {
  70. m_vPolygon.push_back(p);
  71. }
  72. }
  73. }
  74. // TODO
  75. /* Does a fast conservative polygon-box intersection test.
  76. * May return intersection == true even if polygon-box does not intersect. */
  77. int CollisionBounds::intersect(Polygon3D* poly) {
  78. if (poly == NULL) return 0;
  79. if (poly->p_Shape3D == NULL) return 0;
  80. if (poly->m_vIndex.size() == 0) return 0;
  81. // a variable is true if all vertices is outside a plane created by
  82. // a side of the box.
  83. bool bHighX = true;
  84. bool bLowX = true;
  85. bool bHighY = true;
  86. bool bLowY = true;
  87. bool bHighZ = true;
  88. bool bLowZ = true;
  89. // Check if vertices in polygon is inside box.
  90. vector<int>::iterator iter = poly->m_vIndex.begin();
  91. vector<int>::iterator end = poly->m_vIndex.end();
  92. for ( ; iter != end; iter++) {
  93. Vertex3D vtx = poly->p_Shape3D->m_vVtxSrc[(*iter)];
  94. if ( (m_vtxSrc.x - m_fBoxSize*BOUNDS_OVERLAP) < vtx.x+0.01 ) bLowX = false;
  95. if ( vtx.x-0.01 < (m_vtxSrc.x + m_fBoxSize*BOUNDS_OVERLAP) ) bHighX = false;
  96. if ( (m_vtxSrc.y - m_fBoxSize*BOUNDS_OVERLAP) < vtx.y+0.01 ) bLowY = false;
  97. if ( vtx.y-0.01 < (m_vtxSrc.y + m_fBoxSize*BOUNDS_OVERLAP) ) bHighY = false;
  98. if ( (m_vtxSrc.z - m_fBoxSize*BOUNDS_OVERLAP) < vtx.z+0.01 ) bLowZ = false;
  99. if ( vtx.z-0.01 < (m_vtxSrc.z + m_fBoxSize*BOUNDS_OVERLAP) ) bHighZ = false;
  100. }
  101. EM_COUT("CollisionBounds::intersect() " << bLowX <<" "<< bHighX <<" "<<
  102. bLowY <<" "<< bHighY <<" "<< bLowZ <<" "<< bHighZ, 0);
  103. if ( bHighX || bLowX || bHighY || bLowY || bHighZ || bLowZ ) return 0;
  104. return 1;
  105. }
  106. void CollisionBounds::setParent(Group* g) {
  107. p_Parent = g;
  108. }
  109. void CollisionBounds::setShape3D(Shape3D* s, int level) {
  110. if (s == NULL) return;
  111. m_bHasShape3D = true;
  112. // Remove all old collision bounds.
  113. // TODO: Look up the name of the destroy function for vector.
  114. // Create new collision bounds
  115. this->split(level);
  116. vector<Polygon3D*>::iterator iter = s->m_vPolygon.begin();
  117. vector<Polygon3D*>::iterator end = s->m_vPolygon.end();
  118. for (int a=0; iter != end; iter++, a++) {
  119. if (!this->addSurround(*iter)) {
  120. this->addIntersect(*iter);
  121. }
  122. }
  123. this->removeEmpty();
  124. // this->printTree();
  125. }
  126. /* Returns 2 if box surround all vertices, returns 1 if box surround
  127. * at least one vertex, else returns 0. */
  128. int CollisionBounds::surround(Polygon3D* poly) {
  129. if (poly == NULL) return 0;
  130. if (poly->p_Shape3D == NULL) return 0;
  131. if (poly->m_vIndex.size() == 0) return 0;
  132. bool bFull = true;
  133. bool bSurround = false;
  134. // Check if vertices in polygon is inside box.
  135. vector<int>::iterator iter = poly->m_vIndex.begin();
  136. vector<int>::iterator end = poly->m_vIndex.end();
  137. for ( ; iter != end; iter++) {
  138. Vertex3D vtx = poly->p_Shape3D->m_vVtxSrc[(*iter)];
  139. float dx = m_vtxSrc.x - vtx.x;
  140. float dy = m_vtxSrc.y - vtx.y;
  141. float dz = m_vtxSrc.z - vtx.z;
  142. EM_COUT(dx <<" "<< dy <<" "<< dz <<endl, 0);
  143. if ( dx >= -m_fBoxSize*BOUNDS_OVERLAP && dx <= m_fBoxSize*BOUNDS_OVERLAP &&
  144. dy >= -m_fBoxSize*BOUNDS_OVERLAP && dy <= m_fBoxSize*BOUNDS_OVERLAP &&
  145. dz >= -m_fBoxSize*BOUNDS_OVERLAP && dz <= m_fBoxSize*BOUNDS_OVERLAP) {
  146. bSurround = true;
  147. } else {
  148. bFull = false;
  149. }
  150. }
  151. if (bFull) return 2;
  152. else if (bSurround) return 1;
  153. return 0;
  154. }
  155. void CollisionBounds::printTree(int level) {
  156. EM_COUT("T: ", 0);
  157. int a;
  158. for (a=0; a<level; ++a) {
  159. EM_COUT(" ", 0);
  160. }
  161. EM_COUT("CollisionBounds " << this->m_vPolygon.size() << " polygons", 0);
  162. vector<CollisionBounds*>::iterator iter = m_vCollisionBounds.begin();
  163. vector<CollisionBounds*>::iterator end = m_vCollisionBounds.end();
  164. for (; iter != end; ++iter) {
  165. (*iter)->printTree(level+1);
  166. }
  167. }
  168. bool CollisionBounds::removeEmpty() {
  169. vector<CollisionBounds*>::iterator iter = m_vCollisionBounds.begin();
  170. vector<CollisionBounds*>::iterator end = m_vCollisionBounds.end();
  171. for (; iter != end; ++iter) {
  172. if ((*iter)->removeEmpty()) {
  173. CollisionBounds* cb = (*iter);
  174. m_vCollisionBounds.erase(iter);
  175. delete(cb);
  176. // an object is erased, I think we need re-initialize
  177. iter = m_vCollisionBounds.begin();
  178. end = m_vCollisionBounds.end();
  179. EM_COUT("CollisionBounds::removeEmpty - removed a bound", 0);
  180. }
  181. }
  182. return (m_vCollisionBounds.size() == 0 && m_vPolygon.size() == 0);
  183. }
  184. void CollisionBounds::split(int level) {
  185. int a, b, c;
  186. if (level <= 1) return;
  187. EM_COUT("CollisionBounds::split "<< level << endl, 0);
  188. for (a=-1; a<2; a+=2) {
  189. for (b=-1; b<2; b+=2) {
  190. for (c=-1; c<2; c+=2) {
  191. CollisionBounds* cb = new CollisionBounds( m_fBoxSize*0.5,
  192. m_vtxSrc.x + a*m_fBoxSize*0.5, m_vtxSrc.y + b*m_fBoxSize*0.5,
  193. m_vtxSrc.z + c*m_fBoxSize*0.5);
  194. cb->setParent(p_Parent);
  195. m_vCollisionBounds.push_back(cb);
  196. }
  197. }
  198. }
  199. vector<CollisionBounds*>::iterator iter = m_vCollisionBounds.begin();
  200. vector<CollisionBounds*>::iterator end = m_vCollisionBounds.end();
  201. for ( ; iter != end; iter++) {
  202. (*iter)->split(level-1);
  203. }
  204. }
  205. void CollisionBounds::transform(const Matrix & mtx) {
  206. vector<CollisionBounds*>::iterator iter = m_vCollisionBounds.begin();
  207. vector<CollisionBounds*>::iterator end = m_vCollisionBounds.end();
  208. for ( ; iter != end; ++iter) {
  209. (*iter)->transform(mtx);
  210. }
  211. //EMATH_APPLYMATRIX(mtx, m_vtxSrc, m_vtxTrans);
  212. EMath::applyMatrix(mtx, m_vtxSrc, m_vtxTrans);
  213. EM_COUT("CollisionBounds::transform "<< m_vtxTrans.x <<" "<< m_vtxTrans.y <<" "<< m_vtxTrans.z, 0);
  214. }