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

Add distance-preserving alignment #33

Open
wants to merge 23 commits into
base: master
Choose a base branch
from

Conversation

strace44
Copy link

First, thanks for the addon! I've found it quite useful in manipulating UV unwrapping.

After using this addon a few times, I realized that what I really wanted to do isn't implemented: aligning vertices to the U or V axis while preserving the distance between them in UV space. As far as I can tell, the existing code paths use BMLoopUV objects to move vertices in UV space, but I needed to access the parent BMLoop objects to walk the edges between vertices. I didn't see a way to access the BMLoop object from a BMLoopUV, so I had to build entirely separate data structures to map vertex coordinates to BMLoops (see 0c9f0c5). (I consider myself very fluent in Python, and I've written a lot of Python code in the last decade or so, but this is my first exposure to the Blender API.)

The new code in this PR requires NumPy and Python 3.7 or newer -- Blender 2.82 on Windows already includes both, so this version of the addon can be installed and used as-is. On Ubuntu, I had to install the python3-numpy system package, which is now described in the README (ebdad46).

This functionality uses two BFS graph traversals to find a linear ordering of vertices:
cube-unwrap-align

Vertices can overlap in both U and V coordinates; this is handled properly:
cylinder-unwrap-align

Disconnected sets of vertices are aligned independently:
disconnected

If it's not possible to find a simple linear ordering of selected vertices, the addon exits with an error:
no-branching

I also modernized the code a bit and fixed some SyntaxWarnings that are shown by Python 3.8 -- for example, None is usually the only constant that should be compared against with identity and not equality. There is now a math.isclose method that handles the hand-crafted comparison of vertex positions, too. The code formatting was inconsistent in a lot of places, and I cleaned that up with the black formatter.

I understand if you don't want to merge this due to the not-strictly-necessary changes included in this PR, but I couldn't resist making small cleanups while stepping through the code with the debugger to get a feel for the Blender API.

Thanks again for the addon; it was great as an introduction to the Blender API!

* Don't compare against numeric constants with 'is' -- those should be checked
  for equality and not identity
* Remove explicit comparisons against True and False

Also remove some redundant parentheses
The previous data collection/manipulation done in lists_of_verts tracks
BMLoopUV objects, and as far as I can tell, these don't store any references
to the corresponding BMLoops. I need to perform a graph traversal of the
selected UV vertices, which necessitates using the link information in the
BMLoop objects -- so build new mappings storing BMLoops.
I don't know why I thought it was necessary or appropriate to traverse loops
in their *entirety* to find the selected neighbors of a vertex in UV space,
but this definitely isn't appropriate. We just need to look at the previous
and next links.
The direction of vertices isn't stable; successive runs of this flipt he
directionality of the vertices. This is worth fixing, but not for my immediate
usage.
Quick-and-dirty heuristic: choose the vertex order with minimum total L1
distance
Sequence doesn't imply mutability.
Also deduplicate code that chooses new coordinate directions based on minimum
total L1 distance
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.

1 participant