// This file is part of libigl, a simple c++ geometry processing library. // // Copyright (C) 2014 Alec Jacobson // // 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 template < typename Vtype, typename Ftype, typename Ntype, typename UVtype> IGL_INLINE bool igl::readPLY( const std::string filename, std::vector > & V, std::vector > & F, std::vector > & N, std::vector > & UV) { using namespace std; // Largely follows ply2iv.c FILE * ply_file = fopen(filename.c_str(),"r"); if(ply_file == NULL) { return false; } return readPLY(ply_file,V,F,N,UV); } template < typename Vtype, typename Ftype, typename Ntype, typename UVtype> IGL_INLINE bool igl::readPLY( FILE * ply_file, std::vector > & V, std::vector > & F, std::vector > & N, std::vector > & UV) { using namespace std; 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; igl::ply::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}, }; igl::ply::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)}, }; int nelems; char ** elem_names; igl::ply::PlyFile * in_ply = igl::ply::ply_read(ply_file,&nelems,&elem_names); if(in_ply==NULL) { return false; } bool has_normals = false; bool has_texture_coords = false; igl::ply::PlyProperty **plist; int nprops; int elem_count; plist = ply_get_element_description (in_ply,"vertex", &elem_count, &nprops); int native_binary_type = igl::ply::get_native_binary_type2(); 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 (int j = 0; j < nprops; j++) { igl::ply::PlyProperty * prop = plist[j]; if (igl::ply::equal_strings ("nx", prop->name) || igl::ply::equal_strings ("ny", prop->name) || igl::ply::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 (igl::ply::equal_strings ("s", prop->name) || igl::ply::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; } } // Is this call necessary? ply_get_other_properties(in_ply,"vertex", offsetof(Vertex,other_props)); V.resize(elem_count,std::vector(3)); if(has_normals) { N.resize(elem_count,std::vector(3)); }else { N.resize(0); } if(has_texture_coords) { UV.resize(elem_count,std::vector(2)); }else { UV.resize(0); } for(int j = 0;j IGL_INLINE bool igl::readPLY( const std::string filename, Eigen::PlainObjectBase & V, Eigen::PlainObjectBase & F, Eigen::PlainObjectBase & N, Eigen::PlainObjectBase & UV) { std::vector > vV; std::vector > vF; std::vector > vN; std::vector > 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); } template < typename DerivedV, typename DerivedF> IGL_INLINE bool igl::readPLY( const std::string filename, Eigen::PlainObjectBase & V, Eigen::PlainObjectBase & F) { Eigen::MatrixXd N,UV; return readPLY(filename,V,F,N,UV); } #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation template bool igl::readPLY(std::basic_string, std::allocator > const, std::vector >, std::allocator > > >&, std::vector >, std::allocator > > >&, std::vector >, std::allocator > > >&, std::vector >, std::allocator > > >&); template bool igl::readPLY, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(std::basic_string, std::allocator > const, Eigen::PlainObjectBase > &, Eigen::PlainObjectBase > &, Eigen::PlainObjectBase > &, Eigen::PlainObjectBase > &); template bool igl::readPLY, Eigen::Matrix >(std::basic_string, std::allocator > const, Eigen::PlainObjectBase > &, Eigen::PlainObjectBase > &); template bool igl::readPLY, Eigen::Matrix >(std::string, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); #endif