Jelajahi Sumber

ImGuizmo Integration (#1568)

* First working version to automatically clone ImGuizmo into libigl

* Corresponding changes to cmake files

* Moved contents of slicing plugin and menu extra to new file ImGuizmoMenu in imgui directory of igl

* Moved slicing plug into main, and ImGuizmo::EditTransform into ImGuizmoMenu which resides in igl

* Temporary hid Local and World options because they don't do anything and refactored main for tutorial 109 for clarity with some documentation

* Got orthogonal projection to render ImGuizmo normally

* Removed unecessary changes

* Removed snap parameter from ImGuizmo menu

* Added a cmake configuration for ImGuizmo

* Include imgui library in building ImGuizmo target

* Added a workflow

* Added this branch to workflow

* Update linux packages

* Explicitly include imgui header for imguizmo

* Just copy in relevant imguizmo files for now as opposed to through cmake since ImGuizmo repo does not have its own CMake file

* Conditional include to prevent mac build from failing

* Revert files for debugging cmake build

* Added build target for ImGuizmo

* Expose Imgui lib to ImGuizmo with PUBLIC interface

* Refactor build

* Get older SHA1 commit to avoid break on macOS

* Change imguizmo menu namespace

* Cleaning up + fix window border size issue.

Co-authored-by: Jérémie Dumas <[email protected]>
michelle 5 tahun lalu
induk
melakukan
98a1a31641

+ 9 - 0
cmake/LibiglDownloadExternal.cmake

@@ -112,6 +112,15 @@ function(igl_download_imgui)
 	)
 endfunction()
 
+## ImGuizmo
+function(igl_download_imguizmo)
+	igl_download_project(imguizmo
+		GIT_REPOSITORY https://github.com/CedricGuillemet/ImGuizmo.git
+		GIT_TAG        a23567269f6617342bcc112394bdad937b54b2d7
+		${LIBIGL_BRANCH_OPTIONS}
+	)
+endfunction()
+
 ## pybind11
 function(igl_download_pybind11)
 	igl_download_project(pybind11

+ 6 - 1
cmake/libigl.cmake

@@ -398,7 +398,12 @@ if(LIBIGL_WITH_OPENGL_GLFW_IMGUI)
       igl_download_imgui()
       add_subdirectory(${LIBIGL_EXTERNAL}/libigl-imgui imgui)
     endif()
-    target_link_libraries(igl_opengl_glfw_imgui ${IGL_SCOPE} igl_opengl_glfw imgui)
+    if(NOT TARGET imguizmo)
+      igl_download_imguizmo()
+      add_library(imguizmo ${LIBIGL_EXTERNAL}/imguizmo/ImGuizmo.cpp ${LIBIGL_EXTERNAL}/imguizmo/ImGuizmo.h)
+      target_link_libraries(imguizmo PUBLIC imgui)
+    endif()
+    target_link_libraries(igl_opengl_glfw_imgui ${IGL_SCOPE} igl_opengl_glfw imgui imguizmo)
   endif()
 endif()
 

+ 55 - 0
include/igl/opengl/glfw/imgui/ImGuizmo.h

@@ -0,0 +1,55 @@
+#pragma once
+////////////////////////////////////////////////////////////////////////////////
+#include <imgui/imgui.h>
+#include <imgui/imgui_internal.h>
+#include <imguizmo/ImGuizmo.h>
+#include <Eigen/Dense>
+#include <vector>
+////////////////////////////////////////////////////////////////////////////////
+
+namespace igl
+{
+namespace opengl
+{
+namespace glfw
+{
+namespace imgui
+{
+
+void EditTransform(const float *cameraView, const float *cameraProjection, float* matrix, bool isOrthographic)
+{
+	static ImGuizmo::OPERATION mCurrentGizmoOperation(ImGuizmo::ROTATE);
+	static ImGuizmo::MODE mCurrentGizmoMode(ImGuizmo::WORLD);
+
+	if (ImGui::IsKeyPressed(90))
+		mCurrentGizmoOperation = ImGuizmo::TRANSLATE;
+	if (ImGui::IsKeyPressed(69))
+		mCurrentGizmoOperation = ImGuizmo::ROTATE;
+	if (ImGui::IsKeyPressed(82)) // r Key
+		mCurrentGizmoOperation = ImGuizmo::SCALE;
+
+	if (ImGui::RadioButton("Translate", mCurrentGizmoOperation == ImGuizmo::TRANSLATE))
+		mCurrentGizmoOperation = ImGuizmo::TRANSLATE;
+	ImGui::SameLine();
+	if (ImGui::RadioButton("Rotate", mCurrentGizmoOperation == ImGuizmo::ROTATE))
+		mCurrentGizmoOperation = ImGuizmo::ROTATE;
+	ImGui::SameLine();
+	if (ImGui::RadioButton("Scale", mCurrentGizmoOperation == ImGuizmo::SCALE))
+		mCurrentGizmoOperation = ImGuizmo::SCALE;
+
+	float matrixTranslation[3], matrixRotation[3], matrixScale[3];
+	ImGuizmo::DecomposeMatrixToComponents(matrix, matrixTranslation, matrixRotation, matrixScale);
+	ImGui::InputFloat3("Tr", matrixTranslation, 3);
+	ImGui::InputFloat3("Rt", matrixRotation, 3);
+	ImGui::InputFloat3("Sc", matrixScale, 3);
+	ImGuizmo::RecomposeMatrixFromComponents(matrixTranslation, matrixRotation, matrixScale, matrix);
+
+	ImGuiIO& io = ImGui::GetIO();
+	ImGuizmo::SetRect(0, 0, io.DisplaySize.x, io.DisplaySize.y);
+	ImGuizmo::Manipulate(cameraView, cameraProjection, mCurrentGizmoOperation, mCurrentGizmoMode, matrix, NULL, NULL);
+}
+
+} // end namespace
+} // end namespace
+} // end namespace
+} // end namespace

+ 6 - 0
tutorial/109_ImGuizmo/CMakeLists.txt

@@ -0,0 +1,6 @@
+get_filename_component(PROJECT_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME)
+project(${PROJECT_NAME})
+
+set(IMGUIZMO_PATH ${LIBIGL_SOURCE_DIR}/igl/opengl/glfw/imgui/imguizmo)
+add_executable(${PROJECT_NAME}_bin main.cpp)
+target_link_libraries( ${PROJECT_NAME}_bin igl::core igl::opengl igl::opengl_glfw igl::opengl_glfw_imgui tutorials)

+ 102 - 0
tutorial/109_ImGuizmo/main.cpp

@@ -0,0 +1,102 @@
+#include <igl/opengl/glfw/Viewer.h>
+#include <igl/opengl/glfw/imgui/ImGuiMenu.h>
+#include <igl/opengl/glfw/imgui/ImGuizmo.h>
+#include <imgui_impl_glfw.h>
+#include <imgui_impl_opengl3.h>
+#include <GLFW/glfw3.h>
+#include <imgui/imgui.h>
+#include "tutorial_shared_path.h"
+
+class SlicingPlugin : public igl::opengl::glfw::imgui::ImGuiMenu
+{
+  igl::opengl::ViewerData data;
+
+  const Eigen::MatrixXd OV = (Eigen::MatrixXd(4, 3) <<
+    -0.5, -0.5, 0.0,
+    -0.5,  0.5, 0.0,
+    0.5,  0.5, 0.0,
+    0.5, -0.5, 0.0).finished();
+
+  const Eigen::MatrixXi OF = (Eigen::MatrixXi(2, 3) <<
+    0, 2, 1,
+    0, 3, 2).finished();
+
+  virtual void init(igl::opengl::glfw::Viewer *_viewer) override {
+    ImGuiMenu::init(_viewer);
+
+    // Load slicing plane into viewer (a square mesh)
+    data.set_mesh(SlicingPlugin::OV, SlicingPlugin::OF);
+    data.set_face_based(true);
+    data.set_colors(Eigen::RowVector4d(224, 86, 253, 128)/255.0);
+    data.show_lines = false;
+  }
+
+  virtual bool pre_draw() override {
+    ImGuiMenu::pre_draw();
+    ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0);
+    ImGuizmo::BeginFrame();
+    ImGui::PopStyleVar();
+    return false;
+  }
+
+  virtual bool post_draw() override {
+    viewer->core().draw(data);
+    ImGuiMenu::post_draw();
+    return false;
+  }
+
+  virtual void draw_custom_window() override {
+    float menu_width = 180.f * menu_scaling();
+    ImGui::SetNextWindowPos(ImVec2(menu_width, 0.0f), ImGuiCond_FirstUseEver);
+    ImGui::SetNextWindowSize(ImVec2(0.0f, 0.0f), ImGuiCond_FirstUseEver);
+    ImGui::SetNextWindowSizeConstraints(ImVec2(1.5f * menu_width, -1.0f), ImVec2(1.5f * menu_width, -1.0f));
+    bool _guizmo_menu_visible = true;
+    ImGui::Begin(
+      "ImGuizmo Tools", &_guizmo_menu_visible,
+      ImGuiWindowFlags_NoSavedSettings
+      | ImGuiWindowFlags_AlwaysAutoResize
+    );
+
+    draw_imguizmo_menu();
+
+    ImGui::End();
+  }
+
+  virtual void draw_imguizmo_menu() {
+    static Eigen::Matrix4f matrix = Eigen::Matrix4f::Identity();
+    Eigen::Affine3f rescale = Eigen::Scaling(0.5f * viewer->core().camera_base_zoom)
+      * Eigen::Translation3f(viewer->core().camera_base_translation);
+    Eigen::Affine3f view = Eigen::Affine3f( viewer->core().view * 1./viewer->core().camera_zoom ) * rescale.inverse();
+    Eigen::Matrix4f proj = viewer->core().proj;
+    if(viewer->core().orthographic)
+    {
+      view(2,3) -= 50; // Adjust depth for view transform
+    }
+
+    igl::opengl::glfw::imgui::EditTransform(view.matrix().data(), proj.data(), matrix.data(), viewer->core().orthographic);
+
+    // Transform the slicing plane according to
+    // ImGuizmo tool manipulations in the viewer
+    Eigen::Affine3f model = Eigen::Affine3f(matrix) * rescale.inverse();
+    Eigen::MatrixXd V = (SlicingPlugin::OV.rowwise().homogeneous()
+      * model.matrix().cast<double>().transpose()).rowwise().hnormalized();
+
+    if (data.V.rows() == V.rows())
+      data.set_vertices(V);
+  }
+
+};
+
+int main(int argc, char *argv[])
+{
+  // Plot the mesh
+  igl::opengl::glfw::Viewer viewer;
+  std::string filename(TUTORIAL_SHARED_PATH "/cow.off");
+  viewer.load_mesh_from_file(filename);
+
+  // Custom menu
+  SlicingPlugin menu;
+  viewer.plugins.push_back(&menu);
+
+  viewer.launch();
+}

+ 1 - 0
tutorial/CMakeLists.txt

@@ -58,6 +58,7 @@ if(TUTORIALS_CHAPTER1)
   if(LIBIGL_WITH_OPENGL_GLFW_IMGUI)
     add_subdirectory("105_Overlays")
     add_subdirectory("106_ViewerMenu")
+    add_subdirectory("109_ImGuizmo")
   endif()
   add_subdirectory("107_MultipleMeshes")
   add_subdirectory("108_MultipleViews")