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; }
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 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 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."); }
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); }
/* 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); } } }
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; }
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; }
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; }
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 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 ); }
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; }
void MeshBase::loadInfoFromPly( const std::string& filename ) { p_ply ply = ply_open( filename.c_str(), 0); if( !ply ) { throw MeshException( "Error opening ply file during first pass (" + filename + ")" ); } if( !ply_read_header( ply ) ) { throw MeshException( "Error parsing ply header during first pass (" + filename + ")" ); } // Simply get the counts without setting real callbacks; that's for the second pass int num_vertices = ply_set_read_cb( ply, "vertex", "x", NULL, NULL, 0 ); int num_normals = ply_set_read_cb( ply, "vertex", "nx", NULL, NULL, 3 ); int num_triangles = ply_set_read_cb( ply, "face", "vertex_indices", NULL, NULL, 0 ); m_num_vertices = num_vertices; m_num_normals = num_normals; initSingleGroup(); MeshGroup& group = getFirstGroup(); group.num_triangles = num_triangles; }
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 ; } }
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(); }
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; }
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; }
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; }
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; } }*/ }
/******************************************************************************* * 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 ); }
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); }
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; }
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); }