A few attempts to reduce the amount of memory consumption in Freestyle.
[blender-staging.git] / source / blender / freestyle / intern / application / Controller.cpp
1
2 //
3 //  Copyright (C) : Please refer to the COPYRIGHT file distributed 
4 //   with this source distribution. 
5 //
6 //  This program is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU General Public License
8 //  as published by the Free Software Foundation; either version 2
9 //  of the License, or (at your option) any later version.
10 //
11 //  This program is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 //  GNU General Public License for more details.
15 //
16 //  You should have received a copy of the GNU General Public License
17 //  along with this program; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19 //
20 ///////////////////////////////////////////////////////////////////////////////
21
22 // Must be included before any QT header, because of moc
23 #include "../system/PythonInterpreter.h"
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
33
34 #include "../system/StringUtils.h"
35 #include "../scene_graph/NodeShape.h"
36 #include "../scene_graph/NodeTransform.h"
37 #include "../scene_graph/NodeDrawingStyle.h"
38 #include "../winged_edge/WingedEdgeBuilder.h"
39 #include "../winged_edge/WEdge.h"
40 #include "../scene_graph/VertexRep.h"
41 #include "../winged_edge/WXEdgeBuilder.h"
42 #include "../scene_graph/ScenePrettyPrinter.h"
43 #include "../winged_edge/WFillGrid.h"
44
45 #include "../view_map/ViewMapTesselator.h"
46 #include "../stroke/StrokeTesselator.h"
47 #include "../view_map/ViewMapIO.h"
48 #include "Controller.h"
49 #include "../view_map/ViewMap.h"
50 #include "../winged_edge/Curvature.h"
51 #include "../image/Image.h"
52 #include "../view_map/SteerableViewMap.h"
53 #include "../stroke/PSStrokeRenderer.h"
54 #include "../stroke/TextStrokeRenderer.h"
55 #include "../stroke/StyleModule.h"
56
57 #include "../system/StringUtils.h"
58
59 #include "../blender_interface/BlenderFileLoader.h"
60 #include "../blender_interface/BlenderStrokeRenderer.h"
61 #include "../blender_interface/BlenderStyleModule.h"
62
63 #ifdef __cplusplus
64 extern "C" {
65 #endif
66
67         #include "../../FRS_freestyle.h"
68
69 #ifdef __cplusplus
70 }
71 #endif
72
73
74
75 Controller::Controller()
76 {
77         
78   const string sep(Config::DIR_SEP.c_str());
79   //const string filename = Config::Path::getInstance()->getHomeDir() + sep + Config::OPTIONS_DIR + sep + Config::OPTIONS_CURRENT_DIRS_FILE;
80   //_current_dirs = new ConfigIO(filename, Config::APPLICATION_NAME + "CurrentDirs", true);
81
82   _RootNode = new NodeGroup;
83   _RootNode->addRef();
84   
85   _SilhouetteNode = NULL;
86   //_ProjectedSilhouette = NULL;
87   //_VisibleProjectedSilhouette = NULL;
88   
89   _DebugNode = new NodeGroup;
90   _DebugNode->addRef();
91
92   _winged_edge = NULL;
93   
94   _pView = NULL;
95
96   _edgeTesselationNature = (Nature::SILHOUETTE | Nature::BORDER | Nature::CREASE);
97
98   _ProgressBar = new ProgressBar;
99   _SceneNumFaces = 0;
100   _minEdgeSize = DBL_MAX;
101   _EPSILON = 1e-6;
102   _bboxDiag = 0;
103   
104   _ViewMap = 0;
105
106   _Canvas = 0;
107
108   _VisibilityAlgo = ViewMapBuilder::ray_casting;
109   //_VisibilityAlgo = ViewMapBuilder::ray_casting_fast;
110
111   _Canvas = new AppCanvas;
112
113   _inter = new PythonInterpreter();
114   _EnableQI = true;
115   _ComputeRidges = true;
116   _ComputeSteerableViewMap = false;
117   _ComputeSuggestive = true;
118   _ComputeMaterialBoundaries = true;
119   _sphereRadius = 1.0;
120   _creaseAngle = 134.43;
121
122         init_options();
123 }
124
125 Controller::~Controller()
126 {
127   if(NULL != _RootNode)
128     {
129       int ref = _RootNode->destroy();
130       if(0 == ref)
131         delete _RootNode;
132     }
133   
134   if(NULL != _SilhouetteNode)
135     {
136       int ref = _SilhouetteNode->destroy();
137       if(0 == ref)
138         delete _SilhouetteNode;
139     }
140   
141   if(NULL != _DebugNode)
142     {
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     {
155       delete _ViewMap;
156       _ViewMap = 0;
157     }
158
159   if(0 != _Canvas)
160     {
161       delete _Canvas;
162       _Canvas = 0;
163     }
164
165   if (_inter) {
166     delete _inter;
167     _inter = NULL;
168   }
169
170   //delete _current_dirs;
171 }
172
173 void Controller::setView(AppView *iView)
174 {
175   if(NULL == iView)
176     return;
177   
178   _pView = iView;
179   _Canvas->setViewer(_pView);
180 }
181
182 void Controller::setPassDiffuse(float *buf, int width, int height)
183 {
184   AppCanvas *app_canvas = dynamic_cast<AppCanvas *>(_Canvas);
185   assert(app_canvas != 0);
186   app_canvas->setPassDiffuse(buf, width, height);
187 }
188
189 void Controller::setPassZ(float *buf, int width, int height)
190 {
191   AppCanvas *app_canvas = dynamic_cast<AppCanvas *>(_Canvas);
192   assert(app_canvas != 0);
193   app_canvas->setPassZ(buf, width, height);
194 }
195
196 void Controller::setContext(bContext *C)
197 {
198   PythonInterpreter* py_inter = dynamic_cast<PythonInterpreter*>(_inter);
199   assert(py_inter != 0);
200   py_inter->setContext(C);
201 }
202
203 int Controller::LoadMesh(Render *re, SceneRenderLayer* srl)
204 {
205   
206   BlenderFileLoader loader(re, srl);
207   
208   _Chrono.start();
209   
210   NodeGroup *blenderScene = loader.Load();
211
212   if (blenderScene == NULL) {
213         cout << "Cannot load scene" << endl;
214     return 1;
215   }
216
217         if( blenderScene->numberOfChildren() < 1) {
218                 cout << "Empty scene" << endl;
219                 blenderScene->destroy();
220                 delete blenderScene;
221                 return 1;
222         }
223
224           cout << "Scene loaded" << endl;
225   printf("Mesh cleaning    : %lf\n", _Chrono.stop());
226   _SceneNumFaces += loader.numFacesRead();
227
228   if(loader.minEdgeSize() < _minEdgeSize)
229     {
230       _minEdgeSize = loader.minEdgeSize();
231     }
232
233   // DEBUG
234   // ScenePrettyPrinter spp;
235   // blenderScene->accept(spp);
236         
237   _RootNode->AddChild(blenderScene);
238   _RootNode->UpdateBBox(); // FIXME: Correct that by making a Renderer to compute the bbox
239
240   _pView->setModel(_RootNode);
241   //_pView->FitBBox();
242
243
244   _Chrono.start();
245
246   
247   WXEdgeBuilder wx_builder;
248   blenderScene->accept(wx_builder);
249   _winged_edge = wx_builder.getWingedEdge();
250
251   printf("WEdge building   : %lf\n", _Chrono.stop());
252
253  _Chrono.start();
254
255   _Grid.clear();
256   Vec3r size;
257   for(unsigned int i=0; i<3; i++)
258     {
259       size[i] = fabs(_RootNode->bbox().getMax()[i] - _RootNode->bbox().getMin()[i]);
260       size[i] += size[i]/10.0; // let make the grid 1/10 bigger to avoid numerical errors while computing triangles/cells intersections
261       if(size[i]==0){
262           cout << "Warning: the bbox size is 0 in dimension "<<i<<endl;
263       }
264     }
265   _Grid.configure(Vec3r(_RootNode->bbox().getMin() - size / 20.0), size,
266                   _SceneNumFaces);
267
268   // Fill in the grid:
269   WFillGrid fillGridRenderer(&_Grid, _winged_edge);
270   fillGridRenderer.fillGrid();
271
272   printf("Grid building    : %lf\n", _Chrono.stop());
273   
274   // DEBUG
275   _Grid.displayDebug();
276   //  
277   // _pView->setDebug(_DebugNode);
278
279   //delete stuff
280   //  if(0 != ws_builder)
281   //    {
282   //      delete ws_builder;
283   //      ws_builder = 0;
284   //    }
285
286         //soc QFileInfo qfi(iFileName);
287         //soc string basename((const char*)qfi.fileName().toAscii().data());
288         // char cleaned[FILE_MAX];
289         // BLI_strncpy(cleaned, iFileName, FILE_MAX);
290         // BLI_cleanup_file(NULL, cleaned);
291         // string basename = StringUtils::toAscii( string(cleaned) );
292
293   _ListOfModels.push_back("Blender_models");
294
295   cout << "Triangles nb     : " << _SceneNumFaces << endl;
296   _bboxDiag = (_RootNode->bbox().getMax()-_RootNode->bbox().getMin()).norm();
297   cout << "Bounding Box     : " << _bboxDiag << endl;
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         {
327                 int ref = _RootNode->destroy();
328                 if(0 == ref)
329                         _RootNode->addRef();
330                 _RootNode->clearBBox();
331         }
332 }
333
334 void Controller::DeleteWingedEdge()
335 {
336         if(_winged_edge)
337         {
338                 delete _winged_edge;
339                 _winged_edge = NULL;
340         }
341
342         // clears the grid
343         _Grid.clear();
344         _SceneNumFaces = 0;
345         _minEdgeSize = DBL_MAX;
346 }
347
348 void Controller::DeleteViewMap()
349 {
350         _pView->DetachSilhouette();
351         if (NULL != _SilhouetteNode)
352         {
353                 int ref = _SilhouetteNode->destroy();
354                 if(0 == ref) {
355                         delete _SilhouetteNode;
356                         _SilhouetteNode = NULL;
357                 }
358         }
359
360   //  if(NULL != _ProjectedSilhouette)
361   //    {
362   //      int ref = _ProjectedSilhouette->destroy();
363   //      if(0 == ref)
364   //    {
365   //      delete _ProjectedSilhouette;
366   //      _ProjectedSilhouette = NULL;
367   //    }
368   //    }
369   //  if(NULL != _VisibleProjectedSilhouette)
370   //    {
371   //      int ref = _VisibleProjectedSilhouette->destroy();
372   //      if(0 == ref)
373   //    {
374   //      delete _VisibleProjectedSilhouette;
375   //      _VisibleProjectedSilhouette = NULL;
376   //    }
377   //  }  
378
379         _pView->DetachDebug();
380         if(NULL != _DebugNode) {
381       int ref = _DebugNode->destroy();
382       if(0 == ref)
383                   _DebugNode->addRef();
384     }
385
386         if(NULL != _ViewMap) {
387       delete _ViewMap;
388       _ViewMap = 0;
389     }
390 }
391
392 void Controller::ComputeViewMap()
393 {
394
395   if (!_ListOfModels.size())
396     return;
397   
398   if(NULL != _ViewMap)
399     {
400       delete _ViewMap;
401       _ViewMap = 0;
402     }
403
404   _pView->DetachDebug();
405   if(NULL != _DebugNode)
406     {
407       int ref = _DebugNode->destroy();
408       if(0 == ref)
409         _DebugNode->addRef();
410     }
411   
412
413   _pView->DetachSilhouette();
414   if (NULL != _SilhouetteNode)
415     {
416       int ref = _SilhouetteNode->destroy();
417       if(0 == ref)
418         delete _SilhouetteNode;
419     }
420   //  if(NULL != _ProjectedSilhouette)
421   //    {
422   //      int ref = _ProjectedSilhouette->destroy();
423   //      if(0 == ref)
424   //    delete _ProjectedSilhouette;
425   //    }
426   //  if(NULL != _VisibleProjectedSilhouette)
427   //    {
428   //      int ref = _VisibleProjectedSilhouette->destroy();
429   //      if(0 == ref)
430   //    {
431   //      delete _VisibleProjectedSilhouette;
432   //      _VisibleProjectedSilhouette = 0;
433   //    }
434   //  }
435   
436   // retrieve the 3D viewpoint and transformations information
437   //----------------------------------------------------------
438   // Save the viewpoint context at the view level in order 
439   // to be able to restore it later:
440
441   // Restore the context of view:
442   // we need to perform all these operations while the 
443   // 3D context is on.
444   Vec3r vp( freestyle_viewpoint[0], freestyle_viewpoint[1], freestyle_viewpoint[2]);
445
446         //cout << "mv" << endl;
447         real mv[4][4];
448         for( int i= 0; i < 4; i++) {
449                 for( int j= 0; j < 4; j++) {
450                         mv[i][j] = freestyle_mv[i][j];
451                         //cout << mv[i][j] << " ";
452                 }
453         //      cout << endl;
454         }
455         
456         //cout << "\nproj" << endl;
457         real proj[4][4];
458         for( int i= 0; i < 4; i++) {
459                 for( int j= 0; j < 4; j++) {
460                         proj[i][j] = freestyle_proj[i][j];
461                         //cout << proj[i][j] << " ";
462                 }
463                 //cout << endl;
464         }
465
466         int viewport[4];
467         for( int i= 0; i < 4; i++)
468                 viewport[i] = freestyle_viewport[i];
469         
470         //cout << "\nfocal:" << _pView->GetFocalLength() << endl << endl;
471
472
473
474   // Flag the WXEdge structure for silhouette edge detection:
475   //----------------------------------------------------------
476
477         cout << "\n===  Detecting silhouette edges  ===" << endl;
478   _Chrono.start();
479  
480   edgeDetector.setViewpoint(Vec3r(vp));
481   edgeDetector.enableOrthographicProjection(proj[3][3] != 0.0);
482   edgeDetector.enableRidgesAndValleysFlag(_ComputeRidges);
483   edgeDetector.enableSuggestiveContours(_ComputeSuggestive);
484   edgeDetector.enableMaterialBoundaries(_ComputeMaterialBoundaries);
485   edgeDetector.setCreaseAngle(_creaseAngle);
486   edgeDetector.setSphereRadius(_sphereRadius);
487   edgeDetector.setSuggestiveContourKrDerivativeEpsilon(_suggestiveContourKrDerivativeEpsilon);
488   edgeDetector.processShapes(*_winged_edge);
489
490   real duration = _Chrono.stop();
491   printf("Feature lines    : %lf\n", duration);
492
493   // Builds the view map structure from the flagged WSEdge structure:
494   //----------------------------------------------------------
495   ViewMapBuilder vmBuilder;
496   vmBuilder.setEnableQI(_EnableQI);
497   vmBuilder.setViewpoint(Vec3r(vp));
498   vmBuilder.setTransform( mv, proj,viewport, _pView->GetFocalLength(), _pView->GetAspect(), _pView->GetFovyRadian());
499   vmBuilder.setFrustum(_pView->znear(), _pView->zfar());  
500   vmBuilder.setGrid(&_Grid);
501   
502   // Builds a tesselated form of the silhouette for display purpose:
503   //---------------------------------------------------------------
504   ViewMapTesselator3D sTesselator3d;
505   //ViewMapTesselator2D sTesselator2d;
506   //sTesselator2d.setNature(_edgeTesselationNature);
507   sTesselator3d.setNature(_edgeTesselationNature);
508     
509         cout << "\n===  Building the view map  ===" << endl;
510   _Chrono.start();
511   // Build View Map
512   _ViewMap = vmBuilder.BuildViewMap(*_winged_edge, _VisibilityAlgo, _EPSILON);
513   _ViewMap->setScene3dBBox(_RootNode->bbox());
514   
515         printf("ViewMap edge count : %i\n", _ViewMap->viewedges_size() );
516
517   //Tesselate the 3D edges:
518   _SilhouetteNode = sTesselator3d.Tesselate(_ViewMap);
519   _SilhouetteNode->addRef();
520   
521   // Tesselate 2D edges
522   //  _ProjectedSilhouette = sTesselator2d.Tesselate(_ViewMap);
523   //  _ProjectedSilhouette->addRef();
524   
525   duration = _Chrono.stop();
526   printf("ViewMap building : %lf\n", duration);
527
528   
529   _pView->AddSilhouette(_SilhouetteNode);
530   //_pView->AddSilhouette(_WRoot);
531   //_pView->Add2DSilhouette(_ProjectedSilhouette);
532   //_pView->Add2DVisibleSilhouette(_VisibleProjectedSilhouette);  
533   _pView->AddDebug(_DebugNode);
534
535   // Draw the steerable density map:
536   //--------------------------------
537   if(_ComputeSteerableViewMap){
538     ComputeSteerableViewMap();
539   }
540   // Reset Style modules modification flags
541   resetModified(true);
542
543   DeleteWingedEdge();
544 }
545
546 void Controller::ComputeSteerableViewMap(){
547 //soc
548   // if((!_Canvas) || (!_ViewMap))
549   //   return;
550   //   
551   // // Build 4 nodes containing the edges in the 4 directions
552   // NodeGroup *ng[Canvas::NB_STEERABLE_VIEWMAP];
553   // unsigned i;
554   // real c = 32.f/255.f; // see SteerableViewMap::readSteerableViewMapPixel() for information about this 32.
555   // for(i=0; i<Canvas::NB_STEERABLE_VIEWMAP; ++i){
556   //   ng[i] = new NodeGroup;
557   // }
558   // NodeShape *completeNS = new NodeShape;
559   // completeNS->material().setDiffuse(c,c,c,1);
560   // ng[Canvas::NB_STEERABLE_VIEWMAP-1]->AddChild(completeNS);
561   // SteerableViewMap * svm = _Canvas->getSteerableViewMap();
562   // svm->Reset();
563   // 
564   // ViewMap::fedges_container& fedges = _ViewMap->FEdges();
565   // LineRep * fRep;
566   // NodeShape *ns;
567   // for(ViewMap::fedges_container::iterator f=fedges.begin(), fend=fedges.end();
568   // f!=fend;
569   // ++f){
570   //   if((*f)->viewedge()->qi() != 0)
571   //     continue;
572   //   fRep = new LineRep((*f)->vertexA()->point2d(),(*f)->vertexB()->point2d()) ;
573   //   completeNS->AddRep(fRep); // add to the complete map anyway
574   //   double *oweights = svm->AddFEdge(*f);
575   //   for(i=0; i<Canvas::NB_STEERABLE_VIEWMAP-1; ++i){
576   //     ns = new NodeShape;
577   //     double wc = oweights[i]*c;
578   //     if(oweights[i] == 0)
579   //       continue;
580   //     ns->material().setDiffuse(wc, wc, wc, 1);
581   //     ns->AddRep(fRep);
582   //     ng[i]->AddChild(ns);
583   //   }
584   // }
585   // 
586   // GrayImage *img[Canvas::NB_STEERABLE_VIEWMAP];
587   // //#ifdef WIN32
588   // QGLBasicWidget offscreenBuffer(_pView, "SteerableViewMap", _pView->width(), _pView->height()); 
589   // QPixmap pm;
590   // QImage qimg;
591   // for(i=0; i<Canvas::NB_STEERABLE_VIEWMAP; ++i){
592   //   offscreenBuffer.AddNode(ng[i]);
593   //   //img[i] = new GrayImage(_pView->width(), _pView->height());
594   //   //offscreenBuffer.readPixels(0,0,_pView->width(), _pView->height(), img[i]->getArray());
595   //   pm = offscreenBuffer.renderPixmap(_pView->width(), _pView->height());
596   // 
597   //   if(pm.isNull())
598   //     cout << "BuildViewMap Warning: couldn't render the steerable ViewMap" << endl;
599   //   //pm.save(QString("steerable")+QString::number(i)+QString(".bmp"), "BMP");
600   //   // FIXME!! Lost of time !
601   //   qimg = pm.toImage();
602   //   // FIXME !! again!
603   //   img[i] = new GrayImage(_pView->width(), _pView->height());
604   //   for(unsigned y=0;y<img[i]->height();++y){
605   //     for(unsigned x=0;x<img[i]->width();++x){
606   //       //img[i]->setPixel(x,y,(float)qGray(qimg.pixel(x,y))/255.f);
607   //       img[i]->setPixel(x,y,(float)qGray(qimg.pixel(x,y)));
608   //       //        float c = qGray(qimg.pixel(x,y));
609   //       //        img[i]->setPixel(x,y,qGray(qimg.pixel(x,y)));
610   //     }
611   //   }
612   //   offscreenBuffer.DetachNode(ng[i]);
613   //   ng[i]->destroy();
614   //   delete ng[i];
615   //   // check
616   //   //    qimg = QImage(_pView->width(), _pView->height(), 32);
617   //   //    for(y=0;y<img[i]->height();++y){
618   //   //      for(unsigned x=0;x<img[i]->width();++x){
619   //   //        float v = img[i]->pixel(x,y);
620   //   //        qimg.setPixel(x,y,qRgb(v,v,v));
621   //   //      }
622   //   //    }
623   //   //    qimg.save(QString("newsteerable")+QString::number(i)+QString(".bmp"), "BMP");
624   // }
625   // 
626   // 
627   // svm->buildImagesPyramids(img,false,0,1.f);
628 }
629
630 void Controller::saveSteerableViewMapImages(){
631   SteerableViewMap * svm = _Canvas->getSteerableViewMap();
632   if(!svm){
633     cerr << "the Steerable ViewMap has not been computed yet" << endl;
634     return;
635   }
636   svm->saveSteerableViewMap();
637 }
638
639 void Controller::toggleVisibilityAlgo() 
640 {
641   if(_VisibilityAlgo == ViewMapBuilder::ray_casting) {
642     _VisibilityAlgo = ViewMapBuilder::ray_casting_fast;
643   }
644   else if (_VisibilityAlgo == ViewMapBuilder::ray_casting_fast) {
645     _VisibilityAlgo = ViewMapBuilder::ray_casting_very_fast;
646   }
647   else {
648     _VisibilityAlgo = ViewMapBuilder::ray_casting;
649   }
650 }
651
652 void Controller::setQuantitativeInvisibility(bool iBool)
653 {
654   _EnableQI = iBool;
655 }
656
657 bool Controller::getQuantitativeInvisibility() const
658 {
659   return _EnableQI;
660 }
661
662 void Controller::setComputeRidgesAndValleysFlag(bool iBool){
663   _ComputeRidges = iBool;
664 }
665
666 bool Controller::getComputeRidgesAndValleysFlag() const {
667   return _ComputeRidges;
668 }
669
670 void Controller::setComputeSuggestiveContoursFlag(bool b){
671   _ComputeSuggestive = b;
672 }
673   
674 bool Controller::getComputeSuggestiveContoursFlag() const {
675   return _ComputeSuggestive;
676 }
677
678 void Controller::setComputeMaterialBoundariesFlag(bool b){
679   _ComputeMaterialBoundaries = b;
680 }
681   
682 bool Controller::getComputeMaterialBoundariesFlag() const {
683   return _ComputeMaterialBoundaries;
684 }
685
686 void Controller::setComputeSteerableViewMapFlag(bool iBool){
687   _ComputeSteerableViewMap = iBool;
688 }
689
690 bool Controller::getComputeSteerableViewMapFlag() const {
691   return _ComputeSteerableViewMap;
692 }
693
694 void Controller::DrawStrokes()
695 {
696   if(_ViewMap == 0)
697     return;
698
699   cout << "\n===  Stroke drawing  ===" << endl;
700   _Chrono.start();
701   _Canvas->Draw();
702   real d = _Chrono.stop();
703   cout << "Strokes generation  : " << d << endl;
704   cout << "Stroke count  : " << _Canvas->stroke_count << endl;
705   resetModified();
706 }
707
708 void Controller::ResetRenderCount()
709 {
710         _render_count = 0;
711 }
712
713 Render* Controller::RenderStrokes(Render *re) {
714         BlenderStrokeRenderer* blenderRenderer = new BlenderStrokeRenderer(re, ++_render_count);
715         _Canvas->Render( blenderRenderer );
716         DeleteViewMap();
717         Render* freestyle_render = blenderRenderer->RenderScene(re);
718         delete blenderRenderer;
719         
720         return freestyle_render;
721 }
722
723 void Controller::InsertStyleModule(unsigned index, const char *iFileName)
724 {
725         if( !BLI_testextensie(iFileName, ".py") ) {
726                 cerr << "Error: Cannot load \"" << StringUtils::toAscii( string(iFileName) )
727                   << "\", unknown extension" << endl;
728                   return;
729         }
730
731   StyleModule* sm = new StyleModule(iFileName, _inter);
732   _Canvas->InsertStyleModule(index, sm);
733   
734 }
735
736 void Controller::InsertStyleModule(unsigned index, const char *iName, struct Text *iText)
737 {
738         StyleModule* sm = new BlenderStyleModule(iText, iName, _inter);
739   _Canvas->InsertStyleModule(index, sm);
740 }
741
742 void Controller::AddStyleModule(const char *iFileName)
743 {
744   //_pStyleWindow->Add(iFileName);
745 }
746
747 void Controller::RemoveStyleModule(unsigned index)
748 {
749   _Canvas->RemoveStyleModule(index);
750 }
751
752 void Controller::Clear()
753 {
754   _Canvas->Clear();
755 }
756
757 void Controller::ReloadStyleModule(unsigned index, const char * iFileName)
758 {
759   StyleModule* sm = new StyleModule(iFileName, _inter);
760   _Canvas->ReplaceStyleModule(index, sm);
761 }
762
763 void Controller::SwapStyleModules(unsigned i1, unsigned i2)
764 {
765   _Canvas->SwapStyleModules(i1, i2);
766 }
767
768
769 void Controller::toggleLayer(unsigned index, bool iDisplay)
770 {
771   _Canvas->setVisible(index, iDisplay);
772 }
773
774 void Controller::setModified(unsigned index, bool iMod)
775 {
776   //_pStyleWindow->setModified(index, iMod);
777   _Canvas->setModified(index, iMod);
778   updateCausalStyleModules(index + 1);
779 }
780
781 void Controller::updateCausalStyleModules(unsigned index) {
782   vector<unsigned> vec;
783   _Canvas->causalStyleModules(vec, index);
784   for (vector<unsigned>::const_iterator it = vec.begin(); it != vec.end(); it++) {
785     //_pStyleWindow->setModified(*it, true);
786     _Canvas->setModified(*it, true);
787   }
788 }
789
790 void Controller::resetModified(bool iMod)
791 {
792   //_pStyleWindow->resetModified(iMod);
793   _Canvas->resetModified(iMod);
794 }
795
796 NodeGroup * Controller::BuildRep(vector<ViewEdge*>::iterator vedges_begin, 
797                                        vector<ViewEdge*>::iterator vedges_end)
798 {
799   ViewMapTesselator2D tesselator2D;
800   FrsMaterial mat;
801   mat.setDiffuse(1,1,0.3,1);
802   tesselator2D.setFrsMaterial(mat);
803
804   return (tesselator2D.Tesselate(vedges_begin, vedges_end));
805 }
806
807 void Controller::toggleEdgeTesselationNature(Nature::EdgeNature iNature)
808 {
809   _edgeTesselationNature ^= (iNature);
810   ComputeViewMap();
811 }
812
813 void            Controller::setModelsDir(const string& dir) {
814   //_current_dirs->setValue("models/dir", dir);
815 }
816
817 string          Controller::getModelsDir() const {
818   string dir = ".";
819   //_current_dirs->getValue("models/dir", dir);
820   return dir;
821 }
822
823 void            Controller::setModulesDir(const string& dir) {
824   //_current_dirs->setValue("modules/dir", dir);
825 }
826
827 string          Controller::getModulesDir() const {
828   string dir = ".";
829   //_current_dirs->getValue("modules/dir", dir);
830   return dir;
831 }
832
833 void            Controller::setHelpIndex(const string& index) {
834   _help_index = index;
835 }
836
837 string          Controller::getHelpIndex() const {
838   return _help_index;
839 }
840
841 void            Controller::setBrowserCmd(const string& cmd) {
842   _browser_cmd = cmd;
843 }
844
845 string          Controller::getBrowserCmd() const {
846   return _browser_cmd;
847 }
848
849 void            Controller::resetInterpreter() {
850   if (_inter)
851     _inter->reset();
852 }
853
854
855 void Controller::displayDensityCurves(int x, int y){
856   SteerableViewMap * svm = _Canvas->getSteerableViewMap();
857   if(!svm)
858     return;
859
860   unsigned i,j;
861   typedef vector<Vec3r> densityCurve;
862   vector<densityCurve> curves(svm->getNumberOfOrientations()+1);
863   vector<densityCurve> curvesDirection(svm->getNumberOfPyramidLevels());
864
865   // collect the curves values
866   unsigned nbCurves = svm->getNumberOfOrientations()+1;
867   unsigned nbPoints = svm->getNumberOfPyramidLevels();
868   if(!nbPoints)
869     return;
870
871   // build the density/nbLevels curves for each orientation
872   for(i=0;i<nbCurves; ++i){
873     for(j=0; j<nbPoints; ++j){
874       curves[i].push_back(Vec3r(j, svm->readSteerableViewMapPixel(i, j, x, y), 0));
875     }
876   }
877   // build the density/nbOrientations curves for each level
878   for(i=0;i<nbPoints; ++i){
879     for(j=0; j<nbCurves; ++j){
880       curvesDirection[i].push_back(Vec3r(j, svm->readSteerableViewMapPixel(j, i, x, y), 0));
881     }
882   }
883
884   // display the curves
885   // for(i=0; i<nbCurves; ++i)
886   //     _pDensityCurvesWindow->setOrientationCurve(i, Vec2d(0,0), Vec2d(nbPoints, 1), curves[i], "scale", "density");
887   //   for(i=1; i<=8; ++i)
888   //     _pDensityCurvesWindow->setLevelCurve(i, Vec2d(0,0), Vec2d(nbCurves, 1), curvesDirection[i], "orientation", "density");
889   //   _pDensityCurvesWindow->show();
890 }
891
892 void Controller::init_options(){
893 //      from AppOptionsWindow.cpp
894 //      Default init options
895
896         Config::Path * cpath = Config::Path::getInstance();
897         
898         // Directories
899         ViewMapIO::Options::setModelsPath( StringUtils::toAscii( cpath->getModelsPath() ) ); 
900         PythonInterpreter::Options::setPythonPath( StringUtils::toAscii( cpath->getPythonPath() ) );
901         TextureManager::Options::setPatternsPath( StringUtils::toAscii( cpath->getPatternsPath() ) );
902         TextureManager::Options::setBrushesPath( StringUtils::toAscii( cpath->getModelsPath() ) );
903
904         // ViewMap Format
905         ViewMapIO::Options::rmFlags(ViewMapIO::Options::FLOAT_VECTORS);
906         ViewMapIO::Options::rmFlags(ViewMapIO::Options::NO_OCCLUDERS);
907         setComputeSteerableViewMapFlag( false );
908
909         // Visibility
910         setQuantitativeInvisibility(true);
911
912         // soc: initialize canvas
913         _Canvas->init();
914
915         // soc: initialize passes
916         setPassDiffuse(NULL, 0, 0);
917         setPassZ(NULL, 0, 0);
918 }