EmbreeIntersector.h 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. #ifndef IGL_EMBREE_INTERSECTOR_H
  2. #define IGL_EMBREE_INTERSECTOR_H
  3. #undef interface
  4. #undef near
  5. #undef far
  6. #include "common/intersector.h"
  7. #include "common/accel.h"
  8. #include <vector>
  9. //#include "types.h"
  10. namespace igl
  11. {
  12. template <
  13. typename PointMatrixType,
  14. typename FaceMatrixType,
  15. typename RowVector3>
  16. class EmbreeIntersector
  17. {
  18. public:
  19. // V #V by 3 list of vertex positions
  20. // F #F by 3 list of Oriented triangles
  21. //
  22. // Note: this will only find front-facing hits. To consider all hits then
  23. // pass [F;fliplr(F)]
  24. EmbreeIntersector();
  25. EmbreeIntersector(const PointMatrixType & V, const FaceMatrixType & F);
  26. virtual ~EmbreeIntersector();
  27. // Given a ray find the first *front-facing* hit
  28. //
  29. // Inputs:
  30. // origin 3d origin point of ray
  31. // direction 3d (not necessarily normalized) direction vector of ray
  32. // Output:
  33. // hit embree information about hit
  34. // Returns true if and only if there was a hit
  35. bool intersectRay(
  36. const RowVector3& origin,
  37. const RowVector3& direction,
  38. embree::Hit &hit) const;
  39. // Given a ray find the all *front-facing* hits in order
  40. //
  41. // Inputs:
  42. // origin 3d origin point of ray
  43. // direction 3d (not necessarily normalized) direction vector of ray
  44. // Output:
  45. // hit embree information about hit
  46. // num_rays number of rays shot (at least one)
  47. // Returns true if and only if there was a hit
  48. bool intersectRay(
  49. const RowVector3& origin,
  50. const RowVector3& direction,
  51. std::vector<embree::Hit > &hits,
  52. int & num_rays) const;
  53. // Given a ray find the first *front-facing* hit
  54. //
  55. // Inputs:
  56. // a 3d first end point of segment
  57. // ab 3d vector from a to other endpoint b
  58. // Output:
  59. // hit embree information about hit
  60. // Returns true if and only if there was a hit
  61. bool intersectSegment(const RowVector3& a, const RowVector3& ab, embree::Hit &hit) const;
  62. private:
  63. embree::BuildTriangle *triangles;
  64. embree::BuildVertex *vertices;
  65. embree::Ref<embree::Accel> _accel;
  66. embree::Ref<embree::Intersector> _intersector;
  67. };
  68. }
  69. // Implementation
  70. #include <igl/EPS.h>
  71. template <typename RowVector3>
  72. inline embree::Vec3f toVec3f(const RowVector3 &p) { return embree::Vec3f((float)p[0], (float)p[1], (float)p[2]); }
  73. template <
  74. typename PointMatrixType,
  75. typename FaceMatrixType,
  76. typename RowVector3>
  77. igl::EmbreeIntersector < PointMatrixType, FaceMatrixType, RowVector3>
  78. ::EmbreeIntersector()
  79. {
  80. static bool inited = false;
  81. if(!inited)
  82. {
  83. //embree::TaskScheduler::start();//init();
  84. inited = true;
  85. }
  86. }
  87. template <
  88. typename PointMatrixType,
  89. typename FaceMatrixType,
  90. typename RowVector3>
  91. igl::EmbreeIntersector < PointMatrixType, FaceMatrixType, RowVector3>
  92. ::EmbreeIntersector(const PointMatrixType & V, const FaceMatrixType & F)
  93. {
  94. static bool inited = false;
  95. if(!inited)
  96. {
  97. //embree::TaskScheduler::start();//init();
  98. inited = true;
  99. }
  100. size_t numVertices = 0;
  101. size_t numTriangles = 0;
  102. triangles = (embree::BuildTriangle*) embree::rtcMalloc(sizeof(embree::BuildTriangle) * F.rows());
  103. vertices = (embree::BuildVertex*) embree::rtcMalloc(sizeof(embree::BuildVertex) * V.rows());
  104. for(int i = 0; i < (int)V.rows(); ++i)
  105. {
  106. vertices[numVertices++] = embree::BuildVertex((float)V(i,0),(float)V(i,1),(float)V(i,2));
  107. }
  108. for(int i = 0; i < (int)F.rows(); ++i)
  109. {
  110. triangles[numTriangles++] = embree::BuildTriangle((int)F(i,0),(int)F(i,1),(int)F(i,2),i);
  111. }
  112. _accel = embree::rtcCreateAccel("default", "default", triangles, numTriangles, vertices, numVertices);
  113. _intersector = _accel->queryInterface<embree::Intersector>();
  114. }
  115. template <
  116. typename PointMatrixType,
  117. typename FaceMatrixType,
  118. typename RowVector3>
  119. igl::EmbreeIntersector < PointMatrixType, FaceMatrixType, RowVector3>
  120. ::~EmbreeIntersector()
  121. {
  122. embree::rtcFreeMemory();
  123. }
  124. template <
  125. typename PointMatrixType,
  126. typename FaceMatrixType,
  127. typename RowVector3>
  128. bool
  129. igl::EmbreeIntersector < PointMatrixType, FaceMatrixType, RowVector3>
  130. ::intersectRay(const RowVector3& origin, const RowVector3& direction, embree::Hit &hit) const
  131. {
  132. embree::Ray ray(toVec3f(origin), toVec3f(direction), 1e-4f);
  133. _intersector->intersect(ray, hit);
  134. return hit ;
  135. }
  136. template <
  137. typename PointMatrixType,
  138. typename FaceMatrixType,
  139. typename RowVector3>
  140. bool
  141. igl::EmbreeIntersector < PointMatrixType, FaceMatrixType, RowVector3>
  142. ::intersectRay(
  143. const RowVector3& origin,
  144. const RowVector3& direction,
  145. std::vector<embree::Hit > &hits,
  146. int & num_rays) const
  147. {
  148. using namespace std;
  149. num_rays = 0;
  150. hits.clear();
  151. embree::Vec3f o = toVec3f(origin);
  152. embree::Vec3f d = toVec3f(direction);
  153. int last_id0 = -1;
  154. double self_hits = 0;
  155. // This epsilon is directly correleated to the number of missed hits, smaller
  156. // means more accurate and slower
  157. //const double eps = DOUBLE_EPS;
  158. const double eps = FLOAT_EPS;
  159. double min_t = embree::zero;
  160. bool large_hits_warned = false;
  161. while(true)
  162. {
  163. #ifdef VERBOSE
  164. cout<<
  165. o[0]<<" "<<o[1]<<" "<<o[2]<<" + t*"<<
  166. d[0]<<" "<<d[1]<<" "<<d[2]<<" ---> "<<
  167. endl;
  168. #endif
  169. embree::Hit hit;
  170. embree::Ray ray(o,d,min_t);
  171. num_rays++;
  172. _intersector->intersect(ray, hit);
  173. if(hit)
  174. {
  175. // Hit self again, progressively advance
  176. if(hit.id0 == last_id0 || hit.t <= min_t)
  177. {
  178. // sanity check
  179. assert(hit.t<1);
  180. // push min_t a bit more
  181. //double t_push = pow(2.0,self_hits-4)*(hit.t<eps?eps:hit.t);
  182. double t_push = pow(2.0,self_hits)*eps;
  183. #ifdef VERBOSE
  184. cout<<" t_push: "<<t_push<<endl;
  185. #endif
  186. //o = o+t_push*d;
  187. min_t += t_push;
  188. self_hits++;
  189. }else
  190. {
  191. hits.push_back(hit);
  192. #ifdef VERBOSE
  193. cout<<" t: "<<hit.t<<endl;
  194. #endif
  195. // Instead of moving origin, just change min_t. That way calculations
  196. // all use exactly same origin values
  197. min_t = hit.t;
  198. // reset t_scale
  199. self_hits = 0;
  200. }
  201. last_id0 = hit.id0;
  202. //cout<<" id0: "<<hit.id0<<endl;
  203. }else
  204. {
  205. break;
  206. }
  207. if(hits.size()>1000 && !large_hits_warned)
  208. {
  209. cerr<<"Warning: Large number of hits..."<<endl;
  210. cerr<<"[ ";
  211. for(vector<embree::Hit>::iterator hit = hits.begin();
  212. hit != hits.end();
  213. hit++)
  214. {
  215. cerr<<(hit->id0+1)<<" ";
  216. }
  217. cerr.precision(std::numeric_limits< double >::digits10);
  218. cerr<<"[ ";
  219. for(vector<embree::Hit>::iterator hit = hits.begin();
  220. hit != hits.end();
  221. hit++)
  222. {
  223. cerr<<(hit->t)<<endl;;
  224. }
  225. cerr<<"]"<<endl;
  226. large_hits_warned = true;
  227. return hits.empty();
  228. }
  229. }
  230. return hits.empty();
  231. }
  232. template <
  233. typename PointMatrixType,
  234. typename FaceMatrixType,
  235. typename RowVector3>
  236. bool
  237. igl::EmbreeIntersector < PointMatrixType, FaceMatrixType, RowVector3>
  238. ::intersectSegment(const RowVector3& a, const RowVector3& ab, embree::Hit &hit) const
  239. {
  240. embree::Ray ray(toVec3f(a), toVec3f(ab), embree::zero, embree::one);
  241. _intersector->intersect(ray, hit);
  242. return hit ;
  243. }
  244. #endif //EMBREE_INTERSECTOR_H