diff --git a/.gitmodules b/.gitmodules index 9f7a356..a4d1e09 100644 --- a/.gitmodules +++ b/.gitmodules @@ -25,3 +25,6 @@ [submodule "include/glad"] path = include/glad url = https://github.com/Dav1dde/glad.git +[submodule "include/imGuIZMO.quat"] + path = include/imGuIZMO.quat + url = https://github.com/BrutPitt/imGuIZMO.quat.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 68ba9f3..e8c63b1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,8 @@ set(GLFW_BUILD_TESTS OFF) # Don't build GLFW Tests set(GLFW_INSTALL OFF) # We're not building a standalone # set(GLEW_BUILD_DOCS $) # Build docs if debug set(SOIL2_BUILD_TESTS OFF) # Don't build SOIL2 Tests +set(ASSIMP_BUILD_ASSIMP_TOOLS OFF) +set(ASSIMP_BUILD_TESTS OFF) find_package(OpenGL REQUIRED) @@ -53,6 +55,14 @@ add_library( include/imgui/backends/imgui_impl_opengl3.cpp) target_link_libraries(imgui glfw) +include_directories(include) # Kill me please +include_directories(include/imGuIZMO.quat) +add_library( + imGuIZMO STATIC + include/imGuIZMO.quat/imGuIZMO.quat/imGuIZMOquat.cpp +) +target_link_libraries(imGuIZMO imgui) + add_executable(fred engine.cpp shader.c) if(UNIX) target_link_libraries( diff --git a/engine.cpp b/engine.cpp index 2ca7d06..ca36ca7 100644 --- a/engine.cpp +++ b/engine.cpp @@ -1,3 +1,4 @@ +#include "imGuIZMO.quat/vgMath.h" #include #include #include @@ -6,13 +7,18 @@ #include #include #include +#include #include +#define GLM_ENABLE_EXPERIMENTAL +#include #include -#include -#include +#define IMGUI_DEFINE_MATH_OPERATORS // ImGui +#include +#include +#include +#include #include -#include #include #include @@ -23,13 +29,15 @@ #include "shader.h" -constexpr int WIDTH = 1024; +constexpr int WIDTH = 1366; constexpr int HEIGHT = 768; static void glfwErrorCallback(int e, const char *description) { clog_log(CLOG_LEVEL_ERROR, "GLFW Error %d: %s", e, description); } +namespace fred { + static bool loadModel(const char *path, std::vector &indices, std::vector &vertices, std::vector &uvs, @@ -67,6 +75,139 @@ static bool loadModel(const char *path, std::vector &indices, return true; } +GLuint loadTexture(const char *path) { + GLuint texture = SOIL_load_OGL_texture( + path, SOIL_LOAD_AUTO, + SOIL_CREATE_NEW_ID, + SOIL_FLAG_MIPMAPS | SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_COMPRESS_TO_DXT | SOIL_FLAG_INVERT_Y); + if (texture == 0) { + clog_log(CLOG_LEVEL_WARN, "Texture failed to load"); + return 0; + } + return texture; +} + +class Model { +public: + std::vector indices; + GLuint vertexBuffer; + GLuint uvBuffer; + GLuint normalBuffer; + GLuint elementBuffer; + + Model(std::string modelPath) { + std::vector indexed_vertices; + std::vector indexed_uvs; + std::vector indexed_normals; + + loadModel(modelPath.c_str(), indices, indexed_vertices, indexed_uvs, indexed_normals); + + glGenBuffers(1, &vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, indexed_vertices.size() * sizeof(glm::vec3), + &indexed_vertices[0], GL_STATIC_DRAW); + + glGenBuffers(1, &uvBuffer); + glBindBuffer(GL_ARRAY_BUFFER, uvBuffer); + glBufferData(GL_ARRAY_BUFFER, indexed_uvs.size() * sizeof(glm::vec2), + &indexed_uvs[0], GL_STATIC_DRAW); + + glGenBuffers(1, &normalBuffer); + glBindBuffer(GL_ARRAY_BUFFER, normalBuffer); + glBufferData(GL_ARRAY_BUFFER, indexed_normals.size() * sizeof(glm::vec3), + &indexed_normals[0], GL_STATIC_DRAW); + + glGenBuffers(1, &elementBuffer); + glBindBuffer(GL_ARRAY_BUFFER, elementBuffer); + glBufferData(GL_ARRAY_BUFFER, indices.size() * sizeof(unsigned short), + &indices[0], GL_STATIC_DRAW); + } + ~Model() { + // glDeleteBuffers(4, vertexBuffer); // Chances that these are contiguous in memory is zero + glDeleteBuffers(1, &vertexBuffer); + glDeleteBuffers(1, &uvBuffer); + glDeleteBuffers(1, &normalBuffer); + glDeleteBuffers(1, &elementBuffer); + } +}; + +class Texture { +public: + GLuint texture; + + Texture(std::string texturePath) { + texture = loadTexture(texturePath.c_str()); + } + ~Texture() { + glDeleteTextures(1, &texture); + } +}; + +class Shader { +public: + GLuint shaderProgram; + + Shader(std::string vertPath, std::string fragPath) { + shaderProgram = loadShaders(vertPath.c_str(), fragPath.c_str()); + } + ~Shader() { + glDeleteProgram(shaderProgram); + } +}; + +class Asset { +public: + std::vector *indices; + GLuint *vertexBuffer; + GLuint *uvBuffer; + GLuint *normalBuffer; + GLuint *elementBuffer; + + GLuint matrixID; + GLuint textureID; + + glm::vec3 position = glm::vec3(0.0f, 0.0f, 0.0f); + glm::quat rotation = glm::quat(1.0f, 0.0f, 0.0f, 0.0f); // https://en.wikipedia.org/wiki/Quaternion + glm::vec3 scaling = glm::vec3(1.0f, 1.0f, 1.0f); + + GLuint *modelTexture; + + GLuint *shaderProgram; + + Asset(Model &model, Texture &texture, Shader &shader) { + indices = &model.indices; + vertexBuffer = &model.vertexBuffer; + uvBuffer = &model.uvBuffer; + normalBuffer = &model.normalBuffer; + elementBuffer = &model.elementBuffer; + + modelTexture = &texture.texture; + + shaderProgram = &shader.shaderProgram; + + matrixID = glGetUniformLocation(*shaderProgram, "MVP"); + textureID = glGetUniformLocation(*shaderProgram, "textureSampler"); + } +}; + +class Scene { +public: + std::vector assets; + void addAsset(Asset *asset) { + assets.push_back(asset); + } +}; + +GLFWwindow *window; + +static bool shouldExit() { +return glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS && glfwWindowShouldClose(window) == 0; +} + +glm::mat4 mvp; // TODO: REMOVE THIS PLLAAAHSE +glm::mat4 viewMatrix; +glm::mat4 projectionMatrix; + static int initWindow() { glfwSetErrorCallback(glfwErrorCallback); @@ -81,7 +222,6 @@ static int initWindow() { 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) { clog_log(CLOG_LEVEL_ERROR, "Failed to open window."); @@ -113,71 +253,21 @@ static int initWindow() { 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) { - clog_log(CLOG_LEVEL_WARN, "Texture failed to load"); - 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( + projectionMatrix = glm::perspective( glm::radians(45.0f), (float)WIDTH / (float)HEIGHT, 0.1f, 100.0f); // Camera matrix - glm::mat4 view = + viewMatrix = 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"); + mvp = projectionMatrix * viewMatrix * model; glEnable(GL_DEPTH_TEST); // Turn on the Z-buffer glDepthFunc(GL_LESS); // Accept only the closest fragments @@ -186,172 +276,144 @@ static int initWindow() { glClearColor(0.1f, 0.1f, 0.1f, 1.0f); + GLuint vertexArrayID; + glGenVertexArrays(1, &vertexArrayID); + glBindVertexArray(vertexArrayID); + // 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; + //glm::vec3 position = {4, 3, 3}; + //float horizontalAngle = 3.14f; + //float verticalAngle = -0.1f; + //float initialFOV = 60.0f; - float speed = 3.0f; - float mouseSpeed = 0.005f; + //float speed = 3.0f; + //float mouseSpeed = 0.005f; - double xpos, ypos; + //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); + //glDeleteVertexArrays(1, &vertexArrayID); + //ImGui_ImplOpenGL3_Shutdown(); + //ImGui_ImplGlfw_Shutdown(); + //ImGui::DestroyContext(); - // ImGui - // if (glfwGetWindowAttrib(window, GLFW_ICONIFIED) != 0) { - // ImGui_ImplGlfw_Sleep(10); - // continue; // No rendering while minimized - // } + //glfwDestroyWindow(window); + //glfwTerminate(); - glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE); - glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); + return 0; +} - 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(); +void imguiMat4Table(glm::mat4 matrix, const char *name) { + if (ImGui::BeginTable(name, 4)) { + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + ImGui::TableNextColumn(); + ImGui::Text("%f", matrix[i][j]); + } } - ImGui::End(); + ImGui::EndTable(); + } +} - // Compute a Fresh Super Sigma MVP - // What would an input system be without delta time - double currentTime = glfwGetTime(); - float deltaTime = (float)(currentTime - lastTime); +void render(Scene scene) { + // Clear this mf + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glfwGetCursorPos(window, &xpos, &ypos); - glfwSetCursorPos(window, (float)(WIDTH) / 2, (float)(HEIGHT) / 2); + ImGui_ImplOpenGL3_NewFrame(); + ImGui_ImplGlfw_NewFrame(); + ImGui::NewFrame(); - 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); + for (int i = 0; i < scene.assets.size(); i++) { + Asset *currentAsset = scene.assets[i]; - 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; + glUseProgram(*currentAsset->shaderProgram); // Send mega sigma MVP to the vertex shader (transformations for the win) - glUniformMatrix4fv(matrixID, 1, GL_FALSE, &mvp[0][0]); + glm::mat4 rotationMatrix = mat4_cast(currentAsset->rotation); + glm::mat4 translationMatrix = glm::translate(glm::mat4(1), currentAsset->position); + glm::mat4 scalingMatrix = glm::scale(glm::mat4(1), currentAsset->scaling); + glm::mat4 modelMatrix = translationMatrix * rotationMatrix * scalingMatrix; + + mvp = projectionMatrix * viewMatrix * modelMatrix; + + char assetName[] = "Asset: 00"; + sprintf(assetName, "Asset: %d", i); + ImGui::Begin(assetName); + + ImGui::SeparatorText("Position Matrix:"); + imguiMat4Table(translationMatrix, "posmat"); + ImGui::SeparatorText("Rotation Matrix:"); + imguiMat4Table(rotationMatrix, "rotmat"); + ImGui::SeparatorText("Scaling Matrix:"); + imguiMat4Table(scalingMatrix, "scalmat"); + ImGui::SeparatorText("Model Matrix:"); + imguiMat4Table(modelMatrix, "modmat"); + ImGui::End(); + + glUniformMatrix4fv(currentAsset->matrixID, 1, GL_FALSE, &mvp[0][0]); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, *currentAsset->modelTexture); + // Set sampler texture + glUniform1i(currentAsset->textureID, 0); // DRAWING HAPPENS HERE // Vertex Data glEnableVertexAttribArray(0); - glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, *currentAsset->vertexBuffer); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void *)0); // UV Data glEnableVertexAttribArray(1); - glBindBuffer(GL_ARRAY_BUFFER, uvBuffer); + glBindBuffer(GL_ARRAY_BUFFER, *currentAsset->uvBuffer); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void *)0); // Normal Data glEnableVertexAttribArray(2); - glBindBuffer(GL_ARRAY_BUFFER, normalBuffer); + glBindBuffer(GL_ARRAY_BUFFER, *currentAsset->normalBuffer); glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (void *)0); // Index buffer - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *currentAsset->elementBuffer); - glDrawElements(GL_TRIANGLES, (GLsizei)indices.size(), GL_UNSIGNED_SHORT, + glDrawElements(GL_TRIANGLES, currentAsset->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(); + ImGui::Render(); + ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); - glDeleteBuffers(1, &vertexBuffer); - glDeleteBuffers(1, &uvBuffer); - glDeleteBuffers(1, &normalBuffer); - glDeleteBuffers(1, &elementBuffer); - glDeleteProgram(programID); - glDeleteTextures(1, &texture); - glDeleteVertexArrays(1, &vertexArrayID); + // Swap buffers + glfwSwapBuffers(window); + glfwPollEvents(); +} - glfwDestroyWindow(window); - glfwTerminate(); +} // namespace fred + +int main() { + fred::initWindow(); + fred::Model coneModel("../models/model.obj"); + fred::Texture buffBlackGuy("../textures/results/texture_BMP_DXT5_3.DDS"); + fred::Shader basicShader("../shaders/shader.vert", "../shaders/shader.frag"); + fred::Asset cone(coneModel, buffBlackGuy, basicShader); + fred::Asset coneTwo(coneModel, buffBlackGuy, basicShader); + + fred::Scene scene = fred::Scene(); + + scene.addAsset(&cone); + scene.addAsset(&coneTwo); + + while (fred::shouldExit()) { + //while (1) { + fred::render(scene); + cone.position.x += 0.01; + glm::vec3 eulerAngles = glm::eulerAngles(coneTwo.rotation); + eulerAngles.x += glm::radians(1.0f); + coneTwo.rotation = glm::quat(eulerAngles); + } return 0; } - -int main() { return initWindow(); } diff --git a/include/CLog b/include/CLog index 5a8dc48..906059b 160000 --- a/include/CLog +++ b/include/CLog @@ -1 +1 @@ -Subproject commit 5a8dc48b060619da1b6fbbacd18630c4d2c92182 +Subproject commit 906059bd02731184f80d8b3e789e61c5499213d0 diff --git a/include/imGuIZMO.quat b/include/imGuIZMO.quat new file mode 160000 index 0000000..6c038a9 --- /dev/null +++ b/include/imGuIZMO.quat @@ -0,0 +1 @@ +Subproject commit 6c038a90fdadae580b357fbaf26f83cafeb83a6a diff --git a/shaders/shader.vert b/shaders/shader.vert index e75cdc8..6a80973 100644 --- a/shaders/shader.vert +++ b/shaders/shader.vert @@ -11,6 +11,7 @@ uniform mat4 MVP; void main() { gl_Position = MVP * vec4(vertexPosition_modelspace, 1); + //gl_Position = vec4(vertexPosition_modelspace, 1); vec2 UV_FLIPPED; UV_FLIPPED.x = vertexUV.x;