[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [32400] branches/soc-2008-mxcurioni: Added support for three types of stroke caps that determines the shape

Tamito Kajiyama rd6t-kjym at asahi-net.or.jp
Mon Oct 11 00:50:32 CEST 2010


Revision: 32400
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=32400
Author:   kjym3
Date:     2010-10-11 00:50:32 +0200 (Mon, 11 Oct 2010)

Log Message:
-----------
Added support for three types of stroke caps that determines the shape
of both ends of strokes.  The three cap types are: 1) butt caps (flat);
2) round caps (half-circle); and 3) square caps (flat and extended).
Also implemented an option to join those feature edges of the same
object.  These options are available in the "Stroke" tab of the
"Freestyle: Line Style" panel in the Render buttons.

Modified Paths:
--------------
    branches/soc-2008-mxcurioni/release/scripts/freestyle/style_modules/parameter_editor.py
    branches/soc-2008-mxcurioni/release/scripts/ui/properties_render.py
    branches/soc-2008-mxcurioni/source/blender/blenkernel/intern/linestyle.c
    branches/soc-2008-mxcurioni/source/blender/makesdna/DNA_linestyle_types.h
    branches/soc-2008-mxcurioni/source/blender/makesrna/intern/rna_linestyle.c

Modified: branches/soc-2008-mxcurioni/release/scripts/freestyle/style_modules/parameter_editor.py
===================================================================
--- branches/soc-2008-mxcurioni/release/scripts/freestyle/style_modules/parameter_editor.py	2010-10-10 22:15:48 UTC (rev 32399)
+++ branches/soc-2008-mxcurioni/release/scripts/freestyle/style_modules/parameter_editor.py	2010-10-10 22:50:32 UTC (rev 32400)
@@ -17,6 +17,7 @@
 # ##### END GPL LICENSE BLOCK #####
 
 import Freestyle
+import math
 
 from freestyle_init import *
 from logical_operators import *
@@ -298,6 +299,99 @@
         upred = bpred(upred, p)
     return upred
 
+# Stroke caps
+
+def iter_stroke_vertices(stroke):
+    it = stroke.strokeVerticesBegin()
+    while not it.isEnd():
+        yield it.getObject()
+        it.increment()
+
+class RoundCapShader(StrokeShader):
+    def round_cap_thickness(self, x):
+        x = max(0.0, min(x, 1.0))
+        return math.sqrt(1.0 - (x ** 2))
+    def shade(self, stroke):
+        # save the location and attribute of stroke vertices
+        buffer = []
+        for sv in iter_stroke_vertices(stroke):
+            buffer.append((sv.getPoint(), sv.attribute()))
+        # calculate the number of additional vertices to form caps
+        R, L = stroke[0].attribute().getThicknessRL()
+        caplen_beg = (R + L) / 2.0
+        nverts_beg = max(5, int(R + L))
+        R, L = stroke[-1].attribute().getThicknessRL()
+        caplen_end = (R + L) / 2.0
+        nverts_end = max(5, int(R + L))
+        # increase the total number of stroke vertices
+        nverts = stroke.strokeVerticesSize()
+        stroke.Resample(nverts + nverts_beg + nverts_end)
+        # restore the location and attribute of the original vertices
+        for i in range(nverts):
+            p, attr = buffer[i]
+            stroke[nverts_beg + i].setPoint(p)
+            stroke[nverts_beg + i].setAttribute(attr)
+        # reshape the cap at the beginning of the stroke
+        q, attr = buffer[1]
+        p, attr = buffer[0]
+        d = p - q
+        d = d / d.length * caplen_beg
+        n = 1.0 / nverts_beg
+        R, L = attr.getThicknessRL()
+        for i in range(nverts_beg):
+            t = (nverts_beg - i) * n
+            stroke[i].setPoint(p + d * t)
+            r = self.round_cap_thickness((nverts_beg - i + 1) * n)
+            stroke[i].setAttribute(attr)
+            stroke[i].attribute().setThickness(R * r, L * r)
+        # reshape the cap at the end of the stroke
+        q, attr = buffer[-2]
+        p, attr = buffer[-1]
+        d = p - q
+        d = d / d.length * caplen_end
+        n = 1.0 / nverts_end
+        R, L = attr.getThicknessRL()
+        for i in range(nverts_end):
+            t = (nverts_end - i) * n
+            stroke[-i-1].setPoint(p + d * t)
+            r = self.round_cap_thickness((nverts_end - i + 1) * n)
+            stroke[-i-1].setAttribute(attr)
+            stroke[-i-1].attribute().setThickness(R * r, L * r)
+
+class SquareCapShader(StrokeShader):
+    def shade(self, stroke):
+        # save the location and attribute of stroke vertices
+        buffer = []
+        for sv in iter_stroke_vertices(stroke):
+            buffer.append((sv.getPoint(), sv.attribute()))
+        # calculate the number of additional vertices to form caps
+        R, L = stroke[0].attribute().getThicknessRL()
+        caplen_beg = (R + L) / 2.0
+        nverts_beg = 1
+        R, L = stroke[-1].attribute().getThicknessRL()
+        caplen_end = (R + L) / 2.0
+        nverts_end = 1
+        # increase the total number of stroke vertices
+        nverts = stroke.strokeVerticesSize()
+        stroke.Resample(nverts + nverts_beg + nverts_end)
+        # restore the location and attribute of the original vertices
+        for i in range(nverts):
+            p, attr = buffer[i]
+            stroke[nverts_beg + i].setPoint(p)
+            stroke[nverts_beg + i].setAttribute(attr)
+        # reshape the cap at the beginning of the stroke
+        q, attr = buffer[1]
+        p, attr = buffer[0]
+        d = p - q
+        stroke[0].setPoint(p + d / d.length * caplen_beg)
+        stroke[0].setAttribute(attr)
+        # reshape the cap at the end of the stroke
+        q, attr = buffer[-2]
+        p, attr = buffer[-1]
+        d = p - q
+        stroke[-1].setPoint(p + d / d.length * caplen_beg)
+        stroke[-1].setAttribute(attr)
+
 # main function for parameter processing
 
 def process(layer_name, lineset_name):
