blender/release/scripts/op/vertexpaint_dirt.py

191 lines
5.6 KiB
Python
Raw Normal View History

# ***** 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,
2010-02-12 13:34:04 +00:00
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
# <pep8 compliant>
# History
#
# Originally written by Campbell Barton aka ideasman42
#
# 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 math
import time
from mathutils import Vector
from bpy.props import *
2009-12-13 22:48:11 +00:00
def applyVertexDirt(me, blur_iterations, blur_strength, clamp_dirt, clamp_clean, dirt_only):
## Window.WaitCursor(1)
#BPyMesh.meshCalcNormals(me)
2010-08-18 03:42:26 +00:00
vert_tone = [0.0] * len(me.vertices)
2009-12-13 22:48:11 +00:00
min_tone = 180.0
max_tone = 0.0
# create lookup table for each vertex's connected vertices (via edges)
con = []
2010-08-18 03:42:26 +00:00
con = [[] for i in range(len(me.vertices))]
# add connected verts
for e in me.edges:
2010-08-18 03:42:26 +00:00
con[e.vertices[0]].append(e.vertices[1])
con[e.vertices[1]].append(e.vertices[0])
2010-08-18 03:42:26 +00:00
for i, v in enumerate(me.vertices):
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[i]:
2010-08-18 03:42:26 +00:00
vec += (me.vertices[c].co - co).normalize()
# normalize the vector by dividing by the number of connected verts
tot_con = len(con[i])
if tot_con == 0:
continue
vec /= tot_con
# angle is the acos of the dot product between vert and connected verts normals
ang = math.acos(no.dot(vec))
# enforce min/max
ang = max(clamp_dirt, ang)
if not dirt_only:
ang = min(clamp_clean, ang)
vert_tone[i] = ang
# blur tones
for i in range(blur_iterations):
# backup the original tones
orig_vert_tone = list(vert_tone)
# use connected verts look up for blurring
for j, c in enumerate(con):
for v in c:
vert_tone[j] += blur_strength * orig_vert_tone[v]
vert_tone[j] /= len(c) * blur_strength + 1
min_tone = min(vert_tone)
max_tone = max(vert_tone)
# debug information
# print(min_tone * 2 * math.pi)
# print(max_tone * 2 * math.pi)
# print(clamp_clean)
# print(clamp_dirt)
2009-12-13 22:48:11 +00:00
tone_range = max_tone - min_tone
if not tone_range:
return
active_col_layer = None
if len(me.vertex_colors):
for lay in me.vertex_colors:
if lay.active:
active_col_layer = lay.data
else:
bpy.ops.mesh.vertex_color_add()
me.vertex_colors[0].active = True
active_col_layer = me.vertex_colors[0].data
if not active_col_layer:
2009-11-07 22:12:03 +00:00
return('CANCELLED', )
for i, f in enumerate(me.faces):
Apply first pass of edits to rna values from rna_booleans.txt. These are not animated and are best not change names like this too late in the release. ActionGroup.selected -> select: boolean Action Group is selected BezierSplinePoint.hidden -> hide: boolean Visibility status BezierSplinePoint.selected_control_point -> select_control_point: boolean Control point selection status BezierSplinePoint.selected_handle1 -> select_left_handle: boolean Handle 1 selection status BezierSplinePoint.selected_handle2 -> select_right_handle: boolean Handle 2 selection status Bone.restrict_select -> hide_select: boolean Bone is able to be selected Bone.selected -> select: boolean CurveMapPoint.selected -> select: boolean Selection state of the curve point EditBone.restrict_select -> hide_select: boolean Bone is able to be selected EditBone.selected -> select: boolean EditBone.selected_head -> select_head: boolean EditBone.selected_tail -> select_tail: boolean EditBone.locked -> lock: boolean Bone is not able to be transformed when in Edit Mode EditBone.hidden -> hide: boolean Bone is not visible when in Edit Mode NEGATE * FCurve.disabled -> enabled: boolean F-Curve could not be evaluated in past, so should be skipped when evaluating FCurve.locked -> lock: boolean F-Curve's settings cannot be edited FCurve.muted -> mute: boolean F-Curve is not evaluated FCurve.selected -> select: boolean F-Curve is selected for editing NEGATE * FCurve.visible -> hide: boolean F-Curve and its keyframes are shown in the Graph Editor graphs FCurveSample.selected -> select: boolean Selection status GPencilFrame.selected -> select: boolean Frame is selected for editing in the DopeSheet GPencilLayer.locked -> lock: boolean Protect layer from further editing and/or frame changes GPencilLayer.selected -> select: boolean Layer is selected for editing in the DopeSheet Keyframe.selected -> select: boolean Control point selection status Keyframe.selected_handle1 -> select_left_handle: boolean Handle 1 selection status Keyframe.selected_handle2 -> select_right_handle: boolean Handle 2 selection status MeshEdge.selected -> select: boolean MeshEdge.hidden -> hide: boolean MeshFace.hidden -> hide: boolean MeshFace.selected -> select: boolean MeshVertex.hidden -> hide: boolean MeshVertex.selected -> select: boolean MotionPathVert.selected -> select: boolean Path point is selected for editing NlaStrip.selected -> select: boolean NLA Strip is selected NlaTrack.locked -> lock: boolean NLA Track is locked NlaTrack.muted -> mute: boolean NLA Track is not evaluated NlaTrack.selected -> select: boolean NLA Track is selected Object.restrict_render -> hide_render: boolean Restrict renderability Object.restrict_select -> hide_select: boolean Restrict selection in the viewport Object.restrict_view -> hide: boolean Restrict visibility in the viewport Object.selected -> select: boolean Object selection state ObjectBase.selected -> select: boolean Object base selection state PoseBone.selected -> select: boolean Sequence.right_handle_selected -> select_right_handle: boolean Sequence.selected -> select: boolean SplinePoint.selected -> select_control_point: boolean Selection status TimelineMarker.selected -> select: boolean Marker selection state Sequence.left_handle_selected -> select_left_handle: boolean ActionGroup.locked -> lock: boolean Action Group is locked Bone.hidden -> hide: boolean Bone is not visible when it is not in Edit Mode (i.e. in Object or Pose Modes) SplinePoint.hidden -> hide: boolean Visibility status FModifier.muted -> mute: boolean F-Curve Modifier will not be evaluated note: rebaned uv_select to select_uv
2010-07-15 16:56:04 +00:00
if not me.use_paint_mask or f.select:
f_col = active_col_layer[i]
f_col = [f_col.color1, f_col.color2, f_col.color3, f_col.color4]
2010-08-18 03:42:26 +00:00
for j, v in enumerate(f.vertices):
col = f_col[j]
2010-08-18 03:42:26 +00:00
tone = vert_tone[me.vertices[v].index]
2009-12-13 22:48:11 +00:00
tone = (tone - min_tone) / tone_range
if dirt_only:
tone = min(tone, 0.5)
tone *= 2
2009-12-13 22:48:11 +00:00
col[0] = tone * col[0]
col[1] = tone * col[1]
col[2] = tone * col[2]
## Window.WaitCursor(0)
2009-12-13 22:48:11 +00:00
class VertexPaintDirt(bpy.types.Operator):
bl_idname = "paint.vertex_color_dirt"
bl_label = "Dirty Vertex Colors"
bl_options = {'REGISTER', 'UNDO'}
2009-12-13 22:48:11 +00:00
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=180.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=0.0, min=0.0, max=180.0)
dirt_only = BoolProperty(name="Dirt Only", description="Dont calculate cleans for convex areas", default=False)
def execute(self, context):
obj = context.object
if not obj or obj.type != 'MESH':
print('Error, no active mesh object, aborting')
return('CANCELLED',)
mesh = obj.data
t = time.time()
applyVertexDirt(mesh, self.properties.blur_iterations, self.properties.blur_strength, math.radians(self.properties.dirt_angle), math.radians(self.properties.clean_angle), self.properties.dirt_only)
2009-12-13 22:48:11 +00:00
print('Dirt calculated in %.6f' % (time.time() - t))
return {'FINISHED'}
def register():
pass
def unregister():
pass
if __name__ == "__main__":
register()