writePLY.cpp 5.2 KB

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