Example #1
0
bool write_off(const Surface_mesh& mesh, const std::string& filename)
{
    FILE* out = fopen(filename.c_str(), "w");
    if (!out)
        return false;


    // header
    fprintf(out, "OFF\n%d %d 0\n", mesh.n_vertices(), mesh.n_faces());


    // vertices
    Surface_mesh::Vertex_property<Surface_mesh::Point> points = mesh.get_vertex_property<Point>("v:point");
    for (Surface_mesh::Vertex_iterator vit=mesh.vertices_begin(); vit!=mesh.vertices_end(); ++vit)
    {
        const Point& p = points[vit];
        fprintf(out, "%.10f %.10f %.10f\n", p[0], p[1], p[2]);
    }


    // faces
    for (Surface_mesh::Face_iterator fit=mesh.faces_begin(); fit!=mesh.faces_end(); ++fit)
    {
        int nV = mesh.valence(fit);
        fprintf(out, "%d", nV);
        Surface_mesh::Vertex_around_face_circulator fvit=mesh.vertices(fit), fvend=fvit;
        do
        {
            fprintf(out, " %d", ((Surface_mesh::Vertex)fvit).idx());
        }
        while (++fvit != fvend);
        fprintf(out, "\n");
    }

    fclose(out);
    return true;
}
Example #2
0
int main(int argc, char** argv){
    if(argc!=3){
        cout << "usage:" << endl << "isoremesh bunny.obj remeshed.obj" << endl;
        return EXIT_FAILURE;
    }
    std::string input(argv[1]);
    std::string output(argv[2]);
    
    ///--- Load mesh
    Surface_mesh mesh;
    mesh.read(input);
    if(mesh.n_vertices()==0){
        cout << "Input mesh has 0 vertices" << endl;
        return EXIT_FAILURE;
    }
    
    ///--- Remesher is only for triangulations!
    mesh.triangulate();

    ///--- Compute bounding box
    Scalar bbox_diag_length = bounding_box(mesh).diagonal().norm();
    cout << "#vertices: " << mesh.n_vertices() << endl;
    cout << "bbox_diag_length: " << bbox_diag_length << endl;
            
    ///--- Perform remeshing    
    IsotropicRemesher remesher(mesh);
    remesher.num_iterations = 10;
    remesher.sharp_feature_deg = 45;
    remesher.longest_edge_length = 0.02*bbox_diag_length;
    remesher.keep_short_edges = false;
    remesher.reproject_to_surface = true;
    remesher.myout = &std::cout; ///< print output to...
    remesher.execute();
    
    ///--- Write to file
    mesh.write(output);
    return EXIT_SUCCESS;
}
bool read_obj(Surface_mesh& mesh, const std::string& filename)
{
    char   s[200];
    float  x, y, z;
    std::vector<Surface_mesh::Vertex>  vertices;
    std::vector<Texture_coordinate> all_tex_coords;   //individual texture coordinates
    std::vector<int> halfedge_tex_idx; //texture coordinates sorted for halfedges
    Surface_mesh::Halfedge_property <Texture_coordinate> tex_coords = mesh.halfedge_property<Texture_coordinate>("h:texcoord");
    bool with_tex_coord=false;

    // clear mesh
    mesh.clear();


    // open file (in ASCII mode)
    FILE* in = fopen(filename.c_str(), "r");
    if (!in) return false;


    // clear line once
    memset(&s, 0, 200);


    // parse line by line (currently only supports vertex positions & faces
    while(in && !feof(in) && fgets(s, 200, in))
    {
        // comment
        if (s[0] == '#' || isspace(s[0])) continue;

        // vertex
        else if (strncmp(s, "v ", 2) == 0)
        {
            if (sscanf(s, "v %f %f %f", &x, &y, &z))
            {
                mesh.add_vertex(Point(x,y,z));
            }
        }
        // normal
        else if (strncmp(s, "vn ", 3) == 0)
        {
          if (sscanf(s, "vn %f %f %f", &x, &y, &z))
          {
            // problematic as it can be either a vertex property when interpolated
            // or a halfedge property for hard edges
          }
        }

        // texture coordinate
        else if (strncmp(s, "vt ", 3) == 0)
        {
          if (sscanf(s, "vt %f %f", &x, &y))
          {
            z=1;
            all_tex_coords.push_back(Texture_coordinate(x,y,z));
          }
        }

        // face
        else if (strncmp(s, "f ", 2) == 0)
        {
          int component(0), nV(0);
          bool endOfVertex(false);
          char *p0, *p1(s+1);

          vertices.clear();
          halfedge_tex_idx.clear();

          // skip white-spaces
          while (*p1==' ') ++p1;

          while (p1)
          {
            p0 = p1;

            // overwrite next separator

            // skip '/', '\n', ' ', '\0', '\r' <-- don't forget Windows
            while (*p1!='/' && *p1!='\r' && *p1!='\n' && *p1!=' ' && *p1!='\0') ++p1;

            // detect end of vertex
            if (*p1 != '/')
            {
              endOfVertex = true;
            }

            // replace separator by '\0'
            if (*p1 != '\0')
            {
              *p1 = '\0';
              p1++; // point to next token
            }

            // detect end of line and break
            if (*p1 == '\0' || *p1 == '\n')
            {
              p1 = 0;
            }

            // read next vertex component
            if (*p0 != '\0')
            {
              switch (component)
              {
                case 0: // vertex
                {
                  vertices.push_back( Surface_mesh::Vertex(atoi(p0) - 1) );
                  break;
                }
                case 1: // texture coord
                {
                  int idx = atoi(p0)-1;
                  halfedge_tex_idx.push_back(idx);
                  with_tex_coord=true;
                  break;
                }
                case 2: // normal
                  break;
              }
            }

            ++component;

            if (endOfVertex)
            {
              component = 0;
              nV++;
              endOfVertex = false;
            }
          }

          Surface_mesh::Face f=mesh.add_face(vertices);


          // add texture coordinates
          if(with_tex_coord)
          {
              Surface_mesh::Halfedge_around_face_circulator h_fit = mesh.halfedges(f);
              Surface_mesh::Halfedge_around_face_circulator h_end = h_fit;
              unsigned v_idx =0;
              do
              {
                  tex_coords[*h_fit]=all_tex_coords.at(halfedge_tex_idx.at(v_idx));
                  ++v_idx;
                  ++h_fit;
              }
              while(h_fit!=h_end);
          }
        }
        // clear line
        memset(&s, 0, 200);
    }

    fclose(in);
    return true;
}
bool write_obj(const Surface_mesh& mesh, const std::string& filename)
{
    FILE* out = fopen(filename.c_str(), "w");
    if (!out)
        return false;

    // comment
    fprintf(out, "# OBJ export from Surface_mesh\n");

    //vertices
    Surface_mesh::Vertex_property<Point> points = mesh.get_vertex_property<Point>("v:point");
    for (Surface_mesh::Vertex_iterator vit=mesh.vertices_begin(); vit!=mesh.vertices_end(); ++vit)
    {
        const Point& p = points[*vit];
        fprintf(out, "v %.10f %.10f %.10f\n", p[0], p[1], p[2]);
    }

    //normals
    Surface_mesh::Vertex_property<Point> normals = mesh.get_vertex_property<Point>("v:normal");
    for (Surface_mesh::Vertex_iterator vit=mesh.vertices_begin(); vit!=mesh.vertices_end(); ++vit)
    {
        const Point& p = normals[*vit];
        fprintf(out, "vn %.10f %.10f %.10f\n", p[0], p[1], p[2]);
    }

    //optionally texture coordinates
    // do we have them?
    std::vector<std::string> h_props= mesh.halfedge_properties();
    bool with_tex_coord = false;
    std::vector<std::string>::iterator h_prop_end = h_props.end();
    std::vector<std::string>::iterator h_prop_start= h_props.begin();
    while(h_prop_start!=h_prop_end)
    {
        if(0==(*h_prop_start).compare("h:texcoord"))
        {
            with_tex_coord=true;
        }
        ++h_prop_start;
    }

    //if so then add
    if(with_tex_coord)
    {
        Surface_mesh::Halfedge_property<Texture_coordinate> tex_coord = mesh.get_halfedge_property<Texture_coordinate>("h:texcoord");
        for (Surface_mesh::Halfedge_iterator hit=mesh.halfedges_begin(); hit!=mesh.halfedges_end(); ++hit)
        {
            const Texture_coordinate& pt = tex_coord[*hit];
            fprintf(out, "vt %.10f %.10f %.10f\n", pt[0], pt[1], pt[2]);
        }
    }

    //faces
    for (Surface_mesh::Face_iterator fit=mesh.faces_begin(); fit!=mesh.faces_end(); ++fit)
    {
        fprintf(out, "f");
        Surface_mesh::Vertex_around_face_circulator fvit=mesh.vertices(*fit), fvend=fvit;
        Surface_mesh::Halfedge_around_face_circulator fhit=mesh.halfedges(*fit);
        do
        {
            if(with_tex_coord)
            {
                // write vertex index, tex_coord index and normal index
                fprintf(out, " %d/%d/%d", (*fvit).idx()+1, (*fhit).idx()+1, (*fvit).idx()+1);
                ++fhit;
            }
            else
            {
                // write vertex index and normal index
                fprintf(out, " %d//%d", (*fvit).idx()+1, (*fvit).idx()+1);
            }
        }
        while (++fvit != fvend);
        fprintf(out, "\n");
    }

    fclose(out);
    return true;
}
Example #5
0
bool read_off(Surface_mesh& mesh, const std::string& filename)
{
    int err = 0;
    unsigned int       i, j, idx;
    unsigned int       nV, nF, nE;
    Eigen::Vector3d    p, n;
    Eigen::Vector2d    t;
    Surface_mesh::Vertex  v;
    char               line[100], *c;
    bool               has_texcoords = false;
    bool               has_normals   = false;
    bool               has_colors    = false;
    bool               has_hcoords   = false;
    bool               has_dim       = false;
    bool               is_binary     = false;


    // if mesh is not empty we need an offset for vertex indices
    const unsigned int voffset = mesh.n_vertices();


    // open file (in ASCII mode)
    FILE* in = fopen(filename.c_str(), "r");
    if (!in) return false;


    // read header: [ST][C][N][4][n]OFF BINARY
    c = fgets(line, 100, in);
    assert(c != NULL);
    c = line;
    if (c[0] == 'S' && c[1] == 'T') {
        has_texcoords = true;
        c += 2;
    }
    if (c[0] == 'C') {
        has_colors  = true;
        ++c;
    }
    if (c[0] == 'N') {
        has_normals = true;
        ++c;
    }
    if (c[0] == '4') {
        has_hcoords = true;
        ++c;
    }
    if (c[0] == 'n') {
        has_dim     = true;
        ++c;
    }
    if (strncmp(c, "OFF", 3) != 0) {
        fclose(in);    // no OFF
        return false;
    }
    if (strncmp(c+4, "BINARY", 6) == 0) is_binary = true;
    const bool binary = is_binary; // const might speed things up


    // colors, homogeneous coords, and vertex dimension != 3 are not supported
    if (has_colors || has_hcoords || has_dim)
    {
        fclose(in);
        return false;
    }


    // properties
    Surface_mesh::Vertex_property<Surface_mesh::Normal>  normals;
    Surface_mesh::Vertex_property<Surface_mesh::Texture_coordinate>  texcoords;
    if (has_normals)   normals   = mesh.vertex_property<Surface_mesh::Normal>("v:normal");
    if (has_texcoords) texcoords = mesh.vertex_property<Surface_mesh::Texture_coordinate>("v:texcoord");


    // if binary: reopen file in binary mode
    if (binary)
    {
        fclose(in);
        in = fopen(filename.c_str(), "rb");
        c = fgets(line, 100, in);
        assert(c != NULL);
    }

    // (ennetws) bug fix for comments, empty lines..
    while(!binary && true && !feof(in)) {
        fgets(line, 100, in);
        if(strlen(line) > 4 && line[0] != '#')
            break;
    }


    // #Vertice, #Faces, #Edges
    if (binary)
    {
        read(in, nV);
        read(in, nF);
        read(in, nE);
    }
    else
    {
        err = sscanf(line, "%d %d %d", (int*)&nV, (int*)&nF, (int*)&nE); // (ennetws) bug fix
    }
    mesh.reserve(nV, std::max(3*nV, nE), nF);

    // read vertices: pos [norma] [texcoord]
    if (has_normals && has_texcoords)
    {
        for (i=0; i<nV && !feof(in); ++i)
        {
            if (binary)
            {
                read(in, p);
                read(in, n);
                read(in, t);
            }
            else
            {
                err = fscanf(in, "%lf %lf %lf %lf %lf %lf %lf %lf", &p[0], &p[1], &p[2], &n[0], &n[1], &n[2], &t[0], &t[1]);
            }
            v = mesh.add_vertex(p);
            normals[v] = n;
            texcoords[v][0] = t[0];
            texcoords[v][1] = t[1];
        }
    }
    else if (has_normals)
    {
        for (i=0; i<nV && !feof(in); ++i)
        {
            if (binary)
            {
                read(in, p);
                read(in, n);
            }
            else
            {
                err = fscanf(in, "%lf %lf %lf %lf %lf %lf", &p[0], &p[1], &p[2], &n[0], &n[1], &n[2]);
            }
            v = mesh.add_vertex(p);
            normals[v] = n;
        }
    }
    else if (has_texcoords)
    {
        for (i=0; i<nV && !feof(in); ++i)
        {
            if (binary)
            {
                read(in, p);
                read(in, t);
            }
            else
            {
                err = fscanf(in, "%lf %lf %lf %lf %lf", &p[0], &p[1], &p[2], &t[0], &t[1]);
            }
            v = mesh.add_vertex(p);
            texcoords[v][0] = t[0];
            texcoords[v][1] = t[1];
        }
    }
    else
    {
        for (i=0; i<nV && !feof(in); ++i)
        {
            if (binary)
            {
                read(in, p);
            }
            else
            {
                err = fscanf(in, "%lf %lf %lf", &p[0], &p[1], &p[2]);
            }
            mesh.add_vertex(p);
        }
    }



    // read faces: #N v[1] v[2] ... v[n-1]
    std::vector<Surface_mesh::Vertex> vertices;
    for (i=0; i<nF; ++i)
    {
        if (binary)
        {
            read(in, nV);
            vertices.resize(nV);
            for (j=0; j<nV; ++j)
            {
                read(in, idx);
                vertices[j] = Surface_mesh::Vertex(idx+voffset);
            }
        }
        else
        {
            err = fscanf(in, "%d", (int*)&nV);
            vertices.resize(nV);
            for (j=0; j<nV; ++j)
            {
                err = fscanf(in, "%d", (int*)&idx);
                vertices[j] = Surface_mesh::Vertex(idx+voffset);
            }
        }
        mesh.add_face(vertices);
    }



    // File was successfully parsed.
    fclose(in);
    return true;
}
Example #6
0
bool read_off_ascii(Surface_mesh& mesh,
                    FILE* in,
                    const bool has_normals,
                    const bool has_texcoords,
                    const bool has_colors,
                    NamedParameters& np)
{
    char                 line[100], *lp;
    unsigned int         i, j, items, idx, nc;
    unsigned int         nV, nF, nE;
    Vec3f                p, n, c;
    Vec2f                t;
    Surface_mesh::Vertex v;
    typename CGAL::Polygon_mesh_processing::GetVertexPointMap<Surface_mesh, NamedParameters>::const_type
        vpm = choose_param(get_param(np, CGAL::boost::internal_np::vertex_point),
                           get_const_property_map(CGAL::vertex_point, mesh));


    // properties
    Surface_mesh::Vertex_property<Normal>              normals;
    Surface_mesh::Vertex_property<Texture_coordinate>  texcoords;
    Surface_mesh::Vertex_property<Color>               colors;
    if (has_normals)   normals   = mesh.vertex_property<Normal>("v:normal");
    if (has_texcoords) texcoords = mesh.vertex_property<Texture_coordinate>("v:texcoord");
    if (has_colors)    colors    = mesh.vertex_property<Color>("v:color");


    // #Vertice, #Faces, #Edges
    items = fscanf(in, "%d %d %d\n", (int*)&nV, (int*)&nF, (int*)&nE);
    mesh.clear();
    mesh.reserve(nV, std::max(3*nV, nE), nF);


    // read vertices: pos [normal] [color] [texcoord]
    for (i=0; i<nV && !feof(in); ++i)
    {
        // read line
        lp = fgets(line, 100, in);

        // position
        items = sscanf(lp, "%f %f %f%n", &p[0], &p[1], &p[2], &nc);
        assert(items==3);
        Surface_mesh::Vertex v = mesh.add_vertex();
        put(vpm, v, (Point)p);
        lp += nc;

        // normal
        if (has_normals)
        {
            if (sscanf(lp, "%f %f %f%n", &n[0], &n[1], &n[2], &nc) == 3)
            {
                normals[v] = n;
            }
            lp += nc;
        }

        // color
        if (has_colors)
        {
            if (sscanf(lp, "%f %f %f%n", &c[0], &c[1], &c[2], &nc) == 3)
            {
                if (c[0]>1.0f || c[1]>1.0f || c[2]>1.0f) c *= (1.0/255.0);
                colors[v] = c;
            }
            lp += nc;
        }

        // tex coord
        if (has_texcoords)
        {
            items = sscanf(lp, "%f %f%n", &t[0], &t[1], &nc);
            assert(items == 2);
            texcoords[v][0] = t[0];
            texcoords[v][1] = t[1];
            lp += nc;
        }
    }



    // read faces: #N v[1] v[2] ... v[n-1]
    std::vector<Surface_mesh::Vertex> vertices;
    for (i=0; i<nF; ++i)
    {
        // read line
        lp = fgets(line, 100, in);

        // #vertices
        items = sscanf(lp, "%d%n", (int*)&nV, &nc);
        assert(items == 1);
        vertices.resize(nV);
        lp += nc;

        // indices
        for (j=0; j<nV; ++j)
        {
            items = sscanf(lp, "%d%n", (int*)&idx, &nc);
            assert(items == 1);
            vertices[j] = Surface_mesh::Vertex(idx);
            lp += nc;
        }
        mesh.add_face(vertices);
    }


    return true;
}
Example #7
0
bool read_off_binary(Surface_mesh& mesh,
                     FILE* in,
                     const bool has_normals,
                     const bool has_texcoords,
                     const bool has_colors,
                     NamedParameters& np)
{
    unsigned int       i, j, idx;
    unsigned int       nV, nF, nE;
    Vec3f              p, n, c;
    Vec2f              t;
    Surface_mesh::Vertex  v;


    // binary cannot (yet) read colors
    if (has_colors) return false;


    // properties
    Surface_mesh::Vertex_property<Normal>              normals;
    Surface_mesh::Vertex_property<Texture_coordinate>  texcoords;
    if (has_normals)   normals   = mesh.vertex_property<Normal>("v:normal");
    if (has_texcoords) texcoords = mesh.vertex_property<Texture_coordinate>("v:texcoord");
    typename CGAL::Polygon_mesh_processing::GetVertexPointMap<Surface_mesh, NamedParameters>::const_type
        vpm = choose_param(get_param(np, CGAL::boost::internal_np::vertex_point),
                           get_const_property_map(CGAL::vertex_point, mesh));


    // #Vertice, #Faces, #Edges
    read(in, nV);
    read(in, nF);
    read(in, nE);
    mesh.clear();
    mesh.reserve(nV, std::max(3*nV, nE), nF);


    // read vertices: pos [normal] [color] [texcoord]
    for (i=0; i<nV && !feof(in); ++i)
    {
        // position
        read(in, p);
        Surface_mesh::Vertex v = mesh.add_vertex();
        put(vpm, v, (Point)p);

        // normal
        if (has_normals)
        {
            read(in, n);
            normals[v] = n;
        }

        // tex coord
        if (has_texcoords)
        {
            read(in, t);
            texcoords[v][0] = t[0];
            texcoords[v][1] = t[1];
        }
    }


    // read faces: #N v[1] v[2] ... v[n-1]
    std::vector<Surface_mesh::Vertex> vertices;
    for (i=0; i<nF; ++i)
    {
        read(in, nV);
        vertices.resize(nV);
        for (j=0; j<nV; ++j)
        {
            read(in, idx);
            vertices[j] = Surface_mesh::Vertex(idx);
        }
        mesh.add_face(vertices);
    }


    return true;
}