The UV grid on the left hand side is what my script currently does. Here is the code:
def _process_shell_uv(self, object):
mesh = object.data
bm = bmesh.new()
bm.from_mesh(mesh)
bm.verts.ensure_lookup_table()
bm.faces.ensure_lookup_table()
uv_layer = bm.loops.layers.uv.verify()
verts = bm.verts
vert_groups = []
for vert_idx in self.shell_verts['OuterShell']:
inc = 0
verts_in_loop = []
for idx in range(0, 64):
verts_in_loop.append(vert_idx + inc)
inc += len(self.shell_verts['All'])
vert_groups.append(verts_in_loop)
a_y_co = 1
b_y_co = 1
c_y_co = 0
d_y_co = 0
for a, b in zip(vert_groups, vert_groups[1:]):
faces_to_map = []
a_x_co = 0
b_x_co = 1
c_x_co = 1
d_x_co = 0
for idx in range(len(a)):
if idx == len(a) -1:
x = 0
y = 0
else:
x = idx+1
y = idx+1
for face in bm.faces[:]:
if verts[a[idx]] in face.verts[:]\
and verts[b[idx]] in face.verts[:]\
and verts[a[x]] in face.verts[:]\
and verts[b[y]] in face.verts[:]:
faces_to_map.append(face)
for face in faces_to_map:
lengths = [edge.calc_length() for edge in face.edges[:]]
face.loops[0][uv_layer].uv = (a_x_co, a_y_co)
face.loops[1][uv_layer].uv = (b_x_co, b_y_co)
face.loops[2][uv_layer].uv = (c_x_co, c_y_co)
face.loops[3][uv_layer].uv = (d_x_co, d_y_co)
a_x_co += 1
b_x_co += 1
c_x_co += 1
d_x_co += 1
a_y_co += 1
b_y_co += 1
c_y_co += 1
d_y_co += 1
mesh.update()
bm.to_mesh(mesh)
bm.free()
return
I am essentially taking each face and making a 1x1 UV mapping for it. Each vertical strip of the object is laid out horizontally, like this:
But now what I want to do is instead of each face being a 1x1 square in the UV map, I want it to be related to the original size of the faces; effectively I want to unwrap the entire thing to a flat plane, keeping all of the relative length differences. But I don't know what to do in my code to fix it.
The desired result is something like this:

Where each vertical strip is more or less the same according to the geometry. Here is a closer look:
I'm trying to automate a UV unwrapping process so that all of my cylindrical objects follow this kind of format, and more or lesss give me the same result each time. I will add a texture afterwards and have manual control over the scale in a custom addon I am building.



self.shell_verts. In principle, your problem is simple: if the UV map should always consist of X/Y aligned grid, and the width of the cells is already correct, you can calculate the height of each cell ash = face.calc_area() / sum((f.calc_area() for f in column_of_faces))– Markus von Broady Sep 05 '21 at 11:18