Skip to content

Can only have one ImGuiMenu plugin at a time #1656

@alecjacobson

Description

@alecjacobson

The new imguizmo and selection plugins inherit from igl::opengl::glfw::imgui::ImGuiMenu.

Unfortunately, due to how imgui+plugins behave, this means you can only have at most one of these plugins active at a time.

Here's a minimal example:

#include <igl/read_triangle_mesh.h>
#include <igl/opengl/glfw/Viewer.h>
#include <igl/opengl/glfw/imgui/ImGuiMenu.h>
#include <igl/opengl/glfw/imgui/ImGuizmoPlugin.h>
#define WITH_IMGUIZMO
#define WITH_MENU

int main(int argc, char *argv[])
{
  // Load a mesh from file
  Eigen::MatrixXd V;
  Eigen::MatrixXi F;
  igl::read_triangle_mesh(argv[1],V,F);
  // Set up viewer
  igl::opengl::glfw::Viewer vr;
  vr.data().set_mesh(V,F);

  // Attach a menu plugin
#ifdef WITH_MENU
  igl::opengl::glfw::imgui::ImGuiMenu menu;
  vr.plugins.push_back(&menu);
#endif

#ifdef WITH_IMGUIZMO
  igl::opengl::glfw::imgui::ImGuizmoPlugin imguizmo;
  vr.plugins.push_back(&imguizmo);
  // Initialize ImGuizmo at mesh centroid
  imguizmo.T.block(0,3,3,1) = 
    0.5*(V.colwise().maxCoeff() + V.colwise().minCoeff()).transpose().cast<float>();
  // Update can be applied relative to this remembered initial transform
  const Eigen::Matrix4f T0 = imguizmo.T;
  // Attach callback to apply imguizmo's transform to mesh
  imguizmo.callback = [&](const Eigen::Matrix4f & T)
  {
    const Eigen::Matrix4d TT = (T*T0.inverse()).cast<double>().transpose();
    vr.data().set_vertices(
      (V.rowwise().homogeneous()*TT).rowwise().hnormalized());
    vr.data().compute_normals();
  };
#endif
  vr.launch();
}

This crashes on an imgui assertion:

Assertion failed: ((g.FrameCount == 0 || g.FrameCountEnded == g.FrameCount) && "Forgot to call Render() or EndFrame() at the end of the previous frame?"), function ErrorCheckNewFrameSanityChecks, file /Users/ajx/Repos/libigl/external/imgui/imgui.cpp, line 6733.
Process 60128 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = hit program assert
    frame #4: 0x00000001001bc2c4 example`ImGui::ErrorCheckNewFrameSanityChecks() at imgui.cpp:6733:5
   6730	    // (We pass an error message in the assert expression to make it visible to programmers who are not using a debugger, as most assert handlers display their argument)
   6731	    IM_ASSERT(g.Initialized);
   6732	    IM_ASSERT((g.IO.DeltaTime > 0.0f || g.FrameCount == 0)              && "Need a positive DeltaTime!");
-> 6733	    IM_ASSERT((g.FrameCount == 0 || g.FrameCountEnded == g.FrameCount)  && "Forgot to call Render() or EndFrame() at the end of the previous frame?");
   6734	    IM_ASSERT(g.IO.DisplaySize.x >= 0.0f && g.IO.DisplaySize.y >= 0.0f  && "Invalid DisplaySize value!");
   6735	    IM_ASSERT(g.IO.Fonts->Fonts.Size > 0                                && "Font Atlas not built. Did you call io.Fonts->GetTexDataAsRGBA32() / GetTexDataAsAlpha8() ?");
   6736	    IM_ASSERT(g.IO.Fonts->Fonts[0]->IsLoaded()                          && "Font Atlas not built. Did you call io.Fonts->GetTexDataAsRGBA32() / GetTexDataAsAlpha8() ?");
Target 0: (example) stopped.

This appears to be a consequence with how drawing plugins is handled in the Viewer. The viewer will loop over all of the plugins calling their pre_draw functions, then the Viewer draws itself, then the Viewer loops over all of the plugins calling their post_draw functions.

Each of these imgui-based plugins initializes the imgui "context" during its pre_draw, e.g., `ImGuiMenu::predraw contains:

  ImGui_ImplOpenGL3_NewFrame();
  ImGui_ImplGlfw_NewFrame();
  ImGui::NewFrame();

So with 3 plugins, this gets called 3 times, then the Viewer draws, and then each plugin calls imgui "de-initialization"/"render" routines in their post_draw. E.g.,

  ImGui::Render();
  ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());

What's a good fix here?

Do we really need to sandwich the pre/post draw?

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions