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); }
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 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 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); }
/****************************************************************************** Open a polygon file for reading. Entry: filename - name of file to read from Exit: nelems - number of elements in object elem_names - list of element names file_type - file type, either ascii or binary version - version number of PLY file returns a file identifier, used to refer to this file, or NULL if error ******************************************************************************/ PlyFile *ply_open_for_reading(char *filename, int *nelems, char ***elem_names, int *file_type, float *version) { assert(filename != NULL); FILE *fp; PlyFile *plyfile; // open the file for reading fp = fopen (filename, "r"); if (fp == NULL) { log_error("Could not open file %s\n", filename); exit(1); } // create the PlyFile data structure plyfile = ply_read(fp, nelems, elem_names); assert(plyfile != NULL); // determine the file type and version *file_type = plyfile->file_type; *version = plyfile->version; // return a pointer to the file's information */ return (plyfile); }
/* 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 ; }
static bool ply_boot_connection_read_request (ply_boot_connection_t *connection, char **command, char **argument) { uint8_t header[2]; assert (connection != NULL); assert (connection->fd >= 0); if (!ply_read (connection->fd, header, sizeof (header))) return false; *command = calloc (2, sizeof (char)); *command[0] = header[0]; *argument = NULL; if (header[1] == '\002') { uint8_t argument_size; if (!ply_read (connection->fd, &argument_size, sizeof (uint8_t))) { free (*command); return false; } *argument = calloc (argument_size, sizeof (char)); if (!ply_read (connection->fd, *argument, argument_size)) { free (*argument); free (*command); return false; } } return true; }
void reader_t::operator()(vertexes_t& vertexes, faces_t& faces) const { const long nvertexes = ply_set_read_cb(_ply.get(), "vertex", "x", vertex_cb, &vertexes, 0); ply_set_read_cb(_ply.get(), "vertex", "y", vertex_cb, &vertexes, 1); ply_set_read_cb(_ply.get(), "vertex", "z", vertex_cb, &vertexes, 2); const long ntriangles = ply_set_read_cb(_ply.get(), "face", "vertex_indices", face_cb, &faces, 0); vertexes.resize(nvertexes); faces.resize(ntriangles); if (!ply_read(_ply.get())) throw std::runtime_error("Can't read."); }
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; }
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 ); }
point_count_t PlyReader::read(PointViewPtr view, point_count_t num) { CallbackContext context; context.view = view; context.dimensionMap = m_vertexDimensions; // It's possible that point_count_t holds a value that's larger than the // long that is the maximum rply (don't know about ply) point count. long cnt; cnt = Utils::inRange<long>(num) ? num : (std::numeric_limits<long>::max)(); for (auto it : m_vertexDimensions) { ply_set_read_cb(m_ply, "vertex", it.first.c_str(), readPlyCallback, &context, cnt); } if (!ply_read(m_ply)) { std::stringstream ss; ss << "Error reading " << m_filename << "."; throw pdal_error(ss.str()); } return view->size(); }
static gboolean mash_ply_loader_load (MashDataLoader *data_loader, MashDataFlags flags, const gchar *filename, GError **error) { CoglContext *context; CoglIndices *indices; MashPlyLoader *self = MASH_PLY_LOADER (data_loader); MashPlyLoaderPrivate *priv; MashPlyLoaderData data; gchar *display_name; gboolean ret; priv = self->priv; context = es_get_cogl_context (); data.error = NULL; data.n_vertex_bytes = 0; data.available_props = 0; data.got_props = 0; data.vertices = g_byte_array_new (); data.faces = NULL; data.min_vertex.x = G_MAXFLOAT; data.min_vertex.y = G_MAXFLOAT; data.min_vertex.z = G_MAXFLOAT; data.max_vertex.x = -G_MAXFLOAT; data.max_vertex.y = -G_MAXFLOAT; data.max_vertex.z = -G_MAXFLOAT; data.flags = flags; display_name = g_filename_display_name (filename); if ((data.ply = ply_open (filename, mash_ply_loader_error_cb, &data)) == NULL) mash_ply_loader_check_unknown_error (&data); else { if (!ply_read_header (data.ply)) mash_ply_loader_check_unknown_error (&data); else { int i; for (i = 0; i < G_N_ELEMENTS (mash_ply_loader_properties); i++) if (ply_set_read_cb (data.ply, "vertex", mash_ply_loader_properties[i].name, mash_ply_loader_vertex_read_cb, &data, i)) { data.prop_map[i] = data.n_vertex_bytes; data.n_vertex_bytes += mash_ply_loader_properties[i].size; data.available_props |= 1 << i; } /* Align the size of a vertex to 32 bits */ data.n_vertex_bytes = (data.n_vertex_bytes + 3) & ~(guint) 3; if ((data.available_props & MASH_PLY_LOADER_VERTEX_PROPS) != MASH_PLY_LOADER_VERTEX_PROPS) g_set_error (&data.error, MASH_DATA_ERROR, MASH_DATA_ERROR_MISSING_PROPERTY, "PLY file %s is missing the vertex properties", display_name); else if (!ply_set_read_cb (data.ply, "face", "vertex_indices", mash_ply_loader_face_read_cb, &data, i)) g_set_error (&data.error, MASH_DATA_ERROR, MASH_DATA_ERROR_MISSING_PROPERTY, "PLY file %s is missing face property " "'vertex_indices'", display_name); else if (mash_ply_loader_get_indices_type (&data, &data.error) && !ply_read (data.ply)) mash_ply_loader_check_unknown_error (&data); } ply_close (data.ply); } if (data.error) { g_propagate_error (error, data.error); ret = FALSE; } else if (data.faces->len < 3) { g_set_error (error, MASH_DATA_ERROR, MASH_DATA_ERROR_INVALID, "No faces found in %s", display_name); ret = FALSE; } else { CoglAttributeBuffer *attribute_buffer; CoglAttribute *attributes[4]; int n_attributes = 0, i; /* Get rid of the old primitive (if any) */ mash_ply_loader_free_primitive (self); /* Create a new attribute buffer for the vertices */ attribute_buffer = cogl_attribute_buffer_new (context, data.vertices->len, data.vertices->data); /* And describe the attributes */ if ((data.available_props & MASH_PLY_LOADER_VERTEX_PROPS) == MASH_PLY_LOADER_VERTEX_PROPS) { attributes[n_attributes++] = cogl_attribute_new (attribute_buffer, "cogl_position_in", data.n_vertex_bytes, data.prop_map[0], 3, COGL_ATTRIBUTE_TYPE_FLOAT); } if ((data.available_props & MASH_PLY_LOADER_NORMAL_PROPS) == MASH_PLY_LOADER_NORMAL_PROPS) { attributes[n_attributes++] = cogl_attribute_new (attribute_buffer, "cogl_normal_in", data.n_vertex_bytes, data.prop_map[3], 3, COGL_ATTRIBUTE_TYPE_FLOAT); } if ((data.available_props & MASH_PLY_LOADER_TEX_COORD_PROPS) == MASH_PLY_LOADER_TEX_COORD_PROPS) { attributes[n_attributes++] = cogl_attribute_new (attribute_buffer, "cogl_tex_coord0_in", data.n_vertex_bytes, data.prop_map[6], 2, COGL_ATTRIBUTE_TYPE_FLOAT); } if ((data.available_props & MASH_PLY_LOADER_COLOR_PROPS) == MASH_PLY_LOADER_COLOR_PROPS) { attributes[n_attributes++] = cogl_attribute_new (attribute_buffer, "cogl_color_in", data.n_vertex_bytes, data.prop_map[8], 3, COGL_ATTRIBUTE_TYPE_FLOAT); } priv->primitive = cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_TRIANGLES, data.vertices->len, attributes, n_attributes); for (i = 0; i < n_attributes; i++) cogl_object_unref (attributes[i]); indices = cogl_indices_new (context, data.indices_type, data.faces->data, data.faces->len); cogl_primitive_set_indices (priv->primitive, indices, data.faces->len); cogl_object_unref (indices); priv->min_vertex = data.min_vertex; priv->max_vertex = data.max_vertex; ret = TRUE; } g_free (display_name); g_byte_array_free (data.vertices, TRUE); if (data.faces) g_array_free (data.faces, TRUE); return ret; }
static void ply_boot_client_process_incoming_replies (ply_boot_client_t *client) { ply_list_node_t *request_node; ply_boot_client_request_t *request; bool processed_reply; uint8_t byte[2] = ""; uint32_t size; assert (client != NULL); processed_reply = false; if (ply_list_get_length (client->requests_waiting_for_replies) == 0) { ply_error ("received unexpected response from boot status daemon"); return; } if (!ply_read (client->socket_fd, byte, sizeof (uint8_t))) goto out; for (request_node = ply_list_get_first_node (client->requests_waiting_for_replies); request_node; request_node = ply_list_get_next_node (client->requests_waiting_for_replies, request_node)) { assert (request_node != NULL); request = (ply_boot_client_request_t *) ply_list_node_get_data (request_node); assert (request != NULL); if (! strcmp (request->command, PLY_BOOT_PROTOCOL_REQUEST_TYPE_PASSWORD) || ! strcmp (request->command, PLY_BOOT_PROTOCOL_REQUEST_TYPE_QUESTION) || ! strcmp (request->command, PLY_BOOT_PROTOCOL_REQUEST_TYPE_KEYSTROKE)) { if (! memcmp (byte, PLY_BOOT_PROTOCOL_RESPONSE_TYPE_ANSWER, sizeof (uint8_t)) || ! memcmp (byte, PLY_BOOT_PROTOCOL_RESPONSE_TYPE_NO_ANSWER, sizeof (uint8_t))) break; } else { if (memcmp (byte, PLY_BOOT_PROTOCOL_RESPONSE_TYPE_ANSWER, sizeof (uint8_t)) && memcmp (byte, PLY_BOOT_PROTOCOL_RESPONSE_TYPE_NO_ANSWER, sizeof (uint8_t))) break; } } if (memcmp (byte, PLY_BOOT_PROTOCOL_RESPONSE_TYPE_ACK, sizeof (uint8_t)) == 0) request->handler (request->user_data, client); else if (memcmp (byte, PLY_BOOT_PROTOCOL_RESPONSE_TYPE_ANSWER, sizeof (uint8_t)) == 0) { char *answer; if (!ply_read_uint32 (client->socket_fd, &size)) goto out; answer = malloc ((size+1) * sizeof(char)); if (size > 0) { if (!ply_read (client->socket_fd, answer, size)) goto out; } answer[size] = '\0'; ((ply_boot_client_answer_handler_t) request->handler) (request->user_data, answer, client); free(answer); } else if (memcmp (byte, PLY_BOOT_PROTOCOL_RESPONSE_TYPE_MULTIPLE_ANSWERS, sizeof (uint8_t)) == 0) { ply_array_t *array; char **answers; char *answer; char *p; char *q; uint8_t i; array = NULL; answers = NULL; if (!ply_read_uint32 (client->socket_fd, &size)) goto out; assert (size > 0); answer = malloc (size); if (!ply_read (client->socket_fd, answer, size)) { free (answer); goto out; } array = ply_array_new (); p = answer; q = p; for (i = 0; i < size; i++, q++) { if (*q == '\0') { ply_array_add_element (array, strdup (p)); p = q + 1; } } free (answer); answers = (char **) ply_array_steal_elements (array); ply_array_free (array); ((ply_boot_client_multiple_answers_handler_t) request->handler) (request->user_data, (const char * const *) answers, client); ply_free_string_array (answers); } else if (memcmp (byte, PLY_BOOT_PROTOCOL_RESPONSE_TYPE_NO_ANSWER, sizeof (uint8_t)) == 0) { ((ply_boot_client_answer_handler_t) request->handler) (request->user_data, NULL, client); } else goto out; processed_reply = true; out: if (!processed_reply) { if (request->failed_handler != NULL) request->failed_handler (request->user_data, client); } ply_list_remove_node (client->requests_waiting_for_replies, request_node); if (ply_list_get_length (client->requests_waiting_for_replies) == 0) { if (client->daemon_has_reply_watch != NULL) { assert (client->loop != NULL); ply_event_loop_stop_watching_fd (client->loop, client->daemon_has_reply_watch); client->daemon_has_reply_watch = NULL; } } }
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; } }*/ }
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 loadPlyFile(const QString& fileName, PlyLoadInfo& info) { // Read a triangulation from a .ply file std::unique_ptr<t_ply_, int(*)(p_ply)> ply( ply_open(fileName.toUtf8().constData(), NULL, 0, NULL), ply_close); if (!ply || !ply_read_header(ply.get())) { g_logger.error("Could not open ply or read header"); return false; } long nvertices = ply_set_read_cb(ply.get(), "vertex", "x", vertex_cb, &info, 0); if (ply_set_read_cb(ply.get(), "vertex", "y", vertex_cb, &info, 1) != nvertices || ply_set_read_cb(ply.get(), "vertex", "z", vertex_cb, &info, 2) != nvertices) { g_logger.error("Expected vertex properties (x,y,z) in ply file"); return false; } info.verts.reserve(3*nvertices); long ncolors = ply_set_read_cb(ply.get(), "color", "r", color_cb, &info, 0); if (ncolors != 0) { ply_set_read_cb(ply.get(), "color", "g", color_cb, &info, 1); ply_set_read_cb(ply.get(), "color", "b", color_cb, &info, 2); info.colors.reserve(3*nvertices); } if (ncolors == 0) { ncolors = ply_set_read_cb(ply.get(), "vertex", "r", color_cb, &info, 0); if (ncolors != 0) { ply_set_read_cb(ply.get(), "vertex", "g", color_cb, &info, 1); ply_set_read_cb(ply.get(), "vertex", "b", color_cb, &info, 2); info.colors.reserve(3*nvertices); } } // Attempt to load attributes with names face/vertex_index or face/vertex_indices // There doesn't seem to be a real standard here... long nfaces = ply_set_read_cb(ply.get(), "face", "vertex_index", face_cb, &info, 1); if (nfaces == 0) nfaces = ply_set_read_cb(ply.get(), "face", "vertex_indices", face_cb, &info, 1); if (nfaces == 0) { nfaces = ply_set_read_cb(ply.get(), "triangle", "v1", face_cb, &info, 0); if (nfaces != 0 && (ply_set_read_cb(ply.get(), "triangle", "v2", face_cb, &info, 0) != nfaces || ply_set_read_cb(ply.get(), "triangle", "v3", face_cb, &info, 0) != nfaces)) { g_logger.error("Expected triangle properties (v1,v2,v3) in ply file"); return false; } } long nedges = ply_set_read_cb(ply.get(), "edge", "vertex_index", edge_cb, &info, 0); if (nedges == 0) nedges = ply_set_read_cb(ply.get(), "edge", "vertex_indices", edge_cb, &info, 0); // Support for specific Roames Ply format std::vector<unsigned int> innerPolygonVertexCount; std::vector<unsigned int> innerVertexIndices; if (nedges == 0) { nedges = ply_set_read_cb(ply.get(), "polygon", "outer_vertex_index", edge_cb, &info, 1); nedges += ply_set_read_cb(ply.get(), "hullxy", "vertex_index", edge_cb, &info, 1); nedges += ply_set_read_cb(ply.get(), "polygon", "inner_polygon_vertex_counts", list_cb, &innerPolygonVertexCount, 0); ply_set_read_cb(ply.get(), "polygon", "inner_vertex_index", list_cb, &innerVertexIndices, 0); } if (nedges <= 0 && nfaces <= 0) { g_logger.error("Expected more than zero edges or faces in ply file"); return false; } if (nfaces > 0) { // Ply file contains a mesh - load as triangle mesh info.faces.reserve(3*nfaces); } if (nedges > 0) { // Ply file contains a set of edges info.edges.reserve(2*nedges); } if (!ply_read(ply.get())) { g_logger.error("Error reading ply file data section"); return false; } if (info.colors.size() != info.verts.size()) info.colors.clear(); // Reconstruct inner polygons for (size_t i = 0, j = 0; i < innerPolygonVertexCount.size(); ++i) { size_t count = innerPolygonVertexCount[i]; for (size_t k = 0; k < count; ++k) { info.edges.push_back(innerVertexIndices[j + k]); info.edges.push_back(innerVertexIndices[j + (k+1) % count]); } j += count; } return true; }
void ReadFile( MFIList *mfi, Model *model ) { int i,j; PlyFile *ply; int nprops; int num_elems; PlyProperty **plist; char *elem_name; float version; FILE *fp; if ((fp = fopen(mfi->file_info.path, "rb")) == NULL) { crError( "Can't open %s for reading!", mfi->file_info.path ); } ply = ply_read (fp, &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 */ globals.has_nx = globals.has_ny = globals.has_nz = 0; globals.has_r = globals.has_g = globals.has_b = 0; for (j = 0; j < nprops; j++) { if (equal_strings ("nx", plist[j]->name)) globals.has_nx = 1; if (equal_strings ("ny", plist[j]->name)) globals.has_ny = 1; if (equal_strings ("nz", plist[j]->name)) globals.has_nz = 1; if (equal_strings ("red", plist[j]->name)) globals.has_r = 1; if (equal_strings ("green", plist[j]->name)) globals.has_g = 1; if (equal_strings ("blue", plist[j]->name)) globals.has_b = 1; } /* create a vertex list to hold all the vertices */ model->vlist = (Vertex *) crAlloc (sizeof (*(model->vlist)) * num_elems); model->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 (globals.has_r) ply_get_property (ply, elem_name, &vert_props[3]); if (globals.has_g) ply_get_property (ply, elem_name, &vert_props[4]); if (globals.has_b) ply_get_property (ply, elem_name, &vert_props[5]); if (globals.has_nx) ply_get_property (ply, elem_name, &vert_props[6]); if (globals.has_ny) ply_get_property (ply, elem_name, &vert_props[7]); if (globals.has_nz) ply_get_property (ply, elem_name, &vert_props[8]); /* grab all the vertex elements */ for (j = 0; j < num_elems; j++) { model->vlist[j].r = 1.0f; model->vlist[j].g = 1.0f; model->vlist[j].b = 1.0f; model->vlist[j].nx = 1.0f; model->vlist[j].ny = 1.0f; model->vlist[j].nz = 1.0f; ply_get_element (ply, model->vlist+j); model->vlist[j].r /= 255.0f; model->vlist[j].g /= 255.0f; model->vlist[j].b /= 255.0f; } } else if (equal_strings ("face", elem_name)) { /* create a list to hold all the face elements */ model->flist = (Face *) crAlloc (sizeof (*(model->flist)) * num_elems); model->nfaces = num_elems; /* set up for getting face elements */ ply_get_property (ply, elem_name, &face_props[0]); /* grab all the face elements */ crDebug( "Reading %s (%d faces)", mfi->file_info.path, model->nfaces ); model->faces = (unsigned int *) crAlloc( model->nfaces * 3 * sizeof( *(model->faces) ) ); for (j = 0; j < num_elems; j++) { ply_get_element (ply, model->flist + j); model->faces[j*3+0] = model->flist[j].verts[0]; model->faces[j*3+1] = model->flist[j].verts[1]; model->faces[j*3+2] = model->flist[j].verts[2]; } } } ply_close (ply); }
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 ); }
bool loadPlyFile(const QString& fileName, PlyLoadInfo& info) { // Read a triangulation from a .ply file std::unique_ptr<t_ply_, int(*)(p_ply)> ply( ply_open(fileName.toUtf8().constData(), logRplyError, 0, NULL), ply_close); if (!ply || !ply_read_header(ply.get())) { g_logger.error("Could not open ply or read header"); return false; } long nvertices = ply_set_read_cb(ply.get(), "vertex", "x", vertex_cb, &info, 0); if (ply_set_read_cb(ply.get(), "vertex", "y", vertex_cb, &info, 1) != nvertices || ply_set_read_cb(ply.get(), "vertex", "z", vertex_cb, &info, 2) != nvertices) { g_logger.error("Expected vertex properties (x,y,z) in ply file"); return false; } info.nvertices = nvertices; info.currPoly.setVertexCount(nvertices); info.verts.reserve(3*nvertices); long ncolors = ply_set_read_cb(ply.get(), "color", "r", color_cb, &info, 0); if (ncolors != 0) { ply_set_read_cb(ply.get(), "color", "g", color_cb, &info, 1); ply_set_read_cb(ply.get(), "color", "b", color_cb, &info, 2); info.colors.reserve(3*nvertices); } if (ncolors == 0) { ncolors = ply_set_read_cb(ply.get(), "vertex", "r", color_cb, &info, 0); if (ncolors != 0) { ply_set_read_cb(ply.get(), "vertex", "g", color_cb, &info, 1); ply_set_read_cb(ply.get(), "vertex", "b", color_cb, &info, 2); info.colors.reserve(3*nvertices); } } long ntexcoords = ply_set_read_cb(ply.get(), "vertex", "u", texcoord_cb, &info, 0); if (ntexcoords != 0) { if (ply_set_read_cb(ply.get(), "vertex", "v", texcoord_cb, &info, 1) == ntexcoords) info.texcoords.reserve(2*nvertices); else ntexcoords = 0; } const char* cmt = NULL; while (true) { cmt = ply_get_next_comment(ply.get(), cmt); if (!cmt) break; QList<QString> tokens = QString(cmt).split(" "); if (tokens[0] == "TextureFile" && tokens.size() > 1) { QDir d = QFileInfo(fileName).dir(); info.textureFileName = d.absoluteFilePath(tokens[1]); } } long nfaces = 0; long nedges = 0; // Attach callbacks for faces. Try both face.vertex_index and // face.vertex_indices since there doesn't seem to be a real standard. nfaces += ply_set_read_cb(ply.get(), "face", "vertex_index", face_cb, &info, PolygonBuilder::OuterRingInds); nfaces += ply_set_read_cb(ply.get(), "face", "vertex_indices", face_cb, &info, PolygonBuilder::OuterRingInds); // Attach callbacks for polygons with holes. // This isn't a standard at all, it's something I just made up :-/ long npolygons = 0; npolygons += ply_set_read_cb(ply.get(), "polygon", "vertex_index", face_cb, &info, PolygonBuilder::OuterRingInds); npolygons += ply_set_read_cb(ply.get(), "polygon", "outer_vertex_index", face_cb, &info, PolygonBuilder::OuterRingInds); // DEPRECATED nfaces += npolygons; if (npolygons > 0) { // Holes if (ply_set_read_cb(ply.get(), "polygon", "inner_vertex_counts", face_cb, &info, PolygonBuilder::InnerRingSizes)) { if (!ply_set_read_cb(ply.get(), "polygon", "inner_vertex_index", face_cb, &info, PolygonBuilder::InnerRingInds)) { g_logger.error("Found ply property polygon.inner_vertex_counts " "without polygon.inner_vertex_index"); return false; } info.currPoly.setPropertiesAvailable(PolygonBuilder::OuterRingInds | PolygonBuilder::InnerRingSizes | PolygonBuilder::InnerRingInds); } } // Attach callbacks for edges. AFAIK this isn't really a standard, I'm // just copying the semi-standard people use for faces. nedges += ply_set_read_cb(ply.get(), "edge", "vertex_index", edge_cb, &info, 0); nedges += ply_set_read_cb(ply.get(), "edge", "vertex_indices", edge_cb, &info, 0); if (nedges <= 0 && nfaces <= 0) { g_logger.error("Expected more than zero edges or faces in ply file"); return false; } if (!ply_read(ply.get())) { g_logger.error("Error reading ply file data section"); return false; } info.postprocess(); if (info.colors.size() != info.verts.size()) info.colors.clear(); return true; }
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; }
int main(int argc, char **argv) { int nelems; char **elist; int file_type; float version; char header[MAX_HEADER_LENGTH]; PlyFile *ply; char *end; char *progname; char *inName = NULL; FILE *inFile = stdin; progname = argv[0]; argc--; argv++; /* Print usage? */ if (argc > 0 && !strcmp(argv[0], "-h")) { usage(progname); exit(-1); } /* optional input file (if not, read stdin ) */ if (argc > 0 && *argv[0] != '-') { inName = argv[0]; inFile = fopen(inName, "r"); if (inFile == NULL) { fprintf(stderr, "Error: Couldn't open input file %s\n", inName); usage(progname); exit(-1); } argc --; argv ++; } /* Check no extra args */ if (argc > 0) { fprintf(stderr, "Error: Unhandled arg: %s\n", argv[0]); usage(progname); exit(-1); } /* If it's a file, open it twice (first time checks it's a valid * ply file). If it's on stdin, just assume valid ply file, and * get the header in a single pass. */ if (inFile != stdin) { ply = ply_read(inFile, &nelems, &elist); if (!ply) { fprintf(stderr, "Not a Ply file.\n"); exit(1); } ply_close(ply); inFile = fopen(inName, "r"); } fread(header, 1, MAX_HEADER_LENGTH, inFile); header[MAX_HEADER_LENGTH-1] = 0; end = strstr(header, "end_header"); if (end == NULL) { fprintf(stderr, "Did not find end of header within the first "); fprintf(stderr, "%d bytes of the file.\n", MAX_HEADER_LENGTH); exit(1); } *(end+strlen("end_header")+1) = 0; printf("\n%s\n", header); }
DeformModel::DeformModel(const std::string &fname, unsigned int num_frame, float ply_scale) { Init(); // char ply_fname[256]; _num_frame = num_frame; for (unsigned int cur_f = 0; cur_f < _num_frame; cur_f++) { std::stringstream ply_fname; ply_fname << fname << cur_f << ".ply"; // sprintf(ply_fname, "%s%d.ply", fname, cur_f); std::cout << "Opening " << ply_fname.str() << std::endl; FILE *fp = fopen(ply_fname.str().c_str(), "rb"); assert(fp); // PLY object: PlyFile *ply; // PLY properties: char **elist; int nelems; // hand over the stream to the ply functions: ply = ply_read(fp, &nelems, &elist); assert(ply); int file_type; float version; ply_get_info(ply, &version, &file_type); for (int i=0; i<nelems; i++) { char *elem_name = elist[i]; int num_elems, nprops; PlyProperty **plist = ply_get_element_description(ply, elem_name, &num_elems, &nprops); bool has_vertex_x = false, has_vertex_y = false, has_vertex_z = false, has_colors = false; unsigned char color_components = 0; // this is a vertex: if (equal_strings ("vertex", elem_name)) { for (int j=0; j<nprops; j++) { if (equal_strings("x", plist[j]->name)) { ply_get_property (ply, elem_name, &vert_props[0]); /* x */ has_vertex_x = true; } else if (equal_strings("y", plist[j]->name)) { ply_get_property (ply, elem_name, &vert_props[1]); /* y */ has_vertex_y = true; } else if (equal_strings("z", plist[j]->name)) { ply_get_property (ply, elem_name, &vert_props[2]); /* z */ has_vertex_z = true; } else if (equal_strings("red", plist[j]->name)) { ply_get_property (ply, elem_name, &vert_props[3]); /* z */ color_components++; } else if (equal_strings("green", plist[j]->name)) { ply_get_property (ply, elem_name, &vert_props[4]); /* z */ color_components++; } else if (equal_strings("blue", plist[j]->name)) { ply_get_property (ply, elem_name, &vert_props[5]); /* z */ color_components++; } } has_colors = color_components == 3; // test for necessary properties if ((!has_vertex_x) || (!has_vertex_y) || (!has_vertex_z)) { logger->update("Warning: Vertex with less than 3 coordinated detected. Output will most likely be corrupt!"); continue; } // must be first frame, initialize structures: if (_num_vtx == 0) { _num_vtx = num_elems; _vtxs = new vec3f[_num_vtx*_num_frame]; _cur_vtxs = new vec3f[_num_vtx]; _prev_vtxs = new vec3f[_num_vtx]; _vtx_boxes = new BOX[_num_vtx]; _nrms = new vec3f[_num_vtx]; _vtx_fids = new id_list[_num_vtx]; cout << "Vtx # = " << _num_vtx << endl; if (has_colors) _colors = new color3[_num_vtx]; } // grab all the vertex elements PLYVertex plyNewVertex; for (int j=0; j<num_elems; j++) { ply_get_element(ply, (void *)&plyNewVertex); if (has_colors && cur_f == 0) { _colors[j].set(plyNewVertex.color); } _vtxs[cur_f*_num_vtx+j] = vec3f(plyNewVertex.coords) * ply_scale; if (cur_f == 0) { _prev_vtxs[j] = _cur_vtxs[j] = _vtxs[j]; } if (j != 0 && j%1000000 == 0) { cout << " - " << j << " of " << num_elems << " loaded." << endl; } } } // this is a face (and, hopefully, a triangle): else if (equal_strings ("face", elem_name) && _tris == NULL) { // I need this for..., otherwise error ... for (int j=0; j<nprops; j++) { if (equal_strings("vertex_indices", plist[j]->name)) { ply_get_property (ply, elem_name, &face_props[0]); /* vertex_indices */ } } /* grab all the face elements */ PLYFace plyFace; plyFace.other_props = NULL; list<edge2f> edgelist_temp; vector<tri3f> trilist_temp; for (int j = 0; j < num_elems; j++) { ply_get_element(ply, (void *)&plyFace); for (int fi = 0; fi < plyFace.nverts-2; fi++) { // // make a triangle in our format from PLY face + vertices // // copy vertex indices unsigned int id0, id1, id2; id0 = plyFace.verts[0]; id1 = plyFace.verts[fi+1]; id2 = plyFace.verts[fi+2]; tri3f tri(id0, id1, id2); // insert triangle into list trilist_temp.push_back(tri); unsigned int fid = (unsigned int)trilist_temp.size()-1; edgelist_temp.push_back(edge2f(id0, id1, fid)); edgelist_temp.push_back(edge2f(id1, id2, fid)); edgelist_temp.push_back(edge2f(id2, id0, fid)); } free(plyFace.verts); if (j != 0 && j%500000 == 0) { cout << " - " << j << " of " << num_elems << " loaded." << endl; } } edgelist_temp.sort(); list<edge2f> edge_unqie; for (list<edge2f>::iterator it=edgelist_temp.begin(); it!=edgelist_temp.end(); it++) { if (!edge_unqie.empty() && *it == edge_unqie.back()) { // find duplicated with other fid unsigned int fid = (*it).fid(0); assert(fid != -1); edge_unqie.back().set_fid2(fid); } else edge_unqie.push_back(*it); } edgelist_temp.clear(); vector<edge2f> edge_array; _num_edge = (unsigned int)edge_unqie.size(); _edges = new edge2f[_num_edge]; _edg_boxes = new BOX[_num_edge]; unsigned int t=0; for (list<edge2f>::iterator it=edge_unqie.begin(); it != edge_unqie.end(); it++) { _edges[t++] = *it; edge_array.push_back(*it); } // copy over temp list to static array _num_tri = (unsigned int)trilist_temp.size(); cout << "Allocating " << _num_tri*sizeof(tri3f) << " bytes of storage for triangles." << endl; _tris = new tri3f[_num_tri]; _tri_nrms = new vec3f[_num_tri]; _old_tri_nrms = NULL; _tri_edges = new tri3e[_num_tri]; _fac_boxes = new BOX[_num_tri]; _tri_flags = new char[_num_tri]; vector <edge2f>::iterator first = edge_array.begin(); vector <edge2f>::iterator last = edge_array.end(); for (t = 0; t < _num_tri; t++) { _tris[t] = trilist_temp[t]; vector <edge2f>::iterator it1 = lower_bound(first, last, edge2f(_tris[t].id0(), _tris[t].id1(), 0)); vector <edge2f>::iterator it2 = lower_bound(first, last, edge2f(_tris[t].id1(), _tris[t].id2(), 0)); vector <edge2f>::iterator it3 = lower_bound(first, last, edge2f(_tris[t].id2(), _tris[t].id0(), 0)); _tri_edges[t].set(it1-first, it2-first, it3-first); } cout << "Edge # = " << _num_edge << endl; cout << "Tri # = " << _num_tri << endl; } else // otherwise: skip all further NULL; } // PLY parsing ended, clean up vertex buffer and close the file // fclose(fp); ply_close(ply); } UpdateTriNorm(); for (unsigned t = 0; t < _num_tri; t++) for (int i=0; i<3; i++) { unsigned int vid = _tris[t].id(i); _vtx_fids[vid].push_back(t); } BufferAdjacent(); }
ExtTriangleMesh *ExtTriangleMesh::LoadExtTriangleMesh(const std::string &fileName, const bool usePlyNormals) { p_ply plyfile = ply_open(fileName.c_str(), NULL); if (!plyfile) { std::stringstream ss; ss << "Unable to read PLY mesh file '" << fileName << "'"; throw std::runtime_error(ss.str()); } if (!ply_read_header(plyfile)) { std::stringstream ss; ss << "Unable to read PLY header from '" << fileName << "'"; throw std::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) { std::stringstream ss; ss << "No vertices found in '" << fileName << "'"; throw std::runtime_error(ss.str()); } Triangle *vi; long plyNbTris = ply_set_read_cb(plyfile, "face", "vertex_indices", FaceCB, &vi, 0); if (plyNbTris <= 0) { std::stringstream ss; ss << "No triangles found in '" << fileName << "'"; throw std::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) || usePlyNormals) && (plyNbNormals != plyNbVerts)) { std::stringstream ss; ss << "Wrong count of normals in '" << fileName << "'"; throw std::runtime_error(ss.str()); } Spectrum *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); UV *uv; long plyNbUVs = ply_set_read_cb(plyfile, "vertex", "s", UVCB, &uv, 0); ply_set_read_cb(plyfile, "vertex", "t", UVCB, &uv, 1); p = new Point[plyNbVerts]; vi = new Triangle[plyNbTris]; if (plyNbColors == 0) c = NULL; else c = new Spectrum[plyNbVerts]; n = new Normal[plyNbVerts]; if (plyNbUVs == 0) uv = NULL; else uv = new UV[plyNbUVs]; if (!ply_read(plyfile)) { std::stringstream ss; ss << "Unable to parse PLY file '" << fileName << "'"; delete[] p; delete[] vi; delete[] c; delete[] n; delete[] uv; throw std::runtime_error(ss.str()); } ply_close(plyfile); const unsigned int vertexCount = plyNbVerts; const unsigned int triangleCount = plyNbTris; Point *vertices = p; Triangle *triangles = vi; Normal *vertNormals = n; Spectrum *vertColors = c; UV *vertUV = uv; if (!usePlyNormals) { // 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) { SDL_LOG("The model contains a degenerate normal (index " << i << ")"); ++printedWarning; } else if (printedWarning == 15) { SDL_LOG("The model contains more degenerate normals"); ++printedWarning; }*/ vertNormals[i] = Normal(0.f, 0.f, 1.f); } } } return new ExtTriangleMesh(vertexCount, triangleCount, vertices, triangles, vertNormals, vertColors, vertUV); }