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; }
int MapSerializer_ply::num_facet(const std::string& file_name) { p_ply ply = ply_open(file_name.c_str(), nil, 0, nil) ; if(ply == nil) { Logger::err("MapSerializer_ply") << file_name << ": could not open" << std::endl ; return false ; } if(!ply_read_header(ply)) { Logger::err("MapSerializer_ply") << file_name << ": invalid PLY file" << std::endl ; ply_close(ply) ; return false ; } p_ply_element element = nil ; for(;;) { element = ply_get_next_element(ply, element) ; if(element == nil) break ; const char* elt_name = nil ; long num; ply_get_element_info(element, &elt_name, &num) ; if(!strcmp(elt_name, "face")) { if (num > 0) { ply_close(ply) ; return num; } } } ply_close(ply) ; 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; }
bool load(const std::string& filename) { p_ply ply = ply_open(filename.c_str(), nil, 0, nil) ; if(ply == nil) { Logger::err("PlyMeshLoad") << filename << ": could not open" << std::endl ; return false ; } if(!ply_read_header(ply)) { Logger::err("PlyMeshLoad") << filename << ": invalid PLY file" << std::endl ; ply_close(ply) ; return false ; } current_vertex_ = 0 ; current_color_ = 0 ; check_for_colors(ply) ; long nvertices = ply_set_read_cb(ply, "vertex", "x", PlyMeshLoad::vertex_cb, this, 0) ; ply_set_read_cb(ply, "vertex", "y", PlyMeshLoad::vertex_cb, this, 1) ; ply_set_read_cb(ply, "vertex", "z", PlyMeshLoad::vertex_cb, this, 2) ; long nfaces = ply_set_read_cb(ply, "face", "vertex_indices", PlyMeshLoad::face_cb, this, 0); if (nfaces == 0) { Logger::err("PlyMeshLoad") << "0 facet, maybe a point cloud file" << std::endl ; ply_close(ply) ; return false ; } ply_set_read_cb(ply, "tristrips", "vertex_indices", PlyMeshLoad::tristrip_cb, this, 0); builder_.begin_surface() ; builder_.create_vertices(nvertices, has_colors_) ; if(!ply_read(ply)) { Logger::err("PlyMeshLoad") << filename << ": problem occurred while parsing PLY file" << std::endl ; ply_close(ply) ; builder_.end_surface() ; return false ; } ply_close(ply) ; builder_.end_surface() ; if (nfaces == 0) return false; else return true ; }
int loadPlyFile() { p_ply ply = ply_open(filename, NULL, 0, NULL); if (!ply) return -1; if (!ply_read_header(ply)) return -1; vertex_count = ply_set_read_cb(ply, "vertex", "x", vertex_cb, NULL, 0); ply_set_read_cb(ply, "vertex", "y", vertex_cb, NULL, 1); ply_set_read_cb(ply, "vertex", "z", vertex_cb, NULL, 2); ply_set_read_cb(ply, "vertex", "nx", NULL, NULL, 0); ply_set_read_cb(ply, "vertex", "ny", NULL, NULL, 0); ply_set_read_cb(ply, "vertex", "nz", NULL, NULL, 0); face_count = ply_set_read_cb(ply, "face", "vertex_indices", face_cb, NULL, 0); vertices = (double **) malloc(vertex_count * sizeof(double *)); faces = (int **) malloc(face_count * sizeof(int *)); if (!ply_read(ply)) return -1; ply_close(ply); return 1; }
int Model::init(char filename[]){ p_ply ply = ply_open(filename, NULL, 0, NULL); if (!ply) return 1; if (!ply_read_header(ply)) return 1; nvertices = ply_set_read_cb(ply, "vertex", "x", vertex_cb, NULL, 0); ply_set_read_cb(ply, "vertex", "y", vertex_cb, NULL, 0); ply_set_read_cb(ply, "vertex", "z", vertex_cb, NULL, 1); ntriangles = ply_set_read_cb(ply, "face", "vertex_indices", face_cb, NULL, 0); count_t = 0; count_v = 0; if(vertices != NULL){ delete [] vertices; } if(triangles != NULL){ delete [] triangles; } if(nml != NULL){ delete [] nml; } vertices = new vertex[nvertices]; triangles = new triangle[ntriangles]; nml = new normal[ntriangles]; if (!ply_read(ply)) return 1; ply_close(ply); return 0; }
void MeshBase::loadDataFromPly( const std::string& filename ) { p_ply ply = ply_open( filename.c_str(), 0); if( !ply ) { throw MeshException( "Error opening ply file during second pass (" + filename + ")" ); } if( !ply_read_header( ply ) ) { throw MeshException( "Error parsing ply header during second pass (" + filename + ")" ); } MeshGroup& group = getFirstGroup(); PlyData data( m_vertex_data, m_normal_data, group.vertex_indices, group.normal_indices ); ply_set_read_cb( ply, "vertex", "x", plyVertexLoadDataCB, &data, 0); ply_set_read_cb( ply, "vertex", "y", plyVertexLoadDataCB, &data, 1); ply_set_read_cb( ply, "vertex", "z", plyVertexLoadDataCB, &data, 2); ply_set_read_cb( ply, "vertex", "nx", plyVertexLoadDataCB, &data, 3); ply_set_read_cb( ply, "vertex", "ny", plyVertexLoadDataCB, &data, 4); ply_set_read_cb( ply, "vertex", "nz", plyVertexLoadDataCB, &data, 5); ply_set_read_cb( ply, "face", "vertex_indices", plyFaceLoadDataCB, &data, 0); if( !ply_read( ply ) ) { throw MeshException( "Error parsing ply file (" + filename + ")" ); } ply_close(ply); }
void parse_ply(const std::string& filename, PLYParser* parser) { p_ply ply = ply_open(filename.c_str(), NULL, 0, NULL); assert_success(ply != NULL); assert_success(ply_read_header(ply)); const char* elem_name; const char* prop_name; long num_elements; p_ply_element element = ply_get_next_element(ply, NULL); while (element != NULL) { assert_success(ply_get_element_info(element, &elem_name, &num_elements)); p_ply_property property = ply_get_next_property(element, NULL); while (property != NULL) { assert_success(ply_get_property_info(property, &prop_name, NULL, NULL, NULL)); ply_set_read_cb(ply, elem_name, prop_name, ply_parser_call_back, parser, 0); parser->add_property(elem_name, prop_name, num_elements); property = ply_get_next_property(element, property); } element = ply_get_next_element(ply, element); } assert_success(ply_read(ply)); ply_close(ply); }
write_test() { int i,j; PlyFile *ply; int nelems; char **elist; int file_type; float version; int nverts = sizeof (verts) / sizeof (Vertex); int nfaces = sizeof (faces) / sizeof (Face); /* create the vertex index lists for the faces */ for (i = 0; i < nfaces; i++) faces[i].verts = vert_ptrs[i]; /* open either a binary or ascii PLY file for writing */ /* (the file will be called "test.ply" because the routines */ /* enforce the .ply filename extension) */ #if 1 ply = ply_open_for_writing("test", 2, elem_names, PLY_ASCII, &version); #else ply = ply_open_for_writing("test", 2, elem_names, PLY_BINARY_BE, &version); #endif /* describe what properties go into the vertex and face elements */ ply_element_count (ply, "vertex", nverts); ply_describe_property (ply, "vertex", &vert_props[0]); ply_describe_property (ply, "vertex", &vert_props[1]); ply_describe_property (ply, "vertex", &vert_props[2]); ply_element_count (ply, "face", nfaces); ply_describe_property (ply, "face", &face_props[0]); ply_describe_property (ply, "face", &face_props[1]); /* write a comment and an object information field */ ply_put_comment (ply, "author: Greg Turk"); ply_put_obj_info (ply, "random information"); /* we have described exactly what we will put in the file, so */ /* we are now done with the header info */ ply_header_complete (ply); /* set up and write the vertex elements */ ply_put_element_setup (ply, "vertex"); for (i = 0; i < nverts; i++) ply_put_element (ply, (void *) &verts[i]); /* set up and write the face elements */ ply_put_element_setup (ply, "face"); for (i = 0; i < nfaces; i++) ply_put_element (ply, (void *) &faces[i]); /* close the PLY file */ ply_close (ply); }
void PlyReader::done(PointTableRef table) { if (!ply_close(m_ply)) { std::stringstream ss; ss << "Error closing " << m_filename << "."; throw pdal_error(ss.str()); } }
void write_file() { int i,j,k; PlyFile *ply; int num_elems; char *elem_name; /*** Write out the final PLY object ***/ ply = ply_write (stdout, nelems, elist, file_type); /* describe what properties go into the vertex and face elements */ ply_element_count (ply, "vertex", nverts); ply_describe_property (ply, "vertex", &vert_props[0]); ply_describe_property (ply, "vertex", &vert_props[1]); ply_describe_property (ply, "vertex", &vert_props[2]); ply_describe_property (ply, "vertex", &vert_props[3]); ply_describe_property (ply, "vertex", &vert_props[4]); ply_describe_property (ply, "vertex", &vert_props[5]); ply_describe_other_properties (ply, vert_other, offsetof(Vertex,other_props)); ply_element_count (ply, "face", nfaces); ply_describe_property (ply, "face", &face_props[0]); ply_describe_other_properties (ply, face_other, offsetof(Face,other_props)); ply_describe_other_elements (ply, other_elements); for (i = 0; i < num_comments; i++) ply_put_comment (ply, comments[i]); for (i = 0; i < num_obj_info; i++) ply_put_obj_info (ply, obj_info[i]); ply_header_complete (ply); /* set up and write the vertex elements */ ply_put_element_setup (ply, "vertex"); for (i = 0; i < nverts; i++) ply_put_element (ply, (void *) vlist[i]); /* set up and write the face elements */ ply_put_element_setup (ply, "face"); for (i = 0; i < nfaces; i++) ply_put_element (ply, (void *) flist[i]); ply_put_other_elements (ply); /* close the PLY file */ ply_close (ply); }
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 PlyReader::initialize() { p_ply ply = openPly(m_filename); p_ply_element vertex_element = nullptr; bool found_vertex_element = false; const char* element_name; long element_count; while ((vertex_element = ply_get_next_element(ply, vertex_element))) { if (!ply_get_element_info(vertex_element, &element_name, &element_count)) { std::stringstream ss; ss << "Error reading element info in " << m_filename << "."; throw pdal_error(ss.str()); } if (strcmp(element_name, "vertex") == 0) { found_vertex_element = true; break; } } if (!found_vertex_element) { std::stringstream ss; ss << "File " << m_filename << " does not contain a vertex element."; throw pdal_error(ss.str()); } p_ply_property property = nullptr; while ((property = ply_get_next_property(vertex_element, property))) { const char* name; e_ply_type type; e_ply_type length_type; e_ply_type value_type; if (!ply_get_property_info(property, &name, &type, &length_type, &value_type)) { std::stringstream ss; ss << "Error reading property info in " << m_filename << "."; throw pdal_error(ss.str()); } // For now, we'll just use PDAL's built in dimension matching. // We could be smarter about this, e.g. by using the length // and value type attributes. Dimension::Id::Enum dim = Dimension::id(name); if (dim != Dimension::Id::Unknown) { m_vertexDimensions[name] = dim; } } ply_close(ply); }
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"); } }
PlyReader::~PlyReader() { if (isValid()) { for (int i=0; i < m_data->elementCount; ++i) { free(m_data->elementNames[i]); } free(m_data->elementNames); ply_close(m_data->plyFile); m_data->plyFile = nullptr; } }
int main(void) { long nvertices, ntriangles; p_ply ply = ply_open("input.ply", NULL); if (!ply) return 1; if (!ply_read_header(ply)) return 1; nvertices = ply_set_read_cb(ply, "vertex", "x", vertex_cb, NULL, 0); ply_set_read_cb(ply, "vertex", "y", vertex_cb, NULL, 0); ply_set_read_cb(ply, "vertex", "z", vertex_cb, NULL, 1); ntriangles = ply_set_read_cb(ply, "face", "vertex_indices", face_cb, NULL, 0); printf("%ld\n%ld\n", nvertices, ntriangles); if (!ply_read(ply)) return 1; ply_close(ply); return 0; }
void PLYDataWriter::write ( const char * filename ) { assert ( mesh != NULL ); p_ply oply; oply = ply_create( filename, PLY_ASCII, NULL, 0, NULL ); if ( oply == NULL ) { throw std::runtime_error( "Access to output file was impossible." ); } write_header ( oply ); write_vertices ( oply ); write_faces ( oply ); ply_close ( oply ); }
bool PlyBuffer::LoadFromPlyFile(std::wstring fileName, PlyBuffer& vbOut, std::wstring error) { long nvertices, ntriangles; // Open the file p_ply ply = ply_open(Helper::WStringtoString(fileName).c_str(), NULL, 0, NULL); // Check that file is okay if (!ply) { error = L"Failed at loading file " + fileName; return false; } if (!ply_read_header(ply)) return false; // Load info nvertices = ply_set_read_cb(ply, "vertex", "x", vertexX, NULL, 0); ply_set_read_cb(ply, "vertex", "y", vertexY, NULL, 0); ply_set_read_cb(ply, "vertex", "z", vertexZ, NULL, 0); ply_set_read_cb(ply, "vertex", "nx", vertexNX, NULL, 0); ply_set_read_cb(ply, "vertex", "ny", vertexNY, NULL, 0); ply_set_read_cb(ply, "vertex", "nz", vertexNZ, NULL, 0); ply_set_read_cb(ply, "vertex", "u", vertexU, NULL, 0); ply_set_read_cb(ply, "vertex", "v", vertexV, NULL, 1); ntriangles = ply_set_read_cb(ply, "face", "vertex_indices", face_cb, NULL, 0); // Set space for vertices and indices for speed buffer.vertices.reserve(nvertices); buffer.indices.reserve(ntriangles); // Read file if (!ply_read(ply)) return false; // Close file ply_close(ply); //Copy it to the output vbOut = buffer; // Empty the vertex so that don't take up space buffer.vertices = std::vector<PlyBuffer::Vertex>(); buffer.indices = std::vector<WORD>(); return true; }
int MyGlWindow::loadply() { p_ply ply = ply_open("roof.ply", NULL, 0, NULL); if (!ply) return 1; if (!ply_read_header(ply)) return 1; int nvertices = ply_set_read_cb(ply, "vertex", "x", vertex_cb, NULL, 0); ply_set_read_cb(ply, "vertex", "y", vertex_cb, NULL, 0); ply_set_read_cb(ply, "vertex", "z", vertex_cb, NULL, 1); int ntriangles = ply_set_read_cb(ply, "face", "vertex_indices", face_cb, NULL, 0); printf("%ld\n%ld\n", nvertices, ntriangles); if (!ply_read(ply)) return 1; ply_close(ply); std::cout << m_points.size() << std::endl; }
void PlyLoader::load( const optix::Matrix4x4& transform ) { p_ply ply = ply_open( _filename.c_str(), 0); if( !ply ) { throw optix::Exception( "Error opening ply file (" + _filename + ")" ); } if( !ply_read_header( ply ) ) { throw optix::Exception( "Error parsing ply header (" + _filename + ")" ); } ModelData data; int nverts = ply_set_read_cb( ply, "vertex", "x", vertexCB, &data, 0); ply_set_read_cb( ply, "vertex", "y", vertexCB, &data, 1); ply_set_read_cb( ply, "vertex", "z", vertexCB, &data, 2); int ntris = ply_set_read_cb(ply, "face", "vertex_indices", faceCB, &data, 0); data.verts = new optix::float3[ nverts ]; data.tris = new optix::int3[ ntris ]; if( !ply_read( ply ) ) { throw optix::Exception( "Error parsing ply file (" + _filename + ")" ); } ply_close(ply); _aabb = data.aabb; /* std::cerr << " done. got " << nverts << " verts and " << ntris << " tris." << std::endl; for( int i = 0; i < 10; ++i ) { std::cerr << " v: " << data.verts[i] << std::endl; } for( int i = 0; i < 10; ++i ) { std::cerr << " f: " << data.tris[i] << std::endl; } */ createGeometryInstance( data.nverts, data.verts, data.ntris, data.tris ); }
MEM_SmartPtr<BSP_TMesh> BSP_PlyLoader:: NewMeshFromFile( char * file_name, MT_Vector3 &min, MT_Vector3 &max ) { min = MT_Vector3(MT_INFINITY,MT_INFINITY,MT_INFINITY); max = MT_Vector3(-MT_INFINITY,-MT_INFINITY,-MT_INFINITY); PlyProperty vert_props[] = { /* list of property information for a vertex */ {"x", PLY_FLOAT, PLY_FLOAT, offsetof(LoadVertex,x), 0, 0, 0, 0}, {"y", PLY_FLOAT, PLY_FLOAT, offsetof(LoadVertex,y), 0, 0, 0, 0}, {"z", PLY_FLOAT, PLY_FLOAT, offsetof(LoadVertex,z), 0, 0, 0, 0}, }; PlyProperty face_props[] = { /* list of property information for a vertex */ {"vertex_indices", PLY_INT, PLY_INT, offsetof(LoadFace,verts), 1, PLY_UCHAR, PLY_UCHAR, offsetof(LoadFace,nverts)}, }; MEM_SmartPtr<BSP_TMesh> mesh = new BSP_TMesh; if (mesh == NULL) return NULL; int i,j; PlyFile *ply; int nelems; char **elist; int file_type; float version; int nprops; int num_elems; PlyProperty **plist; char *elem_name; LoadVertex load_vertex; LoadFace load_face; /* open a PLY file for reading */ ply = ply_open_for_reading( file_name, &nelems, &elist, &file_type, &version ); if (ply == NULL) return NULL; /* go through each kind of element that we learned is in the file */ /* and read them */ for (i = 0; i < nelems; i++) { /* get the description of the first element */ elem_name = elist[i]; plist = ply_get_element_description (ply, elem_name, &num_elems, &nprops); /* print the name of the element, for debugging */ /* if we're on vertex elements, read them in */ if (equal_strings ("vertex", elem_name)) { /* set up for getting vertex elements */ ply_get_property (ply, elem_name, &vert_props[0]); ply_get_property (ply, elem_name, &vert_props[1]); ply_get_property (ply, elem_name, &vert_props[2]); // make some memory for the vertices mesh->VertexSet().reserve(num_elems); /* grab all the vertex elements */ for (j = 0; j < num_elems; j++) { /* grab and element from the file */ ply_get_element (ply, (void *)&load_vertex); // pass the vertex into the mesh builder. if (load_vertex.x < min.x()) { min.x() = load_vertex.x; } else if (load_vertex.x > max.x()) { max.x()= load_vertex.x; } if (load_vertex.y < min.y()) { min.y() = load_vertex.y; } else if (load_vertex.y > max.y()) { max.y()= load_vertex.y; } if (load_vertex.z < min.z()) { min.z() = load_vertex.z; } else if (load_vertex.z > max.z()) { max.z()= load_vertex.z; } BSP_TVertex my_vert; my_vert.m_pos = MT_Vector3(load_vertex.x,load_vertex.y,load_vertex.z); mesh->VertexSet().push_back(my_vert); } } /* if we're on face elements, read them in */ if (equal_strings ("face", elem_name)) { /* set up for getting face elements */ ply_get_property (ply, elem_name, &face_props[0]); /* grab all the face elements */ for (j = 0; j < num_elems; j++) { ply_get_element (ply, (void *)&load_face); int v; for (v = 2; v< load_face.nverts; v++) { BSP_TFace f; f.m_verts[0] = load_face.verts[0]; f.m_verts[1] = load_face.verts[v-1]; f.m_verts[2] = load_face.verts[v]; mesh->BuildNormal(f); mesh->FaceSet().push_back(f); } // free up the memory this pile of shit used to allocate the polygon's vertices free (load_face.verts); } } } /* close the PLY file */ ply_close (ply); return mesh; }
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; }
void load_ply(const std::string &filename, MatrixXu &F, MatrixXf &V, bool load_faces, const ProgressCallback &progress) { auto message_cb = [](p_ply ply, const char *msg) { cerr << "rply: " << msg << endl; }; Timer<> timer; cout << "Loading \"" << filename << "\" .. "; cout.flush(); p_ply ply = ply_open(filename.c_str(), message_cb, 0, nullptr); if (!ply) throw std::runtime_error("Unable to open PLY file \"" + filename + "\"!"); if (!ply_read_header(ply)) { ply_close(ply); throw std::runtime_error("Unable to open PLY header of \"" + filename + "\"!"); } p_ply_element element = nullptr; uint32_t vertexCount = 0, faceCount = 0; /* Inspect the structure of the PLY file */ while ((element = ply_get_next_element(ply, element)) != nullptr) { const char *name; long nInstances; ply_get_element_info(element, &name, &nInstances); if (!strcmp(name, "vertex")) vertexCount = (uint32_t) nInstances; else if (!strcmp(name, "face")) faceCount = (uint32_t) nInstances; } if (vertexCount == 0 && faceCount == 0) throw std::runtime_error("PLY file \"" + filename + "\" is invalid! No face/vertex/elements found!"); if (load_faces) F.resize(3, faceCount); V.resize(3, vertexCount); struct VertexCallbackData { MatrixXf &V; const ProgressCallback &progress; VertexCallbackData(MatrixXf &V, const ProgressCallback &progress) : V(V), progress(progress) {} }; struct FaceCallbackData { MatrixXu &F; const ProgressCallback &progress; FaceCallbackData(MatrixXu &F, const ProgressCallback &progress) : F(F), progress(progress) {} }; auto rply_vertex_cb = [](p_ply_argument argument) -> int { VertexCallbackData *data; long index, coord; ply_get_argument_user_data(argument, (void **) &data, &coord); ply_get_argument_element(argument, nullptr, &index); data->V(coord, index) = (Float) ply_get_argument_value(argument); if (data->progress && coord == 0 && index % 500000 == 0) data->progress("Loading vertex data", index / (Float) data->V.cols()); return 1; }; auto rply_index_cb = [](p_ply_argument argument) -> int { FaceCallbackData *data; long length, value_index, index; ply_get_argument_property(argument, nullptr, &length, &value_index); if (length != 3) throw std::runtime_error("Only triangle faces are supported!"); ply_get_argument_user_data(argument, (void **) &data, nullptr); ply_get_argument_element(argument, nullptr, &index); if (value_index >= 0) data->F(value_index, index) = (uint32_t) ply_get_argument_value(argument); if (data->progress && value_index == 0 && index % 500000 == 0) data->progress("Loading face data", index / (Float) data->F.cols()); return 1; }; VertexCallbackData vcbData(V, progress); FaceCallbackData fcbData(F, progress); if (!ply_set_read_cb(ply, "vertex", "x", rply_vertex_cb, &vcbData, 0) || !ply_set_read_cb(ply, "vertex", "y", rply_vertex_cb, &vcbData, 1) || !ply_set_read_cb(ply, "vertex", "z", rply_vertex_cb, &vcbData, 2)) { ply_close(ply); throw std::runtime_error("PLY file \"" + filename + "\" does not contain vertex position data!"); } if (load_faces) { if (!ply_set_read_cb(ply, "face", "vertex_indices", rply_index_cb, &fcbData, 0)) { ply_close(ply); throw std::runtime_error("PLY file \"" + filename + "\" does not contain vertex indices!"); } } if (!ply_read(ply)) { ply_close(ply); throw std::runtime_error("Error while loading PLY data from \"" + filename + "\"!"); } ply_close(ply); cout << "done. (V=" << vertexCount; if (load_faces) cout << ", F=" << faceCount; cout << ", took " << timeString(timer.value()) << ")" << endl; }
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<(size_t)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<(size_t)F.rows();i++) { flist[i].nverts = F.cols(); flist[i].verts = new int[F.cols()]; for(size_t c = 0;c<(size_t)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); int native_binary_type = get_native_binary_type2(); ply_put_element_setup(ply, "vertex"); for(const auto v : vlist) { ply_put_element(ply, (void *) &v, &native_binary_type); } ply_put_element_setup(ply, "face"); for(const auto f : flist) { ply_put_element(ply, (void *) &f, &native_binary_type); } ply_close(ply); for(size_t i = 0;i<(size_t)F.rows();i++) { delete[] flist[i].verts; } return true; }
void read_file(FILE *inFile) { int i,j,k; PlyFile *ply; int nprops; int num_elems; PlyProperty **plist; char *elem_name; float version; int get_nx,get_ny,get_nz; /*** Read in the original PLY object ***/ ply = ply_read (inFile, &nelems, &elist); ply_get_info (ply, &version, &file_type); for (i = 0; i < nelems; i++) { /* get the description of the first element */ elem_name = elist[i]; plist = ply_get_element_description (ply, elem_name, &num_elems, &nprops); if (equal_strings ("vertex", elem_name)) { /* see if vertex holds any normal information */ get_nx = get_ny = get_nz = 0; for (j = 0; j < nprops; j++) { if (equal_strings ("nx", plist[j]->name)) get_nx = 1; if (equal_strings ("ny", plist[j]->name)) get_ny = 1; if (equal_strings ("nz", plist[j]->name)) get_nz = 1; } /* create a vertex list to hold all the vertices */ vlist = (Vertex **) malloc (sizeof (Vertex *) * num_elems); nverts = num_elems; /* set up for getting vertex elements */ ply_get_property (ply, elem_name, &vert_props[0]); ply_get_property (ply, elem_name, &vert_props[1]); ply_get_property (ply, elem_name, &vert_props[2]); if (get_nx) ply_get_property (ply, elem_name, &vert_props[3]); if (get_ny) ply_get_property (ply, elem_name, &vert_props[4]); if (get_nz) ply_get_property (ply, elem_name, &vert_props[5]); vert_other = ply_get_other_properties (ply, elem_name, offsetof(Vertex,other_props)); /* grab all the vertex elements */ for (j = 0; j < num_elems; j++) { vlist[j] = (Vertex *) malloc (sizeof (Vertex)); ply_get_element (ply, (void *) vlist[j]); } } else if (equal_strings ("face", elem_name)) { /* create a list to hold all the face elements */ flist = (Face **) malloc (sizeof (Face *) * num_elems); nfaces = num_elems; /* set up for getting face elements */ ply_get_property (ply, elem_name, &face_props[0]); face_other = ply_get_other_properties (ply, elem_name, offsetof(Face,other_props)); /* grab all the face elements */ for (j = 0; j < num_elems; j++) { flist[j] = (Face *) malloc (sizeof (Face)); ply_get_element (ply, (void *) flist[j]); } } else other_elements = ply_get_other_element (ply, elem_name, num_elems); } comments = ply_get_comments (ply, &num_comments); obj_info = ply_get_obj_info (ply, &num_obj_info); ply_close (ply); }
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; }
Geometry::Geometry(const string &fileName) { p_ply plyfile = ply_open(fileName.c_str(), NULL); if (!plyfile) { stringstream ss; ss << "Unable to read PLY mesh file '" << fileName << "'"; throw runtime_error(ss.str()); } if (!ply_read_header(plyfile)) { stringstream ss; ss << "Unable to read PLY header from '" << fileName << "'"; throw runtime_error(ss.str()); } Point *p; long plyNbVerts = ply_set_read_cb(plyfile, "vertex", "x", VertexCB, &p, 0); ply_set_read_cb(plyfile, "vertex", "y", VertexCB, &p, 1); ply_set_read_cb(plyfile, "vertex", "z", VertexCB, &p, 2); if (plyNbVerts <= 0) { stringstream ss; ss << "No vertices found in '" << fileName << "'"; throw runtime_error(ss.str()); } Triangle *vi; long plyNbTris = ply_set_read_cb(plyfile, "face", "vertex_indices", FaceCB, &vi, 0); if (plyNbTris <= 0) { stringstream ss; ss << "No triangles found in '" << fileName << "'"; throw runtime_error(ss.str()); } Normal *n; long plyNbNormals = ply_set_read_cb(plyfile, "vertex", "nx", NormalCB, &n, 0); ply_set_read_cb(plyfile, "vertex", "ny", NormalCB, &n, 1); ply_set_read_cb(plyfile, "vertex", "nz", NormalCB, &n, 2); if ((plyNbNormals > 0) && (plyNbNormals != plyNbVerts)) { stringstream ss; ss << "Wrong count of normals in '" << fileName << "'"; throw runtime_error(ss.str()); } RGB *c; long plyNbColors = ply_set_read_cb(plyfile, "vertex", "red", ColorCB, &c, 0); ply_set_read_cb(plyfile, "vertex", "green", ColorCB, &c, 1); ply_set_read_cb(plyfile, "vertex", "blue", ColorCB, &c, 2); if ((plyNbColors <= 0) || ((plyNbColors > 0) && (plyNbColors != plyNbVerts))) { stringstream ss; ss << "Wrong count of colors in '" << fileName << "'"; throw runtime_error(ss.str()); } p = new Point[plyNbVerts]; vi = new Triangle[plyNbTris]; c = new RGB[plyNbColors]; n = new Normal[plyNbVerts]; if (!ply_read(plyfile)) { stringstream ss; ss << "Unable to parse PLY file '" << fileName << "'"; delete[] p; delete[] vi; delete[] c; delete[] n; throw runtime_error(ss.str()); } ply_close(plyfile); vertexCount = plyNbVerts; triangleCount = plyNbTris; vertices = p; triangles = vi; vertNormals = n; vertColors = c; // Scale vertex colors for (unsigned int i = 0; i < vertexCount; ++i) c[i] *= 0.75f; // It looks like normals exported by Blender are bugged for (unsigned int i = 0; i < vertexCount; ++i) vertNormals[i] = Normal(0.f, 0.f, 0.f); for (unsigned int i = 0; i < triangleCount; ++i) { const Vector e1 = vertices[triangles[i].v[1]] - vertices[triangles[i].v[0]]; const Vector e2 = vertices[triangles[i].v[2]] - vertices[triangles[i].v[0]]; const Normal n = Normal(Normalize(Cross(e1, e2))); vertNormals[triangles[i].v[0]] += n; vertNormals[triangles[i].v[1]] += n; vertNormals[triangles[i].v[2]] += n; } int printedWarning = 0; for (unsigned int i = 0; i < vertexCount; ++i) { vertNormals[i] = Normalize(vertNormals[i]); // Check for degenerate triangles/normals, they can freeze the GPU if (isnan(vertNormals[i].x) || isnan(vertNormals[i].y) || isnan(vertNormals[i].z)) { if (printedWarning < 15) { cerr << "The model contains a degenerate normal (index " << i << ")" << endl; ++printedWarning; } else if (printedWarning == 15) { cerr << "The model contains more degenerate normals" << endl; ++printedWarning; } vertNormals[i] = Normal(0.f, 0.f, 1.f); } } /*if (plyNbNormals <= 0) { // Calculate normals for (unsigned int i = 0; i < triangleCount; ++i) { const Vector e1 = vertices[triangles[i].v[1]] - vertices[triangles[i].v[0]]; const Vector e2 = vertices[triangles[i].v[2]] - vertices[triangles[i].v[0]]; const Normal n = Normal(Normalize(Cross(e1, e2))); vertNormals[triangles[i].v[0]] = n; vertNormals[triangles[i].v[1]] = n; vertNormals[triangles[i].v[2]] = n; } }*/ }
LOD_Decimation_InfoPtr NewVertsFromFile( char * file_name, MT_Vector3 &min, MT_Vector3 &max ) { min = MT_Vector3(MT_INFINITY,MT_INFINITY,MT_INFINITY); max = MT_Vector3(-MT_INFINITY,-MT_INFINITY,-MT_INFINITY); PlyProperty vert_props[] = { /* list of property information for a vertex */ {"x", PLY_FLOAT, PLY_FLOAT, offsetof(LoadVertex,x), 0, 0, 0, 0}, {"y", PLY_FLOAT, PLY_FLOAT, offsetof(LoadVertex,y), 0, 0, 0, 0}, {"z", PLY_FLOAT, PLY_FLOAT, offsetof(LoadVertex,z), 0, 0, 0, 0}, }; PlyProperty face_props[] = { /* list of property information for a vertex */ {"intensity", PLY_UCHAR, PLY_UCHAR, offsetof(LoadFace,intensity), 0, 0, 0, 0}, {"vertex_indices", PLY_INT, PLY_INT, offsetof(LoadFace,verts), 1, PLY_UCHAR, PLY_UCHAR, offsetof(LoadFace,nverts)}, }; #if 0 MEM_SmartPtr<std::vector<float> > verts = new std::vector<float>; MEM_SmartPtr<std::vector<float> > vertex_normals = new std::vector<float>; MEM_SmartPtr<std::vector<int> > faces = new std::vector<int>; #else std::vector<float>* verts = new std::vector<float>; std::vector<float>* vertex_normals = new std::vector<float>; std::vector<int> * faces = new std::vector<int>; #endif int i,j; PlyFile *ply; int nelems; char **elist; int file_type; float version; int nprops; int num_elems; PlyProperty **plist; char *elem_name; LoadVertex load_vertex; LoadFace load_face; /* open a PLY file for reading */ ply = ply_open_for_reading(file_name, &nelems, &elist, &file_type, &version); if (ply == NULL) return NULL; /* go through each kind of element that we learned is in the file */ /* and read them */ for (i = 0; i < nelems; i++) { /* get the description of the first element */ elem_name = elist[i]; plist = ply_get_element_description (ply, elem_name, &num_elems, &nprops); /* print the name of the element, for debugging */ /* if we're on vertex elements, read them in */ if (equal_strings ("vertex", elem_name)) { /* set up for getting vertex elements */ ply_get_property (ply, elem_name, &vert_props[0]); ply_get_property (ply, elem_name, &vert_props[1]); ply_get_property (ply, elem_name, &vert_props[2]); // make some memory for the vertices verts->reserve(num_elems); /* grab all the vertex elements */ for (j = 0; j < num_elems; j++) { /* grab and element from the file */ ply_get_element (ply, (void *)&load_vertex); // pass the vertex into the mesh builder. if (load_vertex.x < min.x()) { min.x() = load_vertex.x; } else if (load_vertex.x > max.x()) { max.x()= load_vertex.x; } if (load_vertex.y < min.y()) { min.y() = load_vertex.y; } else if (load_vertex.y > max.y()) { max.y()= load_vertex.y; } if (load_vertex.z < min.z()) { min.z() = load_vertex.z; } else if (load_vertex.z > max.z()) { max.z()= load_vertex.z; } verts->push_back(load_vertex.x); verts->push_back(load_vertex.y); verts->push_back(load_vertex.z); vertex_normals->push_back(1.0f); vertex_normals->push_back(0.0f); vertex_normals->push_back(0.0f); } } /* if we're on face elements, read them in */ if (equal_strings ("face", elem_name)) { /* set up for getting face elements */ // ply_get_property (ply, elem_name, &face_props[0]); ply_get_property (ply, elem_name, &face_props[1]); /* grab all the face elements */ for (j = 0; j < num_elems; j++) { ply_get_element (ply, (void *)&load_face); faces->push_back(load_face.verts[0]); faces->push_back(load_face.verts[1]); faces->push_back(load_face.verts[2]); // free up the memory this pile of shit used to allocate the polygon's vertices free (load_face.verts); } } } /* close the PLY file */ ply_close (ply); LOD_Decimation_InfoPtr output = new LOD_Decimation_Info; output->vertex_buffer = verts->begin(); output->vertex_num = verts->size()/3; output->triangle_index_buffer = faces->begin(); output->face_num = faces->size()/3; output->intern = NULL; output->vertex_normal_buffer = vertex_normals->begin(); // memory leaks 'r' us #if 0 verts.Release(); vertex_normals.Release(); faces.Release(); #endif return output; }
read_test() { int i,j,k; PlyFile *ply; int nelems; char **elist; int file_type; float version; int nprops; int num_elems; PlyProperty **plist; Vertex **vlist; Face **flist; char *elem_name; int num_comments; char **comments; int num_obj_info; char **obj_info; /* open a PLY file for reading */ ply = ply_open_for_reading("test", &nelems, &elist, &file_type, &version); /* print what we found out about the file */ printf ("version %f\n", version); printf ("type %d\n", file_type); /* go through each kind of element that we learned is in the file */ /* and read them */ for (i = 0; i < nelems; i++) { /* get the description of the first element */ elem_name = elist[i]; plist = ply_get_element_description (ply, elem_name, &num_elems, &nprops); /* print the name of the element, for debugging */ printf ("element %s %d\n", elem_name, num_elems); /* if we're on vertex elements, read them in */ if (equal_strings ("vertex", elem_name)) { /* create a vertex list to hold all the vertices */ vlist = (Vertex **) malloc (sizeof (Vertex *) * num_elems); /* set up for getting vertex elements */ ply_get_property (ply, elem_name, &vert_props[0]); ply_get_property (ply, elem_name, &vert_props[1]); ply_get_property (ply, elem_name, &vert_props[2]); /* grab all the vertex elements */ for (j = 0; j < num_elems; j++) { /* grab and element from the file */ vlist[j] = (Vertex *) malloc (sizeof (Vertex)); ply_get_element (ply, (void *) vlist[j]); /* print out vertex x,y,z for debugging */ printf ("vertex: %g %g %g\n", vlist[j]->x, vlist[j]->y, vlist[j]->z); } } /* if we're on face elements, read them in */ if (equal_strings ("face", elem_name)) { /* create a list to hold all the face elements */ flist = (Face **) malloc (sizeof (Face *) * num_elems); /* set up for getting face elements */ ply_get_property (ply, elem_name, &face_props[0]); ply_get_property (ply, elem_name, &face_props[1]); /* grab all the face elements */ for (j = 0; j < num_elems; j++) { /* grab and element from the file */ flist[j] = (Face *) malloc (sizeof (Face)); ply_get_element (ply, (void *) flist[j]); /* print out face info, for debugging */ printf ("face: %d, list = ", flist[j]->intensity); for (k = 0; k < flist[j]->nverts; k++) printf ("%d ", flist[j]->verts[k]); printf ("\n"); } } /* print out the properties we got, for debugging */ for (j = 0; j < nprops; j++) printf ("property %s\n", plist[j]->name); } /* grab and print out the comments in the file */ comments = ply_get_comments (ply, &num_comments); for (i = 0; i < num_comments; i++) printf ("comment = '%s'\n", comments[i]); /* grab and print out the object information */ obj_info = ply_get_obj_info (ply, &num_obj_info); for (i = 0; i < num_obj_info; i++) printf ("obj_info = '%s'\n", obj_info[i]); /* close the PLY file */ ply_close (ply); }