#ifndef OBJECT_H #define OBJECT_H #include #include #include #include #include #include using std::vector; using glm::vec3; using glm::mat4; typedef struct { vec3 position; vec3 color; vec3 normal; } Vertex; class Object { public: const char* path; vec3 position; vec3 rotation; vec3 scale; vector vertexData; vector vertices; vector normals; vector indices; vector normalIndices; unsigned int VAO; unsigned int VBO; unsigned int EBO; Texture texture1; Object() { } Object(const vec3 p, const vec3 r, const vec3 s, const char* objFilePath) { this->position = p; this->rotation = r; this->scale = s; this->path = objFilePath; std::string obj; std::ifstream objFile; std::stringstream objStringStream; objFile.exceptions(std::ifstream::failbit | std:: ifstream::badbit); try { objFile.open(objFilePath); objStringStream << objFile.rdbuf(); objFile.close(); obj = objStringStream.str(); } catch (std::ifstream::failure e) { std::cout << "Error reading obj file."; } std::string line; while (std::getline(objStringStream, line)) { //std::cout << "\n\nLINE: " << line << std::endl; std::istringstream lineStream(line); std::string lineType; lineStream >> lineType; //std::cout << lineType << std::endl; //std::cout << "Reading line of type " << lineType << std::endl; if (lineType == "v") { Vertex vertex; std::string token; float vector[3]; for (int i = 0 ; i < 6; i++) { //std::cout << "I VALUE: " << i << std::endl; float value = 1; if (!(lineStream >> token)) { vector[i % 3] = 1; //std::cout << "Adding 1 to vertexData because nothing else." << std::endl; } else { vector[i % 3] = std::stof(token); //std::cout << "Adding " << token << " to vertexData." << std::endl; } if (i == 2) { vertex.position = vec3(vector[0], vector[1], vector[2]); //std::cout << " BEGIN POSITION" << std::endl <> token)) { vector[i % 3] = 1; //std::cout << "Adding 1 to vertexData because nothing else." << std::endl; } else { vector[i % 3] = std::stof(token); //std::cout << "Adding " << token << " to vertexData." << std::endl; } if (i == 2) { normal = vec3(vector[0], vector[1], vector[2]); //std::cout << " BEGIN POSITION" << std::endl < tokenIndices; std::vector tokenTexCoords; std::vector tokenNormals; for (int i = 0; lineStream >> token; i++) { std::istringstream tokenStream(token); std::string element; int index, texCoord, normal; for (int i = 0; std::getline(tokenStream, element, '/'); i++) { //std::cout << "element is " << element << std::endl; switch (i) { // Vertex index case 0: index = std::stoi(token); tokenIndices.push_back(index); break; // Vertex texture coordinates case 1: texCoord = std::stoi(token); tokenTexCoords.push_back(texCoord); break; // Vertex normal case 2: if (normals.size() == 0) break; normal = std::stoi(token); tokenNormals.push_back(normal); break; } } } // Iterate through each index (X/0/0) in the f line for (int i = 1; i < tokenIndices.size() - 1; i++) { //std::cout << "token index " << i << std::endl; // Create triangle (0, i, i + 1) for (int which = 0; which < 3; which++) { int index; switch (which) { case 0: index = 0; break; case 1: index = i; break; case 2: index = i + 1; break; } if (index >= 0) { //std::cout << "pushing " < index) normalIndices.push_back(tokenNormals[index] - 1); //if (tokenNormals.size() == tokenIndices.size()) //{ // normals.push_back(tokenNormals[index - 1]); //} //std::cout << "Pushed " << index - 1 << " to indices" << std::endl; continue; } // Negative index indices.push_back((vertices.size()) + tokenIndices[index]); if (tokenNormals.size() > index) normalIndices.push_back((normals.size()) + tokenNormals[index]); //if (tokenNormals.size() == tokenIndices.size()) //{ // normals.push_back((vertexData.size() / 6) + tokenNormals[index]); //} //std::cout << "Pushed " << vertexData.size() + index << " to indices" << std::endl; } } } } std::cout << path << ": Indices: " << indices.size() << "; Normals: " << normalIndices.size() << std::endl; /*for (vec3 normal : normals) { std::cout << normal.x << " " << normal.y << " " << normal.z << std::endl; } */std::cout << std::endl; // Loop through indices and insert normals to vertices for (int i = 0; i < indices.size(); i++) { if (indices.size() != normalIndices.size()) { std::cout << "WARNING: Inequal number of vertex indices and normal indices. Skipping normals." << std::endl; break; } vertices[indices[i]].normal = normals[normalIndices[i]]; } // Generate vertexData for (int i = 0; i < vertices.size(); i++) { Vertex vertex = vertices[i]; vertexData.push_back(vertex.position.x); vertexData.push_back(vertex.position.y); vertexData.push_back(vertex.position.z); vertexData.push_back(vertex.color.x); vertexData.push_back(vertex.color.y); vertexData.push_back(vertex.color.z); vertexData.push_back(vertex.normal.x); vertexData.push_back(vertex.normal.y); vertexData.push_back(vertex.normal.z); //std::cout << vertex.position.x << " "; //std::cout << vertex.position.y << " "; //std::cout << vertex.position.z << "\t\t\t"; //std::cout << vertex.color.x << " "; //std::cout << vertex.color.y << " "; //std::cout << vertex.color.z << std::endl; } //std::cout << "Length of vertices: " << vertices.size() << std::endl; //std::cout << "Path of this one " << path << std::endl << std::endl; glGenVertexArrays(1, &VAO); glBindVertexArray(VAO); glGenBuffers(1, &VBO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, vertexData.size() * sizeof(float), &vertexData[0], GL_STATIC_DRAW); glGenBuffers(1, &EBO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(float), (void*)(3 * sizeof(float))); glEnableVertexAttribArray(1); glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(float), (void*)(6 * sizeof(float))); glEnableVertexAttribArray(2); } /* Object(const vec3 p, const vec3 r, const vec3 s, vector v, vector i, Texture t1 = nullptr) { this->position = p; this->rotation = r; this->scale = s; this->vertexData = v; this->indices = i; this->texture1 = t1; glGenVertexArrays(1, &VAO); glBindVertexArray(VAO); glGenBuffers(1, &VBO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, vertexData.size() * sizeof(float), &vertexData[0], GL_STATIC_DRAW); glGenBuffers(1, &EBO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(float), (void*)(3 * sizeof(float))); glEnableVertexAttribArray(1); glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(float), (void*)(6 * sizeof(float))); glEnableVertexAttribArray(2); } */ void draw(Shader s) { /*mat4 mod = rotationMatrix(); for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { std::cout << mod[i][j] << "\t"; } std::cout << std::endl; }*/ s.setMat4("modelMatrix", &modelMatrix()[0][0]); s.setMat4("normalMatrix", &normalMatrix()[0][0]); texture1.activate(0); s.use(); glBindVertexArray(VAO); glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0); s.setInt("texture1", 0); s.setVec3("lightColor", 1.0, 1.0, 1.0); s.setVec3("objectColor", 0.8, 0.4, 0.2); s.setVec3("lightPos", sin(glfwGetTime() / 3.0f) * 10, 8.0, cos(glfwGetTime() / 3.0f) * 10); glBindVertexArray(0); } mat4 translationMatrix() { return mat4( 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, position.x, position.y, position.z, 1 ); } mat4 rotationMatrix() { mat4 x( 1, 0, 0, 0, 0, cos(rotation.x), sin(rotation.x), 0, 0, -sin(rotation.x), cos(rotation.x), 0, 0, 0, 0, 1 ); mat4 y( cos(rotation.y), 0, -sin(rotation.y), 0, 0, 1, 0, 0, sin(rotation.y), 0, cos(rotation.y), 0, 0, 0, 0, 1 ); mat4 z( cos(rotation.z), sin(rotation.z), 0, 0, -sin(rotation.z), cos(rotation.z), 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ); return z * y * x; } mat4 scaleMatrix() { return mat4( scale.x, 0, 0, 0, 0, scale.y, 0, 0, 0, 0, scale.z, 0, 0, 0, 0, 1 ); } mat4 modelMatrix() { return translationMatrix() * rotationMatrix() * scaleMatrix(); } mat4 normalMatrix() { return glm::transpose(glm::inverse(modelMatrix())); } }; #endif