int main(int argc, char **argv) { const char *value; p_ply iply, oply; iply = ply_open("input.ply", NULL); if (!iply) return 1; if (!ply_read_header(iply)) return 1; oply = ply_create("output.ply", PLY_LITTLE_ENDIAN, NULL); if (!oply) return 1; if (!setup_callbacks(iply, oply)) return 1; /* pass comments and obj_infos from input to output */ value = NULL; while ((value = ply_get_next_comment(iply, value))) if (!ply_add_comment(oply, value)) return 1; value = NULL; while ((value = ply_get_next_obj_info(iply, value))) if (!ply_add_obj_info(oply, value)) return 1;; /* write output header */ if (!ply_write_header(oply)) return 1; /* read input file generating callbacks that pass data to output file */ if (!ply_read(iply)) return 1; /* close up, we are done */ if (!ply_close(iply)) return 1; if (!ply_close(oply)) return 1; return 0; }
/* given a format mode, an input file name and an output file name, * convert input file to output in given format mode */ int main(int argc, char **argv) { const char *value = NULL; e_ply_storage_mode storage_mode = PLY_LITTLE_ENDIAN; const char *iname = NULL, *oname = NULL; p_ply iply = NULL, oply = NULL; /* parse command line arguments */ parse_arguments(argc, argv, &storage_mode, &iname, &oname); /* open input file and make sure we parsed its header */ iply = ply_open(iname, NULL, 0, NULL); if (!iply) error("Unable to open file '%s'", iname); if (!ply_read_header(iply)) error("Failed reading '%s' header", iname); /* create output file */ oply = ply_create(oname, storage_mode, NULL, 0, NULL); if (!oply) error("Unable to create file '%s'", oname); /* create elements and properties in output file and * setup callbacks for them in input file */ setup_callbacks(iply, oply); /* pass comments and obj_infos from input to output */ value = NULL; while ((value = ply_get_next_comment(iply, value))) if (!ply_add_comment(oply, value)) error("Failed adding comments"); value = NULL; while ((value = ply_get_next_obj_info(iply, value))) if (!ply_add_obj_info(oply, value)) error("Failed adding comments"); /* write output header */ if (!ply_write_header(oply)) error("Failed writing '%s' header", oname); /* read input file generating callbacks that pass data to output file */ if (!ply_read(iply)) error("Conversion failed"); /* close up, we are done */ if (!ply_close(iply)) error("Error closing file '%s'", iname); if (!ply_close(oply)) error("Error closing file '%s'", oname); return 0; }
void PLYDataWriter::write_header(p_ply oply) { ply_add_element ( oply, "vertex", mesh->vertex_count() ); ply_add_scalar_property(oply, "x", PLY_FLOAT ); ply_add_scalar_property(oply, "y", PLY_FLOAT ); ply_add_scalar_property(oply, "z", PLY_FLOAT ); ply_add_element ( oply, "face", mesh->face_count() ); ply_add_list_property ( oply, "vertex_index", PLY_UCHAR, PLY_INT ); ply_write_header ( oply ); }
bool WritePlyFile(const std::string &filename, int nTriangles, const int *vertexIndices, int nVertices, const Point3f *P, const Vector3f *S, const Normal3f *N, const Point2f *UV) { p_ply plyFile = ply_create(filename.c_str(), PLY_DEFAULT, PlyErrorCallback, 0, nullptr); if (plyFile != nullptr) { ply_add_element(plyFile, "vertex", nVertices); ply_add_scalar_property(plyFile, "x", PLY_FLOAT); ply_add_scalar_property(plyFile, "y", PLY_FLOAT); ply_add_scalar_property(plyFile, "z", PLY_FLOAT); if (N != nullptr) { ply_add_scalar_property(plyFile, "nx", PLY_FLOAT); ply_add_scalar_property(plyFile, "ny", PLY_FLOAT); ply_add_scalar_property(plyFile, "nz", PLY_FLOAT); } if (UV != nullptr) { ply_add_scalar_property(plyFile, "u", PLY_FLOAT); ply_add_scalar_property(plyFile, "v", PLY_FLOAT); } if (S != nullptr) Warning("PLY mesh in \"%s\" will be missing tangent vectors \"S\".", filename.c_str()); ply_add_element(plyFile, "face", nTriangles); ply_add_list_property(plyFile, "vertex_indices", PLY_UINT8, PLY_INT); ply_write_header(plyFile); for (int i = 0; i < nVertices; ++i) { ply_write(plyFile, P[i].x); ply_write(plyFile, P[i].y); ply_write(plyFile, P[i].z); if (N) { ply_write(plyFile, N[i].x); ply_write(plyFile, N[i].y); ply_write(plyFile, N[i].z); } if (UV) { ply_write(plyFile, UV[i].x); ply_write(plyFile, UV[i].y); } } for (int i = 0; i < nTriangles; ++i) { ply_write(plyFile, 3); ply_write(plyFile, vertexIndices[3 * i]); ply_write(plyFile, vertexIndices[3 * i + 1]); ply_write(plyFile, vertexIndices[3 * i + 2]); } ply_close(plyFile); return true; } return false; }
void PlyWriter::done(PointTableRef table) { if (!ply_add_element(m_ply, "vertex", m_pointCollector->size())) { std::stringstream ss; ss << "Could not add vertex element"; throw pdal_error(ss.str()); } auto dimensions = table.layout()->dims(); for (auto dim : dimensions) { std::string name = Dimension::name(dim); e_ply_type plyType = getPlyType(Dimension::defaultType(dim)); if (!ply_add_scalar_property(m_ply, name.c_str(), plyType)) { std::stringstream ss; ss << "Could not add scalar property '" << name << "'"; throw pdal_error(ss.str()); } } if (!ply_add_comment(m_ply, "Generated by PDAL")) { std::stringstream ss; ss << "Could not add comment"; throw pdal_error(ss.str()); } if (!ply_write_header(m_ply)) { std::stringstream ss; ss << "Could not write ply header"; throw pdal_error(ss.str()); } for (PointId index = 0; index < m_pointCollector->size(); ++index) { for (auto dim : dimensions) { double value = m_pointCollector->getFieldAs<double>(dim, index); if (!ply_write(m_ply, value)) { std::stringstream ss; ss << "Error writing dimension '" << Dimension::name(dim) << "' of point number " << index; throw pdal_error(ss.str()); } } } if (!ply_close(m_ply)) { throw pdal_error("Error closing ply file"); } }
void write_ply(const std::string &filename, const MatrixXu &F, const MatrixXf &V, const MatrixXf &N, const MatrixXf &Nf, const MatrixXf &UV, const MatrixXf &C, const ProgressCallback &progress) { auto message_cb = [](p_ply ply, const char *msg) { cerr << "rply: " << msg << endl; }; Timer<> timer; cout << "Writing \"" << filename << "\" (V=" << V.cols() << ", F=" << F.cols() << ") .. "; cout.flush(); if (N.size() > 0 && Nf.size() > 0) throw std::runtime_error("Please specify either face or vertex normals but not both!"); p_ply ply = ply_create(filename.c_str(), PLY_DEFAULT, message_cb, 0, nullptr); if (!ply) throw std::runtime_error("Unable to write PLY file!"); ply_add_comment(ply, "Generated by Instant Meshes"); ply_add_element(ply, "vertex", V.cols()); ply_add_scalar_property(ply, "x", PLY_FLOAT); ply_add_scalar_property(ply, "y", PLY_FLOAT); ply_add_scalar_property(ply, "z", PLY_FLOAT); if (N.size() > 0) { ply_add_scalar_property(ply, "nx", PLY_FLOAT); ply_add_scalar_property(ply, "ny", PLY_FLOAT); ply_add_scalar_property(ply, "nz", PLY_FLOAT); if (N.cols() != V.cols() || N.rows() != 3) throw std::runtime_error("Vertex normal matrix has incorrect size"); } if (UV.size() > 0) { ply_add_scalar_property(ply, "u", PLY_FLOAT); ply_add_scalar_property(ply, "v", PLY_FLOAT); if (UV.cols() != V.cols() || UV.rows() != 2) throw std::runtime_error("Texture coordinate matrix has incorrect size"); } if (C.size() > 0) { ply_add_scalar_property(ply, "red", PLY_FLOAT); ply_add_scalar_property(ply, "green", PLY_FLOAT); ply_add_scalar_property(ply, "blue", PLY_FLOAT); if (C.cols() != V.cols() || (C.rows() != 3 && C.rows() != 4)) throw std::runtime_error("Color matrix has incorrect size"); } /* Check for irregular faces */ std::map<uint32_t, std::pair<uint32_t, std::map<uint32_t, uint32_t>>> irregular; size_t nIrregular = 0; if (F.rows() == 4) { for (uint32_t f=0; f<F.cols(); ++f) { if (F(2, f) == F(3, f)) { nIrregular++; auto &value = irregular[F(2, f)]; value.first = f; value.second[F(0, f)] = F(1, f); } } } ply_add_element(ply, "face", F.cols() - nIrregular + irregular.size()); ply_add_list_property(ply, "vertex_indices", PLY_UINT8, PLY_INT); if (Nf.size() > 0) { ply_add_scalar_property(ply, "nx", PLY_FLOAT); ply_add_scalar_property(ply, "ny", PLY_FLOAT); ply_add_scalar_property(ply, "nz", PLY_FLOAT); if (Nf.cols() != F.cols() || Nf.rows() != 3) throw std::runtime_error("Face normal matrix has incorrect size"); } ply_write_header(ply); for (uint32_t j=0; j<V.cols(); ++j) { for (uint32_t i=0; i<V.rows(); ++i) ply_write(ply, V(i, j)); if (N.size() > 0) { for (uint32_t i=0; i<N.rows(); ++i) ply_write(ply, N(i, j)); } if (UV.size() > 0) { for (uint32_t i=0; i<UV.rows(); ++i) ply_write(ply, UV(i, j)); } if (C.size() > 0) { for (uint32_t i=0; i<std::min(3u, (uint32_t) C.rows()); ++i) ply_write(ply, C(i, j)); } if (progress && j % 500000 == 0) progress("Writing vertex data", j / (Float) V.cols()); } for (uint32_t f=0; f<F.cols(); ++f) { if (F.rows() == 4 && F(2, f) == F(3, f)) continue; ply_write(ply, F.rows()); for (uint32_t i=0; i<F.rows(); ++i) ply_write(ply, F(i, f)); if (Nf.size() > 0) { for (uint32_t i=0; i<Nf.rows(); ++i) ply_write(ply, Nf(i, f)); } if (progress && f % 500000 == 0) progress("Writing face data", f / (Float) F.cols()); } for (auto item : irregular) { auto face = item.second; uint32_t v = face.second.begin()->first, first = v; ply_write(ply, face.second.size()); while (true) { ply_write(ply, v); v = face.second[v]; if (v == first) break; } if (Nf.size() > 0) { for (uint32_t i=0; i<Nf.rows(); ++i) ply_write(ply, Nf(i, face.first)); } } ply_close(ply); cout << "done. ("; if (irregular.size() > 0) cout << irregular.size() << " irregular faces, "; cout << "took " << timeString(timer.value()) << ")" << endl; }
bool save(const std::string& filename) { if(map_ == nil) { Logger::err("PlyMeshSave") << "mesh is null" << std::endl ; return false ; } p_ply ply = ply_create(filename.c_str(), PLY_LITTLE_ENDIAN, nil, 0, nil) ; if(ply == nil) { Logger::err("PlyMeshSave") << filename << ": could not open" << std::endl ; return false ; } ////////////////////////////////////////////////////////////////////////// if (!ply_add_comment(ply, "saved by [email protected]")) { Logger::err("PlyMeshSave") << "unable to add comment" << std::endl ; ply_close(ply) ; return false ; } int num_v = map_->size_of_vertices(); if (!ply_add_element(ply, "vertex", num_v)) { Logger::err("PlyMeshSave") << "unable to add element \'vertex\'" << std::endl ; ply_close(ply) ; return false ; } e_ply_type length_type, value_type; length_type = value_type = static_cast<e_ply_type>(-1); std::string pos[3] = { "x", "y", "z" }; for (unsigned int i=0; i<3; ++i) { if (!ply_add_property(ply, pos[i].c_str(), PLY_FLOAT, length_type, value_type)) { Logger::err("PlyMeshSave") << "unable to add property \'" << pos[i] << "\'" << std::endl ; ply_close(ply) ; return false ; } } MapVertexAttribute<Color> vertex_color; vertex_color.bind_if_defined(const_cast<Map*>(map_), "color") ; if (vertex_color.is_bound()) { std::string color[4] = { "red", "green", "blue", "alpha" }; for (unsigned int i=0; i<4; ++i) { if (!ply_add_property(ply, color[i].c_str(), PLY_UCHAR, length_type, value_type)) { Logger::err("PlyMeshSave") << "unable to add property \'" << color[i] << "\'" << std::endl ; ply_close(ply) ; return false ; } } } int num_f = map_->size_of_facets(); if (!ply_add_element(ply, "face", num_f)) { Logger::err("PlyMeshSave") << "unable to add element \'face\'" << std::endl ; ply_close(ply) ; return false ; } if (!ply_add_property(ply, "vertex_indices", PLY_LIST, PLY_UCHAR, PLY_INT)) { Logger::err("PlyMeshSave") << "unable to add property \'vertex_indices\'" << std::endl ; ply_close(ply) ; return false ; } if(!ply_write_header(ply)) { Logger::err("PlyMeshSave") << filename << ": invalid PLY file" << std::endl ; ply_close(ply) ; return false ; } ////////////////////////////////////////////////////////////////////////// FOR_EACH_VERTEX_CONST(Map, map_, it) { const vec3& p = it->point(); ply_write(ply, p.x); ply_write(ply, p.y); ply_write(ply, p.z); if (vertex_color.is_bound()) { const Color& c = vertex_color[it]; double r = c.r() * color_mult_; ogf_clamp(r, 0.0, 255.0); double g = c.g() * color_mult_; ogf_clamp(g, 0.0, 255.0); double b = c.b() * color_mult_; ogf_clamp(b, 0.0, 255.0); double a = c.a() * color_mult_; ogf_clamp(a, 0.0, 255.0); ply_write(ply, r); ply_write(ply, g); ply_write(ply, b); ply_write(ply, a); } } // ply files numbering starts with 0 Attribute<Map::Vertex, int> vertex_id(map_->vertex_attribute_manager()); MapEnumerator::enumerate_vertices(const_cast<Map*>(map_), vertex_id, 0); FOR_EACH_FACET_CONST(Map, map_, it) { ply_write(ply, it->nb_vertices()); Map::Halfedge* h = it->halfedge(); do { int id = vertex_id[h->vertex()]; ply_write(ply, id); h = h->next(); } while (h != it->halfedge()); }
/******************************************************************************* * Name: main * Description: ******************************************************************************/ int main( void ) { int i; /* Create new PLY file. */ p_ply oply = ply_create( "new.ply", PLY_ASCII, NULL, 0, NULL ); if ( !oply ) { fprintf( stderr, "ERROR: Could not create »new.ply«\n" ); return EXIT_FAILURE; } /* Add object information to PLY. */ if ( !ply_add_obj_info( oply, "This is just a test." ) ) { fprintf( stderr, "ERROR: Could not add object info.\n" ); return EXIT_FAILURE; } /* Add a comment, too. */ if ( !ply_add_comment( oply, "Just some comment…" ) ) { fprintf( stderr, "ERROR: Could not add comment.\n" ); return EXIT_FAILURE; } /* Add vertex element. We want to add 9999 vertices. */ if ( !ply_add_element( oply, "vertex", 99999 ) ) { fprintf( stderr, "ERROR: Could not add element.\n" ); return EXIT_FAILURE; } /* Add vertex properties: x, y, z, r, g, b */ if ( !ply_add_property( oply, "x", PLY_FLOAT, 0, 0 ) ) { fprintf( stderr, "ERROR: Could not add property x.\n" ); return EXIT_FAILURE; } if ( !ply_add_property( oply, "y", PLY_FLOAT, 0, 0 ) ) { fprintf( stderr, "ERROR: Could not add property x.\n" ); return EXIT_FAILURE; } if ( !ply_add_property( oply, "z", PLY_FLOAT, 0, 0 ) ) { fprintf( stderr, "ERROR: Could not add property x.\n" ); return EXIT_FAILURE; } if ( !ply_add_property( oply, "red", PLY_UCHAR, 0, 0 ) ) { fprintf( stderr, "ERROR: Could not add property x.\n" ); return EXIT_FAILURE; } if ( !ply_add_property( oply, "green", PLY_UCHAR, 0, 0 ) ) { fprintf( stderr, "ERROR: Could not add property x.\n" ); return EXIT_FAILURE; } if ( !ply_add_property( oply, "blue", PLY_UCHAR, 0, 0 ) ) { fprintf( stderr, "ERROR: Could not add property x.\n" ); return EXIT_FAILURE; } /* Write header to file */ if ( !ply_write_header( oply ) ) { fprintf( stderr, "ERROR: Could not write header.\n" ); return EXIT_FAILURE; } /* Now we generate random data to add to the file: */ srand ( time( NULL ) ); for ( i = 0; i < 99999; i++ ) { ply_write( oply, (double) ( rand() % 10000 ) / 10.0 ); /* x */ ply_write( oply, (double) ( rand() % 10000 ) / 10.0 ); /* y */ ply_write( oply, (double) ( rand() % 10000 ) / 10.0 ); /* z */ ply_write( oply, rand() % 256 ); /* red */ ply_write( oply, rand() % 256 ); /* blue */ ply_write( oply, rand() % 256 ); /* green */ } if ( !ply_close( oply ) ) { fprintf( stderr, "ERROR: Could not close file.\n" ); return EXIT_FAILURE; } return EXIT_SUCCESS; }