[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [23796] trunk/blender/release/scripts/io/ mesh_skin.py: skin tool from 2.4, am loathed to do this but durian artists want.
Campbell Barton
ideasman42 at gmail.com
Mon Oct 12 23:11:31 CEST 2009
Revision: 23796
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=23796
Author: campbellbarton
Date: 2009-10-12 23:11:31 +0200 (Mon, 12 Oct 2009)
Log Message:
-----------
skin tool from 2.4, am loathed to do this but durian artists want.
Added Paths:
-----------
trunk/blender/release/scripts/io/mesh_skin.py
Copied: trunk/blender/release/scripts/io/mesh_skin.py (from rev 23795, branches/blender2.4/release/scripts/mesh_skin.py)
===================================================================
--- trunk/blender/release/scripts/io/mesh_skin.py (rev 0)
+++ trunk/blender/release/scripts/io/mesh_skin.py 2009-10-12 21:11:31 UTC (rev 23796)
@@ -0,0 +1,639 @@
+#!BPY
+
+"""
+Name: 'Skin Faces/Edge-Loops'
+Blender: 243
+Group: 'MeshFaceKey'
+Tooltip: 'Select 2 vert loops, then run this script.'
+"""
+
+__author__ = "Campbell Barton AKA Ideasman"
+__url__ = ["blenderartists.org", "www.blender.org"]
+__version__ = "1.1 2006/12/26"
+
+__bpydoc__ = """\
+With this script vertex loops can be skinned: faces are created to connect the
+selected loops of vertices.
+
+Usage:
+
+In mesh Edit mode select the vertices of the loops (closed paths / curves of
+vertices: circles, for example) that should be skinned, then run this script.
+A pop-up will provide further options, if the results of a method are not adequate try one of the others.
+"""
+
+
+# $Id$
+#
+# --------------------------------------------------------------------------
+# Skin Selected edges 1.0 By Campbell Barton (AKA Ideasman)
+# --------------------------------------------------------------------------
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# 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 *****
+# --------------------------------------------------------------------------
+
+# Made by Ideasman/Campbell 2005/06/15 - cbarton at metavr.com
+
+import Blender
+import bpy
+from Blender import Window
+from Blender.Mathutils import MidpointVecs, Vector
+from Blender.Mathutils import AngleBetweenVecs as _AngleBetweenVecs_
+import BPyMessages
+
+from Blender.Draw import PupMenu
+
+BIG_NUM = 1<<30
+
+global CULL_METHOD
+CULL_METHOD = 0
+
+def AngleBetweenVecs(a1,a2):
+ try:
+ return _AngleBetweenVecs_(a1,a2)
+ except:
+ return 180.0
+
+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
+ co1, co2= v1.co, v2.co
+ self.co1= co1
+ self.co2= co2
+
+ # uv1 uv2 vcol1 vcol2 # Add later
+ self.length = (co1 - co2).length
+ self.removed = 0 # Have we been culled from the eloop
+ self.match = None # The other edge were making a face with
+
+ self.cent= MidpointVecs(co1, co2)
+ self.angle= 0.0
+ self.fake= False
+
+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)
+ verts = me.verts
+ self.centre= reduce(lambda a,b: a+verts[b].co/fac, loop, Vector())
+
+ # Convert Vert loop to Edges.
+ 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):
+ self.edges[eIdx].next = self.edges[eIdx+1]
+ self.edges[eIdx].prev = self.edges[eIdx-1]
+ # Now last
+ self.edges[-1].next = self.edges[0]
+ self.edges[-1].prev = self.edges[-2]
+
+
+
+ # GENERATE AN AVERAGE NORMAL FOR THE WHOLE LOOP.
+ self.normal = Vector()
+ for e in self.edges:
+ n = (self.centre-e.co1).cross(self.centre-e.co2)
+ # Do we realy need tot normalize?
+ n.normalize()
+ self.normal += n
+
+ # Generate the angle
+ va= e.cent - e.prev.cent
+ vb= e.next.cent - e.cent
+
+ e.angle= AngleBetweenVecs(va, vb)
+
+ # Blur the angles
+ #for e in self.edges:
+ # e.angle= (e.angle+e.next.angle)/2
+
+ # Blur the angles
+ #for e in self.edges:
+ # e.angle= (e.angle+e.prev.angle)/2
+
+ self.normal.normalize()
+
+ # Generate a normal for each edge.
+ for e in self.edges:
+
+ n1 = e.co1
+ n2 = e.co2
+ n3 = e.prev.co1
+
+ a = n1-n2
+ b = n1-n3
+ normal1 = a.cross(b)
+ normal1.normalize()
+
+ n1 = e.co2
+ n3 = e.next.co2
+ n2 = e.co1
+
+ a = n1-n2
+ b = n1-n3
+
+ normal2 = a.cross(b)
+ normal2.normalize()
+
+ # Reuse normal1 var
+ normal1 += normal1 + normal2
+ normal1.normalize()
+
+ e.normal = normal1
+ #print e.normal
+
+
+
+ def backup(self):
+ # Keep a backup of the edges
+ self.backup_edges = self.edges[:]
+
+ def restore(self):
+ self.edges = self.backup_edges[:]
+ for e in self.edges:
+ e.removed = 0
+
+ def reverse(self):
+ self.edges.reverse()
+ self.normal.negate()
+
+ for e in self.edges:
+ e.normal.negate()
+ e.v1, e.v2 = e.v2, e.v1
+ e.co1, e.co2 = e.co2, e.co1
+ e.next, e.prev = e.prev, e.next
+
+
+ def removeSmallest(self, cullNum, otherLoopLen):
+ '''
+ Removes N Smallest edges and backs up the loop,
+ this is so we can loop between 2 loops as if they are the same length,
+ backing up and restoring incase the loop needs to be skinned with another loop of a different length.
+ '''
+ global CULL_METHOD
+ if CULL_METHOD == 1: # Shortest edge
+ eloopCopy = self.edges[:]
+
+ # Length sort, smallest first
+ try: eloopCopy.sort(key = lambda e1: e1.length)
+ except: eloopCopy.sort(lambda e1, e2: cmp(e1.length, e2.length ))
+
+ # Dont use atm
+ #eloopCopy.sort(lambda e1, e2: cmp(e1.angle*e1.length, e2.angle*e2.length)) # Length sort, smallest first
+ #eloopCopy.sort(lambda e1, e2: cmp(e1.angle, e2.angle)) # Length sort, smallest first
+
+ remNum = 0
+ for i, e in enumerate(eloopCopy):
+ if not e.fake:
+ e.removed = 1
+ self.edges.remove( e ) # Remove from own list, still in linked list.
+ remNum += 1
+
+ if not remNum < cullNum:
+ break
+
+ else: # CULL METHOD is even
+
+ culled = 0
+
+ step = int(otherLoopLen / float(cullNum)) * 2
+
+ currentEdge = self.edges[0]
+ while culled < cullNum:
+
+ # Get the shortest face in the next STEP
+ step_count= 0
+ bestAng= 360.0
+ smallestEdge= None
+ while step_count<=step or smallestEdge==None:
+ step_count+=1
+ if not currentEdge.removed: # 0 or -1 will not be accepted
+ if currentEdge.angle<bestAng and not currentEdge.fake:
+ smallestEdge= currentEdge
+ bestAng= currentEdge.angle
+
+ currentEdge = currentEdge.next
+
+ # In that stepping length we have the smallest edge.remove it
+ smallestEdge.removed = 1
+ self.edges.remove(smallestEdge)
+
+ # Start scanning from the edge we found? - result is over fanning- no good.
+ #currentEdge= smallestEdge.next
+
+ culled+=1
+
+
+# Returns face edges.
+# face must have edge data.
+
+def getSelectedEdges(me, ob):
+ MESH_MODE= Blender.Mesh.Mode()
+
+ if MESH_MODE & Blender.Mesh.SelectModes.EDGE or MESH_MODE & Blender.Mesh.SelectModes.VERTEX:
+ Blender.Mesh.Mode(Blender.Mesh.SelectModes.EDGE)
+ edges= [ ed for ed in me.edges if ed.sel ]
+ # print len(edges), len(me.edges)
+ Blender.Mesh.Mode(MESH_MODE)
+ return edges
+
+ elif MESH_MODE & Blender.Mesh.SelectModes.FACE:
+ Blender.Mesh.Mode(Blender.Mesh.SelectModes.EDGE)
+
+ # value is [edge, face_sel_user_in]
+ '''
+ try: # Python 2.4 only
+ edge_dict= dict((ed.key, [ed, 0]) for ed in me.edges)
+ except:
+ '''
+ # Cant try 2.4 syntax because python 2.3 will complain still
+ edge_dict= dict([(ed.key, [ed, 0]) for ed in me.edges])
+
+ for f in me.faces:
+ if f.sel:
+ for edkey in f.edge_keys:
+ edge_dict[edkey][1] += 1
+
+ Blender.Mesh.Mode(MESH_MODE)
+ return [ ed_data[0] for ed_data in edge_dict.itervalues() if ed_data[1] == 1 ]
+
+
+
+def getVertLoops(selEdges, me):
+ '''
+ return a list of vert loops, closed and open [(loop, closed)...]
+ '''
+
+ mainVertLoops = []
+ # 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)
+
+ # 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
+
+ if len(sbl) > 2:
+ return None
+
+ vert_used[i] = True
+
+ # do an edgeloop seek
+ if len(sbl) == 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:
+
+ 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]
+ # print len(mainVertLoops)
+ return mainVertLoops
+
+
+
+def skin2EdgeLoops(eloop1, eloop2, me, ob, MODE):
+
+ new_faces= [] #
+
+ # Make sure e1 loops is bigger then e2
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list