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"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
using namespace std;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void StrokeGenerator::clear()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_points.clear();
Toshihiro Shimizu 890ddd
	m_modifiedRegion = TRectD();
Toshihiro Shimizu 890ddd
	m_paintedPointCount = 0;
Toshihiro Shimizu 890ddd
	m_p0 = m_p1 = TPointD();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool StrokeGenerator::isEmpty() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return m_points.empty();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void StrokeGenerator::add(const TThickPoint &point, double pixelSize2)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (m_points.empty()) {
Toshihiro Shimizu 890ddd
		double x = point.x, y = point.y, d = point.thick + 3;
Toshihiro Shimizu 890ddd
		m_points.push_back(point);
Toshihiro Shimizu 890ddd
		TRectD rect(x - d, y - d, x + d, y + d);
Toshihiro Shimizu 890ddd
		m_modifiedRegion = rect;
Toshihiro Shimizu 890ddd
		m_lastModifiedRegion = rect;
Toshihiro Shimizu 890ddd
		m_p0 = m_p1 = point;
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		TThickPoint lastPoint = m_points.back();
Toshihiro Shimizu 890ddd
		if (tdistance2(lastPoint, point) >= 4 * pixelSize2) {
Toshihiro Shimizu 890ddd
			m_points.push_back(point);
Toshihiro Shimizu 890ddd
			double d = tmax(point.thick, lastPoint.thick) + 3;
Toshihiro Shimizu 890ddd
			TRectD rect(TRectD(lastPoint, point).enlarge(d));
Toshihiro Shimizu 890ddd
			m_modifiedRegion += rect;
Toshihiro Shimizu 890ddd
			m_lastModifiedRegion += rect;
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			m_points.back().thick = tmax(m_points.back().thick, point.thick);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void StrokeGenerator::filterPoints()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (m_points.size() < 10)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//  filtra m_points iniziali: generalmente elevate variazioni di thickness
Toshihiro Shimizu 890ddd
	//  si hanno tra m_points[0] (al massimo m_points[1]) e i successivi)
Toshihiro Shimizu 890ddd
	int size1 = m_points.size();
Toshihiro Shimizu 890ddd
	int kMin = 0;
Toshihiro Shimizu 890ddd
	int kMax = tmin(4, size1 - 2); //  confronta 5 m_points iniziali con i successivi corrispondenti
Toshihiro Shimizu 890ddd
	int k = kMax;
Toshihiro Shimizu 890ddd
	for (k = kMax; k >= kMin; --k) {
Toshihiro Shimizu 890ddd
		TThickPoint currPoint = m_points[k];
Toshihiro Shimizu 890ddd
		TThickPoint nextPoint = m_points[k + 1];
Toshihiro Shimizu 890ddd
		double dist = tdistance(currPoint, nextPoint);
Toshihiro Shimizu 890ddd
		double deltaThick = fabs(currPoint.thick - nextPoint.thick);
Toshihiro Shimizu 890ddd
		if (deltaThick > 0.6 * dist) //  deltaThick <= dist (condizione approssimata di non-autocontenimento per TTQ)
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			vector<tthickpoint>::iterator it1 = m_points.begin();</tthickpoint>
Toshihiro Shimizu 890ddd
			vector<tthickpoint>::iterator it2 = it1 + k + 1;</tthickpoint>
Toshihiro Shimizu 890ddd
			m_points.erase(it1, it2); //  cancella da m_points[0] a m_points[k]
Toshihiro Shimizu 890ddd
			assert((int)m_points.size() == size1 - k - 1);
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	//  filtra m_points finali: generalmente elevate variazioni di thickness
Toshihiro Shimizu 890ddd
	//  si hanno tra m_points[size - 1] (al massimo m_points[size - 2]) e i predecessori)
Toshihiro Shimizu 890ddd
	int size2 = m_points.size();
Toshihiro Shimizu 890ddd
	kMax = size2 - 1;
Toshihiro Shimizu 890ddd
	kMin = tmax(kMax - 4, 1); //  confronta 5 m_points finali con i predecessori corrispondenti
Toshihiro Shimizu 890ddd
	k = kMin;
Toshihiro Shimizu 890ddd
	for (k = kMin; k <= kMax; ++k) {
Toshihiro Shimizu 890ddd
		TThickPoint currPoint = m_points[k];
Toshihiro Shimizu 890ddd
		TThickPoint prevPoint = m_points[k - 1];
Toshihiro Shimizu 890ddd
		double dist = tdistance(currPoint, prevPoint);
Toshihiro Shimizu 890ddd
		double deltaThick = fabs(currPoint.thick - prevPoint.thick);
Toshihiro Shimizu 890ddd
		if (deltaThick > 0.6 * dist) //  deltaThick <= dist (condizione approssimata di non-autocontenimento per TTQ)
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			int kTmp = k;
Toshihiro Shimizu 890ddd
			while (k <= kMax) //  cancella da m_points[k] a m_points[size2 - 1]
Toshihiro Shimizu 890ddd
			{
Toshihiro Shimizu 890ddd
				m_points.pop_back();
Toshihiro Shimizu 890ddd
				++k;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			assert((int)m_points.size() == size2 - (kMax - kTmp + 1));
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void StrokeGenerator::drawFragments(int first, int last)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (m_points.empty())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	int i = first;
Toshihiro Shimizu 890ddd
	if (last >= (int)m_points.size())
Toshihiro Shimizu 890ddd
		last = m_points.size() - 1;
Toshihiro Shimizu 890ddd
	const double h = 0.01;
Toshihiro Shimizu 890ddd
	TThickPoint a;
Toshihiro Shimizu 890ddd
	TThickPoint b;
Toshihiro Shimizu 890ddd
	TThickPoint c;
Toshihiro Shimizu 890ddd
	TPointD v;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	while (i < last) {
Toshihiro Shimizu 890ddd
		a = m_points[i - 1];
Toshihiro Shimizu 890ddd
		b = m_points[i];
Toshihiro Shimizu 890ddd
		c = m_points[i + 1];
Toshihiro Shimizu 890ddd
		if (a.thick >= h && b.thick >= h && tdistance2(b, a) >= h && tdistance2(a, c) >= h) {
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (i - 1 == 0) {
Toshihiro Shimizu 890ddd
				assert(tdistance(b, a) > h);
Toshihiro Shimizu 890ddd
				v = a.thick * normalize(rotate90(b - a));
Toshihiro Shimizu 890ddd
				m_p0 = a + v;
Toshihiro Shimizu 890ddd
				m_p1 = a - v;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			assert(tdistance(c, a) > h);
Toshihiro Shimizu 890ddd
			v = b.thick * normalize(rotate90(c - a));
Toshihiro Shimizu 890ddd
			TPointD p0 = b + v;
Toshihiro Shimizu 890ddd
			TPointD p1 = b - v;
Toshihiro Shimizu 890ddd
			glBegin(GL_POLYGON);
Toshihiro Shimizu 890ddd
			tglVertex(m_p0);
Toshihiro Shimizu 890ddd
			tglVertex(m_p1);
Toshihiro Shimizu 890ddd
			tglVertex(p1);
Toshihiro Shimizu 890ddd
			tglVertex(p0);
Toshihiro Shimizu 890ddd
			glEnd();
Toshihiro Shimizu 890ddd
			m_p0 = p0;
Toshihiro Shimizu 890ddd
			m_p1 = p1;
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			m_p0 = m_p1 = b;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		glBegin(GL_LINE_STRIP);
Toshihiro Shimizu 890ddd
		tglVertex(a);
Toshihiro Shimizu 890ddd
		tglVertex(b);
Toshihiro Shimizu 890ddd
		glEnd();
Toshihiro Shimizu 890ddd
		i++;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void StrokeGenerator::drawLastFragments()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (m_points.empty())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	int n = m_points.size();
Toshihiro Shimizu 890ddd
	int i = m_paintedPointCount;
Toshihiro Shimizu 890ddd
	const double h = 0.01;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (i == 0) {
Toshihiro Shimizu 890ddd
		TThickPoint a = m_points[0];
Toshihiro Shimizu 890ddd
		if (a.thick >= h)
Toshihiro Shimizu 890ddd
			tglDrawDisk(a, a.thick);
Toshihiro Shimizu 890ddd
		i++;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	drawFragments(i, n - 1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_paintedPointCount = tmax(0, n - 2);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void StrokeGenerator::drawAllFragments()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (m_points.empty())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int n = m_points.size();
Toshihiro Shimizu 890ddd
	int i = 0;
Toshihiro Shimizu 890ddd
	const double h = 0.01;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TThickPoint a = m_points[0];
Toshihiro Shimizu 890ddd
	if (a.thick >= h)
Toshihiro Shimizu 890ddd
		tglDrawDisk(a, a.thick);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	drawFragments(1, n - 1);
Toshihiro Shimizu 890ddd
	/*
Toshihiro Shimizu 890ddd
  //last fragment
Toshihiro Shimizu 890ddd
  TPointD p0 = c+v;
Toshihiro Shimizu 890ddd
  TPointD p1 = c-v;
Toshihiro Shimizu 890ddd
  glBegin(GL_POLYGON);
Toshihiro Shimizu 890ddd
  tglVertex(m_p0);
Toshihiro Shimizu 890ddd
  tglVertex(m_p1);
Toshihiro Shimizu 890ddd
  tglVertex(p1);
Toshihiro Shimizu 890ddd
  tglVertex(p0);
Toshihiro Shimizu 890ddd
  glEnd(); 
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
	a = m_points.back();
Toshihiro Shimizu 890ddd
	if (a.thick >= h)
Toshihiro Shimizu 890ddd
		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
Toshihiro Shimizu 890ddd
TRectD StrokeGenerator::getLastModifiedRegion()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TRectD lastModifiedRegion = m_lastModifiedRegion;
Toshihiro Shimizu 890ddd
	m_lastModifiedRegion.empty();
Toshihiro Shimizu 890ddd
	return lastModifiedRegion;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TStroke *StrokeGenerator::makeStroke(double error, UINT onlyLastPoints) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (onlyLastPoints == 0 || onlyLastPoints > m_points.size())
Toshihiro Shimizu 890ddd
		return TStroke::interpolate(m_points, error);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	vector<tthickpoint> lastPoints(onlyLastPoints);</tthickpoint>
Toshihiro Shimizu 890ddd
	vector<tthickpoint>::const_iterator first = m_points.begin() + (m_points.size() - onlyLastPoints);</tthickpoint>
Toshihiro Shimizu 890ddd
	copy(first, m_points.end(), lastPoints.begin());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return TStroke::interpolate(lastPoints, error);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------