void parse_vn_statement() { Vector3d n; m_lexer.eat_blanks(); n.x = m_lexer.accept_double(); m_lexer.eat_blanks(); n.y = m_lexer.accept_double(); m_lexer.eat_blanks(); n.z = m_lexer.accept_double(); m_normals.push_back(n); }
void parse_vt_statement() { Vector2d v; m_lexer.eat_blanks(); v.x = m_lexer.accept_double(); m_lexer.eat_blanks(); v.y = m_lexer.accept_double(); m_lexer.eat_blanks(); if (!m_lexer.is_eol()) m_lexer.accept_double(); m_tex_coords.push_back(v); }
void parse_v_statement() { Vector3d v; m_lexer.eat_blanks(); v.x = m_lexer.accept_double(); m_lexer.eat_blanks(); v.y = m_lexer.accept_double(); m_lexer.eat_blanks(); v.z = m_lexer.accept_double(); m_lexer.eat_blanks(); if (!m_lexer.is_eol()) m_lexer.accept_double(); m_vertices.push_back(v); }
string parse_compound_identifier() { string identifier; m_lexer.eat_blanks(); while (!m_lexer.is_eol()) { const char* token; size_t token_length; m_lexer.accept_string(&token, &token_length); m_lexer.eat_blanks(); if (!identifier.empty()) identifier += ' '; identifier.append(token, token_length); } return identifier; }
string parse_mesh_name() { string mesh_name; while (!m_lexer.is_eol()) { const char* token; size_t token_length; m_lexer.accept_string(&token, &token_length); m_lexer.eat_blanks(); if (!mesh_name.empty()) mesh_name += ' '; mesh_name.append(token, token_length); } return mesh_name; }
void parse_o_g_statement() { m_lexer.eat_blanks(); // Retrieve the name of the upcoming mesh. const string upcoming_mesh_name = parse_mesh_name(); // Start a new mesh only if the name of the object or group actually changes. if (upcoming_mesh_name != m_mesh_name) { // End the current mesh. if (m_inside_mesh_def) { m_builder.end_mesh(); m_inside_mesh_def = false; } clear_keep_memory(m_vertex_index_mapping); clear_keep_memory(m_tex_coord_index_mapping); clear_keep_memory(m_normal_index_mapping); m_mesh_name = upcoming_mesh_name; } }
void parse_f_statement() { clear_keep_memory(m_face_vertex_indices); clear_keep_memory(m_face_tex_coord_indices); clear_keep_memory(m_face_normal_indices); while (true) { m_lexer.eat_blanks(); if (m_lexer.is_eol()) break; // // Recognized (epsilon) // Accept n // { const long n = m_lexer.accept_long(); const size_t v = fix_index(n, m_vertices.size()); m_face_vertex_indices.push_back(v); } // // Recognized n // Accept (epsilon), / // { const unsigned char c = m_lexer.get_char(); if (m_lexer.is_space(c)) continue; else if (c == '/') m_lexer.next_char(); else parse_error(); } // // Recognized n/ // Accept /, n // { const unsigned char c = m_lexer.get_char(); if (c == '/') { m_lexer.next_char(); goto skip; } else { const long n = m_lexer.accept_long(); const size_t vt = fix_index(n, m_tex_coords.size()); m_face_tex_coord_indices.push_back(vt); } } // // Recognized n/n // Accept (epsilon), / // { const unsigned char c = m_lexer.get_char(); if (m_lexer.is_space(c)) continue; else if (c == '/') m_lexer.next_char(); else parse_error(); } skip: // // Recognized n//, n/n/ // Accept (epsilon), n // { const unsigned char c = m_lexer.get_char(); if (m_lexer.is_space(c)) continue; else { const long n = m_lexer.accept_long(); const size_t vn = fix_index(n, m_normals.size()); m_face_normal_indices.push_back(vn); } } } // Check whether the face is well-formed. const size_t vc = m_face_vertex_indices.size(); const size_t tc = m_face_tex_coord_indices.size(); const size_t nc = m_face_normal_indices.size(); const bool well_formed = vc >= 3 && (tc == 0 || tc == vc) && (nc == 0 || nc == vc); if (well_formed) { // The face is well-formed, insert it into the mesh. insert_face_into_mesh(); } else { // The face is ill-formed, ignore it or abort parsing. if (m_options & StopOnInvalidFaceDef) throw ExceptionInvalidFaceDef(m_lexer.get_line_number()); } }
void parse_file() { while (true) { m_lexer.eat_blanks(); // Handle end of file. if (m_lexer.is_eof()) break; // Handle empty lines. if (m_lexer.is_eol()) { m_lexer.accept_newline(); continue; } const char* keyword; size_t keyword_length; m_lexer.accept_string(&keyword, &keyword_length); if (keyword_length == 1) { switch (keyword[0]) { case 'f': parse_f_statement(); break; case 'g': case 'o': parse_o_g_statement(); break; case 'v': parse_v_statement(); break; default: // Ignore unknown or unhandled statements. m_lexer.eat_line(); continue; } } else if (keyword_length == 2) { switch (keyword[0] * 256 + keyword[1]) { case 'v' * 256 + 'n': parse_vn_statement(); break; case 'v' * 256 + 't': parse_vt_statement(); break; default: // Ignore unknown or unhandled statements. m_lexer.eat_line(); continue; } } else if (strncmp(keyword, "usemtl", keyword_length) == 0) { parse_usemtl_statement(); } else { // Ignore unknown or unhandled statements. m_lexer.eat_line(); continue; } m_lexer.eat_blanks(); m_lexer.accept_newline(); } // End the definition of the last object. if (m_inside_mesh_def) m_builder.end_mesh(); }