433 lines
14 KiB
C++
433 lines
14 KiB
C++
|
|
#ifndef OBJECT_H
|
||
|
|
#define OBJECT_H
|
||
|
|
|
||
|
|
#include <glad/glad.h>
|
||
|
|
#include <GLFW/glfw3.h>
|
||
|
|
#include <glm/glm.hpp>
|
||
|
|
|
||
|
|
#include <shader.hpp>
|
||
|
|
#include <texture.hpp>
|
||
|
|
|
||
|
|
#include <vector>
|
||
|
|
|
||
|
|
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<float> vertexData;
|
||
|
|
|
||
|
|
vector<Vertex> vertices;
|
||
|
|
vector<vec3> normals;
|
||
|
|
vector<unsigned int> indices;
|
||
|
|
vector<unsigned int> 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 <<vector[0] << " ";
|
||
|
|
//std::cout << vector[1] << " ";
|
||
|
|
//std::cout << vector[2] << " " << std::endl;
|
||
|
|
}
|
||
|
|
else if (i == 5)
|
||
|
|
{
|
||
|
|
vertex.color = vec3(vector[0], vector[1], vector[2]);
|
||
|
|
//std::cout << " BEGIN COLOR" << std::endl <<vector[0] << " ";
|
||
|
|
//std::cout << vector[1] << " ";
|
||
|
|
//std::cout << vector[2] << " " << std::endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
}
|
||
|
|
vertices.push_back(vertex);
|
||
|
|
}
|
||
|
|
else if (lineType == "vn")
|
||
|
|
{
|
||
|
|
vec3 normal;
|
||
|
|
std::string token;
|
||
|
|
float vector[3];
|
||
|
|
for (int i = 0 ; i < 3; 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)
|
||
|
|
{
|
||
|
|
normal = vec3(vector[0], vector[1], vector[2]);
|
||
|
|
//std::cout << " BEGIN POSITION" << std::endl <<vector[0] << " ";
|
||
|
|
//std::cout << vector[1] << " ";
|
||
|
|
//std::cout << vector[2] << " " << std::endl;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
normals.push_back(normal);
|
||
|
|
}
|
||
|
|
else if (lineType == "f")
|
||
|
|
{
|
||
|
|
std::string token;
|
||
|
|
std::vector<unsigned int> tokenIndices;
|
||
|
|
std::vector<unsigned int> tokenTexCoords;
|
||
|
|
std::vector<unsigned int> 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 " <<tokenIndices[index] - 1 << " to indices" << std::endl;
|
||
|
|
indices.push_back(tokenIndices[index] - 1);
|
||
|
|
if (tokenNormals.size() > 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<float> v, vector<unsigned int> 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
|
||
|
|
|