148 lines
3.7 KiB
C++
148 lines
3.7 KiB
C++
#include "mesh.hpp"
|
|
|
|
glm::mat4 default_model = glm::rotate(glm::mat4(1.0f), glm::radians(-55.0f), glm::vec3(0.0f, 1.0f, 0.0f));
|
|
|
|
glm::mat4 default_projection = glm::perspective(
|
|
glm::radians(45.0f),
|
|
(float)640 / (float)640,
|
|
0.1f,
|
|
100.0f);
|
|
|
|
std::vector<float>
|
|
load_obj(const std::string &path)
|
|
{
|
|
FILE *in = fopen(path.c_str(), "r");
|
|
|
|
if (in == NULL) {
|
|
// TODO: proper error
|
|
fprintf(stderr, "couldn't open model: %s\n", path.c_str());
|
|
return {};
|
|
}
|
|
|
|
char id[3];
|
|
float x, y, z;
|
|
int ibuf[9];
|
|
|
|
auto parse_line = [&]{
|
|
char c = fgetc(in);
|
|
fseek(in, -1L, SEEK_CUR);
|
|
if (c == EOF) {
|
|
return EOF;
|
|
}
|
|
else if (c == 'v') {
|
|
fscanf(in, "%s %f %f %f", id, &x, &y, &z);
|
|
}
|
|
else if (c == 'f') {
|
|
fscanf(in, "%s %d/%d/%d %d/%d/%d %d/%d/%d",
|
|
id,
|
|
&ibuf[0], &ibuf[1], &ibuf[2],
|
|
&ibuf[3], &ibuf[4], &ibuf[5],
|
|
&ibuf[6], &ibuf[7], &ibuf[8]);
|
|
}
|
|
else {
|
|
while (fgetc(in) != '\n');
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
};
|
|
|
|
std::vector<glm::vec3> vbuf;
|
|
std::vector<glm::vec2> vtbuf;
|
|
std::vector<glm::vec3> vnbuf;
|
|
std::vector<int> fbuf;
|
|
for (;;) {
|
|
int status = parse_line();
|
|
if (status == 1) {
|
|
if (!strcmp(id, "v")) {
|
|
vbuf.push_back(glm::vec3(x, y, z));
|
|
}
|
|
else if (!strcmp(id, "vt")) {
|
|
vtbuf.push_back(glm::vec2(x, y));
|
|
}
|
|
else if (!strcmp(id, "vn")) {
|
|
vnbuf.push_back(glm::vec3(x, y, z));
|
|
}
|
|
else if (!strcmp(id, "f")) {
|
|
for (int i = 0; i < 9; i++)
|
|
fbuf.push_back(ibuf[i]-1);
|
|
}
|
|
}
|
|
else if (status == EOF) break;
|
|
}
|
|
|
|
std::vector<float> product;
|
|
for (size_t i = 0; i < fbuf.size(); i += 3) {
|
|
product.push_back(vbuf[fbuf[i]].x);
|
|
product.push_back(vbuf[fbuf[i]].y);
|
|
product.push_back(vbuf[fbuf[i]].z);
|
|
product.push_back(vtbuf[fbuf[i+1]].x);
|
|
product.push_back(vtbuf[fbuf[i+1]].y);
|
|
product.push_back(vnbuf[fbuf[i+2]].x);
|
|
product.push_back(vnbuf[fbuf[i+2]].y);
|
|
product.push_back(vnbuf[fbuf[i+2]].z);
|
|
}
|
|
|
|
fclose(in);
|
|
|
|
return product;
|
|
}
|
|
|
|
Mesh::Mesh(
|
|
const std::vector<GLfloat> &vertices,
|
|
Shader *s)
|
|
:
|
|
vertex_num(vertices.size() / 8)
|
|
{
|
|
shader = std::shared_ptr<Shader>(s);
|
|
|
|
/* make the vao, vbo, and ebo */
|
|
glGenVertexArrays(1, &vao);
|
|
glGenBuffers(1, &vbo);
|
|
glBindVertexArray(vao);
|
|
|
|
/* copy vertices into vertex buffer */
|
|
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
|
glBufferData(
|
|
GL_ARRAY_BUFFER,
|
|
vertices.size() * sizeof(GLfloat),
|
|
&vertices[0],
|
|
GL_STATIC_DRAW);
|
|
|
|
/* set vertex attributes */
|
|
|
|
/* position */
|
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), 0);
|
|
glEnableVertexAttribArray(0);
|
|
|
|
/* texture coordinate */
|
|
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float),
|
|
(void*)(3 * sizeof(float)));
|
|
glEnableVertexAttribArray(1);
|
|
|
|
/* normal */
|
|
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float),
|
|
(void*)(5 * sizeof(float)));
|
|
glEnableVertexAttribArray(2);
|
|
|
|
shader->set_mat4("model", default_model);
|
|
shader->set_mat4("projection", default_projection);
|
|
|
|
}
|
|
|
|
Mesh::~Mesh()
|
|
{
|
|
glDeleteVertexArrays(1, &vao);
|
|
glDeleteBuffers(1, &vbo);
|
|
}
|
|
|
|
void
|
|
Mesh::draw() const
|
|
{
|
|
shader->use();
|
|
glBindVertexArray(vao);
|
|
glDrawArrays(GL_TRIANGLES, 0, vertex_num);
|
|
glBindVertexArray(0);
|
|
glUseProgram(0);
|
|
}
|