Fix #35561: freestyle + read full sample layers = crash.
[blender.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         _bboxDiag = (_RootNode->bbox().getMax() - _RootNode->bbox().getMin()).norm();
294         if (G.debug & G_DEBUG_FREESTYLE) {
295                 cout << "Triangles nb     : " << _SceneNumFaces << endl;
296                 cout << "Bounding Box     : " << _bboxDiag << endl;
297         }
298
299         ClearRootNode();
300
301         return 0;
302 }
303
304 void Controller::CloseFile()
305 {
306         WShape::setCurrentId(0);
307         _ListOfModels.clear();
308
309         // We deallocate the memory:
310         ClearRootNode();
311         DeleteWingedEdge();
312         DeleteViewMap();
313
314         // clears the canvas
315         _Canvas->Clear();
316
317         // soc: reset passes
318         setPassDiffuse(NULL, 0, 0);
319         setPassZ(NULL, 0, 0);
320 }
321
322 void Controller::ClearRootNode()
323 {
324         _pView->DetachModel();
325         if (NULL != _RootNode) {
326                 int ref = _RootNode->destroy();
327                 if (0 == ref)
328                         _RootNode->addRef();
329                 _RootNode->clearBBox();
330         }
331 }
332
333 void Controller::DeleteWingedEdge()
334 {
335         if (_winged_edge) {
336                 delete _winged_edge;
337                 _winged_edge = NULL;
338         }
339
340         // clears the grid
341         _Grid.clear();
342         _SceneNumFaces = 0;
343         _minEdgeSize = DBL_MAX;
344 }
345
346 void Controller::DeleteViewMap()
347 {
348         _pView->DetachSilhouette();
349         if (NULL != _SilhouetteNode) {
350                 int ref = _SilhouetteNode->destroy();
351                 if (0 == ref) {
352                         delete _SilhouetteNode;
353                         _SilhouetteNode = NULL;
354                 }
355         }
356
357 #if 0
358         if (NULL != _ProjectedSilhouette) {
359                 int ref = _ProjectedSilhouette->destroy();
360                 if (0 == ref) {
361                         delete _ProjectedSilhouette;
362                         _ProjectedSilhouette = NULL;
363                 }
364         }
365         if (NULL != _VisibleProjectedSilhouette) {
366                 int ref = _VisibleProjectedSilhouette->destroy();
367                 if (0 == ref) {
368                         delete _VisibleProjectedSilhouette;
369                         _VisibleProjectedSilhouette = NULL;
370                 }
371         }
372 #endif
373
374         _pView->DetachDebug();
375         if (NULL != _DebugNode) {
376         int ref = _DebugNode->destroy();
377                 if (0 == ref)
378                         _DebugNode->addRef();
379         }
380
381         if (NULL != _ViewMap) {
382                 delete _ViewMap;
383                 _ViewMap = NULL;
384         }
385 }
386
387 void Controller::ComputeViewMap()
388 {
389         if (!_ListOfModels.size())
390                 return;
391
392         if (NULL != _ViewMap) {
393                 delete _ViewMap;
394                 _ViewMap = NULL;
395         }
396
397         _pView->DetachDebug();
398         if (NULL != _DebugNode) {
399                 int ref = _DebugNode->destroy();
400                 if (0 == ref)
401                         _DebugNode->addRef();
402         }
403
404         _pView->DetachSilhouette();
405         if (NULL != _SilhouetteNode) {
406                 int ref = _SilhouetteNode->destroy();
407                 if (0 == ref)
408                         delete _SilhouetteNode;
409         }
410
411 #if 0
412         if (NULL != _ProjectedSilhouette) {
413                 int ref = _ProjectedSilhouette->destroy();
414                 if (0 == ref)
415                         delete _ProjectedSilhouette;
416         }
417
418         if (NULL != _VisibleProjectedSilhouette) {
419                 int ref = _VisibleProjectedSilhouette->destroy();
420                 if (0 == ref) {
421                         delete _VisibleProjectedSilhouette;
422                         _VisibleProjectedSilhouette = NULL;
423                 }
424         }
425 #endif
426
427         // retrieve the 3D viewpoint and transformations information
428         //----------------------------------------------------------
429         // Save the viewpoint context at the view level in order 
430         // to be able to restore it later:
431
432         // Restore the context of view:
433         // we need to perform all these operations while the 
434         // 3D context is on.
435         Vec3r vp(freestyle_viewpoint[0], freestyle_viewpoint[1], freestyle_viewpoint[2]);
436
437 #if 0
438         if (G.debug & G_DEBUG_FREESTYLE) {
439                 cout << "mv" << endl;
440         }
441 #endif
442         real mv[4][4];
443         for (int i = 0; i < 4; i++) {
444                 for (int j = 0; j < 4; j++) {
445                         mv[i][j] = freestyle_mv[i][j];
446 #if 0
447                         if (G.debug & G_DEBUG_FREESTYLE) {
448                                 cout << mv[i][j] << " ";
449                         }
450 #endif
451                 }
452 #if 0
453                 if (G.debug & G_DEBUG_FREESTYLE) {
454                         cout << endl;
455                 }
456 #endif
457         }
458
459 #if 0
460         if (G.debug & G_DEBUG_FREESTYLE) {
461                 cout << "\nproj" << endl;
462         }
463 #endif
464         real proj[4][4];
465         for (int i = 0; i < 4; i++) {
466                 for (int j = 0; j < 4; j++) {
467                         proj[i][j] = freestyle_proj[i][j];
468 #if 0
469                         if (G.debug & G_DEBUG_FREESTYLE) {
470                                 cout << proj[i][j] << " ";
471                         }
472 #endif
473                 }
474 #if 0
475                 if (G.debug & G_DEBUG_FREESTYLE) {
476                         cout << endl;
477                 }
478 #endif
479         }
480
481         int viewport[4];
482         for (int i = 0; i < 4; i++)
483                 viewport[i] = freestyle_viewport[i];
484
485 #if 0
486         if (G.debug & G_DEBUG_FREESTYLE) {
487                 cout << "\nfocal:" << _pView->GetFocalLength() << endl << endl;
488         }
489 #endif
490
491         // Flag the WXEdge structure for silhouette edge detection:
492         //----------------------------------------------------------
493
494         if (G.debug & G_DEBUG_FREESTYLE) {
495                 cout << "\n===  Detecting silhouette edges  ===" << endl;
496         }
497         _Chrono.start();
498
499         edgeDetector.setViewpoint(Vec3r(vp));
500         edgeDetector.enableOrthographicProjection(proj[3][3] != 0.0);
501         edgeDetector.enableRidgesAndValleysFlag(_ComputeRidges);
502         edgeDetector.enableSuggestiveContours(_ComputeSuggestive);
503         edgeDetector.enableMaterialBoundaries(_ComputeMaterialBoundaries);
504         edgeDetector.enableFaceSmoothness(_EnableFaceSmoothness);
505         edgeDetector.setCreaseAngle(_creaseAngle);
506         edgeDetector.setSphereRadius(_sphereRadius);
507         edgeDetector.setSuggestiveContourKrDerivativeEpsilon(_suggestiveContourKrDerivativeEpsilon);
508         edgeDetector.setRenderMonitor(_pRenderMonitor);
509         edgeDetector.processShapes(*_winged_edge);
510
511         real duration = _Chrono.stop();
512         if (G.debug & G_DEBUG_FREESTYLE) {
513                 printf("Feature lines    : %lf\n", duration);
514         }
515
516         if (_pRenderMonitor->testBreak())
517                 return;
518
519         // Builds the view map structure from the flagged WSEdge structure:
520         //----------------------------------------------------------
521         ViewMapBuilder vmBuilder;
522         vmBuilder.setEnableQI(_EnableQI);
523         vmBuilder.setViewpoint(Vec3r(vp));
524         vmBuilder.setTransform(mv, proj, viewport, _pView->GetFocalLength(), _pView->GetAspect(), _pView->GetFovyRadian());
525         vmBuilder.setFrustum(_pView->znear(), _pView->zfar());
526         vmBuilder.setGrid(&_Grid);
527         vmBuilder.setRenderMonitor(_pRenderMonitor);
528
529         // Builds a tesselated form of the silhouette for display purpose:
530         //---------------------------------------------------------------
531         ViewMapTesselator3D sTesselator3d;
532 #if 0
533         ViewMapTesselator2D sTesselator2d;
534         sTesselator2d.setNature(_edgeTesselationNature);
535 #endif
536         sTesselator3d.setNature(_edgeTesselationNature);
537
538         if (G.debug & G_DEBUG_FREESTYLE) {
539                 cout << "\n===  Building the view map  ===" << endl;
540         }
541         _Chrono.start();
542         // Build View Map
543         _ViewMap = vmBuilder.BuildViewMap(*_winged_edge, _VisibilityAlgo, _EPSILON, _RootNode->bbox(), _SceneNumFaces);
544         _ViewMap->setScene3dBBox(_RootNode->bbox());
545
546         if (G.debug & G_DEBUG_FREESTYLE) {
547                 printf("ViewMap edge count : %i\n", _ViewMap->viewedges_size());
548         }
549
550         // Tesselate the 3D edges:
551         _SilhouetteNode = sTesselator3d.Tesselate(_ViewMap);
552         _SilhouetteNode->addRef();
553
554         // Tesselate 2D edges
555 #if 0
556         _ProjectedSilhouette = sTesselator2d.Tesselate(_ViewMap);
557         _ProjectedSilhouette->addRef();
558 #endif
559
560         duration = _Chrono.stop();
561         if (G.debug & G_DEBUG_FREESTYLE) {
562                 printf("ViewMap building : %lf\n", duration);
563         }
564
565         _pView->AddSilhouette(_SilhouetteNode);
566 #if 0
567         _pView->AddSilhouette(_WRoot);
568         _pView->Add2DSilhouette(_ProjectedSilhouette);
569         _pView->Add2DVisibleSilhouette(_VisibleProjectedSilhouette);
570 #endif
571         _pView->AddDebug(_DebugNode);
572
573         // Draw the steerable density map:
574         //--------------------------------
575         if (_ComputeSteerableViewMap) {
576                 ComputeSteerableViewMap();
577         }
578         // Reset Style modules modification flags
579         resetModified(true);
580
581         DeleteWingedEdge();
582 }
583
584 void Controller::ComputeSteerableViewMap()
585 {
586 #if 0  //soc
587         if ((!_Canvas) || (!_ViewMap))
588                 return;
589
590         // Build 4 nodes containing the edges in the 4 directions
591         NodeGroup *ng[Canvas::NB_STEERABLE_VIEWMAP];
592         unsigned i;
593         real c = 32.0f/255.0f; // see SteerableViewMap::readSteerableViewMapPixel() for information about this 32.
594         for (i = 0; i < Canvas::NB_STEERABLE_VIEWMAP; ++i) {
595                 ng[i] = new NodeGroup;
596         }
597         NodeShape *completeNS = new NodeShape;
598         completeNS->material().setDiffuse(c,c,c,1);
599         ng[Canvas::NB_STEERABLE_VIEWMAP-1]->AddChild(completeNS);
600         SteerableViewMap * svm = _Canvas->getSteerableViewMap();
601         svm->Reset();
602
603         ViewMap::fedges_container& fedges = _ViewMap->FEdges();
604         LineRep * fRep;
605         NodeShape *ns;
606         for (ViewMap::fedges_container::iterator f = fedges.begin(), fend = fedges.end();
607              f != fend;
608              ++f)
609         {
610                 if ((*f)->viewedge()->qi() != 0)
611                         continue;
612                 fRep = new LineRep((*f)->vertexA()->point2d(), (*f)->vertexB()->point2d());
613                 completeNS->AddRep(fRep); // add to the complete map anyway
614                 double *oweights = svm->AddFEdge(*f);
615                 for (i = 0; i < (Canvas::NB_STEERABLE_VIEWMAP - 1); ++i) {
616                         ns = new NodeShape;
617                         double wc = oweights[i]*c;
618                         if (oweights[i] == 0)
619                                 continue;
620                         ns->material().setDiffuse(wc, wc, wc, 1);
621                         ns->AddRep(fRep);
622                         ng[i]->AddChild(ns);
623                 }
624         }
625
626         GrayImage *img[Canvas::NB_STEERABLE_VIEWMAP];
627         //#ifdef WIN32
628         QGLBasicWidget offscreenBuffer(_pView, "SteerableViewMap", _pView->width(), _pView->height());
629         QPixmap pm;
630         QImage qimg;
631         for (i = 0; i < Canvas::NB_STEERABLE_VIEWMAP; ++i) {
632                 offscreenBuffer.AddNode(ng[i]);
633 #if 0
634                 img[i] = new GrayImage(_pView->width(), _pView->height());
635                 offscreenBuffer.readPixels(0,0,_pView->width(), _pView->height(), img[i]->getArray());
636 #endif
637                 pm = offscreenBuffer.renderPixmap(_pView->width(), _pView->height());
638
639                 if (pm.isNull()) {
640                         if (G.debug & G_DEBUG_FREESTYLE) {
641                                 cout << "BuildViewMap Warning: couldn't render the steerable ViewMap" << endl;
642                         }
643                 }
644                 //pm.save(QString("steerable") + QString::number(i) + QString(".bmp"), "BMP");
645                 // FIXME!! Lost of time !
646                 qimg = pm.toImage();
647                 // FIXME !! again!
648                 img[i] = new GrayImage(_pView->width(), _pView->height());
649                 for (unsigned int y = 0; y < img[i]->height(); ++y) {
650                         for (unsigned int x = 0; x < img[i]->width(); ++x) {
651                                 //img[i]->setPixel(x, y, (float)qGray(qimg.pixel(x, y)) / 255.0f);
652                                 img[i]->setPixel(x, y, (float)qGray(qimg.pixel(x, y)));
653                                 //float c = qGray(qimg.pixel(x, y));
654                                 //img[i]->setPixel(x, y, qGray(qimg.pixel(x, y)));
655                         }
656                 }
657                 offscreenBuffer.DetachNode(ng[i]);
658                 ng[i]->destroy();
659                 delete ng[i];
660                 // check
661 #if 0
662                 qimg = QImage(_pView->width(), _pView->height(), 32);
663                 for (unsigned int y = 0; y < img[i]->height(); ++y) {
664                         for (unsigned int x = 0; x < img[i]->width(); ++x) {
665                                 float v = img[i]->pixel(x, y);
666                                 qimg.setPixel(x, y, qRgb(v, v, v));
667                         }
668                 }
669                 qimg.save(QString("newsteerable") + QString::number(i) + QString(".bmp"), "BMP");
670 #endif
671         }
672
673
674         svm->buildImagesPyramids(img, false, 0, 1.0f);
675 #endif
676 }
677
678 void Controller::saveSteerableViewMapImages()
679 {
680         SteerableViewMap * svm = _Canvas->getSteerableViewMap();
681         if (!svm) {
682                 cerr << "the Steerable ViewMap has not been computed yet" << endl;
683                 return;
684         }
685         svm->saveSteerableViewMap();
686 }
687
688 void Controller::toggleVisibilityAlgo()
689 {
690         if (_VisibilityAlgo == ViewMapBuilder::ray_casting) {
691                 _VisibilityAlgo = ViewMapBuilder::ray_casting_fast;
692         }
693         else if (_VisibilityAlgo == ViewMapBuilder::ray_casting_fast) {
694                 _VisibilityAlgo = ViewMapBuilder::ray_casting_very_fast;
695         }
696         else {
697                 _VisibilityAlgo = ViewMapBuilder::ray_casting;
698         }
699 }
700
701 void Controller::setVisibilityAlgo(int algo)
702 {
703         switch (algo) {
704                 case FREESTYLE_ALGO_REGULAR:
705                         _VisibilityAlgo = ViewMapBuilder::ray_casting;
706                         break;
707                 case FREESTYLE_ALGO_FAST:
708                         _VisibilityAlgo = ViewMapBuilder::ray_casting_fast;
709                         break;
710                 case FREESTYLE_ALGO_VERYFAST:
711                         _VisibilityAlgo = ViewMapBuilder::ray_casting_very_fast;
712                         break;
713                 case FREESTYLE_ALGO_CULLED_ADAPTIVE_TRADITIONAL:
714                         _VisibilityAlgo = ViewMapBuilder::ray_casting_culled_adaptive_traditional;
715                         break;
716                 case FREESTYLE_ALGO_ADAPTIVE_TRADITIONAL:
717                         _VisibilityAlgo = ViewMapBuilder::ray_casting_adaptive_traditional;
718                         break;
719                 case FREESTYLE_ALGO_CULLED_ADAPTIVE_CUMULATIVE:
720                         _VisibilityAlgo = ViewMapBuilder::ray_casting_culled_adaptive_cumulative;
721                         break;
722                 case FREESTYLE_ALGO_ADAPTIVE_CUMULATIVE:
723                         _VisibilityAlgo = ViewMapBuilder::ray_casting_adaptive_cumulative;
724                         break;
725         }
726 }
727
728 int Controller::getVisibilityAlgo()
729 {
730         switch (_VisibilityAlgo) {
731                 case ViewMapBuilder::ray_casting:
732                         return FREESTYLE_ALGO_REGULAR;
733                 case ViewMapBuilder::ray_casting_fast:
734                         return FREESTYLE_ALGO_FAST;
735                 case ViewMapBuilder::ray_casting_very_fast:
736                         return FREESTYLE_ALGO_VERYFAST;
737                 case ViewMapBuilder::ray_casting_culled_adaptive_traditional:
738                         return FREESTYLE_ALGO_CULLED_ADAPTIVE_TRADITIONAL;
739                 case ViewMapBuilder::ray_casting_adaptive_traditional:
740                         return FREESTYLE_ALGO_ADAPTIVE_TRADITIONAL;
741                 case ViewMapBuilder::ray_casting_culled_adaptive_cumulative:
742                         return FREESTYLE_ALGO_CULLED_ADAPTIVE_CUMULATIVE;
743                 case ViewMapBuilder::ray_casting_adaptive_cumulative:
744                         return FREESTYLE_ALGO_ADAPTIVE_CUMULATIVE;
745         }
746
747         // ray_casting_adaptive_traditional is the most exact replacement
748         // for legacy code
749         return FREESTYLE_ALGO_ADAPTIVE_TRADITIONAL;
750 }
751
752 void Controller::setQuantitativeInvisibility(bool iBool)
753 {
754         _EnableQI = iBool;
755 }
756
757 bool Controller::getQuantitativeInvisibility() const
758 {
759         return _EnableQI;
760 }
761
762 void Controller::setFaceSmoothness(bool iBool)
763 {
764         _EnableFaceSmoothness = iBool;
765 }
766
767 bool Controller::getFaceSmoothness() const
768 {
769         return _EnableFaceSmoothness;
770 }
771
772 void Controller::setComputeRidgesAndValleysFlag(bool iBool)
773 {
774         _ComputeRidges = iBool;
775 }
776
777 bool Controller::getComputeRidgesAndValleysFlag() const
778 {
779         return _ComputeRidges;
780 }
781
782 void Controller::setComputeSuggestiveContoursFlag(bool b)
783 {
784         _ComputeSuggestive = b;
785 }
786
787 bool Controller::getComputeSuggestiveContoursFlag() const
788 {
789         return _ComputeSuggestive;
790 }
791
792 void Controller::setComputeMaterialBoundariesFlag(bool b)
793 {
794         _ComputeMaterialBoundaries = b;
795 }
796
797 bool Controller::getComputeMaterialBoundariesFlag() const
798 {
799         return _ComputeMaterialBoundaries;
800 }
801
802 void Controller::setComputeSteerableViewMapFlag(bool iBool)
803 {
804         _ComputeSteerableViewMap = iBool;
805 }
806
807 bool Controller::getComputeSteerableViewMapFlag() const
808 {
809         return _ComputeSteerableViewMap;
810 }
811
812 void Controller::DrawStrokes()
813 {
814         if (_ViewMap == 0)
815                 return;
816
817         if (G.debug & G_DEBUG_FREESTYLE) {
818                 cout << "\n===  Stroke drawing  ===" << endl;
819         }
820         _Chrono.start();
821         _Canvas->Draw();
822         real d = _Chrono.stop();
823         if (G.debug & G_DEBUG_FREESTYLE) {
824                 cout << "Strokes generation  : " << d << endl;
825                 cout << "Stroke count  : " << _Canvas->stroke_count << endl;
826         }
827         resetModified();
828         DeleteViewMap();
829 }
830
831 void Controller::ResetRenderCount()
832 {
833         _render_count = 0;
834 }
835
836 Render *Controller::RenderStrokes(Render *re, bool render)
837 {
838         _Chrono.start();
839         BlenderStrokeRenderer *blenderRenderer = new BlenderStrokeRenderer(re, ++_render_count);
840         if (render)
841                 _Canvas->Render(blenderRenderer);
842         real d = _Chrono.stop();
843         if (G.debug & G_DEBUG_FREESTYLE) {
844                 cout << "Temporary scene generation: " << d << endl;
845         }
846         _Chrono.start();
847         Render *freestyle_render = blenderRenderer->RenderScene(re, render);
848         d = _Chrono.stop();
849         if (G.debug & G_DEBUG_FREESTYLE) {
850                 cout << "Stroke rendering  : " << d << endl;
851         }
852         delete blenderRenderer;
853
854         return freestyle_render;
855 }
856
857 void Controller::InsertStyleModule(unsigned index, const char *iFileName)
858 {
859         if (!BLI_testextensie(iFileName, ".py")) {
860                 cerr << "Error: Cannot load \"" << string(iFileName) << "\", unknown extension" << endl;
861                 return;
862         }
863
864         StyleModule *sm = new StyleModule(iFileName, _inter);
865         _Canvas->InsertStyleModule(index, sm);
866 }
867
868 void Controller::InsertStyleModule(unsigned index, const char *iName, struct Text *iText)
869 {
870         StyleModule *sm = new BlenderStyleModule(iText, iName, _inter);
871         _Canvas->InsertStyleModule(index, sm);
872 }
873
874 void Controller::AddStyleModule(const char *iFileName)
875 {
876         //_pStyleWindow->Add(iFileName);
877 }
878
879 void Controller::RemoveStyleModule(unsigned index)
880 {
881         _Canvas->RemoveStyleModule(index);
882 }
883
884 void Controller::Clear()
885 {
886         _Canvas->Clear();
887 }
888
889 void Controller::ReloadStyleModule(unsigned index, const char * iFileName)
890 {
891         StyleModule *sm = new StyleModule(iFileName, _inter);
892         _Canvas->ReplaceStyleModule(index, sm);
893 }
894
895 void Controller::SwapStyleModules(unsigned i1, unsigned i2)
896 {
897         _Canvas->SwapStyleModules(i1, i2);
898 }
899
900 void Controller::toggleLayer(unsigned index, bool iDisplay)
901 {
902         _Canvas->setVisible(index, iDisplay);
903 }
904
905 void Controller::setModified(unsigned index, bool iMod)
906 {
907         //_pStyleWindow->setModified(index, iMod);
908         _Canvas->setModified(index, iMod);
909         updateCausalStyleModules(index + 1);
910 }
911
912 void Controller::updateCausalStyleModules(unsigned index)
913 {
914         vector<unsigned> vec;
915         _Canvas->causalStyleModules(vec, index);
916         for (vector<unsigned>::const_iterator it = vec.begin(); it != vec.end(); it++) {
917                 //_pStyleWindow->setModified(*it, true);
918                 _Canvas->setModified(*it, true);
919         }
920 }
921
922 void Controller::resetModified(bool iMod)
923 {
924         //_pStyleWindow->resetModified(iMod);
925         _Canvas->resetModified(iMod);
926 }
927
928 NodeGroup * Controller::BuildRep(vector<ViewEdge*>::iterator vedges_begin, vector<ViewEdge*>::iterator vedges_end)
929 {
930         ViewMapTesselator2D tesselator2D;
931         FrsMaterial mat;
932         mat.setDiffuse(1, 1, 0.3, 1);
933         tesselator2D.setFrsMaterial(mat);
934
935         return (tesselator2D.Tesselate(vedges_begin, vedges_end));
936 }
937
938 void Controller::toggleEdgeTesselationNature(Nature::EdgeNature iNature)
939 {
940         _edgeTesselationNature ^= (iNature);
941         ComputeViewMap();
942 }
943
944 void Controller::setModelsDir(const string& dir)
945 {
946         //_current_dirs->setValue("models/dir", dir);
947 }
948
949 string Controller::getModelsDir() const
950 {
951         string dir = ".";
952         //_current_dirs->getValue("models/dir", dir);
953         return dir;
954 }
955
956 void Controller::setModulesDir(const string& dir)
957 {
958         //_current_dirs->setValue("modules/dir", dir);
959 }
960
961 string Controller::getModulesDir() const
962 {
963         string dir = ".";
964         //_current_dirs->getValue("modules/dir", dir);
965         return dir;
966 }
967
968 void Controller::resetInterpreter()
969 {
970         if (_inter)
971                 _inter->reset();
972 }
973
974
975 void Controller::displayDensityCurves(int x, int y)
976 {
977         SteerableViewMap * svm = _Canvas->getSteerableViewMap();
978         if (!svm)
979                 return;
980
981         unsigned int i, j;
982         typedef vector<Vec3r> densityCurve;
983         vector<densityCurve> curves(svm->getNumberOfOrientations() + 1);
984         vector<densityCurve> curvesDirection(svm->getNumberOfPyramidLevels());
985
986         // collect the curves values
987         unsigned nbCurves = svm->getNumberOfOrientations() + 1;
988         unsigned nbPoints = svm->getNumberOfPyramidLevels();
989         if (!nbPoints)
990                 return;
991
992         // build the density/nbLevels curves for each orientation
993         for (i = 0; i < nbCurves; ++i) {
994                 for (j = 0; j < nbPoints; ++j) {
995                         curves[i].push_back(Vec3r(j, svm->readSteerableViewMapPixel(i, j, x, y), 0));
996                 }
997         }
998         // build the density/nbOrientations curves for each level
999         for (i = 0; i < nbPoints; ++i) {
1000                 for (j = 0; j < nbCurves; ++j) {
1001                         curvesDirection[i].push_back(Vec3r(j, svm->readSteerableViewMapPixel(j, i, x, y), 0));
1002                 }
1003         }
1004
1005         // display the curves
1006 #if 0
1007         for (i = 0; i < nbCurves; ++i)
1008                 _pDensityCurvesWindow->setOrientationCurve(i, Vec2d(0, 0), Vec2d(nbPoints, 1), curves[i], "scale", "density");
1009         for (i = 1; i <= 8; ++i)
1010                 _pDensityCurvesWindow->setLevelCurve(i, Vec2d(0, 0), Vec2d(nbCurves, 1), curvesDirection[i],
1011                                                      "orientation", "density");
1012         _pDensityCurvesWindow->show();
1013 #endif
1014 }
1015
1016 void Controller::init_options()
1017 {
1018         // from AppOptionsWindow.cpp
1019         // Default init options
1020
1021         Config::Path * cpath = Config::Path::getInstance();
1022
1023         // Directories
1024         ViewMapIO::Options::setModelsPath(cpath->getModelsPath());
1025         PythonInterpreter::Options::setPythonPath(cpath->getPythonPath());
1026         TextureManager::Options::setPatternsPath(cpath->getPatternsPath());
1027         TextureManager::Options::setBrushesPath(cpath->getModelsPath());
1028
1029         // ViewMap Format
1030         ViewMapIO::Options::rmFlags(ViewMapIO::Options::FLOAT_VECTORS);
1031         ViewMapIO::Options::rmFlags(ViewMapIO::Options::NO_OCCLUDERS);
1032         setComputeSteerableViewMapFlag(false);
1033
1034         // Visibility
1035         setQuantitativeInvisibility(true);
1036
1037         // soc: initialize canvas
1038         _Canvas->init();
1039
1040         // soc: initialize passes
1041         setPassDiffuse(NULL, 0, 0);
1042         setPassZ(NULL, 0, 0);
1043 }
1044
1045 } /* namespace Freestyle */