#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include extern "C" { #include "shader.h" } #define WIDTH 1024 #define HEIGHT 768 static void glfwErrorCallback(int e, const char *description) { fprintf(stderr, "GLFW Error %d: %s", e, description); } bool loadModel(const char *path, std::vector &indices, std::vector &vertices, std::vector &uvs, std::vector &normals) { Assimp::Importer importer; const aiScene *scene = importer.ReadFile( path, aiProcess_Triangulate | aiProcess_JoinIdenticalVertices | aiProcess_SortByPType); if (!scene) { fprintf(stderr, "%s\n", importer.GetErrorString()); return false; } const aiMesh *mesh = scene->mMeshes[0]; vertices.reserve(mesh->mNumVertices); for (unsigned int i = 0; i < mesh->mNumVertices; i++) { aiVector3D pos = mesh->mVertices[i]; vertices.push_back(glm::vec3(pos.x, pos.y, pos.z)); } uvs.reserve(mesh->mNumVertices); for (unsigned int i = 0; i < mesh->mNumVertices; i++) { aiVector3D UVW = mesh->mTextureCoords[0][i]; // Multiple UVs? Prepsterous! uvs.push_back(glm::vec2(UVW.x, UVW.y)); } normals.reserve(mesh->mNumVertices); for (unsigned int i = 0; i < mesh->mNumFaces; i++) { indices.push_back(mesh->mFaces[i].mIndices[0]); indices.push_back(mesh->mFaces[i].mIndices[1]); indices.push_back(mesh->mFaces[i].mIndices[2]); } return true; } int initWindow() { glfwSetErrorCallback(glfwErrorCallback); glewExperimental = true; if (!glfwInit()) { fprintf(stderr, "GLFW went shitty time\n"); return 1; } glfwWindowHint(GLFW_SAMPLES, 4); // 4x Antialiasing glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // Loser MacOS is broken glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // New GL GLFWwindow *window; window = glfwCreateWindow(WIDTH, HEIGHT, "Fred", NULL, NULL); if (window == NULL) { fprintf(stderr, "Failed to open window.\n"); glfwTerminate(); return 1; } glfwMakeContextCurrent(window); glfwSwapInterval(1); int code; if ((code = glewInit()) != GLEW_OK) { fprintf(stderr, "Failed to init GLEW: %s\n", glewGetErrorString(code)); return 1; } IMGUI_CHECKVERSION(); ImGui::CreateContext(); ImGuiIO &io = ImGui::GetIO(); (void)io; io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; ImGui::StyleColorsDark(); ImGui_ImplGlfw_InitForOpenGL(window, true); ImGui_ImplOpenGL3_Init("#version 330"); std::vector indices; std::vector indexed_vertices; std::vector indexed_uvs; std::vector indexed_normals; if (!loadModel("../models/model.obj", indices, indexed_vertices, indexed_uvs, indexed_normals)) { return 0; } GLuint vertexArrayID; glGenVertexArrays(1, &vertexArrayID); glBindVertexArray(vertexArrayID); GLuint vertexBuffer; glGenBuffers(1, &vertexBuffer); glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); glBufferData(GL_ARRAY_BUFFER, indexed_vertices.size() * sizeof(glm::vec3), &indexed_vertices[0], GL_STATIC_DRAW); GLuint uvBuffer; glGenBuffers(1, &uvBuffer); glBindBuffer(GL_ARRAY_BUFFER, uvBuffer); glBufferData(GL_ARRAY_BUFFER, indexed_uvs.size() * sizeof(glm::vec2), &indexed_uvs[0], GL_STATIC_DRAW); GLuint normalBuffer; glGenBuffers(1, &normalBuffer); glBindBuffer(GL_ARRAY_BUFFER, normalBuffer); glBufferData(GL_ARRAY_BUFFER, indexed_normals.size() * sizeof(glm::vec3), &indexed_normals[0], GL_STATIC_DRAW); GLuint elementBuffer; glGenBuffers(1, &elementBuffer); glBindBuffer(GL_ARRAY_BUFFER, elementBuffer); glBufferData(GL_ARRAY_BUFFER, indices.size() * sizeof(unsigned short), &indices[0], GL_STATIC_DRAW); GLuint texture = SOIL_load_OGL_texture( "../textures/results/texture_BMP_DXT5_3.DDS", SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_MIPMAPS | SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_COMPRESS_TO_DXT); if (texture == 0) { printf("Texture failed to load\n"); return 0; } GLuint programID = loadShaders("../shaders/shader.vert", "../shaders/shader.frag"); // I love glm // Projection matrix, 45deg FOV, 4:3 Aspect Ratio, Planes: 0.1units -> // 100units glm::mat4 projection = glm::perspective( glm::radians(45.0f), (float)WIDTH / (float)HEIGHT, 0.1f, 100.0f); // Camera matrix glm::mat4 view = glm::lookAt(glm::vec3(4, 3, 3), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0)); glm::mat4 model = glm::mat4(1.0f); // Model view projection, the combination of the three vectors glm::mat4 mvp = projection * view * model; GLuint matrixID = glGetUniformLocation(programID, "MVP"); glEnable(GL_DEPTH_TEST); // Turn on the Z-buffer glDepthFunc(GL_LESS); // Accept only the closest fragments glEnable(GL_CULL_FACE); // Backface culling glClearColor(0.1f, 0.1f, 0.1f, 1.0f); // Define camera stuff glm::vec3 position = {4, 3, 3}; float horizontalAngle = 3.14F; // Toward -Z, in Rads float verticalAngle = 0.0f; // On the horizon float initialFOV = 60.0f; float speed = 3.0f; float mouseSpeed = 0.005f; double xpos, ypos; double lastTime = 0; while (glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS && glfwWindowShouldClose(window) == 0) { // Clear this mf glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glUseProgram(programID); // ImGui // if (glfwGetWindowAttrib(window, GLFW_ICONIFIED) != 0) { // ImGui_ImplGlfw_Sleep(10); // continue; // No rendering while minimized // } glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE); glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); ImGui_ImplOpenGL3_NewFrame(); ImGui_ImplGlfw_NewFrame(); ImGui::NewFrame(); // ImGui::ShowDemoWindow(); ImGui::Begin("DEBUG INFO"); ImGui::Text("MVP:"); if (ImGui::BeginTable("mvp", 4)) { ImGui::TableNextColumn(); ImGui::Text("%f", mvp[0][0]); ImGui::TableNextColumn(); ImGui::Text("%f", mvp[0][1]); ImGui::TableNextColumn(); ImGui::Text("%f", mvp[0][2]); ImGui::TableNextColumn(); ImGui::Text("%f", mvp[0][3]); ImGui::TableNextColumn(); ImGui::Text("%f", mvp[1][0]); ImGui::TableNextColumn(); ImGui::Text("%f", mvp[1][1]); ImGui::TableNextColumn(); ImGui::Text("%f", mvp[1][2]); ImGui::TableNextColumn(); ImGui::Text("%f", mvp[1][3]); ImGui::TableNextColumn(); ImGui::Text("%f", mvp[2][0]); ImGui::TableNextColumn(); ImGui::Text("%f", mvp[2][1]); ImGui::TableNextColumn(); ImGui::Text("%f", mvp[2][2]); ImGui::TableNextColumn(); ImGui::Text("%f", mvp[2][3]); ImGui::TableNextColumn(); ImGui::Text("%f", mvp[3][0]); ImGui::TableNextColumn(); ImGui::Text("%f", mvp[3][1]); ImGui::TableNextColumn(); ImGui::Text("%f", mvp[3][2]); ImGui::TableNextColumn(); ImGui::Text("%f", mvp[3][3]); ImGui::EndTable(); } ImGui::End(); // Compute a Fresh Super Sigma MVP // What would an input system be without delta time double currentTime = glfwGetTime(); float deltaTime = (float)(currentTime - lastTime); glfwGetCursorPos(window, &xpos, &ypos); glfwSetCursorPos(window, (float)(WIDTH) / 2, (float)(HEIGHT) / 2); horizontalAngle += mouseSpeed * deltaTime * (float)((float)(WIDTH) / 2 - xpos); verticalAngle += mouseSpeed * deltaTime * (float)((float)(HEIGHT) / 2 - ypos); glm::vec3 direction(cos(verticalAngle) * sin(horizontalAngle), sin(verticalAngle), cos(verticalAngle) * cos(horizontalAngle)); glm::vec3 right(sin(horizontalAngle - 3.14f / 2.0f), 0, cos(horizontalAngle - 3.14f / 2.0f)); glm::vec3 up = glm::cross(right, direction); if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) { position += direction * deltaTime * speed; } if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) { position -= direction * deltaTime * speed; } if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) { position += right * deltaTime * speed; } if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) { position -= right * deltaTime * speed; } // float FOV = initialFOV; // Disabled because unchanged // glm_perspective(glm_rad(FOV), 4.0f/ 3.0f, 0.1f, 100.0f, projection); glm::mat4 view = glm::lookAt(position, position + direction, up); mvp = projection * view * model; // Send mega sigma MVP to the vertex shader (transformations for the win) glUniformMatrix4fv(matrixID, 1, GL_FALSE, &mvp[0][0]); // DRAWING HAPPENS HERE // Vertex Data glEnableVertexAttribArray(0); glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void *)0); // UV Data glEnableVertexAttribArray(1); glBindBuffer(GL_ARRAY_BUFFER, uvBuffer); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void *)0); // Normal Data glEnableVertexAttribArray(2); glBindBuffer(GL_ARRAY_BUFFER, normalBuffer); glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (void *)0); // Index buffer glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer); glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_SHORT, (void *)0); glDisableVertexAttribArray(0); glDisableVertexAttribArray(1); glDisableVertexAttribArray(2); ImGui::Render(); ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); // Swap buffers glfwSwapBuffers(window); glfwPollEvents(); lastTime = currentTime; // Count total frame time } ImGui_ImplOpenGL3_Shutdown(); ImGui_ImplGlfw_Shutdown(); ImGui::DestroyContext(); glDeleteBuffers(1, &vertexBuffer); glDeleteBuffers(1, &uvBuffer); glDeleteBuffers(1, &normalBuffer); glDeleteBuffers(1, &elementBuffer); glDeleteProgram(programID); glDeleteTextures(1, &texture); glDeleteVertexArrays(1, &vertexArrayID); glfwDestroyWindow(window); glfwTerminate(); return 0; } int main() { return initWindow(); }