Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for 2D transformations? #49

Open
jdumas opened this issue Feb 10, 2018 · 7 comments
Open

Support for 2D transformations? #49

jdumas opened this issue Feb 10, 2018 · 7 comments

Comments

@jdumas
Copy link

jdumas commented Feb 10, 2018

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.

@CedricGuillemet
Copy link
Owner

Hi Jeremie,

Look for 'belowAxisLimit' boolean. It's true when the axis is nearly colinear with the camera view direction. If you enhance the checks with a mask (something like belowAxisLimit && ((1<<currentAxis)&AxisMask) you should be able to hide the axis you don't want.
AxisMask would be a combination of
AxisMaskX = 1, AxisMaskY = 2, AxisMaskZ = 4
And add a function ImGuizmo::SetAxisMask(int axisMask) to save the mask that in the context

@jdumas
Copy link
Author

jdumas commented Feb 10, 2018

Thanks! I've hardcoded those changes for now. I also had to fiddle around with the bestAxis in HandleAndDrawLocalBounds() to show the bounds in the plane I was interested in, even when it is viewed at a steep angle. I also modified the DrawCube() function to draw a single face at a coordinate Z=0.

Things are a bit hardcoded for now, so I can't really do a PR, but I may do that later on.

@vamidi
Copy link

vamidi commented Jul 7, 2019

@jdumas can you explain me how you did it? I want to try and make this (picture below) with Imguizmo where you can control a UI element within a X/Y plane
https://docs.unity3d.com/uploads/Main/UI_Anchored4.gif

@jdumas
Copy link
Author

jdumas commented Jul 7, 2019

In HandleAndDrawLocalBounds I have made the following modifications to enforce edits on the XY plane, even when viewed at a grazing angle:

               if ( i == 2 )
               {
                   bestDot = dt;
                   bestAxis = i;
                   bestAxisWorldDirection = dirPlaneNormalWorld;
               }

               if( i == 2 && dt >= 0.1f )
               {
                   axes[numAxes] = i;
                   axesWorldDirections[numAxes] = dirPlaneNormalWorld;
                   ++numAxes;
               }

       // ....

       for (unsigned int axisIndex = 0; axisIndex < numAxes; ++axisIndex)
       {
           if (axisIndex == 1) { break; }

And then my modified version of DrawCube:

   void DrawCube(const float *view, const float *projection, float *matrix)
   {
      matrix_t viewInverse;
      viewInverse.Inverse(*(const matrix_t*)view);
      const matrix_t& model = *(const matrix_t*)matrix;
      matrix_t res = *(const matrix_t*)matrix * *(const matrix_t*)view * *(const matrix_t*)projection;

      for (int iFace = 0; iFace < 6; iFace++)
      {
         const int normalIndex = (iFace % 3);
         const int perpXIndex = (normalIndex + 1) % 3;
         const int perpYIndex = (normalIndex + 2) % 3;
         const float invert = (iFace > 2) ? -1.f : 1.f;

         if (normalIndex != 2) { continue; }

         const vec_t faceCoords[4] = {
            /*directionUnary[normalIndex]*/ + directionUnary[perpXIndex] + directionUnary[perpYIndex],
            /*directionUnary[normalIndex]*/ + directionUnary[perpXIndex] - directionUnary[perpYIndex],
            /*directionUnary[normalIndex]*/ - directionUnary[perpXIndex] - directionUnary[perpYIndex],
            /*directionUnary[normalIndex]*/ - directionUnary[perpXIndex] + directionUnary[perpYIndex],
         };

         // clipping
         bool skipFace = false;
         for (unsigned int iCoord = 0; iCoord < 4; iCoord++)
         {
            vec_t camSpacePosition;
            camSpacePosition.TransformPoint(faceCoords[iCoord] * 0.5f * invert, gContext.mMVP);
            // if (camSpacePosition.z < 0.001f)
            // {
            //    skipFace = true;
            //    break;
            // }
         }
         if (skipFace)
            continue;

         // 3D->2D
         ImVec2 faceCoordsScreen[4];
         for (unsigned int iCoord = 0; iCoord < 4; iCoord++)
            faceCoordsScreen[iCoord] = worldToPos(faceCoords[iCoord] * 0.5f * invert, res);

         // back face culling
         vec_t cullPos, cullNormal;
         cullPos.TransformPoint(faceCoords[0] * 0.5f * invert, model);
         cullNormal.TransformVector(directionUnary[normalIndex] * invert, model);
         float dt = Dot(Normalized(cullPos - viewInverse.v.position), Normalized(cullNormal));
         if (dt>0.f)
            continue;

         // draw face with lighter color
         gContext.mDrawList->AddConvexPolyFilled(faceCoordsScreen, 4, directionColor[normalIndex] | 0x808080);
      }
   }

My version of ImGuizmo is not in sync with upstream anymore, so I may be missing other small changes, but as I recall those where the changes I had to make.

@vamidi
Copy link

vamidi commented Jul 7, 2019

Amazing! I will take a look at it! Thanks!
@jdumas, I tried it out and I think I am doing something wrong? How does it works actually? maybe I can try messing around with variables.
https://gyazo.com/8a8e9649f60de6ebeb4c31f3f3c17927

this needs to be replaced with your piece right?
if (dt >= bestDot) { bestDot = dt; bestAxis = i; bestAxisWorldDirection = dirPlaneNormalWorld; } if (dt >= 0.1f) { axes[numAxes] = i; axesWorldDirections[numAxes] = dirPlaneNormalWorld; ++numAxes; }

@vamidi
Copy link

vamidi commented Jul 24, 2019

@jdumas based on the comment above is it still possible to provide an answer :D ? I notice if I rotate an object it starts to come, but do I need to rotate things beforehand?

@Batres3
Copy link
Contributor

Batres3 commented Nov 23, 2023

I made a pull request implementing this as best I could, it seems to work fine if anyone wants to try it. It is on a branch of my fork of ImGuizmo.

CedricGuillemet added a commit that referenced this issue Sep 20, 2024
Added 2D support through axis masking (Issue #49)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants