Welcome to mirror list, hosted at ThFree Co, Russian Federation.

uv_relax.py « scripts « release - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 78d2dcff18ed5d64b504c4f90e2ff4bf379621c1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
#!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.
"""

# ***** BEGIN GPL LICENSE BLOCK *****
#
# Script copyright (C) Campbell J Barton
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------


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 = [Vector(0,0,0) for v in me.verts] # Z is an int for scaling the first 2 values.
	
	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)
			rv1= relaxVertList[v1.index]
			rv2= relaxVertList[v2.index]
			try: # Do nothing if we exist.
				tmpEdge= relaxEdgeDict[key]
			except:
				tmpEdge= relaxEdgeDict[key]= relaxEdge(rv1,rv2)
			
			# Add the edges to the face.
			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].x += f.uv[i].x
			tempVertUVList[v1.index].y += f.uv[i].y
			tempVertUVList[v1.index].z+=1
			if f.uvSel[i]:
				rv1.sel= True
	
	# Now average UV's into the relaxVerts
	for i, rv in enumerate(relaxVertList):
		if tempVertUVList[i].z > 0:
			newUV= tempVertUVList[i] * (1/tempVertUVList[i].z)
			rv.uv.x= newUV.x
			rv.uv.y= newUV.y
	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()