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