OpenGL-Practice/Object3D.cpp
Jackson H 46df79ca2a init
2024-06-04 10:31:34 -05:00

283 lines
8.9 KiB
C++

#include "Object3D.h"
#include <fstream>
#include <iostream>
#include <strstream>
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<float> temp_vertices;
std::vector<unsigned int> temp_indices;
std::vector<float> 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<float> Object3D::getVBOBuffer()
{
std::vector<float> 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;
}