fix [#27787] Smart UV Unwrap Results in Overlaps
added optional face area weighting (from 2.4x) since this can result in overlapping faces.
This commit is contained in:
@@ -746,13 +746,15 @@ def packIslands(islandList):
|
|||||||
uv.y= (uv.y+yoffset) * yfactor
|
uv.y= (uv.y+yoffset) * yfactor
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def VectoQuat(vec):
|
def VectoQuat(vec):
|
||||||
vec = vec.normalized()
|
a3 = vec.normalized()
|
||||||
if abs(vec.x) > 0.5:
|
up = Vector((0.0, 0.0, 1.0))
|
||||||
return vec.to_track_quat('Z', 'X')
|
if abs(a3.dot(up)) == 1.0:
|
||||||
else:
|
up = Vector((0.0, 1.0, 0.0))
|
||||||
return vec.to_track_quat('Z', 'Y')
|
|
||||||
|
a1 = a3.cross(up).normalized()
|
||||||
|
a2 = a3.cross(a1)
|
||||||
|
return Matrix((a1, a2, a3)).to_quaternion()
|
||||||
|
|
||||||
|
|
||||||
class thickface(object):
|
class thickface(object):
|
||||||
@@ -791,7 +793,11 @@ def main_consts():
|
|||||||
|
|
||||||
global ob
|
global ob
|
||||||
ob = None
|
ob = None
|
||||||
def main(context, island_margin, projection_limit):
|
def main(context,
|
||||||
|
island_margin,
|
||||||
|
projection_limit,
|
||||||
|
user_area_weight,
|
||||||
|
):
|
||||||
global USER_FILL_HOLES
|
global USER_FILL_HOLES
|
||||||
global USER_FILL_HOLES_QUALITY
|
global USER_FILL_HOLES_QUALITY
|
||||||
global USER_STRETCH_ASPECT
|
global USER_STRETCH_ASPECT
|
||||||
@@ -844,7 +850,6 @@ def main(context, island_margin, projection_limit):
|
|||||||
USER_FILL_HOLES = (0)
|
USER_FILL_HOLES = (0)
|
||||||
USER_FILL_HOLES_QUALITY = (50) # Only for hole filling.
|
USER_FILL_HOLES_QUALITY = (50) # Only for hole filling.
|
||||||
USER_VIEW_INIT = (0) # Only for hole filling.
|
USER_VIEW_INIT = (0) # Only for hole filling.
|
||||||
USER_AREA_WEIGHT = (1) # Only for hole filling.
|
|
||||||
|
|
||||||
# Reuse variable
|
# Reuse variable
|
||||||
if len(obList) == 1:
|
if len(obList) == 1:
|
||||||
@@ -970,12 +975,15 @@ def main(context, island_margin, projection_limit):
|
|||||||
|
|
||||||
# Add the average of all these faces normals as a projectionVec
|
# Add the average of all these faces normals as a projectionVec
|
||||||
averageVec = Vector((0.0, 0.0, 0.0))
|
averageVec = Vector((0.0, 0.0, 0.0))
|
||||||
if USER_AREA_WEIGHT:
|
if user_area_weight == 0.0:
|
||||||
for fprop in newProjectMeshFaces:
|
|
||||||
averageVec += (fprop.no * fprop.area)
|
|
||||||
else:
|
|
||||||
for fprop in newProjectMeshFaces:
|
for fprop in newProjectMeshFaces:
|
||||||
averageVec += fprop.no
|
averageVec += fprop.no
|
||||||
|
elif user_area_weight == 1.0:
|
||||||
|
for fprop in newProjectMeshFaces:
|
||||||
|
averageVec += fprop.no * fprop.area
|
||||||
|
else:
|
||||||
|
for fprop in newProjectMeshFaces:
|
||||||
|
averageVec += fprop.no * ((fprop.area * user_area_weight) + (1.0 - user_area_weight))
|
||||||
|
|
||||||
if averageVec.x != 0 or averageVec.y != 0 or averageVec.z != 0: # Avoid NAN
|
if averageVec.x != 0 or averageVec.y != 0 or averageVec.z != 0: # Avoid NAN
|
||||||
projectVecs.append(averageVec.normalized())
|
projectVecs.append(averageVec.normalized())
|
||||||
@@ -1062,7 +1070,7 @@ def main(context, island_margin, projection_limit):
|
|||||||
f_uv = f.uv
|
f_uv = f.uv
|
||||||
for j, v in enumerate(f.v):
|
for j, v in enumerate(f.v):
|
||||||
# XXX - note, between mathutils in 2.4 and 2.5 the order changed.
|
# XXX - note, between mathutils in 2.4 and 2.5 the order changed.
|
||||||
f_uv[j][:] = (v.co * MatQuat)[:2]
|
f_uv[j][:] = (v.co * MatQuat).xy
|
||||||
|
|
||||||
|
|
||||||
if USER_SHARE_SPACE:
|
if USER_SHARE_SPACE:
|
||||||
@@ -1098,12 +1106,8 @@ def main(context, island_margin, projection_limit):
|
|||||||
"""
|
"""
|
||||||
pup_block = [\
|
pup_block = [\
|
||||||
'Projection',\
|
'Projection',\
|
||||||
* ('Angle Limit:', USER_PROJECTION_LIMIT, 1, 89, ''),\
|
|
||||||
('Selected Faces Only', USER_ONLY_SELECTED_FACES, 'Use only selected faces from all selected meshes.'),\
|
('Selected Faces Only', USER_ONLY_SELECTED_FACES, 'Use only selected faces from all selected meshes.'),\
|
||||||
('Init from view', USER_VIEW_INIT, 'The first projection will be from the view vector.'),\
|
('Init from view', USER_VIEW_INIT, 'The first projection will be from the view vector.'),\
|
||||||
('Area Weight', USER_AREA_WEIGHT, 'Weight projections vector by face area.'),\
|
|
||||||
'',\
|
|
||||||
'',\
|
|
||||||
'',\
|
'',\
|
||||||
'UV Layout',\
|
'UV Layout',\
|
||||||
('Share Tex Space', USER_SHARE_SPACE, 'Objects Share texture space, map all objects into 1 uvmap.'),\
|
('Share Tex Space', USER_SHARE_SPACE, 'Objects Share texture space, map all objects into 1 uvmap.'),\
|
||||||
@@ -1125,11 +1129,15 @@ class SmartProject(bpy.types.Operator):
|
|||||||
bl_options = {'REGISTER', 'UNDO'}
|
bl_options = {'REGISTER', 'UNDO'}
|
||||||
|
|
||||||
angle_limit = FloatProperty(name="Angle Limit",
|
angle_limit = FloatProperty(name="Angle Limit",
|
||||||
description="lower for more projection groups, higher for less distortion.",
|
description="lower for more projection groups, higher for less distortion",
|
||||||
default=66.0, min=1.0, max=89.0)
|
default=66.0, min=1.0, max=89.0)
|
||||||
|
|
||||||
island_margin = FloatProperty(name="Island Margin",
|
island_margin = FloatProperty(name="Island Margin",
|
||||||
description="Margin to reduce bleed from adjacent islands.",
|
description="Margin to reduce bleed from adjacent islands",
|
||||||
|
default=0.0, min=0.0, max=1.0)
|
||||||
|
|
||||||
|
user_area_weight = FloatProperty(name="Area Weight",
|
||||||
|
description="Weight projections vector by faces with larger areas",
|
||||||
default=0.0, min=0.0, max=1.0)
|
default=0.0, min=0.0, max=1.0)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -1137,7 +1145,11 @@ class SmartProject(bpy.types.Operator):
|
|||||||
return context.active_object != None
|
return context.active_object != None
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
main(context, self.island_margin, self.angle_limit)
|
main(context,
|
||||||
|
self.island_margin,
|
||||||
|
self.angle_limit,
|
||||||
|
self.user_area_weight,
|
||||||
|
)
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
def invoke(self, context, event):
|
def invoke(self, context, event):
|
||||||
|
Reference in New Issue
Block a user