@@ -372,7 +466,12 @@
         upred = TrueUP1D()
     Operators.select(upred)
     # join feature edges
-    Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(upred)) # FIXME
+    if linestyle.same_object:
+        bpred = SameShapeIdBP1D()
+        chaining_iterator = ChainPredicateIterator(upred, bpred)
+    else:
+        chaining_iterator = ChainSilhouetteIterator()
+    Operators.bidirectionalChain(chaining_iterator, NotUP1D(upred))
     # prepare a list of stroke shaders
     color = linestyle.color
     shaders_list = [
@@ -422,5 +521,9 @@
             shaders_list.append(ThicknessDistanceFromObjectShader(
                 m.blend, m.influence, m.mapping, m.invert, m.curve, m.target,
                 m.range_min, m.range_max, m.value_min, m.value_max))
+    if linestyle.caps == "ROUND":
+        shaders_list.append(RoundCapShader())
+    elif linestyle.caps == "SQUARE":
+        shaders_list.append(SquareCapShader())
     # create strokes using the shaders list
     Operators.create(TrueUP1D(), shaders_list)

Modified: branches/soc-2008-mxcurioni/release/scripts/ui/properties_render.py
===================================================================
--- branches/soc-2008-mxcurioni/release/scripts/ui/properties_render.py	2010-10-10 22:15:48 UTC (rev 32399)
+++ branches/soc-2008-mxcurioni/release/scripts/ui/properties_render.py	2010-10-10 22:50:32 UTC (rev 32400)
@@ -409,7 +409,11 @@
             for modifier in linestyle.thickness_modifiers:
                 self.draw_thickness_modifier(context, modifier)
         elif linestyle.panel == "STROKES":
-            pass
+            col.label(text="Chaining:")
+            col.prop(linestyle, "same_object")
+            col.label(text="Caps:")
+            sub = col.row(align=True)
+            sub.prop(linestyle, "caps", expand=True)
         elif linestyle.panel == "DISTORT":
             pass
         elif linestyle.panel == "MISC":

Modified: branches/soc-2008-mxcurioni/source/blender/blenkernel/intern/linestyle.c
===================================================================
--- branches/soc-2008-mxcurioni/source/blender/blenkernel/intern/linestyle.c	2010-10-10 22:15:48 UTC (rev 32399)
+++ branches/soc-2008-mxcurioni/source/blender/blenkernel/intern/linestyle.c	2010-10-10 22:50:32 UTC (rev 32400)
@@ -62,6 +62,8 @@
 	linestyle->color_modifiers.first = linestyle->color_modifiers.last = NULL;
 	linestyle->alpha_modifiers.first = linestyle->alpha_modifiers.last = NULL;
 	linestyle->thickness_modifiers.first = linestyle->thickness_modifiers.last = NULL;
+
+	linestyle->caps = LS_CAPS_BUTT;
 }
 
 FreestyleLineStyle *FRS_new_linestyle(char *name, struct Main *main)

