diff --git a/lab2/CMakeLists.txt b/lab2/CMakeLists.txt index 6a3485d..e38228d 100644 --- a/lab2/CMakeLists.txt +++ b/lab2/CMakeLists.txt @@ -22,7 +22,7 @@ add_executable( src/graphics/Mesh.cpp src/graphics/Shader.h src/graphics/Shader.cpp -) + src/graphics/MeshLoader.cpp src/graphics/MeshLoader.h) target_link_libraries(${PROJECT_NAME} glfw) target_link_libraries(${PROJECT_NAME} GLEW::GLEW) diff --git a/lab2/res/cube.blend b/lab2/res/cube.blend new file mode 100644 index 0000000..c6187a9 Binary files /dev/null and b/lab2/res/cube.blend differ diff --git a/lab2/res/cube.mtl b/lab2/res/cube.mtl new file mode 100644 index 0000000..1663250 --- /dev/null +++ b/lab2/res/cube.mtl @@ -0,0 +1,12 @@ +# Blender MTL File: 'cube.blend' +# Material Count: 1 + +newmtl Material +Ns 250.000000 +Ka 1.000000 1.000000 1.000000 +Kd 0.800000 0.800000 0.800000 +Ks 0.500000 0.500000 0.500000 +Ke 0.000000 0.000000 0.000000 +Ni 1.000000 +d 1.000000 +illum 2 diff --git a/lab2/res/cube.obj b/lab2/res/cube.obj new file mode 100644 index 0000000..0c3ba01 --- /dev/null +++ b/lab2/res/cube.obj @@ -0,0 +1,32 @@ +# Blender v3.4.1 OBJ File: 'cube.blend' +# www.blender.org +mtllib cube.mtl +o Cube +v 1.000000 1.000000 -1.000000 +v 1.000000 -1.000000 -1.000000 +v 1.000000 1.000000 1.000000 +v 1.000000 -1.000000 1.000000 +v -1.000000 1.000000 -1.000000 +v -1.000000 -1.000000 -1.000000 +v -1.000000 1.000000 1.000000 +v -1.000000 -1.000000 1.000000 +vn 0.0000 1.0000 0.0000 +vn 0.0000 0.0000 1.0000 +vn -1.0000 0.0000 0.0000 +vn 0.0000 -1.0000 0.0000 +vn 1.0000 0.0000 0.0000 +vn 0.0000 0.0000 -1.0000 +usemtl Material +s off +f 5//1 3//1 1//1 +f 3//2 8//2 4//2 +f 7//3 6//3 8//3 +f 2//4 8//4 6//4 +f 1//5 4//5 2//5 +f 5//6 2//6 6//6 +f 5//1 7//1 3//1 +f 3//2 7//2 8//2 +f 7//3 5//3 6//3 +f 2//4 4//4 8//4 +f 1//5 3//5 4//5 +f 5//6 1//6 2//6 diff --git a/lab2/res/main.vsh b/lab2/res/main.vsh index 252f521..cbc7383 100644 --- a/lab2/res/main.vsh +++ b/lab2/res/main.vsh @@ -1,7 +1,7 @@ #version 330 core layout (location = 0) in vec3 v_position; -layout (location = 1) in float light; +layout (location = 1) in vec3 v_normal; out vec4 a_color; uniform mat4 projview; @@ -9,6 +9,6 @@ uniform mat4 projview; void main(){ // gl_Position = vec4(v_position, 1) * projview; gl_Position = projview * vec4(v_position, 1); - a_color = vec4(0.5, 0, 1, 1) * light; + a_color = vec4(0.5, 0, 1, 1); } diff --git a/lab2/src/graphics/Mesh.cpp b/lab2/src/graphics/Mesh.cpp index d8c001a..2adcd87 100644 --- a/lab2/src/graphics/Mesh.cpp +++ b/lab2/src/graphics/Mesh.cpp @@ -43,7 +43,7 @@ void Mesh::reload(const float* buffer, size_t vertices){ this->vertices = vertices; } -void Mesh::draw(){ +void Mesh::draw() const{ glBindVertexArray(vao); glDrawArrays(GL_TRIANGLES, 0, vertices); glBindVertexArray(0); diff --git a/lab2/src/graphics/Mesh.h b/lab2/src/graphics/Mesh.h index 6786a56..993a47a 100644 --- a/lab2/src/graphics/Mesh.h +++ b/lab2/src/graphics/Mesh.h @@ -13,7 +13,7 @@ public: ~Mesh(); void reload(const float* buffer, size_t vertices); - void draw(); + void draw() const; }; #endif /* GRAPHICS_MESH_H_ */ diff --git a/lab2/src/graphics/MeshLoader.cpp b/lab2/src/graphics/MeshLoader.cpp new file mode 100644 index 0000000..f8de1f8 --- /dev/null +++ b/lab2/src/graphics/MeshLoader.cpp @@ -0,0 +1,162 @@ +// +// Created by vlad on 23.03.23. +// + +#include "MeshLoader.h" +#include +#include +#include +#include +#include +#include + + +enum ParserState { + IDLE, + COMMENT, + READ_STR +}; + +struct MeshPoint { + glm::vec3 point; + glm::vec3 normal; +}; + +Mesh *MeshLoader::loadMesh(const std::string &filename) { + std::vector points; + std::vector normals; + std::vector mesh_points; + + + std::ifstream file(filename + ".obj", std::ios::in); + + ParserState state = IDLE; + int line = 1; + + char tmp_buff[128]; + int tmp_buff_index = 0; + while (true) { + char in; + + file.read(&in, 1); + + if (file.eof()) { + break; + } + + if (tmp_buff_index >= 128) { + std::cerr << "[MeshLoader] Error: tmp buffer overflow" + " (line " << line << " file: " << filename << ")" << std::endl; + return nullptr; + } + + if (in == '\n') { + line++; + } + + switch (state) { + case IDLE: + tmp_buff[0] = in; + tmp_buff_index = 1; + + // нет состояния, возможно после пустой строки + if (in == '#' || in == 'o' || in == 's') { + // коммент если это информация о имени объекта или о сглаживании + state = COMMENT; + } else if (in == 'v' || in == 'f') { + state = READ_STR; + } + break; + + case COMMENT: + // строка коммента, читаем до конца линии + if (in == '\n') { + state = IDLE; + } + break; + + case READ_STR: + if (in == '\n') { + state = IDLE; + // парсим строку + tmp_buff[tmp_buff_index] = 0; // делаем null-terminator + tmp_buff_index = 0; + std::string source(tmp_buff); + + if (source.find("v ") == 0) { + // вершина + char* end = nullptr; + + glm::vec3 tmp_point(0, 0, 0); + tmp_point.x = std::strtof(tmp_buff + 2, &end); + tmp_point.y = std::strtof(end, &end); + tmp_point.z = std::strtof(end, &end); + points.push_back(tmp_point); + } else if (source.find("vn ") == 0) { + // нормаль + char* end = nullptr; + + glm::vec3 tmp_point(0, 0, 0); + tmp_point.x = std::strtof(tmp_buff + 3, &end); + tmp_point.y = std::strtof(end, &end); + tmp_point.z = std::strtof(end, &end); + normals.push_back(tmp_point); + } else if (source.find("f ") == 0) { + // фрагмент, он же треугольник + std::istringstream source_stream(tmp_buff + 2); + std::string point; + while (getline(source_stream, point, ' ')) { + std::istringstream point_stream(point); + std::string vertex, texture, normal; + getline(point_stream, vertex, '/'); + getline(point_stream, texture, '/'); + getline(point_stream, normal, '\0'); // до конца строки + + MeshPoint p{}; + // сначала точка + int tmp = std::atoi(vertex.c_str()); + if (tmp > 0) { + tmp -= 1; + p.point = points[tmp]; + } + + tmp = std::atoi(normal.c_str()); + if (tmp > 0) { + tmp -= 1; + p.normal = normals[tmp]; + } + + mesh_points.push_back(p); + } + } + } else { + tmp_buff[tmp_buff_index++] = in; + } + break; + } + } + + // тут имеем готовый массив вершин + // размер меша = кол-во вершин * (3 + 3) + const int vertices = (int)mesh_points.size(); + auto* out_mesh = new float[vertices * (3 + 3)]; + + int curr_index = 0; + for (const auto& p : mesh_points) { + // точка + out_mesh[curr_index++] = p.point.x; + out_mesh[curr_index++] = p.point.y; + out_mesh[curr_index++] = p.point.z; + + // нормаль + out_mesh[curr_index++] = p.normal.x; + out_mesh[curr_index++] = p.normal.y; + out_mesh[curr_index++] = p.normal.z; + } + + const int attrs[] = {3, 3, 0}; + Mesh* m = new Mesh(out_mesh, vertices, attrs); + + delete[] out_mesh; + return m; +} diff --git a/lab2/src/graphics/MeshLoader.h b/lab2/src/graphics/MeshLoader.h new file mode 100644 index 0000000..700a359 --- /dev/null +++ b/lab2/src/graphics/MeshLoader.h @@ -0,0 +1,18 @@ +// +// Created by vlad on 23.03.23. +// + +#ifndef GRAPHICS_LABS_MESHLOADER_H +#define GRAPHICS_LABS_MESHLOADER_H + + +#include +#include "Mesh.h" + +class MeshLoader { +public: + static Mesh *loadMesh(const std::string &filename); +}; + + +#endif //GRAPHICS_LABS_MESHLOADER_H diff --git a/lab2/src/main.cpp b/lab2/src/main.cpp index ee1acdb..793c5cc 100644 --- a/lab2/src/main.cpp +++ b/lab2/src/main.cpp @@ -18,6 +18,7 @@ #include "window/Events.h" #include "graphics/Mesh.h" #include "graphics/Shader.h" +#include "graphics/MeshLoader.h" #define SPEED_FACTOR 2.5f @@ -78,6 +79,7 @@ static void updateCameraPosition(Camera& cam, float delta) { static Mesh* world; +static Mesh* model_mesh; static Shader* shader; static void drawWorld(Camera& cam) { auto projview = cam.getProjection() * cam.getView(); @@ -96,7 +98,8 @@ static void drawWorld(Camera& cam) { angle += 0.001f; shader->uniformMatrix("projview", projview * model_scale * model_translate * model_rotate); - world->draw(); +// world->draw(); + model_mesh->draw(); } @@ -141,20 +144,22 @@ void mainloop(Camera& camera) { void loadResources() { const float buffer[] = { // треугольник - // X Y Z Light - -1, -1, 0.5, 0.5, - 1, -1, 0.5, 0.1, - 0, 1, 0.5, 0.9, + // X Y Z nX nY nZ + -1, -1, 0.5, 0, 0, 1, + 1, -1, 0.5, 0, 0, 1, + 0, 1, 0.5, 0, 0, 1, - -1, -1, -0.5, 0.5, - 1, -1, -0.5, 0.1, - 0, 1, -0.5, 0.9, + -1, -1, -0.5, 0, 0, -1, + 1, -1, -0.5, 0, 0, -1, + 0, 1, -0.5, 0, 0, -1, }; const int mesh_attrs[] { - 3, 1, 0 + 3, 3, 0 }; world = new Mesh(buffer, 6, mesh_attrs); + model_mesh = MeshLoader::loadMesh("res/cube"); + shader = Shader::loadShader("res/main.vsh", "res/main.fsh"); }