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>2006-01-12 15:39:14 +0300
committerCampbell Barton <ideasman42@gmail.com>2006-01-12 15:39:14 +0300
commit5dba8e798a21e7a5728e3f286a498a0430248c77 (patch)
treed65944dc1412e0bb65d6dc251c38d5ec111f43a8 /release
parent6ded7d67d16c49a84e309361fd4fce9a4f999300 (diff)
Renamed clean_mesh.py to mesh_cleanup.py
Rewrote to use Kens Mesh module, much faster, cleaner and nicer UI. - Another use for PupBlock.
Diffstat (limited to 'release')
-rw-r--r--release/scripts/mesh_cleanup.py184
1 files changed, 184 insertions, 0 deletions
diff --git a/release/scripts/mesh_cleanup.py b/release/scripts/mesh_cleanup.py
new file mode 100644
index 00000000000..09b1ef7376c
--- /dev/null
+++ b/release/scripts/mesh_cleanup.py
@@ -0,0 +1,184 @@
+#!BPY
+"""
+Name: 'Clean meshes'
+Blender: 228
+Group: 'Mesh'
+Tooltip: 'Clean unused data from all selected mesh objects.'
+"""
+from Blender import *
+from Blender.Mathutils import TriangleArea
+
+def rem_free_verts(me):
+ vert_users = [0] * len(me.verts)
+ for f in me.faces:
+ for v in f.v:
+ vert_users[v.index]+=1
+
+ for e in me.edges:
+ for v in e: # loop on edge verts
+ vert_users[v.index]+=1
+
+ verts_free = []
+ for i, users in enumerate(vert_users):
+ if not users:
+ verts_free.append(i)
+
+ if verts_free:
+ pass
+ me.verts.delete(verts_free)
+ return len(verts_free)
+
+def rem_free_edges(me, limit=None):
+ ''' Only remove based on limit if a limit is set, else remove all '''
+ def sortPair(a,b):
+ return min(a,b), max(a,b)
+
+ edgeDict = {} # will use a set when python 2.4 is standard.
+
+ for f in me.faces:
+ for i in xrange(len(f.v)):
+ edgeDict[sortPair(f.v[i].index, f.v[i-1].index)] = None
+
+ edges_free = []
+ for e in me.edges:
+ if not edgeDict.has_key(sortPair(e.v1.index, e.v2.index)):
+ edges_free.append(e)
+
+ if limit != None:
+ edges_free = [e for e in edges_free if (e.v1.co-e.v2.co).length <= limit]
+
+ me.edges.delete(edges_free)
+ return len(edges_free)
+
+def rem_area_faces(me, limit=0.001):
+ ''' Faces that have an area below the limit '''
+ def faceArea(f):
+ if len(f.v) == 3:
+ return TriangleArea(f.v[0].co, f.v[1].co, f.v[2].co)
+ elif len(f.v) == 4:
+ return\
+ TriangleArea(f.v[0].co, f.v[1].co, f.v[2].co) +\
+ TriangleArea(f.v[0].co, f.v[2].co, f.v[3].co)
+ rem_faces = [f for f in me.faces if faceArea(f) <= limit]
+ if rem_faces:
+ me.faces.delete( 0, rem_faces )
+ return len(rem_faces)
+
+def rem_perimeter_faces(me, limit=0.001):
+ ''' Faces whos combine edge length is below the limit '''
+ def faceEdLen(f):
+ if len(f.v) == 3:
+ return\
+ (f.v[0].co-f.v[1].co).length +\
+ (f.v[1].co-f.v[2].co).length +\
+ (f.v[2].co-f.v[0].co).length
+ elif len(f.v) == 4:
+ return\
+ (f.v[0].co-f.v[1].co).length +\
+ (f.v[1].co-f.v[2].co).length +\
+ (f.v[2].co-f.v[3].co).length +\
+ (f.v[3].co-f.v[0].co).length
+ rem_faces = [f for f in me.faces if faceEdLen(f) <= limit]
+ if rem_faces:
+ me.faces.delete( 0, rem_faces )
+ return len(rem_faces)
+
+def main():
+
+ def getLimit(text):
+ return Draw.PupFloatInput(text, 0.001, 0.0, 1.0, 0.1, 4)
+
+
+ scn = Scene.GetCurrent()
+ obsel = Object.GetSelected()
+ actob = scn.getActiveObject()
+
+ is_editmode = Window.EditMode()
+
+ # Edit mode object is not active, add it to the list.
+ if is_editmode and (not actob.sel):
+ obsel.append(actob)
+
+ meshes = [ob.getData(mesh=1) for ob in obsel if ob.getType() == 'Mesh']
+
+
+ #====================================#
+ # Popup menu to select the functions #
+ #====================================#
+ '''
+ if not meshes:
+ Draw.PupMenu('ERROR%t|no meshes in selection')
+ return
+ method = Draw.PupMenu("""
+Clean Mesh, Remove...%t|
+Verts: free standing|
+Edges: not in a face|
+Edges: below a length|
+Faces: below an area|%l|
+All of the above|""")
+ if method == -1:
+ return
+
+ if method >= 3:
+ limit = getLimit('threshold: ')
+
+ print 'method', method
+ '''
+
+
+ CLEAN_VERTS_FREE = Draw.Create(1)
+ CLEAN_EDGE_NOFACE = Draw.Create(0)
+ CLEAN_EDGE_SMALL = Draw.Create(0)
+ CLEAN_FACE_PERIMETER = Draw.Create(0)
+ CLEAN_FACE_SMALL = Draw.Create(0)
+ limit = Draw.Create(0.01)
+
+ # Get USER Options
+
+ pup_block = [\
+ ('Verts: free', CLEAN_VERTS_FREE, 'Remove verts that are not used by an edge or a face.'),\
+ ('Edges: free', CLEAN_EDGE_NOFACE, 'Remove edges that are not in a face.'),\
+ ('Edges: short', CLEAN_EDGE_SMALL, 'Remove edges that are below the length limit.'),\
+ ('Faces: small perimeter', CLEAN_FACE_PERIMETER, 'Remove faces below the perimeter limit.'),\
+ ('Faces: small area', CLEAN_FACE_SMALL, 'Remove faces below the area limit (may remove faces stopping T-face artifacts).'),\
+ ('limit: ', limit, 0.001, 1.0, 'Limit used for the area and length tests above (a higher limit will remove more data).'),\
+ ]
+
+
+ if not Draw.PupBlock('Clean Selected Meshes...', pup_block):
+ return
+
+
+ CLEAN_VERTS_FREE = CLEAN_VERTS_FREE.val
+ CLEAN_EDGE_NOFACE = CLEAN_EDGE_NOFACE.val
+ CLEAN_EDGE_SMALL = CLEAN_EDGE_SMALL.val
+ CLEAN_FACE_PERIMETER = CLEAN_FACE_PERIMETER.val
+ CLEAN_FACE_SMALL = CLEAN_FACE_SMALL.val
+ limit = limit.val
+
+ if is_editmode: Window.EditMode(0)
+
+ rem_face_count = rem_edge_count = rem_vert_count = 0
+
+ for me in meshes:
+ if CLEAN_FACE_SMALL:
+ rem_face_count += rem_area_faces(me, limit)
+
+ if CLEAN_FACE_PERIMETER:
+ rem_face_count += rem_perimeter_faces(me, limit)
+
+ if CLEAN_EDGE_SMALL: # for all use 2- remove all edges.
+ rem_edge_count += rem_free_edges(me, limit)
+
+ if CLEAN_EDGE_NOFACE:
+ rem_edge_count += rem_free_edges(me)
+
+ if CLEAN_VERTS_FREE:
+ rem_vert_count += rem_free_verts(me)
+
+ if is_editmode: Window.EditMode(0)
+ Draw.PupMenu('Removed from ' + str(len(meshes)) +' Mesh(es)%t|' + 'Verts:' + str(rem_vert_count) + ' Edges:' + str(rem_edge_count) + ' Faces:' + str(rem_face_count))
+
+if __name__ == '__main__':
+ main()
+