readPLY.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647
  1. #include "readPLY.h"
  2. #include <string>
  3. #include <set>
  4. #include <fstream>
  5. #include <iostream>
  6. #include <cstdint>
  7. #include <Eigen/Core>
  8. #include "tinyply.h"
  9. #include "read_file_binary.h"
  10. #include "FileMemoryStream.h"
  11. namespace igl
  12. {
  13. template <typename T, typename Derived>
  14. IGL_INLINE bool _tinyply_buffer_to_matrix(
  15. tinyply::PlyData & D,
  16. Eigen::PlainObjectBase<Derived> & M,
  17. size_t rows,
  18. size_t cols )
  19. {
  20. Eigen::Map< Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> >
  21. _map( reinterpret_cast<T *>( D.buffer.get()), rows, cols );
  22. M = _map.template cast<typename Derived::Scalar>();
  23. return true;
  24. }
  25. template <typename Derived>
  26. IGL_INLINE bool tinyply_buffer_to_matrix(
  27. tinyply::PlyData & D,
  28. Eigen::PlainObjectBase<Derived> & M,
  29. size_t rows,
  30. size_t cols )
  31. {
  32. switch(D.t)
  33. {
  34. case tinyply::Type::INT8 :
  35. return _tinyply_buffer_to_matrix<std::int8_t,Derived>(D, M,rows,cols);
  36. case tinyply::Type::UINT8 :
  37. return _tinyply_buffer_to_matrix<std::uint8_t,Derived>(D, M,rows,cols);
  38. case tinyply::Type::INT16 :
  39. return _tinyply_buffer_to_matrix<std::int16_t,Derived>(D, M,rows,cols);
  40. case tinyply::Type::UINT16 :
  41. return _tinyply_buffer_to_matrix<std::uint16_t,Derived>(D, M,rows,cols);
  42. case tinyply::Type::INT32 :
  43. return _tinyply_buffer_to_matrix<std::int32_t,Derived>(D, M,rows,cols);
  44. case tinyply::Type::UINT32 :
  45. return _tinyply_buffer_to_matrix<std::uint32_t,Derived>(D, M,rows,cols);
  46. case tinyply::Type::FLOAT32 :
  47. return _tinyply_buffer_to_matrix<float,Derived>(D, M,rows,cols);
  48. case tinyply::Type::FLOAT64 :
  49. return _tinyply_buffer_to_matrix<double,Derived>(D, M,rows,cols);
  50. default:
  51. return false;
  52. }
  53. }
  54. template <typename T, typename Derived>
  55. IGL_INLINE bool _tinyply_tristrips_to_trifaces(
  56. tinyply::PlyData & D,
  57. Eigen::PlainObjectBase<Derived> & M,
  58. size_t el,
  59. size_t el_len )
  60. {
  61. Eigen::Map< Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> >
  62. _map( reinterpret_cast<T *>( D.buffer.get()), el, el_len );
  63. // to make it more interesting, triangles in triangle strip can be separated by negative index elements
  64. // 1. count all triangles
  65. size_t triangles=0;
  66. // TODO: it's possible to optimize this , i suppose
  67. for(size_t i=0; i<el; i++)
  68. for(size_t j=0; j<(el_len-2); j++)
  69. {
  70. if(_map(i,j)>=0 && _map(i,j+1)>=0 && _map(i,j+2)>=0)
  71. triangles++;
  72. }
  73. // 2. convert triangles to faces, skipping over the negative indeces, indicating separate strips
  74. M.resize(triangles, 3);
  75. size_t k=0;
  76. for(size_t i=0; i<el; i++)
  77. {
  78. int flip=0;
  79. for(size_t j=0; j<(el_len-2); j++)
  80. {
  81. if(_map(i,j)>=0 && _map(i,j+1)>=0 && _map(i,j+2)>=0)
  82. {
  83. // consequtive faces on the same strip have to be flip-flopped, to preserve orientation
  84. M( k,0 ) = static_cast<typename Derived::Scalar>( _map(i, j ) );
  85. M( k,1 ) = static_cast<typename Derived::Scalar>( _map(i, j+1+flip ) );
  86. M( k,2 ) = static_cast<typename Derived::Scalar>( _map(i, j+1+(flip^1) ) );
  87. k++;
  88. flip ^= 1;
  89. } else {
  90. // reset flip on new strip start
  91. flip = 0;
  92. }
  93. }
  94. }
  95. assert(k==triangles);
  96. return true;
  97. }
  98. template <typename Derived>
  99. IGL_INLINE bool tinyply_tristrips_to_faces(
  100. tinyply::PlyData & D,
  101. Eigen::PlainObjectBase<Derived> & M,
  102. size_t el,
  103. size_t el_len )
  104. {
  105. switch(D.t)
  106. {
  107. case tinyply::Type::INT8 :
  108. return _tinyply_tristrips_to_trifaces<std::int8_t,Derived>(D, M,el,el_len);
  109. case tinyply::Type::UINT8 :
  110. return _tinyply_tristrips_to_trifaces<std::uint8_t,Derived>(D, M,el,el_len);
  111. case tinyply::Type::INT16 :
  112. return _tinyply_tristrips_to_trifaces<std::int16_t,Derived>(D, M,el,el_len);
  113. case tinyply::Type::UINT16 :
  114. return _tinyply_tristrips_to_trifaces<std::uint16_t,Derived>(D, M,el,el_len);
  115. case tinyply::Type::INT32 :
  116. return _tinyply_tristrips_to_trifaces<std::int32_t,Derived>(D, M,el,el_len);
  117. case tinyply::Type::UINT32 :
  118. return _tinyply_tristrips_to_trifaces<std::uint32_t,Derived>(D, M,el,el_len);
  119. case tinyply::Type::FLOAT32 :
  120. return _tinyply_tristrips_to_trifaces<float,Derived>(D, M,el,el_len);
  121. case tinyply::Type::FLOAT64 :
  122. return _tinyply_tristrips_to_trifaces<double,Derived>(D, M,el,el_len);
  123. default:
  124. return false;
  125. }
  126. }
  127. template <
  128. typename DerivedV,
  129. typename DerivedF,
  130. typename DerivedE,
  131. typename DerivedN,
  132. typename DerivedUV,
  133. typename DerivedVD,
  134. typename DerivedFD,
  135. typename DerivedED
  136. >
  137. IGL_INLINE bool readPLY(
  138. FILE *fp,
  139. Eigen::PlainObjectBase<DerivedV> & V,
  140. Eigen::PlainObjectBase<DerivedF> & F,
  141. Eigen::PlainObjectBase<DerivedE> & E,
  142. Eigen::PlainObjectBase<DerivedN> & N,
  143. Eigen::PlainObjectBase<DerivedUV> & UV,
  144. Eigen::PlainObjectBase<DerivedVD> & VD,
  145. std::vector<std::string> & Vheader,
  146. Eigen::PlainObjectBase<DerivedFD> & FD,
  147. std::vector<std::string> & Fheader,
  148. Eigen::PlainObjectBase<DerivedED> & ED,
  149. std::vector<std::string> & Eheader,
  150. std::vector<std::string> & comments
  151. )
  152. {
  153. // buffer the whole file in memory
  154. // then read from memory buffer
  155. try
  156. {
  157. std::vector<std::uint8_t> fileBufferBytes;
  158. // read_file_binary will call fclose
  159. read_file_binary(fp,fileBufferBytes);
  160. FileMemoryStream stream((char*)fileBufferBytes.data(), fileBufferBytes.size());
  161. return readPLY(stream,V,F,E,N,UV,VD,Vheader,FD,Fheader,ED,Eheader,comments);
  162. }
  163. catch(const std::exception& e)
  164. {
  165. std::cerr << "ReadPLY error: " << e.what() << std::endl;
  166. }
  167. fclose(fp);
  168. return false;
  169. }
  170. template <
  171. typename DerivedV,
  172. typename DerivedF
  173. >
  174. IGL_INLINE bool readPLY(
  175. FILE *fp,
  176. Eigen::PlainObjectBase<DerivedV> & V,
  177. Eigen::PlainObjectBase<DerivedF> & F
  178. )
  179. {
  180. Eigen::MatrixXd N,UV,VD,FD,ED;
  181. Eigen::MatrixXi E;
  182. std::vector<std::string> Vheader,Eheader,Fheader,comments;
  183. return readPLY(fp,V,F,E,N,UV,VD,Vheader,FD,Fheader,ED,Eheader,comments);
  184. }
  185. template <
  186. typename DerivedV,
  187. typename DerivedF,
  188. typename DerivedE
  189. >
  190. IGL_INLINE bool readPLY(
  191. FILE *fp,
  192. Eigen::PlainObjectBase<DerivedV> & V,
  193. Eigen::PlainObjectBase<DerivedF> & F,
  194. Eigen::PlainObjectBase<DerivedE> & E
  195. )
  196. {
  197. Eigen::MatrixXd N,UV,VD,FD,ED;
  198. std::vector<std::string> Vheader,Eheader,Fheader,comments;
  199. return readPLY(fp,V,F,E,N,UV,VD,Vheader,FD,Fheader,ED,Eheader,comments);
  200. }
  201. template <
  202. typename DerivedV,
  203. typename DerivedF,
  204. typename DerivedE,
  205. typename DerivedN,
  206. typename DerivedUV,
  207. typename DerivedVD,
  208. typename DerivedFD,
  209. typename DerivedED
  210. >
  211. IGL_INLINE bool readPLY(
  212. std::istream & ply_stream,
  213. Eigen::PlainObjectBase<DerivedV> & V,
  214. Eigen::PlainObjectBase<DerivedF> & F,
  215. Eigen::PlainObjectBase<DerivedE> & E,
  216. Eigen::PlainObjectBase<DerivedN> & N,
  217. Eigen::PlainObjectBase<DerivedUV> & UV,
  218. Eigen::PlainObjectBase<DerivedVD> & VD,
  219. std::vector<std::string> & Vheader,
  220. Eigen::PlainObjectBase<DerivedFD> & FD,
  221. std::vector<std::string> & Fheader,
  222. Eigen::PlainObjectBase<DerivedED> & ED,
  223. std::vector<std::string> & Eheader,
  224. std::vector<std::string> & comments
  225. )
  226. {
  227. tinyply::PlyFile file;
  228. file.parse_header(ply_stream);
  229. std::set<std::string> vertex_std{ "x","y","z", "nx","ny","nz", "u","v", "texture_u", "texture_v", "s", "t"};
  230. std::set<std::string> face_std { "vertex_index", "vertex_indices"};
  231. std::set<std::string> edge_std { "vertex1", "vertex2"}; //non-standard edge indexes
  232. // Tinyply treats parsed data as untyped byte buffers.
  233. std::shared_ptr<tinyply::PlyData> vertices, normals, faces, texcoords, edges;
  234. // Some ply files contain tristrips instead of faces
  235. std::shared_ptr<tinyply::PlyData> tristrips;
  236. std::shared_ptr<tinyply::PlyData> _vertex_data;
  237. std::vector<std::string> _vertex_header;
  238. std::shared_ptr<tinyply::PlyData> _face_data;
  239. std::vector<std::string> _face_header;
  240. std::shared_ptr<tinyply::PlyData> _edge_data;
  241. std::vector<std::string> _edge_header;
  242. for (auto c : file.get_comments())
  243. comments.push_back(c);
  244. for (auto e : file.get_elements())
  245. {
  246. if(e.name == "vertex" ) // found a vertex
  247. {
  248. for (auto p : e.properties)
  249. {
  250. if(vertex_std.find(p.name) == vertex_std.end())
  251. {
  252. _vertex_header.push_back(p.name);
  253. }
  254. }
  255. }
  256. else if(e.name == "face" ) // found face
  257. {
  258. for (auto p : e.properties)
  259. {
  260. if(face_std.find(p.name) == face_std.end())
  261. {
  262. _face_header.push_back(p.name);
  263. }
  264. }
  265. }
  266. else if(e.name == "edge" ) // found edge
  267. {
  268. for (auto p : e.properties)
  269. {
  270. if(edge_std.find(p.name) == edge_std.end())
  271. {
  272. _edge_header.push_back(p.name);
  273. }
  274. }
  275. }
  276. // skip the unknown entries
  277. }
  278. // The header information can be used to programmatically extract properties on elements
  279. // known to exist in the header prior to reading the data. For brevity of this sample, properties
  280. // like vertex position are hard-coded:
  281. try {
  282. vertices = file.request_properties_from_element("vertex", { "x", "y", "z" });
  283. }
  284. catch (const std::exception & ) { }
  285. try {
  286. normals = file.request_properties_from_element("vertex", { "nx", "ny", "nz" });
  287. }
  288. catch (const std::exception & ) { }
  289. //Try texture coordinates with several names
  290. try {
  291. //texture_u texture_v are the names used by meshlab to store textures
  292. texcoords = file.request_properties_from_element("vertex", { "texture_u", "texture_v" });
  293. }
  294. catch (const std::exception & ) { }
  295. if (!texcoords)
  296. {
  297. try {
  298. //u v are the naive names
  299. texcoords = file.request_properties_from_element("vertex", { "u", "v" });
  300. }
  301. catch (const std::exception & ) { }
  302. }
  303. if (!texcoords)
  304. {
  305. try {
  306. //s t were the names used by blender and the previous libigl PLY reader.
  307. texcoords = file.request_properties_from_element("vertex", { "s", "t" });
  308. }
  309. catch (const std::exception & ) { }
  310. }
  311. // Providing a list size hint (the last argument) is a 2x performance improvement. If you have
  312. // arbitrary ply files, it is best to leave this 0.
  313. try {
  314. faces = file.request_properties_from_element( "face", { "vertex_indices" }, 0);
  315. }
  316. catch (const std::exception & ) { }
  317. if (!faces)
  318. {
  319. try {
  320. // alternative name of the elements
  321. faces = file.request_properties_from_element( "face", { "vertex_index" },0);
  322. }
  323. catch (const std::exception & ) { }
  324. }
  325. if (!faces)
  326. {
  327. try {
  328. // try using tristrips
  329. tristrips = file.request_properties_from_element( "tristrips", { "vertex_indices" }, 0);
  330. }
  331. catch (const std::exception & ) { }
  332. if (!tristrips)
  333. {
  334. try {
  335. // alternative name of the elements
  336. tristrips = file.request_properties_from_element( "tristrips", { "vertex_index" }, 0);
  337. }
  338. catch (const std::exception & ) { }
  339. }
  340. }
  341. try {
  342. edges = file.request_properties_from_element("edge", { "vertex1", "vertex2" });
  343. }
  344. catch (const std::exception & ) { }
  345. if(! _vertex_header.empty())
  346. _vertex_data = file.request_properties_from_element( "vertex", _vertex_header);
  347. if(! _face_header.empty())
  348. _face_data = file.request_properties_from_element( "face", _face_header);
  349. if(! _edge_header.empty())
  350. _edge_data = file.request_properties_from_element( "edge", _edge_header);
  351. // Parse the geometry data
  352. file.read(ply_stream);
  353. if (!vertices || !tinyply_buffer_to_matrix(*vertices,V,vertices->count,3) ) {
  354. // Don't do this because V might have non-trivial compile-time size V.resize(0,0);
  355. }
  356. if (!normals || !tinyply_buffer_to_matrix(*normals,N,normals->count,3) ) {
  357. // Don't do this (see above) N.resize(0,0);
  358. }
  359. if (!texcoords || !tinyply_buffer_to_matrix(*texcoords,UV,texcoords->count,2) ) {
  360. // Don't do this (see above) UV.resize(0,0);
  361. }
  362. //HACK: Unfortunately, tinyply doesn't store list size as a separate variable
  363. if (!faces || !tinyply_buffer_to_matrix(*faces, F, faces->count, faces->count==0?0:faces->buffer.size_bytes()/(tinyply::PropertyTable[faces->t].stride*faces->count) )) {
  364. if(tristrips) { // need to convert to faces
  365. // code based on blender importer for ply
  366. // converting triangle strips into triangles
  367. // tinyply supports tristrips of the same length only
  368. size_t el_count = tristrips->buffer.size_bytes()/(tinyply::PropertyTable[tristrips->t].stride*tristrips->count);
  369. // all strips should have tristrips->count elements
  370. if(!tinyply_tristrips_to_faces(*tristrips, F , tristrips->count, el_count))
  371. {
  372. // Don't do this (see above) F.resize(0,0);
  373. }
  374. } else {
  375. // Don't do this (see above) F.resize(0,0);
  376. }
  377. }
  378. if(!edges || !tinyply_buffer_to_matrix(*edges,E, edges->count,2)) {
  379. // Don't do this (see above) E.resize(0,0);
  380. }
  381. /// convert vertex data:
  382. Vheader=_vertex_header;
  383. if(_vertex_header.empty())
  384. {
  385. // Don't do this (see above) VD.resize(0,0);
  386. }
  387. else
  388. {
  389. VD.resize(vertices->count,_vertex_header.size());
  390. tinyply_buffer_to_matrix(*_vertex_data, VD, vertices->count, _vertex_header.size());
  391. }
  392. /// convert face data:
  393. Fheader=_face_header;
  394. if(_face_header.empty())
  395. {
  396. // Don't do this (see above) FD.resize(0,0);
  397. }
  398. else
  399. {
  400. FD.resize(faces->count, _face_header.size());
  401. tinyply_buffer_to_matrix(*_face_data, FD, faces->count, _face_header.size());
  402. }
  403. /// convert edge data:
  404. Eheader=_edge_header;
  405. if(_edge_header.empty())
  406. {
  407. // Don't do this (see above) ED.resize(0,0);
  408. }
  409. else
  410. {
  411. ED.resize(_edge_data->count, _edge_header.size());
  412. tinyply_buffer_to_matrix(*_edge_data, ED, _edge_data->count, _edge_header.size());
  413. }
  414. return true;
  415. }
  416. template <
  417. typename DerivedV,
  418. typename DerivedF,
  419. typename DerivedE,
  420. typename DerivedN,
  421. typename DerivedUV,
  422. typename DerivedVD,
  423. typename DerivedFD,
  424. typename DerivedED
  425. >
  426. IGL_INLINE bool readPLY(
  427. const std::string& ply_file,
  428. Eigen::PlainObjectBase<DerivedV> & V,
  429. Eigen::PlainObjectBase<DerivedF> & F,
  430. Eigen::PlainObjectBase<DerivedE> & E,
  431. Eigen::PlainObjectBase<DerivedN> & N,
  432. Eigen::PlainObjectBase<DerivedUV> & UV,
  433. Eigen::PlainObjectBase<DerivedVD> & VD,
  434. std::vector<std::string> & VDheader,
  435. Eigen::PlainObjectBase<DerivedFD> & FD,
  436. std::vector<std::string> & FDheader,
  437. Eigen::PlainObjectBase<DerivedED> & ED,
  438. std::vector<std::string> & EDheader,
  439. std::vector<std::string> & comments
  440. )
  441. {
  442. std::ifstream ply_stream(ply_file, std::ios::binary);
  443. if (ply_stream.fail())
  444. {
  445. std::cerr << "ReadPLY: Error opening file " << ply_file << std::endl;
  446. return false;
  447. }
  448. try
  449. {
  450. return readPLY(ply_stream, V, F, E, N, UV, VD, VDheader, FD,FDheader, ED, EDheader, comments );
  451. } catch (const std::exception& e) {
  452. std::cerr << "ReadPLY error: " << ply_file << e.what() << std::endl;
  453. }
  454. return false;
  455. }
  456. template <
  457. typename DerivedV,
  458. typename DerivedF,
  459. typename DerivedE,
  460. typename DerivedN,
  461. typename DerivedUV,
  462. typename DerivedD
  463. >
  464. IGL_INLINE bool readPLY(
  465. const std::string & filename,
  466. Eigen::PlainObjectBase<DerivedV> & V,
  467. Eigen::PlainObjectBase<DerivedF> & F,
  468. Eigen::PlainObjectBase<DerivedE> & E,
  469. Eigen::PlainObjectBase<DerivedN> & N,
  470. Eigen::PlainObjectBase<DerivedUV> & UV,
  471. Eigen::PlainObjectBase<DerivedD> & VD,
  472. std::vector<std::string> & Vheader
  473. )
  474. {
  475. Eigen::MatrixXd FD,ED;
  476. std::vector<std::string> Fheader,Eheader;
  477. std::vector<std::string> comments;
  478. return readPLY(filename,V,F,E,N,UV,VD,Vheader,FD,Fheader,ED,Eheader,comments);
  479. }
  480. template <
  481. typename DerivedV,
  482. typename DerivedF,
  483. typename DerivedE,
  484. typename DerivedN,
  485. typename DerivedUV
  486. >
  487. IGL_INLINE bool readPLY(
  488. const std::string & filename,
  489. Eigen::PlainObjectBase<DerivedV> & V,
  490. Eigen::PlainObjectBase<DerivedF> & F,
  491. Eigen::PlainObjectBase<DerivedE> & E,
  492. Eigen::PlainObjectBase<DerivedN> & N,
  493. Eigen::PlainObjectBase<DerivedUV> & UV
  494. )
  495. {
  496. Eigen::MatrixXd VD,FD,ED;
  497. std::vector<std::string> Vheader,Fheader,Eheader;
  498. std::vector<std::string> comments;
  499. return readPLY(filename,V,F,E, N,UV,VD,Vheader,FD,Fheader,ED,Eheader,comments);
  500. }
  501. template <
  502. typename DerivedV,
  503. typename DerivedF,
  504. typename DerivedN,
  505. typename DerivedUV
  506. >
  507. IGL_INLINE bool readPLY(
  508. const std::string & filename,
  509. Eigen::PlainObjectBase<DerivedV> & V,
  510. Eigen::PlainObjectBase<DerivedF> & F,
  511. Eigen::PlainObjectBase<DerivedN> & N,
  512. Eigen::PlainObjectBase<DerivedUV> & UV
  513. )
  514. {
  515. Eigen::MatrixXd VD,FD,ED;
  516. Eigen::MatrixXi E;
  517. std::vector<std::string> Vheader,Fheader,Eheader;
  518. std::vector<std::string> comments;
  519. return readPLY(filename,V,F,E, N,UV,VD,Vheader,FD,Fheader,ED,Eheader,comments);
  520. }
  521. template <
  522. typename DerivedV,
  523. typename DerivedF
  524. >
  525. IGL_INLINE bool readPLY(
  526. const std::string & filename,
  527. Eigen::PlainObjectBase<DerivedV> & V,
  528. Eigen::PlainObjectBase<DerivedF> & F
  529. )
  530. {
  531. Eigen::MatrixXd N,UV;
  532. Eigen::MatrixXd VD,FD,ED;
  533. Eigen::MatrixXi E;
  534. std::vector<std::string> Vheader,Fheader,Eheader;
  535. std::vector<std::string> comments;
  536. return readPLY(filename,V,F,E,N,UV,VD,Vheader,FD,Fheader,ED,Eheader,comments);
  537. }
  538. template <
  539. typename DerivedV,
  540. typename DerivedF,
  541. typename DerivedE
  542. >
  543. IGL_INLINE bool readPLY(
  544. const std::string & filename,
  545. Eigen::PlainObjectBase<DerivedV> & V,
  546. Eigen::PlainObjectBase<DerivedF> & F,
  547. Eigen::PlainObjectBase<DerivedE> & E
  548. )
  549. {
  550. Eigen::MatrixXd N,UV;
  551. Eigen::MatrixXd VD,FD,ED;
  552. std::vector<std::string> Vheader,Fheader,Eheader;
  553. std::vector<std::string> comments;
  554. return readPLY(filename,V,F,E,N,UV,VD,Vheader,FD,Fheader,ED,Eheader,comments);
  555. }
  556. } //igl namespace
  557. #ifdef IGL_STATIC_LIBRARY
  558. // Explicit template instantiation
  559. // generated by autoexplicit.sh
  560. template bool igl::readPLY<Eigen::Matrix<double, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(FILE*, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 1, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
  561. template bool igl::readPLY<Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(FILE*, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
  562. template bool igl::readPLY<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(FILE*, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);
  563. template bool igl::readPLY<Eigen::Matrix<double, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 3, 1, -1, 3> >(FILE*, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 1, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> >&);
  564. template bool igl::readPLY<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(FILE*, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
  565. template bool igl::readPLY<Eigen::Matrix<double, -1, -1, 1, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(FILE*, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 1, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
  566. template bool igl::readPLY<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
  567. template bool igl::readPLY<Eigen::Matrix<float, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(FILE*, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);
  568. template bool igl::readPLY<Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3> >(FILE*, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3> >&);
  569. template bool igl::readPLY<Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 3, 1, -1, 3> >(FILE*, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> >&);
  570. template bool igl::readPLY<Eigen::Matrix<float, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(FILE*, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
  571. template bool igl::readPLY<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&, std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&);
  572. template bool igl::readPLY<Eigen::Matrix<float, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<float, -1, -1, 0, -1, -1>, Eigen::Matrix<float, -1, -1, 0, -1, -1>, Eigen::Matrix<float, -1, -1, 0, -1, -1>, Eigen::Matrix<float, -1, -1, 0, -1, -1>, Eigen::Matrix<float, -1, -1, 0, -1, -1> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> >&, std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> >&, std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> >&, std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&, std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&);
  573. #endif