diff options
author | Folkert de Vries <flokkievids@gmail.com> | 2015-07-10 15:57:23 +0300 |
---|---|---|
committer | Tamito Kajiyama <rd6t-kjym@asahi-net.or.jp> | 2015-07-10 17:15:56 +0300 |
commit | eeeb845d33e81afbc8ed127e6ab4ae7b18472a54 (patch) | |
tree | 78f8f3ecf9c4dd3bf4383ccc73520bcd2c6b2c7b | |
parent | 7837f0e8332f3726e0322b0c48b0da4d7c2d5813 (diff) |
Freestyle: new stroke modifiers
This patch introduces a couple new stroke modifiers. The ones currently implemented are based on prototypes by @kjym3 and myself.
The new modifiers:
- Tangent
- Thickness noise
- Crease Angle
- Simplification
- Curvature 3D
The documentation for these new modifier types can be found [[ http://www.blender.org/manual/render/freestyle/parameter_editor/index.html | in the manual ]]:
{F134441}
(left: AnisotropicThicknessShader, right: NoiseThicknessShader)
{F140499}
(left: Curvature 3D, right: Simplification)
Author: Folkert de Vries (flokkievids)
Reviewers: kjym3
Subscribers: #user_interface, plasmasolutions, kjym3
Projects: #bf_blender
Differential Revision: https://developer.blender.org/D963
-rw-r--r-- | release/scripts/freestyle/modules/freestyle/utils.py | 180 | ||||
-rw-r--r-- | release/scripts/freestyle/modules/parameter_editor.py | 401 | ||||
-rw-r--r-- | release/scripts/startup/bl_ui/properties_freestyle.py | 100 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/linestyle.c | 311 | ||||
-rw-r--r-- | source/blender/blenloader/intern/readfile.c | 73 | ||||
-rw-r--r-- | source/blender/blenloader/intern/writefile.c | 72 | ||||
-rw-r--r-- | source/blender/freestyle/intern/python/BPy_FrsNoise.cpp | 32 | ||||
-rw-r--r-- | source/blender/freestyle/intern/python/BPy_FrsNoise.h | 2 | ||||
-rw-r--r-- | source/blender/freestyle/intern/stroke/BasicStrokeShaders.cpp | 2 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_linestyle_types.h | 128 | ||||
-rw-r--r-- | source/blender/makesrna/RNA_access.h | 13 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_linestyle.c | 264 |
12 files changed, 1514 insertions, 64 deletions
diff --git a/release/scripts/freestyle/modules/freestyle/utils.py b/release/scripts/freestyle/modules/freestyle/utils.py index 41d2297f723..c66426824c0 100644 --- a/release/scripts/freestyle/modules/freestyle/utils.py +++ b/release/scripts/freestyle/modules/freestyle/utils.py @@ -39,9 +39,11 @@ __all__ = ( "iter_material_value", "iter_t2d_along_stroke", "material_from_fedge", + "normal_at_I0D", "pairwise", "phase_to_direction", "rgb_to_bw", + "simplify", "stroke_curvature", "stroke_normal", "StrokeCollector", @@ -66,8 +68,22 @@ from freestyle.types import ( from mathutils import Vector from functools import lru_cache, namedtuple -from math import cos, sin, pi -from itertools import tee +from math import cos, sin, pi, atan2 +from itertools import tee, compress + +# -- types -- # + +# A named tuple primitive used for storing data that has an upper and +# lower bound (e.g., thickness, range and certain other values) +class BoundedProperty(namedtuple("BoundedProperty", ["min", "max", "delta"])): + def __new__(cls, minimum, maximum, delta=None): + if delta is None: + delta = abs(maximum - minimum) + return super().__new__(cls, minimum, maximum, delta) + + def interpolate(self, val): + result = (self.max - val) / self.delta + return 1.0 - bound(0, result, 1) # -- real utility functions -- # @@ -76,7 +92,6 @@ def rgb_to_bw(r, g, b): """Method to convert rgb to a bw intensity value.""" return 0.35 * r + 0.45 * g + 0.2 * b - def bound(lower, x, higher): """Returns x bounded by a maximum and minimum value. Equivalent to: return min(max(x, lower), higher) @@ -84,7 +99,6 @@ def bound(lower, x, higher): # this is about 50% quicker than min(max(x, lower), higher) return (lower if x <= lower else higher if x >= higher else x) - def get_strokes(): """Get all strokes that are currently available""" return tuple(map(Operators().get_stroke_from_index, range(Operators().get_strokes_size()))) @@ -118,8 +132,60 @@ def material_from_fedge(fe): material = right if (right.priority > left.priority) else left return material -# -- General helper functions -- # +def bounding_box(stroke): + """ + Returns the maximum and minimum coordinates (the bounding box) of the stroke's vertices + """ + x, y = zip(*(svert.point for svert in stroke)) + return (Vector((min(x), min(y))), Vector((max(x), max(y)))) +def normal_at_I0D(it: Interface0DIterator) -> Vector: + """Normal at an Interface0D object. In contrast to Normal2DF0D this + function uses the actual data instead of underlying Fedge objects. + """ + if it.at_last and it.is_begin: + # corner-case + return Vector((0, 0)) + elif it.at_last: + it.decrement() + a, b = it.object, next(it) + elif it.is_begin: + a, b = it.object, next(it) + # give iterator back in original state + it.decrement() + elif it.is_end: + # just fail hard: this shouldn not happen + raise StopIteration() + else: + # this case sometimes has a small difference with Normal2DF0D (1e-3 -ish) + it.decrement() + a = it.object + curr, b = next(it), next(it) + # give iterator back in original state + it.decrement() + return (b.point - a.point).orthogonal().normalized() + +def angle_x_normal(it: Interface0DIterator): + """unsigned angle between a Point's normal and the X axis, in radians""" + normal = normal_at_I0D(it) + return abs(atan2(normal[1], normal[0])) + +def curvature_from_stroke_vertex(svert): + """The 3D curvature of an stroke vertex' underlying geometry + The result is None or in the range [-inf, inf]""" + c1 = svert.first_svertex.curvatures + c2 = svert.second_svertex.curvatures + if c1 is None and c2 is None: + Kr = None + elif c1 is None: + Kr = c2[4] + elif c2 is None: + Kr = c1[4] + else: + Kr = c1[4] + svert.t2d * (c2[4] - c1[4]) + return Kr + +# -- General helper functions -- # @lru_cache(maxsize=32) def phase_to_direction(length): @@ -134,9 +200,74 @@ def phase_to_direction(length): results.append((phase, Vector((cos(2 * pi * phase), sin(2 * pi * phase))))) return results -# A named tuple primitive used for storing data that has an upper and -# lower bound (e.g., thickness, range and certain values) -BoundedProperty = namedtuple("BoundedProperty", ["min", "max", "delta"]) + + +# -- simplification of a set of points; based on simplify.js by Vladimir Agafonkin -- +# https://mourner.github.io/simplify-js/ + +def getSquareSegmentDistance(p, p1, p2): + """ + Square distance between point and a segment + """ + x, y = p1 + + dx, dy = (p2 - p1) + + if dx or dy: + t = ((p.x - x) * dx + (p.y - y) * dy) / (dx * dx + dy * dy) + + if t > 1: + x, y = p2 + elif t > 0: + x += dx * t + y += dy * t + + dx, dy = p.x - x, p.y - y + return dx * dx + dy * dy + + +def simplifyDouglasPeucker(points, tolerance): + length = len(points) + markers = [0] * length + + first = 0 + last = length - 1 + + first_stack = [] + last_stack = [] + + new_points = [] + + markers[first] = 1 + markers[last] = 1 + + while last: + max_sqdist = 0 + + for i in range(first, last): + sqdist = getSquareSegmentDistance(points[i], points[first], points[last]) + + if sqdist > max_sqdist: + index = i + max_sqdist = sqdist + + if max_sqdist > tolerance: + markers[index] = 1 + + first_stack.append(first) + last_stack.append(index) + + first_stack.append(index) + last_stack.append(last) + + first = first_stack.pop() if first_stack else None + last = last_stack.pop() if last_stack else None + + return tuple(compress(points, markers)) + +def simplify(points, tolerance): + """Simplifies a set of points""" + return simplifyDouglasPeucker(points, tolerance * tolerance) class BoundingBox: @@ -346,7 +477,6 @@ def iter_distance_along_stroke(stroke): # -- mathematical operations -- # - def stroke_curvature(it): """ Compute the 2D curvature at the stroke vertex pointed by the iterator 'it'. @@ -390,21 +520,23 @@ def stroke_normal(stroke): for use in geometry modifiers it is advised to cast this generator function to a tuple or list """ - n = len(stroke) - 1 - - for i, svert in enumerate(stroke): - if i == 0: - e = stroke[i + 1].point - svert.point - yield Vector((e[1], -e[0])).normalized() - elif i == n: - e = svert.point - stroke[i - 1].point - yield Vector((e[1], -e[0])).normalized() - else: - e1 = stroke[i + 1].point - svert.point - e2 = svert.point - stroke[i - 1].point - n1 = Vector((e1[1], -e1[0])).normalized() - n2 = Vector((e2[1], -e2[0])).normalized() - yield (n1 + n2).normalized() + # n = len(stroke) - 1 + it = iter(stroke) + yield from (normal_at_I0D(it) for _ in it) + + #for i, svert in enumerate(stroke): + # if i == 0: + # e = stroke[i + 1].point - svert.point + # yield Vector((e[1], -e[0])).normalized() + # elif i == n: + # e = svert.point - stroke[i - 1].point + # yield Vector((e[1], -e[0])).normalized() + # else: + # e1 = stroke[i + 1].point - svert.point + # e2 = svert.point - stroke[i - 1].point + # n1 = Vector((e1[1], -e1[0])).normalized() + # n2 = Vector((e2[1], -e2[0])).normalized() + # yield (n1 + n2).normalized() def get_test_stroke(): diff --git a/release/scripts/freestyle/modules/parameter_editor.py b/release/scripts/freestyle/modules/parameter_editor.py index 3c11c33a39d..a1d0528e117 100644 --- a/release/scripts/freestyle/modules/parameter_editor.py +++ b/release/scripts/freestyle/modules/parameter_editor.py @@ -75,29 +75,34 @@ from freestyle.shaders import ( ConstantColorShader, GuidingLinesShader, PolygonalizationShader, - SamplingShader, - SpatialNoiseShader, - StrokeShader, - StrokeTextureStepShader, - TipRemoverShader, pyBluePrintCirclesShader, pyBluePrintEllipsesShader, pyBluePrintSquaresShader, RoundCapShader, + SamplingShader, + SpatialNoiseShader, SquareCapShader, + StrokeShader, + StrokeTextureStepShader, + ThicknessNoiseShader as thickness_noise, + TipRemoverShader, ) from freestyle.utils import ( + angle_x_normal, + bound, + BoundedProperty, ContextFunctions, + curvature_from_stroke_vertex, getCurrentScene, iter_distance_along_stroke, - iter_t2d_along_stroke, iter_distance_from_camera, iter_distance_from_object, iter_material_value, - stroke_normal, - bound, + iter_t2d_along_stroke, + normal_at_I0D, pairwise, - BoundedProperty, + simplify, + stroke_normal, ) from _freestyle import ( blendRamp, @@ -106,12 +111,16 @@ from _freestyle import ( ) import time +import bpy +import random + from mathutils import Vector -from math import pi, sin, cos, acos, radians +from math import pi, sin, cos, acos, radians, atan2 from itertools import cycle, tee -# lists of callback functions # WARNING: highly experimental, not a stable API +# lists of callback functions +# used by the render_freestyle_svg addon callbacks_lineset_pre = [] callbacks_modifiers_post = [] callbacks_lineset_post = [] @@ -176,7 +185,13 @@ class CurveMappingModifier(ScalarBlendModifier): return (1.0 - t) if self.invert else t def CURVE(self, t): - return evaluateCurveMappingF(self.curve, 0, t) + # deprecated: return evaluateCurveMappingF(self.curve, 0, t) + curve = self.curve + curve.initialize() + result = curve.curves[0].evaluate(t) + # float precision errors in t can give a very weird result for evaluate. + # therefore, bound the result by the curve's min and max values + return bound(curve.clip_min_y, result, curve.clip_max_y) class ThicknessModifierMixIn: @@ -209,10 +224,20 @@ class ThicknessBlenderMixIn(ThicknessModifierMixIn): self.position = position self.ratio = ratio - def blend_thickness(self, svert, v): - """Blends and sets the thickness.""" + def blend_thickness(self, svert, thickness, asymmetric=False): + """Blends and sets the thickness with respect to the position, blend mode and symmetry.""" + if asymmetric: + right, left = thickness + self.blend_thickness_asymmetric(svert, right, left) + else: + if type(thickness) not in {int, float}: + thickness = sum(thickness) + self.blend_thickness_symmetric(svert, thickness) + + + def blend_thickness_symmetric(self, svert, v): + """Blends and sets the thickness. Thickness is equal on each side of the backbone""" outer, inner = svert.attribute.thickness - fe = svert.fedge v = self.blend(outer + inner, v) # Part 1: blend @@ -227,21 +252,29 @@ class ThicknessBlenderMixIn(ThicknessModifierMixIn): else: raise ValueError("unknown thickness position: " + position) - # Part 2: set - if (fe.nature & Nature.BORDER): + self.set_thickness(svert, outer, inner) + + def blend_thickness_asymmetric(self, svert, right, left): + """Blends and sets the thickness. Thickness may be unequal on each side of the backbone""" + # blend the thickness values for both sides. This way, the blend mode is supported. + old = svert.attribute.thickness + new = (right, left) + right, left = (self.blend(*val) for val in zip(old, new)) + + fe = svert.fedge + nature = fe.nature + if (nature & Nature.BORDER): if self.persp_camera: point = -svert.point_3d.normalized() dir = point.dot(fe.normal_left) else: dir = fe.normal_left.z if dir < 0.0: # the back side is visible - outer, inner = inner, outer - elif (fe.nature & Nature.SILHOUETTE): + right, left = left, right + elif (nature & Nature.SILHOUETTE): if fe.is_smooth: # TODO more tests needed - outer, inner = inner, outer - else: - outer = inner = (outer + inner) / 2 - svert.attribute.thickness = (outer, inner) + right, left = left, right + svert.attribute.thickness = (right, left) class BaseThicknessShader(StrokeShader, ThicknessModifierMixIn): @@ -294,7 +327,7 @@ class ThicknessAlongStrokeShader(ThicknessBlenderMixIn, CurveMappingModifier): blend, influence, mapping, invert, curve, value_min, value_max): ThicknessBlenderMixIn.__init__(self, thickness_position, thickness_ratio) CurveMappingModifier.__init__(self, blend, influence, mapping, invert, curve) - self.value = BoundedProperty(value_min, value_max, value_max - value_min) + self.value = BoundedProperty(value_min, value_max) def shade(self, stroke): for svert, t in zip(stroke, iter_t2d_along_stroke(stroke)): @@ -308,7 +341,7 @@ class ColorDistanceFromCameraShader(ColorRampModifier): """Picks a color value from a ramp based on the vertex' distance from the camera.""" def __init__(self, blend, influence, ramp, range_min, range_max): ColorRampModifier.__init__(self, blend, influence, ramp) - self.range = BoundedProperty(range_min, range_max, range_max - range_min) + self.range = BoundedProperty(range_min, range_max) def shade(self, stroke): it = iter_distance_from_camera(stroke, *self.range) @@ -322,7 +355,7 @@ class AlphaDistanceFromCameraShader(CurveMappingModifier): """Picks an alpha value from a curve based on the vertex' distance from the camera""" def __init__(self, blend, influence, mapping, invert, curve, range_min, range_max): CurveMappingModifier.__init__(self, blend, influence, mapping, invert, curve) - self.range = BoundedProperty(range_min, range_max, range_max - range_min) + self.range = BoundedProperty(range_min, range_max) def shade(self, stroke): it = iter_distance_from_camera(stroke, *self.range) @@ -338,8 +371,8 @@ class ThicknessDistanceFromCameraShader(ThicknessBlenderMixIn, CurveMappingModif blend, influence, mapping, invert, curve, range_min, range_max, value_min, value_max): ThicknessBlenderMixIn.__init__(self, thickness_position, thickness_ratio) CurveMappingModifier.__init__(self, blend, influence, mapping, invert, curve) - self.range = BoundedProperty(range_min, range_max, range_max - range_min) - self.value = BoundedProperty(value_min, value_max, value_max - value_min) + self.range = BoundedProperty(range_min, range_max) + self.value = BoundedProperty(value_min, value_max) def shade(self, stroke): for (svert, t) in iter_distance_from_camera(stroke, *self.range): @@ -355,7 +388,7 @@ class ColorDistanceFromObjectShader(ColorRampModifier): ColorRampModifier.__init__(self, blend, influence, ramp) if target is None: raise ValueError("ColorDistanceFromObjectShader: target can't be None ") - self.range = BoundedProperty(range_min, range_max, range_max - range_min) + self.range = BoundedProperty(range_min, range_max) # construct a model-view matrix matrix = getCurrentScene().camera.matrix_world.inverted() # get the object location in the camera coordinate @@ -375,7 +408,7 @@ class AlphaDistanceFromObjectShader(CurveMappingModifier): CurveMappingModifier.__init__(self, blend, influence, mapping, invert, curve) if target is None: raise ValueError("AlphaDistanceFromObjectShader: target can't be None ") - self.range = BoundedProperty(range_min, range_max, range_max - range_min) + self.range = BoundedProperty(range_min, range_max) # construct a model-view matrix matrix = getCurrentScene().camera.matrix_world.inverted() # get the object location in the camera coordinate @@ -397,8 +430,8 @@ class ThicknessDistanceFromObjectShader(ThicknessBlenderMixIn, CurveMappingModif CurveMappingModifier.__init__(self, blend, influence, mapping, invert, curve) if target is None: raise ValueError("ThicknessDistanceFromObjectShader: target can't be None ") - self.range = BoundedProperty(range_min, range_max, range_max - range_min) - self.value = BoundedProperty(value_min, value_max, value_max - value_min) + self.range = BoundedProperty(range_min, range_max) + self.value = BoundedProperty(value_min, value_max) # construct a model-view matrix matrix = getCurrentScene().camera.matrix_world.inverted() # get the object location in the camera coordinate @@ -459,7 +492,7 @@ class ThicknessMaterialShader(ThicknessBlenderMixIn, CurveMappingModifier): ThicknessBlenderMixIn.__init__(self, thickness_position, thickness_ratio) CurveMappingModifier.__init__(self, blend, influence, mapping, invert, curve) self.attribute = material_attribute - self.value = BoundedProperty(value_min, value_max, value_max - value_min) + self.value = BoundedProperty(value_min, value_max) self.func = CurveMaterialF0D() def shade(self, stroke): @@ -478,7 +511,7 @@ class CalligraphicThicknessShader(ThicknessBlenderMixIn, ScalarBlendModifier): ThicknessBlenderMixIn.__init__(self, thickness_position, thickness_ratio) ScalarBlendModifier.__init__(self, blend_type, influence) self.orientation = Vector((cos(orientation), sin(orientation))) - self.thickness = BoundedProperty(thickness_min, thickness_max, thickness_max - thickness_min) + self.thickness = BoundedProperty(thickness_min, thickness_max) self.func = VertexOrientation2DF0D() def shade(self, stroke): @@ -493,11 +526,252 @@ class CalligraphicThicknessShader(ThicknessBlenderMixIn, ScalarBlendModifier): b = self.thickness.min self.blend_thickness(svert, b) +# - Tangent Modifiers - # + +class TangentColorShader(ColorRampModifier): + """Color based on the direction of the stroke""" + def shade(self, stroke): + it = Interface0DIterator(stroke) + for svert in it: + angle = angle_x_normal(it) + fac = self.evaluate(angle / pi) + + a = svert.attribute.color + svert.attribute.color = self.blend_ramp(a, fac) + + +class TangentAlphaShader(CurveMappingModifier): + """Alpha transparency based on the direction of the stroke""" + def shade(self, stroke): + it = Interface0DIterator(stroke) + for svert in it: + angle = angle_x_normal(it) + fac = self.evaluate(angle / pi) + + a = svert.attribute.alpha + svert.attribute.alpha = self.blend(a, fac) + + +class TangentThicknessShader(ThicknessBlenderMixIn, CurveMappingModifier): + """Thickness based on the direction of the stroke""" + def __init__(self, thickness_position, thickness_ratio, blend, influence, mapping, invert, curve, + thickness_min, thickness_max): + ThicknessBlenderMixIn.__init__(self, thickness_position, thickness_ratio) + CurveMappingModifier.__init__(self, blend, influence, mapping, invert, curve) + self.thickness = BoundedProperty(thickness_min, thickness_max) + + def shade(self, stroke): + it = Interface0DIterator(stroke) + for svert in it: + angle = angle_x_normal(it) + thickness = self.thickness.min + self.evaluate(angle / pi) * self.thickness.delta + self.blend_thickness(svert, thickness) + +# - Noise Modifiers - # +class NoiseShader: + """Base class for noise shaders""" + def __init__(self, amplitude, period, seed=512): + self.amplitude = amplitude + self.scale = 1 / period / seed + self.seed = seed + + def noisegen(self, stroke, n1=Noise(), n2=Noise()): + """Produces two noise values per StrokeVertex for every vertex in the stroke""" + initU1 = stroke.length_2d * self.seed + n1.rand(512) * self.seed + initU2 = stroke.length_2d * self.seed + n2.rand() * self.seed + + for svert in stroke: + a = n1.turbulence_smooth(self.scale * svert.curvilinear_abscissa + initU1, 2) + b = n2.turbulence_smooth(self.scale * svert.curvilinear_abscissa + initU2, 2) + yield (svert, a, b) + + +class ThicknessNoiseShader(ThicknessBlenderMixIn, ScalarBlendModifier, NoiseShader): + """Thickness based on pseudo-noise""" + def __init__(self, thickness_position, thickness_ratio, blend_type, influence, amplitude, period, seed=512, asymmetric=True): + ScalarBlendModifier.__init__(self, blend_type, influence) + ThicknessBlenderMixIn.__init__(self, thickness_position, thickness_ratio) + NoiseShader.__init__(self, amplitude, period, seed) + self.asymmetric = asymmetric + + def shade(self, stroke): + for svert, noiseval1, noiseval2 in self.noisegen(stroke): + (r, l) = svert.attribute.thickness + l += noiseval1 * self.amplitude + r += noiseval2 * self.amplitude + self.blend_thickness(svert, (r, l), self.asymmetric) + + +class ColorNoiseShader(ColorRampModifier, NoiseShader): + """Color based on pseudo-noise""" + def __init__(self, blend, influence, ramp, amplitude, period, seed=512): + ColorRampModifier.__init__(self, blend, influence, ramp) + NoiseShader.__init__(self, amplitude, period, seed) + + def shade(self, stroke): + for svert, noiseval1, noiseval2 in self.noisegen(stroke): + position = abs(noiseval1 + noiseval2) + svert.attribute.color = self.blend_ramp(svert.attribute.color, self.evaluate(position)) + + +class AlphaNoiseShader(CurveMappingModifier, NoiseShader): + """Alpha transparency on based pseudo-noise""" + def __init__(self, blend, influence, mapping, invert, curve, amplitude, period, seed=512): + CurveMappingModifier.__init__(self, blend, influence, mapping, invert, curve) + NoiseShader.__init__(self, amplitude, period, seed) + + def shade(self, stroke, n1=Noise(), n2=Noise()): + for svert, noiseval1, noiseval2 in self.noisegen(stroke): + position = abs(noiseval1 + noiseval2) + svert.attribute.alpha = self.blend(svert.attribute.alpha, self.evaluate(position)) + +# - Crease Angle Modifiers - # + +def crease_angle(svert): + """Returns the crease angle between the StrokeVertex' two adjacent faces (in radians)""" + fe = svert.fedge + if not fe or fe.is_smooth or not (fe.nature & Nature.CREASE): + return None + # make sure that the input is within the domain of the acos function + product = bound(-1.0, -fe.normal_left.dot(fe.normal_right), 1.0) + return acos(product) + + +class CreaseAngleColorShader(ColorRampModifier): + """Color based on the crease angle between two adjacent faces on the underlying geometry""" + def __init__(self, blend, influence, ramp, angle_min, angle_max): + ColorRampModifier.__init__(self, blend, influence, ramp) + # angles are (already) in radians + self.angle = BoundedProperty(angle_min, angle_max) + + def shade(self, stroke): + for svert in stroke: + angle = crease_angle(svert) + if angle is None: + continue + t = self.angle.interpolate(angle) + svert.attribute.color = self.blend_ramp(svert.attribute.color, self.evaluate(t)) + + +class CreaseAngleAlphaShader(CurveMappingModifier): + """Alpha transparency based on the crease angle between two adjacent faces on the underlying geometry""" + def __init__(self, blend, influence, mapping, invert, curve, angle_min, angle_max): + CurveMappingModifier.__init__(self, blend, influence, mapping, invert, curve) + # angles are (already) in radians + self.angle = BoundedProperty(angle_min, angle_max) + + def shade(self, stroke): + for svert in stroke: + angle = crease_angle(svert) + if angle is None: + continue + t = self.angle.interpolate(angle) + svert.attribute.alpha = self.blend(svert.attribute.alpha, self.evaluate(t)) + + +class CreaseAngleThicknessShader(ThicknessBlenderMixIn, CurveMappingModifier): + """Thickness based on the crease angle between two adjacent faces on the underlying geometry""" + def __init__(self, thickness_position, thickness_ratio, blend, influence, mapping, invert, curve, + angle_min, angle_max, thickness_min, thickness_max): + ThicknessBlenderMixIn.__init__(self, thickness_position, thickness_ratio) + CurveMappingModifier.__init__(self, blend, influence, mapping, invert, curve) + # angles are (already) in radians + self.angle = BoundedProperty(angle_min, angle_max) + self.thickness = BoundedProperty(thickness_min, thickness_max) + + + def shade(self, stroke): + for svert in stroke: + angle = crease_angle(svert) + if angle is None: + continue + t = self.angle.interpolate(angle) + thickness = self.thickness.min + self.evaluate(t) * self.thickness.delta + self.blend_thickness(svert, thickness) + +# - Curvature3D Modifiers - # + +def normalized_absolute_curvature(svert, bounded_curvature): + """ + Gives the absolute curvature in range [0, 1]. + + The actual curvature (Kr) value can be anywhere in the range [-inf, inf], where convex curvature + yields a positive value, and concave a negative one. These shaders only look for the magnitude + of the 3D curvature, hence the abs() + """ + curvature = curvature_from_stroke_vertex(svert) + if curvature is None: + return 0.0 + return bounded_curvature.interpolate(abs(curvature)) + +class Curvature3DColorShader(ColorRampModifier): + """Color based on the 3D curvature of the underlying geometry""" + def __init__(self, blend, influence, ramp, curvature_min, curvature_max): + ColorRampModifier.__init__(self, blend, influence, ramp) + self.curvature = BoundedProperty(curvature_min, curvature_max) + + def shade(self, stroke): + for svert in stroke: + t = normalized_absolute_curvature(svert, self.curvature) + + a = svert.attribute.color + b = self.evaluate(t) + svert.attribute.color = self.blend_ramp(a, b) + + +class Curvature3DAlphaShader(CurveMappingModifier): + """Alpha based on the 3D curvature of the underlying geometry""" + def __init__(self, blend, influence, mapping, invert, curve, curvature_min, curvature_max): + CurveMappingModifier.__init__(self, blend, influence, mapping, invert, curve) + self.curvature = BoundedProperty(curvature_min, curvature_max) + + def shade(self, stroke): + for svert in stroke: + t = normalized_absolute_curvature(svert, self.curvature) + a = svert.attribute.alpha + b = self.evaluate(t) + svert.attribute.alpha = self.blend(a, b) + + +class Curvature3DThicknessShader(ThicknessBlenderMixIn, CurveMappingModifier): + """Alpha based on the 3D curvature of the underlying geometry""" + def __init__(self, thickness_position, thickness_ratio, blend, influence, mapping, invert, curve, + curvature_min, curvature_max, thickness_min, thickness_max): + ThicknessBlenderMixIn.__init__(self, thickness_position, thickness_ratio) + CurveMappingModifier.__init__(self, blend, influence, mapping, invert, curve) + self.curvature = BoundedProperty(curvature_min, curvature_max) + self.thickness = BoundedProperty(thickness_min, thickness_max) + + + def shade(self, stroke): + for svert in stroke: + t = normalized_absolute_curvature(svert, self.curvature) + thickness = self.thickness.min + self.evaluate(t) * self.thickness.delta + self.blend_thickness(svert, thickness) + # Geometry modifiers +class SimplificationShader(StrokeShader): + """Simplifies a stroke by merging points together""" + def __init__(self, tolerance): + StrokeShader.__init__(self) + self.tolerance = tolerance + + def shade(self, stroke): + points = tuple(svert.point for svert in stroke) + points_simplified = simplify(points, tolerance=self.tolerance) + + it = iter(stroke) + for svert, point in zip(it, points_simplified): + svert.point = point + + for svert in tuple(it): + stroke.remove_vertex(svert) + + class SinusDisplacementShader(StrokeShader): - """Displaces the stroke in a sinewave-like shape.""" + """Displaces the stroke in a sine wave-like shape.""" def __init__(self, wavelength, amplitude, phase): StrokeShader.__init__(self) self.wavelength = wavelength @@ -540,7 +814,7 @@ class PerlinNoise1DShader(StrokeShader): class PerlinNoise2DShader(StrokeShader): """ Displaces the stroke using the strokes coordinates. This means - that in a scene no strokes will be distorded identically. + that in a scene no strokes will be distorted identically. More information on the noise shaders can be found at: freestyleintegration.wordpress.com/2011/09/25/development-updates-on-september-25/ @@ -883,7 +1157,6 @@ class Seed: _seed = Seed() - def get_dashed_pattern(linestyle): """Extracts the dashed pattern from the various UI options """ pattern = [] @@ -1066,6 +1339,8 @@ def process(layer_name, lineset_name): elif m.type == 'BEZIER_CURVE': shaders_list.append(BezierCurveShader( m.error)) + elif m.type == 'SIMPLIFICATION': + shaders_list.append(SimplificationShader(m.tolerance)) elif m.type == 'SINUS_DISPLACEMENT': shaders_list.append(SinusDisplacementShader( m.wavelength, m.amplitude, m.phase)) @@ -1137,6 +1412,21 @@ def process(layer_name, lineset_name): shaders_list.append(ColorMaterialShader( m.blend, m.influence, m.color_ramp, m.material_attribute, m.use_ramp)) + elif m.type == 'TANGENT': + shaders_list.append(TangentColorShader( + m.blend, m.influence, m.color_ramp)) + elif m.type == 'CREASE_ANGLE': + shaders_list.append(CreaseAngleColorShader( + m.blend, m.influence, m.color_ramp, + m.angle_min, m.angle_max)) + elif m.type == 'CURVATURE_3D': + shaders_list.append(Curvature3DColorShader( + m.blend, m.influence, m.color_ramp, + m.curvature_min, m.curvature_max)) + elif m.type == 'NOISE': + shaders_list.append(ColorNoiseShader( + m.blend, m.influence, m.color_ramp, + m.amplitude, m.period, m.seed)) for m in linestyle.alpha_modifiers: if not m.use: continue @@ -1155,6 +1445,21 @@ def process(layer_name, lineset_name): shaders_list.append(AlphaMaterialShader( m.blend, m.influence, m.mapping, m.invert, m.curve, m.material_attribute)) + elif m.type == 'TANGENT': + shaders_list.append(TangentAlphaShader( + m.blend, m.influence, m.mapping, m.invert, m.curve,)) + elif m.type == 'CREASE_ANGLE': + shaders_list.append(CreaseAngleAlphaShader( + m.blend, m.influence, m.mapping, m.invert, m.curve, + m.angle_min, m.angle_max)) + elif m.type == 'CURVATURE_3D': + shaders_list.append(Curvature3DAlphaShader( + m.blend, m.influence, m.mapping, m.invert, m.curve, + m.curvature_min, m.curvature_max)) + elif m.type == 'NOISE': + shaders_list.append(AlphaNoiseShader( + m.blend, m.influence, m.mapping, m.invert, m.curve, + m.amplitude, m.period, m.seed)) for m in linestyle.thickness_modifiers: if not m.use: continue @@ -1183,6 +1488,28 @@ def process(layer_name, lineset_name): thickness_position, linestyle.thickness_ratio, m.blend, m.influence, m.orientation, m.thickness_min, m.thickness_max)) + elif m.type == 'TANGENT': + shaders_list.append(TangentThicknessShader( + thickness_position, linestyle.thickness_ratio, + m.blend, m.influence, m.mapping, m.invert, m.curve, + m.thickness_min, m.thickness_max)) + elif m.type == 'NOISE': + shaders_list.append(ThicknessNoiseShader( + thickness_position, linestyle.thickness_ratio, + m.blend, m.influence, + m.amplitude, m.period, m.seed, m.use_asymmetric)) + elif m.type == 'CREASE_ANGLE': + shaders_list.append(CreaseAngleThicknessShader( + thickness_position, linestyle.thickness_ratio, + m.blend, m.influence, m.mapping, m.invert, m.curve, + m.angle_min, m.angle_max, m.thickness_min, m.thickness_max)) + elif m.type == 'CURVATURE_3D': + shaders_list.append(Curvature3DThicknessShader( + thickness_position, linestyle.thickness_ratio, + m.blend, m.influence, m.mapping, m.invert, m.curve, + m.curvature_min, m.curvature_max, m.thickness_min, m.thickness_max)) + else: + raise RuntimeError("No Thickness modifier with type", type(m), m) # -- Textures -- # has_tex = False if scene.render.use_shading_nodes: diff --git a/release/scripts/startup/bl_ui/properties_freestyle.py b/release/scripts/startup/bl_ui/properties_freestyle.py index 995136b0d97..f58a698d194 100644 --- a/release/scripts/startup/bl_ui/properties_freestyle.py +++ b/release/scripts/startup/bl_ui/properties_freestyle.py @@ -283,6 +283,10 @@ class RENDERLAYER_PT_freestyle_linestyle(RenderLayerFreestyleEditorButtonsPanel, sub.operator("scene.freestyle_modifier_move", icon='TRIA_DOWN', text="").direction = 'DOWN' sub.operator("scene.freestyle_modifier_remove", icon='X', text="") + def draw_modifier_box_error(self, box, modifier, message): + row = box.row() + row.label(text=message, icon="ERROR") + def draw_modifier_common(self, box, modifier): row = box.row() row.prop(modifier, "blend", text="") @@ -351,6 +355,33 @@ class RENDERLAYER_PT_freestyle_linestyle(RenderLayerFreestyleEditorButtonsPanel, if show_ramp: self.draw_modifier_color_ramp_common(box, modifier, False) + elif modifier.type == 'TANGENT': + self.draw_modifier_color_ramp_common(box, modifier, False) + + elif modifier.type == 'NOISE': + self.draw_modifier_color_ramp_common(box, modifier, False) + row = box.row(align=False) + row.prop(modifier, "amplitude") + row.prop(modifier, "period") + row.prop(modifier, "seed") + + elif modifier.type == 'CREASE_ANGLE': + self.draw_modifier_color_ramp_common(box, modifier, False) + row = box.row(align=True) + row.prop(modifier, "angle_min") + row.prop(modifier, "angle_max") + + elif modifier.type == 'CURVATURE_3D': + self.draw_modifier_color_ramp_common(box, modifier, False) + row = box.row(align=True) + row.prop(modifier, "curvature_min") + row.prop(modifier, "curvature_max") + freestyle = context.scene.render.layers.active.freestyle_settings + if not freestyle.use_smoothness: + message = "Enable Face Smoothness to use this modifier" + self.draw_modifier_box_error(col.box(), modifier, message) + + def draw_alpha_modifier(self, context, modifier): layout = self.layout @@ -380,6 +411,32 @@ class RENDERLAYER_PT_freestyle_linestyle(RenderLayerFreestyleEditorButtonsPanel, box.prop(modifier, "material_attribute", text="") self.draw_modifier_curve_common(box, modifier, False, False) + elif modifier.type == 'TANGENT': + self.draw_modifier_curve_common(box, modifier, False, False) + + elif modifier.type == 'NOISE': + self.draw_modifier_curve_common(box, modifier, False, False) + row = box.row(align=False) + row.prop(modifier, "amplitude") + row.prop(modifier, "period") + row.prop(modifier, "seed") + + elif modifier.type == 'CREASE_ANGLE': + self.draw_modifier_curve_common(box, modifier, False, False) + row = box.row(align=True) + row.prop(modifier, "angle_min") + row.prop(modifier, "angle_max") + + elif modifier.type == 'CURVATURE_3D': + self.draw_modifier_curve_common(box, modifier, False, False) + row = box.row(align=True) + row.prop(modifier, "curvature_min") + row.prop(modifier, "curvature_max") + freestyle = context.scene.render.layers.active.freestyle_settings + if not freestyle.use_smoothness: + message = "Enable Face Smoothness to use this modifier" + self.draw_modifier_box_error(col.box(), modifier, message) + def draw_thickness_modifier(self, context, modifier): layout = self.layout @@ -415,6 +472,45 @@ class RENDERLAYER_PT_freestyle_linestyle(RenderLayerFreestyleEditorButtonsPanel, row.prop(modifier, "thickness_min") row.prop(modifier, "thickness_max") + elif modifier.type == 'TANGENT': + self.draw_modifier_curve_common(box, modifier, False, False) + self.mapping = 'CURVE' + row = box.row(align=True) + row.prop(modifier, "thickness_min") + row.prop(modifier, "thickness_max") + + elif modifier.type == 'NOISE': + row = box.row(align=False) + row.prop(modifier, "amplitude") + row.prop(modifier, "period") + row = box.row(align=False) + row.prop(modifier, "seed") + row.prop(modifier, "use_asymmetric") + + elif modifier.type == 'CREASE_ANGLE': + self.draw_modifier_curve_common(box, modifier, False, False) + row = box.row(align=True) + row.prop(modifier, "thickness_min") + row.prop(modifier, "thickness_max") + row = box.row(align=True) + row.prop(modifier, "angle_min") + row.prop(modifier, "angle_max") + + + elif modifier.type == 'CURVATURE_3D': + self.draw_modifier_curve_common(box, modifier, False, False) + row = box.row(align=True) + row.prop(modifier, "thickness_min") + row.prop(modifier, "thickness_max") + row = box.row(align=True) + row.prop(modifier, "curvature_min") + row.prop(modifier, "curvature_max") + freestyle = context.scene.render.layers.active.freestyle_settings + if not freestyle.use_smoothness: + message = "Enable Face Smoothness to use this modifier" + self.draw_modifier_box_error(col.box(), modifier, message) + + def draw_geometry_modifier(self, context, modifier): layout = self.layout @@ -512,6 +608,10 @@ class RENDERLAYER_PT_freestyle_linestyle(RenderLayerFreestyleEditorButtonsPanel, row.prop(modifier, "scale_y") box.prop(modifier, "angle") + elif modifier.type == 'SIMPLIFICATION': + box.prop(modifier, "tolerance") + + def draw(self, context): layout = self.layout diff --git a/source/blender/blenkernel/intern/linestyle.c b/source/blender/blenkernel/intern/linestyle.c index 40db411ef4c..901c6fd54d9 100644 --- a/source/blender/blenkernel/intern/linestyle.c +++ b/source/blender/blenkernel/intern/linestyle.c @@ -73,6 +73,11 @@ static const char *modifier_name[LS_MODIFIER_NUM] = { "Blueprint", "2D Offset", "2D Transform", + "Tangent", + "Noise", + "Crease Angle", + "Simplification", + "3D Curvature", }; static void default_linestyle_settings(FreestyleLineStyle *linestyle) @@ -268,6 +273,18 @@ static LineStyleModifier *alloc_color_modifier(const char *name, int type) case LS_MODIFIER_MATERIAL: size = sizeof(LineStyleColorModifier_Material); break; + case LS_MODIFIER_TANGENT: + size = sizeof(LineStyleColorModifier_Tangent); + break; + case LS_MODIFIER_NOISE: + size = sizeof(LineStyleColorModifier_Noise); + break; + case LS_MODIFIER_CREASE_ANGLE: + size = sizeof(LineStyleColorModifier_CreaseAngle); + break; + case LS_MODIFIER_CURVATURE_3D: + size = sizeof(LineStyleColorModifier_Curvature_3D); + break; default: return NULL; /* unknown modifier type */ } @@ -304,6 +321,25 @@ LineStyleModifier *BKE_linestyle_color_modifier_add(FreestyleLineStyle *linestyl ((LineStyleColorModifier_Material *)m)->color_ramp = add_colorband(1); ((LineStyleColorModifier_Material *)m)->mat_attr = LS_MODIFIER_MATERIAL_LINE; break; + case LS_MODIFIER_TANGENT: + ((LineStyleColorModifier_Tangent *)m)->color_ramp = add_colorband(1); + break; + case LS_MODIFIER_NOISE: + ((LineStyleColorModifier_Noise *)m)->color_ramp = add_colorband(1); + ((LineStyleColorModifier_Noise *)m)->amplitude = 10.0f; + ((LineStyleColorModifier_Noise *)m)->period = 10.0f; + ((LineStyleColorModifier_Noise *)m)->seed = 512; + break; + case LS_MODIFIER_CREASE_ANGLE: + ((LineStyleColorModifier_CreaseAngle *)m)->color_ramp = add_colorband(1); + ((LineStyleColorModifier_CreaseAngle *)m)->min_angle = 0.0f; + ((LineStyleColorModifier_CreaseAngle *)m)->max_angle = DEG2RADF(180.0f); + break; + case LS_MODIFIER_CURVATURE_3D: + ((LineStyleColorModifier_Curvature_3D *)m)->color_ramp = add_colorband(1); + ((LineStyleColorModifier_Curvature_3D *)m)->min_curvature = 0.0f; + ((LineStyleColorModifier_Curvature_3D *)m)->max_curvature = 0.5f; + break; default: return NULL; /* unknown modifier type */ } @@ -362,6 +398,41 @@ LineStyleModifier *BKE_linestyle_color_modifier_copy(FreestyleLineStyle *linesty q->mat_attr = p->mat_attr; break; } + case LS_MODIFIER_TANGENT: + { + LineStyleColorModifier_Tangent *p = (LineStyleColorModifier_Tangent *)m; + LineStyleColorModifier_Tangent *q = (LineStyleColorModifier_Tangent *)new_m; + q->color_ramp = MEM_dupallocN(p->color_ramp); + break; + } + case LS_MODIFIER_NOISE: + { + LineStyleColorModifier_Noise *p = (LineStyleColorModifier_Noise *)m; + LineStyleColorModifier_Noise *q = (LineStyleColorModifier_Noise *)new_m; + q->color_ramp = MEM_dupallocN(p->color_ramp); + q->amplitude = p->amplitude; + q->period = p->period; + q->seed = p->seed; + break; + } + case LS_MODIFIER_CREASE_ANGLE: + { + LineStyleColorModifier_CreaseAngle *p = (LineStyleColorModifier_CreaseAngle *)m; + LineStyleColorModifier_CreaseAngle *q = (LineStyleColorModifier_CreaseAngle *)new_m; + q->color_ramp = MEM_dupallocN(p->color_ramp); + q->min_angle = p->min_angle; + q->max_angle = p->max_angle; + break; + } + case LS_MODIFIER_CURVATURE_3D: + { + LineStyleColorModifier_Curvature_3D *p = (LineStyleColorModifier_Curvature_3D *)m; + LineStyleColorModifier_Curvature_3D *q = (LineStyleColorModifier_Curvature_3D *)new_m; + q->color_ramp = MEM_dupallocN(p->color_ramp); + q->min_curvature = p->min_curvature; + q->max_curvature = p->max_curvature; + break; + } default: return NULL; /* unknown modifier type */ } @@ -387,6 +458,18 @@ int BKE_linestyle_color_modifier_remove(FreestyleLineStyle *linestyle, LineStyle case LS_MODIFIER_MATERIAL: MEM_freeN(((LineStyleColorModifier_Material *)m)->color_ramp); break; + case LS_MODIFIER_TANGENT: + MEM_freeN(((LineStyleColorModifier_Tangent *)m)->color_ramp); + break; + case LS_MODIFIER_NOISE: + MEM_freeN(((LineStyleColorModifier_Noise *)m)->color_ramp); + break; + case LS_MODIFIER_CREASE_ANGLE: + MEM_freeN(((LineStyleColorModifier_CreaseAngle *)m)->color_ramp); + break; + case LS_MODIFIER_CURVATURE_3D: + MEM_freeN(((LineStyleColorModifier_Curvature_3D *)m)->color_ramp); + break; } BLI_freelinkN(&linestyle->color_modifiers, m); return 0; @@ -409,6 +492,18 @@ static LineStyleModifier *alloc_alpha_modifier(const char *name, int type) case LS_MODIFIER_MATERIAL: size = sizeof(LineStyleAlphaModifier_Material); break; + case LS_MODIFIER_TANGENT: + size = sizeof(LineStyleAlphaModifier_Tangent); + break; + case LS_MODIFIER_NOISE: + size = sizeof(LineStyleAlphaModifier_Noise); + break; + case LS_MODIFIER_CREASE_ANGLE: + size = sizeof(LineStyleAlphaModifier_CreaseAngle); + break; + case LS_MODIFIER_CURVATURE_3D: + size = sizeof(LineStyleAlphaModifier_Curvature_3D); + break; default: return NULL; /* unknown modifier type */ } @@ -453,6 +548,37 @@ LineStyleModifier *BKE_linestyle_alpha_modifier_add(FreestyleLineStyle *linestyl p->mat_attr = LS_MODIFIER_MATERIAL_LINE_A; break; } + case LS_MODIFIER_TANGENT: + { + LineStyleAlphaModifier_Tangent *p = (LineStyleAlphaModifier_Tangent *)m; + p->curve = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); + break; + } + case LS_MODIFIER_NOISE: + { + LineStyleAlphaModifier_Noise *p = (LineStyleAlphaModifier_Noise *)m; + p->curve = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); + ((LineStyleAlphaModifier_Noise *)m)->amplitude = 10.0f; + ((LineStyleAlphaModifier_Noise *)m)->period = 10.0f; + ((LineStyleAlphaModifier_Noise *)m)->seed = 512; + break; + } + case LS_MODIFIER_CREASE_ANGLE: + { + LineStyleAlphaModifier_CreaseAngle *p = (LineStyleAlphaModifier_CreaseAngle *)m; + p->curve = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); + ((LineStyleAlphaModifier_CreaseAngle *)m)->min_angle = 0.0f; + ((LineStyleAlphaModifier_CreaseAngle *)m)->max_angle = DEG2RADF(180.0f); + break; + } + case LS_MODIFIER_CURVATURE_3D: + { + LineStyleAlphaModifier_Curvature_3D *p = (LineStyleAlphaModifier_Curvature_3D *)m; + p->curve = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); + ((LineStyleAlphaModifier_Curvature_3D *)m)->min_curvature = 0.0f; + ((LineStyleAlphaModifier_Curvature_3D *)m)->max_curvature = 0.5f; + break; + } default: return NULL; /* unknown modifier type */ } @@ -511,6 +637,45 @@ LineStyleModifier *BKE_linestyle_alpha_modifier_copy(FreestyleLineStyle *linesty q->mat_attr = p->mat_attr; break; } + case LS_MODIFIER_TANGENT: + { + LineStyleAlphaModifier_Tangent *p = (LineStyleAlphaModifier_Tangent *)m; + LineStyleAlphaModifier_Tangent *q = (LineStyleAlphaModifier_Tangent *)new_m; + q->curve = curvemapping_copy(p->curve); + q->flags = p->flags; + break; + } + case LS_MODIFIER_NOISE: + { + LineStyleAlphaModifier_Noise *p = (LineStyleAlphaModifier_Noise *)m; + LineStyleAlphaModifier_Noise *q = (LineStyleAlphaModifier_Noise *)new_m; + q->curve = curvemapping_copy(p->curve); + q->flags = p->flags; + q->amplitude = p->amplitude; + q->period = p->period; + q->seed = p->seed; + break; + } + case LS_MODIFIER_CREASE_ANGLE: + { + LineStyleAlphaModifier_CreaseAngle *p = (LineStyleAlphaModifier_CreaseAngle *)m; + LineStyleAlphaModifier_CreaseAngle *q = (LineStyleAlphaModifier_CreaseAngle *)new_m; + q->curve = curvemapping_copy(p->curve); + q->flags = p->flags; + q->min_angle = p->min_angle; + q->max_angle = p->max_angle; + break; + } + case LS_MODIFIER_CURVATURE_3D: + { + LineStyleAlphaModifier_Curvature_3D *p = (LineStyleAlphaModifier_Curvature_3D *)m; + LineStyleAlphaModifier_Curvature_3D *q = (LineStyleAlphaModifier_Curvature_3D *)new_m; + q->curve = curvemapping_copy(p->curve); + q->flags = p->flags; + q->min_curvature = p->min_curvature; + q->max_curvature = p->max_curvature; + break; + } default: return NULL; /* unknown modifier type */ } @@ -536,6 +701,18 @@ int BKE_linestyle_alpha_modifier_remove(FreestyleLineStyle *linestyle, LineStyle case LS_MODIFIER_MATERIAL: curvemapping_free(((LineStyleAlphaModifier_Material *)m)->curve); break; + case LS_MODIFIER_TANGENT: + curvemapping_free(((LineStyleAlphaModifier_Tangent *)m)->curve); + break; + case LS_MODIFIER_NOISE: + curvemapping_free(((LineStyleAlphaModifier_Noise *)m)->curve); + break; + case LS_MODIFIER_CREASE_ANGLE: + curvemapping_free(((LineStyleAlphaModifier_CreaseAngle *)m)->curve); + break; + case LS_MODIFIER_CURVATURE_3D: + curvemapping_free(((LineStyleAlphaModifier_Curvature_3D *)m)->curve); + break; } BLI_freelinkN(&linestyle->alpha_modifiers, m); return 0; @@ -561,6 +738,18 @@ static LineStyleModifier *alloc_thickness_modifier(const char *name, int type) case LS_MODIFIER_CALLIGRAPHY: size = sizeof(LineStyleThicknessModifier_Calligraphy); break; + case LS_MODIFIER_TANGENT: + size = sizeof(LineStyleThicknessModifier_Tangent); + break; + case LS_MODIFIER_NOISE: + size = sizeof(LineStyleThicknessModifier_Noise); + break; + case LS_MODIFIER_CREASE_ANGLE: + size = sizeof(LineStyleThicknessModifier_CreaseAngle); + break; + case LS_MODIFIER_CURVATURE_3D: + size = sizeof(LineStyleThicknessModifier_Curvature_3D); + break; default: return NULL; /* unknown modifier type */ } @@ -622,6 +811,43 @@ LineStyleModifier *BKE_linestyle_thickness_modifier_add(FreestyleLineStyle *line p->orientation = DEG2RADF(60.0f); break; } + case LS_MODIFIER_TANGENT: + { + LineStyleThicknessModifier_Tangent *p = (LineStyleThicknessModifier_Tangent *)m; + p->curve = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); + p->min_thickness = 1.0f; + p->max_thickness = 10.0f; + break; + } + case LS_MODIFIER_NOISE: + { + LineStyleThicknessModifier_Noise *p = (LineStyleThicknessModifier_Noise *)m; + p->period = 10.0f; + p->amplitude = 10.0f; + p->seed = 512; + p->flags = LS_THICKNESS_ASYMMETRIC; + break; + } + case LS_MODIFIER_CREASE_ANGLE: + { + LineStyleThicknessModifier_CreaseAngle *p = (LineStyleThicknessModifier_CreaseAngle *)m; + p->curve = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); + p->min_angle = 0.0f; + p->max_angle = DEG2RADF(180.0f); + p->min_thickness = 1.0f; + p->max_thickness = 10.0f; + break; + } + case LS_MODIFIER_CURVATURE_3D: + { + LineStyleThicknessModifier_Curvature_3D *p = (LineStyleThicknessModifier_Curvature_3D *)m; + p->curve = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); + p->min_curvature = 0.0f; + p->max_curvature = 0.5f; + p->min_thickness = 1.0f; + p->max_thickness = 10.0f; + break; + } default: return NULL; /* unknown modifier type */ } @@ -699,6 +925,50 @@ LineStyleModifier *BKE_linestyle_thickness_modifier_copy(FreestyleLineStyle *lin q->orientation = p->orientation; break; } + case LS_MODIFIER_TANGENT: + { + LineStyleThicknessModifier_Tangent *p = (LineStyleThicknessModifier_Tangent *)m; + LineStyleThicknessModifier_Tangent *q = (LineStyleThicknessModifier_Tangent *)new_m; + q->curve = curvemapping_copy(p->curve); + q->flags = p->flags; + q->min_thickness = p->min_thickness; + q->max_thickness = p->max_thickness; + break; + } + case LS_MODIFIER_NOISE: + { + LineStyleThicknessModifier_Noise *p = (LineStyleThicknessModifier_Noise *)m; + LineStyleThicknessModifier_Noise *q = (LineStyleThicknessModifier_Noise *)new_m; + q->amplitude = p->amplitude; + q->period = p->period; + q->seed = p->seed; + q->flags = p->flags; + break; + } + case LS_MODIFIER_CURVATURE_3D: + { + LineStyleThicknessModifier_Curvature_3D *p = (LineStyleThicknessModifier_Curvature_3D *)m; + LineStyleThicknessModifier_Curvature_3D *q = (LineStyleThicknessModifier_Curvature_3D *)new_m; + q->curve = curvemapping_copy(p->curve); + q->flags = p->flags; + q->min_curvature = p->min_curvature; + q->max_curvature = p->max_curvature; + q->min_thickness = p->min_thickness; + q->max_thickness = p->max_thickness; + break; + } + case LS_MODIFIER_CREASE_ANGLE: + { + LineStyleThicknessModifier_CreaseAngle *p = (LineStyleThicknessModifier_CreaseAngle *)m; + LineStyleThicknessModifier_CreaseAngle *q = (LineStyleThicknessModifier_CreaseAngle *)new_m; + q->curve = curvemapping_copy(p->curve); + q->flags = p->flags; + q->min_angle = p->min_angle; + q->max_angle = p->max_angle; + q->min_thickness = p->min_thickness; + q->max_thickness = p->max_thickness; + break; + } default: return NULL; /* unknown modifier type */ } @@ -726,6 +996,15 @@ int BKE_linestyle_thickness_modifier_remove(FreestyleLineStyle *linestyle, LineS break; case LS_MODIFIER_CALLIGRAPHY: break; + case LS_MODIFIER_TANGENT: + curvemapping_free(((LineStyleThicknessModifier_Tangent *)m)->curve); + break; + case LS_MODIFIER_NOISE: + break; + case LS_MODIFIER_CREASE_ANGLE: + break; + case LS_MODIFIER_CURVATURE_3D: + break; } BLI_freelinkN(&linestyle->thickness_modifiers, m); return 0; @@ -775,6 +1054,9 @@ static LineStyleModifier *alloc_geometry_modifier(const char *name, int type) case LS_MODIFIER_2D_TRANSFORM: size = sizeof(LineStyleGeometryModifier_2DTransform); break; + case LS_MODIFIER_SIMPLIFICATION: + size = sizeof(LineStyleGeometryModifier_Simplification); + break; default: return NULL; /* unknown modifier type */ } @@ -892,6 +1174,12 @@ LineStyleModifier *BKE_linestyle_geometry_modifier_add(FreestyleLineStyle *lines p->pivot_y = 0.0f; break; } + case LS_MODIFIER_SIMPLIFICATION: + { + LineStyleGeometryModifier_Simplification *p = (LineStyleGeometryModifier_Simplification *)m; + p->tolerance = 0.1f; + break; + } default: return NULL; /* unknown modifier type */ } @@ -1026,6 +1314,13 @@ LineStyleModifier *BKE_linestyle_geometry_modifier_copy(FreestyleLineStyle *line q->pivot_y = p->pivot_y; break; } + case LS_MODIFIER_SIMPLIFICATION: + { + LineStyleGeometryModifier_Simplification *p = (LineStyleGeometryModifier_Simplification *)m; + LineStyleGeometryModifier_Simplification *q = (LineStyleGeometryModifier_Simplification *)new_m; + q->tolerance = p->tolerance; + break; + } default: return NULL; /* unknown modifier type */ } @@ -1125,6 +1420,22 @@ char *BKE_linestyle_path_to_color_ramp(FreestyleLineStyle *linestyle, ColorBand if (color_ramp == ((LineStyleColorModifier_Material *)m)->color_ramp) found = true; break; + case LS_MODIFIER_TANGENT: + if (color_ramp == ((LineStyleColorModifier_Tangent *)m)->color_ramp) + found = true; + break; + case LS_MODIFIER_NOISE: + if (color_ramp == ((LineStyleColorModifier_Noise *)m)->color_ramp) + found = true; + break; + case LS_MODIFIER_CREASE_ANGLE: + if (color_ramp == ((LineStyleColorModifier_CreaseAngle*)m)->color_ramp) + found = true; + break; + case LS_MODIFIER_CURVATURE_3D: + if (color_ramp == ((LineStyleColorModifier_Curvature_3D *)m)->color_ramp) + found = true; + break; } if (found) { diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 9976594ad0b..2eba2b274b3 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -7371,6 +7371,30 @@ static void direct_link_linestyle_color_modifier(FileData *fd, LineStyleModifier m->color_ramp = newdataadr(fd, m->color_ramp); } break; + case LS_MODIFIER_TANGENT: + { + LineStyleColorModifier_Tangent *m = (LineStyleColorModifier_Tangent *)modifier; + m->color_ramp = newdataadr(fd, m->color_ramp); + } + break; + case LS_MODIFIER_NOISE: + { + LineStyleColorModifier_Noise *m = (LineStyleColorModifier_Noise *)modifier; + m->color_ramp = newdataadr(fd, m->color_ramp); + } + break; + case LS_MODIFIER_CREASE_ANGLE: + { + LineStyleColorModifier_CreaseAngle *m = (LineStyleColorModifier_CreaseAngle *)modifier; + m->color_ramp = newdataadr(fd, m->color_ramp); + } + break; + case LS_MODIFIER_CURVATURE_3D: + { + LineStyleColorModifier_Curvature_3D *m = (LineStyleColorModifier_Curvature_3D *)modifier; + m->color_ramp = newdataadr(fd, m->color_ramp); + } + break; } } @@ -7405,6 +7429,34 @@ static void direct_link_linestyle_alpha_modifier(FileData *fd, LineStyleModifier direct_link_curvemapping(fd, m->curve); } break; + case LS_MODIFIER_TANGENT: + { + LineStyleAlphaModifier_Tangent *m = (LineStyleAlphaModifier_Tangent *)modifier; + m->curve = newdataadr(fd, m->curve); + direct_link_curvemapping(fd, m->curve); + } + break; + case LS_MODIFIER_NOISE: + { + LineStyleAlphaModifier_Noise *m = (LineStyleAlphaModifier_Noise *)modifier; + m->curve = newdataadr(fd, m->curve); + direct_link_curvemapping(fd, m->curve); + } + break; + case LS_MODIFIER_CREASE_ANGLE: + { + LineStyleAlphaModifier_CreaseAngle *m = (LineStyleAlphaModifier_CreaseAngle *)modifier; + m->curve = newdataadr(fd, m->curve); + direct_link_curvemapping(fd, m->curve); + } + break; + case LS_MODIFIER_CURVATURE_3D: + { + LineStyleAlphaModifier_Curvature_3D *m = (LineStyleAlphaModifier_Curvature_3D *)modifier; + m->curve = newdataadr(fd, m->curve); + direct_link_curvemapping(fd, m->curve); + } + break; } } @@ -7439,6 +7491,27 @@ static void direct_link_linestyle_thickness_modifier(FileData *fd, LineStyleModi direct_link_curvemapping(fd, m->curve); } break; + case LS_MODIFIER_TANGENT: + { + LineStyleThicknessModifier_Tangent *m = (LineStyleThicknessModifier_Tangent *)modifier; + m->curve = newdataadr(fd, m->curve); + direct_link_curvemapping(fd, m->curve); + } + break; + case LS_MODIFIER_CREASE_ANGLE: + { + LineStyleThicknessModifier_CreaseAngle *m = (LineStyleThicknessModifier_CreaseAngle *)modifier; + m->curve = newdataadr(fd, m->curve); + direct_link_curvemapping(fd, m->curve); + } + break; + case LS_MODIFIER_CURVATURE_3D: + { + LineStyleThicknessModifier_Curvature_3D *m = (LineStyleThicknessModifier_Curvature_3D *)modifier; + m->curve = newdataadr(fd, m->curve); + direct_link_curvemapping(fd, m->curve); + } + break; } } diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index aa44b484f03..25d3f4f0dfb 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -3354,6 +3354,18 @@ static void write_linestyle_color_modifiers(WriteData *wd, ListBase *modifiers) case LS_MODIFIER_MATERIAL: struct_name = "LineStyleColorModifier_Material"; break; + case LS_MODIFIER_TANGENT: + struct_name = "LineStyleColorModifier_Tangent"; + break; + case LS_MODIFIER_NOISE: + struct_name = "LineStyleColorModifier_Noise"; + break; + case LS_MODIFIER_CREASE_ANGLE: + struct_name = "LineStyleColorModifier_CreaseAngle"; + break; + case LS_MODIFIER_CURVATURE_3D: + struct_name = "LineStyleColorModifier_Curvature_3D"; + break; default: struct_name = "LineStyleColorModifier"; /* this should not happen */ } @@ -3373,6 +3385,18 @@ static void write_linestyle_color_modifiers(WriteData *wd, ListBase *modifiers) case LS_MODIFIER_MATERIAL: writestruct(wd, DATA, "ColorBand", 1, ((LineStyleColorModifier_Material *)m)->color_ramp); break; + case LS_MODIFIER_TANGENT: + writestruct(wd, DATA, "ColorBand", 1, ((LineStyleColorModifier_Tangent *)m)->color_ramp); + break; + case LS_MODIFIER_NOISE: + writestruct(wd, DATA, "ColorBand", 1, ((LineStyleColorModifier_Noise *)m)->color_ramp); + break; + case LS_MODIFIER_CREASE_ANGLE: + writestruct(wd, DATA, "ColorBand", 1, ((LineStyleColorModifier_CreaseAngle *)m)->color_ramp); + break; + case LS_MODIFIER_CURVATURE_3D: + writestruct(wd, DATA, "ColorBand", 1, ((LineStyleColorModifier_Curvature_3D *)m)->color_ramp); + break; } } } @@ -3396,6 +3420,18 @@ static void write_linestyle_alpha_modifiers(WriteData *wd, ListBase *modifiers) case LS_MODIFIER_MATERIAL: struct_name = "LineStyleAlphaModifier_Material"; break; + case LS_MODIFIER_TANGENT: + struct_name = "LineStyleAlphaModifier_Tangent"; + break; + case LS_MODIFIER_NOISE: + struct_name = "LineStyleAlphaModifier_Noise"; + break; + case LS_MODIFIER_CREASE_ANGLE: + struct_name = "LineStyleAlphaModifier_CreaseAngle"; + break; + case LS_MODIFIER_CURVATURE_3D: + struct_name = "LineStyleAlphaModifier_Curvature_3D"; + break; default: struct_name = "LineStyleAlphaModifier"; /* this should not happen */ } @@ -3415,6 +3451,18 @@ static void write_linestyle_alpha_modifiers(WriteData *wd, ListBase *modifiers) case LS_MODIFIER_MATERIAL: write_curvemapping(wd, ((LineStyleAlphaModifier_Material *)m)->curve); break; + case LS_MODIFIER_TANGENT: + write_curvemapping(wd, ((LineStyleAlphaModifier_Tangent *)m)->curve); + break; + case LS_MODIFIER_NOISE: + write_curvemapping(wd, ((LineStyleAlphaModifier_Noise *)m)->curve); + break; + case LS_MODIFIER_CREASE_ANGLE: + write_curvemapping(wd, ((LineStyleAlphaModifier_CreaseAngle *)m)->curve); + break; + case LS_MODIFIER_CURVATURE_3D: + write_curvemapping(wd, ((LineStyleAlphaModifier_Curvature_3D *)m)->curve); + break; } } } @@ -3441,6 +3489,18 @@ static void write_linestyle_thickness_modifiers(WriteData *wd, ListBase *modifie case LS_MODIFIER_CALLIGRAPHY: struct_name = "LineStyleThicknessModifier_Calligraphy"; break; + case LS_MODIFIER_TANGENT: + struct_name = "LineStyleThicknessModifier_Tangent"; + break; + case LS_MODIFIER_NOISE: + struct_name = "LineStyleThicknessModifier_Noise"; + break; + case LS_MODIFIER_CREASE_ANGLE: + struct_name = "LineStyleThicknessModifier_CreaseAngle"; + break; + case LS_MODIFIER_CURVATURE_3D: + struct_name = "LineStyleThicknessModifier_Curvature_3D"; + break; default: struct_name = "LineStyleThicknessModifier"; /* this should not happen */ } @@ -3460,6 +3520,15 @@ static void write_linestyle_thickness_modifiers(WriteData *wd, ListBase *modifie case LS_MODIFIER_MATERIAL: write_curvemapping(wd, ((LineStyleThicknessModifier_Material *)m)->curve); break; + case LS_MODIFIER_TANGENT: + write_curvemapping(wd, ((LineStyleThicknessModifier_Tangent *)m)->curve); + break; + case LS_MODIFIER_CREASE_ANGLE: + write_curvemapping(wd, ((LineStyleThicknessModifier_CreaseAngle *)m)->curve); + break; + case LS_MODIFIER_CURVATURE_3D: + write_curvemapping(wd, ((LineStyleThicknessModifier_Curvature_3D *)m)->curve); + break; } } } @@ -3510,6 +3579,9 @@ static void write_linestyle_geometry_modifiers(WriteData *wd, ListBase *modifier case LS_MODIFIER_2D_TRANSFORM: struct_name = "LineStyleGeometryModifier_2DTransform"; break; + case LS_MODIFIER_SIMPLIFICATION: + struct_name = "LineStyleGeometryModifier_Simplification"; + break; default: struct_name = "LineStyleGeometryModifier"; /* this should not happen */ } diff --git a/source/blender/freestyle/intern/python/BPy_FrsNoise.cpp b/source/blender/freestyle/intern/python/BPy_FrsNoise.cpp index 39e4aed7cc0..21a5ceaa3b2 100644 --- a/source/blender/freestyle/intern/python/BPy_FrsNoise.cpp +++ b/source/blender/freestyle/intern/python/BPy_FrsNoise.cpp @@ -25,6 +25,8 @@ #include "BPy_FrsNoise.h" #include "BPy_Convert.h" +#include "../system/RandGen.h" + #include <sstream> #ifdef __cplusplus @@ -69,12 +71,14 @@ static int FrsNoise_init(BPy_FrsNoise *self, PyObject *args, PyObject *kwds) if (!PyArg_ParseTupleAndKeywords(args, kwds, "|l", (char **)kwlist, &seed)) return -1; self->n = new Noise(seed); + self->pn = new PseudoNoise(); return 0; } static void FrsNoise_dealloc(BPy_FrsNoise *self) { delete self->n; + delete self->pn; Py_TYPE(self)->tp_free((PyObject *)self); } @@ -99,6 +103,32 @@ PyDoc_STRVAR(FrsNoise_turbulence1_doc, " :return: A noise value.\n" " :rtype: float"); +static PyObject *FrsNoise_drand(BPy_FrsNoise *self, PyObject *args, PyObject *kwds) +{ + static const char *kwlist[] = {"seed", NULL}; + long seed = 0; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|I", (char **)kwlist, &seed)) { + PyErr_SetString(PyExc_TypeError, "optional argument 1 must be of type int"); + return NULL; + } + if (seed){ + RandGen::srand48(seed); + } + return PyFloat_FromDouble(RandGen::drand48()); +} + +static PyObject *FrsNoise_turbulence_smooth(BPy_FrsNoise *self, PyObject *args, PyObject *kwds) +{ + static const char *kwlist[] = {"v", "oct", NULL}; + + double x; // note: this has to be a double (not float) + unsigned nbOctaves = 8; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "d|I", (char **)kwlist, &x, &nbOctaves)) + return NULL; + return PyFloat_FromDouble(self->pn->turbulenceSmooth(x, nbOctaves)); +} + static PyObject *FrsNoise_turbulence1(BPy_FrsNoise *self, PyObject *args, PyObject *kwds) { static const char *kwlist[] = {"v", "freq", "amp", "oct", NULL}; @@ -257,6 +287,8 @@ static PyMethodDef BPy_FrsNoise_methods[] = { {"smoothNoise1", (PyCFunction)FrsNoise_smoothNoise1, METH_VARARGS | METH_KEYWORDS, FrsNoise_smoothNoise1_doc}, {"smoothNoise2", (PyCFunction)FrsNoise_smoothNoise2, METH_VARARGS | METH_KEYWORDS, FrsNoise_smoothNoise2_doc}, {"smoothNoise3", (PyCFunction)FrsNoise_smoothNoise3, METH_VARARGS | METH_KEYWORDS, FrsNoise_smoothNoise3_doc}, + {"rand", (PyCFunction)FrsNoise_drand, METH_VARARGS | METH_KEYWORDS, NULL}, + {"turbulence_smooth", (PyCFunction)FrsNoise_turbulence_smooth, METH_VARARGS | METH_KEYWORDS, NULL}, {NULL, NULL, 0, NULL} }; diff --git a/source/blender/freestyle/intern/python/BPy_FrsNoise.h b/source/blender/freestyle/intern/python/BPy_FrsNoise.h index 19788e30a43..a5a1064ea8d 100644 --- a/source/blender/freestyle/intern/python/BPy_FrsNoise.h +++ b/source/blender/freestyle/intern/python/BPy_FrsNoise.h @@ -30,6 +30,7 @@ extern "C" { } #include "../geometry/Noise.h" +#include "../system/PseudoNoise.h" using namespace Freestyle; @@ -47,6 +48,7 @@ extern PyTypeObject FrsNoise_Type; typedef struct { PyObject_HEAD Noise *n; + PseudoNoise *pn; } BPy_FrsNoise; /*---------------------------Python BPy_FrsNoise visible prototypes-----------*/ diff --git a/source/blender/freestyle/intern/stroke/BasicStrokeShaders.cpp b/source/blender/freestyle/intern/stroke/BasicStrokeShaders.cpp index 11b7df7ecec..eed90a53d77 100644 --- a/source/blender/freestyle/intern/stroke/BasicStrokeShaders.cpp +++ b/source/blender/freestyle/intern/stroke/BasicStrokeShaders.cpp @@ -185,7 +185,7 @@ int ThicknessNoiseShader::shade(Stroke& stroke) const real bruit, bruit2; PseudoNoise mynoise, mynoise2; for (vend = stroke.strokeVerticesEnd(); v != vend; ++v) { - bruit = mynoise.turbulenceSmooth(_scale * v->curvilinearAbscissa() + initU1, 2); // 2 : nbOctaves + bruit = mynoise.turbulenceSmooth(_scale * v->curvilinearAbscissa() + initU1, 2); // 2 : nbOctaves bruit2 = mynoise2.turbulenceSmooth(_scale * v->curvilinearAbscissa() + initU2, 2); // 2 : nbOctaves const float *originalThickness = v->attribute().getThickness(); float r = bruit * _amplitude + originalThickness[0]; diff --git a/source/blender/makesdna/DNA_linestyle_types.h b/source/blender/makesdna/DNA_linestyle_types.h index ac848600c2d..c613dd3d856 100644 --- a/source/blender/makesdna/DNA_linestyle_types.h +++ b/source/blender/makesdna/DNA_linestyle_types.h @@ -79,7 +79,12 @@ typedef struct LineStyleModifier { #define LS_MODIFIER_BLUEPRINT 16 #define LS_MODIFIER_2D_OFFSET 17 #define LS_MODIFIER_2D_TRANSFORM 18 -#define LS_MODIFIER_NUM 19 +#define LS_MODIFIER_TANGENT 19 +#define LS_MODIFIER_NOISE 20 +#define LS_MODIFIER_CREASE_ANGLE 21 +#define LS_MODIFIER_SIMPLIFICATION 22 +#define LS_MODIFIER_CURVATURE_3D 23 +#define LS_MODIFIER_NUM 24 /* LineStyleModifier::flags */ #define LS_MODIFIER_ENABLED 1 @@ -92,6 +97,9 @@ typedef struct LineStyleModifier { #define LS_MODIFIER_USE_CURVE 1 #define LS_MODIFIER_INVERT 2 +/* flags (for asymmetric thickness application) */ +#define LS_THICKNESS_ASYMMETRIC 1 + /* blend (for alpha & thickness) */ #define LS_VALUE_BLEND 0 #define LS_VALUE_ADD 1 @@ -186,6 +194,117 @@ typedef struct LineStyleThicknessModifier_DistanceFromObject { int pad; } LineStyleThicknessModifier_DistanceFromObject; +/* 3D curvature modifiers */ + +typedef struct LineStyleColorModifier_Curvature_3D { + struct LineStyleModifier modifier; + + float min_curvature, max_curvature; + + struct ColorBand *color_ramp; + float range_min, range_max; +}LineStyleColorModifier_Curvature_3D; + +typedef struct LineStyleAlphaModifier_Curvature_3D { + struct LineStyleModifier modifier; + + struct CurveMapping *curve; + int flags; + float min_curvature, max_curvature; + int pad; +}LineStyleAlphaModifier_Curvature_3D; + +typedef struct LineStyleThicknessModifier_Curvature_3D { + struct LineStyleModifier modifier; + + struct CurveMapping *curve; + int flags, pad; + + float min_curvature, max_curvature; + float min_thickness, max_thickness; +}LineStyleThicknessModifier_Curvature_3D; + +/* Noise modifiers (for color, alpha and thickness) */ + +typedef struct LineStyleColorModifier_Noise { + struct LineStyleModifier modifier; + + struct ColorBand *color_ramp; + float period, amplitude; + int seed, pad; +} LineStyleColorModifier_Noise; + +typedef struct LineStyleAlphaModifier_Noise { + struct LineStyleModifier modifier; + + struct CurveMapping *curve; + int flags; + float period, amplitude; + int seed; +} LineStyleAlphaModifier_Noise; + +typedef struct LineStyleThicknessModifier_Noise { + struct LineStyleModifier modifier; + + float period, amplitude; + int flags; + int seed; + +} LineStyleThicknessModifier_Noise; + +/* Crease Angle modifiers */ + +typedef struct LineStyleColorModifier_CreaseAngle { + struct LineStyleModifier modifier; + + struct ColorBand *color_ramp; + float min_angle, max_angle; +} LineStyleColorModifier_CreaseAngle; + +typedef struct LineStyleAlphaModifier_CreaseAngle { + struct LineStyleModifier modifier; + + struct CurveMapping *curve; + int flags; + float min_angle, max_angle; + int pad; +} LineStyleAlphaModifier_CreaseAngle; + +typedef struct LineStyleThicknessModifier_CreaseAngle { + struct LineStyleModifier modifier; + + struct CurveMapping *curve; + int flags, pad; + + float min_angle, max_angle; + float min_thickness, max_thickness; +} LineStyleThicknessModifier_CreaseAngle; + +/* Tangent modifiers */ + +typedef struct LineStyleColorModifier_Tangent { + struct LineStyleModifier modifier; + + struct ColorBand *color_ramp; +} LineStyleColorModifier_Tangent; + +typedef struct LineStyleAlphaModifier_Tangent { + struct LineStyleModifier modifier; + + struct CurveMapping *curve; + int flags; + int pad; +} LineStyleAlphaModifier_Tangent; + +typedef struct LineStyleThicknessModifier_Tangent { + struct LineStyleModifier modifier; + + struct CurveMapping *curve; + int flags; + float min_thickness, max_thickness; + int pad; +} LineStyleThicknessModifier_Tangent; + /* Material modifiers */ /* mat_attr */ @@ -354,6 +473,13 @@ typedef struct LineStyleGeometryModifier_2DTransform { int pad; } LineStyleGeometryModifier_2DTransform; +typedef struct LineStyleGeometryModifier_Simplification { + struct LineStyleModifier modifier; + + float tolerance; + int pad; +}LineStyleGeometryModifier_Simplification; + /* Calligraphic thickness modifier */ typedef struct LineStyleThicknessModifier_Calligraphy { diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 6b056422404..406bab011aa 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -316,14 +316,22 @@ extern StructRNA RNA_LimitRotationConstraint; extern StructRNA RNA_LimitScaleConstraint; extern StructRNA RNA_LineStyleAlphaModifier; extern StructRNA RNA_LineStyleAlphaModifier_AlongStroke; +extern StructRNA RNA_LineStyleAlphaModifier_CreaseAngle; +extern StructRNA RNA_LineStyleAlphaModifier_Curvature_3D; extern StructRNA RNA_LineStyleAlphaModifier_DistanceFromCamera; extern StructRNA RNA_LineStyleAlphaModifier_DistanceFromObject; extern StructRNA RNA_LineStyleAlphaModifier_Material; +extern StructRNA RNA_LineStyleAlphaModifier_Noise; +extern StructRNA RNA_LineStyleAlphaModifier_Tangent; extern StructRNA RNA_LineStyleColorModifier; extern StructRNA RNA_LineStyleColorModifier_AlongStroke; +extern StructRNA RNA_LineStyleColorModifier_CreaseAngle; +extern StructRNA RNA_LineStyleColorModifier_Curvature_3D; extern StructRNA RNA_LineStyleColorModifier_DistanceFromCamera; extern StructRNA RNA_LineStyleColorModifier_DistanceFromObject; extern StructRNA RNA_LineStyleColorModifier_Material; +extern StructRNA RNA_LineStyleColorModifier_Noise; +extern StructRNA RNA_LineStyleColorModifier_Tangent; extern StructRNA RNA_LineStyleGeometryModifier; extern StructRNA RNA_LineStyleGeometryModifier_2DOffset; extern StructRNA RNA_LineStyleGeometryModifier_2DTransform; @@ -335,6 +343,7 @@ extern StructRNA RNA_LineStyleGeometryModifier_PerlinNoise1D; extern StructRNA RNA_LineStyleGeometryModifier_PerlinNoise2D; extern StructRNA RNA_LineStyleGeometryModifier_Polygonalization; extern StructRNA RNA_LineStyleGeometryModifier_Sampling; +extern StructRNA RNA_LineStyleGeometryModifier_Simplification; extern StructRNA RNA_LineStyleGeometryModifier_SinusDisplacement; extern StructRNA RNA_LineStyleGeometryModifier_SpatialNoise; extern StructRNA RNA_LineStyleGeometryModifier_TipRemover; @@ -343,9 +352,13 @@ extern StructRNA RNA_LineStyleTextureSlot; extern StructRNA RNA_LineStyleThicknessModifier; extern StructRNA RNA_LineStyleThicknessModifier_AlongStroke; extern StructRNA RNA_LineStyleThicknessModifier_Calligraphy; +extern StructRNA RNA_LineStyleThicknessModifier_CreaseAngle; +extern StructRNA RNA_LineStyleThicknessModifier_Curvature_3D; extern StructRNA RNA_LineStyleThicknessModifier_DistanceFromCamera; extern StructRNA RNA_LineStyleThicknessModifier_DistanceFromObject; extern StructRNA RNA_LineStyleThicknessModifier_Material; +extern StructRNA RNA_LineStyleThicknessModifier_Noise; +extern StructRNA RNA_LineStyleThicknessModifier_Tangent; extern StructRNA RNA_LockedTrackConstraint; extern StructRNA RNA_Macro; extern StructRNA RNA_MagicTexture; diff --git a/source/blender/makesrna/intern/rna_linestyle.c b/source/blender/makesrna/intern/rna_linestyle.c index 638bc7a17ea..81f3e149a71 100644 --- a/source/blender/makesrna/intern/rna_linestyle.c +++ b/source/blender/makesrna/intern/rna_linestyle.c @@ -41,26 +41,38 @@ EnumPropertyItem linestyle_color_modifier_type_items[] = { {LS_MODIFIER_ALONG_STROKE, "ALONG_STROKE", ICON_MODIFIER, "Along Stroke", ""}, + {LS_MODIFIER_CREASE_ANGLE, "CREASE_ANGLE", ICON_MODIFIER, "Crease Angle", ""}, + {LS_MODIFIER_CURVATURE_3D, "CURVATURE_3D", ICON_MODIFIER, "Curvature 3D", ""}, {LS_MODIFIER_DISTANCE_FROM_CAMERA, "DISTANCE_FROM_CAMERA", ICON_MODIFIER, "Distance from Camera", ""}, {LS_MODIFIER_DISTANCE_FROM_OBJECT, "DISTANCE_FROM_OBJECT", ICON_MODIFIER, "Distance from Object", ""}, {LS_MODIFIER_MATERIAL, "MATERIAL", ICON_MODIFIER, "Material", ""}, + {LS_MODIFIER_NOISE, "NOISE", ICON_MODIFIER, "Noise", ""}, + {LS_MODIFIER_TANGENT, "TANGENT", ICON_MODIFIER, "Tangent", ""}, {0, NULL, 0, NULL, NULL} }; EnumPropertyItem linestyle_alpha_modifier_type_items[] = { {LS_MODIFIER_ALONG_STROKE, "ALONG_STROKE", ICON_MODIFIER, "Along Stroke", ""}, + {LS_MODIFIER_CREASE_ANGLE, "CREASE_ANGLE", ICON_MODIFIER, "Crease Angle", ""}, + {LS_MODIFIER_CURVATURE_3D, "CURVATURE_3D", ICON_MODIFIER, "Curvature 3D", ""}, {LS_MODIFIER_DISTANCE_FROM_CAMERA, "DISTANCE_FROM_CAMERA", ICON_MODIFIER, "Distance from Camera", ""}, {LS_MODIFIER_DISTANCE_FROM_OBJECT, "DISTANCE_FROM_OBJECT", ICON_MODIFIER, "Distance from Object", ""}, {LS_MODIFIER_MATERIAL, "MATERIAL", ICON_MODIFIER, "Material", ""}, + {LS_MODIFIER_NOISE, "NOISE", ICON_MODIFIER, "Noise", ""}, + {LS_MODIFIER_TANGENT, "TANGENT", ICON_MODIFIER, "Tangent", ""}, {0, NULL, 0, NULL, NULL} }; EnumPropertyItem linestyle_thickness_modifier_type_items[] = { {LS_MODIFIER_ALONG_STROKE, "ALONG_STROKE", ICON_MODIFIER, "Along Stroke", ""}, {LS_MODIFIER_CALLIGRAPHY, "CALLIGRAPHY", ICON_MODIFIER, "Calligraphy", ""}, + {LS_MODIFIER_CREASE_ANGLE, "CREASE_ANGLE", ICON_MODIFIER, "Crease Angle", ""}, + {LS_MODIFIER_CURVATURE_3D, "CURVATURE_3D", ICON_MODIFIER, "Curvature 3D", ""}, {LS_MODIFIER_DISTANCE_FROM_CAMERA, "DISTANCE_FROM_CAMERA", ICON_MODIFIER, "Distance from Camera", ""}, {LS_MODIFIER_DISTANCE_FROM_OBJECT, "DISTANCE_FROM_OBJECT", ICON_MODIFIER, "Distance from Object", ""}, {LS_MODIFIER_MATERIAL, "MATERIAL", ICON_MODIFIER, "Material", ""}, + {LS_MODIFIER_NOISE, "NOISE", ICON_MODIFIER, "Noise", ""}, + {LS_MODIFIER_TANGENT, "TANGENT", ICON_MODIFIER, "Tangent", ""}, {0, NULL, 0, NULL, NULL} }; @@ -75,6 +87,7 @@ EnumPropertyItem linestyle_geometry_modifier_type_items[] = { {LS_MODIFIER_PERLIN_NOISE_2D, "PERLIN_NOISE_2D", ICON_MODIFIER, "Perlin Noise 2D", ""}, {LS_MODIFIER_POLYGONIZATION, "POLYGONIZATION", ICON_MODIFIER, "Polygonization", ""}, {LS_MODIFIER_SAMPLING, "SAMPLING", ICON_MODIFIER, "Sampling", ""}, + {LS_MODIFIER_SIMPLIFICATION, "SIMPLIFICATION", ICON_MODIFIER, "Simplification", ""}, {LS_MODIFIER_SINUS_DISPLACEMENT, "SINUS_DISPLACEMENT", ICON_MODIFIER, "Sinus Displacement", ""}, {LS_MODIFIER_SPATIAL_NOISE, "SPATIAL_NOISE", ICON_MODIFIER, "Spatial Noise", ""}, {LS_MODIFIER_TIP_REMOVER, "TIP_REMOVER", ICON_MODIFIER, "Tip Remover", ""}, @@ -104,6 +117,14 @@ static StructRNA *rna_LineStyle_color_modifier_refine(struct PointerRNA *ptr) return &RNA_LineStyleColorModifier_DistanceFromObject; case LS_MODIFIER_MATERIAL: return &RNA_LineStyleColorModifier_Material; + case LS_MODIFIER_TANGENT: + return &RNA_LineStyleColorModifier_Tangent; + case LS_MODIFIER_NOISE: + return &RNA_LineStyleColorModifier_Noise; + case LS_MODIFIER_CREASE_ANGLE: + return &RNA_LineStyleColorModifier_CreaseAngle; + case LS_MODIFIER_CURVATURE_3D: + return &RNA_LineStyleColorModifier_Curvature_3D; default: return &RNA_LineStyleColorModifier; } @@ -122,6 +143,14 @@ static StructRNA *rna_LineStyle_alpha_modifier_refine(struct PointerRNA *ptr) return &RNA_LineStyleAlphaModifier_DistanceFromObject; case LS_MODIFIER_MATERIAL: return &RNA_LineStyleAlphaModifier_Material; + case LS_MODIFIER_TANGENT: + return &RNA_LineStyleAlphaModifier_Tangent; + case LS_MODIFIER_NOISE: + return &RNA_LineStyleAlphaModifier_Noise; + case LS_MODIFIER_CREASE_ANGLE: + return &RNA_LineStyleAlphaModifier_CreaseAngle; + case LS_MODIFIER_CURVATURE_3D: + return &RNA_LineStyleAlphaModifier_Curvature_3D; default: return &RNA_LineStyleAlphaModifier; } @@ -142,6 +171,14 @@ static StructRNA *rna_LineStyle_thickness_modifier_refine(struct PointerRNA *ptr return &RNA_LineStyleThicknessModifier_Material; case LS_MODIFIER_CALLIGRAPHY: return &RNA_LineStyleThicknessModifier_Calligraphy; + case LS_MODIFIER_TANGENT: + return &RNA_LineStyleThicknessModifier_Tangent; + case LS_MODIFIER_NOISE: + return &RNA_LineStyleThicknessModifier_Noise; + case LS_MODIFIER_CREASE_ANGLE: + return &RNA_LineStyleThicknessModifier_CreaseAngle; + case LS_MODIFIER_CURVATURE_3D: + return &RNA_LineStyleThicknessModifier_Curvature_3D; default: return &RNA_LineStyleThicknessModifier; } @@ -178,6 +215,8 @@ static StructRNA *rna_LineStyle_geometry_modifier_refine(struct PointerRNA *ptr) return &RNA_LineStyleGeometryModifier_2DOffset; case LS_MODIFIER_2D_TRANSFORM: return &RNA_LineStyleGeometryModifier_2DTransform; + case LS_MODIFIER_SIMPLIFICATION: + return &RNA_LineStyleGeometryModifier_Simplification; default: return &RNA_LineStyleGeometryModifier; } @@ -785,6 +824,62 @@ static void rna_def_linestyle_modifiers(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Ramp", "Use color ramp to map the BW average into an RGB color"); RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update"); + srna = RNA_def_struct(brna, "LineStyleColorModifier_Tangent", "LineStyleColorModifier"); + RNA_def_struct_ui_text(srna, "Tangent", "Change line color based on the direction of a stroke"); + rna_def_color_modifier(srna); + rna_def_modifier_color_ramp_common(srna, false); + + srna = RNA_def_struct(brna, "LineStyleColorModifier_Noise", "LineStyleColorModifier"); + RNA_def_struct_ui_text(srna, "Noise", "Change line color based on random noise"); + rna_def_color_modifier(srna); + rna_def_modifier_color_ramp_common(srna, false); + + prop = RNA_def_property(srna, "amplitude", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "amplitude"); + RNA_def_property_ui_text(prop, "Amplitude", "Amplitude of the noise"); + RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update"); + + prop = RNA_def_property(srna, "period", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "period"); + RNA_def_property_ui_text(prop, "Period", "Period of the noise"); + RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update"); + + prop = RNA_def_property(srna, "seed", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "seed"); + RNA_def_property_ui_text(prop, "Seed", "Seed for the noise generation"); + RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update"); + + srna = RNA_def_struct(brna, "LineStyleColorModifier_CreaseAngle", "LineStyleColorModifier"); + RNA_def_struct_ui_text(srna, "Crease Angle", "Change line color based on the underlying crease angle"); + rna_def_color_modifier(srna); + rna_def_modifier_color_ramp_common(srna, false); + + prop = RNA_def_property(srna, "angle_min", PROP_FLOAT, PROP_ANGLE); + RNA_def_property_float_sdna(prop, NULL, "min_angle"); + RNA_def_property_ui_text(prop, "Min Angle", "Minimum angle to modify thickness"); + RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update"); + + prop = RNA_def_property(srna, "angle_max", PROP_FLOAT, PROP_ANGLE); + RNA_def_property_float_sdna(prop, NULL, "max_angle"); + RNA_def_property_ui_text(prop, "Max Angle", "Maximum angle to modify thickness"); + RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update"); + + srna = RNA_def_struct(brna, "LineStyleColorModifier_Curvature_3D", "LineStyleColorModifier"); + RNA_def_struct_ui_text(srna, "Curvature 3D", + "Change line color based on the radial curvature of 3D mesh surfaces"); + rna_def_color_modifier(srna); + rna_def_modifier_color_ramp_common(srna, false); + + prop = RNA_def_property(srna, "curvature_min", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "min_curvature"); + RNA_def_property_ui_text(prop, "Min Curvature", "Minimum Curvature"); + RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update"); + + prop = RNA_def_property(srna, "curvature_max", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "max_curvature"); + RNA_def_property_ui_text(prop, "Max Curvature", "Maximum Curvature"); + RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update"); + /* alpha transparency modifiers */ srna = RNA_def_struct(brna, "LineStyleAlphaModifier", "LineStyleModifier"); @@ -823,14 +918,90 @@ static void rna_def_linestyle_modifiers(BlenderRNA *brna) rna_def_modifier_material_common(srna); rna_def_modifier_curve_common(srna, false, false); - /* line thickness modifiers */ + srna = RNA_def_struct(brna, "LineStyleAlphaModifier_Tangent", "LineStyleAlphaModifier"); + RNA_def_struct_ui_text(srna, "Tangent", "Alpha transparency based on the direction of the stroke"); + rna_def_alpha_modifier(srna); + rna_def_modifier_curve_common(srna, false, false); + + srna = RNA_def_struct(brna, "LineStyleAlphaModifier_Noise", "LineStyleAlphaModifier"); + RNA_def_struct_ui_text(srna, "Noise", "Alpha transparency based on random noise"); + rna_def_alpha_modifier(srna); + rna_def_modifier_curve_common(srna, false, false); + + prop = RNA_def_property(srna, "amplitude", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "amplitude"); + RNA_def_property_ui_text(prop, "Amplitude", "Amplitude of the noise"); + RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update"); + + prop = RNA_def_property(srna, "period", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "period"); + RNA_def_property_ui_text(prop, "Period", "Period of the noise"); + RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update"); + + prop = RNA_def_property(srna, "seed", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "seed"); + RNA_def_property_ui_text(prop, "Seed", "Seed for the noise generation"); + RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update"); + + srna = RNA_def_struct(brna, "LineStyleAlphaModifier_CreaseAngle", "LineStyleAlphaModifier"); + RNA_def_struct_ui_text(srna, "Crease Angle", + "Alpha transparency based on the angle between two adjacent faces"); + rna_def_alpha_modifier(srna); + rna_def_modifier_curve_common(srna, false, false); + + prop = RNA_def_property(srna, "angle_min", PROP_FLOAT, PROP_ANGLE); + RNA_def_property_float_sdna(prop, NULL, "min_angle"); + RNA_def_property_ui_text(prop, "Min Angle", "Minimum angle to modify thickness"); + RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update"); + + prop = RNA_def_property(srna, "angle_max", PROP_FLOAT, PROP_ANGLE); + RNA_def_property_float_sdna(prop, NULL, "max_angle"); + RNA_def_property_ui_text(prop, "Max Angle", "Maximum angle to modify thickness"); + RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update"); + + srna = RNA_def_struct(brna, "LineStyleAlphaModifier_Curvature_3D", "LineStyleAlphaModifier"); + RNA_def_struct_ui_text(srna, "Curvature 3D", + "Alpha transparency based on the radial curvature of 3D mesh surfaces"); + rna_def_alpha_modifier(srna); + rna_def_modifier_curve_common(srna, false, false); + prop = RNA_def_property(srna, "curvature_min", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "min_curvature"); + RNA_def_property_range(prop, 0.0f, 10000.0f); + RNA_def_property_ui_text(prop, "Min Curvature", "Minimum Curvature"); + RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update"); + + prop = RNA_def_property(srna, "curvature_max", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "max_curvature"); + RNA_def_property_range(prop, 0.0f, 10000.0f); + RNA_def_property_ui_text(prop, "Max Curvature", "Maximum Curvature"); + RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update"); + + /* line thickness modifiers */ srna = RNA_def_struct(brna, "LineStyleThicknessModifier", "LineStyleModifier"); RNA_def_struct_sdna(srna, "LineStyleModifier"); RNA_def_struct_refine_func(srna, "rna_LineStyle_thickness_modifier_refine"); RNA_def_struct_path_func(srna, "rna_LineStyle_thickness_modifier_path"); RNA_def_struct_ui_text(srna, "Line Style Thickness Modifier", "Base type to define line thickness modifiers"); + srna = RNA_def_struct(brna, "LineStyleThicknessModifier_Tangent", "LineStyleThicknessModifier"); + RNA_def_struct_ui_text(srna, "Tangent", "Thickness based on the direction of the stroke"); + rna_def_thickness_modifier(srna); + rna_def_modifier_curve_common(srna, false, false); + + prop = RNA_def_property(srna, "thickness_min", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "min_thickness"); + RNA_def_property_range(prop, 0.0f, 10000.0f); + RNA_def_property_ui_text(prop, "Min Thickness", + "Minimum thickness"); + RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update"); + + prop = RNA_def_property(srna, "thickness_max", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "max_thickness"); + RNA_def_property_range(prop, 0.0f, 10000.0f); + RNA_def_property_ui_text(prop, "Max Thickness", "Maximum thickness"); + RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update"); + srna = RNA_def_struct(brna, "LineStyleThicknessModifier_AlongStroke", "LineStyleThicknessModifier"); RNA_def_struct_ui_text(srna, "Along Stroke", "Change line thickness along stroke"); rna_def_thickness_modifier(srna); @@ -882,6 +1053,88 @@ static void rna_def_linestyle_modifiers(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Max Thickness", "Maximum thickness in the main direction"); RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update"); + srna = RNA_def_struct(brna, "LineStyleThicknessModifier_Noise", "LineStyleThicknessModifier"); + RNA_def_struct_ui_text(srna, "Noise", "Line thickness based on random noise"); + rna_def_thickness_modifier(srna); + + prop = RNA_def_property(srna, "amplitude", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "amplitude"); + RNA_def_property_ui_text(prop, "Amplitude", "Amplitude of the noise"); + RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update"); + + prop = RNA_def_property(srna, "period", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "period"); + RNA_def_property_ui_text(prop, "Period", "Period of the noise"); + RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update"); + + prop = RNA_def_property(srna, "seed", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "seed"); + RNA_def_property_ui_text(prop, "Seed", "Seed for the noise generation"); + RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update"); + + prop = RNA_def_property(srna, "use_asymmetric", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flags", LS_THICKNESS_ASYMMETRIC); + RNA_def_property_ui_text(prop, "Asymmetric", "Allow thickness to be assigned asymmetrically"); + RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update"); + + srna = RNA_def_struct(brna, "LineStyleThicknessModifier_Curvature_3D", "LineStyleThicknessModifier"); + RNA_def_struct_ui_text(srna, "Curvature 3D", + "Line thickness based on the radial curvature of 3D mesh surfaces"); + rna_def_thickness_modifier(srna); + rna_def_modifier_curve_common(srna, false, false); + + prop = RNA_def_property(srna, "thickness_min", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "min_thickness"); + RNA_def_property_range(prop, 0.0f, 10000.0f); + RNA_def_property_ui_text(prop, "Min Thickness", "Minimum thickness"); + RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update"); + + prop = RNA_def_property(srna, "thickness_max", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "max_thickness"); + RNA_def_property_range(prop, 0.0f, 10000.0f); + RNA_def_property_ui_text(prop, "Max Thickness", "Maximum thickness"); + RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update"); + + prop = RNA_def_property(srna, "curvature_min", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "min_curvature"); + RNA_def_property_range(prop, 0.0f, 10000.0f); + RNA_def_property_ui_text(prop, "Min Curvature", "Minimum Curvature"); + RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update"); + + prop = RNA_def_property(srna, "curvature_max", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "max_curvature"); + RNA_def_property_range(prop, 0.0f, 10000.0f); + RNA_def_property_ui_text(prop, "Max Curvature", "Maximum Curvature"); + RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update"); + + srna = RNA_def_struct(brna, "LineStyleThicknessModifier_CreaseAngle", "LineStyleThicknessModifier"); + RNA_def_struct_ui_text(srna, "Crease Angle", + "Line thickness based on the angle between two adjacent faces"); + rna_def_thickness_modifier(srna); + rna_def_modifier_curve_common(srna, false, false); + + prop = RNA_def_property(srna, "angle_min", PROP_FLOAT, PROP_ANGLE); + RNA_def_property_float_sdna(prop, NULL, "min_angle"); + RNA_def_property_ui_text(prop, "Min Angle", "Minimum angle to modify thickness"); + RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update"); + + prop = RNA_def_property(srna, "angle_max", PROP_FLOAT, PROP_ANGLE); + RNA_def_property_float_sdna(prop, NULL, "max_angle"); + RNA_def_property_ui_text(prop, "Max Angle", "Maximum angle to modify thickness"); + RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update"); + + prop = RNA_def_property(srna, "thickness_min", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "min_thickness"); + RNA_def_property_range(prop, 0.0f, 10000.0f); + RNA_def_property_ui_text(prop, "Min Thickness", "Minimum thickness"); + RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update"); + + prop = RNA_def_property(srna, "thickness_max", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "max_thickness"); + RNA_def_property_range(prop, 0.0f, 10000.0f); + RNA_def_property_ui_text(prop, "Max Thickness", "Maximum thickness"); + RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update"); + /* geometry modifiers */ srna = RNA_def_struct(brna, "LineStyleGeometryModifier", "LineStyleModifier"); @@ -1167,6 +1420,15 @@ static void rna_def_linestyle_modifiers(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "pivot_y"); RNA_def_property_ui_text(prop, "Pivot Y", "2D Y coordinate of the absolute pivot"); RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update"); + + srna = RNA_def_struct(brna, "LineStyleGeometryModifier_Simplification", "LineStyleGeometryModifier"); + RNA_def_struct_ui_text(srna, "Simplification", "Simplify the stroke set"); + rna_def_geometry_modifier(srna); + + prop = RNA_def_property(srna, "tolerance", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "tolerance"); + RNA_def_property_ui_text(prop, "Tolerance", "Distance below which segments will be merged"); + RNA_def_property_update(prop, NC_LINESTYLE, "rna_LineStyle_update"); } static void rna_def_freestyle_color_modifiers(BlenderRNA *brna, PropertyRNA *cprop) |