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