forked from bartvdbraak/blender
Added a function to BPyMesh - getFaceLoopEdges(faces, seams=[])
returns all face loops as a list of their edge keys Used this in uvcalc_follow_active_coords to speed it from 5.53sec to 0.098 on a 1000 face mesh.
This commit is contained in:
parent
4d74f07043
commit
7b93fff204
@ -301,19 +301,76 @@ def mesh2linkedFaces(me):
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
def getEdgeLoopsFromFaces(faces):
|
def getFaceLoopEdges(faces, seams=[]):
|
||||||
'''
|
'''
|
||||||
Takes me.faces or a list of faces and returns the edge loops
|
Takes me.faces or a list of faces and returns the edge loops
|
||||||
These edge loops are the edges that sit between quads, so they dont touch
|
These edge loops are the edges that sit between quads, so they dont touch
|
||||||
1 quad, not not connected will make 2 edge loops, both only containing 2 edges.
|
1 quad, not not connected will make 2 edge loops, both only containing 2 edges.
|
||||||
|
|
||||||
|
return a list of edge key lists
|
||||||
|
[ [(0,1), (4, 8), (3,8)], ...]
|
||||||
|
|
||||||
|
optionaly, seams are edge keys that will be removed
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
OTHER_INDEX = 2,3,0,1 # opposite face index
|
||||||
|
|
||||||
edges = {}
|
edges = {}
|
||||||
|
|
||||||
for f in faces:
|
for f in faces:
|
||||||
for i, edkey in enumerate(f.edge_keys):
|
if len(f) == 4:
|
||||||
try: edges[edkey].append((f, i))
|
edge_keys = f.edge_keys
|
||||||
except: edges[edkey] = [(f, i)]
|
for i, edkey in enumerate(f.edge_keys):
|
||||||
|
try: edges[edkey].append(edge_keys[OTHER_INDEX[i]])
|
||||||
|
except: edges[edkey] = [ edge_keys[OTHER_INDEX[i]] ]
|
||||||
|
|
||||||
|
for edkey in seams:
|
||||||
|
edges[edkey] = []
|
||||||
|
|
||||||
|
# Collect edge loops here
|
||||||
|
edge_loops = []
|
||||||
|
|
||||||
|
for edkey, ed_adj in edges.iteritems():
|
||||||
|
if 0 <len(ed_adj) < 3: # 1 or 2
|
||||||
|
# Seek the first edge
|
||||||
|
context_loop = [edkey, ed_adj[0]]
|
||||||
|
edge_loops.append(context_loop)
|
||||||
|
if len(ed_adj) == 2:
|
||||||
|
other_dir = ed_adj[1]
|
||||||
|
else:
|
||||||
|
other_dir = None
|
||||||
|
|
||||||
|
ed_adj[:] = []
|
||||||
|
|
||||||
|
flipped = False
|
||||||
|
|
||||||
|
while 1:
|
||||||
|
# from knowing the last 2, look for th next.
|
||||||
|
ed_adj = edges[context_loop[-1]]
|
||||||
|
if len(ed_adj) != 2:
|
||||||
|
|
||||||
|
if other_dir and flipped==False: # the original edge had 2 other edges
|
||||||
|
flipped = True # only flip the list once
|
||||||
|
context_loop.reverse()
|
||||||
|
ed_adj[:] = []
|
||||||
|
context_loop.append(other_dir) # save 1 lookiup
|
||||||
|
|
||||||
|
ed_adj = edges[context_loop[-1]]
|
||||||
|
if len(ed_adj) != 2:
|
||||||
|
ed_adj[:] = []
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
ed_adj[:] = []
|
||||||
|
break
|
||||||
|
|
||||||
|
i = ed_adj.index(context_loop[-2])
|
||||||
|
context_loop.append( ed_adj[ not i] )
|
||||||
|
|
||||||
|
# Dont look at this again
|
||||||
|
ed_adj[:] = []
|
||||||
|
|
||||||
|
|
||||||
|
return edge_loops
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -39,7 +39,8 @@ http://mediawiki.blender.org/index.php/Scripts/Manual/UV_Calculate/Follow_active
|
|||||||
|
|
||||||
|
|
||||||
from Blender import *
|
from Blender import *
|
||||||
|
import BPyMesh
|
||||||
|
reload(BPyMesh)
|
||||||
|
|
||||||
def extend():
|
def extend():
|
||||||
scn = Scene.GetCurrent()
|
scn = Scene.GetCurrent()
|
||||||
@ -54,12 +55,12 @@ def extend():
|
|||||||
me_verts = me.verts
|
me_verts = me.verts
|
||||||
|
|
||||||
# 0:normal extend, 1:edge length
|
# 0:normal extend, 1:edge length
|
||||||
EXTEND_MODE = Draw.PupMenu("Use Face Area%t|Loop Average%x2|Face Average%x1|None%x0")
|
EXTEND_MODE = Draw.PupMenu("Use Face Area%t|Loop Average%x2|None%x0")
|
||||||
if EXTEND_MODE == -1:
|
if EXTEND_MODE == -1:
|
||||||
return
|
return
|
||||||
|
|
||||||
Window.WaitCursor(1)
|
Window.WaitCursor(1)
|
||||||
|
t = sys.time()
|
||||||
edge_average_lengths = {}
|
edge_average_lengths = {}
|
||||||
|
|
||||||
OTHER_INDEX = 2,3,0,1
|
OTHER_INDEX = 2,3,0,1
|
||||||
@ -118,39 +119,22 @@ def extend():
|
|||||||
|
|
||||||
# Set the 2 UV's on the target face that are not touching
|
# Set the 2 UV's on the target face that are not touching
|
||||||
# for this we need to do basic expaning on the source faces UV's
|
# for this we need to do basic expaning on the source faces UV's
|
||||||
if EXTEND_MODE == 1 or EXTEND_MODE == 2:
|
if EXTEND_MODE == 2:
|
||||||
|
|
||||||
try: # divide by zero is possible
|
try: # divide by zero is possible
|
||||||
'''
|
'''
|
||||||
measure the length of each face from the middle of each edge to the opposite
|
measure the length of each face from the middle of each edge to the opposite
|
||||||
allong the axis we are copying, use this
|
allong the axis we are copying, use this
|
||||||
'''
|
'''
|
||||||
|
i1a= edgepair_outer_target[iB]
|
||||||
|
i2a= edgepair_inner_target[iA]
|
||||||
|
if i1a>i2a: i1a, i2a = i2a, i1a
|
||||||
|
|
||||||
if EXTEND_MODE == 1:
|
i1b= edgepair_outer_source[iB]
|
||||||
# Average lengths with edge_average_lengths
|
i2b= edgepair_inner_source[iA]
|
||||||
|
if i1b>i2b: i1b, i2b = i2b, i1b
|
||||||
factor =\
|
# print edge_average_lengths
|
||||||
(\
|
factor = edge_average_lengths[i1a, i2a][0] / edge_average_lengths[i1b, i2b][0]
|
||||||
(me_verts[edgepair_outer_target[iB]].co + me_verts[edgepair_outer_target[iA]].co)-\
|
|
||||||
(me_verts[edgepair_inner_target[iA]].co + me_verts[edgepair_inner_target[iB]].co)\
|
|
||||||
).length / (\
|
|
||||||
(me_verts[edgepair_outer_source[iB]].co + me_verts[edgepair_outer_source[iA]].co)-\
|
|
||||||
(me_verts[edgepair_inner_source[iA]].co + me_verts[edgepair_inner_source[iB]].co)\
|
|
||||||
).length
|
|
||||||
else: # EXTEND_MODE == 2
|
|
||||||
i1a= edgepair_outer_target[iB]
|
|
||||||
i2a= edgepair_inner_target[iA]
|
|
||||||
if i1a>i2a: i1a, i2a = i2a, i1a
|
|
||||||
|
|
||||||
i1b= edgepair_outer_source[iB]
|
|
||||||
i2b= edgepair_inner_source[iA]
|
|
||||||
if i1b>i2b: i1b, i2b = i2b, i1b
|
|
||||||
# print edge_average_lengths
|
|
||||||
factor = edge_average_lengths[i1a, i2a][0] / edge_average_lengths[i1b, i2b][0]
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
except:
|
except:
|
||||||
# Div By Zero?
|
# Div By Zero?
|
||||||
factor = 1.0
|
factor = 1.0
|
||||||
@ -158,12 +142,6 @@ def extend():
|
|||||||
uvs_vhash_target[edgepair_outer_target[iB]][:] = uvs_vhash_source[edgepair_inner_source[0]] +factor * (uvs_vhash_source[edgepair_inner_source[0]] - uvs_vhash_source[edgepair_outer_source[1]])
|
uvs_vhash_target[edgepair_outer_target[iB]][:] = uvs_vhash_source[edgepair_inner_source[0]] +factor * (uvs_vhash_source[edgepair_inner_source[0]] - uvs_vhash_source[edgepair_outer_source[1]])
|
||||||
uvs_vhash_target[edgepair_outer_target[iA]][:] = uvs_vhash_source[edgepair_inner_source[1]] +factor * (uvs_vhash_source[edgepair_inner_source[1]] - uvs_vhash_source[edgepair_outer_source[0]])
|
uvs_vhash_target[edgepair_outer_target[iA]][:] = uvs_vhash_source[edgepair_inner_source[1]] +factor * (uvs_vhash_source[edgepair_inner_source[1]] - uvs_vhash_source[edgepair_outer_source[0]])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# same as above but with no factor
|
# same as above but with no factor
|
||||||
uvs_vhash_target[edgepair_outer_target[iB]][:] = uvs_vhash_source[edgepair_inner_source[0]] + (uvs_vhash_source[edgepair_inner_source[0]] - uvs_vhash_source[edgepair_outer_source[1]])
|
uvs_vhash_target[edgepair_outer_target[iB]][:] = uvs_vhash_source[edgepair_inner_source[0]] + (uvs_vhash_source[edgepair_inner_source[0]] - uvs_vhash_source[edgepair_outer_source[1]])
|
||||||
@ -197,7 +175,7 @@ def extend():
|
|||||||
|
|
||||||
# Modes
|
# Modes
|
||||||
# 0 unsearched
|
# 0 unsearched
|
||||||
# 1:mapped, use search from this face.
|
# 1:mapped, use search from this face. - removed!!
|
||||||
# 2:all siblings have been searched. dont search again.
|
# 2:all siblings have been searched. dont search again.
|
||||||
face_modes = [0] * len(face_sel)
|
face_modes = [0] * len(face_sel)
|
||||||
face_modes[face_act_local_index] = 1 # extend UV's from this face.
|
face_modes[face_act_local_index] = 1 # extend UV's from this face.
|
||||||
@ -213,75 +191,14 @@ def extend():
|
|||||||
SEAM = Mesh.EdgeFlags.SEAM
|
SEAM = Mesh.EdgeFlags.SEAM
|
||||||
|
|
||||||
if EXTEND_MODE == 2:
|
if EXTEND_MODE == 2:
|
||||||
# Generate grid average edge lengths per edgeloop!
|
edge_loops = BPyMesh.getFaceLoopEdges(face_sel, [ed.key for ed in me.edges if ed.flag & SEAM] )
|
||||||
# this means that for each face loop, the edges on it will have new fake, everaged lengths
|
me_verts = me.verts
|
||||||
# WARNING! - This is not that optimal!!!... but neither is it horrid - Campbell
|
for loop in edge_loops:
|
||||||
|
looplen = [0.0]
|
||||||
seam_keys = {} # should be a set
|
for ed in loop:
|
||||||
for ed in me.edges:
|
edge_average_lengths[ed] = looplen
|
||||||
if ed.flag & SEAM:
|
looplen[0] += (me_verts[ed[0]].co - me_verts[ed[1]].co).length
|
||||||
seam_keys[ed.key] = None
|
looplen[0] = looplen[0] / len(loop)
|
||||||
|
|
||||||
|
|
||||||
# edge_average_lengths = {} # ed.key:length
|
|
||||||
# #edge_average_lengths.fromkeys(edge_faces)
|
|
||||||
# Why dosnt fromkeys work?
|
|
||||||
for edkey in edge_faces.keys():
|
|
||||||
edge_average_lengths[edkey] = None
|
|
||||||
|
|
||||||
# EDGROUP is the current edge loop index, assigned to all edges
|
|
||||||
EDGROUP = [0]
|
|
||||||
EDGROUPS = [EDGROUP] #
|
|
||||||
while 1:
|
|
||||||
|
|
||||||
start_edge = None
|
|
||||||
|
|
||||||
# get the first unused edge
|
|
||||||
for edkey, value in edge_average_lengths.iteritems():
|
|
||||||
if value == None:
|
|
||||||
start_edge = edkey
|
|
||||||
break
|
|
||||||
|
|
||||||
if start_edge == None:
|
|
||||||
break
|
|
||||||
|
|
||||||
edge_average_lengths[start_edge] = EDGROUP
|
|
||||||
|
|
||||||
one_more_edge = True
|
|
||||||
while one_more_edge:
|
|
||||||
one_more_edge = False
|
|
||||||
for f in face_sel:
|
|
||||||
edge_keys = f.edge_keys
|
|
||||||
for i, edkey in enumerate(edge_keys):
|
|
||||||
if edge_average_lengths[edkey] == EDGROUP:
|
|
||||||
# if the opposite edge has not been assigned then assign it
|
|
||||||
if (not seam_keys.has_key(edge_keys[OTHER_INDEX[i]])) and\
|
|
||||||
edge_average_lengths[edge_keys[OTHER_INDEX[i]]] == None:
|
|
||||||
|
|
||||||
edge_average_lengths[edge_keys[OTHER_INDEX[i]]] = EDGROUP
|
|
||||||
one_more_edge = True
|
|
||||||
|
|
||||||
# new list
|
|
||||||
EDGROUP = [EDGROUP[0]+1]
|
|
||||||
EDGROUPS.append(EDGROUP)
|
|
||||||
|
|
||||||
edge_average_length_groups = [0.0] * len(EDGROUPS)
|
|
||||||
edge_average_count = [0] * len(EDGROUPS)
|
|
||||||
|
|
||||||
edge_lengths = dict([(ed.key, ed.length) for ed in me.edges])
|
|
||||||
|
|
||||||
# Now we have the edge loops, average the lengths.
|
|
||||||
for edkey, edgroup in edge_average_lengths.iteritems():
|
|
||||||
edge_average_length_groups[edgroup[0]] += edge_lengths[edkey]
|
|
||||||
edge_average_count[edgroup[0]] += 1
|
|
||||||
|
|
||||||
for i in xrange(len(edge_average_count)):
|
|
||||||
if edge_average_count[i]:
|
|
||||||
# so edge_average_lengths now referenced the length rather then the group.
|
|
||||||
EDGROUPS[i][0] = edge_average_length_groups[i] / edge_average_count[i]
|
|
||||||
|
|
||||||
# Finished averaging lengths
|
|
||||||
# edge_average_lengths can be used.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -318,12 +235,12 @@ def extend():
|
|||||||
ok= True # keep searching
|
ok= True # keep searching
|
||||||
|
|
||||||
face_modes[i] = 2 # dont search again
|
face_modes[i] = 2 # dont search again
|
||||||
|
print sys.time() - t
|
||||||
me.update()
|
me.update()
|
||||||
Window.RedrawAll()
|
Window.RedrawAll()
|
||||||
Window.WaitCursor(0)
|
Window.WaitCursor(0)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
#t = sys.time()
|
|
||||||
extend()
|
extend()
|
||||||
#print sys.time() - t
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user