• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

pmp-library / pmp-library / 15070098106

16 May 2025 01:52PM UTC coverage: 91.027% (-0.07%) from 91.097%
15070098106

push

github

mbotsch
improve curvature example GUI

5204 of 5717 relevant lines covered (91.03%)

646093.51 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

70.89
/src/pmp/io/read_obj.cpp
1
// Copyright 2011-2022 the Polygon Mesh Processing Library developers.
2
// Distributed under a MIT-style license, see LICENSE.txt for details.
3

4
#include "pmp/io/read_obj.h"
5
#include "pmp/exceptions.h"
6

7
namespace pmp {
8

9
void read_obj(SurfaceMesh& mesh, const std::filesystem::path& file)
1✔
10
{
11
    std::array<char, 200> s;
12
    float x, y, z;
13
    std::vector<Vertex> vertices;
1✔
14
    std::vector<TexCoord> all_tex_coords; //individual texture coordinates
1✔
15
    std::vector<int>
16
        halfedge_tex_idx; //texture coordinates sorted for halfedges
1✔
17
    HalfedgeProperty<TexCoord> tex_coords =
18
        mesh.halfedge_property<TexCoord>("h:tex");
3✔
19
    bool with_tex_coord = false;
1✔
20

21
    // open file (in ASCII mode)
22
    FILE* in = fopen(file.string().c_str(), "r");
1✔
23
    if (!in)
1✔
24
        throw IOException("Failed to open file: " + file.string());
×
25

26
    // clear line once
27
    memset(s.data(), 0, 200);
1✔
28

29
    // parse line by line (currently only supports vertex positions & faces
30
    while (in && !feof(in) && fgets(s.data(), 200, in))
12✔
31
    {
32
        // comment
33
        if (s[0] == '#' || isspace(s[0]))
5✔
34
            continue;
1✔
35

36
        // vertex
37
        else if (strncmp(s.data(), "v ", 2) == 0)
4✔
38
        {
39
            if (sscanf(s.data(), "v %f %f %f", &x, &y, &z))
3✔
40
            {
41
                mesh.add_vertex(Point(x, y, z));
3✔
42
            }
43
        }
44

45
        // normal
46
        else if (strncmp(s.data(), "vn ", 3) == 0)
1✔
47
        {
48
            if (sscanf(s.data(), "vn %f %f %f", &x, &y, &z))
×
49
            {
50
                // problematic as it can be either a vertex property when interpolated
51
                // or a halfedge property for hard edges
52
            }
53
        }
54

55
        // texture coordinate
56
        else if (strncmp(s.data(), "vt ", 3) == 0)
1✔
57
        {
58
            if (sscanf(s.data(), "vt %f %f", &x, &y))
×
59
            {
60
                all_tex_coords.emplace_back(x, y);
×
61
            }
62
        }
63

64
        // face
65
        else if (strncmp(s.data(), "f ", 2) == 0)
1✔
66
        {
67
            int component(0);
1✔
68
            bool end_of_vertex(false);
1✔
69
            char *p0, *p1(s.data() + 1);
1✔
70

71
            vertices.clear();
1✔
72
            halfedge_tex_idx.clear();
1✔
73

74
            // skip white-spaces
75
            while (*p1 == ' ')
2✔
76
                ++p1;
1✔
77

78
            while (p1)
4✔
79
            {
80
                p0 = p1;
3✔
81

82
                // overwrite next separator
83

84
                // skip '/', '\n', ' ', '\0', '\r' <-- don't forget Windows
85
                while (*p1 != '/' && *p1 != '\r' && *p1 != '\n' && *p1 != ' ' &&
6✔
86
                       *p1 != '\0')
3✔
87
                    ++p1;
3✔
88

89
                // detect end of vertex
90
                if (*p1 != '/')
3✔
91
                {
92
                    end_of_vertex = true;
3✔
93
                }
94

95
                // replace separator by '\0'
96
                if (*p1 != '\0')
3✔
97
                {
98
                    *p1 = '\0';
3✔
99
                    p1++; // point to next token
3✔
100
                }
101

102
                // detect end of line and break
103
                if (*p1 == '\0' || *p1 == '\n')
3✔
104
                {
105
                    p1 = nullptr;
1✔
106
                }
107

108
                // read next vertex component
109
                if (*p0 != '\0')
3✔
110
                {
111
                    switch (component)
3✔
112
                    {
113
                        case 0: // vertex
3✔
114
                        {
115
                            int idx = atoi(p0);
3✔
116
                            if (idx < 0)
3✔
117
                                idx = mesh.n_vertices() + idx + 1;
×
118
                            vertices.emplace_back(idx - 1);
3✔
119
                            break;
3✔
120
                        }
121
                        case 1: // texture coord
×
122
                        {
123
                            const int idx = atoi(p0) - 1;
×
124
                            halfedge_tex_idx.push_back(idx);
×
125
                            with_tex_coord = true;
×
126
                            break;
×
127
                        }
128
                        case 2: // normal
×
129
                            break;
×
130
                    }
131
                }
132

133
                ++component;
3✔
134

135
                if (end_of_vertex)
3✔
136
                {
137
                    component = 0;
3✔
138
                    end_of_vertex = false;
3✔
139
                }
140
            }
141

142
            Face f;
1✔
143
            try
144
            {
145
                f = mesh.add_face(vertices);
1✔
146
            }
147
            catch (const TopologyException& e)
×
148
            {
149
                std::cerr << e.what();
×
150
            }
×
151

152
            // add texture coordinates
153
            if (with_tex_coord && f.is_valid())
1✔
154
            {
155
                auto h_fit = mesh.halfedges(f);
×
156
                auto h_end = h_fit;
×
157
                unsigned v_idx = 0;
×
158
                do
159
                {
160
                    tex_coords[*h_fit] =
×
161
                        all_tex_coords.at(halfedge_tex_idx.at(v_idx));
×
162
                    ++v_idx;
×
163
                    ++h_fit;
×
164
                } while (h_fit != h_end);
×
165
            }
166
        }
167
        // clear line
168
        memset(s.data(), 0, 200);
4✔
169
    }
170

171
    // if there are no textures, delete texture property!
172
    if (!with_tex_coord)
1✔
173
    {
174
        mesh.remove_halfedge_property(tex_coords);
1✔
175
    }
176

177
    fclose(in);
1✔
178
}
1✔
179

180
} // namespace pmp
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc