diff --git a/release/scripts/bpymodules/BPyMesh.py b/release/scripts/bpymodules/BPyMesh.py index e290f4b9abf..81bca31e858 100644 --- a/release/scripts/bpymodules/BPyMesh.py +++ b/release/scripts/bpymodules/BPyMesh.py @@ -308,17 +308,72 @@ me.faces.extend([[me.verts[ii] for ii in i] for i in indices]) ''' +def meshPrettyNormals(me): + ''' + takes a mesh and returns very high quality normals 1 normal per vertex. + The normals should be correct, indipendant of topology + ''' + Ang= Blender.Mathutils.AngleBetweenVecs + Vector= Blender.Mathutils.Vector + SMALL_NUM=0.000001 + # Weight the edge normals by total angle difference + # EDGE METHOD + + vertNormals= [ Vector() for v in xrange(len(me.verts)) ] + edges={} + for f in me.faces: + for i in xrange(len(f.v)): + i1, i2= f.v[i].index, f.v[i-1].index + if i11: + totAngDiff=0 + for j in reversed(xrange(len_fnos)): + for k in reversed(xrange(j)): + #print j,k + try: + totAngDiff+= (Ang(fnos[j], fnos[k])) # /180 isnt needed, just to keeop the vert small. + except: + pass # Zero length face + + # print totAngDiff + if totAngDiff > SMALL_NUM: + + ''' + average_no= Vector() + for no in fnos: + average_no+=no + ''' + average_no= reduce(lambda a,b: a+b, fnos, Vector()) + fnos.append(average_no*totAngDiff) # average no * total angle diff + else: + fnos[0] + else: + fnos.append(fnos[0]) + + for ed, v in edges.iteritems(): + vertNormals[ed[0]]+= v[-1] + vertNormals[ed[1]]+= v[-1] + for v in vertNormals: + v.normalize() + return vertNormals - - -from Blender import * - def pointInsideMesh(ob, pt): - Intersect = Mathutils.Intersect # 2 less dict lookups. - Vector = Mathutils.Vector + Intersect = Blender.Mathutils.Intersect # 2 less dict lookups. + Vector = Blender.Mathutils.Vector def ptInFaceXYBounds(f, pt): @@ -367,7 +422,7 @@ def pointInsideMesh(ob, pt): return False - obImvMat = Mathutils.Matrix(ob.matrixWorld) + obImvMat = Blender.Mathutils.Matrix(ob.matrixWorld) obImvMat.invert() pt.resize4D() obSpacePt = pt* obImvMat @@ -380,19 +435,14 @@ def pointInsideMesh(ob, pt): return len([None for f in me.faces if ptInFaceXYBounds(f, obSpacePt) if faceIntersect(f)]) % 2 - - - - - - - - - - - - - +# Get face center +def faceCent(f): + cent= Blender.Mathutils.Vector() + l= len(f.v) + for v in f.v: + cent+=v.co + return cent*(1.0/l) + # NMesh wrapper Vector= Blender.Mathutils.Vector diff --git a/release/scripts/vertexpaint_selfshadow_ao.py b/release/scripts/vertexpaint_selfshadow_ao.py new file mode 100644 index 00000000000..7f5219f7f8a --- /dev/null +++ b/release/scripts/vertexpaint_selfshadow_ao.py @@ -0,0 +1,173 @@ +#!BPY +""" +Name: 'Self Shadow VCols (AO)...' +Blender: 241 +Group: 'VertexPaint' +Tooltip: 'Generate Fake Ambient Occlusion with vertex colors.' +""" + +__author__ = ["Campbell Barton"] +__url__ = ("blender", "elysiun", "http://members.iinet.net.au/~cpbarton/ideasman/") +__version__ = "0.1" +__bpydoc__ = """\ + +Clean Weight + +This Script is to be used only in weight paint mode, +It removes very low weighted verts from the current group with a weight option. +""" + +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# Script copyright (C) Campbell J Barton +# +# 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 ***** +# -------------------------------------------------------------------------- + +from Blender import * +import BPyMesh +reload(BPyMesh) + + +def vertexFakeAO(me, PREF_BLUR_ITERATIONS, PREF_BLUR_SCALE, PREF_SEL_ONLY): + + V=Mathutils.Vector + M=Mathutils.Matrix + Ang= Mathutils.AngleBetweenVecs + + nos= BPyMesh.meshPrettyNormals(me) + + vert_tone= [0.0] * len(me.verts) + vert_tone_list= [ [] for i in xrange(len(me.verts)) ] + ed_face_users = [ [] for i in xrange(len(me.edges)) ] + + fcent= [BPyMesh.faceCent(f) for f in me.faces] + + min_tone=0 + max_tone=0 + + for i, f in enumerate(me.faces): + c= fcent[i] + fno = f.no*0.0001 + for v in f.v: + #vno=v.no # ugly normal + vno= nos[v.index]*0.0001 # pretty notrmal + + l1= (c-v.co).length + l2= ((c+fno) - (v.co+vno)).length + + if abs(l1-l2) < 0.0000001: + vert_tone_list[v.index].append(0) + continue # look at the next vert + + elif l1l2 + convex=-1# concave, darken. + #if v.sel: print "concave" + a= -Ang(vno, fno) + + #a= Ang(vno, fno) * convex + + #vert_tone[v.index] += a + vert_tone_list[v.index].append(a) + + + # average vert_tone_list into vert_tone + for i, tones in enumerate(vert_tone_list): + if tones: + tone= 0.0 + for t in tones: + tone+=t + tone= tone/len(tones) + + vert_tone[i]= tone + + + + # BLUR TONE + edge_lengths= [ ((ed.v1.co-ed.v2.co).length + 1) * PREF_BLUR_SCALE for ed in me.edges] + + for i in xrange(PREF_BLUR_ITERATIONS): + orig_vert_tone= list(vert_tone) + for ii, ed in enumerate(me.edges): + i1= ed.v1.index + i2= ed.v2.index + l= edge_lengths[ii] + + vert_tone[i1]+= (orig_vert_tone[i2]/len(vert_tone_list[i1]))/ l + vert_tone[i2]+= (orig_vert_tone[i1]/len(vert_tone_list[i2]))/ l + + + min_tone= min(vert_tone) + max_tone= max(vert_tone) + + #print 'min', min_tone, 'max', max_tone + + tone_range= max_tone-min_tone + if max_tone==min_tone: + return + SELFLAG= Mesh.FaceFlags.SELECT + for f in me.faces: + if not PREF_SEL_ONLY or f.flag & SELFLAG: + for i, v in enumerate(f.v): + tone= vert_tone[v.index] + tone= tone-min_tone + tone= (tone/tone_range) + + tone= int(tone*255) + f.col[i].r= f.col[i].g= f.col[i].b= tone + + +def main(): + scn= Scene.GetCurrent() + ob= scn.getActiveObject() + + if not ob or ob.getType() != 'Mesh': + Draw.PupMenu('Error, no active mesh object, aborting.') + return + + me= ob.getData(mesh=1) + + if not me.faceUV: + Draw.PupMenu('Error, The active mesh does not have texface/vertex colors. aborting') + return + + PREF_BLUR_ITERATIONS= Draw.Create(0) + PREF_BLUR_SCALE= Draw.Create(1.0) + PREF_SEL_ONLY= Draw.Create(1) + pup_block= [\ + 'Post AO Blur',\ + (' Iterations:', PREF_BLUR_ITERATIONS, 1, 40, 'Number times to blur the colors. (higher blurs more)'),\ + (' Blur Radius:', PREF_BLUR_SCALE, 0.1, 10.0, 'How much distance effects blur transfur (higher blurs more).'),\ + ('Sel Faces Only', PREF_SEL_ONLY, 'Only apply to UV/Face selected faces (mix vpain/uvface select).'),\ + ] + + if not Draw.PupBlock('Clean Selected Meshes...', pup_block): + return + + PREF_BLUR_ITERATIONS= PREF_BLUR_ITERATIONS.val + PREF_BLUR_SCALE= PREF_BLUR_SCALE.val + PREF_SEL_ONLY= PREF_SEL_ONLY.val + + vertexFakeAO(me, PREF_BLUR_ITERATIONS, PREF_BLUR_SCALE, PREF_SEL_ONLY) + +if __name__=='__main__': + main() +