Giter Club home page Giter Club logo

imguizmo's Introduction

ImGuizmo

Latest stable tagged version is 1.83. Current master version is 1.84 WIP.

What started with the gizmo is now a collection of dear imgui widgets and more advanced controls.

Guizmos

ImViewGizmo

Manipulate view orientation with 1 single line of code

Image of ImViewGizmo

ImGuizmo

ImGizmo is a small (.h and .cpp) library built ontop of Dear ImGui that allow you to manipulate(Rotate & translate at the moment) 4x4 float matrices. No other dependancies. Coded with Immediate Mode (IM) philosophy in mind.

Built against DearImgui 1.53WIP

Image of Rotation Image of Translation Image of Bounds

There is now a sample for Win32/OpenGL ! With a binary in bin directory. Image of Sample

ImSequencer

A WIP little sequencer used to edit frame start/end for different events in a timeline. Image of Rotation Check the sample for the documentation. More to come...

Graph Editor

Nodes + connections. Custom draw inside nodes is possible with the delegate system in place. Image of GraphEditor

API doc

Call BeginFrame right after ImGui_XXXX_NewFrame();

void BeginFrame();

return true if mouse cursor is over any gizmo control (axis, plan or screen component)

bool IsOver();**

return true if mouse IsOver or if the gizmo is in moving state

bool IsUsing();**

enable/disable the gizmo. Stay in the state until next call to Enable. gizmo is rendered with gray half transparent color when disabled

void Enable(bool enable);**

helper functions for manualy editing translation/rotation/scale with an input float translation, rotation and scale float points to 3 floats each Angles are in degrees (more suitable for human editing) example:

 float matrixTranslation[3], matrixRotation[3], matrixScale[3];
 ImGuizmo::DecomposeMatrixToComponents(gizmoMatrix.m16, matrixTranslation, matrixRotation, matrixScale);
 ImGui::InputFloat3("Tr", matrixTranslation, 3);
 ImGui::InputFloat3("Rt", matrixRotation, 3);
 ImGui::InputFloat3("Sc", matrixScale, 3);
 ImGuizmo::RecomposeMatrixFromComponents(matrixTranslation, matrixRotation, matrixScale, gizmoMatrix.m16);

These functions have some numerical stability issues for now. Use with caution.

void DecomposeMatrixToComponents(const float *matrix, float *translation, float *rotation, float *scale);
void RecomposeMatrixFromComponents(const float *translation, const float *rotation, const float *scale, float *matrix);**

Render a cube with face color corresponding to face normal. Usefull for debug/test

void DrawCube(const float *view, const float *projection, float *matrix);**

Call it when you want a gizmo Needs view and projection matrices. Matrix parameter is the source matrix (where will be gizmo be drawn) and might be transformed by the function. Return deltaMatrix is optional. snap points to a float[3] for translation and to a single float for scale or rotation. Snap angle is in Euler Degrees.

    enum OPERATION
    {
        TRANSLATE,
        ROTATE,
        SCALE
    };

    enum MODE
    {
        LOCAL,
        WORLD
    };

void Manipulate(const float *view, const float *projection, OPERATION operation, MODE mode, float *matrix, float *deltaMatrix = 0, float *snap = 0);**

ImGui Example

Code for :

Image of dialog

void EditTransform(const Camera& camera, matrix_t& matrix)
{
    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.m16, matrixTranslation, matrixRotation, matrixScale);
    ImGui::InputFloat3("Tr", matrixTranslation, 3);
    ImGui::InputFloat3("Rt", matrixRotation, 3);
    ImGui::InputFloat3("Sc", matrixScale, 3);
    ImGuizmo::RecomposeMatrixFromComponents(matrixTranslation, matrixRotation, matrixScale, matrix.m16);

    if (mCurrentGizmoOperation != ImGuizmo::SCALE)
    {
        if (ImGui::RadioButton("Local", mCurrentGizmoMode == ImGuizmo::LOCAL))
            mCurrentGizmoMode = ImGuizmo::LOCAL;
        ImGui::SameLine();
        if (ImGui::RadioButton("World", mCurrentGizmoMode == ImGuizmo::WORLD))
            mCurrentGizmoMode = ImGuizmo::WORLD;
    }
    static bool useSnap(false);
    if (ImGui::IsKeyPressed(83))
        useSnap = !useSnap;
    ImGui::Checkbox("", &useSnap);
    ImGui::SameLine();
    vec_t snap;
    switch (mCurrentGizmoOperation)
    {
    case ImGuizmo::TRANSLATE:
        snap = config.mSnapTranslation;
        ImGui::InputFloat3("Snap", &snap.x);
        break;
    case ImGuizmo::ROTATE:
        snap = config.mSnapRotation;
        ImGui::InputFloat("Angle Snap", &snap.x);
        break;
    case ImGuizmo::SCALE:
        snap = config.mSnapScale;
        ImGui::InputFloat("Scale Snap", &snap.x);
        break;
    }
    ImGuiIO& io = ImGui::GetIO();
    ImGuizmo::SetRect(0, 0, io.DisplaySize.x, io.DisplaySize.y);
    ImGuizmo::Manipulate(camera.mView.m16, camera.mProjection.m16, mCurrentGizmoOperation, mCurrentGizmoMode, matrix.m16, NULL, useSnap ? &snap.x : NULL);
}

Install

ImGuizmo can be installed via vcpkg and used cmake

vcpkg install imguizmo

See the vcpkg example for more details

License

ImGuizmo is licensed under the MIT License, see LICENSE for more information.

imguizmo's People

Contributors

aaronkirkham avatar abdul-az avatar adamkewley avatar aidiakapi avatar alexandrejubert avatar amc522 avatar bkaradzic avatar bravoxavi avatar ccawley2011 avatar cedricguillemet avatar cedricguillemetms avatar chainsawkitten avatar dougbinks avatar enginmanap avatar gergondet avatar haskha avatar idbrii avatar jonathanhiggs avatar longod avatar madeso avatar mgerhardy avatar noizex avatar nprotect avatar rokups avatar sherief avatar sonoro1234 avatar syoyo avatar victorfouquet avatar xdudssx avatar ybalrid avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

imguizmo's Issues

Some troubles with integration

I'm trying to use your library for my engine, but I can't properly integrate it.
I have that rendering model:
Scene -> Hierarchy -> GameObject -> Transform { position, rotation, scale } + EditorCamera as a GameObject
When I select a GameObject in hierarchy, I expect to edit its transform, but:

  1. I cannot properly build matrices for ImGuizmo (Maybe I'm so stupid, but nothing I tried helps me)
  2. It render grid and maybe something else orthographically
  3. Even if I get some success, ImGuizmo renders on the background(behind all windows, but I need to render it over the render window only)

Screenshots:
image
image
image

Code of transform editing function:

void EditTransform(Transform* t)
    {
        auto cam = EditorInstance::GetSingleton()->currentScene->Get("Editor Camera");
        auto camCmp = cam->GetComponent<Camera>();

        ImGuizmo::SetOrthographic(false);
        ImGuizmo::BeginFrame();
        ImGuizmo::Enable(true);


        ImGuiIO& io = ImGui::GetIO();
        ImGuizmo::SetRect(0, 0, io.DisplaySize.x, io.DisplaySize.y);

        float* _view = new float[16];
        glm::mat4 mmat = glm::mat4();
        glm::translate(mmat, glm::vec3{t->globalPosition().x, t->globalPosition().y, t->globalPosition().z});
        glm::scale(mmat, glm::vec3{t->scale.x, t->scale.y, t->scale.z});
        glm::rotate(mmat, (float)t->rotation.x , glm::vec3{1, 0, 0});
        glm::rotate(mmat, (float)t->rotation.y , glm::vec3{0, 1, 0});
        glm::rotate(mmat, (float)t->rotation.z , glm::vec3{0, 0, 1});
        
        // ==> WHAT AM I DOING WRONG? NOTHING OF NEXT WORKS PROPERLY.
        //_view =(float*)glm::value_ptr(mmat);
        glGetFloatv(GL_MODELVIEW_MATRIX, _view);
        glm::fmat4 view = glm::mat4(*_view);

        float* _proj = new float[16];
        glm::mat4 pmat = glm::perspectiveFov(camCmp->fov, io.DisplaySize.x, io.DisplaySize.y, camCmp->_near, camCmp->_far);

//  ==> AND HERE TOO
//        _proj = (float*)glm::value_ptr(pmat);
//        glGetFloatv(GL_PROJECTION_MATRIX, _proj);
        glm::fmat4 projection = pmat; //(*_proj);


        auto matrix = glm::lookAt(
            glm::vec3{ cam->transform.globalPosition().x, cam->transform.globalPosition().y, cam->transform.globalPosition().z },
//            { t->globalPosition().x, t->globalPosition().y, t->globalPosition().z },
            { cam->transform.globalPosition().x + cam->transform.direction().x, cam->transform.globalPosition().y + cam->transform.direction().y, cam->transform.globalPosition().z + cam->transform.direction().z },
            { 0, 1, 0});

        ImGuizmo::DrawGrid(&view[0][0], &projection[0][0], &matrix[0][0], 200.0f);
        ImGuizmo::Manipulate(&view[0][0], &projection[0][0], ImGuizmo::TRANSLATE, ImGuizmo::WORLD, &matrix[0][0], NULL, NULL);
    }

Code of render window function:

 void winRender(){
        ImGui::Begin("Render", &win->render, window_flags);
        ImVec2 pos = ImGui::GetWindowPos();
        auto tex = dynamic_cast<NukeOGL*>(EditorInstance::GetSingleton()->render)->getRenderTexture();
        ImVec2 maxPos = ImVec2(pos.x + ImGui::GetWindowSize().x, pos.y + ImGui::GetWindowSize().y + 2);
        ImGui::GetWindowDrawList()->AddImage((void *)tex,
                                             ImVec2(ImGui::GetItemRectMin().x + 0,
                                            ImGui::GetItemRectMin().y - 2),
                                             maxPos, ImVec2(0,1), ImVec2(1,0));
        if(EditorInstance::GetSingleton()->selectedInHieararchy){
           EditTransform(&EditorInstance::GetSingleton()->selectedInHieararchy->transform);
        }

        ImGui::End();
    }

Gizmo moves along side the camera

When I render the scene to a framebuffer texture using ImGui the gizmo axis and start to rotate the camera the gizmo starts to move as well. When I don't render to the texture ImGui works perfectly fine. Do you maybe have an example rendering the gizmos on a framebuffer?

Multi view here

I believe i have a working multi view version which handles drawing the gizmos in any sized window anywhere on the screen .
I suggest change of BeginFrame to SetViewRect
void SetViewRect(float x, float y, float width, float height) { //ImGui::Begin("gizmo", NULL, ImVec2(width, height), 0, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoBringToFrontOnFocus); // this should be optional gContext.mX = x; gContext.mY = y; gContext.mWidth = width; gContext.mHeight = height; gContext.mDrawList = ImGui::GetWindowDrawList(); //ImGui::End() this should be optional }
then replace most of the places that used io.DisplaySize with the width and height.

In worldToPos function
trans.x *= gContext.mWidth; trans.y *= gContext.mHeight; trans.x += gContext.mX; trans.y += gContext.mY;

In ComputeCameraRay function
float mox = ((io.MousePos.x - gContext.mX) / gContext.mWidth) * 2.f - 1.f; float moy = (1.f - ((io.MousePos.y - gContext.mY) / gContext.mHeight)) * 2.f - 1.f;

In DrawRotationGizmo function
drawList->AddCircle(worldToPos(gContext.mModel.v.position, gContext.mViewProjection), 0.06f * gContext.mWidth, colors[0], 64);

In GetRotateType function
if (dist >= 0.058f * gContext.mWidth && dist < 0.062f * gContext.mWidth) type = ROTATE_SCREEN;

thats pretty much it.

Scale axes selection/visual mismatch

When the input model matrix has a non-null rotation, the selectable area of scale axes does not match the location of the axes (see screenshot).
image

I think the issues lies in the GetScaleType function, as the tripod axes are not transformed with the model matrix like in the GetMoveType function

License for this? :)

I am coding an unlicensed/public domain engine and I'd love to integrate this.
What's the license for this?

Btw, integration went incredibly smooth :)
Congrats!

