0
$\begingroup$

newbie here.

I have a very specific question. I’ve done a ton of research and didn’t find anything useful. So, as the Title suggests, I’m trying to export UV layout without all the edges inside of the UV Islands. Coming from 3DS Max, this is an essential part of my workflow and it’s missing from Blender’s built-in capabilities.

What I’ve tried:

  1. I tried hiding the boundary loops and dissolving all verts and edges in the middle. This kind of works but still messes up some of the objects that have smaller parts with fewer verts. Also - it’s really slow, especially with higher-poly objects. Tried a few sub-methods doing this and non of them work properly.

  2. I also tried exporting the standard UV Layout, then importing it into Fotoshop → Layer fill = 0, then stroking it. This method works great except for cases that have UV islands that only have their border edges overlaped, but are still separate islands.In these cases the stroke can’t detect the edge between the 2 islands so it’s unusable for my situation. There are some cases in the workflow where uv islands must be touching (not overlaping).

  3. I also tried using the Fill option in the texture paint with the object selected and a brand new texture created. This sort of works but has its own set of problems and in the end the result is quite bad.

  4. Since my workflow includes a DXF file with every object, I tried the DXF import-export addons. That was a big train wreck, they are quite buggy and even if they weren’t, I can’t find a way to use the imported DXF to export a PNG or JPG file to use as a UV Layout.

  5. I also went through some method of creating a Python program that imports a DXF file, cleans it up and exports it in JPG file. I think I kind of found a way to do all this (so I’ll be able to implement it into a blender script and expose it as a button) but the problem is that in some cases I need to also be able to import .eps files AND perform some boolean operations and then export them into JPG file as well and this is where I think it all gets extremely complicated for my level.

  6. I looked at the .py file responsible for the UV Layout export. It gets the data for every face and its surrounding edges and prints that. So if there’s a way to “trick” this and rewrite it so that it doesn’t get the data for every edge but just the border edges (the outlines of the UV islands) - this could be an actual solution. So if anyone has any ideas - I’m all ears!

  7. The last thing is - I tried examining the Render UVW Template in Max. Now, things in Max are significantly differet. First, when you put an Unwrap UVW modifier, it automatically detects and visualises all UV boundary edges (in green). With that said, I understand that Max reads these as “Seam” edges and I already have a method to automatically set all UV boundary edges as seams in Blender so the question that remains is how to only export them, without all the other edges. The second difference is the “Render” part of this option. I’m not really sure exactly how this thing works and I can’t find any actual information, but if it uses Rendering - this could be another way to do it in Blender. Somehow detecting all UV edge bounds and put a 2-3 pixel stroke on then and then save the image as a PNG or a JPG file.

At the moment I have a workaround that actually uses Illustrator. If I export the UV Layout in Blender (fill = 0) as a .eps file and then import it into Illustrator. I can then use boolean operations in Illustrator to get rid of all the extra edges in the middle and then export a PNG or a JPG file. The problem is that it’s a workaround and uses an additional software. The other problem is that with higher-poly meshes this could be slow. It is acceptable however IF I can do it all in Blender.

So, a bit long, but there it is. If you have ANY other suggestions or ideas on how I can improve some of the methods above so that it actually works - please share your thoughts. Thank you in advance!

P.S: In order to clarify I'm giving an example. So with the stroke method you can get this:enter image description here

But instead, I'd like to get the actual result I would get in 3ds Max: enter image description here

This is the code for the edge selection process. It's fully commented:

import bpy
import bmesh

def export_uv():
    
    op = bpy.ops
    
    # Turn on UV Sync mode
    sync_mode = bpy.context.scene.tool_settings
    if sync_mode.use_uv_select_sync == False:
        sync_mode.use_uv_select_sync = True
    
    # Select all faces
    op.mesh.select_all(action="SELECT")
    
    # Switch context window to UV Editor
    bpy.context.area.type = 'IMAGE_EDITOR'
    bpy.context.area.ui_type = 'UV'
    
    # Set mesh seams according to island setup in the UV Editor
    op.uv.seams_from_islands()
    
    # Switch context window to 3D view window
    bpy.context.area.type = 'VIEW_3D'
    
    # Select all faces
    op.mesh.select_all(action="SELECT")
    
    # Convert the selection to only the borders
    op.mesh.region_to_loop()
    
    # Mark the new selection as Seams
    op.mesh.mark_seam()
    
    # Deselect all faces
    op.mesh.select_all(action="DESELECT")
    
    # Go to OBJECT mode
    op.object.mode_set(mode='OBJECT')
    
    # Itterate through the edges of the object
    for edge in bpy.context.object.data.edges:
        if edge.use_seam == True:
            edge.select = True # Select the first found SEAM edge
            op.object.mode_set(mode='EDIT') # Go to Edit mode
            op.mesh.select_mode(type='EDGE') # Switch to Edge selection
            op.mesh.select_similar(type="SEAM") # Select all the edges that are seams
            break

