EmbreeRenderer.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  1. #include "EmbreeRenderer.h"
  2. // Implementation
  3. //IGL viewing parts
  4. #include "../unproject.h"
  5. #include "../look_at.h"
  6. #include "../frustum.h"
  7. #include "../ortho.h"
  8. // color map
  9. #include "../jet.h"
  10. #include "../PI.h"
  11. IGL_INLINE void igl::embree::EmbreeRenderer::init_view()
  12. {
  13. camera_base_zoom = 1.0f;
  14. camera_zoom = 1.0f;
  15. camera_view_angle = 45.0;
  16. camera_dnear = 1.0;
  17. camera_dfar = 100.0;
  18. camera_base_translation << 0, 0, 0;
  19. camera_translation << 0, 0, 0;
  20. camera_eye << 0, 0, 5;
  21. camera_center << 0, 0, 0;
  22. camera_up << 0, 1, 0;
  23. rot_matrix = Eigen::Matrix3f::Identity();
  24. view = Eigen::Matrix4f::Identity();
  25. proj = Eigen::Matrix4f::Identity();
  26. norm = Eigen::Matrix4f::Identity();
  27. orthographic = false;
  28. }
  29. IGL_INLINE igl::embree::EmbreeRenderer::EmbreeRenderer()
  30. :
  31. scene(NULL),
  32. geomID(0),
  33. initialized(false),
  34. device(igl::embree::EmbreeDevice::get_device())
  35. {
  36. init_view();
  37. uC << 1,0,0;
  38. double_sided = false;
  39. }
  40. IGL_INLINE igl::embree::EmbreeRenderer::EmbreeRenderer(
  41. const EmbreeRenderer &)
  42. :// To make -Weffc++ happy
  43. scene(NULL),
  44. geomID(0),
  45. initialized(false)
  46. {
  47. assert(false && "Embree: Copying EmbreeRenderer is not allowed");
  48. }
  49. IGL_INLINE igl::embree::EmbreeRenderer & igl::embree::EmbreeRenderer::operator=(
  50. const EmbreeRenderer &)
  51. {
  52. assert(false && "Embree: Assigning an EmbreeRenderer is not allowed");
  53. return *this;
  54. }
  55. IGL_INLINE void igl::embree::EmbreeRenderer::init(
  56. const PointMatrixType& V,
  57. const FaceMatrixType& F,
  58. bool isStatic)
  59. {
  60. std::vector<const PointMatrixType*> Vtemp;
  61. std::vector<const FaceMatrixType*> Ftemp;
  62. std::vector<int> masks;
  63. Vtemp.push_back(&V);
  64. Ftemp.push_back(&F);
  65. masks.push_back(0xFFFFFFFF);
  66. init(Vtemp,Ftemp,masks,isStatic);
  67. }
  68. IGL_INLINE void igl::embree::EmbreeRenderer::init(
  69. const std::vector<const PointMatrixType*>& V,
  70. const std::vector<const FaceMatrixType*>& F,
  71. const std::vector<int>& masks,
  72. bool isStatic)
  73. {
  74. if(initialized)
  75. deinit();
  76. if(V.size() == 0 || F.size() == 0)
  77. {
  78. std::cerr << "Embree: No geometry specified!";
  79. return;
  80. }
  81. RTCBuildQuality buildQuality = isStatic ? RTC_BUILD_QUALITY_HIGH : RTC_BUILD_QUALITY_MEDIUM;
  82. // create a scene
  83. scene = rtcNewScene(device);
  84. rtcSetSceneFlags(scene, RTC_SCENE_FLAG_ROBUST);
  85. rtcSetSceneBuildQuality(scene, buildQuality);
  86. for(int g=0;g<(int)V.size();g++)
  87. {
  88. // create triangle mesh geometry in that scene
  89. RTCGeometry geom_0 = rtcNewGeometry (device, RTC_GEOMETRY_TYPE_TRIANGLE);
  90. rtcSetGeometryBuildQuality(geom_0, buildQuality);
  91. rtcSetGeometryTimeStepCount(geom_0,1);
  92. geomID = rtcAttachGeometry(scene,geom_0);
  93. rtcReleaseGeometry(geom_0);
  94. // fill vertex buffer, have to be 16 byte wide( sizeof(float)*4 )
  95. Eigen::Map<Eigen::Matrix<float,-1,4,Eigen::RowMajor>> vertices(
  96. (float*)rtcSetNewGeometryBuffer(geom_0,RTC_BUFFER_TYPE_VERTEX,0,RTC_FORMAT_FLOAT3,4*sizeof(float),V[g]->rows()),
  97. V[g]->rows(),4
  98. );
  99. vertices.block(0,0,V[g]->rows(),3) = V[g]->cast<float>();
  100. // fill triangle buffer
  101. Eigen::Map<Eigen::Matrix<unsigned int,-1,3,Eigen::RowMajor>> triangles(
  102. (unsigned int*) rtcSetNewGeometryBuffer(geom_0,RTC_BUFFER_TYPE_INDEX,0,RTC_FORMAT_UINT3,3*sizeof(unsigned int), F[g]->rows()),
  103. F[g]->rows(),3
  104. );
  105. triangles = F[g]->cast<unsigned int>();
  106. //TODO: store vertices and triangles in array for whatever reason?
  107. rtcSetGeometryMask(geom_0, masks[g]);
  108. rtcCommitGeometry(geom_0);
  109. }
  110. rtcCommitScene(scene);
  111. if(rtcGetDeviceError (device) != RTC_ERROR_NONE)
  112. std::cerr << "Embree: An error occurred while initializing the provided geometry!" << std::endl;
  113. #ifdef IGL_VERBOSE
  114. else
  115. std::cerr << "Embree: geometry added." << std::endl;
  116. #endif
  117. initialized = true;
  118. }
  119. IGL_INLINE igl::embree::EmbreeRenderer::~EmbreeRenderer()
  120. {
  121. if(initialized)
  122. deinit();
  123. igl::embree::EmbreeDevice::release_device();
  124. }
  125. IGL_INLINE void igl::embree::EmbreeRenderer::deinit()
  126. {
  127. if(scene)
  128. {
  129. rtcReleaseScene(scene);
  130. if(rtcGetDeviceError (device) != RTC_ERROR_NONE)
  131. {
  132. std::cerr << "Embree: An error occurred while resetting!" << std::endl;
  133. }
  134. #ifdef IGL_VERBOSE
  135. else
  136. {
  137. std::cerr << "Embree: geometry removed." << std::endl;
  138. }
  139. #endif
  140. }
  141. }
  142. IGL_INLINE bool igl::embree::EmbreeRenderer::intersect_ray(
  143. const Eigen::RowVector3f& origin,
  144. const Eigen::RowVector3f& direction,
  145. Hit & hit,
  146. float tnear,
  147. float tfar,
  148. int mask) const
  149. {
  150. RTCRayHit ray;
  151. ray.ray.flags = 0;
  152. create_ray(ray, origin,direction,tnear,tfar,mask);
  153. // shot ray
  154. {
  155. rtcIntersect1(scene,&ray);
  156. ray.hit.Ng_x = -ray.hit.Ng_x; // EMBREE_FIXME: only correct for triangles,quads, and subdivision surfaces
  157. ray.hit.Ng_y = -ray.hit.Ng_y;
  158. ray.hit.Ng_z = -ray.hit.Ng_z;
  159. }
  160. #ifdef IGL_VERBOSE
  161. if(rtcGetDeviceError (device) != RTC_ERROR_NONE)
  162. std::cerr << "Embree: An error occurred while resetting!" << std::endl;
  163. #endif
  164. if((unsigned)ray.hit.geomID != RTC_INVALID_GEOMETRY_ID)
  165. {
  166. hit.id = ray.hit.primID;
  167. hit.gid = ray.hit.geomID;
  168. hit.u = ray.hit.u;
  169. hit.v = ray.hit.v;
  170. hit.t = ray.ray.tfar;
  171. hit.N = Vec3f(ray.hit.Ng_x, ray.hit.Ng_y, ray.hit.Ng_z);
  172. return true;
  173. }
  174. return false;
  175. }
  176. IGL_INLINE void
  177. igl::embree::EmbreeRenderer
  178. ::create_ray(RTCRayHit& ray, const Eigen::RowVector3f& origin,
  179. const Eigen::RowVector3f& direction, float tnear, float tfar, int mask) const
  180. {
  181. ray.ray.org_x = origin[0];
  182. ray.ray.org_y = origin[1];
  183. ray.ray.org_z = origin[2];
  184. ray.ray.dir_x = direction[0];
  185. ray.ray.dir_y = direction[1];
  186. ray.ray.dir_z = direction[2];
  187. ray.ray.tnear = tnear;
  188. ray.ray.tfar = tfar;
  189. ray.ray.id = RTC_INVALID_GEOMETRY_ID;
  190. ray.ray.mask = mask;
  191. ray.ray.time = 0.0f;
  192. ray.hit.geomID = RTC_INVALID_GEOMETRY_ID;
  193. ray.hit.instID[0] = RTC_INVALID_GEOMETRY_ID;
  194. ray.hit.primID = RTC_INVALID_GEOMETRY_ID;
  195. }
  196. template <typename DerivedV, typename DerivedF>
  197. IGL_INLINE void
  198. igl::embree::EmbreeRenderer
  199. ::set_mesh(const Eigen::MatrixBase<DerivedV> & MV,
  200. const Eigen::MatrixBase<DerivedF> & MF,
  201. bool is_static)
  202. {
  203. V = MV.template cast<float>();
  204. F = MF;
  205. this->init(V,F,is_static);
  206. auto min_point = V.colwise().minCoeff();
  207. auto max_point = V.colwise().maxCoeff();
  208. auto centroid = (0.5*(min_point + max_point)).eval();
  209. camera_base_translation.setConstant(0);
  210. camera_base_translation.head(centroid.size()) = -centroid.cast<float>();
  211. camera_base_zoom = 2.0 / (max_point-min_point).array().abs().maxCoeff();
  212. }
  213. IGL_INLINE void
  214. igl::embree::EmbreeRenderer
  215. ::render_buffer(PixelMatrixType& R, PixelMatrixType&G, PixelMatrixType &B,PixelMatrixType &A)
  216. {
  217. assert(R.rows()==G.rows());assert(R.rows()==B.rows());assert(R.rows()==A.rows());
  218. assert(R.cols()==G.cols());assert(R.cols()==B.cols());assert(R.cols()==A.cols());
  219. Eigen::Vector4f viewport(0,0,R.rows(),R.cols());
  220. float width = R.rows();
  221. float height = R.cols();
  222. // update view matrix
  223. igl::look_at( camera_eye, camera_center, camera_up, view);
  224. view = view
  225. * (rot_matrix * Eigen::Scaling(camera_zoom * camera_base_zoom)
  226. * Eigen::Translation3f(camera_translation + camera_base_translation)).matrix();
  227. if (orthographic)
  228. {
  229. float length = (camera_eye - camera_center).norm();
  230. float h = tan(camera_view_angle/360.0 * igl::PI) * (length);
  231. igl::ortho(-h*width/height, h*width/height, -h, h, camera_dnear, camera_dfar, proj);
  232. } else {
  233. float fH = tan(camera_view_angle / 360.0 * igl::PI) * camera_dnear;
  234. float fW = fH * (double)width/(double)height;
  235. igl::frustum(-fW, fW, -fH, fH, camera_dnear, camera_dfar, proj);
  236. }
  237. // go over all pixels in the "view"
  238. for(int x=0;x<(int)width;++x)
  239. {
  240. for(int y=0;y<(int)height;++y)
  241. {
  242. Vec3f s,d,dir;
  243. igl::embree::EmbreeRenderer::Hit hit;
  244. // look into the screen
  245. Vec3f win_s(x,y,0);
  246. Vec3f win_d(x,y,1);
  247. // Source, destination and direction in world
  248. igl::unproject(win_s,this->view,this->proj,viewport,s);
  249. igl::unproject(win_d,this->view,this->proj,viewport,d);
  250. dir = d-s;
  251. dir.normalize();
  252. auto clamp=[](float x)->unsigned char {return (unsigned char)(x<0?0:x>1.0?255:x*255);};
  253. if(this->intersect_ray(s,dir,hit))
  254. {
  255. if ( double_sided || dir.dot(hit.N) > 0.0f )
  256. {
  257. // TODO: interpolate normals ?
  258. hit.N.normalize();
  259. // cos between ray and face normal
  260. // negative projection will indicate back side
  261. float face_proj = fabs(dir.dot(hit.N));
  262. Eigen::RowVector3f c;
  263. if(this->uniform_color)
  264. {
  265. // same color for the whole mesh
  266. c=this->uC;
  267. } else if(this->face_based) {
  268. // flat color per face
  269. c=this->C.row(hit.id);
  270. } else { //use barycentric coordinates to interpolate colour
  271. c=this->C.row(F(hit.id,1))*hit.u+
  272. this->C.row(F(hit.id,2))*hit.v+
  273. this->C.row(F(hit.id,0))*(1.0-hit.u-hit.v);
  274. }
  275. R(x,y) = clamp(face_proj*c(0));
  276. G(x,y) = clamp(face_proj*c(1));
  277. B(x,y) = clamp(face_proj*c(2));
  278. } else {
  279. // backface?
  280. R(x,y)=0;
  281. G(x,y)=0;
  282. B(x,y)=0;
  283. }
  284. // give the same alpha to all points with something behind
  285. A(x,y)=255;
  286. } else {
  287. R(x,y)=0;
  288. G(x,y)=0;
  289. B(x,y)=0;
  290. A(x,y)=0;
  291. }
  292. }
  293. }
  294. }
  295. template <typename DerivedC>
  296. IGL_INLINE void
  297. igl::embree::EmbreeRenderer
  298. ::set_colors(const Eigen::MatrixBase<DerivedC> & C)
  299. {
  300. if(C.rows()==V.rows()) // per vertex color
  301. {
  302. face_based = false;
  303. this->C = C.template cast<float>();
  304. this->uniform_color=false;
  305. } else if (C.rows()==F.rows()) {
  306. face_based = true;
  307. this->C = C.template cast<float>();
  308. this->uniform_color=false;
  309. } else if (C.rows()==1) {
  310. face_based = true;
  311. this->uC = C.template cast<float>();
  312. this->uniform_color=true;
  313. }else {
  314. // don't know what to do
  315. this->uniform_color=true;
  316. assert(false); //?
  317. }
  318. }
  319. template <typename DerivedD>
  320. IGL_INLINE void
  321. igl::embree::EmbreeRenderer
  322. ::set_data(const Eigen::MatrixBase<DerivedD> & D, igl::ColorMapType cmap)
  323. {
  324. const auto caxis_min = D.minCoeff();
  325. const auto caxis_max = D.maxCoeff();
  326. return set_data(D,caxis_min,caxis_max,cmap);
  327. }
  328. template <typename DerivedD, typename T>
  329. IGL_INLINE void igl::embree::EmbreeRenderer::set_data(
  330. const Eigen::MatrixBase<DerivedD> & D,
  331. T caxis_min,
  332. T caxis_max,
  333. igl::ColorMapType cmap)
  334. {
  335. Eigen::Matrix<T, -1, -1> C;
  336. igl::colormap(cmap,D,caxis_min,caxis_max,C);
  337. set_colors(C);
  338. }
  339. template <typename Derivedr>
  340. IGL_INLINE void
  341. igl::embree::EmbreeRenderer::set_rot(const Eigen::MatrixBase<Derivedr> &r)
  342. {
  343. this->rot_matrix = r.template cast<float>();
  344. }
  345. template <typename T>
  346. IGL_INLINE void
  347. igl::embree::EmbreeRenderer::set_zoom(T zoom)
  348. {
  349. this->camera_zoom=zoom;
  350. }
  351. template <typename Derivedtr>
  352. IGL_INLINE void
  353. igl::embree::EmbreeRenderer::set_translation(const Eigen::MatrixBase<Derivedtr> &tr)
  354. {
  355. this->camera_translation=tr.template cast<float>();
  356. }
  357. IGL_INLINE void
  358. igl::embree::EmbreeRenderer::set_face_based(bool _f)
  359. {
  360. this->face_based=_f;
  361. }
  362. IGL_INLINE void
  363. igl::embree::EmbreeRenderer::set_orthographic(bool o)
  364. {
  365. this->orthographic=o;
  366. }
  367. IGL_INLINE void
  368. igl::embree::EmbreeRenderer::set_double_sided(bool d)
  369. {
  370. this->double_sided=d;
  371. }
  372. #ifdef IGL_STATIC_LIBRARY
  373. template void igl::embree::EmbreeRenderer::set_rot<Eigen::Matrix<double, 3, 3, 0, 3, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, 3, 3, 0, 3, 3> > const&);
  374. template void igl::embree::EmbreeRenderer::set_data<Eigen::Matrix<double, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, igl::ColorMapType);
  375. template void igl::embree::EmbreeRenderer::set_mesh<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, bool);
  376. template void igl::embree::EmbreeRenderer::set_zoom<double>(double);
  377. #endif //IGL_STATIC_LIBRARY