|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "tgl.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/strokegenerator.h"
|
|
Toshihiro Shimizu |
890ddd |
//#include "tofflinegl.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "tstroke.h"
|
|
Jeremy Bullock |
7f2044 |
#include "toonz/preferences.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
using namespace std;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void StrokeGenerator::clear() {
|
|
Shinya Kitaoka |
120a6e |
m_points.clear();
|
|
shun-iwasawa |
3c83df |
m_modifiedRegion = TRectD();
|
|
shun-iwasawa |
3c83df |
m_lastPointRect.empty();
|
|
shun-iwasawa |
3c83df |
m_lastModifiedRegion.empty();
|
|
Shinya Kitaoka |
120a6e |
m_paintedPointCount = 0;
|
|
Shinya Kitaoka |
120a6e |
m_p0 = m_p1 = TPointD();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
bool StrokeGenerator::isEmpty() const { return m_points.empty(); }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void StrokeGenerator::add(const TThickPoint &point, double pixelSize2) {
|
|
Shinya Kitaoka |
120a6e |
if (m_points.empty()) {
|
|
Shinya Kitaoka |
120a6e |
double x = point.x, y = point.y, d = point.thick + 3;
|
|
Shinya Kitaoka |
120a6e |
m_points.push_back(point);
|
|
Shinya Kitaoka |
120a6e |
TRectD rect(x - d, y - d, x + d, y + d);
|
|
Shinya Kitaoka |
120a6e |
m_modifiedRegion = rect;
|
|
shun-iwasawa |
3c83df |
m_lastPointRect = rect;
|
|
Shinya Kitaoka |
120a6e |
m_lastModifiedRegion = rect;
|
|
Shinya Kitaoka |
120a6e |
m_p0 = m_p1 = point;
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
TThickPoint lastPoint = m_points.back();
|
|
Shinya Kitaoka |
120a6e |
if (tdistance2(lastPoint, point) >= 4 * pixelSize2) {
|
|
Shinya Kitaoka |
120a6e |
m_points.push_back(point);
|
|
Shinya Kitaoka |
120a6e |
double d = std::max(point.thick, lastPoint.thick) + 3;
|
|
Shinya Kitaoka |
120a6e |
TRectD rect(TRectD(lastPoint, point).enlarge(d));
|
|
Shinya Kitaoka |
120a6e |
m_modifiedRegion += rect;
|
|
shun-iwasawa |
1fde39 |
m_lastModifiedRegion += rect;
|
|
shun-iwasawa |
1fde39 |
m_lastPointRect = rect;
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
m_points.back().thick = std::max(m_points.back().thick, point.thick);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void StrokeGenerator::filterPoints() {
|
|
Shinya Kitaoka |
120a6e |
if (m_points.size() < 10) return;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// filtra m_points iniziali: generalmente elevate variazioni di thickness
|
|
Shinya Kitaoka |
120a6e |
// si hanno tra m_points[0] (al massimo m_points[1]) e i successivi)
|
|
Shinya Kitaoka |
120a6e |
int size1 = m_points.size();
|
|
Shinya Kitaoka |
120a6e |
int kMin = 0;
|
|
Shinya Kitaoka |
120a6e |
int kMax = std::min(
|
|
Shinya Kitaoka |
120a6e |
4,
|
|
Shinya Kitaoka |
120a6e |
size1 -
|
|
Shinya Kitaoka |
120a6e |
2); // confronta 5 m_points iniziali con i successivi corrispondenti
|
|
Shinya Kitaoka |
120a6e |
int k = kMax;
|
|
Shinya Kitaoka |
120a6e |
for (k = kMax; k >= kMin; --k) {
|
|
Shinya Kitaoka |
120a6e |
TThickPoint currPoint = m_points[k];
|
|
Shinya Kitaoka |
120a6e |
TThickPoint nextPoint = m_points[k + 1];
|
|
Shinya Kitaoka |
120a6e |
double dist = tdistance(currPoint, nextPoint);
|
|
Shinya Kitaoka |
120a6e |
double deltaThick = fabs(currPoint.thick - nextPoint.thick);
|
|
Shinya Kitaoka |
120a6e |
if (deltaThick > 0.6 * dist) // deltaThick <= dist (condizione
|
|
Shinya Kitaoka |
120a6e |
// approssimata di non-autocontenimento per
|
|
Shinya Kitaoka |
120a6e |
// TTQ)
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
vector<tthickpoint>::iterator it1 = m_points.begin();</tthickpoint>
|
|
Shinya Kitaoka |
120a6e |
vector<tthickpoint>::iterator it2 = it1 + k + 1;</tthickpoint>
|
|
Shinya Kitaoka |
120a6e |
m_points.erase(it1, it2); // cancella da m_points[0] a m_points[k]
|
|
Shinya Kitaoka |
120a6e |
assert((int)m_points.size() == size1 - k - 1);
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
// filtra m_points finali: generalmente elevate variazioni di thickness
|
|
Shinya Kitaoka |
120a6e |
// si hanno tra m_points[size - 1] (al massimo m_points[size - 2]) e i
|
|
Shinya Kitaoka |
120a6e |
// predecessori)
|
|
Shinya Kitaoka |
120a6e |
int size2 = m_points.size();
|
|
Shinya Kitaoka |
120a6e |
kMax = size2 - 1;
|
|
Shinya Kitaoka |
120a6e |
kMin = std::max(
|
|
Shinya Kitaoka |
120a6e |
kMax - 4,
|
|
Shinya Kitaoka |
120a6e |
1); // confronta 5 m_points finali con i predecessori corrispondenti
|
|
Shinya Kitaoka |
120a6e |
k = kMin;
|
|
Shinya Kitaoka |
120a6e |
for (k = kMin; k <= kMax; ++k) {
|
|
Shinya Kitaoka |
120a6e |
TThickPoint currPoint = m_points[k];
|
|
Shinya Kitaoka |
120a6e |
TThickPoint prevPoint = m_points[k - 1];
|
|
Shinya Kitaoka |
120a6e |
double dist = tdistance(currPoint, prevPoint);
|
|
Shinya Kitaoka |
120a6e |
double deltaThick = fabs(currPoint.thick - prevPoint.thick);
|
|
Shinya Kitaoka |
120a6e |
if (deltaThick > 0.6 * dist) // deltaThick <= dist (condizione
|
|
Shinya Kitaoka |
120a6e |
// approssimata di non-autocontenimento per
|
|
Shinya Kitaoka |
120a6e |
// TTQ)
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
int kTmp = k;
|
|
Shinya Kitaoka |
120a6e |
while (k <= kMax) // cancella da m_points[k] a m_points[size2 - 1]
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
m_points.pop_back();
|
|
Shinya Kitaoka |
120a6e |
++k;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
assert((int)m_points.size() == size2 - (kMax - kTmp + 1));
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void StrokeGenerator::drawFragments(int first, int last) {
|
|
Shinya Kitaoka |
120a6e |
if (m_points.empty()) return;
|
|
Shinya Kitaoka |
120a6e |
int i = first;
|
|
Shinya Kitaoka |
120a6e |
if (last >= (int)m_points.size()) last = m_points.size() - 1;
|
|
Shinya Kitaoka |
120a6e |
TThickPoint a;
|
|
Shinya Kitaoka |
120a6e |
TThickPoint b;
|
|
Shinya Kitaoka |
120a6e |
TThickPoint c;
|
|
Shinya Kitaoka |
120a6e |
TPointD v;
|
|
Shinya Kitaoka |
120a6e |
|
|
Jeremy Bullock |
7f2044 |
// If drawing a straight line, a stroke can have only two points
|
|
Jeremy Bullock |
7f2044 |
if (m_points.size() == 2) {
|
|
Jeremy Bullock |
7f2044 |
a = m_points[0];
|
|
Jeremy Bullock |
7f2044 |
b = m_points[1];
|
|
Jeremy Bullock |
7f2044 |
if (Preferences::instance()->getShow0ThickLines()) {
|
|
Jeremy Bullock |
7f2044 |
if (a.thick == 0) a.thick = 0.1;
|
|
Jeremy Bullock |
7f2044 |
if (b.thick == 0) b.thick = 0.1;
|
|
Jeremy Bullock |
7f2044 |
}
|
|
Jeremy Bullock |
7f2044 |
// m_p0 = m_p1 = b;
|
|
Jeremy Bullock |
7f2044 |
v = a.thick * normalize(rotate90(b - a));
|
|
Jeremy Bullock |
7f2044 |
m_p0 = a + v;
|
|
Jeremy Bullock |
7f2044 |
m_p1 = a - v;
|
|
Jeremy Bullock |
7f2044 |
v = b.thick * normalize(rotate90(b - a));
|
|
Jeremy Bullock |
7f2044 |
TPointD p0 = b + v;
|
|
Jeremy Bullock |
7f2044 |
TPointD p1 = b - v;
|
|
Jeremy Bullock |
7f2044 |
glBegin(GL_POLYGON);
|
|
Jeremy Bullock |
7f2044 |
tglVertex(m_p0);
|
|
Jeremy Bullock |
7f2044 |
tglVertex(m_p1);
|
|
Jeremy Bullock |
7f2044 |
tglVertex(p1);
|
|
Jeremy Bullock |
7f2044 |
tglVertex(p0);
|
|
Jeremy Bullock |
7f2044 |
glEnd();
|
|
Jeremy Bullock |
7f2044 |
m_p0 = p0;
|
|
Jeremy Bullock |
7f2044 |
m_p1 = p1;
|
|
Jeremy Bullock |
7f2044 |
glBegin(GL_LINE_STRIP);
|
|
Jeremy Bullock |
7f2044 |
tglVertex(a);
|
|
Jeremy Bullock |
7f2044 |
tglVertex(b);
|
|
Jeremy Bullock |
7f2044 |
glEnd();
|
|
Jeremy Bullock |
7f2044 |
return;
|
|
Jeremy Bullock |
7f2044 |
}
|
|
Jeremy Bullock |
7f2044 |
|
|
Shinya Kitaoka |
120a6e |
while (i < last) {
|
|
Shinya Kitaoka |
120a6e |
a = m_points[i - 1];
|
|
Shinya Kitaoka |
120a6e |
b = m_points[i];
|
|
Shinya Kitaoka |
120a6e |
c = m_points[i + 1];
|
|
Jeremy Bullock |
7f2044 |
if (Preferences::instance()->getShow0ThickLines()) {
|
|
Jeremy Bullock |
7f2044 |
if (a.thick == 0) a.thick = 0.1;
|
|
Jeremy Bullock |
7f2044 |
if (b.thick == 0) b.thick = 0.1;
|
|
Jeremy Bullock |
7f2044 |
if (c.thick == 0) c.thick = 0.1;
|
|
Jeremy Bullock |
7f2044 |
}
|
|
shun-iwasawa |
1fde39 |
if (i - 1 == 0) {
|
|
shun-iwasawa |
1fde39 |
v = a.thick * normalize(rotate90(b - a));
|
|
shun-iwasawa |
1fde39 |
m_p0 = a + v;
|
|
shun-iwasawa |
1fde39 |
m_p1 = a - v;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
shun-iwasawa |
1fde39 |
v = b.thick * normalize(rotate90(c - a));
|
|
shun-iwasawa |
1fde39 |
TPointD p0 = b + v;
|
|
shun-iwasawa |
1fde39 |
TPointD p1 = b - v;
|
|
shun-iwasawa |
1fde39 |
glBegin(GL_POLYGON);
|
|
shun-iwasawa |
1fde39 |
tglVertex(m_p0);
|
|
shun-iwasawa |
1fde39 |
tglVertex(m_p1);
|
|
shun-iwasawa |
1fde39 |
tglVertex(p1);
|
|
shun-iwasawa |
1fde39 |
tglVertex(p0);
|
|
shun-iwasawa |
1fde39 |
glEnd();
|
|
shun-iwasawa |
1fde39 |
m_p0 = p0;
|
|
shun-iwasawa |
1fde39 |
m_p1 = p1;
|
|
shun-iwasawa |
1fde39 |
|
|
Shinya Kitaoka |
120a6e |
glBegin(GL_LINE_STRIP);
|
|
Shinya Kitaoka |
120a6e |
tglVertex(a);
|
|
Shinya Kitaoka |
120a6e |
tglVertex(b);
|
|
Shinya Kitaoka |
120a6e |
glEnd();
|
|
Shinya Kitaoka |
120a6e |
i++;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
shun-iwasawa |
1fde39 |
if (last < 2) return;
|
|
shun-iwasawa |
1fde39 |
v = m_points[last].thick *
|
|
shun-iwasawa |
1fde39 |
normalize(rotate90(m_points[last] - m_points[last - 1]));
|
|
shun-iwasawa |
1fde39 |
TPointD p0 = m_points[last] + v;
|
|
shun-iwasawa |
1fde39 |
TPointD p1 = m_points[last] - v;
|
|
shun-iwasawa |
1fde39 |
glBegin(GL_POLYGON);
|
|
shun-iwasawa |
1fde39 |
tglVertex(m_p0);
|
|
shun-iwasawa |
1fde39 |
tglVertex(m_p1);
|
|
shun-iwasawa |
1fde39 |
tglVertex(p1);
|
|
shun-iwasawa |
1fde39 |
tglVertex(p0);
|
|
shun-iwasawa |
1fde39 |
glEnd();
|
|
shun-iwasawa |
1fde39 |
glBegin(GL_LINE_STRIP);
|
|
shun-iwasawa |
1fde39 |
tglVertex(m_points[last - 1]);
|
|
shun-iwasawa |
1fde39 |
tglVertex(m_points[last]);
|
|
shun-iwasawa |
1fde39 |
glEnd();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void StrokeGenerator::drawLastFragments() {
|
|
Shinya Kitaoka |
120a6e |
if (m_points.empty()) return;
|
|
Shinya Kitaoka |
120a6e |
int n = m_points.size();
|
|
Shinya Kitaoka |
120a6e |
int i = m_paintedPointCount;
|
|
Shinya Kitaoka |
120a6e |
const double h = 0.01;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
if (i == 0) {
|
|
Shinya Kitaoka |
120a6e |
TThickPoint a = m_points[0];
|
|
Shinya Kitaoka |
120a6e |
if (a.thick >= h) tglDrawDisk(a, a.thick);
|
|
Shinya Kitaoka |
120a6e |
i++;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
drawFragments(i, n - 1);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
m_paintedPointCount = std::max(0, n - 2);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void StrokeGenerator::drawAllFragments() {
|
|
Shinya Kitaoka |
120a6e |
if (m_points.empty()) return;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int n = m_points.size();
|
|
Shinya Kitaoka |
120a6e |
int i = 0;
|
|
Shinya Kitaoka |
120a6e |
const double h = 0.01;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TThickPoint a = m_points[0];
|
|
Shinya Kitaoka |
120a6e |
if (a.thick >= h) tglDrawDisk(a, a.thick);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
drawFragments(1, n - 1);
|
|
Shinya Kitaoka |
120a6e |
/*
|
|
Shinya Kitaoka |
120a6e |
//last fragment
|
|
Shinya Kitaoka |
120a6e |
TPointD p0 = c+v;
|
|
Shinya Kitaoka |
120a6e |
TPointD p1 = c-v;
|
|
Shinya Kitaoka |
120a6e |
glBegin(GL_POLYGON);
|
|
Shinya Kitaoka |
120a6e |
tglVertex(m_p0);
|
|
Shinya Kitaoka |
120a6e |
tglVertex(m_p1);
|
|
Shinya Kitaoka |
120a6e |
tglVertex(p1);
|
|
Shinya Kitaoka |
120a6e |
tglVertex(p0);
|
|
Shinya Kitaoka |
120a6e |
glEnd();
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Shinya Kitaoka |
120a6e |
a = m_points.back();
|
|
Shinya Kitaoka |
120a6e |
if (a.thick >= h) tglDrawDisk(a, a.thick);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TRectD StrokeGenerator::getModifiedRegion() const { return m_modifiedRegion; }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Jeremy Bullock |
7f2044 |
void StrokeGenerator::removeMiddlePoints() {
|
|
Jeremy Bullock |
7f2044 |
int size = m_points.size();
|
|
Jeremy Bullock |
7f2044 |
if (size > 2) {
|
|
Jeremy Bullock |
7f2044 |
m_points.erase(m_points.begin() + 1, m_points.begin() + (size - 1));
|
|
Jeremy Bullock |
7f2044 |
}
|
|
Jeremy Bullock |
7f2044 |
}
|
|
Jeremy Bullock |
7f2044 |
|
|
Jeremy Bullock |
7f2044 |
//-------------------------------------------------------------------
|
|
Jeremy Bullock |
7f2044 |
|
|
shun-iwasawa |
1fde39 |
TRectD StrokeGenerator::getLastModifiedRegion() {
|
|
shun-iwasawa |
1fde39 |
TRectD ret = m_lastModifiedRegion;
|
|
shun-iwasawa |
1fde39 |
m_lastModifiedRegion = m_lastPointRect;
|
|
shun-iwasawa |
1fde39 |
return ret;
|
|
shun-iwasawa |
1fde39 |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Jeremy Bullock |
cd00fd |
TPointD StrokeGenerator::getFirstPoint() { return m_points[0]; }
|
|
Jeremy Bullock |
cd00fd |
|
|
Jeremy Bullock |
cd00fd |
//-------------------------------------------------------------------
|
|
Jeremy Bullock |
cd00fd |
|
|
Shinya Kitaoka |
120a6e |
TStroke *StrokeGenerator::makeStroke(double error, UINT onlyLastPoints) const {
|
|
Shinya Kitaoka |
120a6e |
if (onlyLastPoints == 0 || onlyLastPoints > m_points.size())
|
|
Shinya Kitaoka |
120a6e |
return TStroke::interpolate(m_points, error);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
vector<tthickpoint> lastPoints(onlyLastPoints);</tthickpoint>
|
|
Shinya Kitaoka |
120a6e |
vector<tthickpoint>::const_iterator first =</tthickpoint>
|
|
Shinya Kitaoka |
120a6e |
m_points.begin() + (m_points.size() - onlyLastPoints);
|
|
Shinya Kitaoka |
120a6e |
copy(first, m_points.end(), lastPoints.begin());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
return TStroke::interpolate(lastPoints, error);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|