1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
17 /** \file
18  * \ingroup freestyle
19  */
20 
21 extern "C" {
22 #include <Python.h>
23 }
24 
25 #include <float.h>
26 #include <fstream>
27 #include <string>
28 
29 #include "AppCanvas.h"
30 #include "AppConfig.h"
31 #include "AppView.h"
32 #include "Controller.h"
33 
34 #include "../image/Image.h"
35 
36 #include "../scene_graph/NodeDrawingStyle.h"
37 #include "../scene_graph/NodeShape.h"
38 #include "../scene_graph/NodeTransform.h"
39 #include "../scene_graph/NodeViewLayer.h"
40 #include "../scene_graph/ScenePrettyPrinter.h"
41 #include "../scene_graph/VertexRep.h"
42 
43 #include "../stroke/PSStrokeRenderer.h"
44 #include "../stroke/StrokeTesselator.h"
45 #include "../stroke/StyleModule.h"
46 #include "../stroke/TextStrokeRenderer.h"
47 
48 #include "../system/PythonInterpreter.h"
49 #include "../system/StringUtils.h"
50 
51 #include "../view_map/SteerableViewMap.h"
52 #include "../view_map/ViewMap.h"
53 #include "../view_map/ViewMapIO.h"
54 #include "../view_map/ViewMapTesselator.h"
55 
56 #include "../winged_edge/Curvature.h"
57 #include "../winged_edge/WEdge.h"
58 #include "../winged_edge/WXEdgeBuilder.h"
59 #include "../winged_edge/WingedEdgeBuilder.h"
60 
61 #include "../blender_interface/BlenderFileLoader.h"
62 #include "../blender_interface/BlenderStrokeRenderer.h"
63 #include "../blender_interface/BlenderStyleModule.h"
64 
65 #include "BKE_global.h"
66 #include "BLI_path_util.h"
67 #include "BLI_utildefines.h"
68 
69 #include "DNA_freestyle_types.h"
70 
71 #include "FRS_freestyle.h"
72 
73 namespace Freestyle {
74 
Controller()75 Controller::Controller()
76 {
77   const string sep(Config::DIR_SEP);
78 #if 0
79   const string filename = Config::Path::getInstance()->getHomeDir() + sep + Config::OPTIONS_DIR +
80                           sep + Config::OPTIONS_CURRENT_DIRS_FILE;
81   _current_dirs = new ConfigIO(filename, Config::APPLICATION_NAME + "CurrentDirs", true);
82 #endif
83 
84   _RootNode = new NodeGroup;
85   _RootNode->addRef();
86 
87 #if 0
88   _SilhouetteNode = NULL;
89   _ProjectedSilhouette = NULL;
90   _VisibleProjectedSilhouette = NULL;
91 
92   _DebugNode = new NodeGroup;
93   _DebugNode->addRef();
94 #endif
95 
96   _winged_edge = NULL;
97 
98   _pView = NULL;
99   _pRenderMonitor = NULL;
100 
101   _edgeTesselationNature = (Nature::SILHOUETTE | Nature::BORDER | Nature::CREASE);
102 
103   _ProgressBar = new ProgressBar;
104   _SceneNumFaces = 0;
105 #if 0
106   _minEdgeSize = DBL_MAX;
107 #endif
108   _EPSILON = 1.0e-6;
109   _bboxDiag = 0;
110 
111   _ViewMap = 0;
112 
113   _Canvas = 0;
114 
115   _VisibilityAlgo = ViewMapBuilder::ray_casting_adaptive_traditional;
116   //_VisibilityAlgo = ViewMapBuilder::ray_casting;
117 
118   _Canvas = new AppCanvas;
119 
120   _inter = new PythonInterpreter();
121   _EnableViewMapCache = false;
122   _EnableQI = true;
123   _EnableFaceSmoothness = false;
124   _ComputeRidges = true;
125   _ComputeSteerableViewMap = false;
126   _ComputeSuggestive = true;
127   _ComputeMaterialBoundaries = true;
128   _sphereRadius = 1.0;
129   _creaseAngle = 134.43;
130   prevSceneHash = -1.0;
131 
132   init_options();
133 }
134 
~Controller()135 Controller::~Controller()
136 {
137   if (NULL != _RootNode) {
138     int ref = _RootNode->destroy();
139     if (0 == ref) {
140       delete _RootNode;
141     }
142   }
143 
144 #if 0
145   if (NULL != _SilhouetteNode) {
146     int ref = _SilhouetteNode->destroy();
147     if (0 == ref) {
148       delete _SilhouetteNode;
149     }
150   }
151 
152   if (NULL != _DebugNode) {
153     int ref = _DebugNode->destroy();
154     if (0 == ref) {
155       delete _DebugNode;
156     }
157   }
158 #endif
159 
160   if (_winged_edge) {
161     delete _winged_edge;
162     _winged_edge = NULL;
163   }
164 
165   if (0 != _ViewMap) {
166     delete _ViewMap;
167     _ViewMap = 0;
168   }
169 
170   if (0 != _Canvas) {
171     delete _Canvas;
172     _Canvas = 0;
173   }
174 
175   if (_inter) {
176     delete _inter;
177     _inter = NULL;
178   }
179 
180   if (_ProgressBar) {
181     delete _ProgressBar;
182     _ProgressBar = NULL;
183   }
184 
185   // delete _current_dirs;
186 }
187 
setView(AppView * iView)188 void Controller::setView(AppView *iView)
189 {
190   if (NULL == iView) {
191     return;
192   }
193 
194   _pView = iView;
195   _Canvas->setViewer(_pView);
196 }
197 
setRenderMonitor(RenderMonitor * iRenderMonitor)198 void Controller::setRenderMonitor(RenderMonitor *iRenderMonitor)
199 {
200   _pRenderMonitor = iRenderMonitor;
201 }
202 
setPassDiffuse(float * buf,int width,int height)203 void Controller::setPassDiffuse(float *buf, int width, int height)
204 {
205   AppCanvas *app_canvas = dynamic_cast<AppCanvas *>(_Canvas);
206   BLI_assert(app_canvas != 0);
207   app_canvas->setPassDiffuse(buf, width, height);
208 }
209 
setPassZ(float * buf,int width,int height)210 void Controller::setPassZ(float *buf, int width, int height)
211 {
212   AppCanvas *app_canvas = dynamic_cast<AppCanvas *>(_Canvas);
213   BLI_assert(app_canvas != 0);
214   app_canvas->setPassZ(buf, width, height);
215 }
216 
setContext(bContext * C)217 void Controller::setContext(bContext *C)
218 {
219   PythonInterpreter *py_inter = dynamic_cast<PythonInterpreter *>(_inter);
220   py_inter->setContext(C);
221 }
222 
hitViewMapCache()223 bool Controller::hitViewMapCache()
224 {
225   if (!_EnableViewMapCache) {
226     return false;
227   }
228   if (sceneHashFunc.match()) {
229     return (NULL != _ViewMap);
230   }
231   sceneHashFunc.store();
232   return false;
233 }
234 
LoadMesh(Render * re,ViewLayer * view_layer,Depsgraph * depsgraph)235 int Controller::LoadMesh(Render *re, ViewLayer *view_layer, Depsgraph *depsgraph)
236 {
237   BlenderFileLoader loader(re, view_layer, depsgraph);
238 
239   loader.setRenderMonitor(_pRenderMonitor);
240 
241   _Chrono.start();
242 
243   NodeGroup *blenderScene = loader.Load();
244 
245   if (blenderScene == NULL) {
246     if (G.debug & G_DEBUG_FREESTYLE) {
247       cout << "Cannot load scene" << endl;
248     }
249     return 1;
250   }
251 
252   if (blenderScene->numberOfChildren() < 1) {
253     if (G.debug & G_DEBUG_FREESTYLE) {
254       cout << "Empty scene" << endl;
255     }
256     blenderScene->destroy();
257     delete blenderScene;
258     return 1;
259   }
260 
261   real duration = _Chrono.stop();
262   if (G.debug & G_DEBUG_FREESTYLE) {
263     cout << "Scene loaded" << endl;
264     printf("Mesh cleaning    : %lf\n", duration);
265     printf("View map cache   : %s\n", _EnableViewMapCache ? "enabled" : "disabled");
266   }
267   _SceneNumFaces += loader.numFacesRead();
268 
269 #if 0
270   if (loader.minEdgeSize() < _minEdgeSize) {
271     _minEdgeSize = loader.minEdgeSize();
272   }
273 #endif
274 
275 #if 0  // DEBUG
276   ScenePrettyPrinter spp;
277   blenderScene->accept(spp);
278 #endif
279 
280   _RootNode->AddChild(blenderScene);
281   _RootNode->UpdateBBox();  // FIXME: Correct that by making a Renderer to compute the bbox
282 
283   _pView->setModel(_RootNode);
284   //_pView->FitBBox();
285 
286   if (_pRenderMonitor->testBreak()) {
287     return 0;
288   }
289 
290   if (_EnableViewMapCache) {
291 
292     NodeCamera *cam;
293     if (g_freestyle.proj[3][3] != 0.0) {
294       cam = new NodeOrthographicCamera;
295     }
296     else {
297       cam = new NodePerspectiveCamera;
298     }
299     double proj[16];
300     for (int i = 0; i < 4; i++) {
301       for (int j = 0; j < 4; j++) {
302         proj[i * 4 + j] = g_freestyle.proj[i][j];
303       }
304     }
305     cam->setProjectionMatrix(proj);
306     _RootNode->AddChild(cam);
307     _RootNode->AddChild(new NodeViewLayer(*re->scene, *view_layer));
308 
309     sceneHashFunc.reset();
310     // blenderScene->accept(sceneHashFunc);
311     _RootNode->accept(sceneHashFunc);
312     if (G.debug & G_DEBUG_FREESTYLE) {
313       cout << "Scene hash       : " << sceneHashFunc.toString() << endl;
314     }
315     if (hitViewMapCache()) {
316       ClearRootNode();
317       return 0;
318     }
319 
320     delete _ViewMap;
321     _ViewMap = NULL;
322   }
323 
324   _Chrono.start();
325 
326   WXEdgeBuilder wx_builder;
327   wx_builder.setRenderMonitor(_pRenderMonitor);
328   blenderScene->accept(wx_builder);
329   _winged_edge = wx_builder.getWingedEdge();
330 
331   duration = _Chrono.stop();
332   if (G.debug & G_DEBUG_FREESTYLE) {
333     printf("WEdge building   : %lf\n", duration);
334   }
335 
336 #if 0
337   _pView->setDebug(_DebugNode);
338 
339   // delete stuff
340   if (0 != ws_builder) {
341     delete ws_builder;
342     ws_builder = 0;
343   }
344 
345   soc QFileInfo qfi(iFileName);
346   soc string basename((const char *)qfi.fileName().toAscii().data());
347   char cleaned[FILE_MAX];
348   BLI_strncpy(cleaned, iFileName, FILE_MAX);
349   BLI_path_normalize(NULL, cleaned);
350   string basename = string(cleaned);
351 #endif
352 
353   _ListOfModels.push_back("Blender_models");
354 
355   _Scene3dBBox = _RootNode->bbox();
356 
357   _bboxDiag = (_RootNode->bbox().getMax() - _RootNode->bbox().getMin()).norm();
358   if (G.debug & G_DEBUG_FREESTYLE) {
359     cout << "Triangles nb     : " << _SceneNumFaces << " imported, " << _winged_edge->getNumFaces()
360          << " retained" << endl;
361     cout << "Bounding Box     : " << _bboxDiag << endl;
362   }
363 
364   ClearRootNode();
365 
366   _SceneNumFaces = _winged_edge->getNumFaces();
367   if (_SceneNumFaces == 0) {
368     DeleteWingedEdge();
369     return 1;
370   }
371 
372   return 0;
373 }
374 
CloseFile()375 void Controller::CloseFile()
376 {
377   WShape::setCurrentId(0);
378   _ListOfModels.clear();
379 
380   // We deallocate the memory:
381   ClearRootNode();
382   DeleteWingedEdge();
383   DeleteViewMap();
384 
385   // clears the canvas
386   _Canvas->Clear();
387 
388   // soc: reset passes
389   setPassDiffuse(NULL, 0, 0);
390   setPassZ(NULL, 0, 0);
391 }
392 
ClearRootNode()393 void Controller::ClearRootNode()
394 {
395   _pView->DetachModel();
396   if (NULL != _RootNode) {
397     int ref = _RootNode->destroy();
398     if (0 == ref) {
399       _RootNode->addRef();
400     }
401     _RootNode->clearBBox();
402   }
403 }
404 
DeleteWingedEdge()405 void Controller::DeleteWingedEdge()
406 {
407   if (_winged_edge) {
408     delete _winged_edge;
409     _winged_edge = NULL;
410   }
411 
412   // clears the grid
413   _Grid.clear();
414   _Scene3dBBox.clear();
415   _SceneNumFaces = 0;
416 #if 0
417   _minEdgeSize = DBL_MAX;
418 #endif
419 }
420 
DeleteViewMap(bool freeCache)421 void Controller::DeleteViewMap(bool freeCache)
422 {
423 #if 0
424   _pView->DetachSilhouette();
425   if (NULL != _SilhouetteNode) {
426     int ref = _SilhouetteNode->destroy();
427     if (0 == ref) {
428       delete _SilhouetteNode;
429       _SilhouetteNode = NULL;
430     }
431   }
432 
433   if (NULL != _ProjectedSilhouette) {
434     int ref = _ProjectedSilhouette->destroy();
435     if (0 == ref) {
436       delete _ProjectedSilhouette;
437       _ProjectedSilhouette = NULL;
438     }
439   }
440   if (NULL != _VisibleProjectedSilhouette) {
441     int ref = _VisibleProjectedSilhouette->destroy();
442     if (0 == ref) {
443       delete _VisibleProjectedSilhouette;
444       _VisibleProjectedSilhouette = NULL;
445     }
446   }
447 
448   _pView->DetachDebug();
449   if (NULL != _DebugNode) {
450     int ref = _DebugNode->destroy();
451     if (0 == ref) {
452       _DebugNode->addRef();
453     }
454   }
455 #endif
456 
457   if (NULL != _ViewMap) {
458     if (freeCache || !_EnableViewMapCache) {
459       delete _ViewMap;
460       _ViewMap = NULL;
461       prevSceneHash = -1.0;
462     }
463     else {
464       _ViewMap->Clean();
465     }
466   }
467 }
468 
ComputeViewMap()469 void Controller::ComputeViewMap()
470 {
471   if (_ListOfModels.empty()) {
472     return;
473   }
474 
475   DeleteViewMap(true);
476 
477   // retrieve the 3D viewpoint and transformations information
478   //----------------------------------------------------------
479   // Save the viewpoint context at the view level in order
480   // to be able to restore it later:
481 
482   // Restore the context of view:
483   // we need to perform all these operations while the
484   // 3D context is on.
485   Vec3f vp(UNPACK3(g_freestyle.viewpoint));
486 
487 #if 0
488   if (G.debug & G_DEBUG_FREESTYLE) {
489     cout << "mv" << endl;
490   }
491 #endif
492   real mv[4][4];
493   for (int i = 0; i < 4; i++) {
494     for (int j = 0; j < 4; j++) {
495       mv[i][j] = g_freestyle.mv[i][j];
496 #if 0
497       if (G.debug & G_DEBUG_FREESTYLE) {
498         cout << mv[i][j] << " ";
499       }
500 #endif
501     }
502 #if 0
503     if (G.debug & G_DEBUG_FREESTYLE) {
504       cout << endl;
505     }
506 #endif
507   }
508 
509 #if 0
510   if (G.debug & G_DEBUG_FREESTYLE) {
511     cout << "\nproj" << endl;
512   }
513 #endif
514   real proj[4][4];
515   for (int i = 0; i < 4; i++) {
516     for (int j = 0; j < 4; j++) {
517       proj[i][j] = g_freestyle.proj[i][j];
518 #if 0
519       if (G.debug & G_DEBUG_FREESTYLE) {
520         cout << proj[i][j] << " ";
521       }
522 #endif
523     }
524 #if 0
525     if (G.debug & G_DEBUG_FREESTYLE) {
526       cout << endl;
527     }
528 #endif
529   }
530 
531   int viewport[4];
532   for (int i = 0; i < 4; i++) {
533     viewport[i] = g_freestyle.viewport[i];
534   }
535 
536 #if 0
537   if (G.debug & G_DEBUG_FREESTYLE) {
538     cout << "\nfocal:" << _pView->GetFocalLength() << endl << endl;
539   }
540 #endif
541 
542   // Flag the WXEdge structure for silhouette edge detection:
543   //----------------------------------------------------------
544 
545   if (G.debug & G_DEBUG_FREESTYLE) {
546     cout << "\n===  Detecting silhouette edges  ===" << endl;
547   }
548   _Chrono.start();
549 
550   edgeDetector.setViewpoint(vp);
551   edgeDetector.enableOrthographicProjection(proj[3][3] != 0.0);
552   edgeDetector.enableRidgesAndValleysFlag(_ComputeRidges);
553   edgeDetector.enableSuggestiveContours(_ComputeSuggestive);
554   edgeDetector.enableMaterialBoundaries(_ComputeMaterialBoundaries);
555   edgeDetector.enableFaceSmoothness(_EnableFaceSmoothness);
556   edgeDetector.setCreaseAngle(_creaseAngle);
557   edgeDetector.setSphereRadius(_sphereRadius);
558   edgeDetector.setSuggestiveContourKrDerivativeEpsilon(_suggestiveContourKrDerivativeEpsilon);
559   edgeDetector.setRenderMonitor(_pRenderMonitor);
560   edgeDetector.processShapes(*_winged_edge);
561 
562   real duration = _Chrono.stop();
563   if (G.debug & G_DEBUG_FREESTYLE) {
564     printf("Feature lines    : %lf\n", duration);
565   }
566 
567   if (_pRenderMonitor->testBreak()) {
568     return;
569   }
570 
571   // Builds the view map structure from the flagged WSEdge structure:
572   //----------------------------------------------------------
573   ViewMapBuilder vmBuilder;
574   vmBuilder.setEnableQI(_EnableQI);
575   vmBuilder.setViewpoint(vp);
576   vmBuilder.setTransform(
577       mv, proj, viewport, _pView->GetFocalLength(), _pView->GetAspect(), _pView->GetFovyRadian());
578   vmBuilder.setFrustum(_pView->znear(), _pView->zfar());
579   vmBuilder.setGrid(&_Grid);
580   vmBuilder.setRenderMonitor(_pRenderMonitor);
581 
582 #if 0
583   // Builds a tesselated form of the silhouette for display purpose:
584   //---------------------------------------------------------------
585   ViewMapTesselator3D sTesselator3d;
586   ViewMapTesselator2D sTesselator2d;
587   sTesselator2d.setNature(_edgeTesselationNature);
588   sTesselator3d.setNature(_edgeTesselationNature);
589 #endif
590 
591   if (G.debug & G_DEBUG_FREESTYLE) {
592     cout << "\n===  Building the view map  ===" << endl;
593   }
594   _Chrono.start();
595   // Build View Map
596   _ViewMap = vmBuilder.BuildViewMap(
597       *_winged_edge, _VisibilityAlgo, _EPSILON, _Scene3dBBox, _SceneNumFaces);
598   _ViewMap->setScene3dBBox(_Scene3dBBox);
599 
600   if (G.debug & G_DEBUG_FREESTYLE) {
601     printf("ViewMap edge count : %i\n", _ViewMap->viewedges_size());
602   }
603 
604 #if 0
605   // Tesselate the 3D edges:
606   _SilhouetteNode = sTesselator3d.Tesselate(_ViewMap);
607   _SilhouetteNode->addRef();
608 
609   // Tesselate 2D edges
610   _ProjectedSilhouette = sTesselator2d.Tesselate(_ViewMap);
611   _ProjectedSilhouette->addRef();
612 #endif
613 
614   duration = _Chrono.stop();
615   if (G.debug & G_DEBUG_FREESTYLE) {
616     printf("ViewMap building : %lf\n", duration);
617   }
618 
619 #if 0
620   _pView->AddSilhouette(_SilhouetteNode);
621   _pView->AddSilhouette(_WRoot);
622   _pView->Add2DSilhouette(_ProjectedSilhouette);
623   _pView->Add2DVisibleSilhouette(_VisibleProjectedSilhouette);
624   _pView->AddDebug(_DebugNode);
625 #endif
626 
627   // Draw the steerable density map:
628   //--------------------------------
629   if (_ComputeSteerableViewMap) {
630     ComputeSteerableViewMap();
631   }
632   // Reset Style modules modification flags
633   resetModified(true);
634 
635   DeleteWingedEdge();
636 }
637 
ComputeSteerableViewMap()638 void Controller::ComputeSteerableViewMap()
639 {
640 #if 0  // soc
641   if ((!_Canvas) || (!_ViewMap)) {
642     return;
643   }
644 
645   // Build 4 nodes containing the edges in the 4 directions
646   NodeGroup *ng[Canvas::NB_STEERABLE_VIEWMAP];
647   unsigned i;
648   real c =
649       32.0f /
650       255.0f;  // see SteerableViewMap::readSteerableViewMapPixel() for information about this 32.
651   for (i = 0; i < Canvas::NB_STEERABLE_VIEWMAP; ++i) {
652     ng[i] = new NodeGroup;
653   }
654   NodeShape *completeNS = new NodeShape;
655   completeNS->material().setDiffuse(c, c, c, 1);
656   ng[Canvas::NB_STEERABLE_VIEWMAP - 1]->AddChild(completeNS);
657   SteerableViewMap *svm = _Canvas->getSteerableViewMap();
658   svm->Reset();
659 
660   ViewMap::fedges_container &fedges = _ViewMap->FEdges();
661   LineRep *fRep;
662   NodeShape *ns;
663   for (ViewMap::fedges_container::iterator f = fedges.begin(), fend = fedges.end(); f != fend;
664        ++f) {
665     if ((*f)->viewedge()->qi() != 0) {
666       continue;
667     }
668     fRep = new LineRep((*f)->vertexA()->point2d(), (*f)->vertexB()->point2d());
669     completeNS->AddRep(fRep);  // add to the complete map anyway
670     double *oweights = svm->AddFEdge(*f);
671     for (i = 0; i < (Canvas::NB_STEERABLE_VIEWMAP - 1); ++i) {
672       ns = new NodeShape;
673       double wc = oweights[i] * c;
674       if (oweights[i] == 0) {
675         continue;
676       }
677       ns->material().setDiffuse(wc, wc, wc, 1);
678       ns->AddRep(fRep);
679       ng[i]->AddChild(ns);
680     }
681   }
682 
683   GrayImage *img[Canvas::NB_STEERABLE_VIEWMAP];
684   //#ifdef WIN32
685   QGLBasicWidget offscreenBuffer(_pView, "SteerableViewMap", _pView->width(), _pView->height());
686   QPixmap pm;
687   QImage qimg;
688   for (i = 0; i < Canvas::NB_STEERABLE_VIEWMAP; ++i) {
689     offscreenBuffer.AddNode(ng[i]);
690 #  if 0
691     img[i] = new GrayImage(_pView->width(), _pView->height());
692     offscreenBuffer.readPixels(0,0,_pView->width(), _pView->height(), img[i]->getArray());
693 #  endif
694     pm = offscreenBuffer.renderPixmap(_pView->width(), _pView->height());
695 
696     if (pm.isNull()) {
697       if (G.debug & G_DEBUG_FREESTYLE) {
698         cout << "BuildViewMap Warning: couldn't render the steerable ViewMap" << endl;
699       }
700     }
701     //pm.save(QString("steerable") + QString::number(i) + QString(".bmp"), "BMP");
702     // FIXME!! Lost of time !
703     qimg = pm.toImage();
704     // FIXME !! again!
705     img[i] = new GrayImage(_pView->width(), _pView->height());
706     for (unsigned int y = 0; y < img[i]->height(); ++y) {
707       for (unsigned int x = 0; x < img[i]->width(); ++x) {
708         //img[i]->setPixel(x, y, (float)qGray(qimg.pixel(x, y)) / 255.0f);
709         img[i]->setPixel(x, y, (float)qGray(qimg.pixel(x, y)));
710         //float c = qGray(qimg.pixel(x, y));
711         //img[i]->setPixel(x, y, qGray(qimg.pixel(x, y)));
712       }
713     }
714     offscreenBuffer.DetachNode(ng[i]);
715     ng[i]->destroy();
716     delete ng[i];
717     // check
718 #  if 0
719     qimg = QImage(_pView->width(), _pView->height(), 32);
720     for (unsigned int y = 0; y < img[i]->height(); ++y) {
721       for (unsigned int x = 0; x < img[i]->width(); ++x) {
722         float v = img[i]->pixel(x, y);
723         qimg.setPixel(x, y, qRgb(v, v, v));
724       }
725     }
726     qimg.save(QString("newsteerable") + QString::number(i) + QString(".bmp"), "BMP");
727 #  endif
728   }
729 
730   svm->buildImagesPyramids(img, false, 0, 1.0f);
731 #endif
732 }
733 
saveSteerableViewMapImages()734 void Controller::saveSteerableViewMapImages()
735 {
736   SteerableViewMap *svm = _Canvas->getSteerableViewMap();
737   if (!svm) {
738     cerr << "the Steerable ViewMap has not been computed yet" << endl;
739     return;
740   }
741   svm->saveSteerableViewMap();
742 }
743 
toggleVisibilityAlgo()744 void Controller::toggleVisibilityAlgo()
745 {
746   if (_VisibilityAlgo == ViewMapBuilder::ray_casting) {
747     _VisibilityAlgo = ViewMapBuilder::ray_casting_fast;
748   }
749   else if (_VisibilityAlgo == ViewMapBuilder::ray_casting_fast) {
750     _VisibilityAlgo = ViewMapBuilder::ray_casting_very_fast;
751   }
752   else {
753     _VisibilityAlgo = ViewMapBuilder::ray_casting;
754   }
755 }
756 
setVisibilityAlgo(int algo)757 void Controller::setVisibilityAlgo(int algo)
758 {
759   switch (algo) {
760     case FREESTYLE_ALGO_REGULAR:
761       _VisibilityAlgo = ViewMapBuilder::ray_casting;
762       break;
763     case FREESTYLE_ALGO_FAST:
764       _VisibilityAlgo = ViewMapBuilder::ray_casting_fast;
765       break;
766     case FREESTYLE_ALGO_VERYFAST:
767       _VisibilityAlgo = ViewMapBuilder::ray_casting_very_fast;
768       break;
769     case FREESTYLE_ALGO_CULLED_ADAPTIVE_TRADITIONAL:
770       _VisibilityAlgo = ViewMapBuilder::ray_casting_culled_adaptive_traditional;
771       break;
772     case FREESTYLE_ALGO_ADAPTIVE_TRADITIONAL:
773       _VisibilityAlgo = ViewMapBuilder::ray_casting_adaptive_traditional;
774       break;
775     case FREESTYLE_ALGO_CULLED_ADAPTIVE_CUMULATIVE:
776       _VisibilityAlgo = ViewMapBuilder::ray_casting_culled_adaptive_cumulative;
777       break;
778     case FREESTYLE_ALGO_ADAPTIVE_CUMULATIVE:
779       _VisibilityAlgo = ViewMapBuilder::ray_casting_adaptive_cumulative;
780       break;
781   }
782 }
783 
getVisibilityAlgo()784 int Controller::getVisibilityAlgo()
785 {
786   switch (_VisibilityAlgo) {
787     case ViewMapBuilder::ray_casting:
788       return FREESTYLE_ALGO_REGULAR;
789     case ViewMapBuilder::ray_casting_fast:
790       return FREESTYLE_ALGO_FAST;
791     case ViewMapBuilder::ray_casting_very_fast:
792       return FREESTYLE_ALGO_VERYFAST;
793     case ViewMapBuilder::ray_casting_culled_adaptive_traditional:
794       return FREESTYLE_ALGO_CULLED_ADAPTIVE_TRADITIONAL;
795     case ViewMapBuilder::ray_casting_adaptive_traditional:
796       return FREESTYLE_ALGO_ADAPTIVE_TRADITIONAL;
797     case ViewMapBuilder::ray_casting_culled_adaptive_cumulative:
798       return FREESTYLE_ALGO_CULLED_ADAPTIVE_CUMULATIVE;
799     case ViewMapBuilder::ray_casting_adaptive_cumulative:
800       return FREESTYLE_ALGO_ADAPTIVE_CUMULATIVE;
801   }
802 
803   // ray_casting_adaptive_traditional is the most exact replacement
804   // for legacy code
805   return FREESTYLE_ALGO_ADAPTIVE_TRADITIONAL;
806 }
807 
setViewMapCache(bool iBool)808 void Controller::setViewMapCache(bool iBool)
809 {
810   _EnableViewMapCache = iBool;
811 }
812 
getViewMapCache() const813 bool Controller::getViewMapCache() const
814 {
815   return _EnableViewMapCache;
816 }
817 
setQuantitativeInvisibility(bool iBool)818 void Controller::setQuantitativeInvisibility(bool iBool)
819 {
820   _EnableQI = iBool;
821 }
822 
getQuantitativeInvisibility() const823 bool Controller::getQuantitativeInvisibility() const
824 {
825   return _EnableQI;
826 }
827 
setFaceSmoothness(bool iBool)828 void Controller::setFaceSmoothness(bool iBool)
829 {
830   _EnableFaceSmoothness = iBool;
831 }
832 
getFaceSmoothness() const833 bool Controller::getFaceSmoothness() const
834 {
835   return _EnableFaceSmoothness;
836 }
837 
setComputeRidgesAndValleysFlag(bool b)838 void Controller::setComputeRidgesAndValleysFlag(bool b)
839 {
840   _ComputeRidges = b;
841 }
842 
getComputeRidgesAndValleysFlag() const843 bool Controller::getComputeRidgesAndValleysFlag() const
844 {
845   return _ComputeRidges;
846 }
847 
setComputeSuggestiveContoursFlag(bool b)848 void Controller::setComputeSuggestiveContoursFlag(bool b)
849 {
850   _ComputeSuggestive = b;
851 }
852 
getComputeSuggestiveContoursFlag() const853 bool Controller::getComputeSuggestiveContoursFlag() const
854 {
855   return _ComputeSuggestive;
856 }
857 
setComputeMaterialBoundariesFlag(bool b)858 void Controller::setComputeMaterialBoundariesFlag(bool b)
859 {
860   _ComputeMaterialBoundaries = b;
861 }
862 
getComputeMaterialBoundariesFlag() const863 bool Controller::getComputeMaterialBoundariesFlag() const
864 {
865   return _ComputeMaterialBoundaries;
866 }
867 
setComputeSteerableViewMapFlag(bool iBool)868 void Controller::setComputeSteerableViewMapFlag(bool iBool)
869 {
870   _ComputeSteerableViewMap = iBool;
871 }
872 
getComputeSteerableViewMapFlag() const873 bool Controller::getComputeSteerableViewMapFlag() const
874 {
875   return _ComputeSteerableViewMap;
876 }
877 
DrawStrokes()878 int Controller::DrawStrokes()
879 {
880   if (_ViewMap == 0) {
881     return 0;
882   }
883 
884   if (G.debug & G_DEBUG_FREESTYLE) {
885     cout << "\n===  Stroke drawing  ===" << endl;
886   }
887   _Chrono.start();
888   _Canvas->Draw();
889   real d = _Chrono.stop();
890   int strokeCount = _Canvas->getStrokeCount();
891   if (G.debug & G_DEBUG_FREESTYLE) {
892     cout << "Strokes generation  : " << d << endl;
893     cout << "Stroke count  : " << strokeCount << endl;
894   }
895   resetModified();
896   DeleteViewMap();
897   return strokeCount;
898 }
899 
ResetRenderCount()900 void Controller::ResetRenderCount()
901 {
902   _render_count = 0;
903 }
904 
RenderStrokes(Render * re,bool render)905 Render *Controller::RenderStrokes(Render *re, bool render)
906 {
907   int totmesh = 0;
908   _Chrono.start();
909   BlenderStrokeRenderer *blenderRenderer = new BlenderStrokeRenderer(re, ++_render_count);
910   if (render) {
911     _Canvas->Render(blenderRenderer);
912     totmesh = blenderRenderer->GenerateScene();
913   }
914   real d = _Chrono.stop();
915   if (G.debug & G_DEBUG_FREESTYLE) {
916     cout << "Temporary scene generation: " << d << endl;
917   }
918   _Chrono.start();
919   Render *freestyle_render = blenderRenderer->RenderScene(re, render);
920   d = _Chrono.stop();
921   if (G.debug & G_DEBUG_FREESTYLE) {
922     cout << "Stroke rendering  : " << d << endl;
923 
924     uintptr_t mem_in_use = MEM_get_memory_in_use();
925     uintptr_t peak_memory = MEM_get_peak_memory();
926 
927     float megs_used_memory = (mem_in_use) / (1024.0 * 1024.0);
928     float megs_peak_memory = (peak_memory) / (1024.0 * 1024.0);
929 
930     printf("%d objs, %d verts, %d faces, mem %.2fM (peak %.2fM)\n",
931            totmesh,
932            freestyle_render->i.totvert,
933            freestyle_render->i.totface,
934            megs_used_memory,
935            megs_peak_memory);
936   }
937   delete blenderRenderer;
938 
939   return freestyle_render;
940 }
941 
InsertStyleModule(unsigned index,const char * iFileName)942 void Controller::InsertStyleModule(unsigned index, const char *iFileName)
943 {
944   if (!BLI_path_extension_check(iFileName, ".py")) {
945     cerr << "Error: Cannot load \"" << string(iFileName) << "\", unknown extension" << endl;
946     return;
947   }
948 
949   StyleModule *sm = new StyleModule(iFileName, _inter);
950   _Canvas->InsertStyleModule(index, sm);
951 }
952 
InsertStyleModule(unsigned index,const char * iName,const char * iBuffer)953 void Controller::InsertStyleModule(unsigned index, const char *iName, const char *iBuffer)
954 {
955   StyleModule *sm = new BufferedStyleModule(iBuffer, iName, _inter);
956   _Canvas->InsertStyleModule(index, sm);
957 }
958 
InsertStyleModule(unsigned index,const char * iName,struct Text * iText)959 void Controller::InsertStyleModule(unsigned index, const char *iName, struct Text *iText)
960 {
961   StyleModule *sm = new BlenderStyleModule(iText, iName, _inter);
962   _Canvas->InsertStyleModule(index, sm);
963 }
964 
AddStyleModule(const char *)965 void Controller::AddStyleModule(const char * /*iFileName*/)
966 {
967   //_pStyleWindow->Add(iFileName);
968 }
969 
RemoveStyleModule(unsigned index)970 void Controller::RemoveStyleModule(unsigned index)
971 {
972   _Canvas->RemoveStyleModule(index);
973 }
974 
Clear()975 void Controller::Clear()
976 {
977   _Canvas->Clear();
978 }
979 
ReloadStyleModule(unsigned index,const char * iFileName)980 void Controller::ReloadStyleModule(unsigned index, const char *iFileName)
981 {
982   StyleModule *sm = new StyleModule(iFileName, _inter);
983   _Canvas->ReplaceStyleModule(index, sm);
984 }
985 
SwapStyleModules(unsigned i1,unsigned i2)986 void Controller::SwapStyleModules(unsigned i1, unsigned i2)
987 {
988   _Canvas->SwapStyleModules(i1, i2);
989 }
990 
toggleLayer(unsigned index,bool iDisplay)991 void Controller::toggleLayer(unsigned index, bool iDisplay)
992 {
993   _Canvas->setVisible(index, iDisplay);
994 }
995 
setModified(unsigned index,bool iMod)996 void Controller::setModified(unsigned index, bool iMod)
997 {
998   //_pStyleWindow->setModified(index, iMod);
999   _Canvas->setModified(index, iMod);
1000   updateCausalStyleModules(index + 1);
1001 }
1002 
updateCausalStyleModules(unsigned index)1003 void Controller::updateCausalStyleModules(unsigned index)
1004 {
1005   vector<unsigned> vec;
1006   _Canvas->causalStyleModules(vec, index);
1007   for (vector<unsigned>::const_iterator it = vec.begin(); it != vec.end(); it++) {
1008     //_pStyleWindow->setModified(*it, true);
1009     _Canvas->setModified(*it, true);
1010   }
1011 }
1012 
resetModified(bool iMod)1013 void Controller::resetModified(bool iMod)
1014 {
1015   //_pStyleWindow->resetModified(iMod);
1016   _Canvas->resetModified(iMod);
1017 }
1018 
BuildRep(vector<ViewEdge * >::iterator vedges_begin,vector<ViewEdge * >::iterator vedges_end)1019 NodeGroup *Controller::BuildRep(vector<ViewEdge *>::iterator vedges_begin,
1020                                 vector<ViewEdge *>::iterator vedges_end)
1021 {
1022   ViewMapTesselator2D tesselator2D;
1023   FrsMaterial mat;
1024   mat.setDiffuse(1, 1, 0.3, 1);
1025   tesselator2D.setFrsMaterial(mat);
1026 
1027   return (tesselator2D.Tesselate(vedges_begin, vedges_end));
1028 }
1029 
toggleEdgeTesselationNature(Nature::EdgeNature iNature)1030 void Controller::toggleEdgeTesselationNature(Nature::EdgeNature iNature)
1031 {
1032   _edgeTesselationNature ^= (iNature);
1033   ComputeViewMap();
1034 }
1035 
setModelsDir(const string &)1036 void Controller::setModelsDir(const string & /*dir*/)
1037 {
1038   //_current_dirs->setValue("models/dir", dir);
1039 }
1040 
getModelsDir() const1041 string Controller::getModelsDir() const
1042 {
1043   string dir = ".";
1044   //_current_dirs->getValue("models/dir", dir);
1045   return dir;
1046 }
1047 
setModulesDir(const string &)1048 void Controller::setModulesDir(const string & /*dir*/)
1049 {
1050   //_current_dirs->setValue("modules/dir", dir);
1051 }
1052 
getModulesDir() const1053 string Controller::getModulesDir() const
1054 {
1055   string dir = ".";
1056   //_current_dirs->getValue("modules/dir", dir);
1057   return dir;
1058 }
1059 
resetInterpreter()1060 void Controller::resetInterpreter()
1061 {
1062   if (_inter) {
1063     _inter->reset();
1064   }
1065 }
1066 
displayDensityCurves(int x,int y)1067 void Controller::displayDensityCurves(int x, int y)
1068 {
1069   SteerableViewMap *svm = _Canvas->getSteerableViewMap();
1070   if (!svm) {
1071     return;
1072   }
1073 
1074   unsigned int i, j;
1075   typedef vector<Vec3r> densityCurve;
1076   vector<densityCurve> curves(svm->getNumberOfOrientations() + 1);
1077   vector<densityCurve> curvesDirection(svm->getNumberOfPyramidLevels());
1078 
1079   // collect the curves values
1080   unsigned nbCurves = svm->getNumberOfOrientations() + 1;
1081   unsigned nbPoints = svm->getNumberOfPyramidLevels();
1082   if (!nbPoints) {
1083     return;
1084   }
1085 
1086   // build the density/nbLevels curves for each orientation
1087   for (i = 0; i < nbCurves; ++i) {
1088     for (j = 0; j < nbPoints; ++j) {
1089       curves[i].push_back(Vec3r(j, svm->readSteerableViewMapPixel(i, j, x, y), 0));
1090     }
1091   }
1092   // build the density/nbOrientations curves for each level
1093   for (i = 0; i < nbPoints; ++i) {
1094     for (j = 0; j < nbCurves; ++j) {
1095       curvesDirection[i].push_back(Vec3r(j, svm->readSteerableViewMapPixel(j, i, x, y), 0));
1096     }
1097   }
1098 
1099   // display the curves
1100 #if 0
1101   for (i = 0; i < nbCurves; ++i) {
1102     _pDensityCurvesWindow->setOrientationCurve(
1103         i, Vec2d(0, 0), Vec2d(nbPoints, 1), curves[i], "scale", "density");
1104   }
1105   for (i = 1; i <= 8; ++i) {
1106     _pDensityCurvesWindow->setLevelCurve(
1107         i, Vec2d(0, 0), Vec2d(nbCurves, 1), curvesDirection[i], "orientation", "density");
1108   }
1109   _pDensityCurvesWindow->show();
1110 #endif
1111 }
1112 
init_options()1113 void Controller::init_options()
1114 {
1115   // from AppOptionsWindow.cpp
1116   // Default init options
1117 
1118   Config::Path *cpath = Config::Path::getInstance();
1119 
1120   // Directories
1121   ViewMapIO::Options::setModelsPath(cpath->getModelsPath());
1122   TextureManager::Options::setPatternsPath(cpath->getPatternsPath());
1123   TextureManager::Options::setBrushesPath(cpath->getModelsPath());
1124 
1125   // ViewMap Format
1126   ViewMapIO::Options::rmFlags(ViewMapIO::Options::FLOAT_VECTORS);
1127   ViewMapIO::Options::rmFlags(ViewMapIO::Options::NO_OCCLUDERS);
1128   setComputeSteerableViewMapFlag(false);
1129 
1130   // Visibility
1131   setQuantitativeInvisibility(true);
1132 
1133   // soc: initialize canvas
1134   _Canvas->init();
1135 
1136   // soc: initialize passes
1137   setPassDiffuse(NULL, 0, 0);
1138   setPassZ(NULL, 0, 0);
1139 }
1140 
1141 } /* namespace Freestyle */
1142