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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2007-01-05 19:41:04 +0300
committerCampbell Barton <ideasman42@gmail.com>2007-01-05 19:41:04 +0300
commit0306a86d941a4ffcc358148b469add1d14f8dc84 (patch)
treeb5eda92a62981a02a595bd5129e0429704105196 /release
parent00c82cd3b2a0ef1056f476b1b7d8034b5b5d4880 (diff)
bugfix, would make bow-tie faces when skinning more then 2 loops.
big speedup to loop detection added support for skinning open loops (could be improved, dosnt work that well when open loops have different vert counts) speedup elsewhere with LC's
Diffstat (limited to 'release')
-rw-r--r--release/scripts/mesh_skin.py176
1 files changed, 110 insertions, 66 deletions
diff --git a/release/scripts/mesh_skin.py b/release/scripts/mesh_skin.py
index edeb0b67407..6052ee2c876 100644
--- a/release/scripts/mesh_skin.py
+++ b/release/scripts/mesh_skin.py
@@ -67,7 +67,8 @@ def AngleBetweenVecs(a1,a2):
except:
return 180.0
-class edge:
+class edge(object):
+ __slots__ = 'v1', 'v2', 'co1', 'co2', 'length', 'removed', 'match', 'cent', 'angle', 'next', 'prev', 'normal', 'fake'
def __init__(self, v1,v2):
self.v1 = v1
self.v2 = v2
@@ -82,21 +83,26 @@ class edge:
self.cent= MidpointVecs(co1, co2)
self.angle= 0.0
+ self.fake= False
-class edgeLoop:
- def __init__(self, loop): # Vert loop
+class edgeLoop(object):
+ __slots__ = 'centre', 'edges', 'normal', 'closed', 'backup_edges'
+ def __init__(self, loop, me, closed): # Vert loop
# Use next and prev, nextDist, prevDist
# Get Loops centre.
fac= len(loop)
- self.centre= reduce(lambda a,b: a+b.co/fac, loop, Vector())
+ verts = me.verts
+ self.centre= reduce(lambda a,b: a+verts[b].co/fac, loop, Vector())
# Convert Vert loop to Edges.
- self.edges = []
- vIdx = 0
- while vIdx < len(loop):
- self.edges.append( edge(loop[vIdx-1], loop[vIdx]) )
- vIdx += 1
+ self.edges = [edge(verts[loop[vIdx-1]], verts[loop[vIdx]]) for vIdx in xrange(len(loop))]
+
+ if not closed:
+ self.edges[0].fake = True # fake edge option
+
+ self.closed = closed
+
# Assign linked list
for eIdx in xrange(len(self.edges)-1):
@@ -165,18 +171,19 @@ class edgeLoop:
def backup(self):
# Keep a backup of the edges
- self.backupEdges = self.edges[:]
+ self.backup_edges = self.edges[:]
def restore(self):
- self.edges = self.backupEdges[:]
+ self.edges = self.backup_edges[:]
for e in self.edges:
e.removed = 0
def reverse(self):
self.edges.reverse()
for e in self.edges:
- e.normal = -e.normal
+ e.normal.negate()
e.v1, e.v2 = e.v2, e.v1
+ e.next, e.prev = e.prev, e.next
self.normal.negate()
def removeSmallest(self, cullNum, otherLoopLen):
@@ -216,7 +223,7 @@ class edgeLoop:
smallestEdge= None
while step_count<=step or smallestEdge==None:
step_count+=1
- if not currentEdge.removed:
+ if not currentEdge.removed: # 0 or -1 will not be accepted
if currentEdge.angle<bestAng:
smallestEdge= currentEdge
bestAng= currentEdge.angle
@@ -265,50 +272,86 @@ def getSelectedEdges(me, ob):
Blender.Mesh.Mode(MESH_MODE)
return [ ed_data[0] for ed_data in edge_dict.itervalues() if ed_data[1] == 1 ]
-
-
-# Like vert loops
-def getVertLoops(selEdges):
+
+def getVertLoops(selEdges, me):
+ '''
+ return a list of vert loops, closed and open [(loop, closed)...]
+ '''
mainVertLoops = []
- while selEdges:
- e = selEdges.pop()
- contextVertLoop= [e.v1, e.v2] # start the vert loop
+ # second method
+ tot = len(me.verts)
+ vert_siblings = [[] for i in xrange(tot)]
+ vert_used = [False] * tot
+
+ for ed in selEdges:
+ i1, i2 = ed.key
+ vert_siblings[i1].append(i2)
+ vert_siblings[i2].append(i1)
- eIdx = 1 # Get us into the loop. dummy var.
-
- # if eIdx == 0 then it means we searched and found no matches...
- # time for a new vert loop,
- while eIdx:
- eIdx = len(selEdges)
- while eIdx:
- eIdx-=1
-
- # Check for edge attached at the head of the loop.
- if contextVertLoop[0] == selEdges[eIdx].v1:
- contextVertLoop.insert(0, selEdges.pop(eIdx).v2)
- elif contextVertLoop[0] == selEdges[eIdx].v2:
- contextVertLoop.insert(0, selEdges.pop(eIdx).v1)
-
- # Chech for edge vert at the tail.
- elif contextVertLoop[-1] == selEdges[eIdx].v1:
- contextVertLoop.append(selEdges.pop(eIdx).v2)
- elif contextVertLoop[-1] == selEdges[eIdx].v2:
- contextVertLoop.append(selEdges.pop(eIdx).v1)
- else:
- # None found? Keep looking
- continue
+
+
+ # remove any triple points
+ for i in xrange(tot):
+ if len(vert_siblings[i]) > 2:
+ vert_siblings[i] = [] # clear
+
+ # find the first used vert and keep looping.
+ for i in xrange(tot):
+ if vert_siblings[i] and not vert_used[i]:
+ sbl = vert_siblings[i] # siblings
+ vert_used[i] = True
+
+ # do an edgeloop seek
+ if len(vert_siblings[i]) == 2:
+ contextVertLoop= [sbl[0], i, sbl[1]] # start the vert loop
+ vert_used[contextVertLoop[ 0]] = True
+ vert_used[contextVertLoop[-1]] = True
+ else:
+ contextVertLoop= [i, sbl[0]]
+ vert_used[contextVertLoop[ 1]] = True
+
+ # Always seek up
+ ok = True
+ while ok:
+ ok = False
+ closed = False
+ sbl = vert_siblings[contextVertLoop[-1]]
+ if len(sbl) == 2:
+ next = sbl[not sbl.index( contextVertLoop[-2] )]
+ if vert_used[next]:
+ closed = True
+ # break
+ else:
+ contextVertLoop.append( next ) # get the vert that isnt the second last
+ vert_used[next] = True
+ ok = True
+
+ # Seek down as long as the starting vert was not at the edge.
+ if not closed and len(vert_siblings[i]) == 2:
- # Once found we.
- break
-
- # Is this a loop? if so then its forst and last vert must be teh same.
- if contextVertLoop[0].index == contextVertLoop[-1].index:
- contextVertLoop.pop() # remove double vert
- mainVertLoops.append(contextVertLoop)
-
- # Build context vert loops
+ ok = True
+ while ok:
+ ok = False
+ sbl = vert_siblings[contextVertLoop[0]]
+ if len(sbl) == 2:
+ next = sbl[not sbl.index( contextVertLoop[1] )]
+ if vert_used[next]:
+ closed = True
+ else:
+ contextVertLoop.insert(0, next) # get the vert that isnt the second last
+ vert_used[next] = True
+ ok = True
+
+ mainVertLoops.append((contextVertLoop, closed))
+
+
+ verts = me.verts
+ # convert from indicies to verts
+ # mainVertLoops = [([verts[i] for i in contextVertLoop], closed) for contextVertLoop, closed in mainVertLoops]
+
return mainVertLoops
+
def skin2EdgeLoops(eloop1, eloop2, me, ob, MODE):
@@ -333,17 +376,14 @@ def skin2EdgeLoops(eloop1, eloop2, me, ob, MODE):
loopDist = skinVector.length
- # IS THE LOOP FLIPPED, IF SO FLIP BACK.
+ # IS THE LOOP FLIPPED, IF SO FLIP BACK. we keep it flipped, its ok,
angleBetweenLoopNormals = AngleBetweenVecs(eloop1.normal, eloop2.normal)
- print eloop1.normal, eloop2.normal
- print "angleBetweenLoopNormals ", angleBetweenLoopNormals
- #if abs(angleBetweenLoopNormals-90) > 90:
if angleBetweenLoopNormals > 90:
eloop2.reverse()
DIR= eloop1.centre - eloop2.centre
-
+ # if eloop2.closed:
bestEloopDist = BIG_NUM
bestOffset = 0
# Loop rotation offset to test.1
@@ -394,7 +434,9 @@ def skin2EdgeLoops(eloop1, eloop2, me, ob, MODE):
# Remember the pairs for fan filling culled edges.
e1.match = e2; e2.match = e1
- new_faces.append([e1.v1, e1.v2, e2.v2, e2.v1])
+
+ if not (e1.fake or e2.fake):
+ new_faces.append([e1.v1, e1.v2, e2.v2, e2.v1])
# FAN FILL MISSING FACES.
if CULL_FACES:
@@ -409,6 +451,7 @@ def skin2EdgeLoops(eloop1, eloop2, me, ob, MODE):
vertFanPivot = contextEdge.match.v2
while contextEdge.next.removed == 1:
+ #if not contextEdge.next.fake:
new_faces.append([contextEdge.next.v1, contextEdge.next.v2, vertFanPivot])
# Should we use another var?, this will work for now.
@@ -417,13 +460,12 @@ def skin2EdgeLoops(eloop1, eloop2, me, ob, MODE):
contextEdge = contextEdge.next
FAN_FILLED_FACES += 1
+ # may need to fan fill backwards 1 for non closed loops.
+
eloop1.restore() # Add culled back into the list.
me.faces.extend(new_faces)
- #if angleBetweenLoopNormals > 90:
- # eloop2.reverse()
-
def main():
global CULL_METHOD
@@ -435,9 +477,11 @@ def main():
return
me = ob.getData(mesh=1)
-
+ time1 = Blender.sys.time()
selEdges = getSelectedEdges(me, ob)
- vertLoops = getVertLoops(selEdges) # list of lists of edges.
+ vertLoops = getVertLoops(selEdges, me) # list of lists of edges.
+ # print len(vertLoops)
+
if len(vertLoops) > 2:
choice = PupMenu('Loft '+str(len(vertLoops))+' edge loops%t|loop|segment')
@@ -453,7 +497,7 @@ def main():
# The line below checks if any of the vert loops are differenyt in length.
- if False in [len(v) == len(vertLoops[0]) for v in vertLoops]:
+ if False in [len(v[0]) == len(vertLoops[0][0]) for v in vertLoops]:
CULL_METHOD = PupMenu('Small to large edge loop distrobution method%t|remove edges evenly|remove smallest edges')
if CULL_METHOD == -1:
if is_editmode: Window.EditMode(1)
@@ -468,8 +512,8 @@ def main():
time1 = Blender.sys.time()
# Convert to special edge data.
edgeLoops = []
- for vloop in vertLoops:
- edgeLoops.append(edgeLoop(vloop))
+ for vloop, closed in vertLoops:
+ edgeLoops.append(edgeLoop(vloop, me, closed))
# VERT LOOP ORDERING CODE