gif

PS: Looking forward for the rotation and scale components! ๐Ÿ˜ƒ

imGuizmo Dummy window on BeginFrame creates big black window with Viewport branch

Problem:
imGuizmo's BeginFrame function uses a dummy window in order to acquire a pointer to the drawlist. This dummy window has its position set to 0,0 and is made to take up the full size of the viewport.

Because of semantic changes (and some bug fixes) to setPos in dearImGUI when using viewports: 0,0 is actually the top-left of the screen, not the imgui application. So using imGuizmo with the docking branch & viewports causes a big black window to appear that cannot be interacted with in the top left of the screen.

BlackBox

The simplest change would be to alter line 744 of ImGuizmo.cpp to

#ifdef IMGUI_HAS_VIEWPORT
	ImGui::SetNextWindowPos(ImGui::GetMainViewport()->Pos);
#else
	ImGui::SetNextWindowPos(ImVec2(0, 0))
#endif

But, it might not even be necessary to have a dummy window at all now due to the addition of GetBackgroundDrawList which could replace most of the function like so:

#ifdef IMGUI_HAS_VIEWPORT
	gContext.mDrawList = ImGui::GetBackgroundDrawList(ImGui::GetMainViewport());
#else
	gContext.mDrawList = ImGui::GetBackgroundDrawList();
#endif

I don't know if imGuizmo uses this dummy window for anything except the draw list.

No gizmos showing up

Hi I went and downloaded the latest imgui. I integrated my own code into the sample and got it running. Looked through imguizmo and integrated it into my code too. But nothing of Imguizmo shows up...here is some code

