hello,
i was thinking about how to load multiple objects in modern OpenGL, but i’m stuck, i tried various things but seems none of them works, so i’m here again to ask you to help me:
this is the code that loads obj files:
#include <fstream>
#include <iostream>
#include <math.h>
#include "ContentManager.h"
GLvoid ContentManager::loadOBJ(const GLchar *file_path)
{
std::string line;
std::ifstream file(file_path);
if (file.fail())
std::cerr << "Cannot open file " << file_path << " file is illegible or doesn' t exist." << std::endl;
else
{
has_uv = false;
has_normal = false;
GLint vertex_count = 0;
GLint normal_count = 0;
GLint face_count = 0;
GLint uv_count = 0;
std::vector <GLfloat> temp_normal;
std::vector <GLuint> temp_normal_index;
GLfloat fill;
while (!file.eof())
{
std::getline(file, line);
if (line.c_str()[0] == 'v')
{
if (line.c_str()[1] == ' ')
{
vertex.resize(vertex_count + 3);
sscanf(line.c_str(), "v %f %f %f", &vertex[vertex_count], &vertex[vertex_count + 1], &vertex[vertex_count + 2]);
vertex_count += 3;
}
else if (line.c_str()[1] == 'n')
{
has_normal = true;
temp_normal.resize(normal_count + 3);
sscanf(line.c_str(), "vn %f %f %f", &temp_normal[normal_count], &temp_normal[normal_count + 1], &temp_normal[normal_count + 2]);
normal_count += 3;
//for now scan only vertices
}
else if (line.c_str()[1] == 't')
{
has_uv = true;
//for now scan only vertices
}
}
else if (line.c_str()[0] == 'f')
{
if (has_normal)
{
if (has_uv)
{
// scan all three value of vertex_index: vertex_vertex_index/uv_vertex_index/normal_vertex_index (x3)
vertex_index.resize(face_count + 3);
temp_normal_index.resize(face_count + 3);
sscanf(line.c_str(), "f %d/%d/%d %d/%d/%d %d/%d/%d", &vertex_index[face_count], &fill, &temp_normal_index[face_count], &vertex_index[face_count + 1], &fill, &temp_normal_index[face_count + 1], &vertex_index[face_count + 2], &fill, &temp_normal_index[face_count + 2]);
face_count += 3;
}
else if (!has_uv)
{
// scan only two value of vertex_index: vertex_vertex_index//normal_vertex_index (x3)
vertex_index.resize(face_count + 3);
temp_normal_index.resize(face_count + 3);
sscanf(line.c_str(), "f %d//%d %d//%d %d//%d", &vertex_index[face_count], &temp_normal_index[face_count], &vertex_index[face_count + 1], &temp_normal_index[face_count + 1], &vertex_index[face_count + 2], &temp_normal_index[face_count + 2]);
face_count += 3;
}
}
else if (!has_normal)
{
if (has_uv)
{
//scan only two value of vertex_index: vertex_vertex_index / uv_vertex_index (x3)
vertex_index.resize(face_count + 3);
sscanf(line.c_str(), "f %d/%d %d/%d %d/%d", &vertex_index[face_count], &fill, &vertex_index[face_count + 1], &fill, &vertex_index[face_count + 2], &fill);
face_count += 3;
}
else if (!has_uv)
{
//scan only one value of vertex_index: vertex_vertex_index (x3)
vertex_index.resize(face_count + 3);
sscanf(line.c_str(), "f %d %d %d", &vertex_index[face_count], &vertex_index[face_count + 1], &vertex_index[face_count + 2]);
face_count += 3;
}
}
}
}
if (has_normal)
{
normal.resize(vertex_count);
std::cout << face_count / 3 << std::endl;
for (GLint i = 0; i < vertex_index.size(); i++)
{
vertex_index[i] -= 1;
temp_normal_index[i] -= 1;
//std::cout << vertex_index[i] << std::endl;
}
temp_buffer_data.resize((vertex_index.size() + temp_normal_index.size()) * 3);
GLint j = 0;
for (GLint i = 0; i < buffer_data.size(); i += 6)
{
buffer_data[vertex_index[j] * 6] = vertex[vertex_index[j] * 3];
buffer_data[vertex_index[j] * 6 + 1] = vertex[vertex_index[j] * 3 + 1];
buffer_data[vertex_index[j] * 6 + 2] = vertex[vertex_index[j] * 3 + 2];
buffer_data[vertex_index[j] * 6 + 3] = temp_normal[temp_normal_index[j] * 3];
buffer_data[vertex_index[j] * 6 + 4] = temp_normal[temp_normal_index[j] * 3 + 1];
buffer_data[vertex_index[j] * 6 + 5] = temp_normal[temp_normal_index[j] * 3 + 2];
//std::cout << vertex_index[j] << " position: " << buffer_data[vertex_index[j] * 6] << " " << buffer_data[vertex_index[j] * 6 + 1] << " " << buffer_data[vertex_index[j] * 6 + 2] << " normal: " << buffer_data[vertex_index[j] * 6 + 3] << " " << buffer_data[vertex_index[j] * 6 + 4] << " " << buffer_data[vertex_index[j] * 6 + 5] << std::endl;
j++;
}
}
/*if (!has_normal)
{
for (GLint i = 0; i < vertex_index.size(); i++)
vertex_index[i] -= 1;
calculateNormals();
buffer_data.resize((vertex_index.size() + normal.size()));
GLint j = 0;
for (GLint i = 0; i < buffer_data.size(); i += 6)
{
buffer_data[vertex_index[j] * 6] = vertex[vertex_index[j] * 3];
buffer_data[vertex_index[j] * 6 + 1] = vertex[vertex_index[j] * 3 + 1];
buffer_data[vertex_index[j] * 6 + 2] = vertex[vertex_index[j] * 3 + 2];
buffer_data[vertex_index[j] * 6 + 3] = normal[j * 3];
buffer_data[vertex_index[j] * 6 + 4] = normal[j * 3 + 1];
buffer_data[vertex_index[j] * 6 + 5] = normal[j * 3 + 2];
//std::cout << vertex_index[j] << " position: " << buffer_data[vertex_index[j] * 6] << " " << buffer_data[vertex_index[j] * 6 + 1] << " " << buffer_data[vertex_index[j] * 6 + 2] << " normal: " << buffer_data[vertex_index[j] * 6 + 3] << " " << buffer_data[vertex_index[j] * 6 + 4] << " " << buffer_data[vertex_index[j] * 6 + 5] << std::endl;
j++;
}
}*/
}
}
GLvoid ContentManager::calculateNormals()
{
GLint normal_count = 0;
for (GLint i = 0; i < vertex_index.size(); i += 3)
{
normal.resize(vertex_index.size());
math::Vector3f temp_normal;
// v1 = p2 - p1 - > v1 = (p2x, p2y, p2z) - (p1x, p1y, p1z)
// v2 = p3 - p1 - > v2 = (p3x, p3y, p3z) - (p1x, p1y, p1z)
// - > v1 = (p2x - p1x, p2y - p1y, p2z - p1z)
// - > v2 = (p3x - p1x, p3y - p1y, p3z - p1z)
// Nx = ((v1y * v2z) - (v1z * v2y))
// Ny = ((v1z * v2x) - (v1x * v2z))
// Nz = ((v1x * v2y) - (v1y * v2x))
// - > Nx = ((p2y - p1y) * (p3z - p1z)) - ((p2z - p1z) * (p3y - p1y))
// - > Ny = ((p2z - p1z) * (p3x - p1x)) - ((p2x - p1x) * (p2z - p1z))
// - > Nz = ((p2x - p1x) * (p3y - p1y)) - ((p2y - p1y) * (p3x - p1x))
math::Vector3f p1 = math::vec3f(vertex[vertex_index[i] * 3], vertex[vertex_index[i] * 3 + 1], vertex[vertex_index[i] * 3 + 2]);
//std::cout << p1.x << " " << p1.y << " " << p1.z << std::endl;
math::Vector3f p2 = math::vec3f(vertex[vertex_index[i + 1] * 3], vertex[vertex_index[i + 1] * 3 + 1], vertex[vertex_index[i + 1] * 3 + 2]);
//std::cout << p2.x << " " << p2.y << " " << p2.z << std::endl;
math::Vector3f p3 = math::vec3f(vertex[vertex_index[i + 2] * 3], vertex[vertex_index[i + 2] * 3 + 1], vertex[vertex_index[i + 2] * 3 + 2]);
//std::cout << p3.x << " " << p3.y << " " << p3.z << std::endl;
math::Vector3f v1 = (p2 - p1);
math::Vector3f v2 = (p3 - p1);
temp_normal = math::normalize(math::cross(v1, v2));
normal[i + 0] = temp_normal.x;
normal[i + 1] = temp_normal.y;
normal[i + 2] = temp_normal.z;
//std::cout << normal[vertex_index[i + 0]] << " " << normal[vertex_index[i + 1]] << " " << normal[vertex_index[i + 2]] << std::endl;
normal_count += 1;
}
}
GLvoid ContentManager::initMesh(GLenum polygon_mode)
{
glGenVertexArrays(1, &vao[0]);
glGenBuffers(1, &vbo[0]);
glGenBuffers(1, &ebo[0]);
glBindVertexArray(vao[0]);
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
glBufferData(GL_ARRAY_BUFFER, buffer_data.size() * sizeof(GLfloat), &buffer_data[0], GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), 0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo[0]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, vertex_index.size() * sizeof(GLuint), &vertex_index[0], GL_STATIC_DRAW);
glBindVertexArray(NULL);
glPolygonMode(GL_FRONT_AND_BACK, polygon_mode);
}
GLvoid ContentManager::drawMesh(GLenum drawing_mode)
{
glBindVertexArray(vao[0]);
glDrawElements(drawing_mode, vertex_index.size(), GL_UNSIGNED_INT, 0);
glBindVertexArray(NULL);
}
GLvoid ContentManager::deleteMesh()
{
glDeleteBuffers(1, &ebo[0]);
glDeleteBuffers(1, &vbo[0]);
glDeleteVertexArrays(1, &vao[0]);
}
so, for what i need for now this works well on a single mesh, but how to adapt the code to load multiple objects, i read that i can use multiple VAOs or a single big VAO (hope this is correct), so my question is if someone of you can you help me to find my way through this