[GSOC 2023] Progress on perspective transformation | Haiku Project

While the change request to add reference images was being reviewed, I started working on ticket #18415, which suggests adding shear and perspective transformations. I decided to implement the perspective transformation since I still need to figure out which way I’m going to implement the shear transformation. Hopefully the experience in implementing the perspective transformation will give me information that will help me decide how to implement the shear transformation.


This is a companion discussion topic for the original entry at https://www.haiku-os.org/blog/zardshard/2023-06-19_gsoc_2023_progress_on_perspective_transformation
9 Likes

Another functionality that would serve a similar purpose would be to add support for drawing on a plane in the same way as how 3D CAD works and let Icon-O-Matic handle the perspective automatically.

In the article example there is a box with 3 planes (top, front, side) all with a round shape. Instead of manually having to create the perspective thru shearing, a perfectly round circle could be drawn on one of the planes in 2D and Icon-O-Matic would handle the perspective automatically.

That would be nice, though it would be very hard to implement since it would require implementing 3d shape support.

The method I’m planning to implement would require you to drag the four red points shown in the left image over to the four red points shown in the right image.

2 Likes

Yes, it is a big change.

The problem with manually changing the perspective is as soon as you go from a plain 2D drawing (as in the left rectangle) and skew it (as in the right box) you can no longer easily make changes and know that the perspective is correct. A good reference image with guidelines, or better up perspective guidelines will help.


An even more advanced idea I had is to add support for automatic perspective on planes to the hvif icon format. In the Patchbay icon example it would mean you would only have to draw the din-sockets once in 2D and have them applied to the three planes with the correct perspective.

Indeed, I’m planning to let the perspective transformation work with reference images.

Also, being able to toggle the perspective transformation on/off would help since it would allow switching between the flat view and the perspective view. I created a ticket with this idea.

1 Like

That would be helpful.

1 Like

Why? It will work as any of the other geometrical transformations that already exist.
You can draw the paths in a frontal view, assing them to a shape, or shapes, select the shapes, transform them to the size/rotation/perspective you need, and then, whatever modification you do to the initial paths gets the same transformation automatically applied.
This is how it works already, the only difference is that perspective transformation will let us achieve results that were previously not possible, costly or really laborious, like… having a correct perpective :upside_down_face:
For the “correctness” part of the problem, it is up to the correctness or incorrectness of the transformation applied, for that the reference perspective guidelines will be really useful.
Given that we now have reference layers, half the problem is already solved :smiley:

1 Like

Yes, it doesn’t look like being able to toggle perspective would be very useful right now. Maybe the story will change if/when support for layers are added to Icon-O-Matic.

I needed a TransformerContainer. Its code would have looked the exact same as PathContainer, ShapeContainer, and StyleContainer. So I planned to make one general Container class. This quickly led down a rabbit hole of many classes that have nearly identical code…

  • AddShapesCommand, AddStylesCommand, AddStylesCommand, and AddTransformersCommand
  • RemovePathsCommand, RemoveStyleCommand, RemoveShapesCommand, and RemoveTransformersCommand
  • MovePathsCommand, MoveStylesCommand, MoveShapesCommand, and MoveTransformersCommand

And maybe more.

So I can either just make a single Container class like I was originally planning to, or merge all of these classes into Container, AddItemsCommand, RemoveItemsCommand, and MoveItemsCommand. I’ve decided to go with the latter option.

2 Likes

I put the code I currently have into a Gerrit change request. Is it going in the right direction?

Update: Oof. I accidentally permanently deleted my Haiku’s disk image. I lost all of my progress on the perspective transformation and the refactoring and then some :cry:

I also lost my Haiku disk image recently, thankfully I had a backup that I could restore from and only lost my most recent work. Since then I’ve started backing up regularly. I got a cheap 2TB spinning rust hard drive and a cheap USB adapter, plugged it in and let it do its thing. I have peace of mind that I won’t have to worry about losing any more work.

1 Like

I’m very sorry to hear… :pensive: Though you know what? It happens to the best of us!

In the future, I would recommend periodically uploading your own work to a git repository to have backups. (Like on GitHub for example, you can fork Haiku’s repository and upload your temporary work to a separate git branch in your own repository.)

Given that you posted this a week ago, maybe this advice is coming a bit late. :sweat_smile:

I even have a nice workflow for easily syncing my branches with Haiku’s master branch and pushing to Gerrit when the time comes. :slight_smile:

1 Like

Actually, I posted it today :sweat_smile:. I couldn’t make >3 posts in a row so I had to edit the week old post. At least I still have that Gerrit change request lying around, so, I have a bit of progress saved.

2 Likes

At long last, I finished the refactoring. It is now ready for review. In all, it removes 1,300 lines from the codebase.

13 Likes

Nice work, well done! :ok_hand:

1 Like

At long last, I have the basics working.

One part that needs to be done yet is to make styles obey the transformation as well. In the image, you can see the gradient transitions from white to gray in a vertical line. That line should be following perspective. Fixing that will also make reference image follow perspective if transformed.

