Skip to content

Added mirror and flip functionality to Layer Special Menu#363

Open
uraniumcrystalsmaster wants to merge 3 commits into
ucupumar:masterfrom
uraniumcrystalsmaster:master
Open

Added mirror and flip functionality to Layer Special Menu#363
uraniumcrystalsmaster wants to merge 3 commits into
ucupumar:masterfrom
uraniumcrystalsmaster:master

Conversation

@uraniumcrystalsmaster
Copy link
Copy Markdown

@uraniumcrystalsmaster uraniumcrystalsmaster commented Feb 14, 2026

Closes #347. Adds two new operators on the right part of the layer special menu under resize and invert for mirroring/flipping texture data across an axis using 3D mesh geometry.

Mirror (wm.y_mirror_image): Overwrites the target side's texture with the source side's.
Flip (wm.y_flip_image): Swaps texture data between both sides.

The user selects an axis (X/Y/Z) and in addition, for mirroring, which side to treat as the source. For perfectly symmetrical meshes, face correspondence is found by mirroring vertex positions and matching via KDTree. For asymmetric meshes, a second pass is used to find the nearest source faces by center distances and interpolate texture data using barycentric coordinates. Expensive operations use numpy for good performance.

@ucupumar
Copy link
Copy Markdown
Owner

Thanks for the PR! I'll test it later 👍

@ucupumar
Copy link
Copy Markdown
Owner

I'm not sure if I use it correctly or not, but it doesn't work when I tried the mirror operator like the video below.

0001-0331.mp4

This is the file to test
501_2D_mirror_test_0.zip

@uraniumcrystalsmaster
Copy link
Copy Markdown
Author

I made a faulty assumption: The mirror/flip functionality was not operating on the modifier (wrench tab) transformed object. It was operating on the original object. The best solution I could think of is to use the object's final rendered state for the mirror/flip functionality as there are four modifiers which have additional render settings (sub. surf., ocean, screw, and multi. res.). This ensures the image/paint doesn't look incorrectly mirrored/flipped during rendering unless the render settings of the modifier are changed after. I have implemented the solution completely and will update the PR tomorrow.

@ucupumar
Copy link
Copy Markdown
Owner

Thanks! Just in case you didn't know, you can get the mesh with applied modifier directly in python ( https://blender.stackexchange.com/questions/7196/how-to-get-a-new-mesh-with-modifiers-applied-using-blender-python-api)

Anyway, I haven't read the code yet, but why you need the mesh data when you only want to mirror the 2d image, isn't numpy enough for this kind of operation?

@uraniumcrystalsmaster
Copy link
Copy Markdown
Author

Why you need the mesh data when you only want to mirror the 2d image, isn't numpy enough for this kind of operation?
Because UV maps are not always symmetrical with the image texture. Notice how Suzanne's UV map is cut into pieces in many different regions instead of being identical at opposite sides of the image. With a basic image mirroring, the user would have to do a lot of extra work warping the UV maps to fit the mirrored image and UV packed objects would need lots of extra editing work. So instead of the feature mirroring the image, the feature copies pixels in 2D texture space, but the source-to-destination mapping is driven by the 3D geometry and UV layout.

Also, the old face texture transfer of the old mirror/flip when faces were not perfectly symmetrical would create artifacts that looked like severe pixelization because it was copying faces. The new algorithm copies individual pixels and has almost no artifacts.

@ucupumar
Copy link
Copy Markdown
Owner

I see, I'm sorry, I thought it was just a simple image flip at first. This is apparently a very sophisticated operator. I tested this again with the previous file and even non-mirrored UV, and it all works! Nice!

But it seems it doesn't produce margin pixels around UV islands, like in the video below.

0001-0529.mp4

Sample file: 501_2D_mirror_test_1.zip

Also, the projected image is a bit grainy. Is there any way to work around these issues? Maybe sample options or something?

One more thing, the operator also doesn't work in UDIM tile outside the number 1001. I think that's fine, but adding a warning or an error would be okay for now.

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

Successfully merging this pull request may close these issues.

2D paint mirror

2 participants