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