Embree2Intersector.h 7.8 KB

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