`
ImGui_ImplWin32_Init(hwnd);
ImGui_ImplDX11_Init(d3d11Device, d3d11DevCon);

// Setup style
//ImGui::StyleColorsDark();
ImGui::StyleColorsClassic();

// Load Fonts
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. 
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple. 
// - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
// - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
// - Read 'misc/fonts/README.txt' for more instructions and details.
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
//io.Fonts->AddFontDefault();
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f);
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
//IM_ASSERT(font != NULL);

// Our state
bool show_demo_window = true;
bool show_another_window = false;
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);

// Main loop
MSG msg;
ZeroMemory(&msg, sizeof(msg));
while (msg.message != WM_QUIT)
{
    // Poll and handle messages (inputs, window resize, etc.)
    // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
    // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
    // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
    // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
    if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
        continue;
    }

    // Start the Dear ImGui frame
    ImGui_ImplDX11_NewFrame();
    ImGui_ImplWin32_NewFrame();
    ImGui::NewFrame();

	ImGuizmo::BeginFrame();

	/*float* view = matrix_to_float_array(camView);
	float* projection = matrix_to_float_array(camProjection);
	float* world = matrix_to_float_array(meshList[0].worldMat);*/

	static ImGuizmo::OPERATION mCurrentGizmoOperation(ImGuizmo::TRANSLATE);
	static ImGuizmo::MODE mCurrentGizmoMode(ImGuizmo::LOCAL);

	DirectX::XMFLOAT4X4 v = change_mat(camView);
	DirectX::XMFLOAT4X4 p = change_mat(camProjection);
	DirectX::XMFLOAT4X4 w = change_mat(meshList[0].worldMat);

	ImGuizmo::Manipulate(&v.m[0][0], &p.m[0][0], mCurrentGizmoOperation, mCurrentGizmoMode, &w.m[0][0]);

`

Here are two of my conversion functions...I tried passing the matrices needed for the function two different ways

`DirectX::XMFLOAT4X4 change_mat(DirectX::XMMATRIX mat)
{
DirectX::XMFLOAT4X4 temp;
DirectX::XMStoreFloat4x4(&temp, mat);

return temp;

}`

`float* matrix_to_float_array(DirectX::XMMATRIX mat)
{
DirectX::XMFLOAT4X4* temp = new DirectX::XMFLOAT4X4();
DirectX::XMStoreFloat4x4(temp, mat);

float m16[16];

m16[0] = temp->_11;
m16[1] = temp->_12;
m16[2] = temp->_13;
m16[3] = temp->_14;
m16[4] = temp->_21;
m16[5] = temp->_22;
m16[6] = temp->_23;
m16[7] = temp->_24;
m16[8] = temp->_31;
m16[9] = temp->_32;
m16[10] = temp->_33;
m16[11] = temp->_34;
m16[12] = temp->_41;
m16[13] = temp->_42;
m16[14] = temp->_43;
m16[15] = temp->_44;

return m16;

}`

I saw someone else had this problem of no gizmo showing up and they didn't set the matrix to anything so thats why theirs didn't work. My matrices are set. The world matrix is set to Matrix.Identity. The models that the matrix represents is showing up so everything is set and working...just not the gizmo.

X -axis is detected throughout the whole screen until object is orientated

So currently, I'm using a perspective camera that is perfectly centred, Pos(0,0,1) facing (0,0,-1) with Up axis of (0,1,0)

I'm trying to achieve perspective view in 2D.

However, with this camera, the Y-arrow is not being detected at all and the X-arrow is constantly being detected. I can only get them to work when I rotate my objects revealing all 3 axes.

However, is there a way to solve this without even rotating my objects at all?

Issues with rotation order.

Rotating object does not seem to fit the rotation order of my engine. The Gizmo and mesh end up not matching at all. Is there a particular rotation order that must be followed?

Multiple gizmos don't appear to work

When using multiple gizmos at a time, they all seem to act as one, rather than individually:

screencapture_2016-09-11-17-16-52

Implementation side I guess Manipulate would need an ID, and take advantage of ImGuiStorage to store if a handle is being used or not. @CedricGuillemet, does this sound reasonable? I am happy to look at implementing and sending over a PR if it doesn't conflict with any ideas you have :)

Support for 2D transformations?

Hi there,

