forked from bartvdbraak/blender
Fix for stroke rendering instability with stroke geometry shaders.
* Stroke::Resample(int nPoints) was not properly working when a wrong value was returned from Stroke::getLength2D(), resulting in repeated warning messages "Warning: incorrect points number" during stroke rendering. The main cause was that stroke geometry shaders did not update the two-dimensional (2D) length (also referred to as curvilinear abscissa) after they modified the 2D points of stroke vertices. Now all stroke geometry shaders make explicit calls for Stroke::UpdateLength() that has been introduced for recomputing the 2D length. Many thanks to Josef who reported the problem together with sample .blend files for reproducing the issue. * Missing Python wrapper of Stroke::getLength2D() was added.
This commit is contained in:
parent
1f25228857
commit
f0acdcf135
@ -449,6 +449,7 @@ class SinusDisplacementShader(StrokeShader):
|
|||||||
u = v.u()
|
u = v.u()
|
||||||
n = n * self._amplitude * math.cos(distance / self._wavelength * 2 * math.pi + self._phase)
|
n = n * self._amplitude * math.cos(distance / self._wavelength * 2 * math.pi + self._phase)
|
||||||
v.setPoint(p + n)
|
v.setPoint(p + n)
|
||||||
|
stroke.UpdateLength()
|
||||||
|
|
||||||
class PerlinNoise1DShader(StrokeShader):
|
class PerlinNoise1DShader(StrokeShader):
|
||||||
def __init__(self, freq = 10, amp = 10, oct = 4, angle = 45, seed = -1):
|
def __init__(self, freq = 10, amp = 10, oct = 4, angle = 45, seed = -1):
|
||||||
@ -468,6 +469,7 @@ class PerlinNoise1DShader(StrokeShader):
|
|||||||
nres = self.__noise.turbulence1(v.u(), self.__freq, self.__amp, self.__oct)
|
nres = self.__noise.turbulence1(v.u(), self.__freq, self.__amp, self.__oct)
|
||||||
v.setPoint(v.getPoint() + nres * self.__dir)
|
v.setPoint(v.getPoint() + nres * self.__dir)
|
||||||
it.increment()
|
it.increment()
|
||||||
|
stroke.UpdateLength()
|
||||||
|
|
||||||
class PerlinNoise2DShader(StrokeShader):
|
class PerlinNoise2DShader(StrokeShader):
|
||||||
def __init__(self, freq = 10, amp = 10, oct = 4, angle = 45, seed = -1):
|
def __init__(self, freq = 10, amp = 10, oct = 4, angle = 45, seed = -1):
|
||||||
@ -488,6 +490,7 @@ class PerlinNoise2DShader(StrokeShader):
|
|||||||
nres = self.__noise.turbulence2(vec, self.__freq, self.__amp, self.__oct)
|
nres = self.__noise.turbulence2(vec, self.__freq, self.__amp, self.__oct)
|
||||||
v.setPoint(v.getPoint() + nres * self.__dir)
|
v.setPoint(v.getPoint() + nres * self.__dir)
|
||||||
it.increment()
|
it.increment()
|
||||||
|
stroke.UpdateLength()
|
||||||
|
|
||||||
# Predicates and helper functions
|
# Predicates and helper functions
|
||||||
|
|
||||||
|
@ -223,6 +223,29 @@ static PyObject * Stroke_RemoveVertex( BPy_Stroke *self, PyObject *args ) {
|
|||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char Stroke_UpdateLength___doc__[] =
|
||||||
|
".. method:: UpdateLength()\n"
|
||||||
|
"\n"
|
||||||
|
" Updates the 2D length of the Stroke.\n";
|
||||||
|
|
||||||
|
static PyObject * Stroke_UpdateLength( BPy_Stroke *self ) {
|
||||||
|
self->s->UpdateLength();
|
||||||
|
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char Stroke_getLength2D___doc__[] =
|
||||||
|
".. method:: getLength2D()\n"
|
||||||
|
"\n"
|
||||||
|
" Returns the 2D length of the Stroke.\n"
|
||||||
|
"\n"
|
||||||
|
" :return: the 2D length of the Stroke.\n"
|
||||||
|
" :rtype: float\n";
|
||||||
|
|
||||||
|
static PyObject * Stroke_getLength2D( BPy_Stroke *self ) {
|
||||||
|
return PyFloat_FromDouble( self->s->getLength2D() );
|
||||||
|
}
|
||||||
|
|
||||||
static char Stroke_getMediumType___doc__[] =
|
static char Stroke_getMediumType___doc__[] =
|
||||||
".. method:: getMediumType()\n"
|
".. method:: getMediumType()\n"
|
||||||
"\n"
|
"\n"
|
||||||
@ -415,6 +438,8 @@ static PyMethodDef BPy_Stroke_methods[] = {
|
|||||||
{"Resample", ( PyCFunction ) Stroke_Resample, METH_VARARGS, Stroke_Resample___doc__},
|
{"Resample", ( PyCFunction ) Stroke_Resample, METH_VARARGS, Stroke_Resample___doc__},
|
||||||
{"RemoveVertex", ( PyCFunction ) Stroke_RemoveVertex, METH_VARARGS, Stroke_RemoveVertex___doc__},
|
{"RemoveVertex", ( PyCFunction ) Stroke_RemoveVertex, METH_VARARGS, Stroke_RemoveVertex___doc__},
|
||||||
{"InsertVertex", ( PyCFunction ) Stroke_InsertVertex, METH_VARARGS, Stroke_InsertVertex___doc__},
|
{"InsertVertex", ( PyCFunction ) Stroke_InsertVertex, METH_VARARGS, Stroke_InsertVertex___doc__},
|
||||||
|
{"UpdateLength", ( PyCFunction ) Stroke_UpdateLength, METH_NOARGS, Stroke_UpdateLength___doc__},
|
||||||
|
{"getLength2D", ( PyCFunction ) Stroke_getLength2D, METH_NOARGS, Stroke_getLength2D___doc__},
|
||||||
{"getMediumType", ( PyCFunction ) Stroke_getMediumType, METH_NOARGS, Stroke_getMediumType___doc__},
|
{"getMediumType", ( PyCFunction ) Stroke_getMediumType, METH_NOARGS, Stroke_getMediumType___doc__},
|
||||||
{"getTextureId", ( PyCFunction ) Stroke_getTextureId, METH_NOARGS, Stroke_getTextureId___doc__},
|
{"getTextureId", ( PyCFunction ) Stroke_getTextureId, METH_NOARGS, Stroke_getTextureId___doc__},
|
||||||
{"hasTips", ( PyCFunction ) Stroke_hasTips, METH_NOARGS, Stroke_hasTips___doc__},
|
{"hasTips", ( PyCFunction ) Stroke_hasTips, METH_NOARGS, Stroke_hasTips___doc__},
|
||||||
|
@ -586,6 +586,8 @@ namespace StrokeShaders {
|
|||||||
(v0)->setPoint(newFirst[0], newFirst[1]);
|
(v0)->setPoint(newFirst[0], newFirst[1]);
|
||||||
Vec2d newLast(last+_amount*dn);
|
Vec2d newLast(last+_amount*dn);
|
||||||
(vn)->setPoint(newLast[0], newLast[1]);
|
(vn)->setPoint(newLast[0], newLast[1]);
|
||||||
|
|
||||||
|
stroke.UpdateLength();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -611,6 +613,7 @@ namespace StrokeShaders {
|
|||||||
sv->setPoint(newPoint[0], newPoint[1]);
|
sv->setPoint(newPoint[0], newPoint[1]);
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
|
stroke.UpdateLength();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -726,6 +729,7 @@ namespace StrokeShaders {
|
|||||||
++it;
|
++it;
|
||||||
++n;
|
++n;
|
||||||
}
|
}
|
||||||
|
stroke.UpdateLength();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -844,6 +848,7 @@ namespace StrokeShaders {
|
|||||||
++p;
|
++p;
|
||||||
++n;
|
++n;
|
||||||
}
|
}
|
||||||
|
stroke.UpdateLength();
|
||||||
|
|
||||||
// Deal with extra vertices:
|
// Deal with extra vertices:
|
||||||
if(nExtraVertex == 0)
|
if(nExtraVertex == 0)
|
||||||
@ -931,6 +936,7 @@ namespace StrokeShaders {
|
|||||||
sv->setPoint(newPoint[0], newPoint[1]);
|
sv->setPoint(newPoint[0], newPoint[1]);
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
|
stroke.UpdateLength();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1038,6 +1044,7 @@ namespace StrokeShaders {
|
|||||||
// u.normalize();
|
// u.normalize();
|
||||||
// (*a)->setPoint((*a)->x()-u.x()*10, (*a)->y()-u.y()*10);
|
// (*a)->setPoint((*a)->x()-u.x()*10, (*a)->y()-u.y()*10);
|
||||||
}
|
}
|
||||||
|
stroke.UpdateLength();
|
||||||
|
|
||||||
// delete stuff
|
// delete stuff
|
||||||
for(cp=_results.begin(), cpend=_results.end();
|
for(cp=_results.begin(), cpend=_results.end();
|
||||||
@ -1076,6 +1083,7 @@ namespace StrokeShaders {
|
|||||||
{
|
{
|
||||||
v->setPoint(piece.A.x()+v->u()*u.x()+n.x()*offset, piece.A.y()+v->u()*u.y()+n.y()*offset);
|
v->setPoint(piece.A.x()+v->u()*u.x()+n.x()*offset, piece.A.y()+v->u()*u.y()+n.y()*offset);
|
||||||
}
|
}
|
||||||
|
stroke.UpdateLength();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -674,28 +674,7 @@ void Stroke::RemoveVertex(StrokeVertex *iVertex)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// recompute various values (length, curvilign abscissa)
|
UpdateLength();
|
||||||
float curvabsc = 0.f;
|
|
||||||
it=_Vertices.begin();
|
|
||||||
itend=_Vertices.end();
|
|
||||||
vertex_container::iterator previous=it;
|
|
||||||
for(;
|
|
||||||
(it!=itend);
|
|
||||||
++it)
|
|
||||||
{
|
|
||||||
if(it != previous)
|
|
||||||
curvabsc += ((*it)->point2d()-(*previous)->point2d()).norm();
|
|
||||||
(*it)->setCurvilinearAbscissa(curvabsc);
|
|
||||||
previous = it;
|
|
||||||
}
|
|
||||||
_Length = curvabsc;
|
|
||||||
it=_Vertices.begin();
|
|
||||||
for(;
|
|
||||||
(it!=itend);
|
|
||||||
++it)
|
|
||||||
{
|
|
||||||
(*it)->setStrokeLength(_Length);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Stroke::InsertVertex(StrokeVertex *iVertex, StrokeInternal::StrokeVertexIterator next)
|
void Stroke::InsertVertex(StrokeVertex *iVertex, StrokeInternal::StrokeVertexIterator next)
|
||||||
@ -704,10 +683,14 @@ void Stroke::InsertVertex(StrokeVertex *iVertex, StrokeInternal::StrokeVertexIte
|
|||||||
|
|
||||||
vertex_container::iterator itnext = next.getIt();
|
vertex_container::iterator itnext = next.getIt();
|
||||||
_Vertices.insert(itnext, iVertex);
|
_Vertices.insert(itnext, iVertex);
|
||||||
|
UpdateLength();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Stroke::UpdateLength()
|
||||||
|
{
|
||||||
// recompute various values (length, curvilign abscissa)
|
// recompute various values (length, curvilign abscissa)
|
||||||
float curvabsc = 0.f;
|
float curvabsc = 0.f;
|
||||||
it=_Vertices.begin();
|
vertex_container::iterator it=_Vertices.begin(), itend=_Vertices.end();
|
||||||
itend=_Vertices.end();
|
|
||||||
vertex_container::iterator previous=it;
|
vertex_container::iterator previous=it;
|
||||||
for(;
|
for(;
|
||||||
(it!=itend);
|
(it!=itend);
|
||||||
|
@ -466,6 +466,9 @@ public:
|
|||||||
*/
|
*/
|
||||||
void InsertVertex(StrokeVertex *iVertex, StrokeInternal::StrokeVertexIterator next);
|
void InsertVertex(StrokeVertex *iVertex, StrokeInternal::StrokeVertexIterator next);
|
||||||
|
|
||||||
|
/*! Updates the 2D length of the Stroke */
|
||||||
|
void UpdateLength();
|
||||||
|
|
||||||
/* Render method */
|
/* Render method */
|
||||||
void Render(const StrokeRenderer *iRenderer );
|
void Render(const StrokeRenderer *iRenderer );
|
||||||
void RenderBasic(const StrokeRenderer *iRenderer );
|
void RenderBasic(const StrokeRenderer *iRenderer );
|
||||||
|
Loading…
Reference in New Issue
Block a user