diff options
author | Campbell Barton <ideasman42@gmail.com> | 2006-01-12 15:39:14 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2006-01-12 15:39:14 +0300 |
commit | 5dba8e798a21e7a5728e3f286a498a0430248c77 (patch) | |
tree | d65944dc1412e0bb65d6dc251c38d5ec111f43a8 | |
parent | 6ded7d67d16c49a84e309361fd4fce9a4f999300 (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.
-rw-r--r-- | release/scripts/mesh_cleanup.py | 184 |
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() + |