I'd like to use this nice little gizmo to set a 2D transformation matrix. Basically I would like to "hide" one of the axes (e.g. Z). I've tried to "squish" things down by setting the Z scaling to 0/1e-3 for either the view matrix, or the manipulated matrix ... And neither of them really works well: with the former approach, I cannot select the Y axis (only the X), but the Z axis/XZ/YZ planes are well hidden; with the latter the Z/XZ/YZ are still visible, and there is some issue with the RectTransform (#20).

Looking at the code it looks like it shouldn't be too hard to add an option to mask one axis, but I'm open to other suggestions.

Ability to restrict rotation about some axes

Is there a way to make it so that rotation can't be done about some of the axes?

For example, I have a need to sometimes restrict the rotation so that an object can be rotated only about the y axis. So, in this case, I would like to disable rotation about x and z axes.

Function "Mogwai" name cryptic

More of a suggestion regarding personal preference here, "Mogwai" seems like quite a cryptic name for a function. To me it feels like having separate "Scale" "Rotate" "Translate" functions would be better, and more approachable.

FWIW I understand the reference, I just don't think everyone will :)

The guizmo doesn't show-up in directX 11

I have a directX11 based engine in which i wanted to add imGuizmo. i already have imgui running but even after following all the steps mentioned on the github page, after enabling the guizmo i still can't get it to show-up at all. and since there was not much code at all i can't seem to figure-out where it might be going wrong. plus where do i give my transformation matrices to the guizmo for it to render with my camera and projection matrices.

Planes are jumbled up:

The XZ and YZ planes are swapped versus their visual presentations.

Visual XY = 4, MOVE_XY
Visual XZ = 6, MOVE_YZ mismatch
Visual YZ = 5, MOVE_XZ mismatch

DrawCube not drawing

DrawCube does not actually render a cube if Manipulate() is not called
I think the incriminated line is:
1945: camSpacePosition.TransformPoint(faceCoords[iCoord] * 0.5f * invert, gContext.mMVP);

Maybe without Manipulate gContext.mMVP is not initialized

need some code comment

I examine Sequencer and your idea is truly inspirational for me.

I try to understand some hard-codded values and ImGui uses.
Some explanatory comment would be great.

to understand your logic and learn some ImGui... I tried to replace this logic:
for (int i = 0; i <= sequence->frame_count; i += frameStep)
with this:
for (int i = first_visible_frame; i <= last_visible_frame; i += frameStep)

I am not good at ImGui so it was hard and time-consuming work for me.
Thank you.

Rotation's final calculation seems wrong.

I believe the correct one will be: (works with local and world coordiante system)

matrix_t deltaM = gContext.mModelInverse * deltaRotation * gContext.mModel; *(matrix_t*)matrix = gContext.mModelSource * deltaM; if (deltaMatrix) { *(matrix_t*)deltaMatrix = deltaM; }
Otherwise amazing job man :)

Behind camera culling.

when behind the camera the gizmo is still rendered but wrong.
Add the following stuff to prevent this.

gContext.mCameraNearPlane.x = (gContext.mViewProjection.m[0][2]); gContext.mCameraNearPlane.y = (gContext.mViewProjection.m[1][2]); gContext.mCameraNearPlane.z = (gContext.mViewProjection.m[2][2]); gContext.mCameraNearPlane.w = (gContext.mViewProjection.m[3][2]);

and this

