2
0

EmbreeRenderer.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  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. uC << 1,0,0;
  29. }
  30. IGL_INLINE igl::embree::EmbreeRenderer::EmbreeRenderer()
  31. :
  32. scene(NULL),
  33. geomID(0),
  34. initialized(false),
  35. device(igl::embree::EmbreeDevice::get_device())
  36. {
  37. init_view();
  38. }
  39. IGL_INLINE igl::embree::EmbreeRenderer::EmbreeRenderer(
  40. const EmbreeRenderer &)
  41. :// To make -Weffc++ happy
  42. scene(NULL),
  43. geomID(0),
  44. initialized(false)
  45. {
  46. assert(false && "Embree: Copying EmbreeRenderer is not allowed");
  47. }
  48. IGL_INLINE igl::embree::EmbreeRenderer & igl::embree::EmbreeRenderer::operator=(
  49. const EmbreeRenderer &)
  50. {
  51. assert(false && "Embree: Assigning an EmbreeRenderer is not allowed");
  52. return *this;
  53. }
  54. IGL_INLINE void igl::embree::EmbreeRenderer::init(
  55. const PointMatrixType& V,
  56. const FaceMatrixType& F,
  57. bool isStatic)
  58. {
  59. std::vector<const PointMatrixType*> Vtemp;
  60. std::vector<const FaceMatrixType*> Ftemp;
  61. std::vector<int> masks;
  62. Vtemp.push_back(&V);
  63. Ftemp.push_back(&F);
  64. masks.push_back(0xFFFFFFFF);
  65. init(Vtemp,Ftemp,masks,isStatic);
  66. }
  67. IGL_INLINE void igl::embree::EmbreeRenderer::init(
  68. const std::vector<const PointMatrixType*>& V,
  69. const std::vector<const FaceMatrixType*>& F,
  70. const std::vector<int>& masks,
  71. bool isStatic)
  72. {
  73. if(initialized)
  74. deinit();
  75. using namespace std;
  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!" << endl;
  113. #ifdef IGL_VERBOSE
  114. else
  115. std::cerr << "Embree: geometry added." << 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. RTCIntersectContext context;
  156. rtcInitIntersectContext(&context);
  157. rtcIntersect1(scene, &context, &ray);
  158. ray.hit.Ng_x = -ray.hit.Ng_x; // EMBREE_FIXME: only correct for triangles,quads, and subdivision surfaces
  159. ray.hit.Ng_y = -ray.hit.Ng_y;
  160. ray.hit.Ng_z = -ray.hit.Ng_z;
  161. }
  162. #ifdef IGL_VERBOSE
  163. if(rtcGetDeviceError (device) != RTC_ERROR_NONE)
  164. std::cerr << "Embree: An error occurred while resetting!" << std::endl;
  165. #endif
  166. if((unsigned)ray.hit.geomID != RTC_INVALID_GEOMETRY_ID)
  167. {
  168. hit.id = ray.hit.primID;
  169. hit.gid = ray.hit.geomID;
  170. hit.u = ray.hit.u;
  171. hit.v = ray.hit.v;
  172. hit.t = ray.ray.tfar;
  173. hit.N = Vec3f(ray.hit.Ng_x, ray.hit.Ng_y, ray.hit.Ng_z);
  174. return true;
  175. }
  176. return false;
  177. }
  178. IGL_INLINE void
  179. igl::embree::EmbreeRenderer
  180. ::create_ray(RTCRayHit& ray, const Eigen::RowVector3f& origin,
  181. const Eigen::RowVector3f& direction, float tnear, float tfar, int mask) const
  182. {
  183. ray.ray.org_x = origin[0];
  184. ray.ray.org_y = origin[1];
  185. ray.ray.org_z = origin[2];
  186. ray.ray.dir_x = direction[0];
  187. ray.ray.dir_y = direction[1];
  188. ray.ray.dir_z = direction[2];
  189. ray.ray.tnear = tnear;
  190. ray.ray.tfar = tfar;
  191. ray.ray.id = RTC_INVALID_GEOMETRY_ID;
  192. ray.ray.mask = mask;
  193. ray.ray.time = 0.0f;
  194. ray.hit.geomID = RTC_INVALID_GEOMETRY_ID;
  195. ray.hit.instID[0] = RTC_INVALID_GEOMETRY_ID;
  196. ray.hit.primID = RTC_INVALID_GEOMETRY_ID;
  197. }
  198. IGL_INLINE void
  199. igl::embree::EmbreeRenderer
  200. ::set_mesh(const Eigen::Matrix<double,Eigen::Dynamic,3> & MV,
  201. const Eigen::Matrix<int, Eigen::Dynamic,3> & MF,
  202. bool is_static)
  203. {
  204. V = MV.cast<float>();
  205. F = MF;
  206. this->init(V,F,is_static);
  207. auto min_point = V.colwise().minCoeff();
  208. auto max_point = V.colwise().maxCoeff();
  209. auto centroid = (0.5*(min_point + max_point)).eval();
  210. camera_base_translation.setConstant(0);
  211. camera_base_translation.head(centroid.size()) = -centroid.cast<float>();
  212. camera_base_zoom = 2.0 / (max_point-min_point).array().abs().maxCoeff();
  213. }
  214. IGL_INLINE void
  215. igl::embree::EmbreeRenderer
  216. ::render_buffer(PixelMatrixType& R, PixelMatrixType&G, PixelMatrixType &B,PixelMatrixType &A)
  217. {
  218. assert(R.rows()==G.rows());assert(R.rows()==B.rows());assert(R.rows()==A.rows());
  219. assert(R.cols()==G.cols());assert(R.cols()==B.cols());assert(R.cols()==A.cols());
  220. Eigen::Vector4f viewport(0,0,R.rows(),R.cols());
  221. float width = R.rows();
  222. float height = R.cols();
  223. // update view matrix
  224. igl::look_at( camera_eye, camera_center, camera_up, view);
  225. view = view
  226. * (rot_matrix * Eigen::Scaling(camera_zoom * camera_base_zoom)
  227. * Eigen::Translation3f(camera_translation + camera_base_translation)).matrix();
  228. if (orthographic)
  229. {
  230. float length = (camera_eye - camera_center).norm();
  231. float h = tan(camera_view_angle/360.0 * igl::PI) * (length);
  232. igl::ortho(-h*width/height, h*width/height, -h, h, camera_dnear, camera_dfar, proj);
  233. } else {
  234. float fH = tan(camera_view_angle / 360.0 * igl::PI) * camera_dnear;
  235. float fW = fH * (double)width/(double)height;
  236. igl::frustum(-fW, fW, -fH, fH, camera_dnear, camera_dfar, proj);
  237. }
  238. // go over all pixels in the "view"
  239. for(int x=0;x<(int)width;++x)
  240. {
  241. for(int y=0;y<(int)height;++y)
  242. {
  243. Vec3f s,d,dir;
  244. igl::embree::EmbreeRenderer::Hit hit;
  245. // look into the screen
  246. Vec3f win_s(x,y,0);
  247. Vec3f win_d(x,y,1);
  248. // Source, destination and direction in world
  249. igl::unproject(win_s,this->view,this->proj,viewport,s);
  250. igl::unproject(win_d,this->view,this->proj,viewport,d);
  251. dir = d-s;
  252. dir.normalize();
  253. auto clamp=[](float x)->unsigned char {return (unsigned char)(x<0?0:x>1.0?255:x*255);};
  254. if(this->intersect_ray(s,dir,hit))
  255. {
  256. if ( dir.dot(hit.N) > 0.0f)
  257. {
  258. // TODO: interpolate normals ?
  259. hit.N.normalize();
  260. // cos between ray and face normal
  261. float face_proj=dir.dot(hit.N);
  262. Eigen::RowVector3f c;
  263. if(this->uniform_color)
  264. {
  265. // same color for the whole mesh
  266. c=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. }
  279. // give the same alpha to all points with something behind
  280. A(x,y)=255;
  281. } else {
  282. R(x,y)=0;
  283. G(x,y)=0;
  284. B(x,y)=0;
  285. A(x,y)=0;
  286. }
  287. }
  288. }
  289. }
  290. IGL_INLINE void
  291. igl::embree::EmbreeRenderer
  292. ::set_colors(const Eigen::MatrixXd & C)
  293. {
  294. if(C.rows()==V.rows()) // per vertex color
  295. {
  296. face_based = false;
  297. this->C = C.cast<float>();
  298. this->uniform_color=false;
  299. } else if (C.rows()==F.rows()) {
  300. face_based = true;
  301. this->C = C.cast<float>();
  302. this->uniform_color=false;
  303. } else if (C.rows()==1) {
  304. face_based = true;
  305. this->uC = C.cast<float>();
  306. this->uniform_color=true;
  307. }else {
  308. // don't know what to do
  309. this->uniform_color=true;
  310. assert(false); //?
  311. }
  312. }
  313. IGL_INLINE void
  314. igl::embree::EmbreeRenderer
  315. ::set_data(const Eigen::VectorXd & D, igl::ColorMapType cmap)
  316. {
  317. const double caxis_min = D.minCoeff();
  318. const double caxis_max = D.maxCoeff();
  319. return set_data(D,caxis_min,caxis_max,cmap);
  320. }
  321. IGL_INLINE void igl::embree::EmbreeRenderer::set_data(
  322. const Eigen::VectorXd & D,
  323. double caxis_min,
  324. double caxis_max,
  325. igl::ColorMapType cmap)
  326. {
  327. Eigen::MatrixXd C;
  328. igl::colormap(cmap,D,caxis_min,caxis_max,C);
  329. set_colors(C);
  330. }
  331. IGL_INLINE void
  332. igl::embree::EmbreeRenderer::set_rot(const Eigen::Matrix3d &r)
  333. {
  334. this->rot_matrix = r.cast<float>();
  335. }
  336. IGL_INLINE void
  337. igl::embree::EmbreeRenderer::set_zoom(double zoom)
  338. {
  339. this->camera_zoom=zoom;
  340. }
  341. IGL_INLINE void
  342. igl::embree::EmbreeRenderer::set_translation(const Eigen::Vector3d &tr)
  343. {
  344. this->camera_translation=tr.cast<float>();
  345. }
  346. IGL_INLINE void
  347. igl::embree::EmbreeRenderer::set_face_based(bool _f)
  348. {
  349. this->face_based=_f;
  350. }
  351. IGL_INLINE void
  352. igl::embree::EmbreeRenderer::set_orthographic(bool o)
  353. {
  354. this->orthographic=o;
  355. }
  356. #ifdef IGL_STATIC_LIBRARY
  357. #endif //IGL_STATIC_LIBRARY