浏览代码

ply support

Former-commit-id: 4d682d4b01bd94bf4c34a46011054e16e588585f
Alec Jacobson 10 年之前
父节点
当前提交
2d6867fe82

+ 1 - 0
RELEASE_HISTORY.txt

@@ -1,3 +1,4 @@
+1.1.1  PLY file format support
 1.1.0  Mesh boolean operations using CGAL and cork, implementing [Attene 14]
 1.0.3  Bone heat method
 1.0.2  Bug fix in winding number code

+ 1 - 1
VERSION.txt

@@ -3,4 +3,4 @@
 # Anyone may increment Minor to indicate a small change.
 # Major indicates a large change or large number of changes (upload to website)
 # World indicates a substantial change or release
-1.1.0
+1.1.1

+ 24 - 1
examples/quicklook-mesh/Info.plist

@@ -13,8 +13,9 @@
 			<array>
 				<string>org.mesh</string>
 				<string>org.obj</string>
-				<string>org.stl</string>
 				<string>org.off</string>
+				<string>org.ply</string>
+				<string>org.stl</string>
 				<string>org.wrl</string>
 			</array>
 		</dict>
@@ -84,6 +85,7 @@
 				</array>
 			</dict>
 		</dict>
+
 		<dict>
 			<key>UTTypeConformsTo</key>
 			<array>
@@ -103,6 +105,27 @@
 				</array>
 			</dict>
 		</dict>
+
+		<dict>
+			<key>UTTypeConformsTo</key>
+			<array>
+				<string>public.image</string>
+			</array>
+			<key>UTTypeDescription</key>
+			<string>PLY 3D file</string>
+			<key>UTTypeIdentifier</key>
+			<string>org.ply</string>
+			<key>UTTypeReferenceURL</key>
+			<string>http://en.wikipedia.org/wiki/PLY_%28file_format%29</string>
+			<key>UTTypeTagSpecification</key>
+			<dict>
+				<key>public.filename-extension</key>
+				<array>
+					<string>ply</string>
+				</array>
+			</dict>
+		</dict>
+
 		<dict>
 			<key>UTTypeConformsTo</key>
 			<array>

+ 9 - 3
examples/quicklook-mesh/src/render_to_buffer.cpp

@@ -2,9 +2,6 @@
 extern "C" {
 #include "render_to_buffer.h"
 };
-// We're probably didn't build libigl.a with LLVM so just use the headers only
-// version.
-#define IGL_HEADER_ONLY
 #include <igl/per_face_normals.h>
 #include <igl/normalize_row_lengths.h>
 #include <igl/get_seconds.h>
