#include "Object3D.h" #include #include #include Object3D::Object3D() = default; Object3D::Object3D(const std::string &file_path) { this->loadFromOBJ(file_path); } bool Object3D::loadFromOBJ(const std::string& file_path) { std::ifstream f(file_path); if (!f.is_open()) return false; std::vector temp_vertices; std::vector temp_indices; std::vector temp_normals; while (!f.eof()) { char line[128]; f.getline(line, 128); std::string l(line); // std::cout << "LINE: " << l << std::endl; if (line[0] == 'f') { l.erase(0, 2); // Erase the "f " size_t pos1 = 0; std::string token1; // Split by space while ((pos1 = l.find(' ')) != std::string::npos) { token1 = l.substr(0, pos1); int face_vert; if (l.find("//") != std::string::npos) { size_t pos2 = 0; std::string token2; bool face = true; while ((pos2 = token1.find("//")) != std::string::npos) { token2 = token1.substr(0, pos2); // std::cout << token1 << std::endl; if (face) { face_vert = std::stoi(token2) - 1; temp_indices.push_back(face_vert); face = false; } token1.erase(0, pos2 + 2); } // The Normal paired with the face is here if (!face) { // std::cout << "thisg" << std::endl; int face_normal = std::stoi(token1) - 1; // std::cout << "f " << face_vert + 1 << "//" << face_normal + 1 << std::endl; bool VBO_el_found = false; // If Vertice AND correct normal are already in VBO buffer just refernce that for (unsigned int i = 0; i < this->VBO_buffer.size(); i += 6) { bool vert_equal = true; bool normal_equal = true; // Since each Vertice & Normal are 3 elements we need to do a little looping for (int a = 0; a < 3; a++) { if (this->VBO_buffer[i + a] != temp_vertices[(face_vert * 3) + a]) { vert_equal = false; break; } } for (int a = 3; a < 6; a++) { if (this->VBO_buffer[i + a] != temp_normals[(face_normal * 3) + a - 3]) { normal_equal = false; break; } } if (vert_equal && normal_equal) { this->EBO_buffer.push_back(i / 6); VBO_el_found = true; } } // If not we need to add it to the VBO buffer if (!VBO_el_found) { // Again we need to add all three elements for each for (int a = 0; a < 3; a++) this->VBO_buffer.push_back(temp_vertices[face_vert * 3 + a]); for (int a = 0; a < 3; a++) this->VBO_buffer.push_back(temp_normals[face_normal * 3 + a]); this->EBO_buffer.push_back(this->VBO_buffer.size() / 6 - 1); } } // std::cout << l << std::endl; // temp_indices.push_back(std::stoi(token1) - 1); } l.erase(0, pos1 + 1); } // std::cout << "thing" << std::endl; // std::cout << l << std::endl; if (l.find("//") != std::string::npos) { size_t pos2 = 0; std::string token2; bool face = true; int face_vert; while ((pos2 = l.find("//")) != std::string::npos) { token2 = l.substr(0, pos2); face_vert = std::stoi(token2) - 1; if (face) { temp_indices.push_back(face_vert); face = false; } // Else case if I want to add normals for the faces l.erase(0, pos2 + 2); } // The Normal paired with the face is here if (!face) { // std::cout << "thisg" << std::endl; int face_normal = std::stoi(l) - 1; // std::cout << "f " << face_vert + 1 << "//" << face_normal + 1 << std::endl; bool VBO_el_found = false; // If Vertice AND correct normal are already in VBO buffer just refernce that for (unsigned int i = 0; i < this->VBO_buffer.size(); i += 6) { bool vert_equal = true; bool normal_equal = true; // Since each Vertice & Normal are 3 elements we need to do a little looping for (int a = 0; a < 3; a++) { if (this->VBO_buffer[i + a] != temp_vertices[(face_vert * 3) + a]) { vert_equal = false; break; } } for (int a = 3; a < 6; a++) { if (this->VBO_buffer[i + a] != temp_normals[(face_normal * 3) + a - 3]) { normal_equal = false; break; } } if (vert_equal && normal_equal) { this->EBO_buffer.push_back(i / 6); VBO_el_found = true; } } // If not we need to add it to the VBO buffer if (!VBO_el_found) { // Again we need to add all three elements for each for (int a = 0; a < 3; a++) this->VBO_buffer.push_back(temp_vertices[face_vert * 3 + a]); for (int a = 0; a < 3; a++) this->VBO_buffer.push_back(temp_normals[face_normal * 3 + a]); this->EBO_buffer.push_back(this->VBO_buffer.size() / 6 - 1); } } // std::cout << l << std::endl; // temp_indices.push_back(std::stoi(token1) - 1); } } else if (line[0] == 'v') { size_t pos1 = 0; std::string token1; bool normal = line[1] == 'n'; if (normal) { l.erase(0, 3); // Get rid of the "vn " } else { l.erase(0, 2); // Get rid of the "v " } // Split by space while ((pos1 = l.find(' ')) != std::string::npos) { token1 = l.substr(0, pos1); if (normal) { temp_normals.push_back(std::stof(token1)); } else { temp_vertices.push_back(std::stof(token1)); } l.erase(0, pos1 + 1); } // Last point is still left after the loop if (normal) { temp_normals.push_back(std::stof(l)); } else { temp_vertices.push_back(std::stof(l)); } } } this->vertices = temp_vertices; this->indices = temp_indices; this->normals = temp_normals; return true; } std::vector Object3D::getVBOBuffer() { std::vector temp_VBO_buffer; for (int i = 0; i < this->vertices.size() / 3; i++) { for (int a = 0; a < 3; a++) temp_VBO_buffer.push_back(this->vertices[(i * 3) + a]); for (int a = 0; a < 3; a++) temp_VBO_buffer.push_back(this->normals[(i * 3) + a]); } return temp_VBO_buffer; }