Added mesh_normal_smooth.py to contrib & svn.
authorBrendon Murphy <meta.androcto1@gmail.com>
Sat, 20 Nov 2010 23:08:15 +0000 (23:08 +0000)
committerBrendon Murphy <meta.androcto1@gmail.com>
Sat, 20 Nov 2010 23:08:15 +0000 (23:08 +0000)
mesh_normal_smooth.py [new file with mode: 0644]

diff --git a/mesh_normal_smooth.py b/mesh_normal_smooth.py
new file mode 100644 (file)
index 0000000..046ae94
--- /dev/null
@@ -0,0 +1,194 @@
+# mesh_normalsmooth_7.py Copyright (C) 2010, Dolf Veenvliet
+#
+# Relaxes selected vertices while retaining the shape as much as possible
+#
+# ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENCE BLOCK *****
+
+bl_addon_info = {
+    "name": "Normal Smooth",
+    "author": "Dolf Veenvliet",
+    "version": (7),
+    "blender": (2, 5, 5),
+    "api": 32738,
+    "location": "View3D > Specials > Normal Smooth ",
+    "description": "Smooth the vertex position based on the normals",
+    "warning": "",
+    "wiki_url": "",
+    "tracker_url": "",
+    "category": "Mesh"}
+    
+"""
+Usage:
+
+Launch from "W-menu" or from "Mesh -> Vertices -> Normal Smooth"
+
+Additional links:
+    Author Site: http://www.macouno.com
+    e-mail: dolf {at} macouno {dot} com
+"""
+
+import bpy, mathutils, math
+from bpy.props import IntProperty
+
+## Rotate one vector (vec1) towards another (vec2)
+## (rad = ammount of degrees to rotate in radians)
+def RotVtoV(vec1, vec2, rad):
+    cross = vec1.cross(vec2)
+    mat = mathutils.Matrix.Rotation(rad, 3, cross)
+    return (vec1 * mat)
+
+
+# Find the new coordinate for this verticle
+def smoothVert(v1, v1in, me):
+    
+    v1co = v1.co
+    v1no = v1.normal
+    
+    # List of verts not to check (don't check against yourself)
+    chk = [v1in]
+    newCo = []
+    
+    # Make sure there's faces, otherwise we do nothing
+    if len(me.faces):
+        
+        # Check every face
+        for f in me.faces:
+            
+            # Only check faces that this vert is in
+            if v1in in f.vertices:
+                
+                # Loop through all the verts in the face
+                for v2in in f.vertices:
+                    
+                    # Make sure you check every vert only once
+                    if not v2in in chk:
+                        
+                        chk.append(v2in)
+                        
+                        v2 = me.vertices[v2in]
+                        
+                        v2co = v2.co
+                        
+                        # Get the vector from one vert to the other
+                        vTov = v2co - v1co
+                        
+                        vLen = vTov.length
+                        
+                        # Use half the distance (actually 0.514 seems to be the specific nr to multiply by... just by experience)
+                        vLen *= 0.514
+                        
+                        # Get the normal rotated 90 degrees (pi * 0.5 = 90 degrees in radians) towards the original vert
+                        vNor = RotVtoV(v2.normal, vTov.normalize(), (math.pi * 0.5))
+                        
+                        # Make the vector the correct length
+                        vNor = vNor.normalize() * vLen
+                        
+                        # Add the vector to the vert position to get the correct coord
+                        vNor = v2co + vNor
+                        
+                        newCo.append(vNor)
+                        
+    # Calculate the new coord only if there's a result
+    if len(newCo):
+        
+        nC = mathutils.Vector()
+        
+        # Add all the new coordinates together
+        for c in newCo:
+            nC = nC + c
+            
+        # Divide the resulting vector by the total to get the average
+        nC = nC / len(newCo)
+        
+    # If there's no result, just return the original coord
+    else:
+        nC = v1co
+                    
+    return nC
+                    
+
+# Base function
+def normal_smooth(context):
+
+    ob = context.active_object
+
+    bpy.ops.object.mode_set(mode='OBJECT')
+    
+    vNew = {}
+    me = ob.data
+    
+    # loop through all verts
+    for v1 in me.vertices:
+        
+        # only smooth selected verts
+        if v1.select:
+            
+            v1in = v1.index
+            
+            # Get the new coords for this vert
+            vNew[v1in] = smoothVert(v1, v1in, me)
+            
+    # Only if they're anything new, can we apply anything
+    if len(vNew):
+        
+        # Get the indexes for all verts to adapt
+        for k in vNew.keys():
+            
+            # Set the vert's new coords
+            me.vertices[k].co = vNew[k]
+            
+    bpy.ops.object.mode_set(mode='EDIT')
+
+    
+class NormalSmooth(bpy.types.Operator):
+    '''Smoothes verticle position based on vertex normals'''
+    bl_idname = 'normal.smooth'
+    bl_label = 'Normal Smooth'
+    bl_options = {'REGISTER', 'UNDO'}
+
+
+    iterations = IntProperty(name="Smoothing iterations",
+                default=1, min=0, max=100, soft_min=0, soft_max=10)
+    
+    @classmethod
+    def poll(cls, context):
+        obj = context.active_object
+        return (obj and obj.type == 'MESH')
+
+    def execute(self, context):
+        for i in range(0,self.iterations):
+            normal_smooth(context)
+        return {'FINISHED'}
+
+
+def menu_func(self, context):
+    self.layout.operator(NormalSmooth.bl_idname, text="Normal Smooth")
+
+
+def register():
+    bpy.types.VIEW3D_MT_edit_mesh_specials.append(menu_func)
+    bpy.types.VIEW3D_MT_edit_mesh_vertices.append(menu_func)
+
+def unregister():
+    bpy.types.VIEW3D_MT_edit_mesh_specials.remove(menu_func)
+    bpy.types.VIEW3D_MT_edit_mesh_vertices.remove(menu_func)
+
+if __name__ == "__main__":
+    register()
\ No newline at end of file