export_uv()
$\endgroup$
12
  • 1
    $\begingroup$ "that have UV islands that are “glued” to each-other." If they're glued together in the UV editor, they're not separate UV islands. It sounds like you're actually after something other than the edges describing UV islands. Maybe you can clarify this in your question? $\endgroup$
    – Nathan
    Feb 25 at 18:41
  • $\begingroup$ I'll correct that. I meant that ONLY the border edges are overlaping, but the two islands are still separate. In these cases you can still link-select them separately since they aren't merged $\endgroup$
    – Aleks K.
    Feb 25 at 21:14
  • 2
    $\begingroup$ At a first glance, I think you should be able to export the current selection by replacing uvs = tuple(tuple(uv.uv) for uv in uv_layer[start:end]) by uvs = tuple(tuple(uv.uv) for uv in uv_layer[start:end]) if uv.select) (line 218) in the exporter. If so, you just have to find a way to select the outline of each island. Alternatively, it should be straight forward and just a few lines to save the selection to a svg file I guess, open source and well documented: w3.org/TR/SVG11 $\endgroup$
    – brockmann
    Feb 26 at 8:18
  • 1
    $\begingroup$ Kind of? Can you share your code how to select the outlines of the islands? ... and ideally your uv's to test? $\endgroup$
    – brockmann
    Feb 26 at 10:02
  • 1
    $\begingroup$ I don't see any reason why not. Also, should be possible to find the outlines using python without any selection in the UV editor / 3d view beforehand. Can you share the current state of your code? $\endgroup$
    – brockmann
    Feb 26 at 10:58
4
$\begingroup$

Mesh 'n Freestyle

enter image description here

Here is a very quick'n'dirty proof of concept.

Make a mesh from our mesh of interest's UV's as demonstrated here How to get data and edit it on UV map edges? . For this one have used numpy to quickly make the mesh. Moved the origin to (0.5, 0.5).

Removed doubles and marked boundary edges selected with bmesh, then as freestyle edges. How do I add a Freestyle Line-Style to a Freestyle Line-Set using python script?

import bpy
import bmesh
import numpy as np

ob = bpy.context.object
me = ob.data
uv_layer = me.uv_layers.active
# get uv values
uvs = np.empty((2 * len(me.loops), 1))
uv_layer.data.foreach_get("uv", uvs)
# select 
x, y = uvs.reshape((-1, 2)).T

z = np.zeros((len(x)))

uvme = bpy.data.meshes.new("UVMesh")
verts = np.array((x, y, z)).T
verts -= (0.5, 0.5, 0)
faces = [p.loop_indices for p in me.polygons]

uvme.from_pydata(
        verts,
        [],
        faces
        )
        
bm = bmesh.new()
bm.from_mesh(uvme)
bmesh.ops.remove_doubles(
        bm,
        dist=1e-4,
        )
for e in bm.edges:
    e.select = e.is_boundary
    
bm.to_mesh(uvme)

for e in uvme.edges:
    e.use_freestyle_mark = e.select
bpy.context.collection.objects.link(bpy.data.objects.new("UVMesh", uvme))

Checked silhouhette in freestyle settings. Rendered with an ortho camera, directly above origin.

Freestyle SVG Exporter

$\endgroup$
1
  • $\begingroup$ Can you comment the code above step by step? I can understand most of it but not all of it and I would like to know exactly what does what. Also would it be ok if you posted a version that's not using numpy? The last time I used numpy in a similar way it all worked fine, but the next day Blender started giving me some errors about it not being able to create an array and then later crashed. In the mean time I'll tell you guys how I did it and it works in all tested cases. Takes about 7-10 seconds with meshes with 400 000 faces. $\endgroup$
    – Aleks K.
    Feb 26 at 22:09
0
$\begingroup$

So the method I ended up using (for now) is a bit unexpected.

  1. I use the method that's described in the question above to select all boundary edges.
  2. After that I use Split -> Faces by edges. What this does is "unweld" ot "unmerge" the selected parts (which in this case are the boundary edges of all the UV islands).
  3. Then, when these are all separated I use select all -> boundary loops to select all the edges in the viewport and then use extrude.
  4. After extruding -> invert selectin and then delete FACES ONLY.
  5. Now you can normally export a UV Layout and it'll all work out.

If you have any concerns about all the manipulation of the object (separating parts, deleting faces, etc) you can do what I did and write in the script to first make a duplicate of the object and after exporting the UV Layout you just delete the copy.

P.S: It would however, be great if we found a way to store all boundary edges of the UV islands into a variable and then after that make Blender display only these edges in the UV Editor (with sync mode turned off). If I can do this, then I can add to the original UV_Layout .py file and make this method appear as like a checkbox for example so that with normal UV Layout exports you'd have the option to only export the boundary edges.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.