readPLY.cpp 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2014 Alec Jacobson <alecjacobson@gmail.com>
  4. //
  5. // This Source Code Form is subject to the terms of the Mozilla Public License
  6. // v. 2.0. If a copy of the MPL was not distributed with this file, You can
  7. // obtain one at http://mozilla.org/MPL/2.0/.
  8. #include "readPLY.h"
  9. #include "list_to_matrix.h"
  10. #include "ply.h"
  11. #include <iostream>
  12. template <
  13. typename Vtype,
  14. typename Ftype,
  15. typename Ntype,
  16. typename UVtype>
  17. IGL_INLINE bool igl::readPLY(
  18. const std::string filename,
  19. std::vector<std::vector<Vtype> > & V,
  20. std::vector<std::vector<Ftype> > & F,
  21. std::vector<std::vector<Ntype> > & N,
  22. std::vector<std::vector<UVtype> > & UV)
  23. {
  24. using namespace std;
  25. // Largely follows ply2iv.c
  26. FILE * ply_file = fopen(filename.c_str(),"r");
  27. if(ply_file == NULL)
  28. {
  29. return false;
  30. }
  31. return readPLY(ply_file,V,F,N,UV);
  32. }
  33. template <
  34. typename Vtype,
  35. typename Ftype,
  36. typename Ntype,
  37. typename UVtype>
  38. IGL_INLINE bool igl::readPLY(
  39. FILE * ply_file,
  40. std::vector<std::vector<Vtype> > & V,
  41. std::vector<std::vector<Ftype> > & F,
  42. std::vector<std::vector<Ntype> > & N,
  43. std::vector<std::vector<UVtype> > & UV)
  44. {
  45. using namespace std;
  46. typedef struct Vertex {
  47. double x,y,z; /* position */
  48. double nx,ny,nz; /* surface normal */
  49. double s,t; /* texture coordinates */
  50. void *other_props; /* other properties */
  51. } Vertex;
  52. typedef struct Face {
  53. unsigned char nverts; /* number of vertex indices in list */
  54. int *verts; /* vertex index list */
  55. void *other_props; /* other properties */
  56. } Face;
  57. igl::ply::PlyProperty vert_props[] = { /* list of property information for a vertex */
  58. {"x", PLY_DOUBLE, PLY_DOUBLE, offsetof(Vertex,x), 0, 0, 0, 0},
  59. {"y", PLY_DOUBLE, PLY_DOUBLE, offsetof(Vertex,y), 0, 0, 0, 0},
  60. {"z", PLY_DOUBLE, PLY_DOUBLE, offsetof(Vertex,z), 0, 0, 0, 0},
  61. {"nx", PLY_DOUBLE, PLY_DOUBLE, offsetof(Vertex,nx), 0, 0, 0, 0},
  62. {"ny", PLY_DOUBLE, PLY_DOUBLE, offsetof(Vertex,ny), 0, 0, 0, 0},
  63. {"nz", PLY_DOUBLE, PLY_DOUBLE, offsetof(Vertex,nz), 0, 0, 0, 0},
  64. {"s", PLY_DOUBLE, PLY_DOUBLE, offsetof(Vertex,s), 0, 0, 0, 0},
  65. {"t", PLY_DOUBLE, PLY_DOUBLE, offsetof(Vertex,t), 0, 0, 0, 0},
  66. };
  67. igl::ply::PlyProperty face_props[] = { /* list of property information for a face */
  68. {"vertex_indices", PLY_INT, PLY_INT, offsetof(Face,verts),
  69. 1, PLY_UCHAR, PLY_UCHAR, offsetof(Face,nverts)},
  70. };
  71. int nelems;
  72. char ** elem_names;
  73. igl::ply::PlyFile * in_ply = igl::ply::ply_read(ply_file,&nelems,&elem_names);
  74. if(in_ply==NULL)
  75. {
  76. return false;
  77. }
  78. bool has_normals = false;
  79. bool has_texture_coords = false;
  80. igl::ply::PlyProperty **plist;
  81. int nprops;
  82. int elem_count;
  83. plist = ply_get_element_description (in_ply,"vertex", &elem_count, &nprops);
  84. int native_binary_type = igl::ply::get_native_binary_type2();
  85. if (plist != NULL)
  86. {
  87. /* set up for getting vertex elements */
  88. ply_get_property (in_ply,"vertex",&vert_props[0]);
  89. ply_get_property (in_ply,"vertex",&vert_props[1]);
  90. ply_get_property (in_ply,"vertex",&vert_props[2]);
  91. for (int j = 0; j < nprops; j++)
  92. {
  93. igl::ply::PlyProperty * prop = plist[j];
  94. if (igl::ply::equal_strings ("nx", prop->name)
  95. || igl::ply::equal_strings ("ny", prop->name)
  96. || igl::ply::equal_strings ("nz", prop->name))
  97. {
  98. ply_get_property (in_ply,"vertex",&vert_props[3]);
  99. ply_get_property (in_ply,"vertex",&vert_props[4]);
  100. ply_get_property (in_ply,"vertex",&vert_props[5]);
  101. has_normals = true;
  102. }
  103. if (igl::ply::equal_strings ("s", prop->name) ||
  104. igl::ply::equal_strings ("t", prop->name))
  105. {
  106. ply_get_property(in_ply,"vertex",&vert_props[6]);
  107. ply_get_property(in_ply,"vertex",&vert_props[7]);
  108. has_texture_coords = true;
  109. }
  110. }
  111. // Is this call necessary?
  112. ply_get_other_properties(in_ply,"vertex",
  113. offsetof(Vertex,other_props));
  114. V.resize(elem_count,std::vector<Vtype>(3));
  115. if(has_normals)
  116. {
  117. N.resize(elem_count,std::vector<Ntype>(3));
  118. }else
  119. {
  120. N.resize(0);
  121. }
  122. if(has_texture_coords)
  123. {
  124. UV.resize(elem_count,std::vector<UVtype>(2));
  125. }else
  126. {
  127. UV.resize(0);
  128. }
  129. for(int j = 0;j<elem_count;j++)
  130. {
  131. Vertex v;
  132. ply_get_element_setup(in_ply,"vertex",3,vert_props);
  133. ply_get_element(in_ply,(void*)&v, &native_binary_type);
  134. V[j][0] = v.x;
  135. V[j][1] = v.y;
  136. V[j][2] = v.z;
  137. if(has_normals)
  138. {
  139. N[j][0] = v.nx;
  140. N[j][1] = v.ny;
  141. N[j][2] = v.nz;
  142. }
  143. if(has_texture_coords)
  144. {
  145. UV[j][0] = v.s;
  146. UV[j][1] = v.t;
  147. }
  148. }
  149. }
  150. plist = ply_get_element_description (in_ply,"face", &elem_count, &nprops);
  151. if (plist != NULL)
  152. {
  153. F.resize(elem_count);
  154. ply_get_property(in_ply,"face",&face_props[0]);
  155. for (int j = 0; j < elem_count; j++)
  156. {
  157. Face f;
  158. ply_get_element(in_ply, (void *) &f, &native_binary_type);
  159. for(size_t c = 0;c<f.nverts;c++)
  160. {
  161. F[j].push_back(f.verts[c]);
  162. }
  163. }
  164. }
  165. ply_close(in_ply);
  166. return true;
  167. }
  168. template <
  169. typename DerivedV,
  170. typename DerivedF,
  171. typename DerivedN,
  172. typename DerivedUV>
  173. IGL_INLINE bool igl::readPLY(
  174. const std::string filename,
  175. Eigen::PlainObjectBase<DerivedV> & V,
  176. Eigen::PlainObjectBase<DerivedF> & F,
  177. Eigen::PlainObjectBase<DerivedN> & N,
  178. Eigen::PlainObjectBase<DerivedUV> & UV)
  179. {
  180. std::vector<std::vector<typename DerivedV::Scalar> > vV;
  181. std::vector<std::vector<typename DerivedF::Scalar> > vF;
  182. std::vector<std::vector<typename DerivedN::Scalar> > vN;
  183. std::vector<std::vector<typename DerivedUV::Scalar> > vUV;
  184. if(!readPLY(filename,vV,vF,vN,vUV))
  185. {
  186. return false;
  187. }
  188. return
  189. list_to_matrix(vV,V) &&
  190. list_to_matrix(vF,F) &&
  191. list_to_matrix(vN,N) &&
  192. list_to_matrix(vUV,UV);
  193. }
  194. template <
  195. typename DerivedV,
  196. typename DerivedF>
  197. IGL_INLINE bool igl::readPLY(
  198. const std::string filename,
  199. Eigen::PlainObjectBase<DerivedV> & V,
  200. Eigen::PlainObjectBase<DerivedF> & F)
  201. {
  202. Eigen::MatrixXd N,UV;
  203. return readPLY(filename,V,F,N,UV);
  204. }
  205. #ifdef IGL_STATIC_LIBRARY
  206. // Explicit template instantiation
  207. template bool igl::readPLY<double, int, double, double>(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > >&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&, std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > >&, std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > >&);
  208. template bool igl::readPLY<Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic>, Eigen::Matrix<int, Eigen::Dynamic, Eigen::Dynamic>, Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic>, Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, Eigen::PlainObjectBase<Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> > &, Eigen::PlainObjectBase<Eigen::Matrix<int, Eigen::Dynamic, Eigen::Dynamic> > &, Eigen::PlainObjectBase<Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> > &, Eigen::PlainObjectBase<Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> > &);
  209. template bool igl::readPLY<Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic>, Eigen::Matrix<int, Eigen::Dynamic, Eigen::Dynamic> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, Eigen::PlainObjectBase<Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> > &, Eigen::PlainObjectBase<Eigen::Matrix<int, Eigen::Dynamic, Eigen::Dynamic> > &);
  210. template bool igl::readPLY<Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 3, 1, -1, 3> >(std::string, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> >&);
  211. #endif