From 38389cf4a0bcd0989e2d411c703fcf07dcb24e84 Mon Sep 17 00:00:00 2001 From: fszewczyk Date: Fri, 17 Mar 2023 16:11:46 +0100 Subject: [PATCH 1/7] Scaling render and initial plot window --- CMakeLists.txt | 1 + src/ui/plot/plotViewTab.cpp | 0 src/ui/plot/plotViewTab.hpp | 0 src/ui/plot/plotWindow.cpp | 21 +++++++++++++++++++ src/ui/plot/plotWindow.hpp | 27 +++++++++++++++++++++++++ src/ui/render/renderWindow.cpp | 22 +++++++++++++++++++- src/ui/settings/worldSettingsWindow.cpp | 13 +++++------- src/ui/ui.cpp | 13 +++++++----- src/ui/ui.hpp | 2 ++ src/world/visibleWorld.cpp | 18 +++++++++++++---- src/world/visibleWorld.hpp | 9 +++++---- 11 files changed, 104 insertions(+), 22 deletions(-) create mode 100644 src/ui/plot/plotViewTab.cpp create mode 100644 src/ui/plot/plotViewTab.hpp create mode 100644 src/ui/plot/plotWindow.cpp create mode 100644 src/ui/plot/plotWindow.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 050f34e..65aa49b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,6 +42,7 @@ add_library( src/ui/ui.cpp src/ui/renderer.cpp src/ui/render/renderWindow.cpp + src/ui/plot/plotWindow.cpp src/ui/settings/cameraSettingsWindow.cpp src/ui/settings/worldSettingsWindow.cpp src/ui/settings/planetSettingsWindow.cpp diff --git a/src/ui/plot/plotViewTab.cpp b/src/ui/plot/plotViewTab.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/ui/plot/plotViewTab.hpp b/src/ui/plot/plotViewTab.hpp new file mode 100644 index 0000000..e69de29 diff --git a/src/ui/plot/plotWindow.cpp b/src/ui/plot/plotWindow.cpp new file mode 100644 index 0000000..3fd6fcf --- /dev/null +++ b/src/ui/plot/plotWindow.cpp @@ -0,0 +1,21 @@ +#include "ui/plot/plotWindow.hpp" +#include "imgui.h" + +namespace shkyera { + +plotWindow::plotWindow(std::shared_ptr world, std::shared_ptr cam) + : m_world(world), m_camera(cam) {} + +systemSettings plotWindow::render(bool &updated) { + worldSettings settingsWorld; + cameraSettings settingsCamera = m_camera->getSettings(); + systemSettings settingsPlot = {settingsWorld, settingsCamera}; + + ImGui::Begin("Planetary System"); + + ImGui::End(); + + return settingsPlot; +} + +} // namespace shkyera \ No newline at end of file diff --git a/src/ui/plot/plotWindow.hpp b/src/ui/plot/plotWindow.hpp new file mode 100644 index 0000000..6d59751 --- /dev/null +++ b/src/ui/plot/plotWindow.hpp @@ -0,0 +1,27 @@ +#ifndef PLOT_WINDOW_H +#define PLOT_WINDOW_H + +#include "world/camera.hpp" +#include "world/visibleWorld.hpp" + +namespace shkyera { + +struct systemSettings { + worldSettings world; + cameraSettings cam; +}; + +class plotWindow { + public: + plotWindow(std::shared_ptr world, std::shared_ptr cam); + + systemSettings render(bool &updated); + + private: + std::shared_ptr m_world; + std::shared_ptr m_camera; +}; + +} // namespace shkyera + +#endif diff --git a/src/ui/render/renderWindow.cpp b/src/ui/render/renderWindow.cpp index 2e32526..bf5ee6a 100644 --- a/src/ui/render/renderWindow.cpp +++ b/src/ui/render/renderWindow.cpp @@ -57,7 +57,27 @@ point3 renderWindow::render(bool sampleTexture, bool &updated, std::pair(m_loadWidth) / m_loadHeight; + + float windowWidth = ImGui::GetWindowWidth() - 30; + float windowHeight = ImGui::GetWindowHeight() - 40; + float windowAspectRatio = windowWidth / windowHeight; + + float displayWidth = windowWidth; + float displayHeight = windowHeight; + + if (renderAspectRatio > windowAspectRatio) + displayHeight = displayWidth / renderAspectRatio; + + displayWidth = displayHeight * renderAspectRatio; + + float offsetWidth = (windowWidth - displayWidth) / 2; + float offsetHeight = (windowHeight - displayHeight) / 2; + + ImGui::Dummy(ImVec2(0, offsetHeight)); + ImGui::Dummy(ImVec2(offsetWidth, 0)); + ImGui::SameLine(); + ImGui::Image((ImTextureID)m_loadTexId, ImVec2(displayWidth, displayHeight)); ImGui::End(); diff --git a/src/ui/settings/worldSettingsWindow.cpp b/src/ui/settings/worldSettingsWindow.cpp index 0fae807..8093345 100644 --- a/src/ui/settings/worldSettingsWindow.cpp +++ b/src/ui/settings/worldSettingsWindow.cpp @@ -12,14 +12,11 @@ worldSettingsWindow::worldSettingsWindow(std::shared_ptr world) : worldSettings worldSettingsWindow::render(bool &updated) { updatePlanetSettingsWindows(); - worldSettings settings; - settings.planets.resize(m_world->getObjects().size()); - settings.updatedPlanets.resize(m_world->getObjects().size()); + worldSettings settings = m_world->getSettings(); - color ambientLightColor = m_world->getAmbientLightColor(); - float ambientLightColorComponents[3] = {static_cast(ambientLightColor[0]), - static_cast(ambientLightColor[1]), - static_cast(ambientLightColor[2])}; + float ambientLightColorComponents[3] = {static_cast(settings.ambientColor[0]), + static_cast(settings.ambientColor[1]), + static_cast(settings.ambientColor[2])}; ImGui::Begin("World"); ImGui::ColorEdit3("Ambient Light", ambientLightColorComponents); @@ -71,7 +68,7 @@ worldSettings worldSettingsWindow::render(bool &updated) { color newAmbientLightColor(ambientLightColorComponents[0], ambientLightColorComponents[1], ambientLightColorComponents[2]); - if (ambientLightColor != newAmbientLightColor) { + if (settings.ambientColor != newAmbientLightColor) { updated = true; } diff --git a/src/ui/ui.cpp b/src/ui/ui.cpp index 569a13b..fa4d2dc 100644 --- a/src/ui/ui.cpp +++ b/src/ui/ui.cpp @@ -19,7 +19,7 @@ namespace shkyera { ui::ui(std::shared_ptr im, std::shared_ptr renderer, std::shared_ptr world, std::shared_ptr cam) : m_renderWindow(im, cam), m_renderer(renderer), m_camera(cam), m_world(world), m_cameraSettingsWindow(cam), - m_worldSettingsWindow(world), m_mouseSensitivity(MOUSE_SENSITIVITY) {} + m_worldSettingsWindow(world), m_plotWindow(world, cam), m_mouseSensitivity(MOUSE_SENSITIVITY) {} void glfw_error_callback(int error, const char *description) { fprintf(stderr, "Glfw Error %d: %s\n", error, description); @@ -56,7 +56,7 @@ void ui::init() { // Setup window #endif // Create window with graphics context - m_window = glfwCreateWindow(1280, 720, "SHKYERA Engine", NULL, NULL); + m_window = glfwCreateWindow(1000, 800, "SHKYERA Engine", NULL, NULL); if (m_window == NULL) return; @@ -229,11 +229,13 @@ void ui::run() { ImGuiID dock_id_left, dock_id_right, dock_id_top_right, dock_id_bottom_right, dock_id_top_left, dock_id_bottom_left; - ImGui::DockBuilderSplitNode(dockspace_id, ImGuiDir_Left, 0.70f, &dock_id_left, &dock_id_right); - ImGui::DockBuilderSplitNode(dock_id_right, ImGuiDir_Up, 0.35f, &dock_id_top_right, + ImGui::DockBuilderSplitNode(dockspace_id, ImGuiDir_Left, 0.65f, &dock_id_left, &dock_id_right); + ImGui::DockBuilderSplitNode(dock_id_right, ImGuiDir_Up, 0.3f, &dock_id_top_right, &dock_id_bottom_right); + ImGui::DockBuilderSplitNode(dock_id_left, ImGuiDir_Up, 0.5f, &dock_id_top_left, &dock_id_bottom_left); - ImGui::DockBuilderDockWindow("Render", dock_id_left); + ImGui::DockBuilderDockWindow("Render", dock_id_top_left); + ImGui::DockBuilderDockWindow("Planetary System", dock_id_bottom_left); ImGui::DockBuilderDockWindow("Camera", dock_id_top_right); ImGui::DockBuilderDockWindow("World", dock_id_bottom_right); @@ -246,6 +248,7 @@ void ui::run() { bool updatedSettings = false; cameraSettings newCameraSettings = m_cameraSettingsWindow.render(updatedSettings); worldSettings newWorldSettings = m_worldSettingsWindow.render(updatedSettings); + systemSettings newSystemSettings = m_plotWindow.render(updatedSettings); point3 cameraTranslation; std::pair mouseMovement; diff --git a/src/ui/ui.hpp b/src/ui/ui.hpp index 34bb840..f8dd504 100644 --- a/src/ui/ui.hpp +++ b/src/ui/ui.hpp @@ -2,6 +2,7 @@ #define UI_H #include "core/image.hpp" +#include "ui/plot/plotWindow.hpp" #include "ui/render/renderWindow.hpp" #include "ui/renderer.hpp" #include "ui/settings/cameraSettingsWindow.hpp" @@ -37,6 +38,7 @@ class ui { renderWindow m_renderWindow; cameraSettingsWindow m_cameraSettingsWindow; worldSettingsWindow m_worldSettingsWindow; + plotWindow m_plotWindow; GLFWwindow *m_window; ImVec4 m_clearColor; diff --git a/src/world/visibleWorld.cpp b/src/world/visibleWorld.cpp index 16121df..5387779 100644 --- a/src/world/visibleWorld.cpp +++ b/src/world/visibleWorld.cpp @@ -37,9 +37,9 @@ void visibleWorld::add(shared_ptr object) { m_objects.push_back(object); } -std::vector> visibleWorld::getObjects() { return m_objects; } -std::shared_ptr visibleWorld::getUniverse() { return m_universe; } -std::shared_ptr visibleWorld::getObjectByIndex(size_t i) { return m_objects[i + 1]; } +std::vector> visibleWorld::getObjects() const { return m_objects; } +std::shared_ptr visibleWorld::getUniverse() const { return m_universe; } +std::shared_ptr visibleWorld::getObjectByIndex(size_t i) const { return m_objects[i + 1]; } size_t visibleWorld::size() const { return m_objects.size(); } @@ -59,6 +59,16 @@ bool visibleWorld::hit(const ray &r, double minT, double maxT, hitData &data) co return hitAnything; } +worldSettings visibleWorld::getSettings() const { + worldSettings settings; + settings.planets.resize(getObjects().size()); + settings.updatedPlanets.resize(getObjects().size()); + + settings.ambientColor = getAmbientLightColor(); + + return settings; +} + void visibleWorld::setSettings(worldSettings &settings) { setAmbientLightColor(settings.ambientColor); @@ -84,6 +94,6 @@ void visibleWorld::setAmbientLightColor(color c) { m_universe->setMaterial(newAmbientLightMaterial); } -color visibleWorld::getAmbientLightColor() { return m_ambientLightColor; } +color visibleWorld::getAmbientLightColor() const { return m_ambientLightColor; } } // namespace shkyera diff --git a/src/world/visibleWorld.hpp b/src/world/visibleWorld.hpp index 68fdadc..23c4535 100644 --- a/src/world/visibleWorld.hpp +++ b/src/world/visibleWorld.hpp @@ -27,17 +27,18 @@ class visibleWorld { void clear(); void add(shared_ptr object); - std::vector> getObjects(); - std::shared_ptr getUniverse(); - std::shared_ptr getObjectByIndex(size_t i); + std::vector> getObjects() const; + std::shared_ptr getUniverse() const; + std::shared_ptr getObjectByIndex(size_t i) const; size_t size() const; bool hit(const ray &r, double minT, double maxT, hitData &data) const; + worldSettings getSettings() const; void setSettings(worldSettings &settings); + color getAmbientLightColor() const; void setAmbientLightColor(color c); - color getAmbientLightColor(); private: std::vector> m_objects; From 7a9aa5cd5c857b6b3be27445ad93edc0c41b4423 Mon Sep 17 00:00:00 2001 From: fszewczyk Date: Fri, 17 Mar 2023 19:49:11 +0100 Subject: [PATCH 2/7] Plotting planets --- CMakeLists.txt | 8 ++- extern/extern.cmake | 1 + extern/solveImPlot.cmake | 20 ++++++++ src/core/image.cpp | 13 ++++- src/core/image.hpp | 4 ++ src/core/texture.cpp | 6 +++ src/core/texture.hpp | 5 +- src/main.cpp | 1 + src/shapes/material.cpp | 8 +++ src/shapes/material.hpp | 4 ++ src/shapes/sphere.cpp | 3 ++ src/shapes/sphere.hpp | 3 ++ src/ui/plot/plotViewTab.cpp | 98 +++++++++++++++++++++++++++++++++++++ src/ui/plot/plotViewTab.hpp | 26 ++++++++++ src/ui/plot/plotWindow.cpp | 19 ++++--- src/ui/plot/plotWindow.hpp | 11 ++--- src/ui/ui.cpp | 24 ++++++--- src/world/visibleWorld.hpp | 6 +++ 18 files changed, 236 insertions(+), 24 deletions(-) create mode 100644 extern/solveImPlot.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 65aa49b..4f8dda2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,6 +43,7 @@ add_library( src/ui/renderer.cpp src/ui/render/renderWindow.cpp src/ui/plot/plotWindow.cpp + src/ui/plot/plotViewTab.cpp src/ui/settings/cameraSettingsWindow.cpp src/ui/settings/worldSettingsWindow.cpp src/ui/settings/planetSettingsWindow.cpp @@ -59,10 +60,13 @@ target_include_directories(shkyera PRIVATE src) target_include_directories(core PRIVATE src ${CMAKE_BINARY_DIR}/_deps/glfw-src/include) target_include_directories(shapes PRIVATE src) target_include_directories(world PRIVATE src) -target_include_directories(ui PRIVATE src ${CMAKE_BINARY_DIR}/_deps/imgui-src ${CMAKE_BINARY_DIR}/_deps/glfw-src/include) +target_include_directories(ui PRIVATE src + ${CMAKE_BINARY_DIR}/_deps/imgui-src + ${CMAKE_BINARY_DIR}/_deps/implot-src + ${CMAKE_BINARY_DIR}/_deps/glfw-src/include) target_link_libraries(shkyera PRIVATE core shapes world ui imgui glfw glad) -target_link_libraries(ui PRIVATE imgui glfw glad core) +target_link_libraries(ui PRIVATE world imgui implot glfw glad core) target_link_libraries(core PRIVATE stb_image glfw glad) diff --git a/extern/extern.cmake b/extern/extern.cmake index aea9205..a16bc5e 100644 --- a/extern/extern.cmake +++ b/extern/extern.cmake @@ -5,5 +5,6 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH};${CMAKE_CURRENT_SOURCE_DIR}/extern) include(solveGlfw) include(solveImGui) +include(solveImPlot) include(solveGlad) include(solveStbImage) diff --git a/extern/solveImPlot.cmake b/extern/solveImPlot.cmake new file mode 100644 index 0000000..eb65200 --- /dev/null +++ b/extern/solveImPlot.cmake @@ -0,0 +1,20 @@ +FetchContent_Declare( + implot + GIT_REPOSITORY "https://github.com/epezent/implot" + GIT_PROGRESS TRUE +) + +FetchContent_MakeAvailable(implot) + +set(IMPLOT_SOURCE + ${CMAKE_BINARY_DIR}/_deps/implot-src/implot.cpp + ${CMAKE_BINARY_DIR}/_deps/implot-src/implot_demo.cpp + ${CMAKE_BINARY_DIR}/_deps/implot-src/implot_items.cpp +) + +add_library(implot STATIC + ${IMPLOT_SOURCE} +) + +target_include_directories(implot PUBLIC "${CMAKE_BINARY_DIR}/implot-src") +target_link_libraries(implot PRIVATE glfw imgui) \ No newline at end of file diff --git a/src/core/image.cpp b/src/core/image.cpp index bea7f08..4ca972c 100644 --- a/src/core/image.cpp +++ b/src/core/image.cpp @@ -14,11 +14,11 @@ namespace shkyera { -image::image() : m_width(0), m_height(0) {} +image::image() : m_width(0), m_height(0), m_dominantColor(randomDouble(0, 1), randomDouble(0, 1), randomDouble(0, 1)) {} image::image(int width, int height) : m_width(width), m_height(height), m_data(height, std::vector(width)), m_verticalPixels(height), - m_horizontalPixels(width) { + m_horizontalPixels(width), m_dominantColor(0, 0, 0) { std::iota(m_verticalPixels.begin(), m_verticalPixels.end(), 0); std::iota(m_horizontalPixels.begin(), m_horizontalPixels.end(), 0); } @@ -48,6 +48,9 @@ image::image(const char *filename) { m_data.resize(height()); + color averageColor; + double imageArea = height() * width(); + for (int y = 0; y < height(); ++y) { std::vector row(width()); @@ -60,11 +63,15 @@ image::image(const char *filename) { } row[x] = pixel; + + averageColor += pixel / imageArea; } m_data[y] = row; } + m_dominantColor = averageColor / 255; + delete raw_data; } @@ -78,6 +85,8 @@ void image::writeImage(std::ostream &out) const { } } +color image::getColor() const { return m_dominantColor; } + void image::scaleImage(std::shared_ptr destinationImage, bool uniformScaling) { float scaleHorizontal = static_cast(width()) / destinationImage->width(); float scaleVertical = static_cast(height()) / destinationImage->height(); diff --git a/src/core/image.hpp b/src/core/image.hpp index 5b486cd..efa91c3 100644 --- a/src/core/image.hpp +++ b/src/core/image.hpp @@ -50,6 +50,8 @@ class image { void clear(); void writeImage(std::ostream &out) const; + color getColor() const; + void scaleImage(std::shared_ptr destinationImage, bool uniformScaling = false); void updateTextureId(); @@ -109,6 +111,8 @@ class image { uint64_t m_textureId; bool m_assignedTextureId; + + color m_dominantColor; }; } // namespace shkyera diff --git a/src/core/texture.cpp b/src/core/texture.cpp index 94d049f..68d66fc 100644 --- a/src/core/texture.cpp +++ b/src/core/texture.cpp @@ -2,6 +2,8 @@ namespace shkyera { +color texture::getColor() const { return color(0.2, 0.8, 0.4); } + solidColor::solidColor(color c) : m_color(c) {} solidColor::solidColor(double r, double g, double b) : m_color(color(r, g, b)) {} @@ -29,6 +31,8 @@ color checkerTexture::value(double u, double v, const point3 &p) const { return m_even->value(u, v, p); } +color checkerTexture::getColor() const { return (m_even->getColor() + m_odd->getColor()) / 2; } + imageTexture::imageTexture(std::shared_ptr image) : m_image(image) {} color imageTexture::value(double u, double v, const point3 &p) const { @@ -50,4 +54,6 @@ color imageTexture::value(double u, double v, const point3 &p) const { return pixelColor; } +color imageTexture::getColor() const { return m_image->getColor(); } + } // namespace shkyera diff --git a/src/core/texture.hpp b/src/core/texture.hpp index 563b10a..8309b07 100644 --- a/src/core/texture.hpp +++ b/src/core/texture.hpp @@ -12,6 +12,7 @@ enum TEXTURE_TYPE { SOLID_COLOR, IMAGE }; class texture { public: virtual color value(double u, double v, const point3 &p) const = 0; + virtual color getColor() const; }; class solidColor : public texture { @@ -22,7 +23,7 @@ class solidColor : public texture { virtual color value(double u, double v, const point3 &p) const override; - color getColor() const; + virtual color getColor() const override; void setColor(color c); private: @@ -38,6 +39,7 @@ class checkerTexture : public texture { checkerTexture(shared_ptr even, shared_ptr odd, double grain); virtual color value(double u, double v, const point3 &p) const override; + virtual color getColor() const override; private: shared_ptr m_even; @@ -54,6 +56,7 @@ class imageTexture : public texture { ~imageTexture() = default; virtual color value(double u, double v, const point3 &p) const override; + virtual color getColor() const override; private: std::shared_ptr m_image; diff --git a/src/main.cpp b/src/main.cpp index eadfa6d..5a0792b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -17,6 +17,7 @@ using namespace shkyera; int main(int argc, char *argv[]) { + const auto aspectRatio = 16.0 / 9.0; const int imageWidth = 600; const int imageHeight = static_cast(imageWidth / aspectRatio); diff --git a/src/shapes/material.cpp b/src/shapes/material.cpp index c08b69d..9f29e07 100644 --- a/src/shapes/material.cpp +++ b/src/shapes/material.cpp @@ -25,6 +25,8 @@ color material::emit(double u, double v, const point3 &p, bool firstHit) const { std::shared_ptr material::getLightMaterial() const { return nullptr; } +color material::getVisibleColor() const { return color(0.2, 0.8, 0.4); } + bool lambertian::scatter(const ray &rayIn, const hitData &data, color &attenuation, ray &rayOut) const { auto scatterDirection = randomInUnitHemisphere(data.normal); rayOut = ray(data.p, scatterDirection); @@ -32,6 +34,8 @@ bool lambertian::scatter(const ray &rayIn, const hitData &data, color &attenuati return true; } +color lambertian::getVisibleColor() const { return m_albedo->getColor(); } + std::shared_ptr lambertian::generateFromImage(std::shared_ptr im) { auto texture = std::make_shared(im); auto material = std::make_shared(texture); @@ -103,6 +107,8 @@ bool metal::scatter(const ray &rayIn, const hitData &data, color &attenuation, r return dot(rayOut.direction(), data.normal) > 0; } +color metal::getVisibleColor() const { return m_albedo; } + bool refractor::scatter(const ray &rayIn, const hitData &data, color &attenuation, ray &rayOut) const { attenuation = color(1.0, 1.0, 1.0); double refractionRatio = data.frontFace ? (1.0 / m_eta) : m_eta; @@ -208,4 +214,6 @@ color diffuseLight::emit(double u, double v, const point3 &p, bool firstHit) con std::shared_ptr diffuseLight::getLightMaterial() const { return m_lightColor; } +color diffuseLight::getVisibleColor() const { return m_textureToDisplay->getColor(); } + } // namespace shkyera diff --git a/src/shapes/material.hpp b/src/shapes/material.hpp index 6c4d851..2d29dc9 100644 --- a/src/shapes/material.hpp +++ b/src/shapes/material.hpp @@ -18,6 +18,7 @@ class material { virtual bool scatter(const ray &rayIn, const hitData &data, color &attenuation, ray &rayOut) const = 0; virtual color emit(double u, double v, const point3 &p, bool firstHit) const; virtual std::shared_ptr getLightMaterial() const; + virtual color getVisibleColor() const; }; class lambertian : public material { @@ -29,6 +30,7 @@ class lambertian : public material { static std::shared_ptr generateFromImageTextureType(int imageTextureType); virtual bool scatter(const ray &rayIn, const hitData &data, color &attenuation, ray &rayOut) const override; + virtual color getVisibleColor() const; private: shared_ptr m_albedo; @@ -39,6 +41,7 @@ class metal : public material { metal(const color &c, double f); virtual bool scatter(const ray &rayIn, const hitData &data, color &attenuation, ray &rayOut) const override; + virtual color getVisibleColor() const; private: color m_albedo; @@ -70,6 +73,7 @@ class diffuseLight : public material { virtual color emit(double u, double v, const point3 &p, bool firstHit) const override; virtual std::shared_ptr getLightMaterial() const override; + virtual color getVisibleColor() const; private: shared_ptr m_textureToDisplay; diff --git a/src/shapes/sphere.cpp b/src/shapes/sphere.cpp index 1ed0e30..a7f9260 100644 --- a/src/shapes/sphere.cpp +++ b/src/shapes/sphere.cpp @@ -47,6 +47,9 @@ void sphere::setMaterial(shared_ptr material) { m_material = material; std::string sphere::getName() const { return m_name; } void sphere::setName(std::string name) { m_name = name; } +point3 sphere::getOrigin() const { return m_center; } +void sphere::setOrigin(point3 p) { m_center = p; } + planetSettings sphere::getSettings() const { planetSettings settings; diff --git a/src/shapes/sphere.hpp b/src/shapes/sphere.hpp index f1df6af..19bb8d9 100644 --- a/src/shapes/sphere.hpp +++ b/src/shapes/sphere.hpp @@ -46,6 +46,9 @@ class sphere { std::string getName() const; void setName(std::string name); + point3 getOrigin() const; + void setOrigin(point3 p); + shared_ptr getMaterial() const; void setMaterial(shared_ptr material); diff --git a/src/ui/plot/plotViewTab.cpp b/src/ui/plot/plotViewTab.cpp index e69de29..46631d6 100644 --- a/src/ui/plot/plotViewTab.cpp +++ b/src/ui/plot/plotViewTab.cpp @@ -0,0 +1,98 @@ +#include + +#include "imgui.h" +#include "implot.h" +#include "ui/plot/plotViewTab.hpp" + +namespace shkyera { + +plotViewTab::plotViewTab(std::shared_ptr world, std::shared_ptr cam, PLANE plane) + : m_world(world), m_camera(cam), m_plane(plane) {} + +systemSettings plotViewTab::render(bool &updated) { + worldSettings settingsWorld; + cameraSettings settingsCamera = m_camera->getSettings(); + systemSettings settingsPlot = {settingsWorld, settingsCamera}; + + ImGui::Unindent(); + if (ImPlot::BeginPlot(("##" + std::to_string(m_plane)).c_str(), + ImVec2(ImGui::GetWindowWidth() - 10, ImGui::GetWindowHeight() - 40), + ImPlotFlags_Equal | ImPlotFlags_NoTitle | ImPlotFlags_NoMouseText)) { + ImPlot::SetupAxes(0, 0, ImPlotAxisFlags_NoTickLabels | ImPlotAxisFlags_NoTickMarks, + ImPlotAxisFlags_NoTickLabels | ImPlotAxisFlags_NoTickMarks); + + auto objects = m_world->getObjects(); + + switch (m_plane) { + case XZ: + std::sort(objects.begin(), objects.end(), + [](const std::shared_ptr &a, const std::shared_ptr &b) -> bool { + return a->getOrigin()[1] < b->getOrigin()[1]; + }); + break; + case XY: + std::sort(objects.begin(), objects.end(), + [](const std::shared_ptr &a, const std::shared_ptr &b) -> bool { + return a->getOrigin()[2] < b->getOrigin()[2]; + }); + break; + case YZ: + default: + std::sort(objects.begin(), objects.end(), + [](const std::shared_ptr &a, const std::shared_ptr &b) -> bool { + return a->getOrigin()[0] < b->getOrigin()[0]; + }); + break; + } + for (auto object : objects) { + if (object == m_world->getUniverse()) + continue; + + planetSettings settingsPlanet = object->getSettings(); + + float x; + float y; + switch (m_plane) { + case XZ: + x = -settingsPlanet.origin[0]; + y = settingsPlanet.origin[2]; + break; + case XY: + x = settingsPlanet.origin[0]; + y = settingsPlanet.origin[1]; + break; + case YZ: + default: + x = settingsPlanet.origin[2]; + y = settingsPlanet.origin[1]; + break; + } + + float lx = x - settingsPlanet.radius - 5; + float ly = y - settingsPlanet.radius - 5; + float tx = x + settingsPlanet.radius + 5; + float ty = y + settingsPlanet.radius + 5; + + float xBorders[4] = {lx, lx, tx, tx}; + float yBorders[4] = {ly, ty, ly, ty}; + + color objectColor = object->getMaterial()->getVisibleColor(); + + ImPlot::SetNextMarkerStyle(ImPlotMarker_Circle, + settingsPlanet.radius / ImPlot::GetPlotLimits().X.Size() * + (0.95 * ImGui::GetWindowWidth()), + ImVec4(objectColor[0], objectColor[1], objectColor[2], 1), -1.0, + ImVec4(objectColor[0], objectColor[1], objectColor[2], 1)); + ImPlot::PlotScatter(settingsPlanet.name.c_str(), &x, &y, 1); + + ImPlot::SetNextMarkerStyle(ImPlotMarker_Circle, 0); + ImPlot::PlotScatter(settingsPlanet.name.c_str(), xBorders, yBorders, 4); + } + + ImPlot::EndPlot(); + } + + return settingsPlot; +} + +} // namespace shkyera \ No newline at end of file diff --git a/src/ui/plot/plotViewTab.hpp b/src/ui/plot/plotViewTab.hpp index e69de29..a6ac869 100644 --- a/src/ui/plot/plotViewTab.hpp +++ b/src/ui/plot/plotViewTab.hpp @@ -0,0 +1,26 @@ +#ifndef PLOT_VIEW_TAB_H +#define PLOT_VIEW_TAB_H + +#include "world/camera.hpp" +#include "world/visibleWorld.hpp" + +namespace shkyera { + +enum PLANE { XY, XZ, YZ }; + +class plotViewTab { + public: + plotViewTab(std::shared_ptr world, std::shared_ptr cam, PLANE plane); + + systemSettings render(bool &updated); + + private: + std::shared_ptr m_world; + std::shared_ptr m_camera; + + PLANE m_plane; +}; + +} // namespace shkyera + +#endif diff --git a/src/ui/plot/plotWindow.cpp b/src/ui/plot/plotWindow.cpp index 3fd6fcf..3a3ba82 100644 --- a/src/ui/plot/plotWindow.cpp +++ b/src/ui/plot/plotWindow.cpp @@ -1,21 +1,28 @@ #include "ui/plot/plotWindow.hpp" #include "imgui.h" +#include "implot.h" namespace shkyera { plotWindow::plotWindow(std::shared_ptr world, std::shared_ptr cam) - : m_world(world), m_camera(cam) {} + : m_topViewTab(world, cam, XZ), m_sideViewTab(world, cam, XY), m_frontViewTab(world, cam, YZ) {} systemSettings plotWindow::render(bool &updated) { - worldSettings settingsWorld; - cameraSettings settingsCamera = m_camera->getSettings(); - systemSettings settingsPlot = {settingsWorld, settingsCamera}; + systemSettings settings; - ImGui::Begin("Planetary System"); + ImGui::Begin("Front view"); + settings = m_frontViewTab.render(updated); + ImGui::End(); + + ImGui::Begin("Side view"); + settings = m_sideViewTab.render(updated); + ImGui::End(); + ImGui::Begin("Top view"); + settings = m_topViewTab.render(updated); ImGui::End(); - return settingsPlot; + return settings; } } // namespace shkyera \ No newline at end of file diff --git a/src/ui/plot/plotWindow.hpp b/src/ui/plot/plotWindow.hpp index 6d59751..a1c35c6 100644 --- a/src/ui/plot/plotWindow.hpp +++ b/src/ui/plot/plotWindow.hpp @@ -1,16 +1,12 @@ #ifndef PLOT_WINDOW_H #define PLOT_WINDOW_H +#include "ui/plot/plotViewTab.hpp" #include "world/camera.hpp" #include "world/visibleWorld.hpp" namespace shkyera { -struct systemSettings { - worldSettings world; - cameraSettings cam; -}; - class plotWindow { public: plotWindow(std::shared_ptr world, std::shared_ptr cam); @@ -18,8 +14,9 @@ class plotWindow { systemSettings render(bool &updated); private: - std::shared_ptr m_world; - std::shared_ptr m_camera; + plotViewTab m_topViewTab; + plotViewTab m_sideViewTab; + plotViewTab m_frontViewTab; }; } // namespace shkyera diff --git a/src/ui/ui.cpp b/src/ui/ui.cpp index fa4d2dc..6fdb00d 100644 --- a/src/ui/ui.cpp +++ b/src/ui/ui.cpp @@ -4,6 +4,7 @@ #include "core/utils.hpp" #include "core/vec3.hpp" +#include "implot.h" #include #include #include @@ -69,6 +70,7 @@ void ui::init() { // Setup window // Setup Dear ImGui context IMGUI_CHECKVERSION(); ImGui::CreateContext(); + ImPlot::CreateContext(); ImGuiIO &io = ImGui::GetIO(); (void)io; io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls @@ -126,13 +128,13 @@ void ui::init() { // Setup window void ui::style() { ImGuiStyle &style = ImGui::GetStyle(); - style.WindowMinSize = ImVec2(160, 20); + style.WindowMinSize = ImVec2(320, 320); style.FramePadding = ImVec2(4, 2); style.ItemSpacing = ImVec2(6, 2); style.ItemInnerSpacing = ImVec2(6, 4); style.Alpha = 0.95f; - style.WindowRounding = 4.0f; - style.FrameRounding = 2.0f; + style.WindowRounding = 8.0f; + style.FrameRounding = 8.0f; style.IndentSpacing = 6.0f; style.ItemInnerSpacing = ImVec2(2, 4); style.ColumnsMinSpacing = 50.0f; @@ -156,17 +158,22 @@ void ui::style() { style.Colors[ImGuiCol_WindowBg] = BACKGROUND_COLOR; style.Colors[ImGuiCol_BorderShadow] = BLACK; style.Colors[ImGuiCol_FrameBg] = ACCENT_COLOR; - style.Colors[ImGuiCol_TitleBg] = ACCENT_COLOR; style.Colors[ImGuiCol_ScrollbarBg] = ACCENT_COLOR; style.Colors[ImGuiCol_FrameBgHovered] = ACCENT_COLOR; style.Colors[ImGuiCol_FrameBgActive] = STRONG_ACCENT_COLOR; - style.Colors[ImGuiCol_TitleBgCollapsed] = ACCENT_COLOR; + style.Colors[ImGuiCol_TitleBgCollapsed] = BACKGROUND_COLOR; + style.Colors[ImGuiCol_TitleBg] = ACCENT_COLOR; style.Colors[ImGuiCol_TitleBgActive] = STRONG_ACCENT_COLOR; style.Colors[ImGuiCol_SliderGrab] = ACCENT_COLOR; style.Colors[ImGuiCol_SliderGrabActive] = STRONG_ACCENT_COLOR; style.Colors[ImGuiCol_Separator] = GREY; style.Colors[ImGuiCol_SeparatorHovered] = LIGHT_GREY; style.Colors[ImGuiCol_SeparatorActive] = LIGHT_GREY; + + ImPlotStyle &plotStyle = ImPlot::GetStyle(); + plotStyle.Colors[ImPlotCol_FrameBg] = BACKGROUND_COLOR; + plotStyle.Colors[ImPlotCol_PlotBg] = BACKGROUND_COLOR; + plotStyle.Colors[ImPlotCol_PlotBorder] = BACKGROUND_COLOR; } void ui::run() { @@ -235,7 +242,11 @@ void ui::run() { ImGui::DockBuilderSplitNode(dock_id_left, ImGuiDir_Up, 0.5f, &dock_id_top_left, &dock_id_bottom_left); ImGui::DockBuilderDockWindow("Render", dock_id_top_left); - ImGui::DockBuilderDockWindow("Planetary System", dock_id_bottom_left); + + ImGui::DockBuilderDockWindow("Top view", dock_id_bottom_left); + ImGui::DockBuilderDockWindow("Front view", dock_id_bottom_left); + ImGui::DockBuilderDockWindow("Side view", dock_id_bottom_left); + ImGui::DockBuilderDockWindow("Camera", dock_id_top_right); ImGui::DockBuilderDockWindow("World", dock_id_bottom_right); @@ -300,6 +311,7 @@ void ui::close() { ImGui_ImplOpenGL3_Shutdown(); ImGui_ImplGlfw_Shutdown(); ImGui::DestroyContext(); + ImPlot::DestroyContext(); glfwDestroyWindow(m_window); glfwTerminate(); diff --git a/src/world/visibleWorld.hpp b/src/world/visibleWorld.hpp index 23c4535..0d0b117 100644 --- a/src/world/visibleWorld.hpp +++ b/src/world/visibleWorld.hpp @@ -5,6 +5,7 @@ #include "core/utils.hpp" #include "core/vec3.hpp" #include "shapes/sphere.hpp" +#include "world/camera.hpp" #include #include @@ -20,6 +21,11 @@ struct worldSettings { std::vector updatedPlanets; }; +struct systemSettings { + worldSettings world; + cameraSettings cam; +}; + class visibleWorld { public: visibleWorld(); From 5e2cd8857e3c95242097e2dbe4143a789bb991c8 Mon Sep 17 00:00:00 2001 From: fszewczyk Date: Fri, 17 Mar 2023 20:14:48 +0100 Subject: [PATCH 3/7] Plotting camera position --- src/ui/plot/plotViewTab.cpp | 60 ++++++++++++++++++++++++ src/ui/settings/planetSettingsWindow.cpp | 10 ++-- 2 files changed, 65 insertions(+), 5 deletions(-) diff --git a/src/ui/plot/plotViewTab.cpp b/src/ui/plot/plotViewTab.cpp index 46631d6..04ee80d 100644 --- a/src/ui/plot/plotViewTab.cpp +++ b/src/ui/plot/plotViewTab.cpp @@ -21,6 +21,29 @@ systemSettings plotViewTab::render(bool &updated) { ImPlot::SetupAxes(0, 0, ImPlotAxisFlags_NoTickLabels | ImPlotAxisFlags_NoTickMarks, ImPlotAxisFlags_NoTickLabels | ImPlotAxisFlags_NoTickMarks); + cameraSettings settings = m_camera->getSettings(); + + float x; + float y; + switch (m_plane) { + case XZ: + x = -settings.origin[0]; + y = settings.origin[2]; + break; + case XY: + x = settings.origin[0]; + y = settings.origin[1]; + break; + case YZ: + default: + x = settings.origin[2]; + y = settings.origin[1]; + break; + } + + ImPlot::SetNextMarkerStyle(ImPlotMarker_Diamond, 8, ImVec4(0.3, 0.3, 0.3, 1), -1.0f, ImVec4(0.2, 0.2, 0.2, 1)); + ImPlot::PlotScatter("Camera", &x, &y, 1); + auto objects = m_world->getObjects(); switch (m_plane) { @@ -44,6 +67,43 @@ systemSettings plotViewTab::render(bool &updated) { }); break; } + + auto legendObjects = objects; + + std::sort(legendObjects.begin(), legendObjects.end(), + [](const std::shared_ptr &a, const std::shared_ptr &b) -> bool { + return a->getName() < b->getName(); + }); + + // Ensures legend to be sorted by order. I apologize to anybody that sees this, I did not have a better idea. + if (objects.size() > 1) { + planetSettings settingsPlanet = objects[1]->getSettings(); + float x; + float y; + switch (m_plane) { + case XZ: + x = -settingsPlanet.origin[0]; + y = settingsPlanet.origin[2]; + break; + case XY: + x = settingsPlanet.origin[0]; + y = settingsPlanet.origin[1]; + break; + case YZ: + default: + x = settingsPlanet.origin[2]; + y = settingsPlanet.origin[1]; + break; + } + for (auto object : legendObjects) { + if (object == m_world->getUniverse()) + continue; + + ImPlot::SetNextMarkerStyle(ImPlotMarker_Circle, 0); + ImPlot::PlotScatter(object->getName().c_str(), &x, &y, 1); + } + } + for (auto object : objects) { if (object == m_world->getUniverse()) continue; diff --git a/src/ui/settings/planetSettingsWindow.cpp b/src/ui/settings/planetSettingsWindow.cpp index 7e6ed24..7640fa2 100644 --- a/src/ui/settings/planetSettingsWindow.cpp +++ b/src/ui/settings/planetSettingsWindow.cpp @@ -30,15 +30,14 @@ planetSettings planetSettingsWindow::render(bool &updated) { ImGui::PushFont(ui::BOLD_FONT); ImGui::Text("Visual"); ImGui::PopFont(); - settings.mat = renderMaterialSettings(); - ImGui::SameLine(); ImGui::SliderFloat(("Radius##" + settings.name).c_str(), &radius, 0.1f, 20.0f, "%.2f"); ImGui::Dummy(ImVec2(0.0f, 5.0f)); + settings.mat = renderMaterialSettings(); ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(ImColor(82, 3, 23))); ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(ImColor(166, 15, 53))); - - if (ImGui::Button("Remove", ImVec2(0.96 * ImGui::GetWindowWidth() - 100, 0.0f))) { + ImGui::SameLine(); + if (ImGui::Button("Remove", ImVec2((ImGui::GetWindowWidth() - 122) / 2, 0))) { settings.remove = true; } @@ -76,7 +75,8 @@ std::shared_ptr planetSettingsWindow::renderMaterialSettings() { static bool isLight = planetLightColor != nullptr; static float lightIntensity = 5; - if (ImGui::Button(("Choose Texture##" + m_planet->getName()).c_str())) { + if (ImGui::Button(("Choose Texture##" + m_planet->getName()).c_str(), + ImVec2((ImGui::GetWindowWidth() - 122) / 2, 0))) { ImGui::OpenPopup((m_planet->getName() + " Texture").c_str()); useSolidColor = false; } From c9f9fe578f28f76b52896f57f7afadf5f65bc31a Mon Sep 17 00:00:00 2001 From: fszewczyk Date: Tue, 21 Mar 2023 17:38:17 +0100 Subject: [PATCH 4/7] Draggable points --- src/main.cpp | 4 +- src/shapes/sphere.cpp | 3 + src/shapes/sphere.hpp | 3 + src/ui/plot/plotViewTab.cpp | 269 +++++++++++++---------- src/ui/plot/plotViewTab.hpp | 8 + src/ui/settings/cameraSettingsWindow.cpp | 4 +- src/ui/settings/worldSettingsWindow.cpp | 1 + 7 files changed, 171 insertions(+), 121 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 5a0792b..25adb9e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -32,8 +32,8 @@ int main(int argc, char *argv[]) { world->add(make_shared(point3(0, 0, -17.5), 10.0, sunMaterial, "Sun")); world->add(make_shared(point3(0, 0, 3), 1.0, marsMaterial, "Mars")); - point3 lookfrom(6, 2, 8); - point3 lookat(100, 20, 100); + point3 lookfrom(-26, 2, -18); + point3 lookat(-100, 20, -100); auto dist_to_focus = 10.0; auto aperture = 0.0; diff --git a/src/shapes/sphere.cpp b/src/shapes/sphere.cpp index a7f9260..577af06 100644 --- a/src/shapes/sphere.cpp +++ b/src/shapes/sphere.cpp @@ -50,6 +50,9 @@ void sphere::setName(std::string name) { m_name = name; } point3 sphere::getOrigin() const { return m_center; } void sphere::setOrigin(point3 p) { m_center = p; } +double sphere::getRadius() const { return m_radius; } +void sphere::setRadius(double radius) { m_radius = radius; } + planetSettings sphere::getSettings() const { planetSettings settings; diff --git a/src/shapes/sphere.hpp b/src/shapes/sphere.hpp index 19bb8d9..7c2226e 100644 --- a/src/shapes/sphere.hpp +++ b/src/shapes/sphere.hpp @@ -49,6 +49,9 @@ class sphere { point3 getOrigin() const; void setOrigin(point3 p); + double getRadius() const; + void setRadius(double radius); + shared_ptr getMaterial() const; void setMaterial(shared_ptr material); diff --git a/src/ui/plot/plotViewTab.cpp b/src/ui/plot/plotViewTab.cpp index 04ee80d..0ae73f6 100644 --- a/src/ui/plot/plotViewTab.cpp +++ b/src/ui/plot/plotViewTab.cpp @@ -1,4 +1,5 @@ #include +#include #include "imgui.h" #include "implot.h" @@ -18,141 +19,175 @@ systemSettings plotViewTab::render(bool &updated) { if (ImPlot::BeginPlot(("##" + std::to_string(m_plane)).c_str(), ImVec2(ImGui::GetWindowWidth() - 10, ImGui::GetWindowHeight() - 40), ImPlotFlags_Equal | ImPlotFlags_NoTitle | ImPlotFlags_NoMouseText)) { - ImPlot::SetupAxes(0, 0, ImPlotAxisFlags_NoTickLabels | ImPlotAxisFlags_NoTickMarks, - ImPlotAxisFlags_NoTickLabels | ImPlotAxisFlags_NoTickMarks); - cameraSettings settings = m_camera->getSettings(); - - float x; - float y; - switch (m_plane) { - case XZ: - x = -settings.origin[0]; - y = settings.origin[2]; - break; - case XY: - x = settings.origin[0]; - y = settings.origin[1]; - break; - case YZ: - default: - x = settings.origin[2]; - y = settings.origin[1]; - break; - } + labelAxes(); + plotDummyPoints(); + plotPlanets(); + plotCamera(); - ImPlot::SetNextMarkerStyle(ImPlotMarker_Diamond, 8, ImVec4(0.3, 0.3, 0.3, 1), -1.0f, ImVec4(0.2, 0.2, 0.2, 1)); - ImPlot::PlotScatter("Camera", &x, &y, 1); - - auto objects = m_world->getObjects(); - - switch (m_plane) { - case XZ: - std::sort(objects.begin(), objects.end(), - [](const std::shared_ptr &a, const std::shared_ptr &b) -> bool { - return a->getOrigin()[1] < b->getOrigin()[1]; - }); - break; - case XY: - std::sort(objects.begin(), objects.end(), - [](const std::shared_ptr &a, const std::shared_ptr &b) -> bool { - return a->getOrigin()[2] < b->getOrigin()[2]; - }); - break; - case YZ: - default: - std::sort(objects.begin(), objects.end(), - [](const std::shared_ptr &a, const std::shared_ptr &b) -> bool { - return a->getOrigin()[0] < b->getOrigin()[0]; - }); - break; - } + ImPlot::EndPlot(); + } - auto legendObjects = objects; + return settingsPlot; +} - std::sort(legendObjects.begin(), legendObjects.end(), - [](const std::shared_ptr &a, const std::shared_ptr &b) -> bool { - return a->getName() < b->getName(); - }); +void plotViewTab::labelAxes() { + switch (m_plane) { + case XZ: + ImPlot::SetupAxes("X", "Z", ImPlotAxisFlags_Invert | ImPlotAxisFlags_NoTickLabels | ImPlotAxisFlags_NoTickMarks, + ImPlotAxisFlags_NoTickLabels | ImPlotAxisFlags_NoTickMarks); + break; + case XY: + ImPlot::SetupAxes("X", "Y", ImPlotAxisFlags_NoTickLabels | ImPlotAxisFlags_NoTickMarks, + ImPlotAxisFlags_NoTickLabels | ImPlotAxisFlags_NoTickMarks); + break; + case YZ: + ImPlot::SetupAxes("Z", "Y", ImPlotAxisFlags_NoTickLabels | ImPlotAxisFlags_NoTickMarks, + ImPlotAxisFlags_NoTickLabels | ImPlotAxisFlags_NoTickMarks); + break; + } +} - // Ensures legend to be sorted by order. I apologize to anybody that sees this, I did not have a better idea. - if (objects.size() > 1) { - planetSettings settingsPlanet = objects[1]->getSettings(); - float x; - float y; - switch (m_plane) { - case XZ: - x = -settingsPlanet.origin[0]; - y = settingsPlanet.origin[2]; - break; - case XY: - x = settingsPlanet.origin[0]; - y = settingsPlanet.origin[1]; - break; - case YZ: - default: - x = settingsPlanet.origin[2]; - y = settingsPlanet.origin[1]; - break; - } - for (auto object : legendObjects) { - if (object == m_world->getUniverse()) - continue; - - ImPlot::SetNextMarkerStyle(ImPlotMarker_Circle, 0); - ImPlot::PlotScatter(object->getName().c_str(), &x, &y, 1); - } - } +void plotViewTab::plotDummyPoints() { + auto objects = m_world->getObjects(); + + std::sort(objects.begin(), objects.end(), + [](const std::shared_ptr &a, const std::shared_ptr &b) -> bool { + return a->getName() < b->getName(); + }); + // Ensures legend to be sorted by order by putting dummy points. + // My sincere apologies to anybody that sees this, I did not have a better idea. + if (objects.size() > 1) { + planetSettings settingsPlanet = objects[1]->getSettings(); + auto [x, y] = getPositionOnPlane(settingsPlanet.origin); for (auto object : objects) { if (object == m_world->getUniverse()) continue; - planetSettings settingsPlanet = object->getSettings(); - - float x; - float y; - switch (m_plane) { - case XZ: - x = -settingsPlanet.origin[0]; - y = settingsPlanet.origin[2]; - break; - case XY: - x = settingsPlanet.origin[0]; - y = settingsPlanet.origin[1]; - break; - case YZ: - default: - x = settingsPlanet.origin[2]; - y = settingsPlanet.origin[1]; - break; - } - - float lx = x - settingsPlanet.radius - 5; - float ly = y - settingsPlanet.radius - 5; - float tx = x + settingsPlanet.radius + 5; - float ty = y + settingsPlanet.radius + 5; - - float xBorders[4] = {lx, lx, tx, tx}; - float yBorders[4] = {ly, ty, ly, ty}; - color objectColor = object->getMaterial()->getVisibleColor(); - ImPlot::SetNextMarkerStyle(ImPlotMarker_Circle, - settingsPlanet.radius / ImPlot::GetPlotLimits().X.Size() * - (0.95 * ImGui::GetWindowWidth()), + ImPlot::SetNextMarkerStyle(ImPlotMarker_Circle, 0, ImVec4(objectColor[0], objectColor[1], objectColor[2], 1), -1.0, ImVec4(objectColor[0], objectColor[1], objectColor[2], 1)); - ImPlot::PlotScatter(settingsPlanet.name.c_str(), &x, &y, 1); - - ImPlot::SetNextMarkerStyle(ImPlotMarker_Circle, 0); - ImPlot::PlotScatter(settingsPlanet.name.c_str(), xBorders, yBorders, 4); + ImPlot::PlotScatter(object->getName().c_str(), &x, &y, 1); } + } +} - ImPlot::EndPlot(); +void plotViewTab::plotCamera() { + cameraSettings settingsCamera = m_camera->getSettings(); + + auto [x, y] = getPositionOnPlane(settingsCamera.origin); + + ImPlot::SetNextMarkerStyle(ImPlotMarker_Diamond, 8, ImVec4(0.3, 0.3, 0.3, 1), -1.0f, ImVec4(0.2, 0.2, 0.2, 1)); + ImPlot::DragPoint(std::hash{}("Camera"), &x, &y, ImVec4(0.3, 0.3, 0.3, 1), 7); +} + +void plotViewTab::plotPlanets() { + auto objectsByPosition = m_world->getObjects(); + auto objectsBySize = objectsByPosition; + + std::sort(objectsBySize.begin(), objectsBySize.end(), + [](const std::shared_ptr &a, const std::shared_ptr &b) -> bool { + return a->getRadius() < b->getRadius(); + }); + + switch (m_plane) { + case XZ: + std::sort(objectsByPosition.begin(), objectsByPosition.end(), + [](const std::shared_ptr &a, const std::shared_ptr &b) -> bool { + return a->getOrigin()[1] < b->getOrigin()[1]; + }); + break; + case XY: + std::sort(objectsByPosition.begin(), objectsByPosition.end(), + [](const std::shared_ptr &a, const std::shared_ptr &b) -> bool { + return a->getOrigin()[2] < b->getOrigin()[2]; + }); + break; + case YZ: + default: + std::sort(objectsByPosition.begin(), objectsByPosition.end(), + [](const std::shared_ptr &a, const std::shared_ptr &b) -> bool { + return a->getOrigin()[0] < b->getOrigin()[0]; + }); + break; } - return settingsPlot; + for (auto object : objectsBySize) { + if (object == m_world->getUniverse()) + continue; + + planetSettings settingsPlanet = object->getSettings(); + auto [x, y] = getPositionOnPlane(settingsPlanet.origin); + + color objectColor = object->getMaterial()->getVisibleColor(); + + ImPlot::SetNextMarkerStyle(ImPlotMarker_Circle, + settingsPlanet.radius / ImPlot::GetPlotLimits().X.Size() * + (0.95 * ImGui::GetWindowWidth()), + ImVec4(objectColor[0], objectColor[1], objectColor[2], 1), -1.0, + ImVec4(objectColor[0], objectColor[1], objectColor[2], 1)); + + ImPlot::DragPoint(std::hash{}(settingsPlanet.name), &x, &y, + ImVec4(objectColor[0], objectColor[1], objectColor[2], 1), + settingsPlanet.radius / ImPlot::GetPlotLimits().X.Size() * (0.95 * ImGui::GetWindowWidth())); + } + + for (auto object : objectsByPosition) { + if (object == m_world->getUniverse()) + continue; + + planetSettings settingsPlanet = object->getSettings(); + + auto [x, y] = getPositionOnPlane(settingsPlanet.origin); + + float lx = x - settingsPlanet.radius - 5; + float ly = y - settingsPlanet.radius - 5; + float tx = x + settingsPlanet.radius + 5; + float ty = y + settingsPlanet.radius + 5; + + float xBorders[4] = {lx, lx, tx, tx}; + float yBorders[4] = {ly, ty, ly, ty}; + + color objectColor = object->getMaterial()->getVisibleColor(); + + ImPlot::SetNextMarkerStyle(ImPlotMarker_Circle, + settingsPlanet.radius / ImPlot::GetPlotLimits().X.Size() * + (0.95 * ImGui::GetWindowWidth()), + ImVec4(objectColor[0], objectColor[1], objectColor[2], 1), -1.0, + ImVec4(objectColor[0], objectColor[1], objectColor[2], 1)); + + ImPlot::DragPoint(std::hash{}(settingsPlanet.name), &x, &y, + ImVec4(objectColor[0], objectColor[1], objectColor[2], 1), + settingsPlanet.radius / ImPlot::GetPlotLimits().X.Size() * (0.95 * ImGui::GetWindowWidth())); + + ImPlot::SetNextMarkerStyle(ImPlotMarker_Circle, 0); + ImPlot::PlotScatter(settingsPlanet.name.c_str(), xBorders, yBorders, 4); + } +} + +std::pair plotViewTab::getPositionOnPlane(point3 point) { + double x; + double y; + switch (m_plane) { + case XZ: + x = point[0]; + y = point[2]; + break; + case XY: + x = point[0]; + y = point[1]; + break; + case YZ: + default: + x = point[2]; + y = point[1]; + break; + } + + return {x, y}; } } // namespace shkyera \ No newline at end of file diff --git a/src/ui/plot/plotViewTab.hpp b/src/ui/plot/plotViewTab.hpp index a6ac869..44b34cd 100644 --- a/src/ui/plot/plotViewTab.hpp +++ b/src/ui/plot/plotViewTab.hpp @@ -15,6 +15,14 @@ class plotViewTab { systemSettings render(bool &updated); private: + void plotDummyPoints(); + void plotCamera(); + void plotPlanets(); + + void labelAxes(); + + std::pair getPositionOnPlane(point3 point); + std::shared_ptr m_world; std::shared_ptr m_camera; diff --git a/src/ui/settings/cameraSettingsWindow.cpp b/src/ui/settings/cameraSettingsWindow.cpp index 82dce93..c8b0cf9 100644 --- a/src/ui/settings/cameraSettingsWindow.cpp +++ b/src/ui/settings/cameraSettingsWindow.cpp @@ -13,7 +13,7 @@ cameraSettings cameraSettingsWindow::render(bool &updated) { cameraSettings settings = m_camera->getSettings(); - float positionX = settings.origin[0]; + float positionX = -settings.origin[0]; float positionY = settings.origin[1]; float positionZ = settings.origin[2]; @@ -39,7 +39,7 @@ cameraSettings cameraSettingsWindow::render(bool &updated) { ImGui::End(); - settings.origin[0] = positionX; + settings.origin[0] = -positionX; settings.origin[1] = positionY; settings.origin[2] = positionZ; diff --git a/src/ui/settings/worldSettingsWindow.cpp b/src/ui/settings/worldSettingsWindow.cpp index 8093345..ae9e60a 100644 --- a/src/ui/settings/worldSettingsWindow.cpp +++ b/src/ui/settings/worldSettingsWindow.cpp @@ -44,6 +44,7 @@ worldSettings worldSettingsWindow::render(bool &updated) { if (ImGui::BeginPopupModal("Add New Object", NULL, ImGuiWindowFlags_AlwaysAutoResize)) { ImGui::InputText("Name", planetName, IM_ARRAYSIZE(planetName)); + ImGui::Dummy(ImVec2(0.0f, 5.0f)); if (ImGui::Button("Cancel")) { ImGui::CloseCurrentPopup(); } From 73108044efdb86c3330daad0e16124239d79ad94 Mon Sep 17 00:00:00 2001 From: fszewczyk Date: Tue, 21 Mar 2023 18:47:26 +0100 Subject: [PATCH 5/7] Updating the world on drag --- src/ui/plot/plotViewTab.cpp | 65 +++++++++++++++++++++++++++++++++---- src/ui/plot/plotViewTab.hpp | 5 +-- src/ui/plot/plotWindow.cpp | 15 +++++++-- src/ui/ui.cpp | 13 ++++++-- 4 files changed, 84 insertions(+), 14 deletions(-) diff --git a/src/ui/plot/plotViewTab.cpp b/src/ui/plot/plotViewTab.cpp index 0ae73f6..8e5d5a2 100644 --- a/src/ui/plot/plotViewTab.cpp +++ b/src/ui/plot/plotViewTab.cpp @@ -1,5 +1,6 @@ #include #include +#include #include "imgui.h" #include "implot.h" @@ -11,7 +12,7 @@ plotViewTab::plotViewTab(std::shared_ptr world, std::shared_ptrgetSettings(); cameraSettings settingsCamera = m_camera->getSettings(); systemSettings settingsPlot = {settingsWorld, settingsCamera}; @@ -22,12 +23,22 @@ systemSettings plotViewTab::render(bool &updated) { labelAxes(); plotDummyPoints(); - plotPlanets(); - plotCamera(); + settingsCamera = plotCamera(); + settingsWorld = plotPlanets(); + settingsCamera = plotCamera(); ImPlot::EndPlot(); } + if (!(settingsCamera == m_camera->getSettings())) + updated = true; + + for (auto wasUpdated : settingsWorld.updatedPlanets) + updated |= wasUpdated; + + settingsPlot.cam = settingsCamera; + settingsPlot.world = settingsWorld; + return settingsPlot; } @@ -56,8 +67,8 @@ void plotViewTab::plotDummyPoints() { return a->getName() < b->getName(); }); - // Ensures legend to be sorted by order by putting dummy points. - // My sincere apologies to anybody that sees this, I did not have a better idea. + // Ensures legend to be sorted in lexicographical order by putting dummy points. + // My sincere apologies to anybody that reads this, I did not have a better idea. if (objects.size() > 1) { planetSettings settingsPlanet = objects[1]->getSettings(); auto [x, y] = getPositionOnPlane(settingsPlanet.origin); @@ -75,19 +86,30 @@ void plotViewTab::plotDummyPoints() { } } -void plotViewTab::plotCamera() { +cameraSettings plotViewTab::plotCamera() { cameraSettings settingsCamera = m_camera->getSettings(); auto [x, y] = getPositionOnPlane(settingsCamera.origin); ImPlot::SetNextMarkerStyle(ImPlotMarker_Diamond, 8, ImVec4(0.3, 0.3, 0.3, 1), -1.0f, ImVec4(0.2, 0.2, 0.2, 1)); ImPlot::DragPoint(std::hash{}("Camera"), &x, &y, ImVec4(0.3, 0.3, 0.3, 1), 7); + + settingsCamera.origin = getPointFromPlane(settingsCamera.origin, x, y); + + return settingsCamera; } -void plotViewTab::plotPlanets() { +worldSettings plotViewTab::plotPlanets() { + worldSettings settingsWorld = m_world->getSettings(); + auto objectsByPosition = m_world->getObjects(); auto objectsBySize = objectsByPosition; + std::map, size_t> originalPlanetIndices; + for (size_t i = 1; i < objectsBySize.size(); ++i) { + originalPlanetIndices.insert(std::make_pair(objectsBySize[i], i - 1)); + } + std::sort(objectsBySize.begin(), objectsBySize.end(), [](const std::shared_ptr &a, const std::shared_ptr &b) -> bool { return a->getRadius() < b->getRadius(); @@ -165,7 +187,16 @@ void plotViewTab::plotPlanets() { ImPlot::SetNextMarkerStyle(ImPlotMarker_Circle, 0); ImPlot::PlotScatter(settingsPlanet.name.c_str(), xBorders, yBorders, 4); + + settingsPlanet.origin = getPointFromPlane(settingsPlanet.origin, x, y); + + if (settingsPlanet.origin != object->getSettings().origin) { + settingsWorld.planets[originalPlanetIndices[object]] = settingsPlanet; + settingsWorld.updatedPlanets[originalPlanetIndices[object]] = true; + } } + + return settingsWorld; } std::pair plotViewTab::getPositionOnPlane(point3 point) { @@ -190,4 +221,24 @@ std::pair plotViewTab::getPositionOnPlane(point3 point) { return {x, y}; } +point3 plotViewTab::getPointFromPlane(point3 point, float x, float y) { + switch (m_plane) { + case XZ: + point[0] = x; + point[2] = y; + break; + case XY: + point[0] = x; + point[1] = y; + break; + case YZ: + default: + point[2] = x; + point[1] = y; + break; + } + + return point; +} + } // namespace shkyera \ No newline at end of file diff --git a/src/ui/plot/plotViewTab.hpp b/src/ui/plot/plotViewTab.hpp index 44b34cd..c07f426 100644 --- a/src/ui/plot/plotViewTab.hpp +++ b/src/ui/plot/plotViewTab.hpp @@ -16,12 +16,13 @@ class plotViewTab { private: void plotDummyPoints(); - void plotCamera(); - void plotPlanets(); + cameraSettings plotCamera(); + worldSettings plotPlanets(); void labelAxes(); std::pair getPositionOnPlane(point3 point); + point3 getPointFromPlane(point3 point, float x, float y); std::shared_ptr m_world; std::shared_ptr m_camera; diff --git a/src/ui/plot/plotWindow.cpp b/src/ui/plot/plotWindow.cpp index 3a3ba82..1457918 100644 --- a/src/ui/plot/plotWindow.cpp +++ b/src/ui/plot/plotWindow.cpp @@ -11,17 +11,26 @@ systemSettings plotWindow::render(bool &updated) { systemSettings settings; ImGui::Begin("Front view"); - settings = m_frontViewTab.render(updated); + systemSettings frontSettings = m_frontViewTab.render(updated); + settings = frontSettings; ImGui::End(); ImGui::Begin("Side view"); - settings = m_sideViewTab.render(updated); + bool sideUpdated = false; + systemSettings sideSettings = m_sideViewTab.render(sideUpdated); + if (sideUpdated) + settings = sideSettings; ImGui::End(); ImGui::Begin("Top view"); - settings = m_topViewTab.render(updated); + bool topUpdated = false; + systemSettings topSettings = m_topViewTab.render(topUpdated); + if (topUpdated) + settings = topSettings; ImGui::End(); + updated |= sideUpdated | topUpdated; + return settings; } diff --git a/src/ui/ui.cpp b/src/ui/ui.cpp index 6fdb00d..5e8baa2 100644 --- a/src/ui/ui.cpp +++ b/src/ui/ui.cpp @@ -257,10 +257,19 @@ void ui::run() { ImGui::End(); bool updatedSettings = false; - cameraSettings newCameraSettings = m_cameraSettingsWindow.render(updatedSettings); - worldSettings newWorldSettings = m_worldSettingsWindow.render(updatedSettings); systemSettings newSystemSettings = m_plotWindow.render(updatedSettings); + cameraSettings newCameraSettings = newSystemSettings.cam; + worldSettings newWorldSettings = newSystemSettings.world; + + if (updatedSettings) { + m_cameraSettingsWindow.render(updatedSettings); + m_worldSettingsWindow.render(updatedSettings); + } else { + newCameraSettings = m_cameraSettingsWindow.render(updatedSettings); + newWorldSettings = m_worldSettingsWindow.render(updatedSettings); + } + point3 cameraTranslation; std::pair mouseMovement; From 9dcc1ec1dae9d2429854e1798a391812371de4ca Mon Sep 17 00:00:00 2001 From: fszewczyk Date: Tue, 21 Mar 2023 18:51:09 +0100 Subject: [PATCH 6/7] Sad comment on our society --- src/ui/plot/plotViewTab.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ui/plot/plotViewTab.cpp b/src/ui/plot/plotViewTab.cpp index 8e5d5a2..5daae65 100644 --- a/src/ui/plot/plotViewTab.cpp +++ b/src/ui/plot/plotViewTab.cpp @@ -23,6 +23,8 @@ systemSettings plotViewTab::render(bool &updated) { labelAxes(); plotDummyPoints(); + + // Plotting camera twice is necessary for dragging settingsCamera = plotCamera(); settingsWorld = plotPlanets(); settingsCamera = plotCamera(); From 51eb6e577960f7955641e791b1e54955db4b6fb2 Mon Sep 17 00:00:00 2001 From: fszewczyk Date: Tue, 21 Mar 2023 19:23:29 +0100 Subject: [PATCH 7/7] Displaying camera focus range --- src/ui/plot/plotViewTab.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/ui/plot/plotViewTab.cpp b/src/ui/plot/plotViewTab.cpp index 5daae65..7ef62d2 100644 --- a/src/ui/plot/plotViewTab.cpp +++ b/src/ui/plot/plotViewTab.cpp @@ -98,6 +98,18 @@ cameraSettings plotViewTab::plotCamera() { settingsCamera.origin = getPointFromPlane(settingsCamera.origin, x, y); + static float focusX[361]; + static float focusY[361]; + for (double deg = 0; deg <= 360; ++deg) { + double angle = deg * 2 * PI / 360; + focusX[static_cast(deg)] = cosf(angle) * settingsCamera.focusDistance + x; + focusY[static_cast(deg)] = sinf(angle) * settingsCamera.focusDistance + y; + } + + ImPlot::SetNextMarkerStyle(ImPlotMarker_None); + ImPlot::SetNextLineStyle(ImVec4(0.3, 0.3, 0.3, settingsCamera.depthOfField), 2); + ImPlot::PlotLine("Camera Focus", focusX, focusY, 361); + return settingsCamera; }