PageRenderTime 77ms CodeModel.GetById 28ms RepoModel.GetById 1ms app.codeStats 0ms

/blender/source/blender/freestyle/intern/stroke/StrokeRep.cpp

https://bitbucket.org/DeanGiberson/blender
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
  1. /*
  2. * ***** BEGIN GPL LICENSE BLOCK *****
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License
  6. * as published by the Free Software Foundation; either version 2
  7. * of the License, or (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software Foundation,
  16. * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  17. *
  18. * ***** END GPL LICENSE BLOCK *****
  19. */
  20. /** \file blender/freestyle/intern/stroke/StrokeRep.cpp
  21. * \ingroup freestyle
  22. * \brief Class to define the representation of a stroke (for display purpose)
  23. * \author Stephane Grabli
  24. * \date 05/03/2003
  25. */
  26. #include "Stroke.h"
  27. #include "StrokeAdvancedIterators.h"
  28. #include "StrokeIterators.h"
  29. #include "StrokeRenderer.h"
  30. #include "StrokeRep.h"
  31. using namespace std;
  32. //
  33. // STROKE VERTEX REP
  34. /////////////////////////////////////
  35. StrokeVertexRep::StrokeVertexRep(const StrokeVertexRep& iBrother)
  36. {
  37. _point2d = iBrother._point2d;
  38. _texCoord = iBrother._texCoord;
  39. _color = iBrother._color;
  40. _alpha = iBrother._alpha;
  41. }
  42. //
  43. // STRIP
  44. /////////////////////////////////////
  45. Strip::Strip(const vector<StrokeVertex*>& iStrokeVertices, bool hasTips, bool beginTip, bool endTip)
  46. {
  47. createStrip(iStrokeVertices);
  48. if (!hasTips)
  49. computeTexCoord (iStrokeVertices);
  50. else
  51. computeTexCoordWithTips (iStrokeVertices, beginTip, endTip);
  52. }
  53. Strip::Strip(const Strip& iBrother)
  54. {
  55. if (!iBrother._vertices.empty()) {
  56. for (vertex_container::const_iterator v = iBrother._vertices.begin(), vend = iBrother._vertices.end();
  57. v != vend;
  58. ++v)
  59. {
  60. _vertices.push_back(new StrokeVertexRep(**v));
  61. }
  62. }
  63. _averageThickness = iBrother._averageThickness;
  64. }
  65. Strip::~Strip()
  66. {
  67. if (!_vertices.empty()) {
  68. for (vertex_container::iterator v = _vertices.begin(), vend = _vertices.end(); v != vend; ++v) {
  69. delete (*v);
  70. }
  71. _vertices.clear();
  72. }
  73. }
  74. //////////////////////////
  75. // Strip creation
  76. //////////////////////////
  77. #define EPS_SINGULARITY_RENDERER 0.05
  78. #define ZERO 0.00001
  79. #define MAX_RATIO_LENGTH_SINGU 2
  80. #define HUGE_COORD 1.0e4
  81. static bool notValid (Vec2r p)
  82. {
  83. return (p[0] != p[0]) || (p[1] != p[1]) || (fabs(p[0]) > HUGE_COORD) || (fabs(p[1]) > HUGE_COORD) ||
  84. (p[0] < -HUGE_COORD) || (p[1] < -HUGE_COORD);
  85. }
  86. static real crossP(const Vec2r& A, const Vec2r& B)
  87. {
  88. return A[0] * B[1] - A[1] * B[0];
  89. }
  90. void Strip::createStrip (const vector<StrokeVertex*>& iStrokeVertices)
  91. {
  92. //computeParameterization();
  93. if (iStrokeVertices.size() < 2) {
  94. cerr << "Warning: strip has less than 2 vertices" << endl;
  95. return;
  96. }
  97. _vertices.reserve(2 * iStrokeVertices.size());
  98. if (!_vertices.empty()) {
  99. for (vertex_container::iterator v = _vertices.begin(), vend = _vertices.end(); v != vend; ++v) {
  100. delete (*v);
  101. }
  102. _vertices.clear();
  103. }
  104. _averageThickness = 0.0;
  105. vector<StrokeVertex *>::const_iterator v, vend, v2, vPrev;
  106. StrokeVertex *sv, *sv2, *svPrev;
  107. //special case of first vertex
  108. v = iStrokeVertices.begin();
  109. sv = *v;
  110. vPrev = v; //in case the stroke has only 2 vertices;
  111. ++v;
  112. sv2 = *v;
  113. Vec2r dir(sv2->getPoint() - sv->getPoint());
  114. Vec2r orthDir(-dir[1], dir[0]);
  115. if (orthDir.norm() > ZERO)
  116. orthDir.normalize();
  117. Vec2r stripDir(orthDir);
  118. // check whether the orientation was user defined
  119. if (sv->attribute().isAttributeAvailableVec2f("orientation")) {
  120. Vec2r userDir = sv->attribute().getAttributeVec2f("orientation");
  121. userDir.normalize();
  122. real dp = userDir * orthDir;
  123. if (dp < 0)
  124. userDir = userDir * (-1.0f);
  125. stripDir = userDir;
  126. }
  127. const float *thickness = sv->attribute().getThickness();
  128. _vertices.push_back(new StrokeVertexRep(sv->getPoint() + thickness[1] * stripDir));
  129. _vertices.push_back(new StrokeVertexRep(sv->getPoint() - thickness[0] * stripDir));
  130. #if 0
  131. Vec2r userDir = _stroke->getBeginningOrientation();
  132. if (userDir != Vec2r(0, 0)) {
  133. userDir.normalize();
  134. real o1 = (orthDir * userDir);
  135. real o2 = crossP(orthDir, userDir);
  136. real orientation = o1 * o2;
  137. if (orientation > 0) {
  138. // then the vertex to move is v0
  139. if (o1 > 0)
  140. _vertex[0] = _vertex[1] + userDir;
  141. else
  142. _vertex[0] = _vertex[1] - userDir;
  143. }
  144. if (orientation < 0) {
  145. // then we must move v1
  146. if (o1 < 0)
  147. _vertex[1] = _vertex[0] + userDir;
  148. else
  149. _vertex[1] = _vertex[0] - userDir;
  150. }
  151. }
  152. #endif
  153. int i = 2; // 2 because we have already processed the first vertex
  154. for (vend = iStrokeVertices.end(); v != vend; ++v) {
  155. v2 = v;
  156. ++v2;
  157. if (v2 == vend)
  158. break;
  159. sv = (*v);
  160. sv2 = (*v2);
  161. svPrev = (*vPrev);
  162. Vec2r p(sv->getPoint()), p2(sv2->getPoint()), pPrev(svPrev->getPoint());
  163. //direction and orthogonal vector to the next segment
  164. Vec2r dir(p2 - p);
  165. float dirNorm = dir.norm();
  166. dir.normalize();
  167. Vec2r orthDir(-dir[1], dir[0]);
  168. Vec2r stripDir = orthDir;
  169. if (sv->attribute().isAttributeAvailableVec2f("orientation")) {
  170. Vec2r userDir = sv->attribute().getAttributeVec2f("orientation");
  171. userDir.normalize();
  172. real dp = userDir * orthDir;
  173. if (dp < 0)
  174. userDir = userDir * (-1.0f);
  175. stripDir = userDir;
  176. }
  177. //direction and orthogonal vector to the previous segment
  178. Vec2r dirPrev(p - pPrev);
  179. float dirPrevNorm = dirPrev.norm();
  180. dirPrev.normalize();
  181. Vec2r orthDirPrev(-dirPrev[1], dirPrev[0]);
  182. Vec2r stripDirPrev = orthDirPrev;
  183. if (svPrev->attribute().isAttributeAvailableVec2f("orientation")) {
  184. Vec2r userDir = svPrev->attribute().getAttributeVec2f("orientation");
  185. userDir.normalize();
  186. real dp = userDir * orthDir;
  187. if (dp < 0)
  188. userDir = userDir * (-1.0f);
  189. stripDirPrev = userDir;
  190. }
  191. const float *thickness = sv->attribute().getThickness();
  192. _averageThickness += thickness[0] + thickness[1];
  193. Vec2r pInter;
  194. int interResult;
  195. interResult = GeomUtils::intersect2dLine2dLine(Vec2r(pPrev + thickness[1] * stripDirPrev),
  196. Vec2r(p + thickness[1] * stripDirPrev),
  197. Vec2r(p + thickness[1] * stripDir),
  198. Vec2r(p2 + thickness[1] * stripDir),
  199. pInter);
  200. if (interResult == GeomUtils::DO_INTERSECT)
  201. _vertices.push_back(new StrokeVertexRep(pInter));
  202. else
  203. _vertices.push_back(new StrokeVertexRep(p + thickness[1] * stripDir));
  204. ++i;
  205. interResult = GeomUtils::intersect2dLine2dLine(Vec2r(pPrev - thickness[0] * stripDirPrev),
  206. Vec2r(p - thickness[0] * stripDirPrev),
  207. Vec2r(p - thickness[0] * stripDir),
  208. Vec2r(p2 - thickness[0] * stripDir),
  209. pInter);
  210. if (interResult == GeomUtils::DO_INTERSECT)
  211. _vertices.push_back(new StrokeVertexRep(pInter));
  212. else
  213. _vertices.push_back(new StrokeVertexRep(p - thickness[0] * stripDir));
  214. ++i;
  215. // if the angle is obtuse, we simply average the directions to avoid the singularity
  216. stripDir = stripDir + stripDirPrev;
  217. if ((dirNorm < ZERO) || (dirPrevNorm < ZERO) || (stripDir.norm() < ZERO)) {
  218. stripDir[0] = 0;
  219. stripDir[1] = 0;
  220. }
  221. else {
  222. stripDir.normalize();
  223. }
  224. Vec2r vec_tmp(_vertices[i - 2]->point2d() - p);
  225. if ((vec_tmp.norm() > thickness[1] * MAX_RATIO_LENGTH_SINGU) || (dirNorm < ZERO) || (dirPrevNorm < ZERO) ||
  226. notValid(_vertices[i - 2]->point2d()) || (fabs(stripDir * dir) < EPS_SINGULARITY_RENDERER))
  227. {
  228. _vertices[i - 2]->setPoint2d(p + thickness[1] * stripDir);
  229. }
  230. vec_tmp = _vertices[i - 1]->point2d() - p;
  231. if ((vec_tmp.norm() > thickness[0] * MAX_RATIO_LENGTH_SINGU) || (dirNorm < ZERO) || (dirPrevNorm < ZERO) ||
  232. notValid(_vertices[i - 1]->point2d()) || (fabs(stripDir * dir) < EPS_SINGULARITY_RENDERER))
  233. {
  234. _vertices[i - 1]->setPoint2d(p - thickness[0] * stripDir);
  235. }
  236. vPrev = v;
  237. } // end of for
  238. //special case of last vertex
  239. sv = *v;
  240. sv2 = *vPrev;
  241. dir = Vec2r(sv->getPoint() - sv2->getPoint());
  242. orthDir = Vec2r(-dir[1], dir[0]);
  243. if (orthDir.norm() > ZERO)
  244. orthDir.normalize();
  245. Vec2r stripDirLast(orthDir);
  246. // check whether the orientation was user defined
  247. if (sv->attribute().isAttributeAvailableVec2f("orientation")) {
  248. Vec2r userDir = sv->attribute().getAttributeVec2f("orientation");
  249. userDir.normalize();
  250. real dp = userDir * orthDir;
  251. if (dp < 0)
  252. userDir = userDir * (-1.0f);
  253. stripDirLast = userDir;
  254. }
  255. const float *thicknessLast = sv->attribute().getThickness();
  256. _vertices.push_back(new StrokeVertexRep(sv->getPoint() + thicknessLast[1] * stripDirLast));
  257. ++i;
  258. _vertices.push_back(new StrokeVertexRep(sv->getPoint() - thicknessLast[0] * stripDirLast));
  259. ++i;
  260. #if 0
  261. int n = i - 1;
  262. // check whether the orientation of the extremity was user defined
  263. userDir = _stroke->getEndingOrientation();
  264. if (userDir != Vec2r(0, 0)) {
  265. userDir.normalize();
  266. real o1 = (orthDir * userDir);
  267. real o2 = crossP(orthDir, userDir);
  268. real orientation = o1 * o2;
  269. if (orientation > 0) {
  270. // then the vertex to move is vn
  271. if (o1 < 0)
  272. _vertex[n] = _vertex[n - 1] + userDir;
  273. else
  274. _vertex[n] = _vertex[n - 1] - userDir;
  275. }
  276. if (orientation < 0) {
  277. // then we must move vn-1
  278. if (o1 > 0)
  279. _vertex[n - 1] = _vertex[n] + userDir;
  280. else
  281. _vertex[n - 1] = _vertex[n] - userDir;
  282. }
  283. }
  284. #endif
  285. _averageThickness /= float(iStrokeVertices.size() - 2);
  286. //I did not use the first and last vertex for the average
  287. if (iStrokeVertices.size() < 3)
  288. _averageThickness = 0.5 * (thicknessLast[1] + thicknessLast[0] + thickness[0] + thickness[1]);
  289. if (i != 2 * (int)iStrokeVertices.size())
  290. cerr << "Warning: problem with stripe size\n";
  291. cleanUpSingularities (iStrokeVertices);
  292. }
  293. // CLEAN UP
  294. /////////////////////////
  295. void Strip::cleanUpSingularities (const vector<StrokeVertex*>& iStrokeVertices)
  296. {
  297. int k;
  298. int sizeStrip = _vertices.size();
  299. for (k = 0; k < sizeStrip; k++) {
  300. if (notValid(_vertices[k]->point2d())) {
  301. cerr << "Warning: strip vertex " << k << " non valid" << endl;
  302. return;
  303. }
  304. }
  305. //return;
  306. if (iStrokeVertices.size() < 2)
  307. return;
  308. int i = 0, j;
  309. vector<StrokeVertex *>::const_iterator v, vend, v2, vPrev;
  310. StrokeVertex *sv, *sv2; //soc unused - *svPrev;
  311. bool singu1 = false, singu2 = false;
  312. int timeSinceSingu1 = 0, timeSinceSingu2 = 0;
  313. //special case of first vertex
  314. v = iStrokeVertices.begin();
  315. for (vend = iStrokeVertices.end(); v != vend; v++) {
  316. v2 = v;
  317. ++v2;
  318. if (v2 == vend)
  319. break;
  320. sv = (*v);
  321. sv2 = (*v2);
  322. Vec2r p(sv->getPoint()), p2(sv2->getPoint());
  323. Vec2r dir(p2 - p);
  324. if (dir.norm() > ZERO)
  325. dir.normalize();
  326. Vec2r dir1, dir2;
  327. dir1 = _vertices[2 * i + 2]->point2d() - _vertices[2 * i]->point2d();
  328. dir2 = _vertices[2 * i + 3]->point2d() - _vertices[2 * i + 1]->point2d();
  329. if ((dir1 * dir) < -ZERO) {
  330. singu1 = true;
  331. timeSinceSingu1++;
  332. }
  333. else {
  334. if (singu1) {
  335. int toto = i - timeSinceSingu1;
  336. if (toto < 0)
  337. cerr << "Stephane dit \"Toto\"" << endl;
  338. //traverse all the vertices of the singularity and average them
  339. Vec2r avP(0.0, 0.0);
  340. for (j = i - timeSinceSingu1; j < i + 1; j++)
  341. avP = Vec2r(avP + _vertices[2 * j]->point2d());
  342. avP = Vec2r( 1.0 / float(timeSinceSingu1 + 1) * avP);
  343. for (j = i - timeSinceSingu1; j < i + 1; j++)
  344. _vertices[2 * j]->setPoint2d(avP);
  345. //_vertex[2 * j] = _vertex[2 * i];
  346. singu1 = false;
  347. timeSinceSingu1 = 0;
  348. }
  349. }
  350. if ((dir2 * dir) < -ZERO) {
  351. singu2 = true;
  352. timeSinceSingu2++;
  353. }
  354. else {
  355. if (singu2) {
  356. int toto = i - timeSinceSingu2;
  357. if (toto < 0)
  358. cerr << "Stephane dit \"Toto\"" << endl;
  359. //traverse all the vertices of the singularity and average them
  360. Vec2r avP(0.0, 0.0);
  361. for (j = i - timeSinceSingu2; j < i + 1; j++)
  362. avP = Vec2r(avP + _vertices[2 * j + 1]->point2d());
  363. avP = Vec2r(1.0 / float(timeSinceSingu2 + 1) * avP);
  364. for (j = i - timeSinceSingu2; j < i + 1; j++)
  365. _vertices[2 * j + 1]->setPoint2d(avP);
  366. //_vertex[2 * j + 1] = _vertex[2 * i + 1];
  367. singu2 = false;
  368. timeSinceSingu2 = 0;
  369. }
  370. }
  371. i++;
  372. }
  373. if (singu1) {
  374. //traverse all the vertices of the singularity and average them
  375. Vec2r avP(0.0, 0.0);
  376. for (j = i - timeSinceSingu1; j < i; j++)
  377. avP = Vec2r(avP + _vertices[2 * j]->point2d());
  378. avP = Vec2r(1.0 / float(timeSinceSingu1) * avP);
  379. for (j = i - timeSinceSingu1; j < i; j++)
  380. _vertices[2 * j]->setPoint2d(avP);
  381. }
  382. if (singu2) {
  383. //traverse all the vertices of the singularity and average them
  384. Vec2r avP(0.0, 0.0);
  385. for (j = i - timeSinceSingu2; j < i; j++)
  386. avP = Vec2r(avP + _vertices[2 * j + 1]->point2d());
  387. avP = Vec2r(1.0 / float(timeSinceSingu2) * avP);
  388. for (j = i - timeSinceSingu2; j < i; j++)
  389. _vertices[2 * j + 1]->setPoint2d(avP);
  390. }
  391. for (k = 0; k < sizeStrip; k++) {
  392. if (notValid(_vertices[k]->point2d())) {
  393. cerr << "Warning: strip vertex " << k << " non valid after cleanup" << endl;
  394. return;
  395. }
  396. }
  397. }
  398. // Texture coordinates
  399. ////////////////////////////////
  400. void Strip::computeTexCoord (const vector<StrokeVertex *>& iStrokeVertices)
  401. {
  402. vector<StrokeVertex *>::const_iterator v, vend;
  403. StrokeVertex *sv;
  404. int i = 0;
  405. for (v = iStrokeVertices.begin(), vend = iStrokeVertices.end(); v != vend; v++) {
  406. sv = (*v);
  407. _vertices[i]->setTexCoord(Vec2r((real)(sv->curvilinearAbscissa() / _averageThickness), 0));
  408. _vertices[i]->setColor(Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1],
  409. sv->attribute().getColor()[2]));
  410. _vertices[i]->setAlpha(sv->attribute().getAlpha());
  411. i++;
  412. _vertices[i]->setTexCoord(Vec2r((real)(sv->curvilinearAbscissa() / _averageThickness), 1));
  413. _vertices[i]->setColor(Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1],
  414. sv->attribute().getColor()[2]));
  415. _vertices[i]->setAlpha(sv->attribute().getAlpha());
  416. i++;
  417. #if 0
  418. cerr << "col=("<<sv->attribute().getColor()[0] << ", "
  419. << sv->attribute().getColor()[1] << ", " << sv->attribute().getColor()[2] << ")" << endl;
  420. #endif
  421. }
  422. }
  423. void Strip::computeTexCoordWithTips (const vector<StrokeVertex*>& iStrokeVertices, bool tipBegin, bool tipEnd)
  424. {
  425. //soc unused - unsigned int sizeStrip = _vertices.size() + 8; //for the transition between the tip and the body
  426. vector<StrokeVertex*>::const_iterator v, vend;
  427. StrokeVertex *sv = NULL;
  428. v = iStrokeVertices.begin();
  429. vend = iStrokeVertices.end();
  430. float l = (*v)->strokeLength() / _averageThickness;
  431. int tiles = int(l);
  432. float fact = (float(tiles) + 0.5) / l;
  433. //soc unused - float uTip2 = float(tiles) + 0.25;
  434. float u = 0;
  435. float uPrev = 0;
  436. int i = 0;
  437. float t;
  438. StrokeVertexRep *tvRep1, *tvRep2;
  439. #if 0
  440. cerr << "l=" << l << " tiles=" << tiles << " _averageThicnkess="
  441. << _averageThickness << " strokeLength=" << (*v)->strokeLength() << endl;
  442. #endif
  443. vector<StrokeVertexRep*>::iterator currentSV = _vertices.begin();
  444. StrokeVertexRep *svRep;
  445. if (tipBegin) {
  446. for (; v != vend; v++) {
  447. sv = (*v);
  448. svRep = *currentSV;
  449. u = sv->curvilinearAbscissa() / _averageThickness * fact;
  450. if (u > 0.25)
  451. break;
  452. svRep->setTexCoord(Vec2r((real)u, 0.5));
  453. svRep->setColor(Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1],
  454. sv->attribute().getColor()[2]));
  455. svRep->setAlpha(sv->attribute().getAlpha());
  456. i++;
  457. ++currentSV;
  458. svRep = *currentSV;
  459. svRep->setTexCoord(Vec2r((real)u, 1));
  460. svRep->setColor(Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1],
  461. sv->attribute().getColor()[2]));
  462. svRep->setAlpha(sv->attribute().getAlpha());
  463. i++;
  464. ++currentSV;
  465. uPrev = u;
  466. }
  467. //first transition vertex
  468. if (fabs(u - uPrev) > ZERO)
  469. t = (0.25 - uPrev) / (u - uPrev);
  470. else
  471. t = 0;
  472. #if 0
  473. if (!tiles)
  474. t = 0.5;
  475. #endif
  476. tvRep1 = new StrokeVertexRep(Vec2r((1 - t) * _vertices[i - 2]->point2d() + t * _vertices[i]->point2d()));
  477. tvRep1->setTexCoord(Vec2r(0.25, 0.5));
  478. tvRep1->setColor(Vec3r((1 - t) * _vertices[i - 2]->color() +
  479. t * Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1],
  480. sv->attribute().getColor()[2])));
  481. tvRep1->setAlpha((1 - t) * _vertices[i - 2]->alpha() + t * sv->attribute().getAlpha());
  482. i++;
  483. tvRep2 = new StrokeVertexRep(Vec2r((1 - t) * _vertices[i - 2]->point2d() + t *_vertices[i]->point2d()));
  484. tvRep2->setTexCoord(Vec2r(0.25, 1));
  485. tvRep2->setColor(Vec3r((1 - t) * _vertices[i - 2]->color() +
  486. t * Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1],
  487. sv->attribute().getColor()[2])));
  488. tvRep2->setAlpha((1 - t) * _vertices[i - 2]->alpha() + t * sv->attribute().getAlpha());
  489. i++;
  490. currentSV = _vertices.insert(currentSV, tvRep1);
  491. ++currentSV;
  492. currentSV = _vertices.insert(currentSV, tvRep2);
  493. ++currentSV;
  494. // copy the vertices with different texture coordinates
  495. tvRep1 = new StrokeVertexRep(_vertices[i - 2]->point2d());
  496. tvRep1->setTexCoord(Vec2r(0.25, 0));
  497. tvRep1->setColor(_vertices[i - 2]->color());
  498. tvRep1->setAlpha(_vertices[i - 2]->alpha());
  499. i++;
  500. tvRep2 = new StrokeVertexRep(_vertices[i - 2]->point2d());
  501. tvRep2->setTexCoord(Vec2r(0.25, 0.5));
  502. tvRep2->setColor(_vertices[i - 2]->color());
  503. tvRep2->setAlpha(_vertices[i - 2]->alpha());
  504. i++;
  505. currentSV = _vertices.insert(currentSV, tvRep1);
  506. ++currentSV;
  507. currentSV = _vertices.insert(currentSV, tvRep2);
  508. ++currentSV;
  509. }
  510. uPrev = 0;
  511. //body of the stroke
  512. for (; v != vend; v++) {
  513. sv = (*v);
  514. svRep = *currentSV;
  515. u = sv->curvilinearAbscissa() / _averageThickness * fact - 0.25;
  516. if (u > tiles)
  517. break;
  518. svRep->setTexCoord(Vec2r((real)u, 0));
  519. svRep->setColor(Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1],
  520. sv->attribute().getColor()[2]));
  521. svRep->setAlpha(sv->attribute().getAlpha());
  522. i++;
  523. ++currentSV;
  524. svRep = *currentSV;
  525. svRep->setTexCoord(Vec2r((real)u, 0.5));
  526. svRep->setColor(Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1],
  527. sv->attribute().getColor()[2]));
  528. svRep->setAlpha(sv->attribute().getAlpha());
  529. i++;
  530. ++currentSV;
  531. uPrev = u;
  532. }
  533. if (tipEnd) {
  534. //second transition vertex
  535. if ((fabs(u - uPrev) > ZERO))
  536. t = (float(tiles) - uPrev) / (u - uPrev);
  537. else
  538. t = 0;
  539. tvRep1 = new StrokeVertexRep(Vec2r((1 - t) * _vertices[i - 2]->point2d() + t * _vertices[i]->point2d()));
  540. tvRep1->setTexCoord(Vec2r((real)tiles, 0));
  541. tvRep1->setColor(Vec3r((1 - t) * _vertices[i - 2]->color() +
  542. t * Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1],
  543. sv->attribute().getColor()[2])));
  544. tvRep1->setAlpha((1 - t) * _vertices[i - 2]->alpha() + t * sv->attribute().getAlpha());
  545. i++;
  546. tvRep2 = new StrokeVertexRep(Vec2r((1 - t) * _vertices[i - 2]->point2d() + t * _vertices[i]->point2d()));
  547. tvRep2->setTexCoord(Vec2r((real)tiles, 0.5));
  548. tvRep2->setColor(Vec3r((1 - t) * _vertices[i - 2]->color() +
  549. t * Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1],
  550. sv->attribute().getColor()[2])));
  551. tvRep2->setAlpha((1 - t) * _vertices[i - 2]->alpha() + t * sv->attribute().getAlpha());
  552. i++;
  553. currentSV = _vertices.insert(currentSV, tvRep1);
  554. ++currentSV;
  555. currentSV = _vertices.insert(currentSV, tvRep2);
  556. ++currentSV;
  557. //copy the vertices with different texture coordinates
  558. tvRep1 = new StrokeVertexRep(_vertices[i - 2]->point2d());
  559. tvRep1->setTexCoord(Vec2r(0.75, 0.5));
  560. tvRep1->setColor(_vertices[i - 2]->color());
  561. tvRep1->setAlpha(_vertices[i - 2]->alpha());
  562. i++;
  563. tvRep2 = new StrokeVertexRep(_vertices[i - 2]->point2d());
  564. tvRep2->setTexCoord(Vec2r(0.75, 1));
  565. tvRep2->setColor(_vertices[i - 2]->color());
  566. tvRep2->setAlpha(_vertices[i - 2]->alpha());
  567. i++;
  568. currentSV = _vertices.insert(currentSV, tvRep1);
  569. ++currentSV;
  570. currentSV = _vertices.insert(currentSV, tvRep2);
  571. ++currentSV;
  572. //end tip
  573. for (; v != vend; v++) {
  574. sv = (*v);
  575. svRep = *currentSV;
  576. u = 0.75 + sv->curvilinearAbscissa() / _averageThickness * fact - float(tiles) - 0.25;
  577. svRep->setTexCoord(Vec2r((real)u, 0.5));
  578. svRep->setColor(Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1],
  579. sv->attribute().getColor()[2]));
  580. svRep->setAlpha(sv->attribute().getAlpha());
  581. i++;
  582. ++currentSV;
  583. svRep = *currentSV;
  584. svRep->setTexCoord(Vec2r((real)u, 1));
  585. svRep->setColor(Vec3r(sv->attribute().getColor()[0], sv->attribute().getColor()[1],
  586. sv->attribute().getColor()[2]));
  587. svRep->setAlpha(sv->attribute().getAlpha());
  588. i++;
  589. ++currentSV;
  590. }
  591. }
  592. #if 0
  593. cerr << "u=" << u << " i=" << i << "/" << _sizeStrip << endl;
  594. for (i = 0; i < _sizeStrip; i++)
  595. _alpha[i] = 1.0;
  596. for (i = 0; i < _sizeStrip; i++)
  597. cerr << "(" << _texCoord[i][0] << ", " << _texCoord[i][1] << ") ";
  598. cerr << endl;
  599. Vec2r vec_tmp;
  600. for (i = 0; i < _sizeStrip / 2; i++)
  601. vec_tmp = _vertex[2 * i] - _vertex[2 * i + 1];
  602. if (vec_tmp.norm() > 4 * _averageThickness)
  603. cerr << "Warning (from Fredo): There is a pb in the texture coordinates computation" << endl;
  604. #endif
  605. }
  606. //
  607. // StrokeRep
  608. /////////////////////////////////////
  609. StrokeRep::StrokeRep()
  610. {
  611. _stroke = 0;
  612. _strokeType = Stroke::OPAQUE_MEDIUM;
  613. TextureManager *ptm = TextureManager::getInstance();
  614. if (ptm)
  615. _textureId = ptm->getDefaultTextureId();
  616. #if 0
  617. _averageTextureAlpha = 0.5; //default value
  618. if (_strokeType == OIL_STROKE)
  619. _averageTextureAlpha = 0.75;
  620. if (_strokeType >= NO_BLEND_STROKE)
  621. _averageTextureAlpha = 1.0
  622. #endif
  623. }
  624. StrokeRep::StrokeRep(Stroke *iStroke)
  625. {
  626. _stroke = iStroke;
  627. _strokeType = iStroke->getMediumType();
  628. _textureId = iStroke->getTextureId();
  629. if (_textureId == 0) {
  630. TextureManager *ptm = TextureManager::getInstance();
  631. if (ptm)
  632. _textureId = ptm->getDefaultTextureId();
  633. }
  634. #if 0
  635. _averageTextureAlpha = 0.5; //default value
  636. if (_strokeType == OIL_STROKE)
  637. _averageTextureAlpha = 0.75;
  638. if (_strokeType >= NO_BLEND_STROKE)
  639. _averageTextureAlpha = 1.0;
  640. #endif
  641. create();
  642. }
  643. StrokeRep::StrokeRep(const StrokeRep& iBrother)
  644. {
  645. //soc unused - int i = 0;
  646. _stroke = iBrother._stroke;
  647. _strokeType = iBrother._strokeType;
  648. _textureId = iBrother._textureId;
  649. for (vector<Strip*>::const_iterator s = iBrother._strips.begin(), send = iBrother._strips.end();
  650. s != send;
  651. ++s)
  652. {
  653. _strips.push_back(new Strip(**s));
  654. }
  655. }
  656. StrokeRep::~StrokeRep()
  657. {
  658. if (!_strips.empty()) {
  659. for (vector<Strip*>::iterator s = _strips.begin(), send = _strips.end(); s != send; ++s) {
  660. delete (*s);
  661. }
  662. _strips.clear();
  663. }
  664. }
  665. void StrokeRep::create()
  666. {
  667. vector<StrokeVertex*> strip;
  668. StrokeInternal::StrokeVertexIterator v = _stroke->strokeVerticesBegin();
  669. StrokeInternal::StrokeVertexIterator vend = _stroke->strokeVerticesEnd();
  670. bool first = true;
  671. bool end = false;
  672. while (v != vend) {
  673. while ((v != vend) && (!(*v).attribute().isVisible())) {
  674. ++v;
  675. first = false;
  676. }
  677. while ((v != vend) && ((*v).attribute().isVisible())) {
  678. strip.push_back(&(*v));
  679. ++v;
  680. }
  681. if (v != vend) {
  682. // add the last vertex and create
  683. strip.push_back(&(*v));
  684. }
  685. else {
  686. end = true;
  687. }
  688. if ((!strip.empty()) && (strip.size() > 1)) {
  689. _strips.push_back(new Strip(strip, _stroke->hasTips(), first, end));
  690. strip.clear();
  691. }
  692. first = false;
  693. }
  694. }
  695. void StrokeRep::Render(const StrokeRenderer *iRenderer)
  696. {
  697. iRenderer->RenderStrokeRep(this);
  698. }