Exemple #1
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;
	}
	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 ;
	}
Exemple #3
0
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;
}
Exemple #4
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.");
}
Exemple #5
0
    void parse_ply(const std::string& filename, PLYParser* parser) {
        p_ply ply = ply_open(filename.c_str(), NULL, 0, NULL);
        assert_success(ply != NULL);
        assert_success(ply_read_header(ply));

        const char* elem_name;
        const char* prop_name;
        long num_elements;
        p_ply_element element = ply_get_next_element(ply, NULL);
        while (element != NULL) {
            assert_success(ply_get_element_info(element, &elem_name, &num_elements));

            p_ply_property property = ply_get_next_property(element, NULL);
            while (property != NULL) {
                assert_success(ply_get_property_info(property, &prop_name, NULL, NULL, NULL));

                ply_set_read_cb(ply, elem_name, prop_name, ply_parser_call_back, parser, 0);
                parser->add_property(elem_name, prop_name, num_elements);

                property = ply_get_next_property(element, property);
            }
            element = ply_get_next_element(ply, element);
        }
        assert_success(ply_read(ply));
        ply_close(ply);
    }
Exemple #6
0
/* 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);
        }
    }
}
Exemple #7
0
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;
}
Exemple #9
0
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;
}
Exemple #10
0
void MeshBase::loadDataFromPly( const std::string& filename )
{
  p_ply ply = ply_open( filename.c_str(), 0);
  if( !ply ) {
    throw MeshException( "Error opening ply file during second pass (" + filename + ")" );
  }

  if( !ply_read_header( ply ) ) {
    throw MeshException( "Error parsing ply header during second pass ("
                         + filename + ")" );
  }

  MeshGroup& group = getFirstGroup();

  PlyData data( m_vertex_data, m_normal_data, group.vertex_indices, group.normal_indices );

  ply_set_read_cb( ply, "vertex", "x", plyVertexLoadDataCB, &data, 0);
  ply_set_read_cb( ply, "vertex", "y", plyVertexLoadDataCB, &data, 1);
  ply_set_read_cb( ply, "vertex", "z", plyVertexLoadDataCB, &data, 2);

  ply_set_read_cb( ply, "vertex", "nx", plyVertexLoadDataCB, &data, 3);
  ply_set_read_cb( ply, "vertex", "ny", plyVertexLoadDataCB, &data, 4);
  ply_set_read_cb( ply, "vertex", "nz", plyVertexLoadDataCB, &data, 5);

  ply_set_read_cb( ply, "face", "vertex_indices", plyFaceLoadDataCB, &data, 0);

  if( !ply_read( ply ) ) {
    throw MeshException( "Error parsing ply file (" + filename + ")" );
  }
  ply_close(ply);
}
void 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;
}
Exemple #13
0
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 ;
		}
	}
Exemple #15
0
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();
}
Exemple #16
0
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;
}
Exemple #18
0
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;
}
Exemple #19
0
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;
		}
	}*/
}
Exemple #20
0
/*******************************************************************************
 *         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 );

}
Exemple #21
0
std::vector<std::shared_ptr<Shape>> CreatePLYMesh(
    const Transform *o2w, const Transform *w2o, bool reverseOrientation,
    const ParamSet &params,
    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);
}
Exemple #22
0
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;
}
Exemple #23
0
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);
}