From __bpydoc__
This script relaxes selected UV verts in relation to there surrounding geometry. Use this script in face select mode. Left Click to finish or wait until no more relaxing can be done.
This commit is contained in:
parent
2c35988fcb
commit
af4f110de5
178
release/scripts/uv_relax.py
Normal file
178
release/scripts/uv_relax.py
Normal file
@ -0,0 +1,178 @@
|
||||
#!BPY
|
||||
"""
|
||||
Name: 'Relax selected UVs.'
|
||||
Blender: 237
|
||||
Group: 'UV'
|
||||
Tooltip: 'Relaxes selected UVs '
|
||||
"""
|
||||
|
||||
__author__ = "Campbell Barton"
|
||||
__url__ = ("blender", "elysiun")
|
||||
__version__ = "1.0 2006/02/07"
|
||||
|
||||
__bpydoc__ = """\
|
||||
This script relaxes selected UV verts in relation to there surrounding geometry.
|
||||
|
||||
Use this script in face select mode.
|
||||
Left Click to finish or wait until no more relaxing can be done.
|
||||
"""
|
||||
|
||||
from Blender import Scene, Object, Mesh, Window
|
||||
from Blender.Mathutils import Vector
|
||||
|
||||
class relaxVert(object):
|
||||
__slots__= 'bvert', 'edges', 'bfaces', 'uv', 'sel'
|
||||
def __init__(self, bvert):
|
||||
self.bvert= bvert
|
||||
self.edges= []
|
||||
self.bfaces= [] # list pf tuples, bface and this verts index in the bface.
|
||||
self.uv= Vector(0,0)
|
||||
self.sel= False
|
||||
|
||||
def setBFaceUV(self):
|
||||
x= self.uv.x
|
||||
y= self.uv.y
|
||||
for bface,i in self.bfaces:
|
||||
bface.uv[i].x= x
|
||||
bface.uv[i].y= y
|
||||
|
||||
class relaxEdge(object):
|
||||
__slots__= 'v1', 'v2', 'length3d', 'lengthUv', 'lengthUvOrig'
|
||||
def __init__(self, v1,v2):
|
||||
self.v1= v1
|
||||
self.v2= v2
|
||||
self.length3d= (v1.bvert.co-v2.bvert.co).length
|
||||
self.lengthUv= None
|
||||
self.lengthUvOrig= None
|
||||
|
||||
def otherVert(self, v):
|
||||
if v==self.v1 and v!=self.v2:
|
||||
return self.v2
|
||||
elif v==self.v2 and v!=self.v1:
|
||||
return self.v1
|
||||
else:
|
||||
raise 'Vert not in edge'
|
||||
|
||||
def setUvLength(self):
|
||||
self.lengthUv= (self.v1.uv - self.v2.uv).length
|
||||
if self.lengthUvOrig==None:
|
||||
self.lengthUvOrig= self.lengthUv
|
||||
def main():
|
||||
scn= Scene.GetCurrent()
|
||||
ob= scn.getActiveObject()
|
||||
if not ob or ob.getType() != 'Mesh':
|
||||
Draw.PupMenu('ERROR: No mesh object in face select mode.')
|
||||
return
|
||||
|
||||
me= ob.getData(mesh=1)
|
||||
|
||||
|
||||
def sortPair(a,b):
|
||||
return min(a,b), max(a,b)
|
||||
|
||||
|
||||
# Build edge data from faces.
|
||||
relaxEdgeDict= {}
|
||||
relaxVertList= [relaxVert(v) for v in me.verts]
|
||||
|
||||
tempVertUVList = [list() for v in me.verts]
|
||||
|
||||
for f in me.faces:
|
||||
for i in xrange(len(f.v)):
|
||||
v1,v2= f.v[i], f.v[i-1]
|
||||
key= sortPair(v1.index, v2.index)
|
||||
try: # Do nothing if we exist.
|
||||
tmpEdge= relaxEdgeDict[key]
|
||||
except:
|
||||
tmpEdge= relaxEdgeDict[key]= relaxEdge(relaxVertList[key[0]],relaxVertList[key[1]])
|
||||
|
||||
# Add the edges to the face.
|
||||
rv1= relaxVertList[v1.index]
|
||||
rv2= relaxVertList[v2.index]
|
||||
rv1.edges.append(tmpEdge)
|
||||
rv2.edges.append(tmpEdge)
|
||||
|
||||
# Will get to all v1's no need to add both per edge.
|
||||
rv1.bfaces.append( (f, i) )
|
||||
tempVertUVList[v1.index].append(f.uv[i])
|
||||
if f.uvSel[i]:
|
||||
rv1.sel= True
|
||||
|
||||
# Now average UV's into the relaxVerts
|
||||
for i, rv in enumerate(relaxVertList):
|
||||
tempUV = Vector(0,0)
|
||||
|
||||
for uv in tempVertUVList[i]:
|
||||
tempUV+= uv
|
||||
tempUV= tempUV * (1/float(len(tempVertUVList[i])))
|
||||
rv.uv= tempUV
|
||||
del tempVertUVList
|
||||
|
||||
# Loop while the button is held, so clicking on a menu wont immediatly exit.
|
||||
while Window.GetMouseButtons() & Window.MButs['L']:
|
||||
pass
|
||||
|
||||
# NOW RELAX
|
||||
#ITERATIONS=1000
|
||||
#for iter in range(ITERATIONS):
|
||||
Window.DrawProgressBar(0.0, '')
|
||||
iter=0
|
||||
while not Window.GetMouseButtons() & Window.MButs['L']:
|
||||
tempUV= Vector(0,0)
|
||||
iter+=1
|
||||
if not iter%10:
|
||||
Window.DrawProgressBar(0.1, 'Left Mouse to Exit %i' % iter)
|
||||
# Set the uv lengths each iteration.
|
||||
for re in relaxEdgeDict.itervalues():
|
||||
re.setUvLength()
|
||||
changed=False
|
||||
for rv in relaxVertList:
|
||||
if rv.sel:
|
||||
backupUV= rv.uv
|
||||
totUvLen= tot3dLen= 0
|
||||
|
||||
for re in rv.edges:
|
||||
tot3dLen+= re.length3d
|
||||
totUvLen+= re.lengthUvOrig # So the UV edges dont keep growing.
|
||||
|
||||
# the radio is the scaler between 3d space and UV space - so we can relax the UVs
|
||||
# so proportionaly the UV lengths match the 3d lengths.
|
||||
ratio = totUvLen/tot3dLen
|
||||
|
||||
# Make a list of new UVs that match the 3d length of the edges.
|
||||
tempUV.y= tempUV.x= 0
|
||||
for re in rv.edges:
|
||||
otherRelaxVert= re.otherVert(rv)
|
||||
targetDist= re.length3d*ratio
|
||||
newUV= rv.uv-otherRelaxVert.uv
|
||||
newUV.normalize()
|
||||
newUV= newUV*targetDist
|
||||
|
||||
#tempUVs.append(newUV+otherRelaxVert.uv)
|
||||
tempUV= tempUV+ ( (newUV+otherRelaxVert.uv) * (1/float(len(rv.edges))))
|
||||
|
||||
|
||||
if (rv.uv!=tempUV):
|
||||
changed= True
|
||||
rv.uv= (rv.uv+tempUV)* 0.5
|
||||
|
||||
if not changed:
|
||||
break
|
||||
|
||||
|
||||
|
||||
# Connection data done.
|
||||
for rv in relaxVertList:
|
||||
if rv.sel:
|
||||
rv.setBFaceUV()
|
||||
|
||||
|
||||
|
||||
me.update()
|
||||
Window.RedrawAll()
|
||||
|
||||
|
||||
Window.DrawProgressBar(1.0, '')
|
||||
|
||||
if __name__=='__main__':
|
||||
main()
|
Loading…
Reference in New Issue
Block a user