You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
644 lines
23 KiB
644 lines
23 KiB
#include "readPLY.h"
|
|
#include <string>
|
|
#include <set>
|
|
#include <fstream>
|
|
#include <iostream>
|
|
#include <Eigen/Core>
|
|
|
|
#include "tinyply.h"
|
|
#include "read_file_binary.h"
|
|
#include "FileMemoryStream.h"
|
|
|
|
|
|
namespace igl
|
|
{
|
|
|
|
template <typename T, typename Derived>
|
|
IGL_INLINE bool _tinyply_buffer_to_matrix(
|
|
tinyply::PlyData & D,
|
|
Eigen::PlainObjectBase<Derived> & M,
|
|
size_t rows,
|
|
size_t cols )
|
|
{
|
|
Eigen::Map< Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> >
|
|
_map( reinterpret_cast<T *>( D.buffer.get()), rows, cols );
|
|
|
|
M = _map.template cast<typename Derived::Scalar>();
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
template <typename Derived>
|
|
IGL_INLINE bool tinyply_buffer_to_matrix(
|
|
tinyply::PlyData & D,
|
|
Eigen::PlainObjectBase<Derived> & M,
|
|
size_t rows,
|
|
size_t cols )
|
|
{
|
|
switch(D.t)
|
|
{
|
|
case tinyply::Type::INT8 :
|
|
return _tinyply_buffer_to_matrix<int8_t,Derived>(D, M,rows,cols);
|
|
case tinyply::Type::UINT8 :
|
|
return _tinyply_buffer_to_matrix<uint8_t,Derived>(D, M,rows,cols);
|
|
case tinyply::Type::INT16 :
|
|
return _tinyply_buffer_to_matrix<int16_t,Derived>(D, M,rows,cols);
|
|
case tinyply::Type::UINT16 :
|
|
return _tinyply_buffer_to_matrix<uint16_t,Derived>(D, M,rows,cols);
|
|
case tinyply::Type::INT32 :
|
|
return _tinyply_buffer_to_matrix<int32_t,Derived>(D, M,rows,cols);
|
|
case tinyply::Type::UINT32 :
|
|
return _tinyply_buffer_to_matrix<uint32_t,Derived>(D, M,rows,cols);
|
|
case tinyply::Type::FLOAT32 :
|
|
return _tinyply_buffer_to_matrix<float,Derived>(D, M,rows,cols);
|
|
case tinyply::Type::FLOAT64 :
|
|
return _tinyply_buffer_to_matrix<double,Derived>(D, M,rows,cols);
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
template <typename T, typename Derived>
|
|
IGL_INLINE bool _tinyply_tristrips_to_trifaces(
|
|
tinyply::PlyData & D,
|
|
Eigen::PlainObjectBase<Derived> & M,
|
|
size_t el,
|
|
size_t el_len )
|
|
{
|
|
|
|
Eigen::Map< Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> >
|
|
_map( reinterpret_cast<T *>( D.buffer.get()), el, el_len );
|
|
|
|
// to make it more interesting, triangles in triangle strip can be separated by negative index elements
|
|
// 1. count all triangles
|
|
size_t triangles=0;
|
|
|
|
// TODO: it's possible to optimize this , i suppose
|
|
for(size_t i=0; i<el; i++)
|
|
for(size_t j=0; j<(el_len-2); j++)
|
|
{
|
|
if(_map(i,j)>=0 && _map(i,j+1)>=0 && _map(i,j+2)>=0)
|
|
triangles++;
|
|
}
|
|
|
|
// 2. convert triangles to faces, skipping over the negative indeces, indicating separate strips
|
|
M.resize(triangles, 3);
|
|
size_t k=0;
|
|
for(size_t i=0; i<el; i++)
|
|
{
|
|
int flip=0;
|
|
for(size_t j=0; j<(el_len-2); j++)
|
|
{
|
|
if(_map(i,j)>=0 && _map(i,j+1)>=0 && _map(i,j+2)>=0)
|
|
{
|
|
// consequtive faces on the same strip have to be flip-flopped, to preserve orientation
|
|
M( k,0 ) = static_cast<typename Derived::Scalar>( _map(i, j ) );
|
|
M( k,1 ) = static_cast<typename Derived::Scalar>( _map(i, j+1+flip ) );
|
|
M( k,2 ) = static_cast<typename Derived::Scalar>( _map(i, j+1+(flip^1) ) );
|
|
k++;
|
|
flip ^= 1;
|
|
} else {
|
|
// reset flip on new strip start
|
|
flip = 0;
|
|
}
|
|
}
|
|
}
|
|
assert(k==triangles);
|
|
return true;
|
|
}
|
|
|
|
template <typename Derived>
|
|
IGL_INLINE bool tinyply_tristrips_to_faces(
|
|
tinyply::PlyData & D,
|
|
Eigen::PlainObjectBase<Derived> & M,
|
|
size_t el,
|
|
size_t el_len )
|
|
{
|
|
switch(D.t)
|
|
{
|
|
case tinyply::Type::INT8 :
|
|
return _tinyply_tristrips_to_trifaces<int8_t,Derived>(D, M,el,el_len);
|
|
case tinyply::Type::UINT8 :
|
|
return _tinyply_tristrips_to_trifaces<uint8_t,Derived>(D, M,el,el_len);
|
|
case tinyply::Type::INT16 :
|
|
return _tinyply_tristrips_to_trifaces<int16_t,Derived>(D, M,el,el_len);
|
|
case tinyply::Type::UINT16 :
|
|
return _tinyply_tristrips_to_trifaces<uint16_t,Derived>(D, M,el,el_len);
|
|
case tinyply::Type::INT32 :
|
|
return _tinyply_tristrips_to_trifaces<int32_t,Derived>(D, M,el,el_len);
|
|
case tinyply::Type::UINT32 :
|
|
return _tinyply_tristrips_to_trifaces<uint32_t,Derived>(D, M,el,el_len);
|
|
case tinyply::Type::FLOAT32 :
|
|
return _tinyply_tristrips_to_trifaces<float,Derived>(D, M,el,el_len);
|
|
case tinyply::Type::FLOAT64 :
|
|
return _tinyply_tristrips_to_trifaces<double,Derived>(D, M,el,el_len);
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
template <
|
|
typename DerivedV,
|
|
typename DerivedF,
|
|
typename DerivedE,
|
|
typename DerivedN,
|
|
typename DerivedUV,
|
|
typename DerivedVD,
|
|
typename DerivedFD,
|
|
typename DerivedED
|
|
>
|
|
IGL_INLINE bool readPLY(
|
|
FILE *fp,
|
|
Eigen::PlainObjectBase<DerivedV> & V,
|
|
Eigen::PlainObjectBase<DerivedF> & F,
|
|
Eigen::PlainObjectBase<DerivedE> & E,
|
|
Eigen::PlainObjectBase<DerivedN> & N,
|
|
Eigen::PlainObjectBase<DerivedUV> & UV,
|
|
|
|
Eigen::PlainObjectBase<DerivedVD> & VD,
|
|
std::vector<std::string> & Vheader,
|
|
Eigen::PlainObjectBase<DerivedFD> & FD,
|
|
std::vector<std::string> & Fheader,
|
|
Eigen::PlainObjectBase<DerivedED> & ED,
|
|
std::vector<std::string> & Eheader,
|
|
std::vector<std::string> & comments
|
|
)
|
|
{
|
|
// buffer the whole file in memory
|
|
// then read from memory buffer
|
|
try
|
|
{
|
|
std::vector<uint8_t> fileBufferBytes;
|
|
// read_file_binary will call fclose
|
|
read_file_binary(fp,fileBufferBytes);
|
|
FileMemoryStream stream((char*)fileBufferBytes.data(), fileBufferBytes.size());
|
|
return readPLY(stream,V,F,E,N,UV,VD,Vheader,FD,Fheader,ED,Eheader,comments);
|
|
}
|
|
catch(const std::exception& e)
|
|
{
|
|
std::cerr << "ReadPLY error: " << e.what() << std::endl;
|
|
}
|
|
fclose(fp);
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
template <
|
|
typename DerivedV,
|
|
typename DerivedF
|
|
>
|
|
IGL_INLINE bool readPLY(
|
|
FILE *fp,
|
|
Eigen::PlainObjectBase<DerivedV> & V,
|
|
Eigen::PlainObjectBase<DerivedF> & F
|
|
)
|
|
{
|
|
Eigen::MatrixXd N,UV,VD,FD,ED;
|
|
Eigen::MatrixXi E;
|
|
std::vector<std::string> Vheader,Eheader,Fheader,comments;
|
|
return readPLY(fp,V,F,E,N,UV,VD,Vheader,FD,Fheader,ED,Eheader,comments);
|
|
}
|
|
|
|
template <
|
|
typename DerivedV,
|
|
typename DerivedF,
|
|
typename DerivedE
|
|
>
|
|
IGL_INLINE bool readPLY(
|
|
FILE *fp,
|
|
Eigen::PlainObjectBase<DerivedV> & V,
|
|
Eigen::PlainObjectBase<DerivedF> & F,
|
|
Eigen::PlainObjectBase<DerivedE> & E
|
|
)
|
|
{
|
|
Eigen::MatrixXd N,UV,VD,FD,ED;
|
|
std::vector<std::string> Vheader,Eheader,Fheader,comments;
|
|
return readPLY(fp,V,F,E,N,UV,VD,Vheader,FD,Fheader,ED,Eheader,comments);
|
|
}
|
|
|
|
|
|
template <
|
|
typename DerivedV,
|
|
typename DerivedF,
|
|
typename DerivedE,
|
|
typename DerivedN,
|
|
typename DerivedUV,
|
|
typename DerivedVD,
|
|
typename DerivedFD,
|
|
typename DerivedED
|
|
>
|
|
IGL_INLINE bool readPLY(
|
|
std::istream & ply_stream,
|
|
Eigen::PlainObjectBase<DerivedV> & V,
|
|
Eigen::PlainObjectBase<DerivedF> & F,
|
|
Eigen::PlainObjectBase<DerivedE> & E,
|
|
Eigen::PlainObjectBase<DerivedN> & N,
|
|
Eigen::PlainObjectBase<DerivedUV> & UV,
|
|
|
|
Eigen::PlainObjectBase<DerivedVD> & VD,
|
|
std::vector<std::string> & Vheader,
|
|
Eigen::PlainObjectBase<DerivedFD> & FD,
|
|
std::vector<std::string> & Fheader,
|
|
Eigen::PlainObjectBase<DerivedED> & ED,
|
|
std::vector<std::string> & Eheader,
|
|
std::vector<std::string> & comments
|
|
)
|
|
{
|
|
tinyply::PlyFile file;
|
|
file.parse_header(ply_stream);
|
|
|
|
std::set<std::string> vertex_std{ "x","y","z", "nx","ny","nz", "u","v", "texture_u", "texture_v", "s", "t"};
|
|
std::set<std::string> face_std { "vertex_index", "vertex_indices"};
|
|
std::set<std::string> edge_std { "vertex1", "vertex2"}; //non-standard edge indexes
|
|
|
|
// Tinyply treats parsed data as untyped byte buffers.
|
|
std::shared_ptr<tinyply::PlyData> vertices, normals, faces, texcoords, edges;
|
|
|
|
// Some ply files contain tristrips instead of faces
|
|
std::shared_ptr<tinyply::PlyData> tristrips;
|
|
|
|
std::shared_ptr<tinyply::PlyData> _vertex_data;
|
|
std::vector<std::string> _vertex_header;
|
|
|
|
std::shared_ptr<tinyply::PlyData> _face_data;
|
|
std::vector<std::string> _face_header;
|
|
|
|
std::shared_ptr<tinyply::PlyData> _edge_data;
|
|
std::vector<std::string> _edge_header;
|
|
|
|
for (auto c : file.get_comments())
|
|
comments.push_back(c);
|
|
|
|
for (auto e : file.get_elements())
|
|
{
|
|
if(e.name == "vertex" ) // found a vertex
|
|
{
|
|
for (auto p : e.properties)
|
|
{
|
|
if(vertex_std.find(p.name) == vertex_std.end())
|
|
{
|
|
_vertex_header.push_back(p.name);
|
|
}
|
|
}
|
|
}
|
|
else if(e.name == "face" ) // found face
|
|
{
|
|
for (auto p : e.properties)
|
|
{
|
|
if(face_std.find(p.name) == face_std.end())
|
|
{
|
|
_face_header.push_back(p.name);
|
|
}
|
|
}
|
|
}
|
|
else if(e.name == "edge" ) // found edge
|
|
{
|
|
for (auto p : e.properties)
|
|
{
|
|
if(edge_std.find(p.name) == edge_std.end())
|
|
{
|
|
_edge_header.push_back(p.name);
|
|
}
|
|
}
|
|
}
|
|
// skip the unknown entries
|
|
}
|
|
|
|
// The header information can be used to programmatically extract properties on elements
|
|
// known to exist in the header prior to reading the data. For brevity of this sample, properties
|
|
// like vertex position are hard-coded:
|
|
try {
|
|
vertices = file.request_properties_from_element("vertex", { "x", "y", "z" });
|
|
}
|
|
catch (const std::exception & ) { }
|
|
|
|
try {
|
|
normals = file.request_properties_from_element("vertex", { "nx", "ny", "nz" });
|
|
}
|
|
catch (const std::exception & ) { }
|
|
|
|
//Try texture coordinates with several names
|
|
try {
|
|
//texture_u texture_v are the names used by meshlab to store textures
|
|
texcoords = file.request_properties_from_element("vertex", { "texture_u", "texture_v" });
|
|
}
|
|
catch (const std::exception & ) { }
|
|
if (!texcoords)
|
|
{
|
|
try {
|
|
//u v are the naive names
|
|
texcoords = file.request_properties_from_element("vertex", { "u", "v" });
|
|
}
|
|
catch (const std::exception & ) { }
|
|
|
|
}
|
|
if (!texcoords)
|
|
{
|
|
try {
|
|
//s t were the names used by blender and the previous libigl PLY reader.
|
|
texcoords = file.request_properties_from_element("vertex", { "s", "t" });
|
|
}
|
|
catch (const std::exception & ) { }
|
|
|
|
}
|
|
|
|
// Providing a list size hint (the last argument) is a 2x performance improvement. If you have
|
|
// arbitrary ply files, it is best to leave this 0.
|
|
try {
|
|
faces = file.request_properties_from_element( "face", { "vertex_indices" }, 0);
|
|
}
|
|
catch (const std::exception & ) { }
|
|
|
|
if (!faces)
|
|
{
|
|
try {
|
|
// alternative name of the elements
|
|
faces = file.request_properties_from_element( "face", { "vertex_index" },0);
|
|
}
|
|
catch (const std::exception & ) { }
|
|
}
|
|
|
|
if (!faces)
|
|
{
|
|
try {
|
|
// try using tristrips
|
|
tristrips = file.request_properties_from_element( "tristrips", { "vertex_indices" }, 0);
|
|
}
|
|
catch (const std::exception & ) { }
|
|
|
|
if (!tristrips)
|
|
{
|
|
try {
|
|
// alternative name of the elements
|
|
tristrips = file.request_properties_from_element( "tristrips", { "vertex_index" }, 0);
|
|
}
|
|
catch (const std::exception & ) { }
|
|
}
|
|
}
|
|
|
|
|
|
try {
|
|
edges = file.request_properties_from_element("edge", { "vertex1", "vertex2" });
|
|
}
|
|
catch (const std::exception & ) { }
|
|
|
|
if(! _vertex_header.empty())
|
|
_vertex_data = file.request_properties_from_element( "vertex", _vertex_header);
|
|
if(! _face_header.empty())
|
|
_face_data = file.request_properties_from_element( "face", _face_header);
|
|
if(! _edge_header.empty())
|
|
_edge_data = file.request_properties_from_element( "edge", _edge_header);
|
|
|
|
// Parse the geometry data
|
|
file.read(ply_stream);
|
|
|
|
if (!vertices || !tinyply_buffer_to_matrix(*vertices,V,vertices->count,3) ) {
|
|
V.resize(0,0);
|
|
}
|
|
|
|
if (!normals || !tinyply_buffer_to_matrix(*normals,N,normals->count,3) ) {
|
|
N.resize(0,0);
|
|
}
|
|
|
|
if (!texcoords || !tinyply_buffer_to_matrix(*texcoords,UV,texcoords->count,2) ) {
|
|
UV.resize(0,0);
|
|
}
|
|
|
|
//HACK: Unfortunately, tinyply doesn't store list size as a separate variable
|
|
if (!faces || !tinyply_buffer_to_matrix(*faces, F, faces->count, faces->count==0?0:faces->buffer.size_bytes()/(tinyply::PropertyTable[faces->t].stride*faces->count) )) {
|
|
|
|
if(tristrips) { // need to convert to faces
|
|
// code based on blender importer for ply
|
|
// converting triangle strips into triangles
|
|
// tinyply supports tristrips of the same length only
|
|
size_t el_count = tristrips->buffer.size_bytes()/(tinyply::PropertyTable[tristrips->t].stride*tristrips->count);
|
|
|
|
// all strips should have tristrips->count elements
|
|
if(!tinyply_tristrips_to_faces(*tristrips, F , tristrips->count, el_count))
|
|
F.resize(0,0);
|
|
|
|
} else {
|
|
F.resize(0,0);
|
|
}
|
|
}
|
|
|
|
if(!edges || !tinyply_buffer_to_matrix(*edges,E, edges->count,2)) {
|
|
E.resize(0,0);
|
|
}
|
|
|
|
/// convert vertex data:
|
|
Vheader=_vertex_header;
|
|
if(_vertex_header.empty())
|
|
{
|
|
VD.resize(0,0);
|
|
}
|
|
else
|
|
{
|
|
VD.resize(vertices->count,_vertex_header.size());
|
|
tinyply_buffer_to_matrix(*_vertex_data, VD, vertices->count, _vertex_header.size());
|
|
}
|
|
|
|
/// convert face data:
|
|
Fheader=_face_header;
|
|
if(_face_header.empty())
|
|
{
|
|
FD.resize(0,0);
|
|
}
|
|
else
|
|
{
|
|
FD.resize(faces->count, _face_header.size());
|
|
tinyply_buffer_to_matrix(*_face_data, FD, faces->count, _face_header.size());
|
|
}
|
|
|
|
/// convert edge data:
|
|
Eheader=_edge_header;
|
|
if(_edge_header.empty())
|
|
{
|
|
ED.resize(0,0);
|
|
}
|
|
else
|
|
{
|
|
ED.resize(_edge_data->count, _edge_header.size());
|
|
tinyply_buffer_to_matrix(*_edge_data, ED, _edge_data->count, _edge_header.size());
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
template <
|
|
typename DerivedV,
|
|
typename DerivedF,
|
|
typename DerivedE,
|
|
typename DerivedN,
|
|
typename DerivedUV,
|
|
typename DerivedVD,
|
|
typename DerivedFD,
|
|
typename DerivedED
|
|
>
|
|
IGL_INLINE bool readPLY(
|
|
const std::string& ply_file,
|
|
Eigen::PlainObjectBase<DerivedV> & V,
|
|
Eigen::PlainObjectBase<DerivedF> & F,
|
|
Eigen::PlainObjectBase<DerivedE> & E,
|
|
Eigen::PlainObjectBase<DerivedN> & N,
|
|
Eigen::PlainObjectBase<DerivedUV> & UV,
|
|
|
|
Eigen::PlainObjectBase<DerivedVD> & VD,
|
|
std::vector<std::string> & VDheader,
|
|
|
|
Eigen::PlainObjectBase<DerivedFD> & FD,
|
|
std::vector<std::string> & FDheader,
|
|
|
|
Eigen::PlainObjectBase<DerivedED> & ED,
|
|
std::vector<std::string> & EDheader,
|
|
std::vector<std::string> & comments
|
|
)
|
|
{
|
|
|
|
std::ifstream ply_stream(ply_file, std::ios::binary);
|
|
if (ply_stream.fail())
|
|
{
|
|
std::cerr << "ReadPLY: Error opening file " << ply_file << std::endl;
|
|
return false;
|
|
}
|
|
try
|
|
{
|
|
return readPLY(ply_stream, V, F, E, N, UV, VD, VDheader, FD,FDheader, ED, EDheader, comments );
|
|
} catch (const std::exception& e) {
|
|
std::cerr << "ReadPLY error: " << ply_file << e.what() << std::endl;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
template <
|
|
typename DerivedV,
|
|
typename DerivedF,
|
|
typename DerivedE,
|
|
typename DerivedN,
|
|
typename DerivedUV,
|
|
typename DerivedD
|
|
>
|
|
IGL_INLINE bool readPLY(
|
|
const std::string & filename,
|
|
Eigen::PlainObjectBase<DerivedV> & V,
|
|
Eigen::PlainObjectBase<DerivedF> & F,
|
|
Eigen::PlainObjectBase<DerivedE> & E,
|
|
Eigen::PlainObjectBase<DerivedN> & N,
|
|
Eigen::PlainObjectBase<DerivedUV> & UV,
|
|
Eigen::PlainObjectBase<DerivedD> & VD,
|
|
std::vector<std::string> & Vheader
|
|
)
|
|
{
|
|
Eigen::MatrixXd FD,ED;
|
|
std::vector<std::string> Fheader,Eheader;
|
|
std::vector<std::string> comments;
|
|
return readPLY(filename,V,F,E,N,UV,VD,Vheader,FD,Fheader,ED,Eheader,comments);
|
|
}
|
|
|
|
template <
|
|
typename DerivedV,
|
|
typename DerivedF,
|
|
typename DerivedE,
|
|
typename DerivedN,
|
|
typename DerivedUV
|
|
>
|
|
IGL_INLINE bool readPLY(
|
|
const std::string & filename,
|
|
Eigen::PlainObjectBase<DerivedV> & V,
|
|
Eigen::PlainObjectBase<DerivedF> & F,
|
|
Eigen::PlainObjectBase<DerivedE> & E,
|
|
Eigen::PlainObjectBase<DerivedN> & N,
|
|
Eigen::PlainObjectBase<DerivedUV> & UV
|
|
)
|
|
{
|
|
Eigen::MatrixXd VD,FD,ED;
|
|
std::vector<std::string> Vheader,Fheader,Eheader;
|
|
std::vector<std::string> comments;
|
|
return readPLY(filename,V,F,E, N,UV,VD,Vheader,FD,Fheader,ED,Eheader,comments);
|
|
}
|
|
|
|
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
|
|
)
|
|
{
|
|
Eigen::MatrixXd VD,FD,ED;
|
|
Eigen::MatrixXi E;
|
|
std::vector<std::string> Vheader,Fheader,Eheader;
|
|
std::vector<std::string> comments;
|
|
return readPLY(filename,V,F,E, N,UV,VD,Vheader,FD,Fheader,ED,Eheader,comments);
|
|
}
|
|
|
|
template <
|
|
typename DerivedV,
|
|
typename DerivedF
|
|
>
|
|
IGL_INLINE bool readPLY(
|
|
const std::string & filename,
|
|
Eigen::PlainObjectBase<DerivedV> & V,
|
|
Eigen::PlainObjectBase<DerivedF> & F
|
|
)
|
|
{
|
|
Eigen::MatrixXd N,UV;
|
|
Eigen::MatrixXd VD,FD,ED;
|
|
Eigen::MatrixXi E;
|
|
|
|
std::vector<std::string> Vheader,Fheader,Eheader;
|
|
std::vector<std::string> comments;
|
|
return readPLY(filename,V,F,E,N,UV,VD,Vheader,FD,Fheader,ED,Eheader,comments);
|
|
}
|
|
|
|
template <
|
|
typename DerivedV,
|
|
typename DerivedF,
|
|
typename DerivedE
|
|
>
|
|
IGL_INLINE bool readPLY(
|
|
const std::string & filename,
|
|
Eigen::PlainObjectBase<DerivedV> & V,
|
|
Eigen::PlainObjectBase<DerivedF> & F,
|
|
Eigen::PlainObjectBase<DerivedE> & E
|
|
)
|
|
{
|
|
Eigen::MatrixXd N,UV;
|
|
Eigen::MatrixXd VD,FD,ED;
|
|
|
|
std::vector<std::string> Vheader,Fheader,Eheader;
|
|
std::vector<std::string> comments;
|
|
return readPLY(filename,V,F,E,N,UV,VD,Vheader,FD,Fheader,ED,Eheader,comments);
|
|
}
|
|
|
|
|
|
} //igl namespace
|
|
|
|
#ifdef IGL_STATIC_LIBRARY
|
|
// Explicit template instantiation
|
|
// generated by autoexplicit.sh
|
|
template bool igl::readPLY<Eigen::Matrix<double, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(FILE*, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 1, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
|
|
template bool igl::readPLY<Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(FILE*, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
|
|
template bool igl::readPLY<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(FILE*, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);
|
|
template bool igl::readPLY<Eigen::Matrix<double, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 3, 1, -1, 3> >(FILE*, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 1, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> >&);
|
|
template bool igl::readPLY<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(FILE*, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
|
|
template bool igl::readPLY<Eigen::Matrix<double, -1, -1, 1, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(FILE*, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 1, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
|
|
template bool igl::readPLY<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> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
|
|
template bool igl::readPLY<Eigen::Matrix<float, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(FILE*, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);
|
|
template bool igl::readPLY<Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3> >(FILE*, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3> >&);
|
|
template bool igl::readPLY<Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 3, 1, -1, 3> >(FILE*, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> >&);
|
|
template bool igl::readPLY<Eigen::Matrix<float, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(FILE*, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
|
|
|
|
template bool igl::readPLY<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -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> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&, std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&);
|
|
template bool igl::readPLY<Eigen::Matrix<float, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<float, -1, -1, 0, -1, -1>, Eigen::Matrix<float, -1, -1, 0, -1, -1>, Eigen::Matrix<float, -1, -1, 0, -1, -1>, Eigen::Matrix<float, -1, -1, 0, -1, -1>, Eigen::Matrix<float, -1, -1, 0, -1, -1> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> >&, std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> >&, std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> >&, std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&, std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&);
|
|
#endif
|
|
|