/blender/source/blender/freestyle/intern/stroke/StrokeRep.cpp
C++ | 782 lines | 625 code | 84 blank | 73 comment | 137 complexity | 9bb289e0167b35c6f1d82f529052c80b MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, AGPL-1.0
- /*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
- /** \file blender/freestyle/intern/stroke/StrokeRep.cpp
- * \ingroup freestyle
- * \brief Class to define the representation of a stroke (for display purpose)
- * \author Stephane Grabli
- * \date 05/03/2003
- */
- #include "Stroke.h"
- #include "StrokeAdvancedIterators.h"
- #include "StrokeIterators.h"
- #include "StrokeRenderer.h"
- #include "StrokeRep.h"
- using namespace std;
- //
- // STROKE VERTEX REP
- /////////////////////////////////////
- StrokeVertexRep::StrokeVertexRep(const StrokeVertexRep& iBrother)
- {
- _point2d = iBrother._point2d;
- _texCoord = iBrother._texCoord;
- _color = iBrother._color;
- _alpha = iBrother._alpha;
- }
- //
- // STRIP
- /////////////////////////////////////
- Strip::Strip(const vector<StrokeVertex*>& iStrokeVertices, bool hasTips, bool beginTip, bool endTip)
- {
- createStrip(iStrokeVertices);
- if (!hasTips)
- computeTexCoord (iStrokeVertices);
- else
- computeTexCoordWithTips (iStrokeVertices, beginTip, endTip);
- }
- Strip::Strip(const Strip& iBrother)
- {
- if (!iBrother._vertices.empty()) {
- for (vertex_container::const_iterator v = iBrother._vertices.begin(), vend = iBrother._vertices.end();
- v != vend;
- ++v)
- {
- _vertices.push_back(new StrokeVertexRep(**v));
- }
- }
- _averageThickness = iBrother._averageThickness;
- }
- Strip::~Strip()
- {
- if (!_vertices.empty()) {
- for (vertex_container::iterator v = _vertices.begin(), vend = _vertices.end(); v != vend; ++v) {
- delete (*v);
- }
- _vertices.clear();
- }
- }
- //////////////////////////
- // Strip creation
- //////////////////////////
- #define EPS_SINGULARITY_RENDERER 0.05
- #define ZERO 0.00001
- #define MAX_RATIO_LENGTH_SINGU 2
- #define HUGE_COORD 1.0e4
- static bool notValid (Vec2r p)
- {
- return (p[0] != p[0]) || (p[1] != p[1]) || (fabs(p[0]) > HUGE_COORD) || (fabs(p[1]) > HUGE_COORD) ||
- (p[0] < -HUGE_COORD) || (p[1] < -HUGE_COORD);
- }
- static real crossP(const Vec2r& A, const Vec2r& B)
- {
- return A[0] * B[1] - A[1] * B[0];
- }
- void Strip::createStrip (const vector<StrokeVertex*>& iStrokeVertices)
- {
- //computeParameterization();
- if (iStrokeVertices.size() < 2) {
- cerr << "Warning: strip has less than 2 vertices" << endl;
- return;
- }
- _vertices.reserve(2 * iStrokeVertices.size());
- if (!_vertices.empty()) {
- for (vertex_container::iterator v = _vertices.begin(), vend = _vertices.end(); v != vend; ++v) {
- delete (*v);
- }
- _vertices.clear();
- }
- _averageThickness = 0.0;
- vector<StrokeVertex *>::const_iterator v, vend, v2, vPrev;
- StrokeVertex *sv, *sv2, *svPrev;
- //special case of first vertex
- v = iStrokeVertices.begin();
- sv = *v;
- vPrev = v; //in case the stroke has only 2 vertices;
- ++v;
- sv2 = *v;
- Vec2r dir(sv2->getPoint() - sv->getPoint());
- Vec2r orthDir(-dir[1], dir[0]);
- if (orthDir.norm() > ZERO)
- orthDir.normalize();
- Vec2r stripDir(orthDir);
- // check whether the orientation was user defined
- if (sv->attribute().isAttributeAvailableVec2f("orientation")) {
- Vec2r userDir = sv->attribute().getAttributeVec2f("orientation");
- userDir.normalize();
- real dp = userDir * orthDir;
- if (dp < 0)
- userDir = userDir * (-1.0f);
- stripDir = userDir;
- }
- const float *thickness = sv->attribute().getThickness();
- _vertices.push_back(new StrokeVertexRep(sv->getPoint() + thickness[1] * stripDir));
- _vertices.push_back(new StrokeVertexRep(sv->getPoint() - thickness[0] * stripDir));
- #if 0
- Vec2r userDir = _stroke->getBeginningOrientation();
- if (userDir != Vec2r(0, 0)) {
- userDir.normalize();
- real o1 = (orthDir * userDir);
- real o2 = crossP(orthDir, userDir);
- real orientation = o1 * o2;
- if (orientation > 0) {
- // then the vertex to move is v0
- if (o1 > 0)
- _vertex[0] = _vertex[1] + userDir;
- else
- _vertex[0] = _vertex[1] - userDir;
- }
- if (orientation < 0) {
- // then we must move v1
- if (o1 < 0)
- _vertex[1] = _vertex[0] + userDir;
- else
- _vertex[1] = _vertex[0] - userDir;
- }
- }
- #endif
- int i = 2; // 2 because we have already processed the first vertex
- for (vend = iStrokeVertices.end(); v != vend; ++v) {
- v2 = v;
- ++v2;
- if (v2 == vend)
- break;
- sv = (*v);
- sv2 = (*v2);
- svPrev = (*vPrev);
- Vec2r p(sv->getPoint()), p2(sv2->getPoint()), pPrev(svPrev->getPoint());
- //direction and orthogonal vector to the next segment
- Vec2r dir(p2 - p);
- float dirNorm = dir.norm();
- dir.normalize();
- Vec2r orthDir(-dir[1], dir[0]);
- Vec2r stripDir = orthDir;
- if (sv->attribute().isAttributeAvailableVec2f("orientation")) {
- Vec2r userDir = sv->attribute().getAttributeVec2f("orientation");
- userDir.normalize();
- real dp = userDir * orthDir;
- if (dp < 0)
- userDir = userDir * (-1.0f);
- stripDir = userDir;
- }
- //direction and orthogonal vector to the previous segment
- Vec2r dirPrev(p - pPrev);
- float dirPrevNorm = dirPrev.norm();
- dirPrev.normalize();
- Vec2r orthDirPrev(-dirPrev[1], dirPrev[0]);
- Vec2r stripDirPrev = orthDirPrev;
- if (svPrev->attribute().isAttributeAvailableVec2f("orientation")) {
- Vec2r userDir = svPrev->attribute().getAttributeVec2f("orientation");
- userDir.normalize();
- real dp = userDir * orthDir;
- if (dp < 0)
- userDir = userDir * (-1.0f);
- stripDirPrev = userDir;
- }
- const float *thickness = sv->attribute().getThickness();
- _averageThickness += thickness[0] + thickness[1];
- Vec2r pInter;
- int interResult;
- interResult = GeomUtils::intersect2dLine2dLine(Vec2r(pPrev + thickness[1] * stripDirPrev),
- Vec2r(p + thickness[1] * stripDirPrev),
- Vec2r(p + thickness[1] * stripDir),
- Vec2r(p2 + thickness[1] * stripDir),
- pInter);
- if (interResult == GeomUtils::DO_INTERSECT)
- _vertices.push_back(new StrokeVertexRep(pInter));
- else
- _vertices.push_back(new StrokeVertexRep(p + thickness[1] * stripDir));
- ++i;
- interResult = GeomUtils::intersect2dLine2dLine(Vec2r(pPrev - thickness[0] * stripDirPrev),
- Vec2r(p - thickness[0] * stripDirPrev),
- Vec2r(p - thickness[0] * stripDir),
- Vec2r(p2 - thickness[0] * stripDir),
- pInter);
- if (interResult == GeomUtils::DO_INTERSECT)
- _vertices.push_back(new StrokeVertexRep(pInter));
- else
- _vertices.push_back(new StrokeVertexRep(p - thickness[0] * stripDir));
- ++i;
- // if the angle is obtuse, we simply average the directions to avoid the singularity
- stripDir = stripDir + stripDirPrev;
- if ((dirNorm < ZERO) || (dirPrevNorm < ZERO) || (stripDir.norm() < ZERO)) {
- stripDir[0] = 0;
- stripDir[1] = 0;
- }
- else {
- stripDir.normalize();
- }
- Vec2r vec_tmp(_vertices[i - 2]->point2d() - p);
- if ((vec_tmp.norm() > thickness[1] * MAX_RATIO_LENGTH_SINGU) || (dirNorm < ZERO) || (dirPrevNorm < ZERO) ||
- notValid(_vertices[i - 2]->point2d()) || (fabs(stripDir * dir) < EPS_SINGULARITY_RENDERER))
- {
- _vertices[i - 2]->setPoint2d(p + thickness[1] * stripDir);
- }
- vec_tmp = _vertices[i - 1]->point2d() - p;
- if ((vec_tmp.norm() > thickness[0] * MAX_RATIO_LENGTH_SINGU) || (dirNorm < ZERO) || (dirPrevNorm < ZERO) ||
- notValid(_vertices[i - 1]->point2d()) || (fabs(stripDir * dir) < EPS_SINGULARITY_RENDERER))
- {
- _vertices[i - 1]->setPoint2d(p - thickness[0] * stripDir);
- }
- vPrev = v;
- } // end of for
- //special case of last vertex
- sv = *v;
- sv2 = *vPrev;
- dir = Vec2r(sv->getPoint() - sv2->getPoint());
- orthDir = Vec2r(-dir[1], dir[0]);
- if (orthDir.norm() > ZERO)
- orthDir.normalize();
- Vec2r stripDirLast(orthDir);
- // check whether the orientation was user defined
- if (sv->attribute().isAttributeAvailableVec2f("orientation")) {
- Vec2r userDir = sv->attribute().getAttributeVec2f("orientation");
- userDir.normalize();
- real dp = userDir * orthDir;
- if (dp < 0)
- userDir = userDir * (-1.0f);
- stripDirLast = userDir;
- }
- const float *thicknessLast = sv->attribute().getThickness();
- _vertices.push_back(new StrokeVertexRep(sv->getPoint() + thicknessLast[1] * stripDirLast));
- ++i;
- _vertices.push_back(new StrokeVertexRep(sv->getPoint() - thicknessLast[0] * stripDirLast));
- ++i;
- #if 0
- int n = i - 1;
- // check whether the orientation of the extremity was user defined
- userDir = _stroke->getEndingOrientation();
- if (userDir != Vec2r(0, 0)) {
- userDir.normalize();
- real o1 = (orthDir * userDir);
- real o2 = crossP(orthDir, userDir);
- real orientation = o1 * o2;
- if (orientation > 0) {
- // then the vertex to move is vn
- if (o1 < 0)
- _vertex[n] = _vertex[n - 1] + userDir;
- else
- _vertex[n] = _vertex[n - 1] - userDir;
- }
- if (orientation < 0) {
- // then we must move vn-1
- if (o1 > 0)
- _vertex[n - 1] = _vertex[n] + userDir;
- else
- _vertex[n - 1] = _vertex[n] - userDir;
- }
- }
- #endif
- _averageThickness /= float(iStrokeVertices.size() - 2);
- //I did not use the first and last vertex for the average
- if (iStrokeVertices.size() < 3)
- _averageThickness = 0.5 * (thicknessLast[1] + thicknessLast[0] + thickness[0] + thickness[1]);
- if (i != 2 * (int)iStrokeVertices.size())
- cerr << "Warning: problem with stripe size\n";
- cleanUpSingularities (iStrokeVertices);
- }
- // CLEAN UP
- /////////////////////////
- void Strip::cleanUpSingularities (const vector<StrokeVertex*>& iStrokeVertices)
- {
- int k;
- int sizeStrip = _vertices.size();
- for (k = 0; k < sizeStrip; k++) {
- if (notValid(_vertices[k]->point2d())) {
- cerr << "Warning: strip vertex " << k << " non valid" << endl;
- return;
- }
- }
- //return;
- if (iStrokeVertices.size() < 2)
- return;
- int i = 0, j;
- vector<StrokeVertex *>::const_iterator v, vend, v2, vPrev;
- StrokeVertex *sv, *sv2; //soc unused - *svPrev;
- bool singu1 = false, singu2 = false;
- int timeSinceSingu1 = 0, timeSinceSingu2 = 0;
- //special case of first vertex
- v = iStrokeVertices.begin();
- for (vend = iStrokeVertices.end(); v != vend; v++) {
- v2 = v;
- ++v2;
- if (v2 == vend)
- break;
- sv = (*v);
- sv2 = (*v2);
- Vec2r p(sv->getPoint()), p2(sv2->getPoint());
- Vec2r dir(p2 - p);
- if (dir.norm() > ZERO)
- dir.normalize();
- Vec2r dir1, dir2;
- dir1 = _vertices[2 * i + 2]->point2d() - _vertices[2 * i]->point2d();
- dir2 = _vertices[2 * i + 3]->point2d() - _vertices[2 * i + 1]->point2d();
- if ((dir1 * dir) < -ZERO) {
- singu1 = true;
- timeSinceSingu1++;
- }
- else {
- if (singu1) {
- int toto = i - timeSinceSingu1;
- if (toto < 0)
- cerr << "Stephane dit \"Toto\"" << endl;
- //traverse all the vertices of the singularity and average them
- Vec2r avP(0.0, 0.0);
- for (j = i - timeSinceSingu1; j < i + 1; j++)
- avP = Vec2r(avP + _vertices[2 * j]->point2d());
- avP = Vec2r( 1.0 / float(timeSinceSingu1 + 1) * avP);
- for (j = i - timeSinceSingu1; j < i + 1; j++)
- _vertices[2 * j]->setPoint2d(avP);
- //_vertex[2 * j] = _vertex[2 * i];
- singu1 = false;
- timeSinceSingu1 = 0;
- }
- }
- if ((dir2 * dir) < -ZERO) {
- singu2 = true;
- timeSinceSingu2++;
- }
- else {
- if (singu2) {
- int toto = i - timeSinceSingu2;
- if (toto < 0)
- cerr << "Stephane dit \"Toto\"" << endl;
- //traverse all the vertices of the singularity and average them
- Vec2r avP(0.0, 0.0);
- for (j = i - timeSinceSingu2; j < i + 1; j++)
- avP = Vec2r(avP + _vertices[2 * j + 1]->point2d());
- avP = Vec2r(1.0 / float(timeSinceSingu2 + 1) * avP);
- for (j = i - timeSinceSingu2; j < i + 1; j++)
- _vertices[2 * j + 1]->setPoint2d(avP);
- //_vertex[2 * j + 1] = _vertex[2 * i + 1];
- singu2 = false;
- timeSinceSingu2 = 0;
- }
- }
- i++;
- }
- if (singu1) {
- //traverse all the vertices of the singularity and average them
- Vec2r avP(0.0, 0.0);
- for (j = i - timeSinceSingu1; j < i; j++)
- avP = Vec2r(avP + _vertices[2 * j]->point2d());
- avP = Vec2r(1.0 / float(timeSinceSingu1) * avP);
- for (j = i - timeSinceSingu1; j < i; j++)
- _vertices[2 * j]->setPoint2d(avP);
- }
- if (singu2) {
- //traverse all the vertices of the singularity and average them
- Vec2r avP(0.0, 0.0);
- for (j = i - timeSinceSingu2; j < i; j++)
- avP = Vec2r(avP + _vertices[2 * j + 1]->point2d());
- avP = Vec2r(1.0 / float(timeSinceSingu2) * avP);
- for (j = i - timeSinceSingu2; j < i; j++)
- _vertices[2 * j + 1]->setPoint2d(avP);
- }
- for (k = 0; k < sizeStrip; k++) {
- if (notValid(_vertices[k]->point2d())) {
- cerr << "Warning: strip vertex " << k << " non valid after cleanup" << endl;
- return;
- }
- }
- }
- // Texture coordinates
- ////////////////////////////////
- void Strip::computeTexCoord (const vector<StrokeVertex *>& iStrokeVertices)
- {
- vector<StrokeVertex *>::const_iterator v, vend;
- StrokeVertex *sv;
- int i = 0;
- for (v = iStrokeVertices.begin(), vend = iStrokeVertices.end(); v != vend; v++) {
- sv = (*v);
- _vertices[i]->setTexCoord(Vec2r((real)(sv->curvilinearAbscissa() / _averageThickness), 0));
- _vertices[i]->setColor(Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1],
- sv->attribute().getColor()[2]));
- _vertices[i]->setAlpha(sv->attribute().getAlpha());
- i++;
- _vertices[i]->setTexCoord(Vec2r((real)(sv->curvilinearAbscissa() / _averageThickness), 1));
- _vertices[i]->setColor(Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1],
- sv->attribute().getColor()[2]));
- _vertices[i]->setAlpha(sv->attribute().getAlpha());
- i++;
- #if 0
- cerr << "col=("<<sv->attribute().getColor()[0] << ", "
- << sv->attribute().getColor()[1] << ", " << sv->attribute().getColor()[2] << ")" << endl;
- #endif
- }
- }
- void Strip::computeTexCoordWithTips (const vector<StrokeVertex*>& iStrokeVertices, bool tipBegin, bool tipEnd)
- {
- //soc unused - unsigned int sizeStrip = _vertices.size() + 8; //for the transition between the tip and the body
- vector<StrokeVertex*>::const_iterator v, vend;
- StrokeVertex *sv = NULL;
- v = iStrokeVertices.begin();
- vend = iStrokeVertices.end();
- float l = (*v)->strokeLength() / _averageThickness;
- int tiles = int(l);
- float fact = (float(tiles) + 0.5) / l;
- //soc unused - float uTip2 = float(tiles) + 0.25;
- float u = 0;
- float uPrev = 0;
- int i = 0;
- float t;
- StrokeVertexRep *tvRep1, *tvRep2;
- #if 0
- cerr << "l=" << l << " tiles=" << tiles << " _averageThicnkess="
- << _averageThickness << " strokeLength=" << (*v)->strokeLength() << endl;
- #endif
- vector<StrokeVertexRep*>::iterator currentSV = _vertices.begin();
- StrokeVertexRep *svRep;
- if (tipBegin) {
- for (; v != vend; v++) {
- sv = (*v);
- svRep = *currentSV;
- u = sv->curvilinearAbscissa() / _averageThickness * fact;
- if (u > 0.25)
- break;
- svRep->setTexCoord(Vec2r((real)u, 0.5));
- svRep->setColor(Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1],
- sv->attribute().getColor()[2]));
- svRep->setAlpha(sv->attribute().getAlpha());
- i++;
- ++currentSV;
- svRep = *currentSV;
- svRep->setTexCoord(Vec2r((real)u, 1));
- svRep->setColor(Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1],
- sv->attribute().getColor()[2]));
- svRep->setAlpha(sv->attribute().getAlpha());
- i++;
- ++currentSV;
- uPrev = u;
- }
- //first transition vertex
- if (fabs(u - uPrev) > ZERO)
- t = (0.25 - uPrev) / (u - uPrev);
- else
- t = 0;
- #if 0
- if (!tiles)
- t = 0.5;
- #endif
- tvRep1 = new StrokeVertexRep(Vec2r((1 - t) * _vertices[i - 2]->point2d() + t * _vertices[i]->point2d()));
- tvRep1->setTexCoord(Vec2r(0.25, 0.5));
- tvRep1->setColor(Vec3r((1 - t) * _vertices[i - 2]->color() +
- t * Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1],
- sv->attribute().getColor()[2])));
- tvRep1->setAlpha((1 - t) * _vertices[i - 2]->alpha() + t * sv->attribute().getAlpha());
- i++;
- tvRep2 = new StrokeVertexRep(Vec2r((1 - t) * _vertices[i - 2]->point2d() + t *_vertices[i]->point2d()));
- tvRep2->setTexCoord(Vec2r(0.25, 1));
- tvRep2->setColor(Vec3r((1 - t) * _vertices[i - 2]->color() +
- t * Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1],
- sv->attribute().getColor()[2])));
- tvRep2->setAlpha((1 - t) * _vertices[i - 2]->alpha() + t * sv->attribute().getAlpha());
- i++;
- currentSV = _vertices.insert(currentSV, tvRep1);
- ++currentSV;
- currentSV = _vertices.insert(currentSV, tvRep2);
- ++currentSV;
- // copy the vertices with different texture coordinates
- tvRep1 = new StrokeVertexRep(_vertices[i - 2]->point2d());
- tvRep1->setTexCoord(Vec2r(0.25, 0));
- tvRep1->setColor(_vertices[i - 2]->color());
- tvRep1->setAlpha(_vertices[i - 2]->alpha());
- i++;
- tvRep2 = new StrokeVertexRep(_vertices[i - 2]->point2d());
- tvRep2->setTexCoord(Vec2r(0.25, 0.5));
- tvRep2->setColor(_vertices[i - 2]->color());
- tvRep2->setAlpha(_vertices[i - 2]->alpha());
- i++;
- currentSV = _vertices.insert(currentSV, tvRep1);
- ++currentSV;
- currentSV = _vertices.insert(currentSV, tvRep2);
- ++currentSV;
- }
- uPrev = 0;
- //body of the stroke
- for (; v != vend; v++) {
- sv = (*v);
- svRep = *currentSV;
- u = sv->curvilinearAbscissa() / _averageThickness * fact - 0.25;
- if (u > tiles)
- break;
- svRep->setTexCoord(Vec2r((real)u, 0));
- svRep->setColor(Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1],
- sv->attribute().getColor()[2]));
- svRep->setAlpha(sv->attribute().getAlpha());
- i++;
- ++currentSV;
- svRep = *currentSV;
- svRep->setTexCoord(Vec2r((real)u, 0.5));
- svRep->setColor(Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1],
- sv->attribute().getColor()[2]));
- svRep->setAlpha(sv->attribute().getAlpha());
- i++;
- ++currentSV;
- uPrev = u;
- }
- if (tipEnd) {
- //second transition vertex
- if ((fabs(u - uPrev) > ZERO))
- t = (float(tiles) - uPrev) / (u - uPrev);
- else
- t = 0;
- tvRep1 = new StrokeVertexRep(Vec2r((1 - t) * _vertices[i - 2]->point2d() + t * _vertices[i]->point2d()));
- tvRep1->setTexCoord(Vec2r((real)tiles, 0));
- tvRep1->setColor(Vec3r((1 - t) * _vertices[i - 2]->color() +
- t * Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1],
- sv->attribute().getColor()[2])));
- tvRep1->setAlpha((1 - t) * _vertices[i - 2]->alpha() + t * sv->attribute().getAlpha());
- i++;
- tvRep2 = new StrokeVertexRep(Vec2r((1 - t) * _vertices[i - 2]->point2d() + t * _vertices[i]->point2d()));
- tvRep2->setTexCoord(Vec2r((real)tiles, 0.5));
- tvRep2->setColor(Vec3r((1 - t) * _vertices[i - 2]->color() +
- t * Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1],
- sv->attribute().getColor()[2])));
- tvRep2->setAlpha((1 - t) * _vertices[i - 2]->alpha() + t * sv->attribute().getAlpha());
- i++;
- currentSV = _vertices.insert(currentSV, tvRep1);
- ++currentSV;
- currentSV = _vertices.insert(currentSV, tvRep2);
- ++currentSV;
- //copy the vertices with different texture coordinates
- tvRep1 = new StrokeVertexRep(_vertices[i - 2]->point2d());
- tvRep1->setTexCoord(Vec2r(0.75, 0.5));
- tvRep1->setColor(_vertices[i - 2]->color());
- tvRep1->setAlpha(_vertices[i - 2]->alpha());
- i++;
- tvRep2 = new StrokeVertexRep(_vertices[i - 2]->point2d());
- tvRep2->setTexCoord(Vec2r(0.75, 1));
- tvRep2->setColor(_vertices[i - 2]->color());
- tvRep2->setAlpha(_vertices[i - 2]->alpha());
- i++;
- currentSV = _vertices.insert(currentSV, tvRep1);
- ++currentSV;
- currentSV = _vertices.insert(currentSV, tvRep2);
- ++currentSV;
- //end tip
- for (; v != vend; v++) {
- sv = (*v);
- svRep = *currentSV;
- u = 0.75 + sv->curvilinearAbscissa() / _averageThickness * fact - float(tiles) - 0.25;
- svRep->setTexCoord(Vec2r((real)u, 0.5));
- svRep->setColor(Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1],
- sv->attribute().getColor()[2]));
- svRep->setAlpha(sv->attribute().getAlpha());
- i++;
- ++currentSV;
- svRep = *currentSV;
- svRep->setTexCoord(Vec2r((real)u, 1));
- svRep->setColor(Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1],
- sv->attribute().getColor()[2]));
- svRep->setAlpha(sv->attribute().getAlpha());
- i++;
- ++currentSV;
- }
- }
- #if 0
- cerr << "u=" << u << " i=" << i << "/" << _sizeStrip << endl;
- for (i = 0; i < _sizeStrip; i++)
- _alpha[i] = 1.0;
- for (i = 0; i < _sizeStrip; i++)
- cerr << "(" << _texCoord[i][0] << ", " << _texCoord[i][1] << ") ";
- cerr << endl;
- Vec2r vec_tmp;
- for (i = 0; i < _sizeStrip / 2; i++)
- vec_tmp = _vertex[2 * i] - _vertex[2 * i + 1];
- if (vec_tmp.norm() > 4 * _averageThickness)
- cerr << "Warning (from Fredo): There is a pb in the texture coordinates computation" << endl;
- #endif
- }
- //
- // StrokeRep
- /////////////////////////////////////
- StrokeRep::StrokeRep()
- {
- _stroke = 0;
- _strokeType = Stroke::OPAQUE_MEDIUM;
- TextureManager *ptm = TextureManager::getInstance();
- if (ptm)
- _textureId = ptm->getDefaultTextureId();
- #if 0
- _averageTextureAlpha = 0.5; //default value
- if (_strokeType == OIL_STROKE)
- _averageTextureAlpha = 0.75;
- if (_strokeType >= NO_BLEND_STROKE)
- _averageTextureAlpha = 1.0
- #endif
- }
- StrokeRep::StrokeRep(Stroke *iStroke)
- {
- _stroke = iStroke;
- _strokeType = iStroke->getMediumType();
- _textureId = iStroke->getTextureId();
- if (_textureId == 0) {
- TextureManager *ptm = TextureManager::getInstance();
- if (ptm)
- _textureId = ptm->getDefaultTextureId();
- }
- #if 0
- _averageTextureAlpha = 0.5; //default value
- if (_strokeType == OIL_STROKE)
- _averageTextureAlpha = 0.75;
- if (_strokeType >= NO_BLEND_STROKE)
- _averageTextureAlpha = 1.0;
- #endif
- create();
- }
- StrokeRep::StrokeRep(const StrokeRep& iBrother)
- {
- //soc unused - int i = 0;
- _stroke = iBrother._stroke;
- _strokeType = iBrother._strokeType;
- _textureId = iBrother._textureId;
- for (vector<Strip*>::const_iterator s = iBrother._strips.begin(), send = iBrother._strips.end();
- s != send;
- ++s)
- {
- _strips.push_back(new Strip(**s));
- }
- }
- StrokeRep::~StrokeRep()
- {
- if (!_strips.empty()) {
- for (vector<Strip*>::iterator s = _strips.begin(), send = _strips.end(); s != send; ++s) {
- delete (*s);
- }
- _strips.clear();
- }
- }
- void StrokeRep::create()
- {
- vector<StrokeVertex*> strip;
- StrokeInternal::StrokeVertexIterator v = _stroke->strokeVerticesBegin();
- StrokeInternal::StrokeVertexIterator vend = _stroke->strokeVerticesEnd();
- bool first = true;
- bool end = false;
- while (v != vend) {
- while ((v != vend) && (!(*v).attribute().isVisible())) {
- ++v;
- first = false;
- }
- while ((v != vend) && ((*v).attribute().isVisible())) {
- strip.push_back(&(*v));
- ++v;
- }
- if (v != vend) {
- // add the last vertex and create
- strip.push_back(&(*v));
- }
- else {
- end = true;
- }
- if ((!strip.empty()) && (strip.size() > 1)) {
- _strips.push_back(new Strip(strip, _stroke->hasTips(), first, end));
- strip.clear();
- }
- first = false;
- }
- }
- void StrokeRep::Render(const StrokeRenderer *iRenderer)
- {
- iRenderer->RenderStrokeRep(this);
- }