writePLY.cpp 3.8 KB

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