#include #include #include #include #include #include #include #include "util.hpp" #include "shaders.hpp" static GLFWwindow* window; void framebuffer_size_callback(GLFWwindow* window, int width, int height) { glViewport(0, 0, width, height); } void processInput(GLFWwindow* window) { if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) glfwSetWindowShouldClose(window, true); } bool glfw_window_setup() { glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); window = glfwCreateWindow(800, 800, "LearnOpenGL", NULL, NULL); if (window == NULL) { std::cout << "Failed to create GLFW windoww" << std::endl; glfwTerminate(); return false; } glfwMakeContextCurrent(window); return true; } enum class ParserState { PREFIX, VERTEX, FACE, FACE_SKIP, }; std::optional, array>> load_icosphere() { std::FILE* f = NULL; if (fopen_s(&f, "Icosphere.obj", "r")) { return {}; } // MEMORY LEAK!!! 84 verts currently float* vert_data = (float*)malloc(sizeof(float) * 128); size_t vert_data_size = 0; // MEMORY LEAK!!! (I think) unsigned int* indices_data = (unsigned int*)malloc(sizeof(int) * 256); size_t indices_data_size = 0; ParserState state = ParserState::PREFIX; char ln[128]; int len = 0; int start = 0; while ((ln[len] = std::fgetc(f)) != EOF) { switch (state) { case ParserState::PREFIX: if (len > 0 && ln[len - 1] == 'v' && ln[len] == ' ') { state = ParserState::VERTEX; start = len + 1; } else if (len > 0 && ln[len - 1] == 'f' && ln[len] == ' ') { state = ParserState::FACE; start = len + 1; } break; case ParserState::VERTEX: if (ln[len] == ' ' || ln[len] == '\n') { vert_data[vert_data_size] = atof(&ln[start]); vert_data_size++; start = len + 1; } break; case ParserState::FACE: if (ln[len] == '/') { state = ParserState::FACE_SKIP; indices_data[indices_data_size] = atoi(&ln[start]) - 1; indices_data_size++; } break; case ParserState::FACE_SKIP: if (ln[len] == ' ') { state = ParserState::FACE; start = len + 1; } } if (ln[len] == '\n') { len = 0; state = ParserState::PREFIX; } len++; } array verts = { vert_data, vert_data_size }; array indices = { indices_data, indices_data_size }; return std::make_pair(verts, indices); } int main() { if (!glfw_window_setup()) return -1; auto data = load_icosphere(); if (!data) { std::cout << "ERROR loading the icosphere obj file failed" << std::endl; return -1; } auto verts = data.value().first; auto indices = data.value().second; if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { std::cout << "Failed to initialize GLAD" << std::endl; return -1; } glViewport(0, 0, 800, 800); glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); // Write to back buffer glfwSwapBuffers(window); // front buffer is now back glClear(GL_COLOR_BUFFER_BIT); // Write to back buffer again (former front buf) unsigned int VAO; glGenVertexArrays(1, &VAO); glBindVertexArray(VAO); unsigned int VBO; glGenBuffers(1, &VBO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, verts.len * sizeof(float), verts.data, GL_STATIC_DRAW); unsigned int EBO; glGenBuffers(1, &EBO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.len * sizeof(unsigned int), indices.data, GL_STATIC_DRAW); uint program_id; const char* vertex_filepath = "src/shaders/vertex.glsl"; const char* fragment_filepath = "src/shaders/fragment.glsl"; if (!shader::load(&program_id, vertex_filepath, fragment_filepath)) return -1; shader::use(program_id); // Tell opengl which attribute our data is for (i.e. location) glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); while (!glfwWindowShouldClose(window)) { float time = glfwGetTime(); shader::set_uniform(program_id, "color", vec4 { 1, sin(time), 1, 1.0 }); shader::use(program_id); glClear(GL_COLOR_BUFFER_BIT); glDrawElements(GL_TRIANGLES, indices.len, GL_UNSIGNED_INT, 0); glBindVertexArray(VAO); processInput(window); glfwSwapBuffers(window); glfwPollEvents(); } glfwTerminate(); return 0; }