`void Manipulate(const float view, const float *projection, OPERATION operation, MODE mode, float *matrix, float *deltaMatrix)
{
ComputeContext(view, projection, matrix, mode);
// set delta to identity
if (deltaMatrix)
((matrix_t
)deltaMatrix)->SetToIdentity();

    vec_t cameraEyeToGizmo = Normalized(gContext.mModel.v.position - gContext.mCameraEye);
    if (cameraEyeToGizmo.Dot3(gContext.mCameraNearPlane) < 0)
        return;'

Local Space vs World Space

Hi!
I was wondering what the difference between world space and local space was, and when I should use what. I was also wondering if this uses Z-Up or Y-Up by default. Thanks!

Rotation with screen rotate (white circle) in WORLD mode reset the rotation

Hello @CedricGuillemet,

First of all thank you for this nice manipulator.

Here are the steps to reproduce the issue (maybe it's related to #72) :
launch ImGuizmoSample.exe
Select Rotate
Select World
Rotate the cube with the white circle
Click on the white circle
Behaviour is : Rotation components are reset to 0
Behaviour should be : Rotation components do not change

I must admit that this week I haven't time to look at it in details so I don't know if the following change is relevant but here is the small change (ImGuizmo.cpp) :
line 1795 was :
*(matrix_t*)matrix = scaleOrigin * deltaRotation * gContext.mModel;
is :
if (gContext.mMode == LOCAL) *(matrix_t*)matrix = scaleOrigin * deltaRotation * gContext.mModel; else *(matrix_t*)matrix = scaleOrigin * deltaRotation * @gContext.mModelSource;

World space scale?

When there is already applied rotation then what should world space scale do? Maybe shear? Enginens like Unity seems to avoid this issue by just prohibiting it - there scaling via gizmos can only be done in local space

Delta matrix receives incorrect scale value

When scaling delta matrix gets absolute scale value on every frame while translation and rotation receive delta since the last frame. Could this be made consistent with translation and rotation?

Documentation needs updating to reflect change from Mogwai to Manipulate

Super minor, but worth pointing out. With the change of Mogwai to Manipulate, the in header documentation should reflect this change.

ImGuizmo::Mogwai(gCurrentCamera->mView.m16, gCurrentCamera->mProjection.m16, mCurrentGizmoOperation, mCurrentGizmoMode, gizmoMatrix.m16);

should be

ImGuizmo::Manipulate(gCurrentCamera->mView.m16, gCurrentCamera->mProjection.m16, mCurrentGizmoOperation, mCurrentGizmoMode, gizmoMatrix.m16);

PS: Thanks for sharing ImGuizmo, just integrated it and am excited to use it more.

Multiple viewport support

Just looking through it at the moment, and it appears that it's only setup to do a single fullscreen viewport. I hope to use it for multiple viewports at some point, and just curious if it's planned or not?

I have a few ideas of how to adapt this, possibly by doing something along the lines of adding something like:

void BeginView(Rect viewport, const float *view, const float *projection);
void EndView();
void Mogwai(MODE mode, float *matrix, float *deltaMatrix = 0);

That way the view & projection wouldn't even need to be passed up either, could be scoped nicely, and keep usage cleaner. Of course this would work on the assumption that ImGui is being rendered fullscreen at the end of all rendering (as I'm sure most people are using it anyway).

ImGuizmo doesn't detect mouse movement

Hello,

As said in the title, the gizmo doesn't detect he mouse movement at all, but it detects the clics and my camera movements nicely.

I saw in the demo that you are using the ImApp class, i don't use this, i use the raw ImGui opengl implementation, maybe the problem comes from this ?

THRJPsm 1

Another thing, i don't know if it's a bug or not, but as seen in my screenshot, the x and z axis doesn't align with the world axis, it just turns and flip when it reaches 180 degrees.

Thanks for your help.

gitignore

Opening the solution in VS leaves a ton of working changes that could be mostly avoided. How about we add a gitignore for the unneeded stuff like:

.vs
Debug
imgui.ini
*.vcxproj.user

There's also the main vcxproj which can show up due to toolset changes but nothing we can do about that. Still a big difference to discard one item prior to a pull.

Rotate gizmo keeps rotating/wobbling

In the HandleRotation function at line 1795 the code

if (applyRotationLocaly) { *(matrix_t*)matrix = scaleOrigin * deltaRotation * gContext.mModel; }
assumes that you'd be handling the object matrix directly but my game engine has a system where it handles the matrix build every frame thus i only need the position, rotation and scale. I tried to replaced it with

if (applyRotationLocaly) { ImGuizmo::DecomposeMatrixToComponents(matrix, tx->pos_, tx->rot_, tx->scale_); }

tx is my transform component

So it basically just keeps rotating/wobbling. Strangely enough it works for translation and scaling but not rotation with the above method. Any ideas?

EDIT: Nevermind, I found another way. My bad.

translation snap problem

translation snap doesnt seem to work correctly when there is an applied rotation.
For example try rotating 45 degrees about the Y axis and then try translating with snap

Invalid movement on one axis

When dragging one gizmo axis, perpendicular mouse movement causes incorrect movement. Gif below displays how dragging vertical axis sideways moves object up and down. Other two axis do not have this problem.

video

It is not always same axis. It depends on point of view which axis misbehaves. This happens when translating or scaling. Depending on angle of view small sideways movement may cause huge changes and cause object "fly" out of the view and sometimes finding it can be tricky.

PR #33 seems to make this less of a problem i think, but does not fix it entirely. Or i may be imagining things and it was less of a problem only due to my point of view when testing. I am no longer sure.

Coordinate system requirements

Is ImGuizmo depend on a particular coordinate system? I'm trying to retrofit a 3D editor with ImGuizmo, one that is based on Dx9+Gamebryo. Gamebryo's coordinate system, for some reason, is different from the usual left-hand/right-hand systems :

  • The Up vector is in +Y
  • The Right vector is in +Z
  • The Forward vector is in +X

Unfortunately, using the view/perspective matrices of that coordinate system renders the gizmo incorrectly (it appears along the negative vertical axis and gets culled on the slightest movement of the camera). How would I go about resolving this issue? The gizmo does work with a regular LH coordinate system (tested it in a demo DirectX project).

io.WantCaptureMouse

Hi there,

I think that ImGUI::GetIO().WantCaptureMouse should be true when any ring is highlighted I think. Otherwise, there's no way to know whether a click in your scene was meant to select something in the scene, or if it was meant for the gizmo.

Perhaps there are other flags like this that also need to be managed?

PS - I know there is IsOver() and IsUsing() on ImGuizmo, but I feel like WantCaptureMouse is part of the puzzle

Issues in Y-up environment

Seeing issues where translation doesn't appear to work correctly when in an Y-up environment (EDIT: Y-up or not doesn't seem to matter, tried with different view matrix since it did seem suspect as that should be handled by the view matrix!). Individual axis translate correctly, but the XY, YZ, XZ plates don't. The thin RGB lines in these images are my own debug rendering to check against the gizmos.

XY: Is fine:
image

YZ behaves as XZ:
image

and XZ behaves as YZ:
image

After rotating, the translation gizmo no longer reacts to the correct mouse positions either:

image
image

Any idea what may be the issue here? Rotation gizmo seems to work 100% fine (X, Y, Z & screen space rotation)

In case it's related, the Scale gizmo doesn't appear to do anything at all, it just draws as a circle:

image

Scaling after rotate resets the size of the objectzazz

here is the code


#include "header.h"
#include <imgui.h>
#include "imgui_impl_glfw_gl3.h"
#include <stdio.h>

void init_graphics(DrawObject * obj, Camera * camera, int display_width, int display_height)
{
    obj->genVA();
    obj->genBuff();
    obj->bindVA();
    obj->bindBuff();
    obj->updateVAP(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
    glEnableVertexAttribArray(0);
    obj->updateBuffData(3*4* sizeof(GLfloat));
    obj->bufferdata[0] = 0.5f; obj->bufferdata[1] = 0.5f; obj->bufferdata[2] = 0.0f;
    obj->bufferdata[3] = -0.5f; obj->bufferdata[4] = 0.5f; obj->bufferdata[5] = 0.0f;
    obj->bufferdata[6] = -0.5f; obj->bufferdata[7] = -0.5f; obj->bufferdata[8] = 0.0f;
    obj->bufferdata[9] = 0.5f; obj->bufferdata[10] = -0.5f; obj->bufferdata[11] = 0.0f;
    //glm::perspective(camera->Zoom, (float) display_width/ (float) display_height, 1.0f, 1000.0f);
    obj->modelLoc = glGetUniformLocation(obj->shader.Program, "model");
    glUniformMatrix4fv(obj->modelLoc,1 ,GL_FALSE, glm::value_ptr(obj->model));
    glBindVertexArray(0);
}

void draw_object(DrawObject * obj, Camera * camera, int display_width, int display_height){
    obj->shader.Use();
    obj->view = glm::lookAt(glm::vec3(camera->Position.x, camera->Position.y, camera->Position.z),
                            glm::vec3(camera->Position.x + camera->Front.x, camera->Position.y + camera->Front.y, camera->Position.z + camera->Front.z),
                            glm::vec3(camera->Up.x, camera->Up.y, camera->Up.z));
    
    obj->projection = glm::perspective(camera->Zoom, (float) display_width/ (float) display_height, 1.0f, 1000.0f);
    
    obj->modelLoc = glGetUniformLocation(obj->shader.Program, "model");
    obj->viewLoc = glGetUniformLocation(obj->shader.Program, "view");
    obj->projLoc = glGetUniformLocation(obj->shader.Program, "projection");
    
    glUniformMatrix4fv(obj->viewLoc, 1, GL_FALSE, glm::value_ptr(obj->view));
    glUniformMatrix4fv(obj->projLoc, 1, GL_FALSE, glm::value_ptr(obj->projection));
    glUniformMatrix4fv(obj->modelLoc, 1, GL_FALSE, glm::value_ptr(obj->model));
    
    obj->bindBuff();
    obj->updateBuffData(3*4*sizeof(GLfloat));
    glEnableVertexAttribArray(0);
    
    obj->bindVA();
    
    glUniformMatrix4fv(obj->modelLoc, 1, GL_FALSE, glm::value_ptr(obj->model));
    glDrawArrays(GL_LINE_STRIP, 0, 4);
    glUniformMatrix4fv(obj->modelLoc, 1, GL_FALSE, glm::value_ptr(obj->model));
    glBindVertexArray(0);
}

void EditTransform(const Camera * camera, DrawObject * obj, float * matrix, float * view, float * proj)
{
    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);
    
    if (mCurrentGizmoOperation != ImGuizmo::SCALE)
    {
        if (ImGui::RadioButton("Local", mCurrentGizmoMode == ImGuizmo::LOCAL))
            mCurrentGizmoMode = ImGuizmo::LOCAL;
        ImGui::SameLine();
        if (ImGui::RadioButton("World", mCurrentGizmoMode == ImGuizmo::WORLD))
            mCurrentGizmoMode = ImGuizmo::WORLD;
    }
    static bool useSnap(false);
    if (ImGui::IsKeyPressed(83))
        useSnap = !useSnap;
    ImGui::Checkbox("", &useSnap);
    ImGui::SameLine();
    /*
    vec_t snap;
    switch (mCurrentGizmoOperation)
    {
        case ImGuizmo::TRANSLATE:
            snap = config.mSnapTranslation;
            ImGui::InputFloat3("Snap", &snap.x);
            break;
        case ImGuizmo::ROTATE:
            snap = config.mSnapRotation;
            ImGui::InputFloat("Angle Snap", &snap.x);
            break;
        case ImGuizmo::SCALE:
            snap = config.mSnapScale;
            ImGui::InputFloat("Scale Snap", &snap.x);
            break;
    }
     */
    ImGuiIO& io = ImGui::GetIO();
    ImGuizmo::SetRect(0, 0, io.DisplaySize.x, io.DisplaySize.y);
    ImGuizmo::Manipulate(view, proj, mCurrentGizmoOperation, mCurrentGizmoMode, matrix, NULL, NULL);
}

int main(){
    static Header * h = new Header();
    glfwSetErrorCallback(h->error_callback);
    
    if(!glfwInit())
        exit;
    
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
    
#if __MACOS_CORE__
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif
    
    h->window = (GLFWwindow *)glfwCreateWindow(1280, 800, "Troubleshooting OpenGL", NULL, NULL);
    if(!h->window){
        glfwTerminate();
        exit(EXIT_FAILURE);
    }
    glfwMakeContextCurrent(h->window);
    
    glewExperimental = GL_TRUE;
    GLenum err = glewInit();
    if(GLEW_OK != err){
        std::cout << "Error: " << glewGetErrorString(err) << std::endl;
    }
    ImGui_ImplGlfwGL3_Init(h->window, true);
    glfwSwapInterval(1);
    
    bool show_test_window = true;
    bool show_another_window = false;
    ImVec4 clear_color = ImColor(114, 144, 154);
    
    int display_width, display_height;
    
    DrawObject * obj1 = new DrawObject("obj1VS.glsl", "obj1FS.glsl", 3 * 4);
    glClearColor(0.2f, 0.2f, 0.2f, 1.0f);
    init_graphics(obj1, h->camera, display_width, display_height);
    int display_w, display_h;
    glfwGetFramebufferSize(h->window, &display_w, &display_h);
    glm::mat4 model;// = glm::mat4(0.0f);
    model = glm::translate(model, glm::vec3(0.0f, 0.0f, 0.0f));
    
    float * mtx = (float *) glm::value_ptr(model);
    float * pos = (float *) glm::value_ptr(glm::vec3(0.0f, 0.0f, 0.0f));
    float * rot = (float *) glm::value_ptr(glm::vec3(0.0f, 0.0f, 0.0f));
    float * scale = (float *) glm::value_ptr(glm::vec3(1.0f, 1.0f, 1.0f));
     
    //glUniformMatrix4fv(obj1->modelLoc, 1, GL_FALSE, glm::value_ptr(model));
    while( !glfwWindowShouldClose(h->window) )
    {
        glfwPollEvents();
        float * view_float, * model_float, * proj_float;
        view_float = (float *) glm::value_ptr(glm::lookAt(glm::vec3(h->camera->Position.x, h->camera->Position.y, h->camera->Position.z),
                                                          glm::vec3(h->camera->Position.x + h->camera->Front.x, h->camera->Position.y + h->camera->Front.y, h->camera->Position.z + h->camera->Front.z),
                                                          glm::vec3(h->camera->Up.x, h->camera->Up.y, h->camera->Up.z)));
        model_float = mtx;
        proj_float = (float *) glm::value_ptr(glm::perspective(h->camera->Zoom, (float) display_width/ (float) display_height, 1.0f, 1000.0f));
        // pass projection matrix to shader (note that in this case it could change every frame)
        ImGui_ImplGlfwGL3_NewFrame();
        
        glfwGetFramebufferSize(h->window, &display_width, &display_height);
        glViewport(0, 0, display_w, display_h);
        glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT );
        
        ImGuizmo::BeginFrame();
        
        // 1. Show a simple window
        // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug"
        {
            static float f = 0.0f;
            ImGui::Text("Hello, world!");
            ImGui::SliderFloat("float", &f, 0.0f, 1.0f);
            ImGui::ColorEdit3("clear color", (float*)&clear_color);
            if (ImGui::Button("Test Window")) show_test_window ^= 1;
            if (ImGui::Button("Another Window")) show_another_window ^= 1;
            ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
        }
        
        // 2. Show another simple window, this time using an explicit Begin/End pair
        if (show_another_window)
        {
            ImGui::SetNextWindowSize(ImVec2(200,100), ImGuiSetCond_FirstUseEver);
            ImGui::Begin("Another Window", &show_another_window);
            ImGui::Text("Hello");
            ImGui::End();
        }
        
        // 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow()
        if (show_test_window)
        {
            ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiSetCond_FirstUseEver);
            ImGui::ShowTestWindow(&show_test_window);
        }
        
        memcpy(glm::value_ptr(obj1->model), mtx, sizeof(float)*16);
        draw_object(obj1,h->camera,display_width,display_height);
        EditTransform(h->camera, obj1, mtx, view_float, proj_float);
        
        for (int i = 0; i < 16; i++){
            std::cout << mtx[i] << " ";
            if(1 > 0)
                if(i%4 == 0 )
                    std::cout << std::endl;
        }
        
        ImGui::Render();
        glfwSwapBuffers(h->window);
        
    }
    
}

t

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.