1 // Copyright (C) 2012-2019 The VPaint Developers.
2 // See the COPYRIGHT file at the top-level directory of this distribution
3 // and at https://github.com/dalboris/vpaint/blob/master/COPYRIGHT
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 
17 #include "../XmlStreamReader.h"
18 #include "../XmlStreamWriter.h"
19 #include <QTextStream>
20 #include <QtDebug>
21 #include <QMessageBox>
22 #include <array>
23 #include <vector>
24 
25 #include "../SaveAndLoad.h"
26 #include "../Random.h"
27 
28 #include "EdgeGeometry.h"
29 
30 #include "KeyVertex.h"
31 #include "KeyEdge.h"
32 #include "KeyFace.h"
33 #include "../DevSettings.h"
34 #include "../Global.h"
35 
36 #include "../OpenGL.h"
37 
38 #if defined(__APPLE__) && defined(__MACH__)
39 #  include <OpenGL/glu.h>
40 #else
41 #  include <GL/glu.h>
42 #endif
43 
44 // ------- Unnamed namespace for non-friend non-member helper functions -------
45 
46 namespace
47 {
48 
49 using namespace VectorAnimationComplex;
50 
51 // Active tesselator
52 GLUtesselator * tobj = 0;
53 
54 // Offline tesselator: outputs the triangulation as offlineTessTriangles
55 GLUtesselator * tobjOffline = 0;
56 Triangles offlineTessTriangles;
57 GLenum offlineTessWhich;
58 int offlineTessIter;
59 double offlineTessAX, offlineTessAY;
60 double offlineTessBX, offlineTessBY;
61 double offlineTessCX, offlineTessCY;
62 
63 #ifdef _WIN32
64 #define CALLBACK __stdcall
65 #else
66 #define CALLBACK
67 #endif
68 
offlineTessBegin(GLenum which)69 void CALLBACK offlineTessBegin(GLenum which)
70 {
71     offlineTessWhich = which;
72     offlineTessIter = 0;
73 }
74 
offlineTessEnd(void)75 void CALLBACK offlineTessEnd(void)
76 {
77 }
78 
offlineTessError(GLenum errorCode)79 void CALLBACK offlineTessError(GLenum errorCode)
80 {
81    const GLubyte *estring;
82    estring = gluErrorString(errorCode);
83 
84    qDebug() << "Tessellation Error:" << estring;
85 }
86 
offlineTessVertex(GLvoid * vertex)87 void CALLBACK offlineTessVertex(GLvoid *vertex)
88 {
89     const GLdouble *pointer = (GLdouble *) vertex;
90 
91     if(offlineTessWhich == GL_TRIANGLES)
92     {
93         if(offlineTessIter == 0)
94         {
95             offlineTessAX = pointer[0];
96             offlineTessAY = pointer[1];
97             offlineTessIter = 1;
98         }
99         else if(offlineTessIter == 1)
100         {
101             offlineTessBX = pointer[0];
102             offlineTessBY = pointer[1];
103             offlineTessIter = 2;
104         }
105         else
106         {
107             offlineTessCX = pointer[0];
108             offlineTessCY = pointer[1];
109             offlineTessIter = 0;
110 
111             offlineTessTriangles.append(offlineTessAX, offlineTessAY,
112                                         offlineTessBX, offlineTessBY,
113                                         offlineTessCX, offlineTessCY);
114         }
115     }
116     else if(offlineTessWhich == GL_TRIANGLE_FAN)
117     {
118         if(offlineTessIter == 0)
119         {
120             offlineTessAX = pointer[0];
121             offlineTessAY = pointer[1];
122             offlineTessIter = 1;
123         }
124         else if(offlineTessIter == 1)
125         {
126             offlineTessBX = pointer[0];
127             offlineTessBY = pointer[1];
128             offlineTessIter = 2;
129         }
130         else
131         {
132             offlineTessCX = pointer[0];
133             offlineTessCY = pointer[1];
134 
135             offlineTessTriangles.append(offlineTessAX, offlineTessAY,
136                                         offlineTessBX, offlineTessBY,
137                                         offlineTessCX, offlineTessCY);
138 
139             offlineTessBX = offlineTessCX;
140             offlineTessBY = offlineTessCY;
141         }
142     }
143     else if(offlineTessWhich == GL_TRIANGLE_STRIP)
144     {
145         if(offlineTessIter == 0)
146         {
147             offlineTessAX = pointer[0];
148             offlineTessAY = pointer[1];
149             offlineTessIter = 1;
150         }
151         else if(offlineTessIter == 1)
152         {
153             offlineTessBX = pointer[0];
154             offlineTessBY = pointer[1];
155             offlineTessIter = 2;
156         }
157         else if(offlineTessIter == 2)
158         {
159             offlineTessCX = pointer[0];
160             offlineTessCY = pointer[1];
161 
162             offlineTessTriangles.append(offlineTessAX, offlineTessAY,
163                                         offlineTessBX, offlineTessBY,
164                                         offlineTessCX, offlineTessCY);
165 
166             offlineTessAX = offlineTessCX;
167             offlineTessAY = offlineTessCY;
168             offlineTessIter = 3;
169         }
170         else
171         {
172             offlineTessCX = pointer[0];
173             offlineTessCY = pointer[1];
174 
175             offlineTessTriangles.append(offlineTessAX, offlineTessAY,
176                                         offlineTessBX, offlineTessBY,
177                                         offlineTessCX, offlineTessCY);
178 
179             offlineTessBX = offlineTessCX;
180             offlineTessBY = offlineTessCY;
181             offlineTessIter = 2;
182         }
183     }
184     else if(offlineTessWhich == GL_LINE_LOOP)
185     {
186     }
187 }
188 
offlineTessCombine(GLdouble coords[3],GLdouble * [4],GLfloat[4],GLdouble ** dataOut)189 void CALLBACK offlineTessCombine(GLdouble coords[3],
190                         GLdouble * /*vertex_data*/ [4],
191                         GLfloat /*weight*/ [4], GLdouble **dataOut )
192 {
193    GLdouble * vertex = (GLdouble *) malloc(6 * sizeof(GLdouble));
194    vertex[0] = coords[0];
195    vertex[1] = coords[1];
196    vertex[2] = coords[2];
197 
198    *dataOut = vertex;
199 }
200 
201 typedef std::vector< std::vector< std::array<GLdouble, 3> > > PolygonData;
202 
createPolygonData(const QList<Cycle> & cycles)203 PolygonData createPolygonData(const QList<Cycle> & cycles)
204 {
205     PolygonData vertices;
206     for(int k=0; k<cycles.size(); ++k)      // for each cycle
207     {
208         vertices << std::vector< std::array<GLdouble, 3> >(); // create a contour data
209 
210         for(int i=0; i<cycles[k].size(); ++i) // for each edge in the cycle
211         {
212             QList<Eigen::Vector2d> & sampling = cycles[k][i].edge->geometry()->sampling();
213             if(cycles[k][i].side)
214             {
215                 int last = sampling.size()-1;
216                 if(i+1<cycles[k].size())
217                 {
218                     // if there is a following edge, then don't insert last vertex
219                     // otherwise it will be duplicated
220                     last--;
221                 }
222                 for(int j=0; j<=last; ++j)
223                 {
224                     std::array<GLdouble, 3> a = {sampling[j][0], sampling[j][1], 0};
225                     vertices.back().emplace_back(a);
226                 }
227             }
228             else
229             {
230                 int first = 0;
231                 if(i+1<cycles[k].size())
232                 {
233                     // if there is a following edge, then don't insert last vertex
234                     // otherwise it will be duplicated
235                     first++;
236                 }
237                 for(int j=sampling.size()-1; j>=first; --j)
238                 {
239                     std::array<GLdouble, 3> a = {sampling[j][0], sampling[j][1], 0};
240                     vertices.back().emplace_back(a);
241                 }
242             }
243         }
244     }
245 
246     return vertices;
247 }
248 
computeTrianglesFromCycles(const QList<Cycle> & cycles,Triangles & triangles)249 void computeTrianglesFromCycles(const QList<Cycle> & cycles, Triangles & triangles)
250 {
251 
252     // Creating polygon data for GLU tesselator
253     PolygonData vertices = createPolygonData(cycles);
254 
255     // Creating the GLU tesselation object
256     if(!tobjOffline)
257     {
258         tobjOffline = gluNewTess();
259     }
260     if(tobj != tobjOffline)
261     {
262         tobj = tobjOffline;
263 
264         gluTessCallback(tobj, GLU_TESS_VERTEX,
265                         (GLvoid (CALLBACK*) ()) &offlineTessVertex);
266         gluTessCallback(tobj, GLU_TESS_BEGIN,
267                         (GLvoid (CALLBACK*) ()) &offlineTessBegin);
268         gluTessCallback(tobj, GLU_TESS_END,
269                         (GLvoid (CALLBACK*) ()) &offlineTessEnd);
270         gluTessCallback(tobj, GLU_TESS_ERROR,
271                         (GLvoid (CALLBACK*) ()) &offlineTessError);
272         gluTessCallback(tobj, GLU_TESS_COMBINE,
273                         (GLvoid (CALLBACK*) ()) &offlineTessCombine);
274     }
275 
276     // Using the tesselation object
277     gluTessProperty(tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);
278 
279     // Specifying data
280     offlineTessTriangles.clear();
281     gluTessBeginPolygon(tobj, NULL);
282     {
283         for(auto & vec: vertices) // for each cycle
284         {
285             gluTessBeginContour(tobj); // draw a contour
286             {
287                 for(auto & v: vec) // for each vertex in cycle
288                 {
289                     // safeguard against NaN and other oddities
290                     const double MAX_VALUE = 10000;
291                     const double MIN_VALUE = -10000;
292                     if( v[0] > MIN_VALUE &&
293                         v[0] < MAX_VALUE &&
294                         v[1] > MIN_VALUE &&
295                         v[1] < MAX_VALUE &&
296                         v[2] > MIN_VALUE &&
297                         v[2] < MAX_VALUE )
298                     {
299                         gluTessVertex(tobj, v.data(), v.data()); // send vertex
300                     }
301                     else
302                     {
303                         qDebug() << "ignored vertex" << v[0]  << v[1]  << v[2] << "for tesselation";
304                     }
305                 }
306             }
307             gluTessEndContour(tobj);
308         }
309     }
310     gluTessEndPolygon(tobj);
311 
312     // Tranfer to member data
313     triangles = offlineTessTriangles;
314 }
315 
316 }
317 
318 
319 namespace VectorAnimationComplex
320 {
321 
322 // ------------------------------- Key Face -------------------------------
323 
KeyFace(VAC * vac,const Time & t)324 KeyFace::KeyFace(VAC * vac, const Time & t) :
325     Cell(vac),
326     KeyCell(vac, t),
327     FaceCell(vac)
328 {
329     initColor_();
330 }
331 
KeyFace(VAC * vac,const Cycle & cycle)332 KeyFace::KeyFace(VAC * vac, const Cycle & cycle) :
333     Cell(vac),
334     KeyCell(vac, cycle.time()),
335     FaceCell(vac)
336 {
337     addCycle(cycle);
338     initColor_();
339 }
340 
KeyFace(VAC * vac,const QList<Cycle> & cycles)341 KeyFace::KeyFace(VAC * vac, const QList<Cycle> & cycles) :
342     Cell(vac),
343     KeyCell(vac, cycles[0].time()),
344     FaceCell(vac)
345 {
346     addCycles(cycles);
347     initColor_();
348 }
349 
initColor_()350 void KeyFace::initColor_()
351 {
352     // Random color
353     /*
354         // using hsv to rgb
355         double H = Random::random(60./60.,200./60.);
356         double S = 0.2;
357         double V = 1;
358 
359         double C = V*S;
360         double X = C * ( 1 - std::abs(std::fmod(H,2)-1) );
361         double R1, G1, B1;
362         if(H<1) { R1=C; G1=X; B1=0;}
363         else if(H<2) { R1=X; G1=C; B1=0;}
364         else if(H<3) { R1=0; G1=C; B1=X;}
365         else if(H<4) { R1=0; G1=X; B1=C;}
366         else if(H<5) { R1=X; G1=0; B1=C;}
367         else { R1=C; G1=0; B1=X;}
368         double m = V - C;
369         color_[0] = R1+m;
370         color_[1] = G1+m;
371         color_[2] = B1+m;
372         color_[3] = 1;
373     */
374 
375     // Color from GUI
376     setColor(global()->faceColor());
377 }
378 
clearCycles_()379 void KeyFace::clearCycles_()
380 {
381     foreach(Cell * cell, spatialBoundary())
382         removeMeFromSpatialStarOf_(cell);
383 
384     cycles_.clear();
385     processGeometryChanged_();
386 }
387 
setCycles(const QList<Cycle> & cycles)388 void KeyFace::setCycles(const QList<Cycle> & cycles)
389 {
390     clearCycles_();
391     addCycles(cycles);
392 }
393 
addCycles(const QList<Cycle> & cycles)394 void KeyFace::addCycles(const QList<Cycle> & cycles)
395 {
396     for(int i=0; i<cycles.size(); ++i)
397         addCycle(cycles[i]);
398 }
399 
addCycle(const Cycle & cycle)400 void KeyFace::addCycle(const Cycle & cycle)
401 {
402     cycles_ << cycle;
403     foreach(KeyCell * cell, cycle.cells())
404         addMeToSpatialStarOf_(cell);
405     processGeometryChanged_();
406 }
407 
triangulate_(Time time,Triangles & out) const408 void KeyFace::triangulate_(Time time, Triangles & out) const
409 {
410     out.clear();
411     if (exists(time))
412         computeTrianglesFromCycles(cycles_, out);
413 }
414 
getSampling(Time) const415 QList<QList<Eigen::Vector2d> > KeyFace::getSampling(Time /*time*/) const
416 {
417     QList<QList<Eigen::Vector2d> > res;
418     PolygonData data = createPolygonData(cycles_);
419 
420     for(unsigned int k=0; k<data.size(); ++k) // for each cycle
421     {
422         res << QList<Eigen::Vector2d>();
423         for(unsigned int i=0; i<data[k].size(); ++i) // for each edge in the cycle
424         {
425             res[k] << Eigen::Vector2d(data[k][i][0], data[k][i][1]);
426         }
427     }
428 
429     return res;
430 }
431 
xmlType_() const432 QString KeyFace::xmlType_() const
433 {
434     return "face";
435 }
436 
write_(XmlStreamWriter & xml) const437 void KeyFace::write_(XmlStreamWriter & xml) const
438 {
439     // Base classes
440     Cell::write_(xml);
441     KeyCell::write_(xml);
442     FaceCell::write_(xml);
443 
444     // Cycles
445     QString cyclesstring;
446     for(int i=0; i<cycles_.size(); ++i)
447     {
448         if(i>0)
449             cyclesstring += " ";
450         cyclesstring += cycles_[i].toString();
451     }
452     xml.writeAttribute("cycles", cyclesstring);
453 }
454 
KeyFace(VAC * vac,XmlStreamReader & xml)455 KeyFace::KeyFace(VAC * vac, XmlStreamReader & xml) :
456     Cell(vac, xml),
457     KeyCell(vac, xml),
458     FaceCell(vac, xml)
459 {
460     // Cycles
461     QString str;
462     QStringRef d = xml.attributes().value("cycles");
463     bool opened = false;
464     for(int i=0; i<d.length(); ++i)
465     {
466         QChar c = d.at(i);
467         if(c == '[')
468             opened = true;
469         if(opened)
470             str += c;
471         if(c==']')
472         {
473             cycles_ << Cycle();
474             cycles_.last().fromString(str);
475             opened = false;
476             str.clear();
477         }
478     }
479 }
480 
save_(QTextStream & out)481 void KeyFace::save_(QTextStream & out)
482 {
483     // Base classes
484     Cell::save_(out);
485     KeyCell::save_(out);
486     FaceCell::save_(out);
487 
488     // Cycles
489     out << Save::newField("Cycles") << cycles_;
490 }
491 
KeyFace(VAC * vac,QTextStream & in)492 KeyFace::KeyFace(VAC * vac, QTextStream & in) :
493     Cell(vac, in),
494     KeyCell(vac, in),
495     FaceCell(vac, in)
496 {
497     Field field;
498 
499     // Cycles
500     in >> /*field >>*/ cycles_; // Reason of comment: see Cell::Cell(VAC * vac, QTextStream & in)
501 }
502 
read2ndPass()503 void KeyFace::read2ndPass()
504 {
505     // Base classes
506     Cell::read2ndPass();
507     KeyCell::read2ndPass();
508     FaceCell::read2ndPass();
509 
510     // Cycles
511     for(int i=0; i<cycles_.size(); ++i)
512         cycles_[i].convertTempIdsToPointers(vac());
513 }
514 
~KeyFace()515 KeyFace::~KeyFace()
516 {
517 }
518 
spatialBoundary() const519 CellSet KeyFace::spatialBoundary() const
520 {
521     CellSet res;
522 
523     for(int i=0; i<cycles_.size(); ++i)
524     {
525         CellSet cells = cycles_[i].cells();
526         res.unite(cells);
527     }
528 
529     return res;
530 }
531 
updateBoundary_impl(KeyEdge * oldEdge,const KeyEdgeList & newEdges)532 void KeyFace::updateBoundary_impl(KeyEdge * oldEdge, const KeyEdgeList & newEdges)
533 {
534     for(int i=0; i<cycles_.size(); ++i)
535         cycles_[i].replaceEdges(oldEdge, newEdges);
536 }
537 
538 // Update boundary
updateBoundary_impl(KeyVertex * oldVertex,KeyVertex * newVertex)539 void KeyFace::updateBoundary_impl(KeyVertex * oldVertex, KeyVertex * newVertex)
540 {
541     for(int i=0; i<cycles_.size(); ++i)
542         cycles_[i].replaceVertex(oldVertex, newVertex);
543 }
544 
updateBoundary_impl(const KeyHalfedge & oldHalfedge,const KeyHalfedge & newHalfedge)545 void KeyFace::updateBoundary_impl(const KeyHalfedge & oldHalfedge, const KeyHalfedge & newHalfedge)
546 {
547     for(int i=0; i<cycles_.size(); ++i)
548         cycles_[i].replaceHalfedge(oldHalfedge, newHalfedge);
549 }
550 
clone()551 KeyFace * KeyFace::clone()
552 {
553     return new KeyFace(this);
554 }
555 
remapPointers(VAC * newVAC)556 void KeyFace::remapPointers(VAC * newVAC)
557 {
558     Cell::remapPointers(newVAC);
559     KeyCell::remapPointers(newVAC);
560     FaceCell::remapPointers(newVAC);
561 
562     for(int i=0; i<cycles_.size(); ++i)
563         cycles_[i].remapPointers(newVAC);
564 }
565 
KeyFace(KeyFace * other)566 KeyFace::KeyFace(KeyFace * other) :
567     Cell(other),
568     KeyCell(other),
569     FaceCell(other)
570 {
571     cycles_ = other->cycles_;
572 }
573 
check_() const574 bool KeyFace::check_() const
575 {
576     // todo
577     return true;
578 }
579 
580 // --------------------------- Preview Key Face ---------------------------
581 
582 
PreviewKeyFace()583 PreviewKeyFace::PreviewKeyFace() :
584     cycles_()
585 {
586 }
587 
PreviewKeyFace(const Cycle & cycle)588 PreviewKeyFace::PreviewKeyFace(const Cycle & cycle) :
589     cycles_()
590 {
591     cycles_ << cycle;
592     computeTriangles_();
593 }
594 
PreviewKeyFace(const QList<Cycle> & cycles)595 PreviewKeyFace::PreviewKeyFace(const QList<Cycle> & cycles) :
596     cycles_(cycles)
597 {
598 }
599 
clear()600 void PreviewKeyFace::clear()
601 {
602     cycles_.clear();
603     triangles_.clear();
604 }
605 
operator <<(const Cycle & cycle)606 PreviewKeyFace & PreviewKeyFace::operator<< (const Cycle & cycle)
607 {
608     cycles_ << cycle;
609     computeTriangles_();
610     return *this;
611 }
612 
computeTriangles_()613 void PreviewKeyFace::computeTriangles_()
614 {
615     computeTrianglesFromCycles(cycles_,triangles_);
616 }
617 
intersects(double x,double y) const618 bool PreviewKeyFace::intersects(double x, double y) const
619 {
620     return triangles_.intersects(Eigen::Vector2d(x,y));
621 }
622 
draw(ViewSettings &)623 void PreviewKeyFace::draw(ViewSettings & /*viewSettings*/)
624 {
625     // Setting the color
626     glColor4d(0.9,0.9,0.9,0.8);
627 
628     // Drawing
629     triangles_.draw();
630 }
631 
632 }
633