add length average option to 'Follow Active Quads' unwrap, gives nicer results.
authorCampbell Barton <ideasman42@gmail.com>
Fri, 4 Jan 2013 07:57:33 +0000 (07:57 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Fri, 4 Jan 2013 07:57:33 +0000 (07:57 +0000)
release/scripts/startup/bl_operators/uvcalc_follow_active.py
source/blender/editors/mesh/mesh_navmesh.c

index 727c4ad739f4b8a0a3aad4f45d53abdca9fb0c3d..d870ef963eaec37290771db88fb6311b93ab5c57 100644 (file)
@@ -26,6 +26,7 @@ from bpy.types import Operator
 
 
 def extend(obj, operator, EXTEND_MODE):
+    
     import bmesh
     me = obj.data
     # script will fail without UVs
@@ -46,12 +47,12 @@ def extend(obj, operator, EXTEND_MODE):
 
     faces = [f for f in bm.faces if f.select and len(f.verts) == 4]
 
-    for f in faces:
-        f.tag = False
-    f_act.tag = True
-
-
     # our own local walker
+    def walk_face_init(faces, f_act):
+        for f in faces:
+            f.tag = False
+        f_act.tag = True
+    
     def walk_face(f):
         # all faces in this list must be tagged
         f.tag = True
@@ -73,6 +74,30 @@ def extend(obj, operator, EXTEND_MODE):
             faces_a, faces_b = faces_b, faces_a
             faces_b.clear()
 
+    def walk_edgeloop(l):
+        """
+        Could make this a generic function
+        """
+        e_first = l.edge
+        e = None
+        while True:
+            e = l.edge
+            yield e
+
+            # don't step past non-manifold edges
+            if e.is_manifold:
+                # welk around the quad and then onto the next face
+                l = l.link_loop_radial_next
+                if len(l.face.verts) == 4:
+                    l = l.link_loop_next.link_loop_next
+                    if l.edge is e_first:
+                        break
+                else:
+                    break
+            else:
+                break
+
+
     def extrapolate_uv(fac,
                        l_a_outer, l_a_inner,
                        l_b_outer, l_b_inner):
@@ -119,7 +144,9 @@ def extend(obj, operator, EXTEND_MODE):
         l_a_uv = [l[uv_act].uv for l in l_a]
         l_b_uv = [l[uv_act].uv for l in l_b]
 
-        if EXTEND_MODE == 'LENGTH':
+        if EXTEND_MODE == 'LENGTH_AVERAGE':
+            fac = edge_lengths[l_b[2].edge.index][0] / edge_lengths[l_a[1].edge.index][0]
+        elif EXTEND_MODE == 'LENGTH':
             a0, b0, c0 = l_a[3].vert.co, l_a[0].vert.co, l_b[3].vert.co
             a1, b1, c1 = l_a[2].vert.co, l_a[1].vert.co, l_b[2].vert.co
 
@@ -140,6 +167,40 @@ def extend(obj, operator, EXTEND_MODE):
                        l_a_uv[2], l_a_uv[1],
                        l_b_uv[2], l_b_uv[1])
 
+    # -------------------------------------------
+    # Calculate average length per loop if needed
+
+    if EXTEND_MODE == 'LENGTH_AVERAGE':
+        bm.edges.index_update()
+        edge_lengths = [None] * len(bm.edges)
+
+        for f in faces:
+            # we know its a quad
+            l_quad = f.loops[:]
+            l_pair_a = (l_quad[0], l_quad[2])
+            l_pair_b = (l_quad[1], l_quad[3])
+
+            for l_pair in (l_pair_a, l_pair_b):
+                if edge_lengths[l_pair[0].edge.index] is None:
+
+                    edge_length_store = [-1.0]
+                    edge_length_accum = 0.0
+                    edge_length_total = 0
+
+                    for l in l_pair:
+                        if edge_lengths[l.edge.index] is None:
+                            for e in walk_edgeloop(l):
+                                if edge_lengths[e.index] is None:
+                                    edge_lengths[e.index] = edge_length_store
+                                    edge_length_accum += e.calc_length()
+                                    edge_length_total += 1
+
+                    edge_length_store[0] = edge_length_accum / edge_length_total
+
+    # done with average length
+    # ------------------------
+
+    walk_face_init(faces, f_act)
     for f_triple in walk_face(f_act):
         apply_uv(*f_triple)
 
@@ -162,8 +223,10 @@ class FollowActiveQuads(Operator):
             name="Edge Length Mode",
             description="Method to space UV edge loops",
             items=(('EVEN', "Even", "Space all UVs evenly"),
-                   ('LENGTH', "Length", "Average space UVs edge length of each loop")),
-            default='LENGTH',
+                   ('LENGTH', "Length", "Average space UVs edge length of each loop"),
+                   ('LENGTH_AVERAGE', "Length Average", "Average space UVs edge length of each loop"),
+                   ),
+            default='LENGTH_AVERAGE',
             )
 
     @classmethod
index a7f77d0d4830f18b6e9dfca3a19fe684156180e1..41d4d4aafecc6aa72122358e6cd773cf0b23a31b 100644 (file)
@@ -188,7 +188,7 @@ static bool buildNavMesh(const RecastData *recastParams, int nverts, float *vert
 
        /* zero dimensions cause zero alloc later on [#33758] */
        if (width <= 0 || height <= 0) {
-               BKE_report(reports, RPT_ERROR, "Object has no volume");
+               BKE_report(reports, RPT_ERROR, "Object has a width or height of zero");
                return false;
        }