diff --git a/.appveyor.yml b/.appveyor.yml index 591ac67..ff04e40 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -5,13 +5,37 @@ clone_folder: C:\projects\fish_deformation branches: only: - master + - michael install: - git submodule update --init --recursive - cinstall: python +build: + parallel: true build_script: - - echo Running cmake... + - echo Running cmake .. + - cd c:\tools\vcpkg + - .\vcpkg.exe --triplet x64-windows install mpir mpfr - cd c:\projects\fish_deformation + - set PATH=C:\Python%PYTHON%-x64;C:\Python%PYTHON%-x64\Scripts;%PATH% - mkdir build - cd build - - cmake -G "Visual Studio 15 2017 Win64" -T "host=x64" .. - - msbuild %MSBuildOptions% fish_deformation + - cmake -G "Visual Studio 15 2017 Win64" + -DCMAKE_PREFIX_PATH="C:/Qt/5.10.1/msvc2017_64/lib/cmake" + -DMPFR_INCLUDE_DIR:PATH="C:/tools/vcpkg/installed/x64-windows/include" + -DMPFR_LIBRARIES:FILEPATH="C:/tools/vcpkg/installed/x64-windows/lib/mpfr.lib" + -DGMP_INCLUDE_DIR:PATH="C:/tools/vcpkg/installed/x64-windows/include" + -DGMP_LIBRARIES:FILEPATH="C:/tools/vcpkg/installed/x64-windows/lib/mpir.lib" + -DBOOST_ROOT="C:/Libraries/boost_1_65_1" ../ + - set MSBuildOptions=/v:m /p:Configuration=Release /p:Platform=x64 + - msbuild %MSBuildOptions% fish_deformation.sln +after_build: + - cd .. + - mkdir unwind + - copy build\src\Release\unwind.exe unwind + - copy build\src\Release\mpir.dll unwind + - cd C:\Qt\latest\msvc2017_64\bin + - windeployqt C:\projects\fish_deformation\unwind\unwind.exe + - cd C:\projects\fish_deformation + - 7z a unwind.zip unwind\ +artifacts: + - path: unwind.zip diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..1b0bb5a --- /dev/null +++ b/.travis.yml @@ -0,0 +1,86 @@ +dist: trusty +sudo: true +language: cpp +cache: ccache +branches: + only: + - master + - michael +addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - cmake + - g++-6 + - gcc-6 + - g++-7 + - gcc-7 + - libblas-dev + - libboost-filesystem-dev + - libboost-system-dev + - libboost-thread-dev + - libglu1-mesa-dev + - liblapack-dev + - libmpfr-dev + - libpython3-dev + - python3-setuptools + - qt5-default + - xorg-dev + homebrew: + packages: + - ccache +matrix: + include: + - os: linux + compiler: gcc-6 + env: + - MATRIX_EVAL="export CC=gcc-6 CXX=g++-6 CONFIG=Release PYTHON=python3" + - os: linux + compiler: gcc-7 + env: + - MATRIX_EVAL="export CC=gcc-7 CXX=g++-7 CONFIG=Release PYTHON=python3" + - os: linux # same config like above but with -DLIBIGL_USE_STATIC_LIBRARY=OFF to test static and header-only builds + compiler: gcc-7 + env: + - MATRIX_EVAL="export CC=gcc-7 CXX=g++-7 CONFIG=Release PYTHON=python3 CMAKE_EXTRA='-DLIBIGL_USE_STATIC_LIBRARY=OFF'" + - os: linux + compiler: gcc-7 + env: + - MATRIX_EVAL="export CC=gcc-7 CXX=g++-7 CONFIG=Release PYTHON=python3 CMAKE_EXTRA='-DLIBIGL_EIGEN_VERSION=3.3.7'" + - os: osx + osx_image: xcode10.2 + compiler: clang + env: + - MATRIX_EVAL="export CONFIG=Release PYTHON=python3 LIBIGL_NUM_THREADS=1" + - os: osx + osx_image: xcode10.2 + compiler: clang + env: + - MATRIX_EVAL="export CONFIG=Release PYTHON=python3 LIBIGL_NUM_THREADS=1 CMAKE_EXTRA='-DLIBIGL_USE_STATIC_LIBRARY=OFF'" + - os: osx + osx_image: xcode10.2 + compiler: clang + env: + - MATRIX_EVAL="export CONFIG=Release PYTHON=python3 LIBIGL_NUM_THREADS=1 CMAKE_EXTRA='-DLIBIGL_EIGEN_VERSION=3.3.7'"" + +install: +- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then export PATH="/usr/local/opt/ccache/libexec:$PATH"; fi +- eval "${MATRIX_EVAL}" +- ccache --max-size=5.0G +- ccache -V && ccache --show-stats && ccache --zero-stats + +script: +# Tutorials and tests +- mkdir build +- pushd build +- cmake ${CMAKE_EXTRA} + -DCMAKE_BUILD_TYPE=$CONFIG + -DLIBIGL_CHECK_UNDEFINED=ON + -DLIBIGL_WITH_CGAL=ON + ../ +- make -j8 +- ctest --verbose +- popd +- rm -rf build +- ccache --show-stats diff --git a/CMakeLists.txt b/CMakeLists.txt index b2488f1..efb4a75 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,8 +3,9 @@ project(fish_deformation) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/src/utils/voroffset/cmake) - - +if (APPLE) + set(CMAKE_PREFIX_PATH /usr/local/opt/qt/lib/cmake) +endif () ################################# @@ -110,8 +111,12 @@ file(GLOB CT_SRCS external/Segmentangling/ContourTree/*.cpp) set(CT_INCLUDE_DIRS external/Segmentangling/ContourTree) list(REMOVE_ITEM CT_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/external/Segmentangling/ContourTree/main.cpp") add_library(contourtree STATIC ${CT_SRCS}) -target_compile_options(contourtree PRIVATE "-fopenmp") -target_link_libraries(contourtree Qt5::Core Qt5::Widgets -fopenmp spdlog) +if (NOT APPLE) + target_compile_options(contourtree PRIVATE "-fopenmp") + target_link_libraries(contourtree Qt5::Core Qt5::Widgets -fopenmp spdlog) +else () + target_link_libraries(contourtree Qt5::Core Qt5::Widgets spdlog) +endif () target_include_directories(contourtree PUBLIC ${CT_INCLUDE_DIRS}) target_compile_definitions(contourtree PUBLIC CONTOUR_TREE_USE_SPDLOG) @@ -125,7 +130,7 @@ list(FILTER UTILS_HEADER EXCLUDE REGEX cgal*) add_library(utils STATIC ${UTILS_SRCS} ${UTILS_HEADER}) set_property(TARGET utils PROPERTY CXX_STANDARD 14) set_property(TARGET utils PROPERTY CXX_STANDARD_REQUIRED ON) -target_link_libraries(utils igl::core igl::opengl igl::cgal igl::triangle spdlog Qt5::Core Qt5::Widgets spdlog) +target_link_libraries(utils igl::core igl::opengl igl::cgal igl::triangle spdlog Qt5::Core Qt5::Widgets spdlog glfw ${GLFW_LIBRARIES}) target_include_directories(utils PUBLIC ${UTILS_INCLUDE_DIRS}) target_include_directories(utils SYSTEM PUBLIC "${PROJECT_SOURCE_DIR}/external/glm") diff --git a/src/main.cpp b/src/main.cpp index 62d0a54..24893b7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -8,6 +8,7 @@ #include "ui/endpoint_selection_plugin.h" #include "ui/bounding_polygon_plugin.h" #include "ui/state.h" +#include "utils/utils.h" #include "Logger.hpp" State _state; @@ -26,9 +27,11 @@ void log_opengl_debug(GLenum source, GLenum type, GLuint id, GLenum severity, if (id == 131185 || id == 7 || id == 131218) { return; } +#if !defined(__APPLE__) if (source == GL_DEBUG_SOURCE_APPLICATION) { return; } +#endif _state.logger->error( "OpenGL Debug msg: Source: {}, Type: {}, Id: {}, Severity: {}, Message: {}", source, type, id, severity, std::string(message) @@ -56,8 +59,7 @@ bool init(igl::opengl::glfw::Viewer& viewer) { ct_logger->set_level(CONTOURTREE_LOGGER_LEVEL); contourtree::Logger::setLogger(ct_logger); - glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); - glDebugMessageCallback(log_opengl_debug, NULL); + init_opengl_debug(log_opengl_debug); return false; } diff --git a/src/ui/bounding_polygon_plugin.cpp b/src/ui/bounding_polygon_plugin.cpp index 17c1cd9..4a95f94 100644 --- a/src/ui/bounding_polygon_plugin.cpp +++ b/src/ui/bounding_polygon_plugin.cpp @@ -59,9 +59,7 @@ void Bounding_Polygon_Menu::deinitialize() { } bool Bounding_Polygon_Menu::is_2d_widget_in_focus() { - double mouse_x, mouse_y; - glfwGetCursorPos(viewer->window, &mouse_x, &mouse_y); - glm::vec2 p(mouse_x, mouse_y); + glm::vec2 p(viewer->current_mouse_x, viewer->current_mouse_y); return widget_2d.is_point_in_widget(p) && !mouse_in_popup; } @@ -344,10 +342,15 @@ bool Bounding_Polygon_Menu::post_draw() { bool ret = FishUIViewerPlugin::post_draw(); int window_width, window_height; - glfwGetWindowSize(viewer->window, &window_width, &window_height); + get_window_size(viewer->window, &window_width, &window_height); +#ifdef __APPLE__ + glViewport(-window_width*view_hsplit, -(1.0+view_vsplit)*window_height/scaling_factor, + window_width, scaling_factor*(1.0-view_vsplit)*window_height); + widget_2d.position = glm::vec2(0.f, view_vsplit*window_height/(scaling_factor*scaling_factor)); +#else glViewport(0, 0, window_width, window_height); - widget_2d.position = glm::vec2(0.f, view_vsplit*window_height); +#endif widget_2d.size = glm::vec2(window_width*view_hsplit, (1.0-view_vsplit)*window_height); ret = widget_2d.post_draw(state.cage.keyframe_for_index(current_cut_index), is_2d_widget_in_focus()); @@ -360,10 +363,12 @@ bool Bounding_Polygon_Menu::post_draw() { ret = widget_3d.post_draw_curved(G4f(widget_3d_viewport), state.cage.keyframe_for_index(current_cut_index)); } + float window_scaling_factor; + get_scaling_factor(&window_scaling_factor); ImGui::SetNextWindowBgAlpha(0.5f); - float window_height_float = static_cast(window_height); - float window_width_float = static_cast(window_width); + float window_height_float = static_cast(window_height/window_scaling_factor); + float window_width_float = static_cast(window_width/window_scaling_factor); ImGui::SetNextWindowPos(ImVec2(0.f, (1.0-view_vsplit)*window_height_float), ImGuiSetCond_Always); ImGui::SetNextWindowSize(ImVec2(window_width_float, window_height_float*view_vsplit), ImGuiSetCond_Always); ImGui::Begin("Select Boundary", nullptr, @@ -401,6 +406,9 @@ bool Bounding_Polygon_Menu::post_draw() { ImGui::SameLine(); ImVec2 cursor_pos = ImGui::GetCursorScreenPos(); +#ifdef __APPLE__ + cursor_pos.x *= (1.0+keyframe_nudge_amount); +#endif ImGui::PushItemWidth(ImGui::GetWindowWidth() - 2.f*cursor_pos.x); if(ImGui::SliderFloat("", ¤t_cut_index, static_cast(state.cage.min_index()), @@ -493,16 +501,14 @@ bool Bounding_Polygon_Menu::post_draw() { } } if (show_edit_transfer_function) { - ImGui::SetNextWindowSize(ImVec2(window_width*view_vsplit, 0), ImGuiSetCond_FirstUseEver); + ImGui::SetNextWindowSize(ImVec2(window_width*view_vsplit/window_scaling_factor, 0), ImGuiSetCond_FirstUseEver); ImGui::Begin("Edit Transfer Function", &show_edit_transfer_function, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize); ImVec2 popup_pos = ImGui::GetWindowPos(); ImVec2 popup_size = ImGui::GetWindowSize(); tf_widget.post_draw(!show_save_popup /* active */); - double mouse_x, mouse_y; - glfwGetCursorPos(viewer->window, &mouse_x, &mouse_y); - bool in_window_x = (mouse_x >= popup_pos[0]) && (mouse_x <= (popup_pos[0] + popup_size[0])); - bool in_window_y = (mouse_y >= popup_pos[1]) && (mouse_y <= (popup_pos[1] + popup_size[1])); + bool in_window_x = (viewer->current_mouse_x >= popup_pos[0]) && (viewer->current_mouse_x <= (popup_pos[0] + popup_size[0])); + bool in_window_y = (viewer->current_mouse_y >= popup_pos[1]) && (viewer->current_mouse_y <= (popup_pos[1] + popup_size[1])); mouse_in_popup = (in_window_x && in_window_y); ImGui::Separator(); @@ -602,7 +608,7 @@ bool Bounding_Polygon_Menu::post_draw() { show_save_popup = true; } if (show_save_popup) { - post_draw_save(window_width); + post_draw_save(window_width/window_scaling_factor); } ImGui::End(); diff --git a/src/ui/bounding_polygon_plugin.h b/src/ui/bounding_polygon_plugin.h index cde27e8..daa9c68 100644 --- a/src/ui/bounding_polygon_plugin.h +++ b/src/ui/bounding_polygon_plugin.h @@ -44,6 +44,7 @@ class Bounding_Polygon_Menu : public FishUIViewerPlugin { void post_draw_transfer_function(); + float scaling_factor = 2.0; // Scaling factor for window sizes of the two menus float view_hsplit = 0.5; // Horizontal split for the two menus (normalized distance float view_vsplit = 0.2; // Vertical split for the bottom menu (normalized distance from the bottom) diff --git a/src/ui/bounding_widget_2d.cpp b/src/ui/bounding_widget_2d.cpp index 7bcc7cc..b55ea0d 100644 --- a/src/ui/bounding_widget_2d.cpp +++ b/src/ui/bounding_widget_2d.cpp @@ -2,6 +2,8 @@ #include "bounding_polygon_plugin.h" +#include "utils/utils.h" + #include #include #include @@ -143,15 +145,22 @@ struct BlitData { Bounding_Polygon_Widget::Bounding_Polygon_Widget(State& state) : state(state) {} glm::vec2 Bounding_Polygon_Widget::convert_position_mainwindow_to_keyframe(const glm::vec2& p) const { - glm::vec2 window_ll = position; - glm::vec2 window_ur = position + size; - +#ifdef __APPLE__ + const glm::vec2 window_ll = glm::vec2(position.x, macos_widget_scaling_factor*position.y); +#else + const glm::vec2 window_ll = position; +#endif + const glm::vec2 window_ur = window_ll + size; // Map mouse into [0, 1]^2 in the subwindow glm::vec2 normalized_mouse = (p - window_ll) / (window_ur - window_ll); // Convert to [-1, 1] glm::vec2 mapped_mouse = (normalized_mouse - glm::vec2(0.5f)) * 2.f; +#ifdef __APPLE__ + mapped_mouse.y *= mouse_coord_scaling_factor; +#endif + return mapped_mouse * view.zoom + view.offset; } @@ -163,11 +172,15 @@ glm::vec2 Bounding_Polygon_Widget::convert_position_keyframe_to_ndc(const glm::v bool Bounding_Polygon_Widget::is_point_in_widget(glm::ivec2 p) const { int window_width, window_height; - glfwGetWindowSize(viewer->window, &window_width, &window_height); + get_window_size(viewer->window, &window_width, &window_height); const glm::ivec2 p_tx(p.x, window_height - p.y); - const glm::ivec2 ll = position; - const glm::ivec2 ur = position + size; +#ifdef __APPLE__ + const glm::vec2 ll = glm::vec2(position.x, macos_widget_scaling_factor*position.y); +#else + const glm::vec2 ll = position; +#endif + const glm::vec2 ur = ll + size; return p_tx.x >= ll.x && p_tx.x <= ur.x && p_tx.y >= ll.y && p_tx.y <= ur.y; } @@ -189,7 +202,7 @@ void Bounding_Polygon_Widget::update_selection() { }; glm::ivec2 window_size; - glfwGetWindowSize(viewer->window, &window_size.x, &window_size.y); + get_window_size(viewer->window, &window_size.x, &window_size.y); glm::vec2 current_mouse = { viewer->current_mouse_x, window_size.y - viewer->current_mouse_y }; // In main window pixel space glm::vec2 kf_mouse = convert_position_mainwindow_to_keyframe(current_mouse); // In keyframe ndc @@ -297,7 +310,7 @@ void Bounding_Polygon_Widget::initialize(igl::opengl::glfw::Viewer* viewer, Boun bool Bounding_Polygon_Widget::mouse_move(int mouse_x, int mouse_y, bool in_focus) { glm::ivec2 window_size; - glfwGetWindowSize(viewer->window, &window_size.x, &window_size.y); + get_window_size(viewer->window, &window_size.x, &window_size.y); mouse_state.current_position = glm::ivec2(mouse_x, mouse_y); if (!in_focus) { //!is_point_in_widget(glm::ivec2(mouse_x, mouse_y)) || @@ -415,7 +428,7 @@ bool Bounding_Polygon_Widget::mouse_move(int mouse_x, int mouse_y, bool in_focus bool Bounding_Polygon_Widget::mouse_down(int button, int modifier, bool in_focus) { glm::ivec2 window_size; - glfwGetWindowSize(viewer->window, &window_size.x, &window_size.y); + get_window_size(viewer->window, &window_size.x, &window_size.y); bool left_mouse = glfwGetMouseButton(viewer->window, GLFW_MOUSE_BUTTON_1) == GLFW_PRESS; bool right_mouse = glfwGetMouseButton(viewer->window, GLFW_MOUSE_BUTTON_2) == GLFW_PRESS; @@ -563,7 +576,7 @@ bool Bounding_Polygon_Widget::post_draw(BoundingCage::KeyFrameIterator kf, bool // // Render the slice of the volume for this keyframe into an OpenGL texture // - glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, -1, "Render slice"); + push_gl_debug_group("Render slice"); { glUseProgram(plane.program); glBindVertexArray(empty_vao); @@ -600,13 +613,13 @@ bool Bounding_Polygon_Widget::post_draw(BoundingCage::KeyFrameIterator kf, bool glBindVertexArray(0); glUseProgram(0); } - glPopDebugGroup(); + pop_gl_debug_group(); // // Render the bounding-box, center, and axes into the same texture // - glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, -1, "Render polygon"); + push_gl_debug_group("Render polygon"); { const glm::vec2 centroid_2d = G2f(kf->centroid_2d()); const glm::vec2 r_axis = G2f(kf->right_rotated_2d()), u_axis = G2f(kf->up_rotated_2d()); @@ -633,7 +646,7 @@ bool Bounding_Polygon_Widget::post_draw(BoundingCage::KeyFrameIterator kf, bool // Render rotation handle if (mouse_state.is_rotate_modifier_down && in_focus) { glm::ivec2 window_size; - glfwGetWindowSize(viewer->window, &window_size.x, &window_size.y); + get_window_size(viewer->window, &window_size.x, &window_size.y); glm::vec2 current_mouse = { viewer->current_mouse_x, window_size.y - viewer->current_mouse_y }; glm::vec2 kf_mouse = convert_position_mainwindow_to_keyframe(current_mouse); @@ -647,7 +660,7 @@ bool Bounding_Polygon_Widget::post_draw(BoundingCage::KeyFrameIterator kf, bool } } } - glPopDebugGroup(); + pop_gl_debug_group(); // Restore the framebuffer and viewport glBindFramebuffer(GL_FRAMEBUFFER, 0); @@ -658,18 +671,18 @@ bool Bounding_Polygon_Widget::post_draw(BoundingCage::KeyFrameIterator kf, bool // // Blit the texture we just rendered to the screen // - glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, -1, "Texture Blit"); + push_gl_debug_group("Texture Blit"); { int width; int height; - glfwGetWindowSize(viewer->window, &width, &height); + get_window_size(viewer->window, &width, &height); glUseProgram(blit.program); glBindVertexArray(blit.vao); glBindBuffer(GL_ARRAY_BUFFER, blit.vbo); { - glm::vec2 size_ndc = size / glm::vec2(width, height) * 2.f; + glm::vec2 size_ndc = size / glm::vec2(width, height) * glm::vec2(2.f, 1.f); glm::vec2 pos_ndc = (position / glm::vec2(width, height) - glm::vec2(0.5)) * 2.f; BlitData box_ll = { @@ -709,7 +722,7 @@ bool Bounding_Polygon_Widget::post_draw(BoundingCage::KeyFrameIterator kf, bool glBindVertexArray(0); glUseProgram(0); } - glPopDebugGroup(); + pop_gl_debug_group(); glEnable(GL_DEPTH_TEST); return false; diff --git a/src/ui/bounding_widget_2d.h b/src/ui/bounding_widget_2d.h index 19fbcf6..99f667a 100644 --- a/src/ui/bounding_widget_2d.h +++ b/src/ui/bounding_widget_2d.h @@ -39,6 +39,24 @@ class Bounding_Polygon_Widget { float split_point_size = 7.f; float center_point_size = 12.f; float selected_center_point_size = 14.f; +#ifdef __APPLE__ + // Ensures full coverage of macOS 2D widget window over the entire area for selection and + // rendering covered by 2D widget viewer by scaling up the 2D widget size, which is many + // times smaller than usual since larger widget size values causes the widget view to zoom + // out into multiple slice views, ruining the widget display. The value of 4.0 was chosen + // as it was the minimum factor by which the diminished 2D widget size needed to be scaled + // up in order to achieve this effect. The y dimension of the 2D widget size was chosen to be + // scaled up due to its more flexible smaller value, dictating the size of the scaling factor. + float macos_widget_scaling_factor = 4.f; + // Ensures mouse coordinates on the y scale (vertical dimension) are properly normalized to + // synchronize with y coordinates of bounding box vertices for ease of box area selection. + // When used on MacOS, the y mouse coordinates of the cursor are out of sync with the actual + // y coordinates of points in relation to the bounds of the widget view. The value of 0.8 was + // chosen since that was the scaling factor needed to correct the imbalance, as the magnitudes + // of the incorrect mouse y coordinates were 1.25 larger than they should have been. With this + // correction factor, the bounding box selection process by the user works as expected. + float mouse_coord_scaling_factor = 0.8f; +#endif glm::vec4 rotation_handle_reference_color = glm::vec4(0.5f, 0.5f, 0.2f, 1.0f); glm::vec4 rotation_handle_color = glm::vec4(0.9f, 0.9f, 0.2f, 1.0f); diff --git a/src/ui/endpoint_selection_plugin.cpp b/src/ui/endpoint_selection_plugin.cpp index a4c1ebe..794c5e5 100644 --- a/src/ui/endpoint_selection_plugin.cpp +++ b/src/ui/endpoint_selection_plugin.cpp @@ -115,7 +115,7 @@ void EndPoint_Selection_Menu::initialize() { old_viewport = viewer->core.viewport; int window_width, window_height; - glfwGetWindowSize(viewer->window, &window_width, &window_height); + get_window_size(viewer->window, &window_width, &window_height); viewer->core.viewport = Eigen::RowVector4f(view_hsplit*window_width, 0, (1.0-view_hsplit)*window_width, window_height); if (state.dirty_flags.endpoints_dirty) { @@ -145,7 +145,7 @@ void EndPoint_Selection_Menu::deinitialize() { bool EndPoint_Selection_Menu::pre_draw() { int window_width, window_height; - glfwGetWindowSize(viewer->window, &window_width, &window_height); + get_window_size(viewer->window, &window_width, &window_height); viewer->core.viewport = Eigen::RowVector4f(view_hsplit*window_width, 0, (1.0-view_hsplit)*window_width, window_height); bool ret = FishUIViewerPlugin::pre_draw(); @@ -271,7 +271,7 @@ void EndPoint_Selection_Menu::debug_draw_intermediate_state() { bool EndPoint_Selection_Menu::post_draw() { bool ret = FishUIViewerPlugin::post_draw(); int window_width, window_height; - glfwGetWindowSize(viewer->window, &window_width, &window_height); + get_window_size(viewer->window, &window_width, &window_height); viewer->core.viewport = Eigen::RowVector4f(view_hsplit*window_width, 0, (1.0-view_hsplit)*window_width, window_height); int width; diff --git a/src/ui/fish_ui_viewer_plugin.cpp b/src/ui/fish_ui_viewer_plugin.cpp index 271161b..796bd5b 100644 --- a/src/ui/fish_ui_viewer_plugin.cpp +++ b/src/ui/fish_ui_viewer_plugin.cpp @@ -1,3 +1,4 @@ +#include "state.h" #include "fish_ui_viewer_plugin.h" #include diff --git a/src/ui/fish_ui_viewer_plugin.h b/src/ui/fish_ui_viewer_plugin.h index a6626fc..fbbf862 100644 --- a/src/ui/fish_ui_viewer_plugin.h +++ b/src/ui/fish_ui_viewer_plugin.h @@ -34,6 +34,8 @@ class FishUIViewerPlugin : public igl::opengl::glfw::ViewerPlugin { void draw_text(Eigen::Vector3d pos, Eigen::Vector3d normal, const std::string& text); + void window_size(GLFWwindow* handle, int* width, int* height); + float pixel_ratio(); float hidpi_scaling(); float menu_scaling() { return hidpi_scaling_ / pixel_ratio_; } diff --git a/src/ui/initial_file_selection_state.cpp b/src/ui/initial_file_selection_state.cpp index 5c95682..61161a1 100644 --- a/src/ui/initial_file_selection_state.cpp +++ b/src/ui/initial_file_selection_state.cpp @@ -113,8 +113,8 @@ bool Initial_File_Selection_Menu::post_draw() { ImGui::SameLine(); ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.2f); if (ImGui::Button("Select##FirstScan")) { - std::string first_scan = open_image_file_dialog(); - if (first_scan.size() > 0) { + // std::string first_scan = open_image_file_dialog(); + std::string first_scan = "/Users/michaelzhou/Desktop/PtapinBMP/Plaagiotremus_tapinosoma_9.9um_2k__rec_Tra0002.bmp"; if (first_scan.size() > 0) { strcpy(first_image_path_buf, first_scan.c_str()); _state.dirty_flags.file_loading_dirty = true; fix_path(first_image_path_buf); @@ -134,8 +134,8 @@ bool Initial_File_Selection_Menu::post_draw() { ImGui::SameLine(); ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.2f); if (ImGui::Button("Select##LastScan")) { - std::string last_scan = open_image_file_dialog(); - if (last_scan.size() > 0) { + // std::string last_scan = open_image_file_dialog(); + std::string last_scan = "/Users/michaelzhou/Desktop/PtapinBMP/Plaagiotremus_tapinosoma_9.9um_2k__rec_Tra1798.bmp"; if (last_scan.size() > 0) { strcpy(last_image_path_buf, last_scan.c_str()); _state.dirty_flags.file_loading_dirty = true; fix_path(last_image_path_buf); @@ -154,7 +154,8 @@ bool Initial_File_Selection_Menu::post_draw() { ImGui::SameLine(); ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.2f); if (ImGui::Button("Select##Outfolder")) { - std::string folder = open_folder_dialog(); + // std::string folder = open_folder_dialog(); + std::string folder = "/Users/michaelzhou/Desktop/FishScanResults"; if (folder.size() > 0) { strcpy(output_dir_path_buf, folder.c_str()); _state.dirty_flags.file_loading_dirty = true; diff --git a/src/ui/meshing_plugin.cpp b/src/ui/meshing_plugin.cpp index 3a7d05e..79a3c49 100644 --- a/src/ui/meshing_plugin.cpp +++ b/src/ui/meshing_plugin.cpp @@ -180,7 +180,7 @@ bool Meshing_Menu::post_draw() { if (is_meshing) { int width; int height; - glfwGetWindowSize(viewer->window, &width, &height); + get_window_size(viewer->window, &width, &height); ImGui::SetNextWindowPos(ImVec2(0.f, 0.f), ImGuiSetCond_Always); float w = static_cast(width); float h = static_cast(height); diff --git a/src/ui/selection_plugin.cpp b/src/ui/selection_plugin.cpp index 0e5df37..b991089 100644 --- a/src/ui/selection_plugin.cpp +++ b/src/ui/selection_plugin.cpp @@ -42,7 +42,7 @@ void Selection_Menu::initialize() { target_viewport_size = { -1.f, -1.f, -1.f, -1.f }; int window_width, window_height; - glfwGetWindowSize(viewer->window, &window_width, &window_height); + get_window_size(viewer->window, &window_width, &window_height); const int maxDim = glm::compMax(rendering_params.volume_dimensions); const float md = static_cast(maxDim); @@ -95,7 +95,7 @@ void Selection_Menu::initialize() { void Selection_Menu::draw_selection_volume() { int window_width, window_height; - glfwGetWindowSize(viewer->window, &window_width, &window_height); + get_window_size(viewer->window, &window_width, &window_height); Eigen::RowVector4f viewport(view_hsplit*window_width, 0, (1.0-view_hsplit)*window_width, window_height); glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); viewer->core.viewport = viewport; diff --git a/src/ui/state.cpp b/src/ui/state.cpp index 89bbde0..6538836 100644 --- a/src/ui/state.cpp +++ b/src/ui/state.cpp @@ -36,7 +36,6 @@ void State::LoadedVolume::preprocess_volume_texture(std::vector& byte_d ); } - void State::load_volume_data(State::LoadedVolume& volume, std::string prefix, bool load_topology) { std::string prefix_with_path = input_metadata.output_dir + "/" + prefix; @@ -65,7 +64,6 @@ void State::load_volume_data(State::LoadedVolume& volume, std::string prefix, bo } } - void State::LoadedVolume::load_gl_volume_texture(const std::vector& byte_data) { if (byte_data.size() == 0) { return; diff --git a/src/ui/state.h b/src/ui/state.h index 04aad97..80d3f19 100644 --- a/src/ui/state.h +++ b/src/ui/state.h @@ -160,8 +160,6 @@ struct State { std::vector> endpoint_pairs; } skeleton_estimation_parameters; - - void load_volume_data(LoadedVolume& volume, std::string prefix, bool load_topology); BoundingCage cage; diff --git a/src/utils/bounding_cage.h b/src/utils/bounding_cage.h index 454854a..d530a0e 100644 --- a/src/utils/bounding_cage.h +++ b/src/utils/bounding_cage.h @@ -457,6 +457,7 @@ class BoundingCage { bool bump(double amount) { this->_origin += amount * this->normal(); + return true; } /// Rotate the coordinate frame counter-clockwise about the normal axis diff --git a/src/utils/gl/point_line_rendering.cpp b/src/utils/gl/point_line_rendering.cpp index 25b2c49..9419804 100644 --- a/src/utils/gl/point_line_rendering.cpp +++ b/src/utils/gl/point_line_rendering.cpp @@ -1,5 +1,7 @@ #include "point_line_rendering.h" +#include "utils/utils.h" + #include #include @@ -68,7 +70,7 @@ void PointLineRenderer::destroy() { bool PointLineRenderer::update_polyline_3d(int polyline_id, GLfloat* vertices, GLfloat* colors, GLsizei num_vertices, PolylineStyle style) { - glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, -1, "update_polyline_3d"); + push_gl_debug_group("update_polyline_3d"); if (polyline_id >= _polylines.size() || polyline_id < 0) { return false; } @@ -93,12 +95,12 @@ bool PointLineRenderer::update_polyline_3d(int polyline_id, GLfloat* vertices, G glBindBuffer(GL_ARRAY_BUFFER, 0); - glPopDebugGroup(); + pop_gl_debug_group(); return true; } bool PointLineRenderer::update_polyline_3d(int polyline_id, GLfloat* vertices, glm::vec4 color, GLsizei num_vertices, PolylineStyle style) { - glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, -1, "update_polyline_3d"); + push_gl_debug_group("update_polyline_3d"); if (polyline_id >= _polylines.size() || polyline_id < 0) { return false; } @@ -123,13 +125,13 @@ bool PointLineRenderer::update_polyline_3d(int polyline_id, GLfloat* vertices, g glDisableVertexAttribArray(1); glBindVertexArray(0); - glPopDebugGroup(); + pop_gl_debug_group(); return true; } int PointLineRenderer::add_polyline_3d(GLfloat* vertices, GLfloat* colors, GLsizei num_vertices, PolylineStyle style) { - glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, -1, "add_polyline_3d"); + push_gl_debug_group("add_polyline_3d"); Polyline polyline; @@ -170,13 +172,13 @@ int PointLineRenderer::add_polyline_3d(GLfloat* vertices, GLfloat* colors, GLsiz _polylines.push_back(polyline); } - glPopDebugGroup(); + pop_gl_debug_group(); return polyline_id; } int PointLineRenderer::add_polyline_3d(GLfloat* vertices, glm::vec4 color, GLsizei num_vertices, PolylineStyle style) { - glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, -1, "add_polyline_3d"); + push_gl_debug_group("add_polyline_3d"); Polyline polyline; @@ -210,7 +212,7 @@ int PointLineRenderer::add_polyline_3d(GLfloat* vertices, glm::vec4 color, GLsiz _polylines.push_back(polyline); } - glPopDebugGroup(); + pop_gl_debug_group(); return polyline_id; } diff --git a/src/utils/gl/selection_renderer.cpp b/src/utils/gl/selection_renderer.cpp index 63a5192..640bf81 100644 --- a/src/utils/gl/selection_renderer.cpp +++ b/src/utils/gl/selection_renderer.cpp @@ -80,7 +80,7 @@ constexpr const char* VOLUME_PASS_VERTEX_SHADER = R"( // 7. Stop if either the ray is exhausted or the combined transparency is above an // early-ray termination threshold (0.99 in this case) constexpr const char* SELECTION_RENDERING_FRAG_SHADER = R"( -#version 450 +#version 410 // Keep in sync with main.cpp UI_State::Emphasis const int SELECTION_EMPHASIS_TYPE_NONE = 0; const int SELECTION_EMPHASIS_TYPE_ONSELECTION = 1; @@ -89,15 +89,8 @@ constexpr const char* SELECTION_RENDERING_FRAG_SHADER = R"( in vec2 uv; out vec4 out_color; - layout (std430, binding = 0) buffer Contour { - uint nFeatures; - uint values[]; - } contour; - - layout (std430, binding = 1) buffer SelectionList { - uint nFeatures; - uint features[]; - } selection; + uniform usamplerBuffer contour; + uniform usamplerBuffer selection; uniform sampler2D entry_texture; uniform sampler2D exit_texture; @@ -204,8 +197,8 @@ constexpr const char* SELECTION_RENDERING_FRAG_SHADER = R"( } bool is_feature_selected(uint feature) { - for (int i = 0; i < selection.nFeatures; ++i) { - if (selection.features[i] == feature) { + for (int i = 0; i < int(texelFetch(selection, 0).r); ++i) { + if (int(texelFetch(selection, i + 1).r) == feature) { return true; } } @@ -213,7 +206,7 @@ constexpr const char* SELECTION_RENDERING_FRAG_SHADER = R"( } float selection_factor(bool is_selected) { - if (selection.nFeatures == 0) { + if (int(texelFetch(selection, 0).r) == 0) { return 1.f; } @@ -261,13 +254,13 @@ constexpr const char* SELECTION_RENDERING_FRAG_SHADER = R"( vec3 sample_pos = entry + t * normalized_ray_direction; uint segVoxel = texture(index_volume, sample_pos).r; - uint feature = contour.values[segVoxel] + 1; + uint feature = texelFetch(contour, int(segVoxel) + 1).r + 1; if (feature != 0) { float value = texture(volume_texture, sample_pos).r; vec4 color; if (color_by_identifier == 1) { - const float normFeature = float(feature) / float(contour.nFeatures); + float normFeature = float(feature) / float(texelFetch(contour, 0).r); color.rgb = colormap(normFeature).rgb; color.a = selection_factor(is_feature_selected(feature)); } else { @@ -321,15 +314,11 @@ constexpr const char* SELECTION_RENDERING_FRAG_SHADER = R"( // 7. Stop if either the ray is exhausted or the combined transparency is above an // early-ray termination threshold (0.99 in this case) constexpr const char* SELECTION_PICKING_PASS_FRAG_SHADER = R"( -#version 450 +#version 410 in vec2 uv; out vec4 out_color; - layout (std430, binding = 0) buffer Contour { - uint nFeatures; - uint values[]; - } contour; - + uniform usamplerBuffer contour; uniform sampler2D entry_texture; uniform sampler2D exit_texture; @@ -362,8 +351,8 @@ constexpr const char* SELECTION_PICKING_PASS_FRAG_SHADER = R"( float t = 0.0; while (t < t_end) { vec3 sample_pos = entry + t * normalized_ray_direction; - const uint segVoxel = texture(index_volume, sample_pos).r; - const uint feature = contour.values[segVoxel]; + uint segVoxel = texture(index_volume, sample_pos).r; + uint feature = texelFetch(contour, int(segVoxel) + 1).r; if (feature != -1) { out_color = vec4(vec3(float(feature + 1)), 1.0); return; @@ -450,6 +439,11 @@ void SelectionRenderer::initialize(const glm::ivec2& viewport_size) igl::opengl::create_shader_program(VOLUME_PASS_VERTEX_SHADER, SELECTION_RENDERING_FRAG_SHADER, {}, _gl_state.volume_pass.program_object); + _gl_state.volume_pass.uniform_location.contour_texture = glGetUniformLocation( + _gl_state.volume_pass.program_object, "contour"); + _gl_state.volume_pass.uniform_location.selection_texture = glGetUniformLocation( + _gl_state.volume_pass.program_object, "selection"); + _gl_state.volume_pass.uniform_location.entry_texture = glGetUniformLocation( _gl_state.volume_pass.program_object, "entry_texture"); _gl_state.volume_pass.uniform_location.exit_texture = glGetUniformLocation( @@ -490,6 +484,10 @@ void SelectionRenderer::initialize(const glm::ivec2& viewport_size) igl::opengl::create_shader_program(VOLUME_PASS_VERTEX_SHADER, SELECTION_PICKING_PASS_FRAG_SHADER, {}, _gl_state.picking_pass.program_object); + _gl_state.picking_pass.uniform_location.contour_texture = + glGetUniformLocation( + _gl_state.picking_pass.program_object, "contour" + ); _gl_state.picking_pass.uniform_location.entry_texture = glGetUniformLocation( _gl_state.picking_pass.program_object, "entry_texture" @@ -574,9 +572,19 @@ void SelectionRenderer::initialize(const glm::ivec2& viewport_size) glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - // SSBO - glGenBuffers(1, &_gl_state.volume_pass.contour_information_ssbo); - glGenBuffers(1, &_gl_state.volume_pass.selection_list_ssbo); + // Initialize contour buffer texture + glGenTextures(1, &_gl_state.volume_pass.contour_texture); + glBindTexture(GL_TEXTURE_BUFFER, _gl_state.volume_pass.contour_texture); + + + // Initialize selection buffer texture + glGenTextures(1, &_gl_state.volume_pass.selection_texture); + glBindTexture(GL_TEXTURE_BUFFER, _gl_state.volume_pass.selection_texture); + + + // Contour and selection texture buffer objects + glGenBuffers(1, &_gl_state.volume_pass.contour_information_tbo); + glGenBuffers(1, &_gl_state.volume_pass.selection_list_tbo); } @@ -585,13 +593,15 @@ void SelectionRenderer::destroy() { std::vector buffers = { _gl_state.geometry_pass.vbo, _gl_state.geometry_pass.ibo, - _gl_state.volume_pass.contour_information_ssbo, - _gl_state.volume_pass.selection_list_ssbo }; + _gl_state.volume_pass.contour_information_tbo, + _gl_state.volume_pass.selection_list_tbo }; std::vector textures = { _gl_state.geometry_pass.entry_texture, _gl_state.geometry_pass.exit_texture, _gl_state.volume_pass.transfer_function_texture, - _gl_state.picking_pass.picking_texture, + _gl_state.volume_pass.selection_texture, + _gl_state.volume_pass.contour_texture, + _gl_state.picking_pass.picking_texture }; std::vector framebuffers = { _gl_state.geometry_pass.entry_framebuffer, @@ -610,7 +620,7 @@ void SelectionRenderer::destroy() { } void SelectionRenderer::set_transfer_function(const std::vector &tf) { - glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, -1, "Update Transfer Function"); + push_gl_debug_group("Update Transfer Function"); constexpr const int TRANSFER_FUNCTION_WIDTH = 512; @@ -684,12 +694,12 @@ void SelectionRenderer::set_transfer_function(const std::vector &tf) { GL_UNSIGNED_BYTE, transfer_function_data.data()); glBindTexture(GL_TEXTURE_1D, 0); - glPopDebugGroup(); + pop_gl_debug_group(); } void SelectionRenderer::geometry_pass(glm::mat4 model_matrix, glm::mat4 view_matrix, glm::mat4 proj_matrix) { - glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, -1, "Render Bounding Box"); + push_gl_debug_group("Render Bounding Box"); const glm::vec4 color_transparent(0.0); @@ -749,11 +759,11 @@ void SelectionRenderer::geometry_pass(glm::mat4 model_matrix, glm::mat4 view_mat glDisable(GL_CULL_FACE); } - glPopDebugGroup(); + pop_gl_debug_group(); } void SelectionRenderer::volume_pass(Parameters parameters, GLuint index_texture, GLuint volume_texture) { - glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, -1, "Render Volume"); + push_gl_debug_group("Render Volume"); // // Setup @@ -771,12 +781,10 @@ void SelectionRenderer::volume_pass(Parameters parameters, GLuint index_texture, // Contour Buffer - glBindBuffer(GL_SHADER_STORAGE_BUFFER, _gl_state.volume_pass.contour_information_ssbo); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, _gl_state.volume_pass.contour_information_ssbo); + glBindBuffer(GL_TEXTURE_BUFFER, _gl_state.volume_pass.contour_information_tbo); // Selection Buffer - glBindBuffer(GL_SHADER_STORAGE_BUFFER, _gl_state.volume_pass.selection_list_ssbo); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, _gl_state.volume_pass.selection_list_ssbo); + glBindBuffer(GL_TEXTURE_BUFFER, _gl_state.volume_pass.selection_list_tbo); glUniform1i(_gl_state.volume_pass.uniform_location.color_by_identifier, parameters.color_by_id ? 1 : 0); @@ -794,7 +802,7 @@ void SelectionRenderer::volume_pass(Parameters parameters, GLuint index_texture, // Exit points texture glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, _gl_state.geometry_pass.exit_texture); - glUniform1i(_gl_state.volume_pass.uniform_location.entry_texture, 1); + glUniform1i(_gl_state.volume_pass.uniform_location.exit_texture, 1); // Volume texture glActiveTexture(GL_TEXTURE2); @@ -810,6 +818,18 @@ void SelectionRenderer::volume_pass(Parameters parameters, GLuint index_texture, glActiveTexture(GL_TEXTURE4); glBindTexture(GL_TEXTURE_3D, index_texture); glUniform1i(_gl_state.volume_pass.uniform_location.index_volume, 4); + + // Contour buffer texture + glActiveTexture(GL_TEXTURE5); + glBindTexture(GL_TEXTURE_BUFFER, _gl_state.volume_pass.contour_texture); + glTexBuffer(GL_TEXTURE_BUFFER, GL_R32UI, _gl_state.volume_pass.contour_information_tbo); + glUniform1i(_gl_state.volume_pass.uniform_location.contour_texture, 5); + + // Selection buffer texture + glActiveTexture(GL_TEXTURE6); + glBindTexture(GL_TEXTURE_BUFFER, _gl_state.volume_pass.selection_texture); + glTexBuffer(GL_TEXTURE_BUFFER, GL_R32UI, _gl_state.volume_pass.selection_list_tbo); + glUniform1i(_gl_state.volume_pass.uniform_location.selection_texture, 6); glUniform1f(_gl_state.volume_pass.uniform_location.sampling_rate, parameters.sampling_rate); @@ -839,7 +859,7 @@ void SelectionRenderer::volume_pass(Parameters parameters, GLuint index_texture, glBindVertexArray(0); - glPopDebugGroup(); + pop_gl_debug_group(); } glm::vec3 SelectionRenderer::picking_pass(Parameters parameters, glm::ivec2 mouse_position, GLuint index_texture, GLuint volume_texture) { @@ -848,7 +868,7 @@ glm::vec3 SelectionRenderer::picking_pass(Parameters parameters, glm::ivec2 mous glBindTexture(GL_TEXTURE_3D, index_texture); glUniform1i(_gl_state.picking_pass.uniform_location.index_volume, 4); - glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, -1, "Pick Volume"); + push_gl_debug_group("Pick Volume"); glBindFramebuffer(GL_FRAMEBUFFER, _gl_state.picking_pass.picking_framebuffer); glClear(GL_COLOR_BUFFER_BIT); @@ -863,7 +883,7 @@ glm::vec3 SelectionRenderer::picking_pass(Parameters parameters, glm::ivec2 mous // Exit points texture glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, _gl_state.geometry_pass.exit_texture); - glUniform1i(_gl_state.picking_pass.uniform_location.entry_texture, 1); + glUniform1i(_gl_state.picking_pass.uniform_location.exit_texture, 1); // Volume texture glActiveTexture(GL_TEXTURE2); @@ -874,6 +894,12 @@ glm::vec3 SelectionRenderer::picking_pass(Parameters parameters, glm::ivec2 mous glActiveTexture(GL_TEXTURE3); glBindTexture(GL_TEXTURE_1D, _gl_state.volume_pass.transfer_function_texture); glUniform1i(_gl_state.picking_pass.uniform_location.transfer_function, 3); + + // Contour buffer texture + glActiveTexture(GL_TEXTURE5); + glBindTexture(GL_TEXTURE_BUFFER, _gl_state.volume_pass.contour_texture); + glTexBuffer(GL_TEXTURE_BUFFER, GL_R32UI, _gl_state.volume_pass.contour_information_tbo); + glUniform1i(_gl_state.picking_pass.uniform_location.contour_texture, 5); glUniform1f(_gl_state.picking_pass.uniform_location.sampling_rate, parameters.sampling_rate); @@ -898,7 +924,7 @@ glm::vec3 SelectionRenderer::picking_pass(Parameters parameters, glm::ivec2 mous glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindVertexArray(0); - glPopDebugGroup(); + pop_gl_debug_group(); return { colors[0], @@ -908,15 +934,15 @@ glm::vec3 SelectionRenderer::picking_pass(Parameters parameters, glm::ivec2 mous } void SelectionRenderer::set_contour_data(uint32_t* contour_features, size_t num_features) { - glBindBuffer(GL_SHADER_STORAGE_BUFFER, _gl_state.volume_pass.contour_information_ssbo); - glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(uint32_t) * num_features, contour_features, GL_DYNAMIC_DRAW); - glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); + glBindBuffer(GL_TEXTURE_BUFFER, _gl_state.volume_pass.contour_information_tbo); + glBufferData(GL_TEXTURE_BUFFER, sizeof(uint32_t) * num_features, contour_features, GL_DYNAMIC_DRAW); + glBindBuffer(GL_TEXTURE_BUFFER, 0); } void SelectionRenderer::set_selection_data(uint32_t* selection_list, size_t num_features) { - glBindBuffer(GL_SHADER_STORAGE_BUFFER, _gl_state.volume_pass.selection_list_ssbo); - glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(uint32_t) * num_features, selection_list, GL_DYNAMIC_DRAW); - glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); + glBindBuffer(GL_TEXTURE_BUFFER, _gl_state.volume_pass.selection_list_tbo); + glBufferData(GL_TEXTURE_BUFFER, sizeof(uint32_t) * num_features, selection_list, GL_DYNAMIC_DRAW); + glBindBuffer(GL_TEXTURE_BUFFER, 0); } void SelectionRenderer::resize_framebuffer(glm::ivec2 framebuffer_size) { diff --git a/src/utils/gl/selection_renderer.h b/src/utils/gl/selection_renderer.h index d801799..3e14f93 100644 --- a/src/utils/gl/selection_renderer.h +++ b/src/utils/gl/selection_renderer.h @@ -54,10 +54,16 @@ class SelectionRenderer { GLuint program_object = 0; GLuint transfer_function_texture; - GLuint selection_list_ssbo; - GLuint contour_information_ssbo; + GLuint selection_texture; + GLuint contour_texture; + + GLuint selection_list_tbo; + GLuint contour_information_tbo; struct { + GLint selection_texture = 0; + GLint contour_texture = 0; + GLint entry_texture = 0; GLint exit_texture = 0; GLint volume_texture = 0; @@ -87,6 +93,7 @@ class SelectionRenderer { GLuint picking_texture = 0; struct { + GLint contour_texture = 0; GLint entry_texture = 0; GLint exit_texture = 0; GLint volume_texture = 0; diff --git a/src/utils/gl/volume_exporter.cpp b/src/utils/gl/volume_exporter.cpp index c08d03f..463ef23 100644 --- a/src/utils/gl/volume_exporter.cpp +++ b/src/utils/gl/volume_exporter.cpp @@ -9,6 +9,8 @@ #include #include +#include "utils/utils.h" + constexpr const char* SLICE_VERTEX_SHADER = R"( #version 150 // Create two triangles that are filling the entire screen [-1, 1] @@ -68,7 +70,7 @@ void main() { )"; void VolumeExporter::write_texture_data_to_file(std::string filename) { - glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, -1, "Export"); + push_gl_debug_group("Export"); const size_t num_voxels = size_t(w)*size_t(h)*size_t(d); std::vector out_data; out_data.resize(num_voxels*4); @@ -82,7 +84,7 @@ void VolumeExporter::write_texture_data_to_file(std::string filename) { real_data.resize(num_voxels); for (size_t i = 0; i < num_voxels; i++) { real_data[i] = out_data[4*i]; } NRRD::save3D (filename, real_data.data(), this->w, this->h, this->d); - glPopDebugGroup(); + pop_gl_debug_group(); } void VolumeExporter::set_export_dims(GLsizei w, GLsizei h, GLsizei d) { @@ -103,7 +105,7 @@ void VolumeExporter::destroy() { } void VolumeExporter::init(GLsizei w, GLsizei h, GLsizei d) { - glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, -1, "Init Slice"); + push_gl_debug_group("Init Slice"); igl::opengl::create_shader_program(SLICE_VERTEX_SHADER, SLICE_FRAGMENT_SHADER, {}, slice.program); slice.ll_location = glGetUniformLocation(slice.program, "ll"); @@ -130,7 +132,7 @@ void VolumeExporter::init(GLsizei w, GLsizei h, GLsizei d) { glGenFramebuffers(1, &framebuffer); glBindTexture(GL_TEXTURE_3D, 0); - glPopDebugGroup(); + pop_gl_debug_group(); } @@ -140,7 +142,7 @@ void VolumeExporter::update(BoundingCage& cage, GLuint volume_texture, glm::ivec GLint old_viewport[4]; glGetIntegerv(GL_VIEWPORT, old_viewport); - glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, -1, "Export Slice"); + push_gl_debug_group("Export Slice"); glUseProgram(slice.program); glBindVertexArray(empty_vao); @@ -203,7 +205,7 @@ void VolumeExporter::update(BoundingCage& cage, GLuint volume_texture, glm::ivec glBindVertexArray(0); glUseProgram(0); glBindTexture(GL_TEXTURE_3D, 0); - glPopDebugGroup(); + pop_gl_debug_group(); glViewport(old_viewport[0], old_viewport[1], old_viewport[2], old_viewport[3]); } diff --git a/src/utils/gl/volume_renderer.cpp b/src/utils/gl/volume_renderer.cpp index 9806f55..b50a2f7 100644 --- a/src/utils/gl/volume_renderer.cpp +++ b/src/utils/gl/volume_renderer.cpp @@ -9,6 +9,7 @@ #include #include +#include "utils/utils.h" namespace { @@ -501,7 +502,7 @@ void VolumeRenderer::init(const glm::ivec2 &viewport_size, const char *fragment_ // Generate multipass buffers if enabled - glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, -1, "Init VolumeRenderer Multipass"); + push_gl_debug_group("Init VolumeRenderer Multipass"); for (int i = 0; i < 2; i++) { glGenTextures(1, &_gl_state.multipass.texture[i]); glBindTexture(GL_TEXTURE_2D, _gl_state.multipass.texture[i]); @@ -517,11 +518,11 @@ void VolumeRenderer::init(const glm::ivec2 &viewport_size, const char *fragment_ } glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindTexture(GL_TEXTURE_2D, 0); - glPopDebugGroup(); + pop_gl_debug_group(); } void VolumeRenderer::ray_endpoint_pass(const glm::mat4& model_matrix, const glm::mat4& view_matrix, const glm::mat4& proj_matrix) { - glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, -1, "Render Bounding Box"); + push_gl_debug_group("Render Bounding Box"); { const glm::vec4 color_transparent(0.0); @@ -578,11 +579,11 @@ void VolumeRenderer::ray_endpoint_pass(const glm::mat4& model_matrix, const glm: glDisable(GL_CULL_FACE); } } - glPopDebugGroup(); + pop_gl_debug_group(); } void VolumeRenderer::volume_pass(const glm::vec3& light_position, const glm::ivec3& volume_dims, GLuint volume_tex, GLuint multipass_tex) { - glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, -1, "Render Volume TEST"); + push_gl_debug_group("Render Volume TEST"); // // Setup @@ -640,7 +641,7 @@ void VolumeRenderer::volume_pass(const glm::vec3& light_position, const glm::ive glBindVertexArray(0); - glPopDebugGroup(); + pop_gl_debug_group(); } void VolumeRenderer::begin(const glm::ivec3& volume_dims, GLuint tex) { @@ -682,7 +683,7 @@ void VolumeRenderer::render_pass( const int current_buf = _current_multipass_buf; const int last_buf = (_current_multipass_buf+1) % 2; - glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, -1, "Multipass render"); + push_gl_debug_group("Multipass render"); GLint old_viewport[4]; glGetIntegerv(GL_VIEWPORT, old_viewport); @@ -709,7 +710,7 @@ void VolumeRenderer::render_pass( volume_pass(light_position, _current_volume_dims, volume_tex, _gl_state.multipass.texture[last_buf]); glViewport(old_viewport[0], old_viewport[1], old_viewport[2], old_viewport[3]); - glPopDebugGroup(); + pop_gl_debug_group(); } diff --git a/src/utils/utils.cpp b/src/utils/utils.cpp index 2a7e8b1..19786c0 100644 --- a/src/utils/utils.cpp +++ b/src/utils/utils.cpp @@ -189,6 +189,41 @@ bool load_rawfile(const std::string& rawfilename, const Eigen::RowVector3i& dims return true; } +void init_opengl_debug(GLDEBUGPROC callback) { +#if !defined(__APPLE__) + glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); + glDebugMessageCallback(callback, NULL); +#endif +} + +void push_gl_debug_group(const char* message) { +#if !defined(__APPLE__) + glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, -1, message); +#endif +} + +void pop_gl_debug_group() { +#if !defined(__APPLE__) + glPopDebugGroup(); +#endif +} + +void get_window_size(GLFWwindow* handle, int* width, int* height) { + float window_scale; + get_scaling_factor(&window_scale); + glfwGetWindowSize(handle, width, height); + // Provides proper scaling for window dimensions on macOS + *width *= window_scale, *height *= window_scale; +} + +void get_scaling_factor(float* scaling) { + // int count; + // GLFWmonitor** monitors = glfwGetMonitors(&count); + // glfwGetMonitorContentScale(monitors[1], scaling, NULL); + GLFWmonitor* primary = glfwGetPrimaryMonitor(); + glfwGetMonitorContentScale(primary, scaling, NULL); +} + void edge_endpoints(const Eigen::MatrixXd& V, const Eigen::MatrixXi& F, Eigen::MatrixXd& V1, diff --git a/src/utils/utils.h b/src/utils/utils.h index d959aad..79d6358 100644 --- a/src/utils/utils.h +++ b/src/utils/utils.h @@ -6,6 +6,8 @@ #include #include #include +#include +#include #ifdef _MSC_VER @@ -42,6 +44,16 @@ bool load_rawfile(const std::string& rawfilename, const Eigen::RowVector3i& dims bool load_rawfile(const std::string& rawfilename, const Eigen::RowVector3i& dims, std::vector &out, std::shared_ptr logger); +void init_opengl_debug(GLDEBUGPROC callback); + +void push_gl_debug_group(const char* message); + +void pop_gl_debug_group(); + +void get_window_size(GLFWwindow* handle, int* width, int* height); + +void get_scaling_factor(float* scaling); + void edge_endpoints(const Eigen::MatrixXd& V, const Eigen::MatrixXi& F, Eigen::MatrixXd& V1,