soc-2008-mxcurioni: first version of lib3ds code. It does NOT work yet and has to...
[blender.git] / source / blender / freestyle / intern / app_blender / 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 "AppGLWidget.h"
30 #include "AppCanvas.h"
31 #include "AppConfig.h"
32
33
34 #include "../system/StringUtils.h"
35 #include "../scene_graph/MaxFileLoader.h"
36 #include "../scene_graph/NodeShape.h"
37 #include "../scene_graph/NodeTransform.h"
38 #include "../scene_graph/NodeDrawingStyle.h"
39 #include "../winged_edge/WingedEdgeBuilder.h"
40 #include "../winged_edge/WEdge.h"
41 #include "../scene_graph/VertexRep.h"
42 #include "../winged_edge/WXEdgeBuilder.h"
43 #include "../scene_graph/ScenePrettyPrinter.h"
44 #include "../winged_edge/WFillGrid.h"
45
46 #include "../view_map/ViewMapTesselator.h"
47 #include "../stroke/StrokeTesselator.h"
48 #include "../view_map/ViewMapIO.h"
49 #include "Controller.h"
50 #include "../view_map/ViewMap.h"
51 #include "../winged_edge/Curvature.h"
52 //#include "QGLBasicWidget.h"
53 //#include <qimage.h>
54 #include "../image/Image.h"
55 #include "../view_map/SteerableViewMap.h"
56 #include "../stroke/PSStrokeRenderer.h"
57 #include "../stroke/TextStrokeRenderer.h"
58 #include "../stroke/StyleModule.h"
59
60 #ifndef WIN32
61 //# include "GLXOffscreenBuffer.h"
62 //# include "GLXOffscreenBuffer.h"
63 #endif
64
65 #include "../system/StringUtils.h"
66
67 #include "../scene_graph/BlenderFileLoader.h"
68
69 Controller::Controller()
70 {
71         
72   const string sep(Config::DIR_SEP.c_str());
73   //const string filename = Config::Path::getInstance()->getHomeDir() + sep + Config::OPTIONS_DIR + sep + Config::OPTIONS_CURRENT_DIRS_FILE;
74   //_current_dirs = new ConfigIO(filename, Config::APPLICATION_NAME + "CurrentDirs", true);
75
76   _RootNode = new NodeGroup;
77   _RootNode->addRef();
78   
79   _SilhouetteNode = NULL;
80   //_ProjectedSilhouette = NULL;
81   //_VisibleProjectedSilhouette = NULL;
82   
83   _DebugNode = new NodeGroup;
84   _DebugNode->addRef();
85
86   _winged_edge = NULL;
87   
88   _pView = NULL;
89
90   _edgeTesselationNature = (Nature::SILHOUETTE | Nature::BORDER | Nature::CREASE);
91
92   _ProgressBar = new ProgressBar;
93   _SceneNumFaces = 0;
94   _minEdgeSize = DBL_MAX;
95   _bboxDiag = 0;
96   
97   _ViewMap = 0;
98
99   _Canvas = 0;
100
101   _VisibilityAlgo = ViewMapBuilder::ray_casting;
102   //_VisibilityAlgo = ViewMapBuilder::ray_casting_fast;
103
104   _Canvas = new AppCanvas;
105
106   _inter = new PythonInterpreter;
107   _EnableQI = true;
108   _ComputeRidges = true;
109   _ComputeSteerableViewMap = false;
110   _ComputeSuggestive = true;
111   _sphereRadius = 1.0;
112
113         init_options();
114 }
115
116 Controller::~Controller()
117 {
118   if(NULL != _RootNode)
119     {
120       int ref = _RootNode->destroy();
121       if(0 == ref)
122         delete _RootNode;
123     }
124   
125   if(NULL != _SilhouetteNode)
126     {
127       int ref = _SilhouetteNode->destroy();
128       if(0 == ref)
129         delete _SilhouetteNode;
130     }
131   
132   if(NULL != _DebugNode)
133     {
134       int ref = _DebugNode->destroy();
135       if(0 == ref)
136         delete _DebugNode;
137     }
138
139   if(_winged_edge) {
140     delete _winged_edge;
141     _winged_edge = NULL;
142   }
143
144   if(0 != _ViewMap)
145     {
146       delete _ViewMap;
147       _ViewMap = 0;
148     }
149
150   if(0 != _Canvas)
151     {
152       delete _Canvas;
153       _Canvas = 0;
154     }
155
156   if (_inter) {
157     delete _inter;
158     _inter = NULL;
159   }
160
161   //delete _current_dirs;
162 }
163
164 void Controller::setView(AppGLWidget *iView)
165 {
166   if(NULL == iView)
167     return;
168   
169   _pView = iView;
170   _Canvas->setViewer(_pView);
171 }
172
173 int Controller::LoadMesh(Render *re)
174 {
175   if (_pView)
176     _pView->setUpdateMode(false);
177   
178   BlenderFileLoader loader(re);
179   
180   _Chrono.start();
181   
182   NodeGroup *blenderScene = loader.Load();
183
184   if (blenderScene == NULL) {
185         cout << "Cannot load scene" << endl;
186     return 1;
187   }
188
189   cout << "Scene loaded\n" << endl;
190
191   printf("Mesh cleaning    : %lf\n", _Chrono.stop());
192   _SceneNumFaces += loader.numFacesRead();
193
194   if(loader.minEdgeSize() < _minEdgeSize)
195     {
196       _minEdgeSize = loader.minEdgeSize();
197       _EPSILON = _minEdgeSize*1e-6;
198       if(_EPSILON < DBL_MIN)
199         _EPSILON = 0.0;
200     }
201
202   cout << "Epsilon computed : " << _EPSILON << endl;
203
204   // DEBUG
205 //   ScenePrettyPrinter spp;
206 //   blenderScene->accept(spp);
207         
208   _RootNode->AddChild(blenderScene);
209   _RootNode->UpdateBBox(); // FIXME: Correct that by making a Renderer to compute the bbox
210
211   _pView->setModel(_RootNode);
212   //_pView->FitBBox();
213
214
215   _Chrono.start();
216
217   
218   WXEdgeBuilder wx_builder;
219   blenderScene->accept(wx_builder);
220   _winged_edge = wx_builder.getWingedEdge();
221
222   printf("WEdge building   : %lf\n", _Chrono.stop());
223
224  _Chrono.start();
225
226   _Grid.clear();
227   Vec3r size;
228   for(unsigned int i=0; i<3; i++)
229     {
230       size[i] = fabs(_RootNode->bbox().getMax()[i] - _RootNode->bbox().getMin()[i]);
231       size[i] += size[i]/10.0; // let make the grid 1/10 bigger to avoid numerical errors while computing triangles/cells intersections
232       if(size[i]==0){
233           cout << "Warning: the bbox size is 0 in dimension "<<i<<endl;
234       }
235     }
236   _Grid.configure(Vec3r(_RootNode->bbox().getMin() - size / 20.0), size,
237                   _SceneNumFaces);
238
239   // Fill in the grid:
240   WFillGrid fillGridRenderer(&_Grid, _winged_edge);
241   fillGridRenderer.fillGrid();
242
243   printf("Grid building    : %lf\n", _Chrono.stop());
244   
245   // DEBUG
246 //   _Grid.displayDebug();
247    
248   _pView->setDebug(_DebugNode);
249
250   //delete stuff
251   //  if(0 != ws_builder)
252   //    {
253   //      delete ws_builder;
254   //      ws_builder = 0;
255   //    }
256   _pView->updateGL();
257   
258
259         //soc QFileInfo qfi(iFileName);
260         //soc string basename((const char*)qfi.fileName().toAscii().data());
261         // char cleaned[FILE_MAX];
262         // BLI_strncpy(cleaned, iFileName, FILE_MAX);
263         // BLI_cleanup_file(NULL, cleaned);
264         // string basename = StringUtils::toAscii( string(cleaned) );
265
266   _ListOfModels.push_back("Blender_models");
267
268   cout << "Triangles nb     : " << _SceneNumFaces << endl;
269   _bboxDiag = (_RootNode->bbox().getMax()-_RootNode->bbox().getMin()).norm();
270   cout << "Bounding Box     : " << _bboxDiag << endl;
271   return 0;
272 }
273
274
275 int Controller::Load3DSFile(const char *iFileName)
276 {
277   if (_pView)
278     _pView->setUpdateMode(false);
279   
280   MaxFileLoader loader3DS(iFileName);
281   //_RootNode->AddChild(BuildSceneTest());
282   
283   _Chrono.start();
284   
285   NodeGroup *maxScene = loader3DS.Load();
286
287   if (maxScene == NULL) {
288         cout << "Cannot load scene" << endl;
289     return 1;
290   }
291
292   cout << "Scene loaded\n" << endl;
293
294   printf("Mesh cleaning    : %lf\n", _Chrono.stop());
295   _SceneNumFaces += loader3DS.numFacesRead();
296
297   if(loader3DS.minEdgeSize() < _minEdgeSize)
298     {
299       _minEdgeSize = loader3DS.minEdgeSize();
300       _EPSILON = _minEdgeSize*1e-6;
301       if(_EPSILON < DBL_MIN)
302         _EPSILON = 0.0;
303     }
304
305   cout << "Epsilon computed : " << _EPSILON << endl;
306
307   // DEBUG
308 //   ScenePrettyPrinter spp;
309 //   maxScene->accept(spp);
310         
311   _RootNode->AddChild(maxScene);
312   _RootNode->UpdateBBox(); // FIXME: Correct that by making a Renderer to compute the bbox
313
314   _pView->setModel(_RootNode);
315   //_pView->FitBBox();
316
317
318   _Chrono.start();
319
320   
321   WXEdgeBuilder wx_builder;
322   maxScene->accept(wx_builder);
323   _winged_edge = wx_builder.getWingedEdge();
324
325   printf("WEdge building   : %lf\n", _Chrono.stop());
326
327  _Chrono.start();
328
329   _Grid.clear();
330   Vec3r size;
331   for(unsigned int i=0; i<3; i++)
332     {
333       size[i] = fabs(_RootNode->bbox().getMax()[i] - _RootNode->bbox().getMin()[i]);
334       size[i] += size[i]/10.0; // let make the grid 1/10 bigger to avoid numerical errors while computing triangles/cells intersections
335       if(size[i]==0){
336           cout << "Warning: the bbox size is 0 in dimension "<<i<<endl;
337       }
338     }
339   _Grid.configure(Vec3r(_RootNode->bbox().getMin() - size / 20.0), size,
340                   _SceneNumFaces);
341
342   // Fill in the grid:
343   WFillGrid fillGridRenderer(&_Grid, _winged_edge);
344   fillGridRenderer.fillGrid();
345
346   printf("Grid building    : %lf\n", _Chrono.stop());
347   
348   // DEBUG
349 //   _Grid.displayDebug();
350    
351   _pView->setDebug(_DebugNode);
352
353   //delete stuff
354   //  if(0 != ws_builder)
355   //    {
356   //      delete ws_builder;
357   //      ws_builder = 0;
358   //    }
359   _pView->updateGL();
360   
361
362         //soc QFileInfo qfi(iFileName);
363         //soc string basename((const char*)qfi.fileName().toAscii().data());
364         char cleaned[FILE_MAX];
365         BLI_strncpy(cleaned, iFileName, FILE_MAX);
366         BLI_cleanup_file(NULL, cleaned);
367         string basename = StringUtils::toAscii( string(cleaned) );
368
369   _ListOfModels.push_back(basename);
370
371   cout << "Triangles nb     : " << _SceneNumFaces << endl;
372   _bboxDiag = (_RootNode->bbox().getMax()-_RootNode->bbox().getMin()).norm();
373   cout << "Bounding Box     : " << _bboxDiag << endl;
374   return 0;
375 }
376
377 void Controller::CloseFile()
378 {
379   WShape::setCurrentId(0);
380   _pView->DetachModel();
381   _ListOfModels.clear();
382   if(NULL != _RootNode)
383     {
384       int ref = _RootNode->destroy();
385       if(0 == ref)
386         _RootNode->addRef();
387     
388       _RootNode->clearBBox();
389     }
390   
391   _pView->DetachSilhouette();
392   if (NULL != _SilhouetteNode)
393     {
394       int ref = _SilhouetteNode->destroy();
395       if(0 == ref)
396         {
397           delete _SilhouetteNode;
398           _SilhouetteNode = NULL;
399         }
400     }
401   //  if(NULL != _ProjectedSilhouette)
402   //    {
403   //      int ref = _ProjectedSilhouette->destroy();
404   //      if(0 == ref)
405   //    {
406   //      delete _ProjectedSilhouette;
407   //      _ProjectedSilhouette = NULL;
408   //    }
409   //    }
410   //  if(NULL != _VisibleProjectedSilhouette)
411   //    {
412   //      int ref = _VisibleProjectedSilhouette->destroy();
413   //      if(0 == ref)
414   //    {
415   //      delete _VisibleProjectedSilhouette;
416   //      _VisibleProjectedSilhouette = NULL;
417   //    }
418   //  }
419   
420   _pView->DetachDebug();
421   if(NULL != _DebugNode)
422     {
423       int ref = _DebugNode->destroy();
424       if(0 == ref)
425         _DebugNode->addRef();
426     }
427   
428   if(_winged_edge) {
429     delete _winged_edge;
430     _winged_edge = NULL;
431   }
432
433   // We deallocate the memory:
434   if(NULL != _ViewMap)
435     {
436       delete _ViewMap;
437       _ViewMap = 0;
438     }
439
440   // clears the canvas
441   _Canvas->Erase();
442
443   // clears the grid
444   _Grid.clear();
445   _SceneNumFaces = 0;
446   _minEdgeSize = DBL_MAX;
447   //  _pView2D->DetachScene();
448   //  if(NULL != _SRoot)
449   //  {
450   //    int ref = _SRoot->destroy();
451   //    if(0 == ref)
452   //    {
453   //      //_SRoot->addRef();
454   //      delete _SRoot;
455   //      _SRoot = NULL;
456   //    }
457   //  }
458 }
459
460 //  static const streamsize buffer_size = 512 * 1024;
461
462 void Controller::SaveViewMapFile(const char *oFileName)
463 {
464   if (!_ViewMap)
465     return;
466
467   ofstream ofs(oFileName, ios::binary);
468   if (!ofs.is_open()) {
469     cerr << "Error: Cannot save this file" << endl;
470     return;
471   }
472 //    char buffer[buffer_size];
473 //  #if defined(__GNUC__) && (__GNUC__ < 3)
474 //    ofs.rdbuf()->setbuf(buffer, buffer_size);
475 //  # else
476 //    ofs.rdbuf()->pubsetbuf(buffer, buffer_size);
477 //  #endif
478   _Chrono.start();
479
480   ofs << Config::VIEWMAP_MAGIC << endl << Config::VIEWMAP_VERSION << endl;
481
482   // Write the models filenames
483   ofs << _ListOfModels.size() << endl;
484   for (vector<string>::const_iterator i = _ListOfModels.begin(); i != _ListOfModels.end(); i++)
485     ofs << *i << "\n";
486
487   // Save the camera position
488   float position[3];
489   float orientation[4];
490   _pView->getCameraState(position, orientation);
491   ofs.write((char*)position, 3 * sizeof(*position));
492   ofs.write((char*)orientation, 4 * sizeof(*orientation));
493
494   // Write ViewMap
495   if (ViewMapIO::save(ofs, _ViewMap, 0)) {
496     _Chrono.stop();
497     cerr << "Error: Cannot save this file" << endl;
498     return;
499   }
500
501   real d = _Chrono.stop();
502   cout << "ViewMap saving   : " << d << endl;
503 }
504
505 // void Controller::LoadViewMapFile(const char *iFileName, bool only_camera)
506 // {
507 //   ifstream ifs(iFileName, ios::binary);
508 //   if (!ifs.is_open()) {
509 //     cerr << "Error: Cannot load this file" << endl;
510 //     return;
511 //   }
512 // //    char buffer[buffer_size];
513 // //  #if defined(__GNUC__) && (__GNUC__ < 3)
514 // //    ifs.rdbuf()->setbuf(buffer, buffer_size);
515 // //  # else
516 // //    ifs.rdbuf()->pubsetbuf(buffer, buffer_size);
517 // //  #endif
518 // 
519 //   // Test File Magic and version
520 //   char tmp_buffer[256];
521 //   string test;
522 //   
523 //   ifs.getline(tmp_buffer, 255);
524 //   test = tmp_buffer;
525 //   if (test != Config::VIEWMAP_MAGIC) {
526 //     cerr << "Error: This is not a valid ." << Config::VIEWMAP_EXTENSION << " file" << endl;
527 //     return;
528 //   }
529 //   ifs.getline(tmp_buffer, 255);
530 //   test = tmp_buffer;
531 //   if (test != Config::VIEWMAP_VERSION && !only_camera) {
532 //     cerr << "Error: This version of the ." << Config::VIEWMAP_EXTENSION << " file format is no longer supported" << endl;
533 //     return;
534 //   }
535 // 
536 //   // Read the models filenames and open them (if not already done)
537 //   string tmp;
538 //   vector<string> tmp_vec;
539 //   unsigned models_nb, i;
540 // 
541 //   ifs.getline(tmp_buffer, 255);
542 //   models_nb = atoi(tmp_buffer);
543 //   for (i = 0; i < models_nb; i++) {
544 //     ifs.getline(tmp_buffer, 255);
545 //     tmp = tmp_buffer;
546 //     tmp_vec.push_back(tmp);
547 //   }
548 //   if (_ListOfModels != tmp_vec && !only_camera) {
549 //     CloseFile();
550 //     vector<string> pathnames;
551 //     int err = 0;
552 //     for (vector<string>::const_iterator i = tmp_vec.begin(); i != tmp_vec.end(); i++)
553 //       {
554 //      pathnames.clear();
555 //      StringUtils::getPathName(ViewMapIO::Options::getModelsPath(), *i, pathnames);
556 //      for (vector<string>::const_iterator j = pathnames.begin(); j != pathnames.end(); j++)
557 //        if (!(err = Load3DSFile(j->c_str())))
558 //          break;
559 //      if (err) {
560 //        cerr << "Error: cannot find model \"" << *i << "\" - check the path in the Options" << endl;
561 //        return;
562 //      }
563 //       }
564 //   }
565 // 
566 //   // set the camera position
567 //   float position[3];
568 //   float orientation[4];
569 //   ifs.read((char*)position, 3 * sizeof(*position));
570 //   ifs.read((char*)orientation, 4 * sizeof(*orientation));
571 //   _pView->setCameraState(position, orientation);
572 //   _pView->saveCameraState();
573 // 
574 //   if (only_camera) {
575 //     return;
576 //   }
577 // 
578 //   // Reset ViewMap
579 //   if(NULL != _ViewMap)
580 //     {
581 //       delete _ViewMap;
582 //       _ViewMap = 0;
583 //     }
584 //   _pView->DetachSilhouette();
585 //   if (NULL != _SilhouetteNode)
586 //     {
587 //       int ref = _SilhouetteNode->destroy();
588 //       if(0 == ref)
589 //      delete _SilhouetteNode;
590 //     }
591 //   //  if(NULL != _ProjectedSilhouette)
592 //   //    {
593 //   //      int ref = _ProjectedSilhouette->destroy();
594 //   //      if(0 == ref)
595 //   // delete _ProjectedSilhouette;
596 //   //    }
597 //   //  if(NULL != _VisibleProjectedSilhouette)
598 //   //    {
599 //   //      int ref = _VisibleProjectedSilhouette->destroy();
600 //   //      if(0 == ref)
601 //   // {
602 //   //   delete _VisibleProjectedSilhouette;
603 //   //   _VisibleProjectedSilhouette = 0;
604 //   // }
605 //    // }
606 //   _ViewMap = new ViewMap();
607 // 
608 //   // Read ViewMap
609 //   _Chrono.start();
610 //   if (ViewMapIO::load(ifs, _ViewMap, 0)) {
611 //     _Chrono.stop();
612 // 
613 //     cerr << "Error: This is not a valid ." << Config::VIEWMAP_EXTENSION << " file" << endl;
614 //     return;
615 //   }
616 // 
617 //   // Update display
618 //   ViewMapTesselator3D sTesselator3d;
619 //   //ViewMapTesselator2D sTesselator2d;
620 //   //sTesselator2d.setNature(_edgeTesselationNature);
621 //   sTesselator3d.setNature(_edgeTesselationNature);
622 //   
623 //   // Tesselate the 3D edges:
624 //   _SilhouetteNode = sTesselator3d.Tesselate(_ViewMap);
625 //   _SilhouetteNode->addRef();
626 //   
627 //   // Tesselate 2D edges
628 //   //  _ProjectedSilhouette = sTesselator2d.Tesselate(_ViewMap);
629 //   //  _ProjectedSilhouette->addRef();
630 //   //  
631 //   _pView->AddSilhouette(_SilhouetteNode);
632 //   //_pView->Add2DSilhouette(_ProjectedSilhouette);
633 // 
634 //   // Update options window
635 //   //_pOptionsWindow->updateViewMapFormat();
636 // 
637 //   real d = _Chrono.stop();
638 //   cout << "ViewMap loading  : " << d << endl;
639 // 
640 //   // Compute the Directional ViewMap:
641 //   if(_ComputeSteerableViewMap){
642 //     ComputeSteerableViewMap();
643 //   }
644 // 
645 //   // Reset Style modules modification flags
646 //   resetModified(true);
647 // }
648
649 void Controller::ComputeViewMap()
650 {
651
652   if (!_ListOfModels.size())
653     return;
654   
655   if(NULL != _ViewMap)
656     {
657       delete _ViewMap;
658       _ViewMap = 0;
659     }
660
661   _pView->DetachDebug();
662   if(NULL != _DebugNode)
663     {
664       int ref = _DebugNode->destroy();
665       if(0 == ref)
666         _DebugNode->addRef();
667     }
668   
669
670   _pView->DetachSilhouette();
671   if (NULL != _SilhouetteNode)
672     {
673       int ref = _SilhouetteNode->destroy();
674       if(0 == ref)
675         delete _SilhouetteNode;
676     }
677   //  if(NULL != _ProjectedSilhouette)
678   //    {
679   //      int ref = _ProjectedSilhouette->destroy();
680   //      if(0 == ref)
681   //    delete _ProjectedSilhouette;
682   //    }
683   //  if(NULL != _VisibleProjectedSilhouette)
684   //    {
685   //      int ref = _VisibleProjectedSilhouette->destroy();
686   //      if(0 == ref)
687   //    {
688   //      delete _VisibleProjectedSilhouette;
689   //      _VisibleProjectedSilhouette = 0;
690   //    }
691   //  }
692   
693   // retrieve the 3D viewpoint and transformations information
694   //----------------------------------------------------------
695   // Save the viewpoint context at the view level in order 
696   // to be able to restore it later:
697   _pView->saveCameraState();
698
699   // Restore the context of view:
700   // we need to perform all these operations while the 
701   // 3D context is on.
702   _pView->set3DContext();
703   float src[3] = { 0, 0, 0 };
704   float vp_tmp[3] = { 0, 0, 0 };
705   _pView->_camera->getWorldCoordinatesOf(src, vp_tmp);
706   Vec3r vp(vp_tmp[0], vp_tmp[1], vp_tmp[2]);
707
708   real mv[4][4];
709   _pView->RetriveModelViewMatrix((real *)mv);
710   // retrieve the projection matrix:
711   real proj[4][4];
712   _pView->RetrieveProjectionMatrix((real *)proj);
713   int viewport[4];
714   _pView->RetrieveViewport(viewport);  
715   real focalLength = _pView->GetFocalLength();
716
717   // Flag the WXEdge structure for silhouette edge detection:
718   //----------------------------------------------------------
719
720   _Chrono.start();
721  
722   edgeDetector.setViewpoint(Vec3r(vp));
723   edgeDetector.enableRidgesAndValleysFlag(_ComputeRidges);
724   edgeDetector.enableSuggestiveContours(_ComputeSuggestive);
725   edgeDetector.setSphereRadius(_sphereRadius);
726   edgeDetector.setSuggestiveContourKrDerivativeEpsilon(_suggestiveContourKrDerivativeEpsilon);
727   edgeDetector.processShapes(*_winged_edge);
728
729   real duration = _Chrono.stop();
730   printf("Feature lines    : %lf\n", duration);
731
732   // Builds the view map structure from the flagged WSEdge structure:
733   //----------------------------------------------------------
734   ViewMapBuilder vmBuilder;
735   vmBuilder.setEnableQI(_EnableQI);
736   vmBuilder.setViewpoint(Vec3r(vp));
737   
738   vmBuilder.setTransform(mv, proj, viewport, focalLength, _pView->GetAspect(), _pView->GetFovyRadian());
739   vmBuilder.setFrustum(_pView->znear(), _pView->zfar());
740   
741   vmBuilder.setGrid(&_Grid);
742   
743   // Builds a tesselated form of the silhouette for display purpose:
744   //---------------------------------------------------------------
745   ViewMapTesselator3D sTesselator3d;
746   //ViewMapTesselator2D sTesselator2d;
747   //sTesselator2d.setNature(_edgeTesselationNature);
748   sTesselator3d.setNature(_edgeTesselationNature);
749     
750   _Chrono.start();
751   // Build View Map
752   _ViewMap = vmBuilder.BuildViewMap(*_winged_edge, _VisibilityAlgo, _EPSILON);
753   _ViewMap->setScene3dBBox(_RootNode->bbox());
754   
755         printf("ViewMap edge count : %i\n", _ViewMap->viewedges_size() );
756
757   //Tesselate the 3D edges:
758   _SilhouetteNode = sTesselator3d.Tesselate(_ViewMap);
759   _SilhouetteNode->addRef();
760   
761   // Tesselate 2D edges
762   //  _ProjectedSilhouette = sTesselator2d.Tesselate(_ViewMap);
763   //  _ProjectedSilhouette->addRef();
764   
765   duration = _Chrono.stop();
766   printf("ViewMap building : %lf\n", duration);
767
768   
769   _pView->AddSilhouette(_SilhouetteNode);
770   //_pView->AddSilhouette(_WRoot);
771   //_pView->Add2DSilhouette(_ProjectedSilhouette);
772   //_pView->Add2DVisibleSilhouette(_VisibleProjectedSilhouette);  
773   _pView->AddDebug(_DebugNode);
774
775   // Draw the steerable density map:
776   //--------------------------------
777   if(_ComputeSteerableViewMap){
778     ComputeSteerableViewMap();
779   }
780   // Reset Style modules modification flags
781   resetModified(true);
782 }
783
784 void Controller::ComputeSteerableViewMap(){
785 //soc
786   // if((!_Canvas) || (!_ViewMap))
787   //   return;
788   //   
789   // // Build 4 nodes containing the edges in the 4 directions
790   // NodeGroup *ng[Canvas::NB_STEERABLE_VIEWMAP];
791   // unsigned i;
792   // real c = 32.f/255.f; // see SteerableViewMap::readSteerableViewMapPixel() for information about this 32.
793   // for(i=0; i<Canvas::NB_STEERABLE_VIEWMAP; ++i){
794   //   ng[i] = new NodeGroup;
795   // }
796   // NodeShape *completeNS = new NodeShape;
797   // completeNS->material().setDiffuse(c,c,c,1);
798   // ng[Canvas::NB_STEERABLE_VIEWMAP-1]->AddChild(completeNS);
799   // SteerableViewMap * svm = _Canvas->getSteerableViewMap();
800   // svm->Reset();
801   // 
802   // ViewMap::fedges_container& fedges = _ViewMap->FEdges();
803   // LineRep * fRep;
804   // NodeShape *ns;
805   // for(ViewMap::fedges_container::iterator f=fedges.begin(), fend=fedges.end();
806   // f!=fend;
807   // ++f){
808   //   if((*f)->viewedge()->qi() != 0)
809   //     continue;
810   //   fRep = new LineRep((*f)->vertexA()->point2d(),(*f)->vertexB()->point2d()) ;
811   //   completeNS->AddRep(fRep); // add to the complete map anyway
812   //   double *oweights = svm->AddFEdge(*f);
813   //   for(i=0; i<Canvas::NB_STEERABLE_VIEWMAP-1; ++i){
814   //     ns = new NodeShape;
815   //     double wc = oweights[i]*c;
816   //     if(oweights[i] == 0)
817   //       continue;
818   //     ns->material().setDiffuse(wc, wc, wc, 1);
819   //     ns->AddRep(fRep);
820   //     ng[i]->AddChild(ns);
821   //   }
822   // }
823   // 
824   // GrayImage *img[Canvas::NB_STEERABLE_VIEWMAP];
825   // //#ifdef WIN32
826   // QGLBasicWidget offscreenBuffer(_pView, "SteerableViewMap", _pView->width(), _pView->height()); 
827   // QPixmap pm;
828   // QImage qimg;
829   // for(i=0; i<Canvas::NB_STEERABLE_VIEWMAP; ++i){
830   //   offscreenBuffer.AddNode(ng[i]);
831   //   //img[i] = new GrayImage(_pView->width(), _pView->height());
832   //   //offscreenBuffer.readPixels(0,0,_pView->width(), _pView->height(), img[i]->getArray());
833   //   pm = offscreenBuffer.renderPixmap(_pView->width(), _pView->height());
834   // 
835   //   if(pm.isNull())
836   //     cout << "BuildViewMap Warning: couldn't render the steerable ViewMap" << endl;
837   //   //pm.save(QString("steerable")+QString::number(i)+QString(".bmp"), "BMP");
838   //   // FIXME!! Lost of time !
839   //   qimg = pm.toImage();
840   //   // FIXME !! again!
841   //   img[i] = new GrayImage(_pView->width(), _pView->height());
842   //   for(unsigned y=0;y<img[i]->height();++y){
843   //     for(unsigned x=0;x<img[i]->width();++x){
844   //       //img[i]->setPixel(x,y,(float)qGray(qimg.pixel(x,y))/255.f);
845   //       img[i]->setPixel(x,y,(float)qGray(qimg.pixel(x,y)));
846   //       //        float c = qGray(qimg.pixel(x,y));
847   //       //        img[i]->setPixel(x,y,qGray(qimg.pixel(x,y)));
848   //     }
849   //   }
850   //   offscreenBuffer.DetachNode(ng[i]);
851   //   ng[i]->destroy();
852   //   delete ng[i];
853   //   // check
854   //   //    qimg = QImage(_pView->width(), _pView->height(), 32);
855   //   //    for(y=0;y<img[i]->height();++y){
856   //   //      for(unsigned x=0;x<img[i]->width();++x){
857   //   //        float v = img[i]->pixel(x,y);
858   //   //        qimg.setPixel(x,y,qRgb(v,v,v));
859   //   //      }
860   //   //    }
861   //   //    qimg.save(QString("newsteerable")+QString::number(i)+QString(".bmp"), "BMP");
862   // }
863   // 
864   // 
865   // svm->buildImagesPyramids(img,false,0,1.f);
866 }
867
868 void Controller::saveSteerableViewMapImages(){
869   SteerableViewMap * svm = _Canvas->getSteerableViewMap();
870   if(!svm){
871     cerr << "the Steerable ViewMap has not been computed yet" << endl;
872     return;
873   }
874   svm->saveSteerableViewMap();
875 }
876
877 void Controller::toggleVisibilityAlgo() 
878 {
879   if(_VisibilityAlgo == ViewMapBuilder::ray_casting) {
880     _VisibilityAlgo = ViewMapBuilder::ray_casting_fast;
881   }
882   else if (_VisibilityAlgo == ViewMapBuilder::ray_casting_fast) {
883     _VisibilityAlgo = ViewMapBuilder::ray_casting_very_fast;
884   }
885   else {
886     _VisibilityAlgo = ViewMapBuilder::ray_casting;
887   }
888 }
889
890 void Controller::setQuantitativeInvisibility(bool iBool)
891 {
892   _EnableQI = iBool;
893 }
894
895 bool Controller::getQuantitativeInvisibility() const
896 {
897   return _EnableQI;
898 }
899
900 void Controller::setComputeRidgesAndValleysFlag(bool iBool){
901   _ComputeRidges = iBool;
902 }
903
904 bool Controller::getComputeRidgesAndValleysFlag() const {
905   return _ComputeRidges;
906 }
907 void Controller::setComputeSuggestiveContoursFlag(bool b){
908   _ComputeSuggestive = b;
909 }
910   
911 bool Controller::getComputeSuggestiveContoursFlag() const {
912   return _ComputeSuggestive;
913 }
914 void Controller::setComputeSteerableViewMapFlag(bool iBool){
915   _ComputeSteerableViewMap = iBool;
916 }
917
918 bool Controller::getComputeSteerableViewMapFlag() const {
919   return _ComputeSteerableViewMap;
920 }
921 void Controller::setFrontBufferFlag(bool iBool)
922 {
923   AppGLWidget::setFrontBufferFlag(iBool);
924 }
925
926 bool Controller::getFrontBufferFlag() const
927 {
928   return AppGLWidget::getFrontBufferFlag();
929 }
930
931 void Controller::setBackBufferFlag(bool iBool)
932 {
933   AppGLWidget::setBackBufferFlag(iBool);
934 }
935
936 bool Controller::getBackBufferFlag() const
937 {
938   return AppGLWidget::getBackBufferFlag();
939 }
940
941 void Controller::DrawStrokes()
942 {
943   if(_ViewMap == 0)
944     return;
945
946   _Chrono.start();
947   _Canvas->Draw();
948   real d = _Chrono.stop();
949   cout << "Strokes drawing  : " << d << endl;
950   resetModified();
951 }
952
953 void Controller::InsertStyleModule(unsigned index, const char *iFileName)
954 {
955   // QFileInfo fi(iFileName);
956   // string ext = fi.suffix();
957   // if (ext != "py") {
958   //   cerr << "Error: Cannot load \"" << fi.fileName().toAscii().data()
959   //     << "\", unknown extension" << endl;
960   //   return;
961   // }
962
963         if( !BLI_testextensie(iFileName, ".py") ) {
964                 cerr << "Error: Cannot load \"" << StringUtils::toAscii( string(iFileName) )
965                   << "\", unknown extension" << endl;
966                   return;
967         }
968
969   StyleModule* sm = new StyleModule(iFileName, _inter);
970   _Canvas->InsertStyleModule(index, sm);
971   
972 }
973
974 void Controller::AddStyleModule(const char *iFileName)
975 {
976   //_pStyleWindow->Add(iFileName);
977 }
978
979 void Controller::RemoveStyleModule(unsigned index)
980 {
981   _Canvas->RemoveStyleModule(index);
982 }
983
984 void Controller::Clear()
985 {
986   _Canvas->Clear();
987 }
988
989 void Controller::ReloadStyleModule(unsigned index, const char * iFileName)
990 {
991   StyleModule* sm = new StyleModule(iFileName, _inter);
992   _Canvas->ReplaceStyleModule(index, sm);
993 }
994
995 void Controller::SwapStyleModules(unsigned i1, unsigned i2)
996 {
997   _Canvas->SwapStyleModules(i1, i2);
998 }
999
1000
1001 void Controller::toggleLayer(unsigned index, bool iDisplay)
1002 {
1003   _Canvas->setVisible(index, iDisplay);
1004   _pView->updateGL();
1005 }
1006
1007 void Controller::setModified(unsigned index, bool iMod)
1008 {
1009   //_pStyleWindow->setModified(index, iMod);
1010   _Canvas->setModified(index, iMod);
1011   updateCausalStyleModules(index + 1);
1012 }
1013
1014 void Controller::updateCausalStyleModules(unsigned index) {
1015   vector<unsigned> vec;
1016   _Canvas->causalStyleModules(vec, index);
1017   for (vector<unsigned>::const_iterator it = vec.begin(); it != vec.end(); it++) {
1018     //_pStyleWindow->setModified(*it, true);
1019     _Canvas->setModified(*it, true);
1020   }
1021 }
1022
1023 void Controller::saveSnapshot(bool b) {
1024  _pView->saveSnapshot(b);
1025 }
1026
1027 void Controller::resetModified(bool iMod)
1028 {
1029   //_pStyleWindow->resetModified(iMod);
1030   _Canvas->resetModified(iMod);
1031 }
1032
1033 FEdge* Controller::SelectFEdge(real x, real y)
1034 {
1035   if (!_ViewMap)
1036     return NULL;
1037
1038   FEdge *fedge = (FEdge*)_ViewMap->getClosestFEdge(x,y);
1039   //ViewEdge *selection = fedge->viewedge();
1040   _pView->setSelectedFEdge(fedge);
1041   _Canvas->setSelectedFEdge(fedge);
1042   return fedge;
1043 }
1044
1045 ViewEdge* Controller::SelectViewEdge(real x, real y)
1046 {
1047   if (!_ViewMap)
1048     return NULL;
1049
1050   FEdge *fedge = (FEdge*)_ViewMap->getClosestFEdge(x,y);
1051   ViewEdge *selection = fedge->viewedge();
1052   _pView->setSelectedFEdge(fedge);
1053   _Canvas->setSelectedFEdge(fedge);
1054   return selection;
1055 }
1056
1057 NodeGroup * Controller::BuildRep(vector<ViewEdge*>::iterator vedges_begin, 
1058                                        vector<ViewEdge*>::iterator vedges_end)
1059 {
1060   ViewMapTesselator2D tesselator2D;
1061   FrsMaterial mat;
1062   mat.setDiffuse(1,1,0.3,1);
1063   tesselator2D.setFrsMaterial(mat);
1064
1065   return (tesselator2D.Tesselate(vedges_begin, vedges_end));
1066 }
1067
1068 void Controller::toggleEdgeTesselationNature(Nature::EdgeNature iNature)
1069 {
1070   _edgeTesselationNature ^= (iNature);
1071   ComputeViewMap();
1072 }
1073
1074 void            Controller::setModelsDir(const string& dir) {
1075   //_current_dirs->setValue("models/dir", dir);
1076 }
1077
1078 string          Controller::getModelsDir() const {
1079   string dir = ".";
1080   //_current_dirs->getValue("models/dir", dir);
1081   return dir;
1082 }
1083
1084 void            Controller::setModulesDir(const string& dir) {
1085   //_current_dirs->setValue("modules/dir", dir);
1086 }
1087
1088 string          Controller::getModulesDir() const {
1089   string dir = ".";
1090   //_current_dirs->getValue("modules/dir", dir);
1091   return dir;
1092 }
1093
1094 void            Controller::setPapersDir(const string& dir) {
1095   //_current_dirs->setValue("papers/dir", dir);
1096 }
1097
1098 string          Controller::getPapersDir() const {
1099   string dir = Config::Path::getInstance()->getPapersDir();
1100   //_current_dirs->getValue("papers/dir", dir);
1101   return dir;
1102 }
1103
1104 void            Controller::setHelpIndex(const string& index) {
1105   _help_index = index;
1106 }
1107
1108 string          Controller::getHelpIndex() const {
1109   return _help_index;
1110 }
1111
1112 void            Controller::setBrowserCmd(const string& cmd) {
1113   _browser_cmd = cmd;
1114 }
1115
1116 string          Controller::getBrowserCmd() const {
1117   return _browser_cmd;
1118 }
1119
1120 void            Controller::resetInterpreter() {
1121   if (_inter)
1122     _inter->reset();
1123 }
1124
1125
1126 void Controller::displayDensityCurves(int x, int y){
1127   SteerableViewMap * svm = _Canvas->getSteerableViewMap();
1128   if(!svm)
1129     return;
1130
1131   unsigned i,j;
1132   typedef vector<Vec3r> densityCurve;
1133   vector<densityCurve> curves(svm->getNumberOfOrientations()+1);
1134   vector<densityCurve> curvesDirection(svm->getNumberOfPyramidLevels());
1135
1136   // collect the curves values
1137   unsigned nbCurves = svm->getNumberOfOrientations()+1;
1138   unsigned nbPoints = svm->getNumberOfPyramidLevels();
1139   if(!nbPoints)
1140     return;
1141
1142   // build the density/nbLevels curves for each orientation
1143   for(i=0;i<nbCurves; ++i){
1144     for(j=0; j<nbPoints; ++j){
1145       curves[i].push_back(Vec3r(j, svm->readSteerableViewMapPixel(i, j, x, y), 0));
1146     }
1147   }
1148   // build the density/nbOrientations curves for each level
1149   for(i=0;i<nbPoints; ++i){
1150     for(j=0; j<nbCurves; ++j){
1151       curvesDirection[i].push_back(Vec3r(j, svm->readSteerableViewMapPixel(j, i, x, y), 0));
1152     }
1153   }
1154
1155   // display the curves
1156   // for(i=0; i<nbCurves; ++i)
1157   //     _pDensityCurvesWindow->setOrientationCurve(i, Vec2d(0,0), Vec2d(nbPoints, 1), curves[i], "scale", "density");
1158   //   for(i=1; i<=8; ++i)
1159   //     _pDensityCurvesWindow->setLevelCurve(i, Vec2d(0,0), Vec2d(nbCurves, 1), curvesDirection[i], "orientation", "density");
1160   //   _pDensityCurvesWindow->show();
1161 }
1162
1163 void Controller::init_options(){
1164 //      from AppOptionsWindow.cpp
1165 //      Default init options
1166
1167         Config::Path * cpath = Config::Path::getInstance();
1168         
1169         // Directories
1170         ViewMapIO::Options::setModelsPath( StringUtils::toAscii( cpath->getModelsPath() ) ); 
1171         PythonInterpreter::Options::setPythonPath( StringUtils::toAscii( cpath->getPythonPath() ) );
1172         TextureManager::Options::setPatternsPath( StringUtils::toAscii( cpath->getPatternsPath() ) );
1173         TextureManager::Options::setBrushesPath( StringUtils::toAscii( cpath->getModelsPath() ) );
1174
1175         // ViewMap Format
1176         ViewMapIO::Options::rmFlags(ViewMapIO::Options::FLOAT_VECTORS);
1177         ViewMapIO::Options::rmFlags(ViewMapIO::Options::NO_OCCLUDERS);
1178         setComputeSteerableViewMapFlag( false );
1179
1180         // Visibility
1181         setQuantitativeInvisibility(true);
1182
1183          // Papers Textures
1184         vector<string> sl;
1185         sl.push_back( StringUtils::toAscii( cpath->getPapersDir() + Config::DEFAULT_PAPER_TEXTURE ) );
1186         TextureManager::Options::setPaperTextures( sl );
1187
1188         // Drawing Buffers
1189         setFrontBufferFlag(false);
1190         setBackBufferFlag(true);
1191
1192         // Ridges and Valleys
1193         setComputeRidgesAndValleysFlag( false );
1194         
1195         // Suggestive Contours
1196         setComputeSuggestiveContoursFlag( false );
1197         setSphereRadius(1);
1198         setSuggestiveContourKrDerivativeEpsilon(0);
1199
1200         // soc: initialize canvas
1201         _Canvas->init();
1202 }