Embree2Intersector.h 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. #ifndef IGL_EMBREE_INTERSECTOR_H
  2. #define IGL_EMBREE_INTERSECTOR_H
  3. #include "include/embree.h"
  4. #include "include/intersector1.h"
  5. #include "common/ray.h"
  6. #include <vector>
  7. namespace igl
  8. {
  9. struct Hit
  10. {
  11. int id; // primitive id
  12. float u,v; // barycentric coordinates
  13. float t; // distance = direction*t to intersection
  14. };
  15. template <
  16. typename Scalar,
  17. typename Index>
  18. class EmbreeIntersector
  19. {
  20. typedef Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic> PointMatrixType;
  21. typedef Eigen::Matrix<Index,Eigen::Dynamic,Eigen::Dynamic> FaceMatrixType;
  22. typedef Eigen::Matrix<Scalar,1,3> RowVector3;
  23. public:
  24. // V #V by 3 list of vertex positions
  25. // F #F by 3 list of Oriented triangles
  26. EmbreeIntersector();
  27. EmbreeIntersector(
  28. const PointMatrixType & V,
  29. const FaceMatrixType & F,
  30. const char* structure = "default",
  31. const char* builder = "default",
  32. const char* traverser = "default");
  33. virtual ~EmbreeIntersector();
  34. // Given a ray find the first hit
  35. //
  36. // Inputs:
  37. // origin 3d origin point of ray
  38. // direction 3d (not necessarily normalized) direction vector of ray
  39. // Output:
  40. // hit information about hit
  41. // Returns true if and only if there was a hit
  42. bool intersectRay(
  43. const RowVector3& origin,
  44. const RowVector3& direction,
  45. Hit& hit,
  46. float tnear = 0,
  47. float tfar = embree::inf) const;
  48. // Given a ray find the all hits in order
  49. //
  50. // Inputs:
  51. // origin 3d origin point of ray
  52. // direction 3d (not necessarily normalized) direction vector of ray
  53. // Output:
  54. // hit information about hit
  55. // num_rays number of rays shot (at least one)
  56. // Returns true if and only if there was a hit
  57. bool intersectRay(
  58. const RowVector3& origin,
  59. const RowVector3& direction,
  60. std::vector<Hit > &hits,
  61. int& num_rays,
  62. float tnear = 0,
  63. float tfar = embree::inf) const;
  64. // Given a ray find the first hit
  65. //
  66. // Inputs:
  67. // a 3d first end point of segment
  68. // ab 3d vector from a to other endpoint b
  69. // Output:
  70. // hit information about hit
  71. // Returns true if and only if there was a hit
  72. bool intersectSegment(const RowVector3& a, const RowVector3& ab, Hit &hit) const;
  73. private:
  74. embree::RTCGeometry* mesh;
  75. embree::RTCTriangle* triangles;
  76. embree::RTCVertex *vertices;
  77. embree::Intersector1 *intersector;
  78. };
  79. }
  80. // Implementation
  81. #include <igl/EPS.h>
  82. template <typename RowVector3>
  83. inline embree::Vector3f toVector3f(const RowVector3 &p) { return embree::Vector3f((float)p[0], (float)p[1], (float)p[2]); }
  84. template <
  85. typename Scalar,
  86. typename Index>
  87. igl::EmbreeIntersector < Scalar, Index>
  88. ::EmbreeIntersector()
  89. {
  90. static bool inited = false;
  91. if(!inited)
  92. {
  93. embree::rtcInit();
  94. embree::rtcStartThreads();
  95. inited = true;
  96. }
  97. }
  98. template <
  99. typename Scalar,
  100. typename Index>
  101. igl::EmbreeIntersector < Scalar, Index>
  102. ::EmbreeIntersector(const PointMatrixType & V,
  103. const FaceMatrixType & F,
  104. const char* structure,
  105. const char* builder,
  106. const char* traverser)
  107. {
  108. static bool inited = false;
  109. if(!inited)
  110. {
  111. embree::rtcInit();
  112. #ifdef VERBOSE
  113. embree::rtcSetVerbose(3);
  114. #endif
  115. embree::rtcStartThreads();
  116. inited = true;
  117. }
  118. mesh = embree::rtcNewTriangleMesh(F.rows(),V.rows(),structure);
  119. // fill vertex buffer
  120. vertices = embree::rtcMapPositionBuffer(mesh);
  121. for(int i=0;i<(int)V.rows();i++)
  122. {
  123. vertices[i] = embree::RTCVertex((float)V(i,0),(float)V(i,1),(float)V(i,2));
  124. }
  125. embree::rtcUnmapPositionBuffer(mesh);
  126. // fill triangle buffer
  127. triangles = embree::rtcMapTriangleBuffer(mesh);
  128. for(int i=0;i<(int)F.rows();i++)
  129. {
  130. triangles[i] = embree::RTCTriangle((int)F(i,0),(int)F(i,1),(int)F(i,2),i);
  131. }
  132. embree::rtcUnmapTriangleBuffer(mesh);
  133. embree::rtcBuildAccel(mesh,builder);
  134. embree::rtcCleanupGeometry(mesh);
  135. intersector = embree::rtcQueryIntersector1(mesh,traverser);
  136. }
  137. template <
  138. typename Scalar,
  139. typename Index>
  140. igl::EmbreeIntersector < Scalar, Index>
  141. ::~EmbreeIntersector()
  142. {
  143. embree::rtcDeleteIntersector1(intersector);
  144. embree::rtcDeleteGeometry(mesh);
  145. // embree::rtcStopThreads();
  146. // embree::rtcExit();
  147. // embree::rtcFreeMemory();
  148. }
  149. template <
  150. typename Scalar,
  151. typename Index>
  152. bool
  153. igl::EmbreeIntersector< Scalar, Index>
  154. ::intersectRay(
  155. const RowVector3& origin,
  156. const RowVector3& direction,
  157. Hit& hit,
  158. float tnear,
  159. float tfar) const
  160. {
  161. embree::Ray ray(toVector3f(origin), toVector3f(direction), tnear, tfar);
  162. intersector->intersect(ray);
  163. if(ray)
  164. {
  165. hit.id = ray.id0;
  166. hit.u = ray.u;
  167. hit.v = ray.v;
  168. hit.t = ray.tfar;
  169. return true;
  170. }
  171. return false;
  172. }
  173. template <
  174. typename Scalar,
  175. typename Index>
  176. bool
  177. igl::EmbreeIntersector < Scalar, Index>
  178. ::intersectRay(
  179. const RowVector3& origin,
  180. const RowVector3& direction,
  181. std::vector<Hit > &hits,
  182. int& num_rays,
  183. float tnear,
  184. float tfar) const
  185. {
  186. using namespace std;
  187. num_rays = 0;
  188. hits.clear();
  189. int last_id0 = -1;
  190. double self_hits = 0;
  191. // This epsilon is directly correleated to the number of missed hits, smaller
  192. // means more accurate and slower
  193. //const double eps = DOUBLE_EPS;
  194. const double eps = FLOAT_EPS;
  195. double min_t = tnear;
  196. bool large_hits_warned = false;
  197. embree::Ray ray(toVector3f(origin),toVector3f(direction));
  198. while(true)
  199. {
  200. ray.tnear = min_t;
  201. ray.tfar = tfar;
  202. ray.id0 = -1;
  203. num_rays++;
  204. intersector->intersect(ray);
  205. if(ray)
  206. {
  207. // Hit self again, progressively advance
  208. if(ray.id0 == last_id0 || ray.tfar <= min_t)
  209. {
  210. // push min_t a bit more
  211. //double t_push = pow(2.0,self_hits-4)*(hit.t<eps?eps:hit.t);
  212. double t_push = pow(2.0,self_hits)*eps;
  213. #ifdef VERBOSE
  214. cout<<" t_push: "<<t_push<<endl;
  215. #endif
  216. //o = o+t_push*d;
  217. min_t += t_push;
  218. self_hits++;
  219. }
  220. else
  221. {
  222. Hit hit;
  223. hit.id = ray.id0;
  224. hit.u = ray.u;
  225. hit.v = ray.v;
  226. hit.t = ray.tfar;
  227. hits.push_back(hit);
  228. #ifdef VERBOSE
  229. cout<<" t: "<<hit.t<<endl;
  230. #endif
  231. // Instead of moving origin, just change min_t. That way calculations
  232. // all use exactly same origin values
  233. min_t = ray.tfar;
  234. // reset t_scale
  235. self_hits = 0;
  236. }
  237. last_id0 = ray.id0;
  238. }
  239. else
  240. break; // no more hits
  241. if(hits.size()>1000 && !large_hits_warned)
  242. {
  243. cerr<<"Warning: Large number of hits..."<<endl;
  244. cerr<<"[ ";
  245. for(vector<Hit>::iterator hit = hits.begin(); hit != hits.end();hit++)
  246. {
  247. cerr<<(hit->id+1)<<" ";
  248. }
  249. cerr.precision(std::numeric_limits< double >::digits10);
  250. cerr<<"[ ";
  251. for(vector<Hit>::iterator hit = hits.begin(); hit != hits.end(); hit++)
  252. {
  253. cerr<<(hit->t)<<endl;;
  254. }
  255. cerr<<"]"<<endl;
  256. large_hits_warned = true;
  257. return hits.empty();
  258. }
  259. }
  260. return hits.empty();
  261. }
  262. template <
  263. typename Scalar,
  264. typename Index>
  265. bool
  266. igl::EmbreeIntersector < Scalar, Index>
  267. ::intersectSegment(const RowVector3& a, const RowVector3& ab, Hit &hit) const
  268. {
  269. embree::Ray ray(toVector3f(a), toVector3f(ab), embree::zero, embree::one);
  270. intersector->intersect(ray);
  271. if(ray)
  272. {
  273. hit.id = ray.id0;
  274. hit.u = ray.u;
  275. hit.v = ray.v;
  276. hit.t = ray.tfar;
  277. return true;
  278. }
  279. return false;
  280. }
  281. #endif //EMBREE_INTERSECTOR_H