In its present form, perspective transformations aren’t very useful, except for reference images. Usually, if you want to apply perspective to something, you will want to apply perspective to multiple shapes at the same time. Currently, you will have to recreate the perspective transformation for each shape that you want transformed. This is laborious and makes the resulting HVIF file bigger than it has to be. There are two solutions that I can think of:

  1. Add support for layers. Then, you can add a single perspective transformation to the layer and let it affect every shape in the layer. This would require updating the HVIF format.
  2. Add support for the same perspective transformation to be applied to multiple shapes. This would make transformations similar to shapes and styles, in that they can be reused in multiple shapes. This would also require updating the HVIF format.

Even if I don’t decide to tackle the problem yet, perspective transformations would be useful for putting reference images into/out of perspective.

11 Likes

Wonderful work!

Can I order a plate of each three? :smiley:
Im such a glutton :stuck_out_tongue_winking_eye:

Even if internally they work the same, each of the three serves a slightly different purpose.

This last weeks I have been musing about @Null 's idea for perspective planes, and I have to retract myself and concede that it was indeed a good idea.

Even started to write a lengthy response discussing the possibilities, but the draft got lost after some server problem with Discuss and was too lazy to write it again.
Apart from that I didn’t wanted to stress you out after losing part of the progress, messing with exotic ideas, but now that you mention them yourself… :smiley:

Apart from the basic perspective transformation that can be applied to any path or shape at any moment, Layers was one of the possibilities and a new item called Planes was the other.

BTW, layers are a worthy addition by themselves just by the fact that they let you select a bunch of shapes in one go instead of having to select them manually every time, they’re invaluable to organize elements that go together, even if nothing else could be done with them.
Also, they can exist inside the Shapes list, so no need to take extra room for them in the UI:

Layer:
-Shape
-Shape
Layer:
-Shape
-Shape
-Shape

So I’ll say, keep 'em coming either way!

But lets consider them in the actual context of a transformation applied to a layer.

Pros:

  • transforming a bunch of shapes maintaining the geometrical relationship between them
  • possibility of adding new shapes after (or even before) the initial transformation
  • each shape can get fine-tuned individually

Cons:

  • for repeated elements the shapes need to be duplicated, increasing the filesize cost

The other one, Planes, is how I imagined Null’s idea could be implemented without needing to implement 3d features for it. As it will be a new item alongside Paths, Shapes and styles, with its own list, a bit of room will need to be made in the UI.

Pros:

  • the same Plane be applied to more than one shape or layer
  • (here comes the special part from Null’s idea) each shape or layer could have more than one Plane applied, in doing so, it appears in each of the planes with the corresponding projection
  • less filesize cost in having a shape or layer appearing more than one time without duplicating them

Cons:

  • it doesn’t let each ‘virtual copy’ of the original shapes to be fine-tuned as they are not duplicates

I left a copy of this in the ticket so the info doesn’t get too scattered
https://dev.haiku-os.org/ticket/18415

3 Likes

Nice ideas. No idea if I will be able to implement them all, but, while we’re dreaming…

There is the possibility of completely redesigning the UI around layers. The shape, style, and transformer menus would disappear leaving just the layers menu. It would look like

  • Layer 1
    • Shape 1
      • Path 1
      • Path 2
      • Style 1 :link:
      • Transformation 1
      • Transformation 2
    • Shape 2
      • Path 3
      • Style 1 :link:

Here, you can see that Style 1 is shared across two shapes.

This also lets you implement the idea of planes without taking up more space in the UI.

  • Layer 1 :link: (hidden)
    • Shapes to make one face of patchbay’s icon
  • Layer 2
    • Layer 1 :link:
    • Perspective transformation 1
  • Layer 3
    • Layer 1 :link:
    • Perspective transformation 2
  • Layer 4
    • Layer 1 :link:
    • Perspective transformation 3

That rearrangement would leave so much free space in the UI, I wouldn’t know what to do with it all :smile:

I also mirrored this comment on ticket #18415. Maybe we should split this line of discussion into a separate ticket, since this one could be closed once the perspective and shear transformations are implemented.

1 Like

At some point for too complex things, people should stop using Icon-O-Matic and turn to Wonderbrush, which already does layers and a lot more things.

I think the idea of Icon-O-Matic is to do only simple things that directly translate into the vector icon format, which is intentionally limited because it is, more or less, an “export” format. We should probably keep this in mind and not go too far with extra features.

Layers are useful when editing an image, but Icon-O-Matic maybe shouldn’t be used at that point. Only later, when you know what the final image should look like and you’re trying to fit it into an icon as small as possible.

3 Likes

Now there’s a more realistic, achievable vision of what Icon-O-Matic should be :joy:. Icon-O-Matic could be a complete Inkscape-but-for-Haiku, but that would probably never get finished.

That being said, layers do have some utility in making icons smaller. One example is Patchbay’s icon, where layers would make it unnecessary to repeat the same shapes again and again. Regardless, I’m not if I’ll ever get around to adding layers, since there are many other things to do.

1 Like