@@ -13,6 +10,7 @@ extern "C" {
 #include <igl/material_colors.h>
 #include <igl/pathinfo.h>
 #include <igl/readOBJ.h>
+#include <igl/readPLY.h>
 #include <igl/readSTL.h>
 #include <igl/readWRL.h>
 #include <igl/polygon_mesh_to_triangle_mesh.h>
@@ -376,6 +374,14 @@ bool render_to_buffer(
       red(width,height,buffer);
       return false;
     }
+  }else if(ext == "ply")
+  {
+    // Convert extension to lower case
+    if(!igl::readPLY(filename,vV,vF,vN,vTC))
+    {
+      red(width,height,buffer);
+      return false;
+    }
   }else if(ext == "stl")
   {
     // Convert extension to lower case

+ 6 - 1
file-formats/index.html

@@ -27,7 +27,12 @@
     href=http://www.cs.berkeley.edu/~jrs/stellar/#fileformats>Stellar</a>.
     </li>
     <li><a href="http://tetgen.berlios.de/fformats.off.html">.off</a> Geomview's polyhedral file format</li>
-    <li><a href="http://en.wikipedia.org/wiki/Wavefront_.obj_file#File_format">.obj</a> Wavefront object file format. Usually unsafe to assume anything more than vertex positions and triangle indices are supported</li>
+    <li><a
+    href="http://en.wikipedia.org/wiki/Wavefront_.obj_file#File_format">.obj</a>
+    Wavefront object file format. Usually unsafe to assume anything more than
+    vertex positions and triangle indices are supported</li>
+    <li><a href=http://en.wikipedia.org/wiki/PLY_%28file_format%29>.ply</a>
+    Polygon File Format, supporting ASCII and binary encoding</li>
     <li><a
     href=https://en.wikipedia.org/wiki/Portable_Network_Graphics>.png</a>
     Portable Network Graphics image file. IGLLIB (in the libiglpng extra)

+ 1 - 1
include/igl/cotmatrix.h

@@ -1,6 +1,6 @@
 // This file is part of libigl, a simple c++ geometry processing library.
 // 
-// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
+// Copyright (C) 2014 Alec Jacobson <alecjacobson@gmail.com>
 // 
 // This Source Code Form is subject to the terms of the Mozilla Public License 
 // v. 2.0. If a copy of the MPL was not distributed with this file, You can 

+ 1 - 0
include/igl/ply.h.REMOVED.git-id

@@ -0,0 +1 @@
+05e282fe767ea0bd8987f68ae4b79d0ab4c26a09

+ 190 - 0
include/igl/readPLY.cpp

@@ -0,0 +1,190 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+//
+// Copyright (C) 2014 Alec Jacobson <alecjacobson@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+#include "readPLY.h"
+#include "list_to_matrix.h"
+#include "ply.h"
+#include <iostream>
+
+template <
+  typename Vtype,
+  typename Ftype,
+  typename Ntype,
+  typename UVtype>
+IGL_INLINE bool igl::readPLY(
+  const std::string & filename,
+  std::vector<std::vector<Vtype> > & V,
+  std::vector<std::vector<Ftype> > & F,
+  std::vector<std::vector<Ntype> > & N,
+  std::vector<std::vector<UVtype> >  & UV)
+{
+  using namespace std;
+  // Largely follows ply2iv.c
+  PlyOtherProp *vert_other,*face_other;
+
+   typedef struct Vertex {
+     double x,y,z;          /* position */
+     double nx,ny,nz;         /* surface normal */
+     double s,t;              /* texture coordinates */
+     void *other_props;       /* other properties */
+   } Vertex;
+
+   typedef struct Face {
+     unsigned char nverts;    /* number of vertex indices in list */
+     int *verts;              /* vertex index list */
+     void *other_props;       /* other properties */
+   } Face;
+
+  PlyProperty vert_props[] = { /* list of property information for a vertex */
+    {"x", PLY_DOUBLE, PLY_DOUBLE, offsetof(Vertex,x), 0, 0, 0, 0},
+    {"y", PLY_DOUBLE, PLY_DOUBLE, offsetof(Vertex,y), 0, 0, 0, 0},
+    {"z", PLY_DOUBLE, PLY_DOUBLE, offsetof(Vertex,z), 0, 0, 0, 0},
+    {"nx", PLY_DOUBLE, PLY_DOUBLE, offsetof(Vertex,nx), 0, 0, 0, 0},
+    {"ny", PLY_DOUBLE, PLY_DOUBLE, offsetof(Vertex,ny), 0, 0, 0, 0},
+    {"nz", PLY_DOUBLE, PLY_DOUBLE, offsetof(Vertex,nz), 0, 0, 0, 0},
+    {"s", PLY_DOUBLE, PLY_DOUBLE, offsetof(Vertex,s), 0, 0, 0, 0},
+    {"t", PLY_DOUBLE, PLY_DOUBLE, offsetof(Vertex,t), 0, 0, 0, 0},
+  };
+
+  PlyProperty face_props[] = { /* list of property information for a face */
+    {"vertex_indices", PLY_INT, PLY_INT, offsetof(Face,verts),
+      1, PLY_UCHAR, PLY_UCHAR, offsetof(Face,nverts)},
+  };
+  char * elem_name;
+  FILE * fp = fopen(filename.c_str(),"r");
+  if(fp == NULL)
+  {
+    return false;
+  }
+  int nelems;
+  char ** elem_names;
+  PlyFile * in_ply = ply_read(fp,&nelems,&elem_names);
+  if(in_ply==NULL)
+  {
+    return false;
+  }
+
+  bool has_normals = false;
+  bool has_texture_coords = false;
+  PlyProperty **plist;
+  int nprops;
+  int elem_count;
+  plist = ply_get_element_description (in_ply,"vertex", &elem_count, &nprops);
+  if (plist != NULL)
+  {
+    /* set up for getting vertex elements */
+    ply_get_property (in_ply,"vertex",&vert_props[0]);
+    ply_get_property (in_ply,"vertex",&vert_props[1]);
+    ply_get_property (in_ply,"vertex",&vert_props[2]);
+    for (size_t j = 0; j < nprops; j++)
+    {
+      PlyProperty * prop = plist[j];
+      if (equal_strings ("nx", prop->name) 
+        || equal_strings ("ny", prop->name)
+        || equal_strings ("nz", prop->name))
+      {
+        ply_get_property (in_ply,"vertex",&vert_props[3]);
+        ply_get_property (in_ply,"vertex",&vert_props[4]);
+        ply_get_property (in_ply,"vertex",&vert_props[5]);
+        has_normals = true;
+      }
+      if (equal_strings ("s", prop->name) ||
+        equal_strings ("t", prop->name))
+      {
+        ply_get_property(in_ply,"vertex",&vert_props[6]);
+        ply_get_property(in_ply,"vertex",&vert_props[7]);
+        has_texture_coords = true;
+      }
+    }
+    vert_other = ply_get_other_properties(in_ply,"vertex",
+				     offsetof(Vertex,other_props));
+    V.resize(elem_count,std::vector<Vtype>(3));
+    if(has_normals)
+    {
+      N.resize(elem_count,std::vector<Ntype>(3));
+    }else
+    {
+      N.resize(0);
+    }
+    if(has_texture_coords)
+    {
+      UV.resize(elem_count,std::vector<UVtype>(2));
+    }else
+    {
+      UV.resize(0);
+    }
+    for(size_t j = 0;j<elem_count;j++)
+    {
+      Vertex v;
+      ply_get_element_setup(in_ply,"vertex",3,vert_props);
+      ply_get_element(in_ply,(void*)&v);
+      V[j][0] = v.x;
+      V[j][1] = v.y;
+      V[j][2] = v.z;
+      if(has_normals)
+      {
+        N[j][0] = v.nx;
+        N[j][1] = v.ny;
+        N[j][2] = v.nz;
+      }
+      if(has_texture_coords)
+      {
+        UV[j][0] = v.s;
+        UV[j][1] = v.t;
+      }
+    }
+  }
+  plist = ply_get_element_description (in_ply,"face", &elem_count, &nprops);
+  if (plist != NULL)
+  {
+    F.resize(elem_count);
+    ply_get_property(in_ply,"face",&face_props[0]);
+    for (size_t j = 0; j < elem_count; j++) 
+    {
+      Face f;
+      ply_get_element(in_ply, (void *) &f);
+      for(size_t c = 0;c<f.nverts;c++)
+      {
+        F[j].push_back(f.verts[c]);
+      }
+    }
+  }
+  ply_close(in_ply);
+  fclose(fp);
+  return true;
+}
+
+template <
+  typename DerivedV,
+  typename DerivedF,
+  typename DerivedN,
+  typename DerivedUV>
+IGL_INLINE bool igl::readPLY(
+  const std::string & filename,
+  Eigen::PlainObjectBase<DerivedV> & V,
+  Eigen::PlainObjectBase<DerivedF> & F,
+  Eigen::PlainObjectBase<DerivedN> & N,
+  Eigen::PlainObjectBase<DerivedUV> & UV)
+{
+  std::vector<std::vector<typename DerivedV::Scalar> > vV;
+  std::vector<std::vector<typename DerivedF::Scalar> > vF;
+  std::vector<std::vector<typename DerivedN::Scalar> > vN;
+  std::vector<std::vector<typename DerivedUV::Scalar> > vUV;
+  if(!readPLY(filename,vV,vF,vN,vUV))
+  {
+    return false;
+  }
+  return 
+    list_to_matrix(vV,V) &&
+    list_to_matrix(vF,F) &&
+    list_to_matrix(vN,N) &&
+    list_to_matrix(vUV,UV);
+}
+
+#ifdef IGL_STATIC_LIBRARY
+// Explicit template specialization
+#endif

+ 54 - 0
include/igl/readPLY.h

@@ -0,0 +1,54 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2014 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#ifndef IGL_READPLY_H
+#define IGL_READPLY_H
+#include "igl_inline.h"
+#include <Eigen/Core>
+#include <string>
+#include <vector>
+
+namespace igl
+{
+  // Read a mesh from a .ply file. 
+  //
+  // Inputs:
+  //   filename  path to .ply file
+  // Outputs:
+  //   V  #V by 3 list of vertex positions
+  //   F  #F list of lists of triangle indices
+  //   N  #V by 3 list of vertex normals
+  //   UV  #V by 2 list of vertex texture coordinates
+  // Returns true iff success
+  template <
+    typename Vtype,
+    typename Ftype,
+    typename Ntype,
+    typename UVtype>
+  IGL_INLINE bool readPLY(
+    const std::string & filename,
+    std::vector<std::vector<Vtype> > & V,
+    std::vector<std::vector<Ftype> > & F,
+    std::vector<std::vector<Ntype> > & N,
+    std::vector<std::vector<UVtype> >  & UV);
+  template <
+    typename DerivedV,
+    typename DerivedF,
+    typename DerivedN,
+    typename DerivedUV>
+  IGL_INLINE bool readPLY(
+    const std::string & filename,
+    Eigen::PlainObjectBase<DerivedV> & V,
+    Eigen::PlainObjectBase<DerivedF> & F,
+    Eigen::PlainObjectBase<DerivedN> & N,
+    Eigen::PlainObjectBase<DerivedUV> & UV);
+}
+#ifndef IGL_STATIC_LIBRARY
+#  include "readPLY.cpp"
+#endif
+#endif
+

+ 7 - 0
include/igl/read_triangle_mesh.cpp

@@ -12,6 +12,7 @@
 #include <igl/readOBJ.h>
 #include <igl/readOFF.h>
 #include <igl/readSTL.h>
+#include <igl/readPLY.h>
 #include <igl/readWRL.h>
 #include <igl/pathinfo.h>
 #include <igl/boundary_facets.h>
@@ -104,6 +105,12 @@ IGL_INLINE bool igl::read_triangle_mesh(
     {
       return false;
     }
+  }else if(ext == "ply")
+  {
+    if(!readPLY(filename,vV,vF,vN,vTC))
+    {
+      return false;
+    }
   }else if(ext == "stl")
   {
     MatrixXd _;

+ 4 - 2
include/igl/read_triangle_mesh.h

@@ -20,13 +20,15 @@
 
 namespace igl
 {
-  // read mesh from an ascii file with automatic detection of file format. supported: obj, off)
+  // read mesh from an ascii file with automatic detection of file format.
+  // supported: obj, off, stl, wrl, ply, mesh)
+  // 
   // Templates:
   //   Scalar  type for positions and vectors (will be read as double and cast
   //     to Scalar)
   //   Index  type for indices (will be read as int and cast to Index)
   // Inputs:
-  //   str  path to .obj/.off file
+  //   str  path to file
   // Outputs:
   //   V  eigen double matrix #V by 3
   //   F  eigen int matrix #F by 3

+ 142 - 0
include/igl/writePLY.cpp

@@ -0,0 +1,142 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+//
+// Copyright (C) 2014 Alec Jacobson <alecjacobson@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+#include "writePLY.h"
+#include <igl/ply.h>
+
+template <
+  typename DerivedV,
+  typename DerivedF,
+  typename DerivedN,
+  typename DerivedUV>
+IGL_INLINE bool igl::writePLY(
+  const std::string & filename,
+  const Eigen::PlainObjectBase<DerivedV> & V,
+  const Eigen::PlainObjectBase<DerivedF> & F,
+  const Eigen::PlainObjectBase<DerivedN> & N,
+  const Eigen::PlainObjectBase<DerivedUV> & UV,
+  const bool ascii)
+{
+  // Largely based on obj2ply.c
+
+  typedef struct Vertex
+  {
+    double x,y,z,w;          /* position */
+    double nx,ny,nz;         /* surface normal */
+    double s,t;              /* texture coordinates */
+  } Vertex;
+
+  typedef struct Face
+  {
+    unsigned char nverts;    /* number of vertex indices in list */
+    int *verts;              /* vertex index list */
+  } Face;
+
+  PlyProperty vert_props[] = 
+  { /* list of property information for a vertex */
+    {"x", PLY_DOUBLE, PLY_DOUBLE, offsetof(Vertex,x), 0, 0, 0, 0},
+    {"y", PLY_DOUBLE, PLY_DOUBLE, offsetof(Vertex,y), 0, 0, 0, 0},
+    {"z", PLY_DOUBLE, PLY_DOUBLE, offsetof(Vertex,z), 0, 0, 0, 0},
+    {"nx", PLY_DOUBLE, PLY_DOUBLE, offsetof(Vertex,nx), 0, 0, 0, 0},
+    {"ny", PLY_DOUBLE, PLY_DOUBLE, offsetof(Vertex,ny), 0, 0, 0, 0},
+    {"nz", PLY_DOUBLE, PLY_DOUBLE, offsetof(Vertex,nz), 0, 0, 0, 0},
+    {"s", PLY_DOUBLE, PLY_DOUBLE, offsetof(Vertex,s), 0, 0, 0, 0},
+    {"t", PLY_DOUBLE, PLY_DOUBLE, offsetof(Vertex,t), 0, 0, 0, 0},
+  };
+
+  PlyProperty face_props[] = 
+  { /* list of property information for a face */
+    {"vertex_indices", PLY_INT, PLY_INT, offsetof(Face,verts),
+      1, PLY_UCHAR, PLY_UCHAR, offsetof(Face,nverts)},
+  };
+  const bool has_normals = N.rows() > 0;
+  const bool has_texture_coords = UV.rows() > 0;
+  std::vector<Vertex> vlist(V.rows());
+  std::vector<Face> flist(F.rows());
+  for(size_t i = 0;i<V.rows();i++)
+  {
+    vlist[i].x = V(i,0);
+    vlist[i].y = V(i,1);
+    vlist[i].z = V(i,2);
+    if(has_normals)
+    {
+      vlist[i].nx = N(i,0);
+      vlist[i].ny = N(i,1);
+      vlist[i].nz = N(i,2);
+    }
+    if(has_texture_coords)
+    {
+      vlist[i].s = UV(i,0);
+      vlist[i].t = UV(i,1);
+    }
+  }
+  for(size_t i = 0;i<F.rows();i++)
+  {
+    flist[i].nverts = F.cols();
+    flist[i].verts = new int[F.cols()];
+    for(size_t c = 0;c<F.cols();c++)
+    {
+      flist[i].verts[c] = F(i,c);
+    }
+  }
+
+  const char * elem_names[] = {"vertex","face"};
+  FILE * fp = fopen(filename.c_str(),"w");
+  if(fp==NULL)
+  {
+    return false;
+  }
+  PlyFile * ply = ply_write(fp, 2,elem_names, 
+      (ascii ? PLY_ASCII : PLY_BINARY_LE));
+  if(ply==NULL)
+  {
+    return false;
+  }
+
+  std::vector<PlyProperty> plist;
+  plist.push_back(vert_props[0]);
+  plist.push_back(vert_props[1]);
+  plist.push_back(vert_props[2]);
+  if (has_normals) 
+  {
+    plist.push_back(vert_props[3]);
+    plist.push_back(vert_props[4]);
+    plist.push_back(vert_props[5]);
+  }
+  if (has_texture_coords)
+  {
+    plist.push_back(vert_props[6]);
+    plist.push_back(vert_props[7]);
+  }
+  ply_describe_element(ply, "vertex", V.rows(),plist.size(),
+    &plist[0]);
+
+  ply_describe_element(ply, "face", F.rows(),1,&face_props[0]);
+  ply_header_complete(ply);
+  ply_put_element_setup(ply, "vertex");
+  for(const auto v : vlist)
+  {
+    ply_put_element(ply, (void *) &v);
+  }
+  ply_put_element_setup(ply, "face");
+  for(const auto f : flist)
+  {
+    ply_put_element(ply, (void *) &f);
+  }
+
+  ply_close(ply);
+  fclose(fp);
+  for(size_t i = 0;i<F.rows();i++)
+  {
+    delete[] flist[i].verts;
+  }
+  return true;
+}
+
+#ifdef IGL_STATIC_LIBRARY
+// Explicit template specialization
+#endif

+ 41 - 0
include/igl/writePLY.h

@@ -0,0 +1,41 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2014 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#ifndef IGL_WRITEPLY_H
+#define IGL_WRITEPLY_H
+#include "igl_inline.h"
+#include <Eigen/Core>
+#include <string>
+
+namespace igl
+{
+  // Write a mesh to a .ply file. 
+  //
+  // Inputs:
+  //   filename  path to .ply file
+  //   V  #V by 3 list of vertex positions
+  //   F  #F by 3 list of triangle indices
+  //   N  #V by 3 list of vertex normals
+  //   UV  #V by 2 list of vertex texture coordinates
+  // Returns true iff success
+  template <
+    typename DerivedV,
+    typename DerivedF,
+    typename DerivedN,
+    typename DerivedUV>
+  IGL_INLINE bool writePLY(
+    const std::string & filename,
+    const Eigen::PlainObjectBase<DerivedV> & V,
+    const Eigen::PlainObjectBase<DerivedF> & F,
+    const Eigen::PlainObjectBase<DerivedN> & N,
+    const Eigen::PlainObjectBase<DerivedUV> & UV,
+    const bool ascii = true);
+}
+#ifndef IGL_STATIC_LIBRARY
+#  include "writePLY.cpp"
+#endif
+#endif