| 260 | } |
| 261 | |
| 262 | bool OBJParser::parse_face_line(char* line) { |
| 263 | const char WHITE_SPACE[] = " \t\n\r"; |
| 264 | constexpr int INVALID = std::numeric_limits<int>::max(); |
| 265 | char* field = strtok(line, WHITE_SPACE); |
| 266 | assert(field != NULL); |
| 267 | |
| 268 | // Ignore header "f" |
| 269 | field = strtok(NULL, WHITE_SPACE); |
| 270 | |
| 271 | // Extract vertex idx |
| 272 | std::vector<size_t> idx; |
| 273 | std::vector<size_t> t_idx; |
| 274 | std::vector<size_t> n_idx; |
| 275 | int v_idx, vt_idx, vn_idx; |
| 276 | while (field != NULL) { |
| 277 | // Note each vertex field could be in any of the following formats: |
| 278 | // v_idx or v_idx/vt_idx or v_idx/vt_idx/vn_idx or v_idx//vn_idx |
| 279 | v_idx = vt_idx = vn_idx = INVALID; |
| 280 | v_idx = atoi(field); |
| 281 | char* loc = strchr(field, '/'); |
| 282 | if (loc != NULL) { |
| 283 | loc++; |
| 284 | vt_idx = atoi(loc); |
| 285 | loc = strchr(loc, '/'); |
| 286 | if (loc != NULL) { |
| 287 | loc++; |
| 288 | vn_idx = atoi(loc); |
| 289 | } |
| 290 | } |
| 291 | |
| 292 | if (v_idx == INVALID) return false; |
| 293 | |
| 294 | // Negative index means relative index from the vertices read so |
| 295 | // far. -1 refers to the last vertex read in. |
| 296 | if (v_idx < 0) { |
| 297 | v_idx = m_vertices.size() + v_idx + 1; |
| 298 | } |
| 299 | if (vt_idx < 0) { |
| 300 | vt_idx = m_corner_textures.size() + vt_idx + 1; |
| 301 | } |
| 302 | if (vn_idx < 0) { |
| 303 | vn_idx = m_corner_normals.size() + vn_idx + 1; |
| 304 | } |
| 305 | assert(v_idx > 0); |
| 306 | assert(vt_idx >= 0); |
| 307 | assert(vn_idx >= 0); |
| 308 | idx.push_back(v_idx-1); // OBJ has index starting from 1 |
| 309 | if (vt_idx != INVALID) t_idx.push_back(vt_idx-1); |
| 310 | else t_idx.push_back(INVALID); |
| 311 | if (vn_idx != INVALID) n_idx.push_back(vn_idx-1); |
| 312 | else n_idx.push_back(INVALID); |
| 313 | |
| 314 | // Get next token |
| 315 | field = strtok(NULL, WHITE_SPACE); |
| 316 | } |
| 317 | |
| 318 | const size_t num_idx_parsed = idx.size(); |
| 319 | if (num_idx_parsed == 3) { |