So, Lets understand the problem or the issue I am trying to resolve. Lets say I have two mesh in the viewport as in the image.
First mesh is a square with 2 loop cuts or 3 faces. And second is square with 4 faces. So I unwrap, and get UV of 1st as a perfect square and second one with 2 islands which is 1 face and other is 3 faced island. But lets say I somehow misplaced one face from 1st mesh UV island and it got shifted like in the image.:
Is there a way I can detect that my mesh has that UV face splitted or have 2 island instead of one? But second UV mesh is correct so it doesn't get selected with the script because it has seams to mark it having split faces. As it can be bit troublesome if the no. of UV islands get high and gets time consuming. The result I am kind of wanting to get is like this , so it selects the UV islands which shouldn't have been splitted.
Thank you.
-
I think you need to unwrap the model using the marked seams or calculate the number on your own. Then you need to compare this number(X) with the actual number of UV islands (Y) (https://blender.stackexchange.com/questions/48827/how-to-get-lists-of-uv-island-from-python-script). If X equals Y then everything is fine. If you want to select the split UV island then you additionally need to compare the results. Could be time consuming... – Blunder Jun 05 '22 at 19:41
-
Another way is to select a single face in the UV editor, do ops.uv.select_linked(), then check if all faces are selected or not. But controlling the UV editor from Python is a huge pain in the ass... – scurest Jun 05 '22 at 20:17
1 Answers
You can use a loop's link_loop_radial_next to get the equivalent loop on the neighboring face. Assuming manifold geometry - each edge builds exactly 2 faces - or at least assuming no edge builds more than 2 faces, if there's another face, and so another radial loop - it goes in the opposite direction, and so matching this loop's start with other loop's end, and this loop's end with other loop's start will reveal if the UVs were moved:
import bpy, bmesh
from bpy import context as C
tolerance = 0
bpy.ops.mesh.select_all(action='DESELECT')
me = C.object.data
bm = bmesh.from_edit_mesh(me) # assuming Edit Mode
uvl = bm.loops.layers.uv['UVMap']
for face in bm.faces:
for loop in face.loops:
neighbour_loop = loop.link_loop_radial_next
if loop is neighbour_loop or loop.edge.seam:
# edge.is_boundary = True, there's no neighboring face
continue
loop1_start_uv = loop[uvl].uv
loop1_end_uv = loop.link_loop_next[uvl].uv
loop2_start_uv = neighbour_loop[uvl].uv
loop2_end_uv = neighbour_loop.link_loop_next[uvl].uv
vert1_uv_distance = (loop1_start_uv - loop2_end_uv).length
vert2_uv_distance = (loop1_end_uv - loop2_start_uv).length
if vert1_uv_distance > tolerance or vert2_uv_distance > tolerance:
# edge is between connected faces, but is too far away in UV
loop.edge.select = True
The result of running the script on Susanne:
Edit: added the or loop.edge.seam check and a seam on X=0 (keep in mind that's not the seam originally used to unwrap Susanne):
- 36,563
- 3
- 30
- 99
-
Yeah thats really the best approach and it is exactly what I needed. so my models always have seams but sometimes some island get split during packing or something, so figuring out island which are by mistakenly split, instead of only split from the seams. Your code gives clear selection of the faulty Island. Thank you. Really appreciate the approach and things I got to learn. I shouldn't ask but can you recommend a good course for python scripting youtube one's aren't that good if you wanna go into good coding for blender functions and opertaors. – NamanDeep Jun 06 '22 at 04:50
-
1@NamanDeep https://blender.stackexchange.com/users/15543/batfinger?tab=answers https://www.youtube.com/playlist?list=PLa1F2ddGya_8acrgoQr1fTeIuQtkSd6BW https://www.youtube.com/watch?v=XqX5wh4YeRw https://studio.blender.org/training/scripting-for-artists/ https://github.com/njanakiev/blender-scripting
https://docs.blender.org/api/current/ https://docs.blender.org/manual/en/latest/advanced/scripting/addon_tutorial.html https://docs.blender.org/api/current/info_quickstart.html https://docs.blender.org/api/current/info_overview.html
– Markus von Broady Jun 06 '22 at 09:56 -
Hello there! I have faced a bit of issue with the code you wrote above In the line " bm = bmesh.from_edit_mesh(me) # assuming Edit Mode uvl = bm.loops.layers.uv['UVMap'] " I want to change the selecting UV method to be active uv, rather than uv named as UVMap. I couldn't find a way since it was made in ops method, if you could suggest some edit, would be helpful – NamanDeep Jul 30 '22 at 15:27
-
1@NamanDeep either
uvl = bm.loops.layers.uv[me.uv_layers.active.name]oruvl = bm.loops.layers.uv[me.uv_layers.active_index]should work – Markus von Broady Aug 02 '22 at 12:03 -
1Thank you! You are the best, Appreciate the help. Sorry to bother ya haha, But it solved the problem. Again thank you! – NamanDeep Aug 03 '22 at 16:26

