COctreeTriangleSelector.cpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. // Copyright (C) 2002-2012 Nikolaus Gebhardt
  2. // This file is part of the "Irrlicht Engine".
  3. // For conditions of distribution and use, see copyright notice in irrlicht.h
  4. #include "COctreeTriangleSelector.h"
  5. #include "ISceneNode.h"
  6. #include "os.h"
  7. namespace irr
  8. {
  9. namespace scene
  10. {
  11. //! constructor
  12. COctreeTriangleSelector::COctreeTriangleSelector(const IMesh* mesh,
  13. ISceneNode* node, s32 minimalPolysPerNode)
  14. : CTriangleSelector(mesh, node), Root(0), NodeCount(0),
  15. MinimalPolysPerNode(minimalPolysPerNode)
  16. {
  17. #ifdef _DEBUG
  18. setDebugName("COctreeTriangleSelector");
  19. #endif
  20. if (!Triangles.empty())
  21. {
  22. const u32 start = os::Timer::getRealTime();
  23. // create the triangle octree
  24. Root = new SOctreeNode();
  25. Root->Triangles = Triangles;
  26. constructOctree(Root);
  27. c8 tmp[256];
  28. sprintf(tmp, "Needed %ums to create OctreeTriangleSelector.(%d nodes, %u polys)",
  29. os::Timer::getRealTime() - start, NodeCount, Triangles.size());
  30. os::Printer::log(tmp, ELL_INFORMATION);
  31. }
  32. }
  33. //! destructor
  34. COctreeTriangleSelector::~COctreeTriangleSelector()
  35. {
  36. delete Root;
  37. }
  38. void COctreeTriangleSelector::constructOctree(SOctreeNode* node)
  39. {
  40. ++NodeCount;
  41. node->Box.reset(node->Triangles[0].pointA);
  42. // get bounding box
  43. const u32 cnt = node->Triangles.size();
  44. for (u32 i=0; i<cnt; ++i)
  45. {
  46. node->Box.addInternalPoint(node->Triangles[i].pointA);
  47. node->Box.addInternalPoint(node->Triangles[i].pointB);
  48. node->Box.addInternalPoint(node->Triangles[i].pointC);
  49. }
  50. const core::vector3df& middle = node->Box.getCenter();
  51. core::vector3df edges[8];
  52. node->Box.getEdges(edges);
  53. core::aabbox3d<f32> box;
  54. core::array<core::triangle3df> keepTriangles;
  55. // calculate children
  56. if (!node->Box.isEmpty() && (s32)node->Triangles.size() > MinimalPolysPerNode)
  57. for (s32 ch=0; ch<8; ++ch)
  58. {
  59. box.reset(middle);
  60. box.addInternalPoint(edges[ch]);
  61. node->Child[ch] = new SOctreeNode();
  62. for (s32 i=0; i<(s32)node->Triangles.size(); ++i)
  63. {
  64. if (node->Triangles[i].isTotalInsideBox(box))
  65. {
  66. node->Child[ch]->Triangles.push_back(node->Triangles[i]);
  67. //node->Triangles.erase(i);
  68. //--i;
  69. }
  70. else
  71. {
  72. keepTriangles.push_back(node->Triangles[i]);
  73. }
  74. }
  75. memcpy(node->Triangles.pointer(), keepTriangles.pointer(),
  76. sizeof(core::triangle3df)*keepTriangles.size());
  77. node->Triangles.set_used(keepTriangles.size());
  78. keepTriangles.set_used(0);
  79. if (node->Child[ch]->Triangles.empty())
  80. {
  81. delete node->Child[ch];
  82. node->Child[ch] = 0;
  83. }
  84. else
  85. constructOctree(node->Child[ch]);
  86. }
  87. }
  88. //! Gets all triangles which lie within a specific bounding box.
  89. void COctreeTriangleSelector::getTriangles(core::triangle3df* triangles,
  90. s32 arraySize, s32& outTriangleCount,
  91. const core::aabbox3d<f32>& box,
  92. const core::matrix4* transform) const
  93. {
  94. core::matrix4 mat(core::matrix4::EM4CONST_NOTHING);
  95. core::aabbox3d<f32> invbox = box;
  96. if (SceneNode)
  97. {
  98. SceneNode->getAbsoluteTransformation().getInverse(mat);
  99. mat.transformBoxEx(invbox);
  100. }
  101. if (transform)
  102. mat = *transform;
  103. else
  104. mat.makeIdentity();
  105. if (SceneNode)
  106. mat *= SceneNode->getAbsoluteTransformation();
  107. s32 trianglesWritten = 0;
  108. if (Root)
  109. getTrianglesFromOctree(Root, trianglesWritten,
  110. arraySize, invbox, &mat, triangles);
  111. outTriangleCount = trianglesWritten;
  112. }
  113. void COctreeTriangleSelector::getTrianglesFromOctree(
  114. SOctreeNode* node, s32& trianglesWritten,
  115. s32 maximumSize, const core::aabbox3d<f32>& box,
  116. const core::matrix4* mat, core::triangle3df* triangles) const
  117. {
  118. if (!box.intersectsWithBox(node->Box))
  119. return;
  120. const u32 cnt = node->Triangles.size();
  121. for (u32 i=0; i<cnt; ++i)
  122. {
  123. const core::triangle3df& srcTri = node->Triangles[i];
  124. // This isn't an accurate test, but it's fast, and the
  125. // API contract doesn't guarantee complete accuracy.
  126. if (srcTri.isTotalOutsideBox(box))
  127. continue;
  128. core::triangle3df& dstTri = triangles[trianglesWritten];
  129. mat->transformVect(dstTri.pointA, srcTri.pointA );
  130. mat->transformVect(dstTri.pointB, srcTri.pointB );
  131. mat->transformVect(dstTri.pointC, srcTri.pointC );
  132. ++trianglesWritten;
  133. // Halt when the out array is full.
  134. if (trianglesWritten == maximumSize)
  135. return;
  136. }
  137. for (u32 i=0; i<8; ++i)
  138. if (node->Child[i])
  139. getTrianglesFromOctree(node->Child[i], trianglesWritten,
  140. maximumSize, box, mat, triangles);
  141. }
  142. //! Gets all triangles which have or may have contact with a 3d line.
  143. // new version: from user Piraaate
  144. void COctreeTriangleSelector::getTriangles(core::triangle3df* triangles, s32 arraySize,
  145. s32& outTriangleCount, const core::line3d<f32>& line,
  146. const core::matrix4* transform) const
  147. {
  148. #if 0
  149. core::aabbox3d<f32> box(line.start);
  150. box.addInternalPoint(line.end);
  151. // TODO: Could be optimized for line a little bit more.
  152. COctreeTriangleSelector::getTriangles(triangles, arraySize, outTriangleCount,
  153. box, transform);
  154. #else
  155. core::matrix4 mat ( core::matrix4::EM4CONST_NOTHING );
  156. core::vector3df vectStartInv ( line.start ), vectEndInv ( line.end );
  157. if (SceneNode)
  158. {
  159. mat = SceneNode->getAbsoluteTransformation();
  160. mat.makeInverse();
  161. mat.transformVect(vectStartInv, line.start);
  162. mat.transformVect(vectEndInv, line.end);
  163. }
  164. core::line3d<f32> invline(vectStartInv, vectEndInv);
  165. mat.makeIdentity();
  166. if (transform)
  167. mat = (*transform);
  168. if (SceneNode)
  169. mat *= SceneNode->getAbsoluteTransformation();
  170. s32 trianglesWritten = 0;
  171. if (Root)
  172. getTrianglesFromOctree(Root, trianglesWritten, arraySize, invline, &mat, triangles);
  173. outTriangleCount = trianglesWritten;
  174. #endif
  175. }
  176. void COctreeTriangleSelector::getTrianglesFromOctree(SOctreeNode* node,
  177. s32& trianglesWritten, s32 maximumSize, const core::line3d<f32>& line,
  178. const core::matrix4* transform, core::triangle3df* triangles) const
  179. {
  180. if (!node->Box.intersectsWithLine(line))
  181. return;
  182. s32 cnt = node->Triangles.size();
  183. if (cnt + trianglesWritten > maximumSize)
  184. cnt -= cnt + trianglesWritten - maximumSize;
  185. s32 i;
  186. if ( transform->isIdentity() )
  187. {
  188. for (i=0; i<cnt; ++i)
  189. {
  190. triangles[trianglesWritten] = node->Triangles[i];
  191. ++trianglesWritten;
  192. }
  193. }
  194. else
  195. {
  196. for (i=0; i<cnt; ++i)
  197. {
  198. triangles[trianglesWritten] = node->Triangles[i];
  199. transform->transformVect(triangles[trianglesWritten].pointA);
  200. transform->transformVect(triangles[trianglesWritten].pointB);
  201. transform->transformVect(triangles[trianglesWritten].pointC);
  202. ++trianglesWritten;
  203. }
  204. }
  205. for (i=0; i<8; ++i)
  206. if (node->Child[i])
  207. getTrianglesFromOctree(node->Child[i], trianglesWritten,
  208. maximumSize, line, transform, triangles);
  209. }
  210. } // end namespace scene
  211. } // end namespace irr