Fix for Sinus Displacement and 2D Offset stroke geometry modifiers.

These modifiers were not working properly when they were applied to strokes
whose backbone was already modified by other geometry shaders.  This problem
was due to the use of Normal2DF0D that compute 2D vertex normals based on
the underlying FEdges up on which initial stroke geometry is defined.  Now vertex
normals are computed on the basis of modified stroke vertices.

A helper function 'stroke_normal' for computing normals of stroke vertices was
added to the 'freestyle.utils' API module.
This commit is contained in:
Tamito Kajiyama 2014-04-11 15:16:03 +09:00
parent 88298f1c40
commit 716803c0a0
3 changed files with 59 additions and 12 deletions

View File

@ -39,8 +39,10 @@ from freestyle.types import (
from freestyle.predicates import (
ExternalContourUP1D,
)
from freestyle.utils import ContextFunctions as CF
from freestyle.utils import (
ContextFunctions as CF,
stroke_normal,
)
import bpy

View File

@ -26,3 +26,44 @@ from _freestyle import (
getCurrentScene,
integrate,
)
# constructs for definition of helper functions in Python
from freestyle.types import (
StrokeVertexIterator,
)
import mathutils
def stroke_normal(it):
"""
Compute the 2D normal at the stroke vertex pointed by the iterator
'it'. It is noted that Normal2DF0D computes normals based on
underlying FEdges instead, which is inappropriate for strokes when
they have already been modified by stroke geometry modifiers.
"""
# first stroke segment
it_next = StrokeVertexIterator(it)
it_next.increment()
if it.is_begin:
e = it_next.object.point_2d - it.object.point_2d
n = mathutils.Vector((e[1], -e[0]))
n.normalize()
return n
# last stroke segment
it_prev = StrokeVertexIterator(it)
it_prev.decrement()
if it_next.is_end:
e = it.object.point_2d - it_prev.object.point_2d
n = mathutils.Vector((e[1], -e[0]))
n.normalize()
return n
# two subsequent stroke segments
e1 = it_next.object.point_2d - it.object.point_2d
e2 = it.object.point_2d - it_prev.object.point_2d
n1 = mathutils.Vector((e1[1], -e1[0]))
n2 = mathutils.Vector((e2[1], -e2[0]))
n1.normalize()
n2.normalize()
n = n1 + n2
n.normalize()
return n

View File

@ -76,6 +76,7 @@ from freestyle.shaders import (
from freestyle.utils import (
ContextFunctions,
getCurrentScene,
stroke_normal,
)
from _freestyle import (
blendRamp,
@ -582,13 +583,15 @@ class SinusDisplacementShader(StrokeShader):
self._wavelength = wavelength
self._amplitude = amplitude
self._phase = phase / wavelength * 2 * math.pi
self._getNormal = Normal2DF0D()
def shade(self, stroke):
# separately iterate over stroke vertices to compute normals
buf = []
for it, distance in iter_distance_along_stroke(stroke):
v = it.object
n = self._getNormal(Interface0DIterator(it))
n = n * self._amplitude * math.cos(distance / self._wavelength * 2 * math.pi + self._phase)
buf.append((it.object, distance, stroke_normal(it)))
# iterate over the vertices again to displace them
for v, distance, normal in buf:
n = normal * self._amplitude * math.cos(distance / self._wavelength * 2 * math.pi + self._phase)
v.point = v.point + n
stroke.update_length()
@ -639,18 +642,19 @@ class Offset2DShader(StrokeShader):
self.__start = start
self.__end = end
self.__xy = mathutils.Vector((x, y))
self.__getNormal = Normal2DF0D()
def shade(self, stroke):
# first iterate over stroke vertices to compute normals
buf = []
it = stroke.stroke_vertices_begin()
while not it.is_end:
v = it.object
u = v.u
a = self.__start + u * (self.__end - self.__start)
n = self.__getNormal(Interface0DIterator(it))
buf.append((it.object, stroke_normal(it)))
it.increment()
# again iterate over the vertices to add displacement
for v, n in buf:
a = self.__start + v.u * (self.__end - self.__start)
n = n * a
v.point = v.point + n + self.__xy
it.increment()
stroke.update_length()