/* prepares the conversion */ static void setup_callbacks(p_ply iply, p_ply oply) { p_ply_element element = NULL; /* iterate over all elements in input file */ while ((element = ply_get_next_element(iply, element))) { p_ply_property property = NULL; gint32 ninstances = 0; const char *element_name; ply_get_element_info(element, &element_name, &ninstances); /* add this element to output file */ if (!ply_add_element(oply, element_name, ninstances)) error("Unable to add output element '%s'", element_name); /* iterate over all properties of current element */ while ((property = ply_get_next_property(element, property))) { const char *property_name; e_ply_type type, length_type, value_type; ply_get_property_info(property, &property_name, &type, &length_type, &value_type); /* setup input callback for this property */ if (!ply_set_read_cb(iply, element_name, property_name, callback, oply, 0)) error("Unable to setup input callback for property '%s'", property_name); /* add this property to output file */ if (!ply_add_property(oply, property_name, type, length_type, value_type)) error("Unable to add output property '%s'", property_name); } } }
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; }
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); }
static int setup_callbacks(p_ply iply, p_ply oply) { p_ply_element element = NULL; /* iterate over all elements in input file */ while ((element = ply_get_next_element(iply, element))) { p_ply_property property = NULL; long nelems = 0; const char *element_name; ply_get_element_info(element, &element_name, &nelems); /* add this element to output file */ if (!ply_add_element(oply, element_name, nelems)) return 0; /* iterate over all properties of current element */ while ((property = ply_get_next_property(element, property))) { const char *property_name; e_ply_type type, length_type, value_type; ply_get_property_info(property, &property_name, &type, &length_type, &value_type); /* setup input callback for this property */ if (!ply_set_read_cb(iply, element_name, property_name, callback, oply, 0)) return 0; /* add this property to output file */ if (!ply_add_property(oply, property_name, type, length_type, value_type)) return 0; } } return 1; }
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 check_for_colors(p_ply ply) { p_ply_element element = nil ; bool has_r = false ; bool has_g = false ; bool has_b = false ; bool has_red = false ; bool has_green = false ; bool has_blue = false ; for(;;) { element = ply_get_next_element(ply, element) ; if(element == nil) { break ; } const char* elt_name = nil ; ply_get_element_info(element, &elt_name, nil) ; if(!strcmp(elt_name, "vertex")) { p_ply_property prop = nil ; for(;;) { prop = ply_get_next_property(element, prop) ; if(prop == nil) { break ; } const char* prop_name = nil ; ply_get_property_info(prop, &prop_name, nil, nil, nil) ; has_r = has_r || !strcmp(prop_name, "r") ; has_g = has_g || !strcmp(prop_name, "g") ; has_b = has_b || !strcmp(prop_name, "b") ; has_red = has_red || !strcmp(prop_name, "red") ; has_green = has_green || !strcmp(prop_name, "green") ; has_blue = has_blue || !strcmp(prop_name, "blue") ; } } } if(has_r && has_g && has_b) { has_colors_ = true ; color_mult_ = 1.0 ; ply_set_read_cb(ply, "vertex", "r", PlyMeshLoad::color_cb, this, 0) ; ply_set_read_cb(ply, "vertex", "g", PlyMeshLoad::color_cb, this, 1) ; ply_set_read_cb(ply, "vertex", "b", PlyMeshLoad::color_cb, this, 2) ; } else if(has_red && has_green && has_blue) { has_colors_ = true ; color_mult_ = 1.0 / 255.0 ; ply_set_read_cb(ply, "vertex", "red", PlyMeshLoad::color_cb, this, 0) ; ply_set_read_cb(ply, "vertex", "green", PlyMeshLoad::color_cb, this, 1) ; ply_set_read_cb(ply, "vertex", "blue", PlyMeshLoad::color_cb, this, 2) ; } else { has_colors_ = false ; } }
int ply_parser_call_back(p_ply_argument argument) { p_ply_element elem; p_ply_property prop; const char* elem_name; const char* prop_name; PLYParser* parser; long prop_len; long value_idx; assert_success(ply_get_argument_element(argument, &elem, NULL)); assert_success(ply_get_argument_property(argument, &prop, &prop_len, &value_idx)); assert_success(ply_get_element_info(elem, &elem_name, NULL)); assert_success(ply_get_property_info(prop, &prop_name, NULL, NULL, NULL)); assert_success(ply_get_argument_user_data(argument, (void**)&parser, NULL)); Float value = ply_get_argument_value(argument); if (value_idx >= 0) parser->add_property_value(elem_name, prop_name, value); return 1; }
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; }
std::vector<std::shared_ptr<Shape>> CreatePLYMesh( const Transform *o2w, const Transform *w2o, bool reverseOrientation, const ParamSet ¶ms, std::map<std::string, std::shared_ptr<Texture<Float>>> *floatTextures) { const std::string filename = params.FindOneFilename("filename", ""); p_ply ply = ply_open(filename.c_str(), rply_message_callback, 0, nullptr); if (!ply) { Error("Couldn't open PLY file \"%s\"", filename.c_str()); return std::vector<std::shared_ptr<Shape>>(); } if (!ply_read_header(ply)) { Error("Unable to read the header of PLY file \"%s\"", filename.c_str()); return std::vector<std::shared_ptr<Shape>>(); } p_ply_element element = nullptr; long 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 = nInstances; else if (!strcmp(name, "face")) faceCount = nInstances; } if (vertexCount == 0 || faceCount == 0) { Error("PLY file \"%s\" is invalid! No face/vertex elements found!", filename.c_str()); return std::vector<std::shared_ptr<Shape>>(); } CallbackContext context; if (ply_set_read_cb(ply, "vertex", "x", rply_vertex_callback, &context, 0x030) && ply_set_read_cb(ply, "vertex", "y", rply_vertex_callback, &context, 0x031) && ply_set_read_cb(ply, "vertex", "z", rply_vertex_callback, &context, 0x032)) { context.p = new Point3f[vertexCount]; } else { Error("PLY file \"%s\": Vertex coordinate property not found!", filename.c_str()); return std::vector<std::shared_ptr<Shape>>(); } if (ply_set_read_cb(ply, "vertex", "nx", rply_vertex_callback, &context, 0x130) && ply_set_read_cb(ply, "vertex", "ny", rply_vertex_callback, &context, 0x131) && ply_set_read_cb(ply, "vertex", "nz", rply_vertex_callback, &context, 0x132)) context.n = new Normal3f[vertexCount]; /* There seem to be lots of different conventions regarding UV coordinate * names */ if ((ply_set_read_cb(ply, "vertex", "u", rply_vertex_callback, &context, 0x220) && ply_set_read_cb(ply, "vertex", "v", rply_vertex_callback, &context, 0x221)) || (ply_set_read_cb(ply, "vertex", "s", rply_vertex_callback, &context, 0x220) && ply_set_read_cb(ply, "vertex", "t", rply_vertex_callback, &context, 0x221)) || (ply_set_read_cb(ply, "vertex", "texture_u", rply_vertex_callback, &context, 0x220) && ply_set_read_cb(ply, "vertex", "texture_v", rply_vertex_callback, &context, 0x221)) || (ply_set_read_cb(ply, "vertex", "texture_s", rply_vertex_callback, &context, 0x220) && ply_set_read_cb(ply, "vertex", "texture_t", rply_vertex_callback, &context, 0x221))) context.uv = new Point2f[vertexCount]; /* Allocate enough space in case all faces are quads */ context.indices = new int[faceCount * 6]; context.vertexCount = vertexCount; ply_set_read_cb(ply, "face", "vertex_indices", rply_face_callback, &context, 0); if (!ply_read(ply)) { Error("Unable to read the contents of PLY file \"%s\"", filename.c_str()); ply_close(ply); return std::vector<std::shared_ptr<Shape>>(); } ply_close(ply); if (context.error) return std::vector<std::shared_ptr<Shape>>(); // Look up an alpha texture, if applicable std::shared_ptr<Texture<Float>> alphaTex; std::string alphaTexName = params.FindTexture("alpha"); if (alphaTexName != "") { if (floatTextures->find(alphaTexName) != floatTextures->end()) alphaTex = (*floatTextures)[alphaTexName]; else Error("Couldn't find float texture \"%s\" for \"alpha\" parameter", alphaTexName.c_str()); } else if (params.FindOneFloat("alpha", 1.f) == 0.f) { alphaTex.reset(new ConstantTexture<Float>(0.f)); } std::shared_ptr<Texture<Float>> shadowAlphaTex; std::string shadowAlphaTexName = params.FindTexture("shadowalpha"); if (shadowAlphaTexName != "") { if (floatTextures->find(shadowAlphaTexName) != floatTextures->end()) shadowAlphaTex = (*floatTextures)[shadowAlphaTexName]; else Error( "Couldn't find float texture \"%s\" for \"shadowalpha\" " "parameter", shadowAlphaTexName.c_str()); } else if (params.FindOneFloat("shadowalpha", 1.f) == 0.f) shadowAlphaTex.reset(new ConstantTexture<Float>(0.f)); return CreateTriangleMesh(o2w, w2o, reverseOrientation, context.indexCtr / 3, context.indices, vertexCount, context.p, nullptr, context.n, context.uv, alphaTex, shadowAlphaTex); }
/******************************************************************************* * Name: loadPly * Description: Load a ply file into memory. ******************************************************************************/ void loadPly( char * filename, size_t idx ) { printf( "Loading »%s«…\n", filename ); p_ply ply = ply_open( filename, NULL, 0, NULL ); if ( !ply ) { fprintf( stderr, "error: Could not open »%s«.\n", filename ); exit( EXIT_FAILURE ); } if ( !ply_read_header( ply ) ) { fprintf( stderr, "error: Could not read header.\n" ); exit( EXIT_FAILURE ); } /* Check if there are vertices and get the amount of vertices. */ char buf[256] = ""; char elemname[256] = "point"; const char * name = buf; long int nvertices = 0; long int count = 0; p_ply_element elem = NULL; while ( ( elem = ply_get_next_element( ply, elem ) ) ) { ply_get_element_info( elem, &name, &count ); if ( !strcmp( name, "vertex" ) ) { nvertices = count; strcpy( elemname, "vertex" ); p_ply_property prop = NULL; if ( g_clouds[ idx ].colors ) { free( g_clouds[ idx ].colors ); } while ( ( prop = ply_get_next_property( elem, prop ) ) ) { ply_get_property_info( prop, &name, NULL, NULL, NULL ); if ( !strcmp( name, "red" ) ) { /* We have color information */ g_clouds[ idx ].colors = ( uint8_t * ) realloc( g_clouds[ idx ].colors, nvertices * 3 * sizeof(uint8_t) ); } } } else if ( !strcmp( name, "point" ) ) { nvertices = count; strcpy( elemname, "point" ); p_ply_property prop = NULL; if ( g_clouds[ idx ].colors ) { free( g_clouds[ idx ].colors ); } while ( ( prop = ply_get_next_property( elem, prop ) ) ) { ply_get_property_info( prop, &name, NULL, NULL, NULL ); if ( !strcmp( name, "red" ) ) { /* We have color information */ g_clouds[ idx ].colors = ( uint8_t * ) realloc( g_clouds[ idx ].colors, nvertices * 3 * sizeof(uint8_t) ); } } /* Point is more important than vertex. Thus we can stop immediately if * we got this element. */ break; } } if ( !nvertices ) { fprintf( stderr, "warning: No vertices in ply.\n" ); return; } /* Allocate memory. */ g_clouds[ idx ].pointcount = nvertices; nvertices++; g_clouds[ idx ].vertices = (float*) malloc( nvertices * 3 * sizeof(float) ); uint8_t* color = g_clouds[ idx ].colors; g_clouds[ idx ].boundingbox.min.x = DBL_MAX; g_clouds[ idx ].boundingbox.min.y = DBL_MAX; g_clouds[ idx ].boundingbox.min.z = DBL_MAX; g_clouds[ idx ].boundingbox.max.x = DBL_MIN; g_clouds[ idx ].boundingbox.max.y = DBL_MIN; g_clouds[ idx ].boundingbox.max.z = DBL_MIN; struct { float* v; boundingbox_t* b; } d = { g_clouds[ idx ].vertices, &g_clouds[ idx ].boundingbox }; /* Set callbacks. */ nvertices = ply_set_read_cb( ply, elemname, "x", plyVertexCb, &d, 0 ); ply_set_read_cb( ply, elemname, "y", plyVertexCb, &d, 1 ); ply_set_read_cb( ply, elemname, "z", plyVertexCb, &d, 2 ); if ( color ) { ply_set_read_cb( ply, elemname, "red", plyColorCb, &color, 0 ); ply_set_read_cb( ply, elemname, "green", plyColorCb, &color, 1 ); ply_set_read_cb( ply, elemname, "blue", plyColorCb, &color, 2 ); } /* Read ply file. */ if ( !ply_read( ply ) ) { fprintf( stderr, "error: could not read »%s«.\n", filename ); exit( EXIT_FAILURE ); } ply_close( ply ); printf( "%ld values read.\nPoint cloud loaded.", nvertices ); g_maxdim = max( max( max( g_maxdim, d.b->max.x - d.b->min.x ), d.b->max.y - d.b->min.y ), d.b->max.z - d.b->min.z ); g_bb.max.x = max( g_bb.max.x, d.b->max.x ); g_bb.max.y = max( g_bb.max.y, d.b->max.y ); g_bb.max.z = max( g_bb.max.z, d.b->max.z ); g_bb.min.x = min( g_bb.min.x, d.b->min.x ); g_bb.min.y = min( g_bb.min.y, d.b->min.y ); g_bb.min.z = min( g_bb.min.z, d.b->min.z ); }
static gboolean mash_ply_loader_get_indices_type (MashPlyLoaderData *data, GError **error) { CoglContext *context; p_ply_element elem = NULL; context = es_get_cogl_context (); /* Look for the 'vertices' element */ while ((elem = ply_get_next_element (data->ply, elem))) { const char *name; gint32 n_instances; if (ply_get_element_info (elem, &name, &n_instances)) { if (!strcmp (name, "vertex")) { if (n_instances <= 0x100) { data->indices_type = COGL_INDICES_TYPE_UNSIGNED_BYTE; data->faces = g_array_new (FALSE, FALSE, sizeof (guint8)); } else if (n_instances <= 0x10000) { data->indices_type = COGL_INDICES_TYPE_UNSIGNED_SHORT; data->faces = g_array_new (FALSE, FALSE, sizeof (guint16)); } else if (cogl_has_feature (context, COGL_FEATURE_ID_UNSIGNED_INT_INDICES)) { data->indices_type = COGL_INDICES_TYPE_UNSIGNED_INT; data->faces = g_array_new (FALSE, FALSE, sizeof (guint32)); } else { g_set_error (error, MASH_DATA_ERROR, MASH_DATA_ERROR_UNSUPPORTED, "The PLY file requires unsigned int indices " "but this is not supported by your GL driver"); return FALSE; } return TRUE; } } else { g_set_error (error, MASH_DATA_ERROR, MASH_DATA_ERROR_UNKNOWN, "Error getting element info"); return FALSE; } } g_set_error (error, MASH_DATA_ERROR, MASH_DATA_ERROR_MISSING_PROPERTY, "PLY file is missing the vertex element"); return FALSE; }