33 const std::string obj_file_name,
34 std::vector<std::vector<double>> &
V,
35 std::vector<std::vector<double>> &TC,
36 std::vector<std::vector<double>> &N,
37 std::vector<std::vector<int>> &
F,
38 std::vector<std::vector<int>> &FTC,
39 std::vector<std::vector<int>> &FN,
40 std::vector<std::vector<int>> &L)
43 FILE *obj_file = fopen(obj_file_name.c_str(),
"r");
46 logger().error(
"OBJReader::read: {:s} could not be opened!", obj_file_name);
49 return read(obj_file,
V, TC, N,
F, FTC, FN, L);
54 std::vector<std::vector<double>> &
V,
55 std::vector<std::vector<double>> &TC,
56 std::vector<std::vector<double>> &N,
57 std::vector<std::vector<int>> &
F,
58 std::vector<std::vector<int>> &FTC,
59 std::vector<std::vector<int>> &FN,
60 std::vector<std::vector<int>> &L)
78 std::string tic_tac_toe(
"#");
80 const int LINE_MAX_LEN = 2048;
82 char line[LINE_MAX_LEN];
84 while (fgets(line, LINE_MAX_LEN, obj_file) != NULL)
86 char type[LINE_MAX_LEN];
88 if (sscanf(line,
"%s", type) == 1)
91 char *rest_of_line = &line[strlen(type)];
94 std::istringstream ls(&line[1]);
95 std::vector<double> vertex{std::istream_iterator<double>(ls),
96 std::istream_iterator<double>()};
113 sscanf(rest_of_line,
"%lf %lf %lf\n", &
x[0], &
x[1], &
x[2]);
117 "OBJReader::read: normal on line {:d} should have 3 "
123 std::vector<double> normal(count);
124 for (
int i = 0; i < count; i++)
134 sscanf(rest_of_line,
"%lf %lf %lf\n", &
x[0], &
x[1], &
x[2]);
135 if (count != 2 && count != 3)
138 "OBJReader::read: texture coords on line {:d} should have "
139 "2 or 3 coordinates (has {:d})",
144 std::vector<double> tex(count);
145 for (
int i = 0; i < count; i++)
153 const auto &shift = [&
V](
const int i) ->
int {
154 return i < 0 ? i +
V.size() : i - 1;
156 const auto &shift_t = [&TC](
const int i) ->
int {
157 return i < 0 ? i + TC.size() : i - 1;
159 const auto &shift_n = [&N](
const int i) ->
int {
160 return i < 0 ? i + N.size() : i - 1;
163 std::vector<int> ftc;
166 char word[LINE_MAX_LEN];
168 while (sscanf(rest_of_line,
"%s%n", word, &offset) == 1)
171 rest_of_line += offset;
174 if (sscanf(word,
"%ld/%ld/%ld", &i, &it, &in) == 3)
176 f.push_back(shift(i));
177 ftc.push_back(shift_t(it));
178 fn.push_back(shift_n(in));
180 else if (sscanf(word,
"%ld/%ld", &i, &it) == 2)
182 f.push_back(shift(i));
183 ftc.push_back(shift_t(it));
185 else if (sscanf(word,
"%ld//%ld", &i, &in) == 2)
187 f.push_back(shift(i));
188 fn.push_back(shift_n(in));
190 else if (sscanf(word,
"%ld", &i) == 1)
192 f.push_back(shift(i));
197 "OBJReader::read: face on line {:d} has invalid "
204 if ((f.size() > 0 && fn.size() == 0 && ftc.size() == 0)
205 || (f.size() > 0 && fn.size() == f.size()
207 || (f.size() > 0 && fn.size() == 0
208 && ftc.size() == f.size())
209 || (f.size() > 0 && fn.size() == f.size()
210 && ftc.size() == f.size()))
221 "OBJReader::read: face on line {:d} has invalid format",
229 std::istringstream ls(&line[1]);
230 std::vector<int> polyline{std::istream_iterator<int>(ls),
231 std::istream_iterator<int>()};
233 if (polyline.size() < 2)
236 "OBJReader::read: line element on line {:d} should have "
237 "at least 2 vertices",
243 for (
int i = 0; i < polyline.size(); i++)
245 polyline[i] = polyline[i] < 0 ? polyline[i] +
V.size()
249 L.push_back(polyline);
253 && (type[0] ==
'#' || type[0] ==
'g' || type[0] ==
's'
254 || strcmp(
"usemtl", type) == 0
255 || strcmp(
"mtllib", type) == 0))
262 std::string line_no_newline = remove_newline(line);
264 "OBJReader::read: ignored non-comment line {:d}: {:s}", line_no,
276 assert(
F.size() == FN.size());
277 assert(
F.size() == FTC.size());
283 const std::string obj_file_name,
284 std::vector<std::vector<double>> &
V,
285 std::vector<std::vector<int>> &
F,
286 std::vector<std::vector<int>> &L)
288 std::vector<std::vector<double>> TC, N;
289 std::vector<std::vector<int>> FTC, FN;
290 return read(obj_file_name,
V, TC, N,
F, FTC, FN, L);
294 const std::string str,
299 std::vector<std::vector<double>> vV, vTC, vN;
300 std::vector<std::vector<int>> vF, vFTC, vFN, vL;
301 bool success =
read(str, vV, vTC, vN, vF, vFTC, vFN, vL);
308 bool V_rect = igl::list_to_matrix(vV,
V);
314 bool F_rect = igl::list_to_matrix(vF,
F);
320 std::vector<std::vector<int>> vE;
321 for (
const std::vector<int> &polyline : vL)
323 for (
int i = 1; i < polyline.size(); i++)
325 vE.push_back({{polyline[i - 1], polyline[i]}});
328 bool E_rect = igl::list_to_matrix(vE, E);
331 logger().error(
"OBJReader::read: edges not rectangular matrix!");
static bool read(const std::string obj_file_name, std::vector< std::vector< double > > &V, std::vector< std::vector< double > > &TC, std::vector< std::vector< double > > &N, std::vector< std::vector< int > > &F, std::vector< std::vector< int > > &FTC, std::vector< std::vector< int > > &FN, std::vector< std::vector< int > > &L)
Read a mesh from an ascii obj file.