Commit f75647c7 authored by Philip Trettner's avatar Philip Trettner
Browse files

Merge branch 'feature/imguizmo-sample' into 'develop'

Add sample for ImGuizmo usage

See merge request !15
parents e068b75c 2143e10f
Pipeline #18415 passed with stage
in 21 minutes and 39 seconds
glow-extras @ 48afcb1f
Subproject commit 9a73f0ea1a1272d861fd329d8f61f24cb74d536b
Subproject commit 48afcb1fdbcaf874f7d58d86545525bca554696c
imgui @ 8ca0ab36
Subproject commit fcf73e7562f82dca7de2e66666e77cbbcc38be5b
Subproject commit 8ca0ab36f8a5072b8dfaf569646233166f507c84
#include <imgui/imgui.h>
#include <imgui/imguizmo.h>
#include <glow/common/str_utils.hh>
#include <glow/data/TextureData.hh>
......@@ -15,6 +16,8 @@
#include <glow-extras/viewer/canvas.hh>
#include <glow-extras/viewer/view.hh>
#include <GLFW/glfw3.h>
#include <typed-geometry/tg.hh>
// path to sample files
......@@ -164,6 +167,117 @@ void advanced_objects(pm::vertex_attribute<tg::pos3> const& pos)
// TODO: images
void imguizmo(pm::vertex_attribute<tg::pos3> const& pos)
// This sample shows how to use ImGuizmo, a very useful addon for ImGui for editing 4x4 affine transformation matrices using the viewer
// For additional information refer to
// your own camera is required to access the camera's view and projection matrix
auto cam = gv::CameraController::create();
// cache the renderable
auto r = gv::make_renderable(pos);
// local vs global coordinate system
auto currentGizmoMode = ImGuizmo::LOCAL;
// the operation that we want to perform (rotate, scale, or translate)
auto currentGizmoOperation = ImGuizmo::ROTATE;
// do we want to snap to specific values
bool useSnap = false;
// the values that we want to snap to, i.e. 1 degree steps
float snap[3] = {1.f, 1.f, 1.f};
// the transformation that we want to edit
auto transform = tg::mat4::identity;
// an interactive view is required
gv::interactive([&](float) {
// you can define keybindings to select an operation
if (ImGui::IsKeyPressed(GLFW_KEY_T))
currentGizmoOperation = ImGuizmo::TRANSLATE;
if (ImGui::IsKeyPressed(GLFW_KEY_R))
currentGizmoOperation = ImGuizmo::ROTATE;
if (ImGui::IsKeyPressed(GLFW_KEY_S))
currentGizmoOperation = ImGuizmo::SCALE;
// you can also choose the correct operation using gui elements
if (ImGui::RadioButton("Translate", currentGizmoOperation == ImGuizmo::TRANSLATE))
currentGizmoOperation = ImGuizmo::TRANSLATE;
if (ImGui::RadioButton("Rotate", currentGizmoOperation == ImGuizmo::ROTATE))
currentGizmoOperation = ImGuizmo::ROTATE;
if (ImGui::RadioButton("Scale", currentGizmoOperation == ImGuizmo::SCALE))
currentGizmoOperation = ImGuizmo::SCALE;
// ImGuizmo decomposes your input transform into translation, rotation, and scaling components
float matrixTranslation[3], matrixRotation[3], matrixScale[3];
ImGuizmo::DecomposeMatrixToComponents(&transform[0][0], matrixTranslation, matrixRotation, matrixScale);
// show the three components individually
ImGui::InputFloat3("Tr", matrixTranslation);
ImGui::InputFloat3("Rt", matrixRotation);
ImGui::InputFloat3("Sc", matrixScale);
// rebuild your 4x4 transform matrix
ImGuizmo::RecomposeMatrixFromComponents(matrixTranslation, matrixRotation, matrixScale, &transform[0][0]);
// only show the radio button to choose local/global coordinate system when NOT scaling
// as scaling is always in local coordinates
if (currentGizmoOperation != ImGuizmo::SCALE)
if (ImGui::RadioButton("Local", currentGizmoMode == ImGuizmo::LOCAL))
currentGizmoMode = ImGuizmo::LOCAL;
if (ImGui::RadioButton("World", currentGizmoMode == ImGuizmo::WORLD))
currentGizmoMode = ImGuizmo::WORLD;
// toggle snap on p key
if (ImGui::IsKeyPressed(GLFW_KEY_P))
useSnap = !useSnap;
// ... or use gui elements
ImGui::Checkbox("", &useSnap);
// name the snap input accordingly
switch (currentGizmoOperation)
case ImGuizmo::TRANSLATE:
ImGui::InputFloat3("Snap", snap);
case ImGuizmo::ROTATE:
ImGui::InputFloat("Angle Snap", snap);
case ImGuizmo::SCALE:
ImGui::InputFloat("Scale Snap", snap);
default: // silence warnings as there are quite a few more possible operations supported by ImGuizmo
break; // do nothing
// ImGuizmo requires view and projection matrix for rendering.
// However, it does not work with a reversed z projection matrix, which is used by the viewer by default
// So we need to disable it temporarily, generate a projection matrix without it, and then reactivate it
auto view = cam->computeViewMatrix();
auto const rev_z_enabled = cam->reverseZEnabled();
cam->setReverseZEnabled(false); //
auto project = cam->computeProjMatrix();
// This is where all the ImGuizmo magic comes together
ImGuizmo::Manipulate(&view[0][0], &project[0][0], currentGizmoOperation, currentGizmoMode, &transform[0][0], nullptr, useSnap ? &snap[0] : nullptr);
// Because the view is resized when we change the object, it might be a good idea to pass the viewer a fixed bounding box
auto const aabb = tg::aabb3(tg::pos3(-2), tg::pos3(2));
gv::view(r, cam, transform, aabb);
void advanced_visualization(pm::vertex_attribute<tg::pos3> const& pos)
// the args in gv::view(obj, args) do not only configure the viewer but also change how the renderable is visualized
......@@ -1011,6 +1125,8 @@ int main()
// known issues
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment