writePLY.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  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 "writePLY.h"
  9. #include <vector>
  10. #include <igl/ply.h>
  11. #include <vector>
  12. namespace
  13. {
  14. template <typename Scalar> int ply_type();
  15. template <> int ply_type<char>(){ return PLY_CHAR; }
  16. template <> int ply_type<short>(){ return PLY_SHORT; }
  17. template <> int ply_type<int>(){ return PLY_INT; }
  18. template <> int ply_type<unsigned char>(){ return PLY_UCHAR; }
  19. template <> int ply_type<unsigned short>(){ return PLY_SHORT; }
  20. template <> int ply_type<unsigned int>(){ return PLY_UINT; }
  21. template <> int ply_type<float>(){ return PLY_FLOAT; }
  22. template <> int ply_type<double>(){ return PLY_DOUBLE; }
  23. }
  24. template <
  25. typename DerivedV,
  26. typename DerivedF,
  27. typename DerivedN,
  28. typename DerivedUV>
  29. IGL_INLINE bool igl::writePLY(
  30. const std::string & filename,
  31. const Eigen::MatrixBase<DerivedV> & V,
  32. const Eigen::MatrixBase<DerivedF> & F,
  33. const Eigen::MatrixBase<DerivedN> & N,
  34. const Eigen::MatrixBase<DerivedUV> & UV,
  35. const bool ascii)
  36. {
  37. // Largely based on obj2ply.c
  38. typedef typename DerivedV::Scalar VScalar;
  39. typedef typename DerivedN::Scalar NScalar;
  40. typedef typename DerivedUV::Scalar UVScalar;
  41. typedef typename DerivedF::Scalar FScalar;
  42. typedef struct Vertex
  43. {
  44. VScalar x,y,z,w; /* position */
  45. NScalar nx,ny,nz; /* surface normal */
  46. UVScalar s,t; /* texture coordinates */
  47. } Vertex;
  48. typedef struct Face
  49. {
  50. unsigned char nverts; /* number of vertex indices in list */
  51. FScalar *verts; /* vertex index list */
  52. } Face;
  53. igl::ply::PlyProperty vert_props[] =
  54. { /* list of property information for a vertex */
  55. {"x", ply_type<VScalar>(), ply_type<VScalar>(),offsetof(Vertex,x),0,0,0,0},
  56. {"y", ply_type<VScalar>(), ply_type<VScalar>(),offsetof(Vertex,y),0,0,0,0},
  57. {"z", ply_type<VScalar>(), ply_type<VScalar>(),offsetof(Vertex,z),0,0,0,0},
  58. {"nx",ply_type<NScalar>(), ply_type<NScalar>(),offsetof(Vertex,nx),0,0,0,0},
  59. {"ny",ply_type<NScalar>(), ply_type<NScalar>(),offsetof(Vertex,ny),0,0,0,0},
  60. {"nz",ply_type<NScalar>(), ply_type<NScalar>(),offsetof(Vertex,nz),0,0,0,0},
  61. {"s", ply_type<UVScalar>(),ply_type<UVScalar>(),offsetof(Vertex,s),0,0,0,0},
  62. {"t", ply_type<UVScalar>(),ply_type<UVScalar>(),offsetof(Vertex,t),0,0,0,0},
  63. };
  64. igl::ply::PlyProperty face_props[] =
  65. { /* list of property information for a face */
  66. {"vertex_indices", ply_type<FScalar>(), ply_type<FScalar>(),
  67. offsetof(Face,verts), 1, PLY_UCHAR, PLY_UCHAR, offsetof(Face,nverts)},
  68. };
  69. const bool has_normals = N.rows() > 0;
  70. const bool has_texture_coords = UV.rows() > 0;
  71. std::vector<Vertex> vlist(V.rows());
  72. std::vector<Face> flist(F.rows());
  73. for(size_t i = 0;i<(size_t)V.rows();i++)
  74. {
  75. vlist[i].x = V(i,0);
  76. vlist[i].y = V(i,1);
  77. vlist[i].z = V(i,2);
  78. if(has_normals)
  79. {
  80. vlist[i].nx = N(i,0);
  81. vlist[i].ny = N(i,1);
  82. vlist[i].nz = N(i,2);
  83. }
  84. if(has_texture_coords)
  85. {
  86. vlist[i].s = UV(i,0);
  87. vlist[i].t = UV(i,1);
  88. }
  89. }
  90. for(size_t i = 0;i<(size_t)F.rows();i++)
  91. {
  92. flist[i].nverts = F.cols();
  93. flist[i].verts = new FScalar[F.cols()];
  94. for(size_t c = 0;c<(size_t)F.cols();c++)
  95. {
  96. flist[i].verts[c] = F(i,c);
  97. }
  98. }
  99. const char * elem_names[] = {"vertex","face"};
  100. FILE * fp = fopen(filename.c_str(),"w");
  101. if(fp==NULL)
  102. {
  103. return false;
  104. }
  105. igl::ply::PlyFile * ply = igl::ply::ply_write(fp, 2,elem_names,
  106. (ascii ? PLY_ASCII : PLY_BINARY_LE));
  107. if(ply==NULL)
  108. {
  109. return false;
  110. }
  111. std::vector<igl::ply::PlyProperty> plist;
  112. plist.push_back(vert_props[0]);
  113. plist.push_back(vert_props[1]);
  114. plist.push_back(vert_props[2]);
  115. if (has_normals)
  116. {
  117. plist.push_back(vert_props[3]);
  118. plist.push_back(vert_props[4]);
  119. plist.push_back(vert_props[5]);
  120. }
  121. if (has_texture_coords)
  122. {
  123. plist.push_back(vert_props[6]);
  124. plist.push_back(vert_props[7]);
  125. }
  126. ply_describe_element(ply, "vertex", V.rows(),plist.size(),
  127. &plist[0]);
  128. ply_describe_element(ply, "face", F.rows(),1,&face_props[0]);
  129. ply_header_complete(ply);
  130. int native_binary_type = igl::ply::get_native_binary_type2();
  131. ply_put_element_setup(ply, "vertex");
  132. for(const auto v : vlist)
  133. {
  134. ply_put_element(ply, (void *) &v, &native_binary_type);
  135. }
  136. ply_put_element_setup(ply, "face");
  137. for(const auto f : flist)
  138. {
  139. ply_put_element(ply, (void *) &f, &native_binary_type);
  140. }
  141. ply_close(ply);
  142. for(size_t i = 0;i<(size_t)F.rows();i++)
  143. {
  144. delete[] flist[i].verts;
  145. }
  146. return true;
  147. }
  148. template <
  149. typename DerivedV,
  150. typename DerivedF>
  151. IGL_INLINE bool igl::writePLY(
  152. const std::string & filename,
  153. const Eigen::MatrixBase<DerivedV> & V,
  154. const Eigen::MatrixBase<DerivedF> & F,
  155. const bool ascii)
  156. {
  157. Eigen::Matrix<typename DerivedV::Scalar,Eigen::Dynamic,Eigen::Dynamic> N,UV;
  158. return writePLY(filename,V,F,N,UV,ascii);
  159. }
  160. #ifdef IGL_STATIC_LIBRARY
  161. // Explicit template instantiation
  162. // generated by autoexplicit.sh
  163. template bool igl::writePLY<Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 3, 1, -1, 3> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> > const&, bool);
  164. // generated by autoexplicit.sh
  165. template bool igl::writePLY<Eigen::Matrix<double, 8, 3, 0, 8, 3>, Eigen::Matrix<int, 12, 3, 0, 12, 3> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 8, 3, 0, 8, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, 12, 3, 0, 12, 3> > const&, bool);
  166. template bool igl::writePLY<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::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, bool);
  167. template bool igl::writePLY<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, bool);
  168. template bool igl::writePLY<Eigen::Matrix<double, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 3, 1, -1, 3> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 1, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> > const&, bool);
  169. #endif