Modified: branches/soc-2008-mxcurioni/source/blender/makesdna/DNA_linestyle_types.h
===================================================================
--- branches/soc-2008-mxcurioni/source/blender/makesdna/DNA_linestyle_types.h	2010-10-10 22:15:48 UTC (rev 32399)
+++ branches/soc-2008-mxcurioni/source/blender/makesdna/DNA_linestyle_types.h	2010-10-10 22:50:32 UTC (rev 32400)
@@ -179,17 +179,22 @@
 #define LS_PANEL_MISC         6
 
 /* FreestyleLineStyle::flag */
-#define LS_DS_EXPAND 1 /* for animation editors */
+#define LS_DS_EXPAND    1 /* for animation editors */
+#define LS_SAME_OBJECT  2
 
+/* FreestyleLineStyle::caps */
+#define LS_CAPS_BUTT    1
+#define LS_CAPS_ROUND   2
+#define LS_CAPS_SQUARE  3
+
 typedef struct FreestyleLineStyle {
 	ID id;
 	struct AnimData *adt;
 
 	float r, g, b, alpha;
 	float thickness;
-	int flag;
+	int flag, caps;
 	int panel; /* for UI */
-	int pad1;
 
 	ListBase color_modifiers;
 	ListBase alpha_modifiers;

Modified: branches/soc-2008-mxcurioni/source/blender/makesrna/intern/rna_linestyle.c
===================================================================
--- branches/soc-2008-mxcurioni/source/blender/makesrna/intern/rna_linestyle.c	2010-10-10 22:15:48 UTC (rev 32399)
+++ branches/soc-2008-mxcurioni/source/blender/makesrna/intern/rna_linestyle.c	2010-10-10 22:50:32 UTC (rev 32400)
@@ -400,6 +400,11 @@
 		{LS_PANEL_DISTORT, "DISTORT", 0, "Distort", "Show the panel for stroke distortion."},
 		{LS_PANEL_MISC, "MISC", 0, "Misc", "Show the panel for miscellaneous options."},
 		{0, NULL, 0, NULL, NULL}};
+	static EnumPropertyItem cap_items[] = {
+		{LS_CAPS_BUTT, "BUTT", 0, "Butt", "Butt cap (flat)."},
+		{LS_CAPS_ROUND, "ROUND", 0, "Round", "Round cap (half-circle)."},
+		{LS_CAPS_SQUARE, "SQUARE", 0, "Square", "Square cap (flat and extended)."},
+		{0, NULL, 0, NULL, NULL}};
 
 	srna= RNA_def_struct(brna, "FreestyleLineStyle", "ID");
 	RNA_def_struct_ui_text(srna, "Freestyle Line Style", "Freestyle line style, reusable by multiple line sets");
@@ -444,6 +449,17 @@
 	RNA_def_property_struct_type(prop, "LineStyleThicknessModifier");
 	RNA_def_property_ui_text(prop, "Thickness Modifiers", "List of line thickness modifiers.");
 
+	prop= RNA_def_property(srna, "same_object", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_sdna(prop, NULL, "flag", LS_SAME_OBJECT);
+	RNA_def_property_ui_text(prop, "Same Object", "if true, only feature edges of the same object are joined.");
+	RNA_def_property_update(prop, NC_SCENE, NULL);
+
+	prop= RNA_def_property(srna, "caps", PROP_ENUM, PROP_NONE);
+	RNA_def_property_enum_bitflag_sdna(prop, NULL, "caps");
+	RNA_def_property_enum_items(prop, cap_items);
+	RNA_def_property_ui_text(prop, "Cap", "Select the shape of both ends of strokes.");
+	RNA_def_property_update(prop, NC_SCENE, NULL);
+
 }
 
 void RNA_def_linestyle(BlenderRNA *brna)





More information about the Bf-blender-cvs mailing list