This repository has been archived on 2023-10-09. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
blender-archive/source/blender/freestyle/intern/application/Controller.cpp

1138 lines
28 KiB
C++
Raw Normal View History

/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/** \file
* \ingroup freestyle
*/
extern "C" {
#include <Python.h>
}
#include <string>
#include <fstream>
#include <float.h>
#include "AppView.h"
#include "AppCanvas.h"
#include "AppConfig.h"
#include "Controller.h"
#include "../image/Image.h"
#include "../scene_graph/NodeDrawingStyle.h"
#include "../scene_graph/NodeShape.h"
#include "../scene_graph/NodeTransform.h"
#include "../scene_graph/NodeViewLayer.h"
#include "../scene_graph/ScenePrettyPrinter.h"
#include "../scene_graph/VertexRep.h"
#include "../stroke/PSStrokeRenderer.h"
#include "../stroke/TextStrokeRenderer.h"
#include "../stroke/StrokeTesselator.h"
#include "../stroke/StyleModule.h"
#include "../system/StringUtils.h"
#include "../system/PythonInterpreter.h"
#include "../view_map/SteerableViewMap.h"
#include "../view_map/ViewMap.h"
#include "../view_map/ViewMapIO.h"
#include "../view_map/ViewMapTesselator.h"
#include "../winged_edge/Curvature.h"
#include "../winged_edge/WEdge.h"
#include "../winged_edge/WingedEdgeBuilder.h"
#include "../winged_edge/WXEdgeBuilder.h"
#include "../blender_interface/BlenderFileLoader.h"
#include "../blender_interface/BlenderStrokeRenderer.h"
#include "../blender_interface/BlenderStyleModule.h"
#include "BKE_global.h"
2014-04-17 12:55:17 +09:00
#include "BLI_utildefines.h"
#include "BLI_path_util.h"
Optimized view map calculation by Alexander Beels. * View map calculation has been intensively optimized for speed by means of: 1) new spatial grid data structures (SphericalGrid for perspective cameras and BoxGrid for orthographic cameras; automatically switched based on the camera type); 2) a heuristic grid density calculation algorithm; and 3) new line visibility computation algorithms: A "traditional" algorithm for emulating old visibility algorithms, and a "cumulative" algorithm for improved, more consistent line visibility, both exploiting the new spatial grid data structures for fast ray casting. A new option "Raycasting Algorithm" was added to allow users to choose a ray casting (line visibility) algorithm. Available choices are: - Normal Ray Casting - Fast Ray Casting - Very Fast Ray Casting - Culled Traditional Visibility Detection - Unculled Traditional Visibility Detection - Culled Cumulative Visibility Detection - Unculled Cumulative Visibility Detection The first three algorithms are those available in the original Freestyle (the "normal" ray casting was used unconditionally, though). The "fast" and "very fast" ray casting algorithms achieve a faster calculation at the cost of less visibility accuracy. The last four are newly introduced optimized options. The culled versions of the new algorithms will exclude from visibility calculation those faces that lay outside the camera, which leads to a faster view map construction. The unculled counterparts will take all faces into account. The unculled visibility algorithms are useful when culling affects stroke chaining. The recommended options for users are the culled/unculled cumulative visibility algorithms. These options are meant to replace the old algorithms in the future. Performance improvements over the old algorithms depend on the scenes to be rendered. * Silhouette detection has also been considerably optimized for speed. Performance gains by this optimization do not depend on scenes. * Improper handling of error conditions in the view map construction was fixed.
2011-03-14 00:36:27 +00:00
#include "DNA_freestyle_types.h"
#include "FRS_freestyle.h"
Attempt to fix a potential name conflict between Freestyle and the compositor. A crash in the Freestyle renderer was reported by Ton on IRC with a stack trace below. Note that #2 is in Freestyle, whereas #1 is in the compositor. The problem was observed in a debug build on OS X 10.7 (gcc 4.2, openmp disabled, no llvm). ---------------------------------------------------------------------- Program received signal EXC_BAD_ACCESS, Could not access memory. Reason: 13 at address: 0x0000000000000000 [Switching to process 72386 thread 0xf303] 0x0000000100c129f3 in NodeBase::~NodeBase (this=0x10e501c80) at COM_NodeBase.cpp:43 43 delete (this->m_outputsockets.back()); Current language: auto; currently c++ (gdb) where #0 0x0000000100c129f3 in NodeBase::~NodeBase (this=0x10e501c80) at COM_NodeBase.cpp:43 #1 0x0000000100c29066 in Node::~Node (this=0x10e501c80) at COM_Node.h:49 #2 0x000000010089c273 in NodeShape::~NodeShape (this=0x10e501c80) at NodeShape.cpp:43 #3 0x000000010089910b in NodeGroup::destroy (this=0x10e501da0) at NodeGroup.cpp:61 #4 0x00000001008990cd in NodeGroup::destroy (this=0x10e5014b0) at NodeGroup.cpp:59 #5 0x00000001008990cd in NodeGroup::destroy (this=0x114e18da0) at NodeGroup.cpp:59 #6 0x00000001007e6602 in Controller::ClearRootNode (this=0x114e19640) at Controller.cpp:329 #7 0x00000001007ea52e in Controller::LoadMesh (this=0x114e19640, re=0x10aba4638, srl=0x1140f5258) at Controller.cpp:302 #8 0x00000001008030ad in prepare (re=0x10aba4638, srl=0x1140f5258) at FRS_freestyle.cpp:302 #9 0x000000010080457a in FRS_do_stroke_rendering (re=0x10aba4638, srl=0x1140f5258) at FRS_freestyle.cpp:600 #10 0x00000001006aeb9d in add_freestyle (re=0x10aba4638) at pipeline.c:1584 #11 0x00000001006aceb7 in do_render_3d (re=0x10aba4638) at pipeline.c:1094 #12 0x00000001006ae061 in do_render_fields_blur_3d (re=0x10aba4638) at pipeline.c:1367 #13 0x00000001006afa16 in do_render_composite_fields_blur_3d (re=0x10aba4638) at pipeline.c:1815 #14 0x00000001006b04e4 in do_render_all_options (re=0x10aba4638) at pipeline.c:2021 ---------------------------------------------------------------------- Apparently a name conflict between the two Blender modules is taking place. The present commit hence intends to address it by putting all the Freestyle C++ classes in the namespace 'Freestyle'. This revision will also prevent potential name conflicts with other Blender modules in the future. Special thanks to Lukas Toenne for the help with C++ namespace.
2013-04-09 00:46:49 +00:00
namespace Freestyle {
Controller::Controller()
{
const string sep(Config::DIR_SEP.c_str());
#if 0
const string filename = Config::Path::getInstance()->getHomeDir() + sep + Config::OPTIONS_DIR +
sep + Config::OPTIONS_CURRENT_DIRS_FILE;
_current_dirs = new ConfigIO(filename, Config::APPLICATION_NAME + "CurrentDirs", true);
#endif
_RootNode = new NodeGroup;
_RootNode->addRef();
#if 0
_SilhouetteNode = NULL;
_ProjectedSilhouette = NULL;
_VisibleProjectedSilhouette = NULL;
_DebugNode = new NodeGroup;
_DebugNode->addRef();
#endif
_winged_edge = NULL;
_pView = NULL;
_pRenderMonitor = NULL;
_edgeTesselationNature = (Nature::SILHOUETTE | Nature::BORDER | Nature::CREASE);
_ProgressBar = new ProgressBar;
_SceneNumFaces = 0;
#if 0
_minEdgeSize = DBL_MAX;
#endif
_EPSILON = 1.0e-6;
_bboxDiag = 0;
_ViewMap = 0;
_Canvas = 0;
_VisibilityAlgo = ViewMapBuilder::ray_casting_adaptive_traditional;
//_VisibilityAlgo = ViewMapBuilder::ray_casting;
_Canvas = new AppCanvas;
_inter = new PythonInterpreter();
_EnableViewMapCache = false;
_EnableQI = true;
_EnableFaceSmoothness = false;
_ComputeRidges = true;
_ComputeSteerableViewMap = false;
_ComputeSuggestive = true;
_ComputeMaterialBoundaries = true;
_sphereRadius = 1.0;
_creaseAngle = 134.43;
prevSceneHash = -1.0;
init_options();
}
Controller::~Controller()
{
if (NULL != _RootNode) {
int ref = _RootNode->destroy();
if (0 == ref) {
delete _RootNode;
}
}
#if 0
if (NULL != _SilhouetteNode) {
int ref = _SilhouetteNode->destroy();
if (0 == ref)
delete _SilhouetteNode;
}
if (NULL != _DebugNode) {
int ref = _DebugNode->destroy();
if (0 == ref)
delete _DebugNode;
}
#endif
if (_winged_edge) {
delete _winged_edge;
_winged_edge = NULL;
}
if (0 != _ViewMap) {
delete _ViewMap;
_ViewMap = 0;
}
if (0 != _Canvas) {
delete _Canvas;
_Canvas = 0;
}
if (_inter) {
delete _inter;
_inter = NULL;
}
if (_ProgressBar) {
delete _ProgressBar;
_ProgressBar = NULL;
}
// delete _current_dirs;
}
void Controller::setView(AppView *iView)
{
if (NULL == iView) {
return;
}
_pView = iView;
_Canvas->setViewer(_pView);
}
void Controller::setRenderMonitor(RenderMonitor *iRenderMonitor)
{
_pRenderMonitor = iRenderMonitor;
}
void Controller::setPassDiffuse(float *buf, int width, int height)
{
AppCanvas *app_canvas = dynamic_cast<AppCanvas *>(_Canvas);
BLI_assert(app_canvas != 0);
app_canvas->setPassDiffuse(buf, width, height);
}
void Controller::setPassZ(float *buf, int width, int height)
{
AppCanvas *app_canvas = dynamic_cast<AppCanvas *>(_Canvas);
BLI_assert(app_canvas != 0);
app_canvas->setPassZ(buf, width, height);
}
void Controller::setContext(bContext *C)
{
PythonInterpreter *py_inter = dynamic_cast<PythonInterpreter *>(_inter);
py_inter->setContext(C);
}
bool Controller::hitViewMapCache()
{
if (!_EnableViewMapCache) {
return false;
}
if (sceneHashFunc.match()) {
return (NULL != _ViewMap);
}
sceneHashFunc.store();
return false;
}
int Controller::LoadMesh(Render *re, ViewLayer *view_layer, Depsgraph *depsgraph)
{
BlenderFileLoader loader(re, view_layer, depsgraph);
loader.setRenderMonitor(_pRenderMonitor);
_Chrono.start();
NodeGroup *blenderScene = loader.Load();
if (blenderScene == NULL) {
if (G.debug & G_DEBUG_FREESTYLE) {
cout << "Cannot load scene" << endl;
}
return 1;
}
if (blenderScene->numberOfChildren() < 1) {
if (G.debug & G_DEBUG_FREESTYLE) {
cout << "Empty scene" << endl;
}
blenderScene->destroy();
delete blenderScene;
return 1;
}
real duration = _Chrono.stop();
if (G.debug & G_DEBUG_FREESTYLE) {
cout << "Scene loaded" << endl;
printf("Mesh cleaning : %lf\n", duration);
printf("View map cache : %s\n", _EnableViewMapCache ? "enabled" : "disabled");
}
_SceneNumFaces += loader.numFacesRead();
#if 0
if (loader.minEdgeSize() < _minEdgeSize) {
_minEdgeSize = loader.minEdgeSize();
}
#endif
#if 0 // DEBUG
ScenePrettyPrinter spp;
blenderScene->accept(spp);
#endif
_RootNode->AddChild(blenderScene);
_RootNode->UpdateBBox(); // FIXME: Correct that by making a Renderer to compute the bbox
_pView->setModel(_RootNode);
//_pView->FitBBox();
if (_pRenderMonitor->testBreak()) {
return 0;
}
if (_EnableViewMapCache) {
NodeCamera *cam;
if (g_freestyle.proj[3][3] != 0.0) {
cam = new NodeOrthographicCamera;
}
else {
cam = new NodePerspectiveCamera;
}
double proj[16];
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
proj[i * 4 + j] = g_freestyle.proj[i][j];
}
}
cam->setProjectionMatrix(proj);
_RootNode->AddChild(cam);
_RootNode->AddChild(new NodeViewLayer(*re->scene, *view_layer));
sceneHashFunc.reset();
// blenderScene->accept(sceneHashFunc);
_RootNode->accept(sceneHashFunc);
if (G.debug & G_DEBUG_FREESTYLE) {
cout << "Scene hash : " << sceneHashFunc.toString() << endl;
}
if (hitViewMapCache()) {
ClearRootNode();
return 0;
}
else {
delete _ViewMap;
_ViewMap = NULL;
}
}
_Chrono.start();
WXEdgeBuilder wx_builder;
wx_builder.setRenderMonitor(_pRenderMonitor);
blenderScene->accept(wx_builder);
_winged_edge = wx_builder.getWingedEdge();
duration = _Chrono.stop();
if (G.debug & G_DEBUG_FREESTYLE) {
printf("WEdge building : %lf\n", duration);
}
#if 0
_pView->setDebug(_DebugNode);
// delete stuff
if (0 != ws_builder) {
delete ws_builder;
ws_builder = 0;
}
soc QFileInfo qfi(iFileName);
soc string basename((const char *)qfi.fileName().toAscii().data());
char cleaned[FILE_MAX];
BLI_strncpy(cleaned, iFileName, FILE_MAX);
BLI_cleanup_file(NULL, cleaned);
string basename = string(cleaned);
#endif
_ListOfModels.push_back("Blender_models");
_Scene3dBBox = _RootNode->bbox();
_bboxDiag = (_RootNode->bbox().getMax() - _RootNode->bbox().getMin()).norm();
if (G.debug & G_DEBUG_FREESTYLE) {
cout << "Triangles nb : " << _SceneNumFaces << " imported, " << _winged_edge->getNumFaces()
<< " retained" << endl;
cout << "Bounding Box : " << _bboxDiag << endl;
}
ClearRootNode();
_SceneNumFaces = _winged_edge->getNumFaces();
if (_SceneNumFaces == 0) {
DeleteWingedEdge();
return 1;
}
return 0;
}
void Controller::CloseFile()
{
WShape::setCurrentId(0);
_ListOfModels.clear();
// We deallocate the memory:
ClearRootNode();
DeleteWingedEdge();
DeleteViewMap();
// clears the canvas
_Canvas->Clear();
// soc: reset passes
setPassDiffuse(NULL, 0, 0);
setPassZ(NULL, 0, 0);
}
void Controller::ClearRootNode()
{
_pView->DetachModel();
if (NULL != _RootNode) {
int ref = _RootNode->destroy();
if (0 == ref) {
_RootNode->addRef();
}
_RootNode->clearBBox();
}
}
void Controller::DeleteWingedEdge()
{
if (_winged_edge) {
delete _winged_edge;
_winged_edge = NULL;
}
// clears the grid
_Grid.clear();
_Scene3dBBox.clear();
_SceneNumFaces = 0;
#if 0
_minEdgeSize = DBL_MAX;
#endif
}
void Controller::DeleteViewMap(bool freeCache)
{
#if 0
_pView->DetachSilhouette();
if (NULL != _SilhouetteNode) {
int ref = _SilhouetteNode->destroy();
if (0 == ref) {
delete _SilhouetteNode;
_SilhouetteNode = NULL;
}
}
if (NULL != _ProjectedSilhouette) {
int ref = _ProjectedSilhouette->destroy();
if (0 == ref) {
delete _ProjectedSilhouette;
_ProjectedSilhouette = NULL;
}
}
if (NULL != _VisibleProjectedSilhouette) {
int ref = _VisibleProjectedSilhouette->destroy();
if (0 == ref) {
delete _VisibleProjectedSilhouette;
_VisibleProjectedSilhouette = NULL;
}
}
_pView->DetachDebug();
if (NULL != _DebugNode) {
int ref = _DebugNode->destroy();
if (0 == ref)
_DebugNode->addRef();
}
#endif
if (NULL != _ViewMap) {
if (freeCache || !_EnableViewMapCache) {
delete _ViewMap;
_ViewMap = NULL;
prevSceneHash = -1.0;
}
else {
_ViewMap->Clean();
}
}
}
void Controller::ComputeViewMap()
{
if (!_ListOfModels.size()) {
return;
}
DeleteViewMap(true);
// retrieve the 3D viewpoint and transformations information
//----------------------------------------------------------
// Save the viewpoint context at the view level in order
// to be able to restore it later:
// Restore the context of view:
// we need to perform all these operations while the
// 3D context is on.
Vec3f vp(UNPACK3(g_freestyle.viewpoint));
The GL-based renderer was removed. Freestyle now uses Blender's internal renderer to raster strokes. The render generated from Freestyle's data is currently stored in the original scene's render structure ( as 'freestyle_render'): when the render database is generated, the scene's geometrical data is first imported into Freestyle and strokes are calculated. The generated strokes are used to create a Blender scene, rendered independently. The render result is used in the rendering loop. The final rendering is performed the same way edge rendering is, in a function ('freestyle_enhance_add') operating on each individual render part. Freestyle strokes are only included if the toggle button "Freestyle" (in the 'Output' panel) is active and if the "Freestyle" render layer is also selected. Freestyle's panel appears when the toggle button 'Freestyle' is active. IMPORTANT: as of now, rendering ONLY works when OSA is disabled and when Xparts = Yparts = 1. If these settings are not set, a bogus image will be created. To make the render happen, many modifications had to be made: - the Canvas::Draw and Operators::create methods no longer render strokes. They only generate shading and locational information. - a BlenderStrokeRenderer class was added to turn Freestyle's strokes into a Blender scene. Basically, the scene consists of strokes in their projected image 2D coordinates and an orthographic camera centered in the middle of the corresponding canvas. The scene is rendered using vertex colors, in shadeless mode (therefore, no lamp is needed). BlenderStrokeRenderer uses the old GLTextureManager to load textures (as required by the StrokeRenderer class), even though stroke textures are probably not supported (not tested). After the scene is rendered, it is safely and automatically discarded. - AppCanvas' code was greatly reduced to the bare minimum. The former AppCanvas would use an OpenGL-based back buffer and z buffer to determine the scene's color and depth information. In the future, this data will be determined from the corresponding render passes. Currently, the integration is not achieved so all style modules using depth/color information are sure to fail. - before, Freestyle needed an OpenGL context to determine the camera's information and to compute the view map. As of now, the modelview and projection matrices are fully determined using data provided by Blender. This means both perspective and orthographic projections are supported. The AppGLWidget will very soon be removed completely.
2008-12-01 21:30:44 +00:00
#if 0
if (G.debug & G_DEBUG_FREESTYLE) {
cout << "mv" << endl;
}
#endif
real mv[4][4];
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
mv[i][j] = g_freestyle.mv[i][j];
#if 0
if (G.debug & G_DEBUG_FREESTYLE) {
cout << mv[i][j] << " ";
}
#endif
}
#if 0
if (G.debug & G_DEBUG_FREESTYLE) {
cout << endl;
}
#endif
}
#if 0
if (G.debug & G_DEBUG_FREESTYLE) {
cout << "\nproj" << endl;
}
#endif
real proj[4][4];
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
proj[i][j] = g_freestyle.proj[i][j];
#if 0
if (G.debug & G_DEBUG_FREESTYLE) {
cout << proj[i][j] << " ";
}
#endif
}
#if 0
if (G.debug & G_DEBUG_FREESTYLE) {
cout << endl;
}
#endif
}
The GL-based renderer was removed. Freestyle now uses Blender's internal renderer to raster strokes. The render generated from Freestyle's data is currently stored in the original scene's render structure ( as 'freestyle_render'): when the render database is generated, the scene's geometrical data is first imported into Freestyle and strokes are calculated. The generated strokes are used to create a Blender scene, rendered independently. The render result is used in the rendering loop. The final rendering is performed the same way edge rendering is, in a function ('freestyle_enhance_add') operating on each individual render part. Freestyle strokes are only included if the toggle button "Freestyle" (in the 'Output' panel) is active and if the "Freestyle" render layer is also selected. Freestyle's panel appears when the toggle button 'Freestyle' is active. IMPORTANT: as of now, rendering ONLY works when OSA is disabled and when Xparts = Yparts = 1. If these settings are not set, a bogus image will be created. To make the render happen, many modifications had to be made: - the Canvas::Draw and Operators::create methods no longer render strokes. They only generate shading and locational information. - a BlenderStrokeRenderer class was added to turn Freestyle's strokes into a Blender scene. Basically, the scene consists of strokes in their projected image 2D coordinates and an orthographic camera centered in the middle of the corresponding canvas. The scene is rendered using vertex colors, in shadeless mode (therefore, no lamp is needed). BlenderStrokeRenderer uses the old GLTextureManager to load textures (as required by the StrokeRenderer class), even though stroke textures are probably not supported (not tested). After the scene is rendered, it is safely and automatically discarded. - AppCanvas' code was greatly reduced to the bare minimum. The former AppCanvas would use an OpenGL-based back buffer and z buffer to determine the scene's color and depth information. In the future, this data will be determined from the corresponding render passes. Currently, the integration is not achieved so all style modules using depth/color information are sure to fail. - before, Freestyle needed an OpenGL context to determine the camera's information and to compute the view map. As of now, the modelview and projection matrices are fully determined using data provided by Blender. This means both perspective and orthographic projections are supported. The AppGLWidget will very soon be removed completely.
2008-12-01 21:30:44 +00:00
int viewport[4];
for (int i = 0; i < 4; i++) {
viewport[i] = g_freestyle.viewport[i];
}
2009-04-12 07:02:03 +00:00
#if 0
if (G.debug & G_DEBUG_FREESTYLE) {
cout << "\nfocal:" << _pView->GetFocalLength() << endl << endl;
}
#endif
The GL-based renderer was removed. Freestyle now uses Blender's internal renderer to raster strokes. The render generated from Freestyle's data is currently stored in the original scene's render structure ( as 'freestyle_render'): when the render database is generated, the scene's geometrical data is first imported into Freestyle and strokes are calculated. The generated strokes are used to create a Blender scene, rendered independently. The render result is used in the rendering loop. The final rendering is performed the same way edge rendering is, in a function ('freestyle_enhance_add') operating on each individual render part. Freestyle strokes are only included if the toggle button "Freestyle" (in the 'Output' panel) is active and if the "Freestyle" render layer is also selected. Freestyle's panel appears when the toggle button 'Freestyle' is active. IMPORTANT: as of now, rendering ONLY works when OSA is disabled and when Xparts = Yparts = 1. If these settings are not set, a bogus image will be created. To make the render happen, many modifications had to be made: - the Canvas::Draw and Operators::create methods no longer render strokes. They only generate shading and locational information. - a BlenderStrokeRenderer class was added to turn Freestyle's strokes into a Blender scene. Basically, the scene consists of strokes in their projected image 2D coordinates and an orthographic camera centered in the middle of the corresponding canvas. The scene is rendered using vertex colors, in shadeless mode (therefore, no lamp is needed). BlenderStrokeRenderer uses the old GLTextureManager to load textures (as required by the StrokeRenderer class), even though stroke textures are probably not supported (not tested). After the scene is rendered, it is safely and automatically discarded. - AppCanvas' code was greatly reduced to the bare minimum. The former AppCanvas would use an OpenGL-based back buffer and z buffer to determine the scene's color and depth information. In the future, this data will be determined from the corresponding render passes. Currently, the integration is not achieved so all style modules using depth/color information are sure to fail. - before, Freestyle needed an OpenGL context to determine the camera's information and to compute the view map. As of now, the modelview and projection matrices are fully determined using data provided by Blender. This means both perspective and orthographic projections are supported. The AppGLWidget will very soon be removed completely.
2008-12-01 21:30:44 +00:00
// Flag the WXEdge structure for silhouette edge detection:
//----------------------------------------------------------
if (G.debug & G_DEBUG_FREESTYLE) {
cout << "\n=== Detecting silhouette edges ===" << endl;
}
_Chrono.start();
edgeDetector.setViewpoint(vp);
edgeDetector.enableOrthographicProjection(proj[3][3] != 0.0);
edgeDetector.enableRidgesAndValleysFlag(_ComputeRidges);
edgeDetector.enableSuggestiveContours(_ComputeSuggestive);
edgeDetector.enableMaterialBoundaries(_ComputeMaterialBoundaries);
edgeDetector.enableFaceSmoothness(_EnableFaceSmoothness);
edgeDetector.setCreaseAngle(_creaseAngle);
edgeDetector.setSphereRadius(_sphereRadius);
edgeDetector.setSuggestiveContourKrDerivativeEpsilon(_suggestiveContourKrDerivativeEpsilon);
edgeDetector.setRenderMonitor(_pRenderMonitor);
edgeDetector.processShapes(*_winged_edge);
real duration = _Chrono.stop();
if (G.debug & G_DEBUG_FREESTYLE) {
printf("Feature lines : %lf\n", duration);
}
if (_pRenderMonitor->testBreak()) {
return;
}
// Builds the view map structure from the flagged WSEdge structure:
//----------------------------------------------------------
ViewMapBuilder vmBuilder;
vmBuilder.setEnableQI(_EnableQI);
vmBuilder.setViewpoint(vp);
vmBuilder.setTransform(
mv, proj, viewport, _pView->GetFocalLength(), _pView->GetAspect(), _pView->GetFovyRadian());
vmBuilder.setFrustum(_pView->znear(), _pView->zfar());
vmBuilder.setGrid(&_Grid);
vmBuilder.setRenderMonitor(_pRenderMonitor);
#if 0
// Builds a tesselated form of the silhouette for display purpose:
//---------------------------------------------------------------
ViewMapTesselator3D sTesselator3d;
ViewMapTesselator2D sTesselator2d;
sTesselator2d.setNature(_edgeTesselationNature);
sTesselator3d.setNature(_edgeTesselationNature);
#endif
if (G.debug & G_DEBUG_FREESTYLE) {
cout << "\n=== Building the view map ===" << endl;
}
_Chrono.start();
// Build View Map
_ViewMap = vmBuilder.BuildViewMap(
*_winged_edge, _VisibilityAlgo, _EPSILON, _Scene3dBBox, _SceneNumFaces);
_ViewMap->setScene3dBBox(_Scene3dBBox);
if (G.debug & G_DEBUG_FREESTYLE) {
printf("ViewMap edge count : %i\n", _ViewMap->viewedges_size());
}
#if 0
// Tesselate the 3D edges:
_SilhouetteNode = sTesselator3d.Tesselate(_ViewMap);
_SilhouetteNode->addRef();
// Tesselate 2D edges
_ProjectedSilhouette = sTesselator2d.Tesselate(_ViewMap);
_ProjectedSilhouette->addRef();
#endif
duration = _Chrono.stop();
if (G.debug & G_DEBUG_FREESTYLE) {
printf("ViewMap building : %lf\n", duration);
}
#if 0
_pView->AddSilhouette(_SilhouetteNode);
_pView->AddSilhouette(_WRoot);
_pView->Add2DSilhouette(_ProjectedSilhouette);
_pView->Add2DVisibleSilhouette(_VisibleProjectedSilhouette);
_pView->AddDebug(_DebugNode);
#endif
// Draw the steerable density map:
//--------------------------------
if (_ComputeSteerableViewMap) {
ComputeSteerableViewMap();
}
// Reset Style modules modification flags
resetModified(true);
DeleteWingedEdge();
}
void Controller::ComputeSteerableViewMap()
{
#if 0 // soc
if ((!_Canvas) || (!_ViewMap))
return;
// Build 4 nodes containing the edges in the 4 directions
NodeGroup *ng[Canvas::NB_STEERABLE_VIEWMAP];
unsigned i;
real c =
32.0f /
255.0f; // see SteerableViewMap::readSteerableViewMapPixel() for information about this 32.
for (i = 0; i < Canvas::NB_STEERABLE_VIEWMAP; ++i) {
ng[i] = new NodeGroup;
}
NodeShape *completeNS = new NodeShape;
completeNS->material().setDiffuse(c, c, c, 1);
ng[Canvas::NB_STEERABLE_VIEWMAP - 1]->AddChild(completeNS);
SteerableViewMap *svm = _Canvas->getSteerableViewMap();
svm->Reset();
ViewMap::fedges_container &fedges = _ViewMap->FEdges();
LineRep *fRep;
NodeShape *ns;
for (ViewMap::fedges_container::iterator f = fedges.begin(), fend = fedges.end(); f != fend;
++f) {
if ((*f)->viewedge()->qi() != 0)
continue;
fRep = new LineRep((*f)->vertexA()->point2d(), (*f)->vertexB()->point2d());
completeNS->AddRep(fRep); // add to the complete map anyway
double *oweights = svm->AddFEdge(*f);
for (i = 0; i < (Canvas::NB_STEERABLE_VIEWMAP - 1); ++i) {
ns = new NodeShape;
double wc = oweights[i] * c;
if (oweights[i] == 0)
continue;
ns->material().setDiffuse(wc, wc, wc, 1);
ns->AddRep(fRep);
ng[i]->AddChild(ns);
}
}
GrayImage *img[Canvas::NB_STEERABLE_VIEWMAP];
//#ifdef WIN32
QGLBasicWidget offscreenBuffer(_pView, "SteerableViewMap", _pView->width(), _pView->height());
QPixmap pm;
QImage qimg;
for (i = 0; i < Canvas::NB_STEERABLE_VIEWMAP; ++i) {
offscreenBuffer.AddNode(ng[i]);
# if 0
img[i] = new GrayImage(_pView->width(), _pView->height());
offscreenBuffer.readPixels(0,0,_pView->width(), _pView->height(), img[i]->getArray());
# endif
pm = offscreenBuffer.renderPixmap(_pView->width(), _pView->height());
if (pm.isNull()) {
if (G.debug & G_DEBUG_FREESTYLE) {
cout << "BuildViewMap Warning: couldn't render the steerable ViewMap" << endl;
}
}
//pm.save(QString("steerable") + QString::number(i) + QString(".bmp"), "BMP");
// FIXME!! Lost of time !
qimg = pm.toImage();
// FIXME !! again!
img[i] = new GrayImage(_pView->width(), _pView->height());
for (unsigned int y = 0; y < img[i]->height(); ++y) {
for (unsigned int x = 0; x < img[i]->width(); ++x) {
//img[i]->setPixel(x, y, (float)qGray(qimg.pixel(x, y)) / 255.0f);
img[i]->setPixel(x, y, (float)qGray(qimg.pixel(x, y)));
//float c = qGray(qimg.pixel(x, y));
//img[i]->setPixel(x, y, qGray(qimg.pixel(x, y)));
}
}
offscreenBuffer.DetachNode(ng[i]);
ng[i]->destroy();
delete ng[i];
// check
# if 0
qimg = QImage(_pView->width(), _pView->height(), 32);
for (unsigned int y = 0; y < img[i]->height(); ++y) {
for (unsigned int x = 0; x < img[i]->width(); ++x) {
float v = img[i]->pixel(x, y);
qimg.setPixel(x, y, qRgb(v, v, v));
}
}
qimg.save(QString("newsteerable") + QString::number(i) + QString(".bmp"), "BMP");
# endif
}
svm->buildImagesPyramids(img, false, 0, 1.0f);
#endif
}
void Controller::saveSteerableViewMapImages()
{
SteerableViewMap *svm = _Canvas->getSteerableViewMap();
if (!svm) {
cerr << "the Steerable ViewMap has not been computed yet" << endl;
return;
}
svm->saveSteerableViewMap();
}
void Controller::toggleVisibilityAlgo()
{
if (_VisibilityAlgo == ViewMapBuilder::ray_casting) {
_VisibilityAlgo = ViewMapBuilder::ray_casting_fast;
}
else if (_VisibilityAlgo == ViewMapBuilder::ray_casting_fast) {
_VisibilityAlgo = ViewMapBuilder::ray_casting_very_fast;
}
else {
_VisibilityAlgo = ViewMapBuilder::ray_casting;
}
}
Optimized view map calculation by Alexander Beels. * View map calculation has been intensively optimized for speed by means of: 1) new spatial grid data structures (SphericalGrid for perspective cameras and BoxGrid for orthographic cameras; automatically switched based on the camera type); 2) a heuristic grid density calculation algorithm; and 3) new line visibility computation algorithms: A "traditional" algorithm for emulating old visibility algorithms, and a "cumulative" algorithm for improved, more consistent line visibility, both exploiting the new spatial grid data structures for fast ray casting. A new option "Raycasting Algorithm" was added to allow users to choose a ray casting (line visibility) algorithm. Available choices are: - Normal Ray Casting - Fast Ray Casting - Very Fast Ray Casting - Culled Traditional Visibility Detection - Unculled Traditional Visibility Detection - Culled Cumulative Visibility Detection - Unculled Cumulative Visibility Detection The first three algorithms are those available in the original Freestyle (the "normal" ray casting was used unconditionally, though). The "fast" and "very fast" ray casting algorithms achieve a faster calculation at the cost of less visibility accuracy. The last four are newly introduced optimized options. The culled versions of the new algorithms will exclude from visibility calculation those faces that lay outside the camera, which leads to a faster view map construction. The unculled counterparts will take all faces into account. The unculled visibility algorithms are useful when culling affects stroke chaining. The recommended options for users are the culled/unculled cumulative visibility algorithms. These options are meant to replace the old algorithms in the future. Performance improvements over the old algorithms depend on the scenes to be rendered. * Silhouette detection has also been considerably optimized for speed. Performance gains by this optimization do not depend on scenes. * Improper handling of error conditions in the view map construction was fixed.
2011-03-14 00:36:27 +00:00
void Controller::setVisibilityAlgo(int algo)
{
switch (algo) {
case FREESTYLE_ALGO_REGULAR:
_VisibilityAlgo = ViewMapBuilder::ray_casting;
break;
case FREESTYLE_ALGO_FAST:
_VisibilityAlgo = ViewMapBuilder::ray_casting_fast;
break;
case FREESTYLE_ALGO_VERYFAST:
_VisibilityAlgo = ViewMapBuilder::ray_casting_very_fast;
break;
case FREESTYLE_ALGO_CULLED_ADAPTIVE_TRADITIONAL:
_VisibilityAlgo = ViewMapBuilder::ray_casting_culled_adaptive_traditional;
break;
case FREESTYLE_ALGO_ADAPTIVE_TRADITIONAL:
_VisibilityAlgo = ViewMapBuilder::ray_casting_adaptive_traditional;
break;
case FREESTYLE_ALGO_CULLED_ADAPTIVE_CUMULATIVE:
_VisibilityAlgo = ViewMapBuilder::ray_casting_culled_adaptive_cumulative;
break;
case FREESTYLE_ALGO_ADAPTIVE_CUMULATIVE:
_VisibilityAlgo = ViewMapBuilder::ray_casting_adaptive_cumulative;
break;
}
Optimized view map calculation by Alexander Beels. * View map calculation has been intensively optimized for speed by means of: 1) new spatial grid data structures (SphericalGrid for perspective cameras and BoxGrid for orthographic cameras; automatically switched based on the camera type); 2) a heuristic grid density calculation algorithm; and 3) new line visibility computation algorithms: A "traditional" algorithm for emulating old visibility algorithms, and a "cumulative" algorithm for improved, more consistent line visibility, both exploiting the new spatial grid data structures for fast ray casting. A new option "Raycasting Algorithm" was added to allow users to choose a ray casting (line visibility) algorithm. Available choices are: - Normal Ray Casting - Fast Ray Casting - Very Fast Ray Casting - Culled Traditional Visibility Detection - Unculled Traditional Visibility Detection - Culled Cumulative Visibility Detection - Unculled Cumulative Visibility Detection The first three algorithms are those available in the original Freestyle (the "normal" ray casting was used unconditionally, though). The "fast" and "very fast" ray casting algorithms achieve a faster calculation at the cost of less visibility accuracy. The last four are newly introduced optimized options. The culled versions of the new algorithms will exclude from visibility calculation those faces that lay outside the camera, which leads to a faster view map construction. The unculled counterparts will take all faces into account. The unculled visibility algorithms are useful when culling affects stroke chaining. The recommended options for users are the culled/unculled cumulative visibility algorithms. These options are meant to replace the old algorithms in the future. Performance improvements over the old algorithms depend on the scenes to be rendered. * Silhouette detection has also been considerably optimized for speed. Performance gains by this optimization do not depend on scenes. * Improper handling of error conditions in the view map construction was fixed.
2011-03-14 00:36:27 +00:00
}
int Controller::getVisibilityAlgo()
{
switch (_VisibilityAlgo) {
case ViewMapBuilder::ray_casting:
return FREESTYLE_ALGO_REGULAR;
case ViewMapBuilder::ray_casting_fast:
return FREESTYLE_ALGO_FAST;
case ViewMapBuilder::ray_casting_very_fast:
return FREESTYLE_ALGO_VERYFAST;
case ViewMapBuilder::ray_casting_culled_adaptive_traditional:
return FREESTYLE_ALGO_CULLED_ADAPTIVE_TRADITIONAL;
case ViewMapBuilder::ray_casting_adaptive_traditional:
return FREESTYLE_ALGO_ADAPTIVE_TRADITIONAL;
case ViewMapBuilder::ray_casting_culled_adaptive_cumulative:
return FREESTYLE_ALGO_CULLED_ADAPTIVE_CUMULATIVE;
case ViewMapBuilder::ray_casting_adaptive_cumulative:
return FREESTYLE_ALGO_ADAPTIVE_CUMULATIVE;
}
// ray_casting_adaptive_traditional is the most exact replacement
// for legacy code
return FREESTYLE_ALGO_ADAPTIVE_TRADITIONAL;
Optimized view map calculation by Alexander Beels. * View map calculation has been intensively optimized for speed by means of: 1) new spatial grid data structures (SphericalGrid for perspective cameras and BoxGrid for orthographic cameras; automatically switched based on the camera type); 2) a heuristic grid density calculation algorithm; and 3) new line visibility computation algorithms: A "traditional" algorithm for emulating old visibility algorithms, and a "cumulative" algorithm for improved, more consistent line visibility, both exploiting the new spatial grid data structures for fast ray casting. A new option "Raycasting Algorithm" was added to allow users to choose a ray casting (line visibility) algorithm. Available choices are: - Normal Ray Casting - Fast Ray Casting - Very Fast Ray Casting - Culled Traditional Visibility Detection - Unculled Traditional Visibility Detection - Culled Cumulative Visibility Detection - Unculled Cumulative Visibility Detection The first three algorithms are those available in the original Freestyle (the "normal" ray casting was used unconditionally, though). The "fast" and "very fast" ray casting algorithms achieve a faster calculation at the cost of less visibility accuracy. The last four are newly introduced optimized options. The culled versions of the new algorithms will exclude from visibility calculation those faces that lay outside the camera, which leads to a faster view map construction. The unculled counterparts will take all faces into account. The unculled visibility algorithms are useful when culling affects stroke chaining. The recommended options for users are the culled/unculled cumulative visibility algorithms. These options are meant to replace the old algorithms in the future. Performance improvements over the old algorithms depend on the scenes to be rendered. * Silhouette detection has also been considerably optimized for speed. Performance gains by this optimization do not depend on scenes. * Improper handling of error conditions in the view map construction was fixed.
2011-03-14 00:36:27 +00:00
}
void Controller::setViewMapCache(bool iBool)
{
_EnableViewMapCache = iBool;
}
bool Controller::getViewMapCache() const
{
return _EnableViewMapCache;
}
void Controller::setQuantitativeInvisibility(bool iBool)
{
_EnableQI = iBool;
}
bool Controller::getQuantitativeInvisibility() const
{
return _EnableQI;
}
Optimized view map calculation by Alexander Beels. * View map calculation has been intensively optimized for speed by means of: 1) new spatial grid data structures (SphericalGrid for perspective cameras and BoxGrid for orthographic cameras; automatically switched based on the camera type); 2) a heuristic grid density calculation algorithm; and 3) new line visibility computation algorithms: A "traditional" algorithm for emulating old visibility algorithms, and a "cumulative" algorithm for improved, more consistent line visibility, both exploiting the new spatial grid data structures for fast ray casting. A new option "Raycasting Algorithm" was added to allow users to choose a ray casting (line visibility) algorithm. Available choices are: - Normal Ray Casting - Fast Ray Casting - Very Fast Ray Casting - Culled Traditional Visibility Detection - Unculled Traditional Visibility Detection - Culled Cumulative Visibility Detection - Unculled Cumulative Visibility Detection The first three algorithms are those available in the original Freestyle (the "normal" ray casting was used unconditionally, though). The "fast" and "very fast" ray casting algorithms achieve a faster calculation at the cost of less visibility accuracy. The last four are newly introduced optimized options. The culled versions of the new algorithms will exclude from visibility calculation those faces that lay outside the camera, which leads to a faster view map construction. The unculled counterparts will take all faces into account. The unculled visibility algorithms are useful when culling affects stroke chaining. The recommended options for users are the culled/unculled cumulative visibility algorithms. These options are meant to replace the old algorithms in the future. Performance improvements over the old algorithms depend on the scenes to be rendered. * Silhouette detection has also been considerably optimized for speed. Performance gains by this optimization do not depend on scenes. * Improper handling of error conditions in the view map construction was fixed.
2011-03-14 00:36:27 +00:00
void Controller::setFaceSmoothness(bool iBool)
{
_EnableFaceSmoothness = iBool;
Optimized view map calculation by Alexander Beels. * View map calculation has been intensively optimized for speed by means of: 1) new spatial grid data structures (SphericalGrid for perspective cameras and BoxGrid for orthographic cameras; automatically switched based on the camera type); 2) a heuristic grid density calculation algorithm; and 3) new line visibility computation algorithms: A "traditional" algorithm for emulating old visibility algorithms, and a "cumulative" algorithm for improved, more consistent line visibility, both exploiting the new spatial grid data structures for fast ray casting. A new option "Raycasting Algorithm" was added to allow users to choose a ray casting (line visibility) algorithm. Available choices are: - Normal Ray Casting - Fast Ray Casting - Very Fast Ray Casting - Culled Traditional Visibility Detection - Unculled Traditional Visibility Detection - Culled Cumulative Visibility Detection - Unculled Cumulative Visibility Detection The first three algorithms are those available in the original Freestyle (the "normal" ray casting was used unconditionally, though). The "fast" and "very fast" ray casting algorithms achieve a faster calculation at the cost of less visibility accuracy. The last four are newly introduced optimized options. The culled versions of the new algorithms will exclude from visibility calculation those faces that lay outside the camera, which leads to a faster view map construction. The unculled counterparts will take all faces into account. The unculled visibility algorithms are useful when culling affects stroke chaining. The recommended options for users are the culled/unculled cumulative visibility algorithms. These options are meant to replace the old algorithms in the future. Performance improvements over the old algorithms depend on the scenes to be rendered. * Silhouette detection has also been considerably optimized for speed. Performance gains by this optimization do not depend on scenes. * Improper handling of error conditions in the view map construction was fixed.
2011-03-14 00:36:27 +00:00
}
bool Controller::getFaceSmoothness() const
{
return _EnableFaceSmoothness;
Optimized view map calculation by Alexander Beels. * View map calculation has been intensively optimized for speed by means of: 1) new spatial grid data structures (SphericalGrid for perspective cameras and BoxGrid for orthographic cameras; automatically switched based on the camera type); 2) a heuristic grid density calculation algorithm; and 3) new line visibility computation algorithms: A "traditional" algorithm for emulating old visibility algorithms, and a "cumulative" algorithm for improved, more consistent line visibility, both exploiting the new spatial grid data structures for fast ray casting. A new option "Raycasting Algorithm" was added to allow users to choose a ray casting (line visibility) algorithm. Available choices are: - Normal Ray Casting - Fast Ray Casting - Very Fast Ray Casting - Culled Traditional Visibility Detection - Unculled Traditional Visibility Detection - Culled Cumulative Visibility Detection - Unculled Cumulative Visibility Detection The first three algorithms are those available in the original Freestyle (the "normal" ray casting was used unconditionally, though). The "fast" and "very fast" ray casting algorithms achieve a faster calculation at the cost of less visibility accuracy. The last four are newly introduced optimized options. The culled versions of the new algorithms will exclude from visibility calculation those faces that lay outside the camera, which leads to a faster view map construction. The unculled counterparts will take all faces into account. The unculled visibility algorithms are useful when culling affects stroke chaining. The recommended options for users are the culled/unculled cumulative visibility algorithms. These options are meant to replace the old algorithms in the future. Performance improvements over the old algorithms depend on the scenes to be rendered. * Silhouette detection has also been considerably optimized for speed. Performance gains by this optimization do not depend on scenes. * Improper handling of error conditions in the view map construction was fixed.
2011-03-14 00:36:27 +00:00
}
void Controller::setComputeRidgesAndValleysFlag(bool iBool)
{
_ComputeRidges = iBool;
}
bool Controller::getComputeRidgesAndValleysFlag() const
{
return _ComputeRidges;
}
void Controller::setComputeSuggestiveContoursFlag(bool b)
{
_ComputeSuggestive = b;
}
bool Controller::getComputeSuggestiveContoursFlag() const
{
return _ComputeSuggestive;
}
void Controller::setComputeMaterialBoundariesFlag(bool b)
{
_ComputeMaterialBoundaries = b;
}
bool Controller::getComputeMaterialBoundariesFlag() const
{
return _ComputeMaterialBoundaries;
}
void Controller::setComputeSteerableViewMapFlag(bool iBool)
{
_ComputeSteerableViewMap = iBool;
}
bool Controller::getComputeSteerableViewMapFlag() const
{
return _ComputeSteerableViewMap;
}
int Controller::DrawStrokes()
{
if (_ViewMap == 0) {
return 0;
}
if (G.debug & G_DEBUG_FREESTYLE) {
cout << "\n=== Stroke drawing ===" << endl;
}
_Chrono.start();
_Canvas->Draw();
real d = _Chrono.stop();
int strokeCount = _Canvas->getStrokeCount();
if (G.debug & G_DEBUG_FREESTYLE) {
cout << "Strokes generation : " << d << endl;
cout << "Stroke count : " << strokeCount << endl;
}
resetModified();
DeleteViewMap();
return strokeCount;
}
void Controller::ResetRenderCount()
{
_render_count = 0;
}
Render *Controller::RenderStrokes(Render *re, bool render)
{
int totmesh = 0;
_Chrono.start();
BlenderStrokeRenderer *blenderRenderer = new BlenderStrokeRenderer(re, ++_render_count);
if (render) {
_Canvas->Render(blenderRenderer);
totmesh = blenderRenderer->GenerateScene();
}
real d = _Chrono.stop();
if (G.debug & G_DEBUG_FREESTYLE) {
cout << "Temporary scene generation: " << d << endl;
}
_Chrono.start();
Render *freestyle_render = blenderRenderer->RenderScene(re, render);
d = _Chrono.stop();
if (G.debug & G_DEBUG_FREESTYLE) {
cout << "Stroke rendering : " << d << endl;
uintptr_t mem_in_use = MEM_get_memory_in_use();
uintptr_t mmap_in_use = MEM_get_mapped_memory_in_use();
uintptr_t peak_memory = MEM_get_peak_memory();
float megs_used_memory = (mem_in_use - mmap_in_use) / (1024.0 * 1024.0);
float mmap_used_memory = (mmap_in_use) / (1024.0 * 1024.0);
float megs_peak_memory = (peak_memory) / (1024.0 * 1024.0);
printf("%d objs, %d verts, %d faces, mem %.2fM (%.2fM, peak %.2fM)\n",
totmesh,
freestyle_render->i.totvert,
freestyle_render->i.totface,
megs_used_memory,
mmap_used_memory,
megs_peak_memory);
}
delete blenderRenderer;
return freestyle_render;
The GL-based renderer was removed. Freestyle now uses Blender's internal renderer to raster strokes. The render generated from Freestyle's data is currently stored in the original scene's render structure ( as 'freestyle_render'): when the render database is generated, the scene's geometrical data is first imported into Freestyle and strokes are calculated. The generated strokes are used to create a Blender scene, rendered independently. The render result is used in the rendering loop. The final rendering is performed the same way edge rendering is, in a function ('freestyle_enhance_add') operating on each individual render part. Freestyle strokes are only included if the toggle button "Freestyle" (in the 'Output' panel) is active and if the "Freestyle" render layer is also selected. Freestyle's panel appears when the toggle button 'Freestyle' is active. IMPORTANT: as of now, rendering ONLY works when OSA is disabled and when Xparts = Yparts = 1. If these settings are not set, a bogus image will be created. To make the render happen, many modifications had to be made: - the Canvas::Draw and Operators::create methods no longer render strokes. They only generate shading and locational information. - a BlenderStrokeRenderer class was added to turn Freestyle's strokes into a Blender scene. Basically, the scene consists of strokes in their projected image 2D coordinates and an orthographic camera centered in the middle of the corresponding canvas. The scene is rendered using vertex colors, in shadeless mode (therefore, no lamp is needed). BlenderStrokeRenderer uses the old GLTextureManager to load textures (as required by the StrokeRenderer class), even though stroke textures are probably not supported (not tested). After the scene is rendered, it is safely and automatically discarded. - AppCanvas' code was greatly reduced to the bare minimum. The former AppCanvas would use an OpenGL-based back buffer and z buffer to determine the scene's color and depth information. In the future, this data will be determined from the corresponding render passes. Currently, the integration is not achieved so all style modules using depth/color information are sure to fail. - before, Freestyle needed an OpenGL context to determine the camera's information and to compute the view map. As of now, the modelview and projection matrices are fully determined using data provided by Blender. This means both perspective and orthographic projections are supported. The AppGLWidget will very soon be removed completely.
2008-12-01 21:30:44 +00:00
}
void Controller::InsertStyleModule(unsigned index, const char *iFileName)
{
if (!BLI_path_extension_check(iFileName, ".py")) {
cerr << "Error: Cannot load \"" << string(iFileName) << "\", unknown extension" << endl;
return;
}
StyleModule *sm = new StyleModule(iFileName, _inter);
_Canvas->InsertStyleModule(index, sm);
}
void Controller::InsertStyleModule(unsigned index, const char *iName, const char *iBuffer)
{
StyleModule *sm = new BufferedStyleModule(iBuffer, iName, _inter);
_Canvas->InsertStyleModule(index, sm);
}
void Controller::InsertStyleModule(unsigned index, const char *iName, struct Text *iText)
{
StyleModule *sm = new BlenderStyleModule(iText, iName, _inter);
_Canvas->InsertStyleModule(index, sm);
}
void Controller::AddStyleModule(const char * /*iFileName*/)
{
//_pStyleWindow->Add(iFileName);
}
void Controller::RemoveStyleModule(unsigned index)
{
_Canvas->RemoveStyleModule(index);
}
void Controller::Clear()
{
_Canvas->Clear();
}
void Controller::ReloadStyleModule(unsigned index, const char *iFileName)
{
StyleModule *sm = new StyleModule(iFileName, _inter);
_Canvas->ReplaceStyleModule(index, sm);
}
void Controller::SwapStyleModules(unsigned i1, unsigned i2)
{
_Canvas->SwapStyleModules(i1, i2);
}
void Controller::toggleLayer(unsigned index, bool iDisplay)
{
_Canvas->setVisible(index, iDisplay);
}
void Controller::setModified(unsigned index, bool iMod)
{
//_pStyleWindow->setModified(index, iMod);
_Canvas->setModified(index, iMod);
updateCausalStyleModules(index + 1);
}
void Controller::updateCausalStyleModules(unsigned index)
{
vector<unsigned> vec;
_Canvas->causalStyleModules(vec, index);
for (vector<unsigned>::const_iterator it = vec.begin(); it != vec.end(); it++) {
//_pStyleWindow->setModified(*it, true);
_Canvas->setModified(*it, true);
}
}
void Controller::resetModified(bool iMod)
{
//_pStyleWindow->resetModified(iMod);
_Canvas->resetModified(iMod);
}
NodeGroup *Controller::BuildRep(vector<ViewEdge *>::iterator vedges_begin,
vector<ViewEdge *>::iterator vedges_end)
{
ViewMapTesselator2D tesselator2D;
FrsMaterial mat;
mat.setDiffuse(1, 1, 0.3, 1);
tesselator2D.setFrsMaterial(mat);
return (tesselator2D.Tesselate(vedges_begin, vedges_end));
}
void Controller::toggleEdgeTesselationNature(Nature::EdgeNature iNature)
{
_edgeTesselationNature ^= (iNature);
ComputeViewMap();
}
void Controller::setModelsDir(const string & /*dir*/)
{
//_current_dirs->setValue("models/dir", dir);
}
string Controller::getModelsDir() const
{
string dir = ".";
//_current_dirs->getValue("models/dir", dir);
return dir;
}
void Controller::setModulesDir(const string & /*dir*/)
{
//_current_dirs->setValue("modules/dir", dir);
}
string Controller::getModulesDir() const
{
string dir = ".";
//_current_dirs->getValue("modules/dir", dir);
return dir;
}
void Controller::resetInterpreter()
{
if (_inter) {
_inter->reset();
}
}
void Controller::displayDensityCurves(int x, int y)
{
SteerableViewMap *svm = _Canvas->getSteerableViewMap();
if (!svm) {
return;
}
unsigned int i, j;
typedef vector<Vec3r> densityCurve;
vector<densityCurve> curves(svm->getNumberOfOrientations() + 1);
vector<densityCurve> curvesDirection(svm->getNumberOfPyramidLevels());
// collect the curves values
unsigned nbCurves = svm->getNumberOfOrientations() + 1;
unsigned nbPoints = svm->getNumberOfPyramidLevels();
if (!nbPoints) {
return;
}
// build the density/nbLevels curves for each orientation
for (i = 0; i < nbCurves; ++i) {
for (j = 0; j < nbPoints; ++j) {
curves[i].push_back(Vec3r(j, svm->readSteerableViewMapPixel(i, j, x, y), 0));
}
}
// build the density/nbOrientations curves for each level
for (i = 0; i < nbPoints; ++i) {
for (j = 0; j < nbCurves; ++j) {
curvesDirection[i].push_back(Vec3r(j, svm->readSteerableViewMapPixel(j, i, x, y), 0));
}
}
// display the curves
#if 0
for (i = 0; i < nbCurves; ++i)
_pDensityCurvesWindow->setOrientationCurve(
i, Vec2d(0, 0), Vec2d(nbPoints, 1), curves[i], "scale", "density");
for (i = 1; i <= 8; ++i)
_pDensityCurvesWindow->setLevelCurve(
i, Vec2d(0, 0), Vec2d(nbCurves, 1), curvesDirection[i], "orientation", "density");
_pDensityCurvesWindow->show();
#endif
}
void Controller::init_options()
{
// from AppOptionsWindow.cpp
// Default init options
Config::Path *cpath = Config::Path::getInstance();
// Directories
ViewMapIO::Options::setModelsPath(cpath->getModelsPath());
TextureManager::Options::setPatternsPath(cpath->getPatternsPath());
TextureManager::Options::setBrushesPath(cpath->getModelsPath());
// ViewMap Format
ViewMapIO::Options::rmFlags(ViewMapIO::Options::FLOAT_VECTORS);
ViewMapIO::Options::rmFlags(ViewMapIO::Options::NO_OCCLUDERS);
setComputeSteerableViewMapFlag(false);
// Visibility
setQuantitativeInvisibility(true);
// soc: initialize canvas
_Canvas->init();
// soc: initialize passes
setPassDiffuse(NULL, 0, 0);
setPassZ(NULL, 0, 0);
}
Attempt to fix a potential name conflict between Freestyle and the compositor. A crash in the Freestyle renderer was reported by Ton on IRC with a stack trace below. Note that #2 is in Freestyle, whereas #1 is in the compositor. The problem was observed in a debug build on OS X 10.7 (gcc 4.2, openmp disabled, no llvm). ---------------------------------------------------------------------- Program received signal EXC_BAD_ACCESS, Could not access memory. Reason: 13 at address: 0x0000000000000000 [Switching to process 72386 thread 0xf303] 0x0000000100c129f3 in NodeBase::~NodeBase (this=0x10e501c80) at COM_NodeBase.cpp:43 43 delete (this->m_outputsockets.back()); Current language: auto; currently c++ (gdb) where #0 0x0000000100c129f3 in NodeBase::~NodeBase (this=0x10e501c80) at COM_NodeBase.cpp:43 #1 0x0000000100c29066 in Node::~Node (this=0x10e501c80) at COM_Node.h:49 #2 0x000000010089c273 in NodeShape::~NodeShape (this=0x10e501c80) at NodeShape.cpp:43 #3 0x000000010089910b in NodeGroup::destroy (this=0x10e501da0) at NodeGroup.cpp:61 #4 0x00000001008990cd in NodeGroup::destroy (this=0x10e5014b0) at NodeGroup.cpp:59 #5 0x00000001008990cd in NodeGroup::destroy (this=0x114e18da0) at NodeGroup.cpp:59 #6 0x00000001007e6602 in Controller::ClearRootNode (this=0x114e19640) at Controller.cpp:329 #7 0x00000001007ea52e in Controller::LoadMesh (this=0x114e19640, re=0x10aba4638, srl=0x1140f5258) at Controller.cpp:302 #8 0x00000001008030ad in prepare (re=0x10aba4638, srl=0x1140f5258) at FRS_freestyle.cpp:302 #9 0x000000010080457a in FRS_do_stroke_rendering (re=0x10aba4638, srl=0x1140f5258) at FRS_freestyle.cpp:600 #10 0x00000001006aeb9d in add_freestyle (re=0x10aba4638) at pipeline.c:1584 #11 0x00000001006aceb7 in do_render_3d (re=0x10aba4638) at pipeline.c:1094 #12 0x00000001006ae061 in do_render_fields_blur_3d (re=0x10aba4638) at pipeline.c:1367 #13 0x00000001006afa16 in do_render_composite_fields_blur_3d (re=0x10aba4638) at pipeline.c:1815 #14 0x00000001006b04e4 in do_render_all_options (re=0x10aba4638) at pipeline.c:2021 ---------------------------------------------------------------------- Apparently a name conflict between the two Blender modules is taking place. The present commit hence intends to address it by putting all the Freestyle C++ classes in the namespace 'Freestyle'. This revision will also prevent potential name conflicts with other Blender modules in the future. Special thanks to Lukas Toenne for the help with C++ namespace.
2013-04-09 00:46:49 +00:00
} /* namespace Freestyle */