fix BGE bug #8668: Behavior of os.getcwd() is not consistent between operating systems
[blender-staging.git] / release / scripts / vertexpaint_selfshadow_ao.py
1 #!BPY
2 """
3 Name: 'Self Shadow VCols (AO)...'
4 Blender: 245
5 Group: 'VertexPaint'
6 Tooltip: 'Generate Fake Ambient Occlusion with vertex colors.'
7 """
8
9 __author__ = "Campbell Barton aka ideasman42"
10 __url__ = ["www.blender.org", "blenderartists.org", "www.python.org"]
11 __version__ = "0.1"
12 __bpydoc__ = """\
13
14 Self Shadow
15
16 This usript uses the angles between faces to shade the mesh,
17 and optionaly blur the shading to remove artifacts from spesific edges.
18 """
19
20 # ***** BEGIN GPL LICENSE BLOCK *****
21 #
22 # Script copyright (C) Campbell J Barton
23 #
24 # This program is free software; you can redistribute it and/or
25 # modify it under the terms of the GNU General Public License
26 # as published by the Free Software Foundation; either version 2
27 # of the License, or (at your option) any later version.
28 #
29 # This program is distributed in the hope that it will be useful,
30 # but WITHOUT ANY WARRANTY; without even the implied warranty of
31 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
32 # GNU General Public License for more details.
33 #
34 # You should have received a copy of the GNU General Public License
35 # along with this program; if not, write to the Free Software Foundation,
36 # Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
37 #
38 # ***** END GPL LICENCE BLOCK *****
39 # --------------------------------------------------------------------------
40
41 from Blender import Scene, Draw, sys, Window, Mathutils, Mesh
42 import bpy
43 import BPyMesh
44
45
46 def vertexFakeAO(me, PREF_BLUR_ITERATIONS, PREF_BLUR_RADIUS, PREF_MIN_EDLEN, PREF_CLAMP_CONCAVE, PREF_CLAMP_CONVEX, PREF_SHADOW_ONLY, PREF_SEL_ONLY):
47         Window.WaitCursor(1)
48         DotVecs = Mathutils.DotVecs
49         Ang= Mathutils.AngleBetweenVecs
50         
51         BPyMesh.meshCalcNormals(me)
52
53         vert_tone= [0.0] * len(me.verts)
54         vert_tone_count= [0] * len(me.verts)
55
56         min_tone=0
57         max_tone=0
58
59         for i, f in enumerate(me.faces):
60                 fc= f.cent
61                 fno = f.no
62                 
63                 for v in f.v:
64                         vno=v.no # get a scaled down normal.
65                         
66                         dot= DotVecs(vno, v.co) - DotVecs(vno, fc)
67                         vert_tone_count[v.index]+=1
68                         try:
69                                 a= Ang(vno, fno)
70                         except:
71                                 continue
72                         
73                         # Convex
74                         if dot>0:
75                                 a= min(PREF_CLAMP_CONVEX, a)
76                                 if not PREF_SHADOW_ONLY:
77                                         vert_tone[v.index] += a
78                         else:
79                                 a= min(PREF_CLAMP_CONCAVE, a)
80                                 vert_tone[v.index] -= a
81         
82         # average vert_tone_list into vert_tonef
83         for i, tones in enumerate(vert_tone):
84                 if vert_tone_count[i]:
85                         vert_tone[i] = vert_tone[i] / vert_tone_count[i]
86
87
88         # BLUR TONE
89         edge_lengths= [ ed.length for ed in me.edges]
90         
91         for i in xrange(PREF_BLUR_ITERATIONS):
92                 orig_vert_tone= list(vert_tone)
93                 for ii, ed in enumerate(me.edges):
94                         i1= ed.v1.index
95                         i2= ed.v2.index
96                         l= edge_lengths[ii]
97                         
98                         f=1.0
99                         if l > PREF_MIN_EDLEN and l < PREF_BLUR_RADIUS:
100                                 f= l/PREF_BLUR_RADIUS
101                                 
102                                 len_vert_tone_list_i1 = vert_tone_count[i1]
103                                 len_vert_tone_list_i2 = vert_tone_count[i2]
104                                         
105                                 if not len_vert_tone_list_i1: len_vert_tone_list_i1=1
106                                 if not len_vert_tone_list_i2: len_vert_tone_list_i2=1
107                                 
108                                 val1= (orig_vert_tone[i2]/len_vert_tone_list_i1)/ f
109                                 val2= (orig_vert_tone[i1]/len_vert_tone_list_i2)/ f
110                                 
111                                 vert_tone[i1]+= val1
112                                 vert_tone[i2]+= val2
113         
114
115         min_tone= min(vert_tone)
116         max_tone= max(vert_tone)
117         
118         #print min_tone, max_tone
119         
120         tone_range= max_tone-min_tone
121         if max_tone==min_tone:
122                 return
123         
124         for f in me.faces:
125                 if not PREF_SEL_ONLY or f.sel:
126                         f_col= f.col
127                         for i, v in enumerate(f):
128                                 col= f_col[i]
129                                 tone= vert_tone[v.index]
130                                 tone= (tone-min_tone)/tone_range
131                                 
132                                 col.r= int(tone*col.r)
133                                 col.g= int(tone*col.g)
134                                 col.b= int(tone*col.b)
135         
136         Window.WaitCursor(0)
137
138 def main():
139         sce= bpy.data.scenes.active
140         ob= sce.objects.active
141         
142         if not ob or ob.type != 'Mesh':
143                 Draw.PupMenu('Error, no active mesh object, aborting.')
144                 return
145         
146         me= ob.getData(mesh=1)
147         
148         PREF_BLUR_ITERATIONS= Draw.Create(1)    
149         PREF_BLUR_RADIUS= Draw.Create(0.05)
150         PREF_MIN_EDLEN= Draw.Create(0.01)
151         PREF_CLAMP_CONCAVE= Draw.Create(90)
152         PREF_CLAMP_CONVEX= Draw.Create(20)
153         PREF_SHADOW_ONLY= Draw.Create(0)
154         PREF_SEL_ONLY= Draw.Create(0)   
155         pup_block= [\
156         'Post AO Blur',\
157         ('  Iterations:', PREF_BLUR_ITERATIONS, 0, 40, 'Number times to blur the colors. (higher blurs more)'),\
158         ('  Blur Radius:', PREF_BLUR_RADIUS, 0.01, 40.0, 'How much distance effects blur transfur (higher blurs more).'),\
159         ('  Min EdgeLen:', PREF_MIN_EDLEN, 0.00001, 1.0, 'Minimim edge length to blur (very low values can cause errors).'),\
160         'Angle Clipping',\
161         ('  Highlight Angle:', PREF_CLAMP_CONVEX, 0, 180, 'Less then 180 limits the angle used in the tonal range.'),\
162         ('  Shadow Angle:', PREF_CLAMP_CONCAVE, 0, 180, 'Less then 180 limits the angle used in the tonal range.'),\
163         ('Shadow Only', PREF_SHADOW_ONLY, 'Dont calculate highlights for convex areas.'),\
164         ('Sel Faces Only', PREF_SEL_ONLY, 'Only apply to UV/Face selected faces (mix vpain/uvface select).'),\
165         ]
166         
167         if not Draw.PupBlock('SelfShadow...', pup_block):
168                 return
169         
170         PREF_BLUR_ITERATIONS= PREF_BLUR_ITERATIONS.val
171         PREF_BLUR_RADIUS= PREF_BLUR_RADIUS.val
172         PREF_MIN_EDLEN= PREF_MIN_EDLEN.val
173         PREF_CLAMP_CONCAVE= PREF_CLAMP_CONCAVE.val
174         PREF_CLAMP_CONVEX= PREF_CLAMP_CONVEX.val
175         PREF_SHADOW_ONLY= PREF_SHADOW_ONLY.val
176         PREF_SEL_ONLY= PREF_SEL_ONLY.val
177         
178         if not me.vertexColors:
179                 me.vertexColors= 1
180         
181         t= sys.time()
182         vertexFakeAO(me, PREF_BLUR_ITERATIONS, PREF_BLUR_RADIUS, PREF_MIN_EDLEN, PREF_CLAMP_CONCAVE, PREF_CLAMP_CONVEX, PREF_SHADOW_ONLY, PREF_SEL_ONLY)
183         print 'done in %.6f' % (sys.time()-t)
184 if __name__=='__main__':
185         main()
186