From 87352034fdc2919528ee95d184b1642a3b0c644f Mon Sep 17 00:00:00 2001 From: illegitimate-egg Date: Fri, 18 Oct 2024 00:57:50 +0100 Subject: [PATCH] Uhhhhhhhhhhhhh --- .gitmodules | 3 + CMakeLists.txt | 13 +++- extern/CLog | 2 +- extern/ImGuizmo | 1 + src/engine.cpp | 154 ++++++++++++++++++++++++++++++++++++++---------- src/shader.c | 16 ++--- 6 files changed, 149 insertions(+), 40 deletions(-) create mode 160000 extern/ImGuizmo diff --git a/.gitmodules b/.gitmodules index ca047d9..af92430 100644 --- a/.gitmodules +++ b/.gitmodules @@ -22,3 +22,6 @@ [submodule "extern/glad"] path = extern/glad url = https://github.com/Dav1dde/glad.git +[submodule "extern/ImGuizmo"] + path = extern/ImGuizmo + url = https://github.com/maritim/ImGuizmo.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 5ce468b..7926959 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,6 +55,17 @@ add_library( extern/imgui/backends/imgui_impl_opengl3.cpp) target_link_libraries(imgui glfw) +include_directories(extern/ImGuizmo) +add_library( + imguizmo STATIC + extern/ImGuizmo/GraphEditor.cpp + extern/ImGuizmo/ImCurveEdit.cpp + extern/ImGuizmo/ImGradient.cpp + extern/ImGuizmo/ImGuizmo.cpp + extern/ImGuizmo/ImSequencer.cpp +) +target_link_libraries(imguizmo imgui) + add_executable(fred src/engine.cpp src/shader.c) target_link_libraries(fred $<$:-lm> glad_gl_core_33 glm glfw - soil2 assimp imgui clog) + soil2 assimp imgui imguizmo clog) diff --git a/extern/CLog b/extern/CLog index 78f58ff..8fafc54 160000 --- a/extern/CLog +++ b/extern/CLog @@ -1 +1 @@ -Subproject commit 78f58ffefc782c3bcc0bccaf7df38b064da6f170 +Subproject commit 8fafc54518584db67f3e85dab29ba7afa5cdd284 diff --git a/extern/ImGuizmo b/extern/ImGuizmo new file mode 160000 index 0000000..315acb2 --- /dev/null +++ b/extern/ImGuizmo @@ -0,0 +1 @@ +Subproject commit 315acb262ce7358a84bbce1b5d2684024035529d diff --git a/src/engine.cpp b/src/engine.cpp index 07b1311..7f25200 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include @@ -17,6 +18,7 @@ #include #include #include +#include #include #include @@ -32,7 +34,7 @@ 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); + clog_log(CLOG_LEVEL_ERROR, "GLFW Error %d: %s\n", e, description); } namespace fred { @@ -41,14 +43,14 @@ static bool loadModel(const char *path, std::vector &indices, std::vector &vertices, std::vector &uvs, std::vector &normals) { - clog_log(CLOG_LEVEL_DEBUG, "Loading model: %s", path); + clog_log(CLOG_LEVEL_DEBUG, "Loading model: %s\n", path); Assimp::Importer importer; const aiScene *scene = importer.ReadFile( path, aiProcess_Triangulate | aiProcess_JoinIdenticalVertices | aiProcess_SortByPType); if (!scene) { - clog_log(CLOG_LEVEL_ERROR, "%s", importer.GetErrorString()); + clog_log(CLOG_LEVEL_ERROR, "%s\n", importer.GetErrorString()); return false; } const aiMesh *mesh = scene->mMeshes[0]; @@ -80,13 +82,13 @@ static bool loadModel(const char *path, std::vector &indices, } GLuint loadTexture(const char *path) { - clog_log(CLOG_LEVEL_DEBUG, "Loading texture: %s", path); + clog_log(CLOG_LEVEL_DEBUG, "Loading texture: %s\n", 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"); + clog_log(CLOG_LEVEL_WARN, "Texture failed to load\n"); return 0; } return texture; @@ -285,15 +287,24 @@ float getUnscaledDeltaTime() { return deltaTime; } +bool exitFlag = false; + static bool shouldExit() { -return glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS && glfwWindowShouldClose(window) == 0; + return !(glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS && glfwWindowShouldClose(window) == 0) || exitFlag; +} + +std::string log; +void appendLog(clog_log_level_e, char *message, int length) { + log.append(message); } static int initWindow() { + clog_set_append_newline(0); + clog_set_log_callback(appendLog, 1); glfwSetErrorCallback(glfwErrorCallback); if (!glfwInit()) { - clog_log(CLOG_LEVEL_ERROR, "GLFW went shitty time (failed to init)"); + clog_log(CLOG_LEVEL_ERROR, "GLFW went shitty time (failed to init)\n"); return 1; } @@ -305,7 +316,7 @@ static int initWindow() { window = glfwCreateWindow(WIDTH, HEIGHT, "Fred", NULL, NULL); if (window == NULL) { - clog_log(CLOG_LEVEL_ERROR, "Failed to open window."); + clog_log(CLOG_LEVEL_ERROR, "Failed to open window.\n"); glfwTerminate(); return 1; } @@ -315,10 +326,10 @@ static int initWindow() { int version; if ((version = gladLoadGL(glfwGetProcAddress))) { - clog_log(CLOG_LEVEL_DEBUG, "GL version: %d.%d", GLAD_VERSION_MAJOR(version), + clog_log(CLOG_LEVEL_DEBUG, "GL version: %d.%d\n", GLAD_VERSION_MAJOR(version), GLAD_VERSION_MINOR(version)); } else { - clog_log(CLOG_LEVEL_ERROR, "Failed to init GL!"); + clog_log(CLOG_LEVEL_ERROR, "Failed to init GL!\n"); return 1; } @@ -329,7 +340,7 @@ static int initWindow() { io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; - //io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; + io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; ImGui::StyleColorsDark(); @@ -404,6 +415,7 @@ void destroy() { void render(Scene scene) { static ImVec2 viewportSize = ImVec2(1024, 768); + static ImVec2 viewportPosition = ImVec2(0, 0); static ImVec2 viewportSizeOld = viewportSize; if (viewportSizeOld != viewportSize) { glBindTexture(GL_TEXTURE_2D, renderedTexture); @@ -428,6 +440,7 @@ void render(Scene scene) { ImGui_ImplOpenGL3_NewFrame(); ImGui_ImplGlfw_NewFrame(); ImGui::NewFrame(); + ImGuizmo::BeginFrame(); static ImGuiDockNodeFlags dockspaceFlags = ImGuiDockNodeFlags_PassthruCentralNode; ImGuiWindowFlags windowFlags = ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking; @@ -444,11 +457,25 @@ void render(Scene scene) { windowFlags |= ImGuiWindowFlags_NoBackground; } + ImGui::ShowDemoWindow(); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f)); ImGui::Begin("DockSpace", nullptr, windowFlags); ImGui::PopStyleVar(); ImGui::PopStyleVar(2); + if (ImGui::BeginMenuBar()) { + if (ImGui::BeginMenu("File")) { + if (ImGui::MenuItem("Exit")) { + exitFlag = true; + } + ImGui::EndMenu(); + } + + ImGui::EndMenuBar(); + } + + ImGuiIO &io = ImGui::GetIO(); if (io.ConfigFlags & ImGuiConfigFlags_DockingEnable) { ImGuiID dockspace_id = ImGui::GetID("myDockSpace"); @@ -461,11 +488,14 @@ void render(Scene scene) { ImGui::DockBuilderAddNode(dockspace_id, dockspaceFlags | ImGuiDockNodeFlags_DockSpace); ImGui::DockBuilderSetNodeSize(dockspace_id, viewport->Size); - ImGuiID dock_id_left = ImGui::DockBuilderSplitNode(dockspace_id, ImGuiDir_Left, 0.2f, nullptr, &dockspace_id); ImGuiID dock_id_down = ImGui::DockBuilderSplitNode(dockspace_id, ImGuiDir_Down, 0.25f, nullptr, &dockspace_id); + ImGuiID dock_id_left = ImGui::DockBuilderSplitNode(dockspace_id, ImGuiDir_Left, 0.2f, nullptr, &dockspace_id); + ImGuiID dock_id_right = ImGui::DockBuilderSplitNode(dockspace_id, ImGuiDir_Right, 0.3f, nullptr, &dockspace_id); - ImGui::DockBuilderDockWindow("Down", dock_id_down); - ImGui::DockBuilderDockWindow("Left", dock_id_left); + ImGui::DockBuilderDockWindow("Console", dock_id_down); + ImGui::DockBuilderDockWindow("User Render Callback", dock_id_left); + ImGui::DockBuilderDockWindow("Viewport", ImGui::DockBuilderGetCentralNode(dockspace_id)->ID); + ImGui::DockBuilderDockWindow("Asset Information", dock_id_right); ImGui::DockBuilderFinish(dockspace_id); } } @@ -490,17 +520,6 @@ void render(Scene scene) { glm::mat4 mvp = projectionMatrix * viewMatrix * modelMatrix; - char assetName[] = "Asset: 00"; - sprintf(assetName, "Asset: %d", i); - ImGui::Begin(assetName); - ImGui::Text("Frametime/Deltatime (ms): %f", deltaTime * 1000); - glm::vec3 rotationEuler = glm::degrees(eulerAngles(currentAsset->rotation)); - ImGui::DragFloat3("Translate", (float*)¤tAsset->position, 0.01f); - ImGui::DragFloat3("Rotate", (float*)&rotationEuler); - ImGui::DragFloat3("Scale", (float*)¤tAsset->scaling, 0.01f); - currentAsset->rotation = glm::quat(glm::radians(rotationEuler)); - ImGui::End(); - glUniformMatrix4fv(currentAsset->matrixID, 1, GL_FALSE, &mvp[0][0]); glUniformMatrix4fv(currentAsset->modelMatrixID, 1, GL_FALSE, &modelMatrix[0][0]); glUniformMatrix4fv(currentAsset->viewMatrixID, 1, GL_FALSE, &viewMatrix[0][0]); @@ -556,18 +575,93 @@ void render(Scene scene) { ImGui::Begin("Viewport"); ImGui::Image((ImTextureID)frameBufferName, viewportSize, ImVec2(0, 1), ImVec2(1, 0)); viewportSize = ImGui::GetWindowContentRegionMax() - ImGui::GetWindowContentRegionMin(); + viewportPosition = ImGui::GetWindowPos(); ImGui::End(); ImGui::PopStyleVar(); + ImGui::Begin("Console"); + bool autoScroll = true; + if(ImGui::BeginPopup("Options")) { + ImGui::Checkbox("Auto-scroll", &autoScroll); + ImGui::EndPopup(); + } + + if (ImGui::Button("Options")) { + ImGui::OpenPopup("Options"); + } + ImGui::Separator(); + + const float footerHeightToReserve = ImGui::GetStyle().ItemSpacing.y + ImGui::GetFrameHeightWithSpacing(); + if (ImGui::BeginChild("ScrollingRegion", ImVec2(0, 0), ImGuiChildFlags_NavFlattened, ImGuiWindowFlags_HorizontalScrollbar)) { + if (ImGui::BeginPopupContextWindow()) { + if (ImGui::Selectable("Clear")) { + log = ""; + ImGui::EndPopup(); + } + ImGui::EndChild(); + ImGui::Separator(); + } + ImGui::Text("%s", log.c_str()); + static std::string oldLog = log; + if (oldLog != log && autoScroll) { + ImGui::SetScrollHereY(1.0f); + oldLog = log; + } + ImGui::EndChild(); + } + + ImGui::End(); + + ImGui::Begin("Asset Information"); + static int assetNum = 0; + ImGui::Text("Select asset ID"); + for (int i = 0; i < scene.assets.size(); i++) { + char index[4]; // Probably never will need more than 3 digits of precision + sprintf(index, "%d", i); + if (ImGui::RadioButton(index, assetNum == i)) { + assetNum = i; + } + } + ImGui::Separator(); + Asset *currentAsset = scene.assets[assetNum]; + ImGuizmo::SetOwnerWindowName("Viewport"); + static ImGuizmo::OPERATION currentGizmoOperation(ImGuizmo::ROTATE); + static ImGuizmo::MODE currentGizmoMode(ImGuizmo::WORLD); + if (ImGui::RadioButton("Translate", currentGizmoOperation == ImGuizmo::TRANSLATE)) { + currentGizmoOperation = ImGuizmo::TRANSLATE; + } + ImGui::SameLine(); + if (ImGui::RadioButton("Rotate", currentGizmoOperation == ImGuizmo::ROTATE)) { + currentGizmoOperation = ImGuizmo::ROTATE; + } + ImGui::SameLine(); + if (ImGui::RadioButton("Scale", currentGizmoOperation == ImGuizmo::SCALE)) { + currentGizmoOperation = ImGuizmo::SCALE; + } + ImGui::DragFloat3("Translate", ¤tAsset->position[0], 0.01); + ImGui::DragFloat4("Rotate", ¤tAsset->rotation[0], 0.01); + ImGui::DragFloat3("Scale", ¤tAsset->scaling[0], 0.01); + + 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; + + ImGuizmo::SetRect(viewportPosition.x, viewportPosition.y, viewportSize.x, viewportSize.y); + ImGuizmo::Manipulate((const float *)&viewMatrix, (const float *)&projectionMatrix, currentGizmoOperation, currentGizmoMode, (float *)&modelMatrix, NULL, NULL); + glm::vec3 shitAngles; + ImGuizmo::DecomposeMatrixToComponents((float *)&modelMatrix, ¤tAsset->position[0], (float *)&shitAngles, ¤tAsset->scaling[0]); + currentAsset->rotation = glm::quat(glm::radians(shitAngles)); + ImGui::End(); glBindFramebuffer(GL_FRAMEBUFFER, 0); glViewport(0, 0, WIDTH, HEIGHT); ImGui::Render(); ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); - //ImGui::UpdatePlatformWindows(); - //ImGui::RenderPlatformWindowsDefault(); - //glfwMakeContextCurrent(window); + ImGui::UpdatePlatformWindows(); + ImGui::RenderPlatformWindowsDefault(); + glfwMakeContextCurrent(window); // Swap buffers glfwSwapBuffers(window); @@ -618,11 +712,11 @@ int main() { scene.addAsset(cone); scene.addAsset(suzanne); - scene.setRenderCallback(&renderCallback); + scene.setRenderCallback(renderCallback); fred::setDeltaTimeMultiplier(20.0f); - while (fred::shouldExit()) { + while (!fred::shouldExit()) { fred::render(scene); cone.position.x += 0.01 * fred::getDeltaTime(); glm::vec3 eulerAngles = glm::eulerAngles(suzanne.rotation); diff --git a/src/shader.c b/src/shader.c index e69305b..f256d93 100644 --- a/src/shader.c +++ b/src/shader.c @@ -35,7 +35,7 @@ GLuint loadShaders(const char *vertex_file_path, FILE *vertexShaderFD; if ((err = fopen_s(&vertexShaderFD, vertex_file_path, "rb"))) { - clog_log(CLOG_LEVEL_ERROR, "Failed to open Vertex Shader \"%s\": %d", + clog_log(CLOG_LEVEL_ERROR, "Failed to open Vertex Shader \"%s\": %d\n", vertex_file_path, err); return 0; } @@ -48,7 +48,7 @@ GLuint loadShaders(const char *vertex_file_path, FILE *fragmentShaderFD; if ((err = fopen_s(&fragmentShaderFD, fragment_file_path, "rb"))) { - clog_log(CLOG_LEVEL_ERROR, "Failed to open Vertex Shader \"%s\": %d", + clog_log(CLOG_LEVEL_ERROR, "Failed to open Vertex Shader \"%s\": %d\n", fragment_file_path, err); return 0; } @@ -62,7 +62,7 @@ GLuint loadShaders(const char *vertex_file_path, GLint result = GL_FALSE; int infoLogLength; - clog_log(CLOG_LEVEL_DEBUG, "Compiling shader: %s", vertex_file_path); + clog_log(CLOG_LEVEL_DEBUG, "Compiling shader: %s\n", vertex_file_path); char const *vertexShaderCodeConst = vertexShaderCode; glShaderSource(vertexShaderID, 1, &vertexShaderCodeConst, NULL); glCompileShader(vertexShaderID); @@ -76,11 +76,11 @@ GLuint loadShaders(const char *vertex_file_path, sizeof(char)); // Not all compilers support VLAs, this will do glGetShaderInfoLog(vertexShaderID, infoLogLength - 1, NULL, vertexShaderErrorMessage); - clog_log(CLOG_LEVEL_ERROR, "%s", vertexShaderErrorMessage); + clog_log(CLOG_LEVEL_ERROR, "%s\n", vertexShaderErrorMessage); free(vertexShaderErrorMessage); } - clog_log(CLOG_LEVEL_DEBUG, "Compiling shader: %s", fragment_file_path); + clog_log(CLOG_LEVEL_DEBUG, "Compiling shader: %s\n", fragment_file_path); char const *fragmentShaderCodeConst = fragmentShaderCode; glShaderSource(fragmentShaderID, 1, &fragmentShaderCodeConst, NULL); glCompileShader(fragmentShaderID); @@ -93,11 +93,11 @@ GLuint loadShaders(const char *vertex_file_path, (char *)malloc(infoLogLength * sizeof(char)); glGetShaderInfoLog(fragmentShaderID, infoLogLength - 1, NULL, fragmentShaderErrorMessage); - clog_log(CLOG_LEVEL_ERROR, "%s", fragmentShaderErrorMessage); + clog_log(CLOG_LEVEL_ERROR, "%s\n", fragmentShaderErrorMessage); free(fragmentShaderErrorMessage); } - clog_log(CLOG_LEVEL_DEBUG, "Linking shader program"); + clog_log(CLOG_LEVEL_DEBUG, "Linking shader program\n"); GLuint programID = glCreateProgram(); glAttachShader(programID, vertexShaderID); glAttachShader(programID, fragmentShaderID); @@ -111,7 +111,7 @@ GLuint loadShaders(const char *vertex_file_path, ; glGetProgramInfoLog(programID, infoLogLength - 1, NULL, programErrorMessage); - clog_log(CLOG_LEVEL_ERROR, "%s", programErrorMessage); + clog_log(CLOG_LEVEL_ERROR, "%s\n", programErrorMessage); free(programErrorMessage); }