Welcome to mirror list, hosted at ThFree Co, Russian Federation.

vertexpaint_dirt.py « io « scripts « release - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 9f55d3bb04231f8c7141a49074123e454675c1c2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# bl_author = ["Campbell Barton aka ideasman42", "Keith Boshoff aka Wahooney"]
# bl_url = ["www.blender.org", "blenderartists.org", "www.python.org"]
# bl_version = "0.2"

# ***** 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 *****
# --------------------------------------------------------------------------

# History
#
# 2009-11-01: * 2.5 port by Keith "Wahooney" Boshoff
#              * Replaced old method with my own, speed is similar (about 0.001 sec on Suzanne)
#               but results are far more accurate
#

import bpy
import Mathutils
import math
import time

from Mathutils import Vector
from bpy.props import *

def applyVertexDirt(me, blur_iterations, blur_strength, clamp_dirt, clamp_clean, dirt_only, sel_only):
##    Window.WaitCursor(1)

    #BPyMesh.meshCalcNormals(me)

    vert_tone= [0.0] * len(me.verts)
    vert_tone_count= [0] * len(me.verts)

    # create lookup table for each vertex's connected vertices (via edges)
    con = [[] for i in range(len(me.verts))]

    min_tone=180.0
    max_tone=0.0

    # add connected verts
    for e in me.edges:
        con[e.verts[0]].append(e.verts[1])
        con[e.verts[1]].append(e.verts[0])

    for v in me.verts:
        vec = Vector()
        no = v.normal
        co = v.co

        # get the direction of the vectors between the vertex and it's connected vertices
        for c in con[v.index]:
            vec += Vector(me.verts[c].co - co).normalize()

        # normalize the vector by dividing by the number of connected verts
        vec /= len(con[v.index])

        # angle is the acos of the dot product between vert and connected verts normals
        ang = math.acos(no.dot(vec))

        # enforce min/max

        vert_tone[v.index] = max(clamp_clean, min(clamp_dirt, ang))

    # average vert_tone_list into vert_tonef
#    for i, tones in enumerate(vert_tone):
#        if vert_tone_count[i]:
#            vert_tone[i] = vert_tone[i] / vert_tone_count[i]

    # Below we use edges to blur along so the edges need counting, not the faces
    vert_tone_count=    [0] *    len(me.verts)
    for ed in me.edges:
        vert_tone_count[ed.verts[0]] += 1
        vert_tone_count[ed.verts[1]] += 1


    # Blur tone
    blur        = blur_strength
    blur_inv    = 1.0 - blur_strength

    for i in range(blur_iterations):

        # backup the original tones
        orig_vert_tone= list(vert_tone)

        for ed in me.edges:

            i1 = ed.verts[0]
            i2 = ed.verts[1]

            val1 = (orig_vert_tone[i2]*blur) +  (orig_vert_tone[i1]*blur_inv)
            val2 = (orig_vert_tone[i1]*blur) +  (orig_vert_tone[i2]*blur_inv)

            # Apply the ton divided by the number of faces connected
            vert_tone[i1] += val1 / max(vert_tone_count[i1], 1)
            vert_tone[i2] += val2 / max(vert_tone_count[i2], 1)


    min_tone= min(vert_tone)
    max_tone= max(vert_tone)

    print(min_tone)
    print(max_tone)
    print(clamp_clean)
    print(clamp_dirt)

    tone_range= max_tone-min_tone
    if max_tone==min_tone:
        return

    for lay in me.vertex_colors:
        if lay.active:
            active_col_layer = lay.data

    if not active_col_layer:
        return('CANCELLED', )

    for i, f in enumerate(me.faces):
        if not sel_only or f.sel:
            f_col = active_col_layer[i]

            f_col = [f_col.color1, f_col.color2, f_col.color3, f_col.color4]

            for j, v in enumerate(f.verts):
                col = f_col[j]
                tone = vert_tone[me.verts[v].index]
                tone = (tone-min_tone)/tone_range

                col[0] = tone*col[0]
                col[1] = tone*col[1]
                col[2] = tone*col[2]

##    Window.WaitCursor(0)


class VertexPaintDirt(bpy.types.Operator):
    '''This script uses the concavity of vertices to shade the mesh, and optionaly blur the shading to remove artifacts from spesific edges.'''

    bl_idname = "mesh.vertex_paint_dirt"
    bl_label = "Dirty Vertex Colors"
    bl_register = True
    bl_undo = True

    blur_strength = FloatProperty(name="Blur Strength", description="Blur strength per iteration", default=1.0, min=0.01, max=1.0)
    blur_iterations = IntProperty(name="Blur Iterations", description="Number times to blur the colors. (higher blurs more)", default=1, min=0, max=40)
    clean_angle = FloatProperty(name="Highlight Angle", description="Less then 90 limits the angle used in the tonal range", default=0.0, min=0.0, max=180.0)
    dirt_angle = FloatProperty(name="Dirt Angle", description="Less then 90 limits the angle used in the tonal range", default=180.0, min=0.0, max=180.0)
    dirt_only = BoolProperty(name="Dirt Only", description="Dont calculate cleans for convex areas", default=False)
    sel_faces_only = BoolProperty(name="Selected Faces Only", description="Only apply to UV/Face selected faces (mix vpain/uvface select)", default=False)

    def execute(self, context):
        sce= context.scene
        ob= context.object

        if not ob or ob.type != 'MESH':
            print('Error, no active mesh object, aborting.')
            print(ob)
            print(ob.type)
            return('CANCELLED',)

        me = ob.data

        t = time.time()

        applyVertexDirt(me, self.blur_iterations, self.blur_strength, math.radians(self.dirt_angle), math.radians(self.clean_angle), self.dirt_only, self.sel_faces_only)

        print('done in %.6f' % (time.time()-t))

        return('FINISHED',)


bpy.ops.add(VertexPaintDirt)

if __name__ == "__main__":
    bpy.ops.mesh.vertex_paint_dirt()