diff --git a/include/igl/opengl/ViewerCore.cpp b/include/igl/opengl/ViewerCore.cpp index 2697c2a63..24b2fb268 100644 --- a/include/igl/opengl/ViewerCore.cpp +++ b/include/igl/opengl/ViewerCore.cpp @@ -180,16 +180,16 @@ IGL_INLINE void igl::opengl::ViewerCore::draw( if (data.V.rows()>0) { // Render fill - if (data.show_faces) + if (is_set(data.show_faces)) { // Texture - glUniform1f(texture_factori, data.show_texture ? 1.0f : 0.0f); + glUniform1f(texture_factori, is_set(data.show_texture) ? 1.0f : 0.0f); data.meshgl.draw_mesh(true); glUniform1f(texture_factori, 0.0f); } // Render wireframe - if (data.show_lines) + if (is_set(data.show_lines)) { glLineWidth(data.line_width); glUniform4f(fixed_colori, @@ -201,9 +201,9 @@ IGL_INLINE void igl::opengl::ViewerCore::draw( } } - if (data.show_overlay) + if (is_set(data.show_overlay)) { - if (data.show_overlay_depth) + if (is_set(data.show_overlay_depth)) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST); @@ -352,6 +352,28 @@ IGL_INLINE void igl::opengl::ViewerCore::set_rotation_type( } } +IGL_INLINE void igl::opengl::ViewerCore::set(unsigned int &property_mask, bool value) const +{ + if (!value) + unset(property_mask); + else + property_mask |= id; +} + +IGL_INLINE void igl::opengl::ViewerCore::unset(unsigned int &property_mask) const +{ + property_mask &= ~id; +} + +IGL_INLINE void igl::opengl::ViewerCore::toggle(unsigned int &property_mask) const +{ + property_mask ^= id; +} + +IGL_INLINE bool igl::opengl::ViewerCore::is_set(unsigned int property_mask) const +{ + return (property_mask & id); +} IGL_INLINE igl::opengl::ViewerCore::ViewerCore() { diff --git a/include/igl/opengl/ViewerCore.h b/include/igl/opengl/ViewerCore.h index 67accb2f8..16578274a 100644 --- a/include/igl/opengl/ViewerCore.h +++ b/include/igl/opengl/ViewerCore.h @@ -37,7 +37,6 @@ public: // Serialization code IGL_INLINE void InitSerialization(); - // ------------------- Camera control functions // Adjust the view to see the entire model @@ -91,10 +90,24 @@ public: }; IGL_INLINE void set_rotation_type(const RotationType & value); + // ------------------- Option helpers + + // Set a ViewerData visualization option for this viewport + IGL_INLINE void set(unsigned int &property_mask, bool value = true) const; + + // Unset a ViewerData visualization option for this viewport + IGL_INLINE void unset(unsigned int &property_mask) const; + + // Toggle a ViewerData visualization option for this viewport + IGL_INLINE void toggle(unsigned int &property_mask) const; + + // Check whether a ViewerData visualization option is set for this viewport + IGL_INLINE bool is_set(unsigned int property_mask) const; + // ------------------- Properties // Unique identifier - int id; + unsigned int id = 1u; // Colors Eigen::Vector4f background_color; diff --git a/include/igl/opengl/ViewerData.cpp b/include/igl/opengl/ViewerData.cpp index 86b5374ba..285500461 100644 --- a/include/igl/opengl/ViewerData.cpp +++ b/include/igl/opengl/ViewerData.cpp @@ -7,6 +7,7 @@ // obtain one at http://mozilla.org/MPL/2.0/. #include "ViewerData.h" +#include "ViewerCore.h" #include "../per_face_normals.h" #include "../material_colors.h" @@ -121,6 +122,15 @@ IGL_INLINE void igl::opengl::ViewerData::set_visible(bool value, unsigned int co is_visible &= ~core_id; } +IGL_INLINE void igl::opengl::ViewerData::copy_options(const ViewerCore &from, const ViewerCore &to) +{ + to.set(show_overlay , from.is_set(show_overlay) ); + to.set(show_overlay_depth, from.is_set(show_overlay_depth)); + to.set(show_texture , from.is_set(show_texture) ); + to.set(show_faces , from.is_set(show_faces) ); + to.set(show_lines , from.is_set(show_lines) ); +} + IGL_INLINE void igl::opengl::ViewerData::set_colors(const Eigen::MatrixXd &C) { using namespace std; @@ -222,7 +232,6 @@ IGL_INLINE void igl::opengl::ViewerData::set_uv(const Eigen::MatrixXd& UV_V, con dirty |= MeshGL::DIRTY_UV; } - IGL_INLINE void igl::opengl::ViewerData::set_texture( const Eigen::Matrix& R, const Eigen::Matrix& G, diff --git a/include/igl/opengl/ViewerData.h b/include/igl/opengl/ViewerData.h index 9395a850c..937844347 100644 --- a/include/igl/opengl/ViewerData.h +++ b/include/igl/opengl/ViewerData.h @@ -34,6 +34,9 @@ namespace igl namespace opengl { +// Forward declaration +class ViewerCore; + class ViewerData { public: @@ -135,6 +138,9 @@ public: // Generates a default grid texture IGL_INLINE void grid_texture(); + // Copy visualization options from one viewport to another + IGL_INLINE void copy_options(const ViewerCore &from, const ViewerCore &to); + Eigen::MatrixXd V; // Vertices of the current mesh (#V x 3) Eigen::MatrixXi F; // Faces of the mesh (#F x 3) @@ -186,17 +192,21 @@ public: // Enable per-face or per-vertex properties bool face_based; - // Visualization options - unsigned int is_visible; - bool show_overlay; - bool show_overlay_depth; - bool show_texture; - bool show_faces; - bool show_lines; - bool show_vertid; - bool show_faceid; + // Invert mesh normals bool invert_normals; + // Visualization options + // Each option is a binary mask specifying on which viewport each option is set. + // When using a single viewport, standard boolean can still be used for simplicity. + unsigned int is_visible; + unsigned int show_overlay; + unsigned int show_overlay_depth; + unsigned int show_texture; + unsigned int show_faces; + unsigned int show_lines; + bool show_vertid; // shared across viewports for now + bool show_faceid; // shared across viewports for now + // Point size / line width float point_size; float line_width; diff --git a/include/igl/opengl/glfw/Viewer.cpp b/include/igl/opengl/glfw/Viewer.cpp index e647f2ac3..da75e54f3 100644 --- a/include/igl/opengl/glfw/Viewer.cpp +++ b/include/igl/opengl/glfw/Viewer.cpp @@ -523,7 +523,7 @@ namespace glfw case 'L': case 'l': { - data().show_lines = !data().show_lines; + core().toggle(data().show_lines); return true; } case 'O': @@ -535,7 +535,7 @@ namespace glfw case 'T': case 't': { - data().show_faces = !data().show_faces; + core().toggle(data().show_faces); return true; } case 'Z': @@ -560,6 +560,13 @@ namespace glfw (selected_data_index + data_list.size() + (unicode_key=='>'?1:-1))%data_list.size(); return true; } + case '{': + case '}': + { + selected_core_index = + (selected_core_index + core_list.size() + (unicode_key=='}'?1:-1))%core_list.size(); + return true; + } case ';': data().show_vertid = !data().show_vertid; return true; @@ -1070,8 +1077,14 @@ namespace glfw core_list.back().id = next_core_id; next_core_id <<= 1; if (!append_empty) + { for (auto &data : data_list) + { data.set_visible(true, core_list.back().id); + data.copy_options(core(), core_list.back()); + } + } + selected_core_index = core_list.size()-1; return core_list.back().id; } diff --git a/include/igl/opengl/glfw/imgui/ImGuiHelpers.h b/include/igl/opengl/glfw/imgui/ImGuiHelpers.h index 4762b9ff1..1d3e3bcca 100644 --- a/include/igl/opengl/glfw/imgui/ImGuiHelpers.h +++ b/include/igl/opengl/glfw/imgui/ImGuiHelpers.h @@ -101,6 +101,15 @@ inline bool SliderScalar(const char *label, T* value, T min = 0, T max = 0, cons return SliderScalar(label, ImGuiDataTypeTraits::value, value, &min, &max, fmt); } +template +inline bool Checkbox(const char* label, Getter get, Setter set) +{ + bool value = get(); + bool ret = ImGui::Checkbox(label, &value); + set(value); + return ret; +} + } // namespace ImGui #endif // IGL_OPENGL_GLFW_IMGUI_IMGUIHELPERS_H diff --git a/include/igl/opengl/glfw/imgui/ImGuiMenu.cpp b/include/igl/opengl/glfw/imgui/ImGuiMenu.cpp index caad3a3bf..039cf125c 100644 --- a/include/igl/opengl/glfw/imgui/ImGuiMenu.cpp +++ b/include/igl/opengl/glfw/imgui/ImGuiMenu.cpp @@ -7,6 +7,7 @@ // obtain one at http://mozilla.org/MPL/2.0/. //////////////////////////////////////////////////////////////////////////////// #include "ImGuiMenu.h" +#include "ImGuiHelpers.h" #include #include #include @@ -261,6 +262,15 @@ IGL_INLINE void ImGuiMenu::draw_viewer_menu() ImGui::PopItemWidth(); } + // Helper for setting viewport specific mesh options + auto make_checkbox = [&](const char *label, unsigned int &option) + { + return ImGui::Checkbox(label, + [&]() { return viewer->core().is_set(option); }, + [&](bool value) { return viewer->core().set(option, value); } + ); + }; + // Draw options if (ImGui::CollapsingHeader("Draw Options", ImGuiTreeNodeFlags_DefaultOpen)) { @@ -268,13 +278,13 @@ IGL_INLINE void ImGuiMenu::draw_viewer_menu() { viewer->data().dirty = MeshGL::DIRTY_ALL; } - ImGui::Checkbox("Show texture", &(viewer->data().show_texture)); + make_checkbox("Show texture", viewer->data().show_texture); if (ImGui::Checkbox("Invert normals", &(viewer->data().invert_normals))) { viewer->data().dirty |= igl::opengl::MeshGL::DIRTY_NORMAL; } - ImGui::Checkbox("Show overlay", &(viewer->data().show_overlay)); - ImGui::Checkbox("Show overlay depth", &(viewer->data().show_overlay_depth)); + make_checkbox("Show overlay", viewer->data().show_overlay); + make_checkbox("Show overlay depth", viewer->data().show_overlay_depth); ImGui::ColorEdit4("Background", viewer->core().background_color.data(), ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_PickerHueWheel); ImGui::ColorEdit4("Line color", viewer->data().line_color.data(), @@ -287,8 +297,8 @@ IGL_INLINE void ImGuiMenu::draw_viewer_menu() // Overlays if (ImGui::CollapsingHeader("Overlays", ImGuiTreeNodeFlags_DefaultOpen)) { - ImGui::Checkbox("Wireframe", &(viewer->data().show_lines)); - ImGui::Checkbox("Fill", &(viewer->data().show_faces)); + make_checkbox("Wireframe", viewer->data().show_lines); + make_checkbox("Fill", viewer->data().show_faces); ImGui::Checkbox("Show vertex labels", &(viewer->data().show_vertid)); ImGui::Checkbox("Show faces labels", &(viewer->data().show_faceid)); } diff --git a/tutorial/106_ViewerMenu/main.cpp b/tutorial/106_ViewerMenu/main.cpp index dd2dce711..09f32722b 100755 --- a/tutorial/106_ViewerMenu/main.cpp +++ b/tutorial/106_ViewerMenu/main.cpp @@ -86,7 +86,6 @@ int main(int argc, char *argv[]) ImGuiWindowFlags_NoSavedSettings ); - // Expose the same variable directly ... ImGui::PushItemWidth(-80); ImGui::DragScalar("double", ImGuiDataType_Double, &doubleVariable, 0.1, 0, 0, "%.4f"); diff --git a/tutorial/108_MultipleViews/main.cpp b/tutorial/108_MultipleViews/main.cpp index 8be687cdc..f41942fbb 100644 --- a/tutorial/108_MultipleViews/main.cpp +++ b/tutorial/108_MultipleViews/main.cpp @@ -19,7 +19,7 @@ int main(int argc, char * argv[]) viewer.core().viewport = Eigen::Vector4f(0, 0, 640, 800); left_view = viewer.core_list[0].id; right_view = viewer.append_core(Eigen::Vector4f(640, 0, 640, 800)); - return true; + return false; }; viewer.callback_key_down = [&](igl::opengl::glfw::Viewer &, unsigned int key, int mod)