writePLY.cpp 4.8 KB

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