diff options
Diffstat (limited to 'source/blender/freestyle/intern/application')
9 files changed, 2195 insertions, 0 deletions
diff --git a/source/blender/freestyle/intern/application/AppCanvas.cpp b/source/blender/freestyle/intern/application/AppCanvas.cpp new file mode 100755 index 00000000000..848d8ce08bb --- /dev/null +++ b/source/blender/freestyle/intern/application/AppCanvas.cpp @@ -0,0 +1,138 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "../rendering/GLBlendEquation.h" + +#include "AppView.h" +#include "../image/Image.h" +#include "../system/TimeStamp.h" +#include "Controller.h" +#include "../stroke/StrokeRenderer.h" +#include "AppCanvas.h" +#include "../rendering/GLRenderer.h" +#include "../rendering/GLStrokeRenderer.h" +#include "AppConfig.h" + +#include "../system/StringUtils.h" + +AppCanvas::AppCanvas() +:Canvas() +{ + _pViewer = 0; + _MapsPath = StringUtils::toAscii( Config::Path::getInstance()->getMapsDir() ).c_str(); +} + +AppCanvas::AppCanvas(AppView* iViewer) +:Canvas() +{ + _pViewer = iViewer; +} + +AppCanvas::AppCanvas(const AppCanvas& iBrother) +:Canvas(iBrother) +{ + _pViewer = iBrother._pViewer; +} + +AppCanvas::~AppCanvas() +{ + _pViewer = 0; +} + +void AppCanvas::setViewer(AppView *iViewer) +{ + _pViewer = iViewer; +} + +int AppCanvas::width() const +{ + return _pViewer->width(); +} + +int AppCanvas::height() const +{ + return _pViewer->height();; +} + +BBox<Vec3r> AppCanvas::scene3DBBox() const +{ + return _pViewer->scene3DBBox(); +} + +void AppCanvas::preDraw() +{ + Canvas::preDraw(); +} + +void AppCanvas::init() +{ + + // static bool firsttime = true; + // if (firsttime) { + // + // _Renderer = new BlenderStrokeRenderer; + // if(!StrokeRenderer::loadTextures()) + // { + // cerr << "unable to load stroke textures" << endl; + // return; + // } + // } +} + +void AppCanvas::postDraw() +{ + Canvas::postDraw(); +} + +void AppCanvas::Erase() +{ + Canvas::Erase(); +} + +// Abstract + +#include "../image/GaussianFilter.h" +void AppCanvas::readColorPixels(int x,int y,int w, int h, RGBImage& oImage) const +{ + //static unsigned number = 0; + float *rgb = new float[3*w*h]; + //_pViewer->readPixels(x,y,w,h,AppGLWidget::RGB,rgb); + oImage.setArray(rgb, width(), height(), w,h, x, y, false); +} + +void AppCanvas::readDepthPixels(int x,int y,int w, int h, GrayImage& oImage) const +{ + float *rgb = new float[w*h]; + //_pViewer->readPixels(x,y,w,h,AppGLWidget::DEPTH,rgb); + oImage.setArray(rgb, width(), height(), w,h, x, y, false); +} + +void AppCanvas::RenderStroke(Stroke *iStroke) { + + if(_basic) + iStroke->RenderBasic(_Renderer); + else + iStroke->Render(_Renderer); +} + + +void AppCanvas::update() {} + diff --git a/source/blender/freestyle/intern/application/AppCanvas.h b/source/blender/freestyle/intern/application/AppCanvas.h new file mode 100755 index 00000000000..fa8d3cba373 --- /dev/null +++ b/source/blender/freestyle/intern/application/AppCanvas.h @@ -0,0 +1,52 @@ +#ifndef ARTCANVAS_H +#define ARTCANVAS_H + +#include "../stroke/Canvas.h" +#include "AppView.h" + +class AppCanvas : public Canvas +{ + +public: + AppCanvas(); + AppCanvas(AppView *iViewer); + AppCanvas(const AppCanvas& iBrother); + virtual ~AppCanvas(); + + /*! operations that need to be done before a draw */ + virtual void preDraw(); + + /*! operations that need to be done after a draw */ + virtual void postDraw(); + + /*! Erases the layers and clears the canvas */ + virtual void Erase(); + + /* init the canvas */ + virtual void init(); + + /*! Reads a pixel area from the canvas */ + virtual void readColorPixels(int x,int y,int w, int h, RGBImage& oImage) const; + /*! Reads a depth pixel area from the canvas */ + virtual void readDepthPixels(int x,int y,int w, int h, GrayImage& oImage) const; + + virtual BBox<Vec3r> scene3DBBox() const ; + + // abstract + virtual void RenderStroke(Stroke*); + virtual void update(); + + + /*! accessors */ + virtual int width() const ; + virtual int height() const ; + + AppView *_pViewer; + inline const AppView * viewer() const {return _pViewer;} + + /*! modifiers */ + void setViewer(AppView *iViewer) ; +}; + + +#endif diff --git a/source/blender/freestyle/intern/application/AppConfig.cpp b/source/blender/freestyle/intern/application/AppConfig.cpp new file mode 100755 index 00000000000..9ef14321624 --- /dev/null +++ b/source/blender/freestyle/intern/application/AppConfig.cpp @@ -0,0 +1,92 @@ +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "AppConfig.h" +#include <iostream> + +#include "../system/StringUtils.h" +using namespace std; + +extern "C" { + #include "BLI_util.h" +} + +namespace Config { +Path* Path::_pInstance = 0; +Path::Path() { + // get the root directory + //soc + setRootDir( BLI_gethome_folder("scripts", BLI_GETHOME_ALL) ); + + _pInstance = this; +} +void Path::setRootDir(const string& iRootDir) { + _ProjectDir = iRootDir + string(DIR_SEP.c_str()) + "freestyle"; + _ModelsPath = ""; + _PatternsPath = _ProjectDir + string(DIR_SEP.c_str()) + "data" + + string(DIR_SEP.c_str()) + "textures" + string(DIR_SEP.c_str()) + + "variation_patterns" + string(DIR_SEP.c_str()); + _BrushesPath = _ProjectDir + string(DIR_SEP.c_str()) + "data" + + string(DIR_SEP.c_str()) + "textures" + string(DIR_SEP.c_str()) + + "brushes" + string(DIR_SEP.c_str()); + _PythonPath = _ProjectDir + string(DIR_SEP.c_str()) ++ "style_modules" + string(DIR_SEP.c_str()) ; + if (getenv("PYTHONPATH")) { + _PythonPath += string(PATH_SEP.c_str()) + string(getenv("PYTHONPATH")); + } +#ifdef WIN32 + _BrowserCmd = "C:\\Program Files\\Internet Explorer\\iexplore.exe %s"; +#else + _BrowserCmd = "mozilla %s"; +#endif + _HelpIndexPath = _ProjectDir + string(DIR_SEP.c_str()) + "doc" + + string(DIR_SEP.c_str()) + "html" + string(DIR_SEP.c_str()) + + "index.html"; + _EnvMapDir = _ProjectDir + string(DIR_SEP.c_str()) + "data" + + string(DIR_SEP.c_str()) + "env_map" + string(DIR_SEP.c_str()); + _MapsDir = _ProjectDir + string(DIR_SEP.c_str()) + "data" + + string(DIR_SEP.c_str()) + "maps" + string(DIR_SEP.c_str()); +} +void Path::setHomeDir(const string& iHomeDir) { + _HomeDir = iHomeDir; +} +Path::~Path() { + _pInstance = 0; +} +Path* Path::getInstance() { + return _pInstance; +} +string Path::getEnvVar(const string& iEnvVarName) { + string value; + if (!getenv(StringUtils::toAscii(iEnvVarName).c_str() ) ) { + cerr << "Warning: You may want to set the $" + << StringUtils::toAscii(iEnvVarName) + << " environment variable to use Freestyle." << endl + << " Otherwise, the current directory will be used instead." + << endl; + value = "."; + } else { + value = getenv(StringUtils::toAscii(iEnvVarName).c_str() ); + } + return value; +} + +} // End of namepace Config + diff --git a/source/blender/freestyle/intern/application/AppConfig.h b/source/blender/freestyle/intern/application/AppConfig.h new file mode 100755 index 00000000000..59e85ca2e17 --- /dev/null +++ b/source/blender/freestyle/intern/application/AppConfig.h @@ -0,0 +1,105 @@ +// +// Filename : AppConfig.h +// Author : Emmanuel Turquin +// Purpose : Configuration file +// Date of creation : 26/02/2003 +// +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef APP_CONFIG_H +# define APP_CONFIG_H + +# include <string> +# include "../system/FreestyleConfig.h" +# include "../system/Precision.h" + +using namespace std; + +namespace Config { + + class Path{ + protected: + static Path * _pInstance; + string _ProjectDir; + string _ModelsPath; + string _PatternsPath; + string _BrushesPath; + string _PythonPath; + string _BrowserCmd; + string _HelpIndexPath; + string _EnvMapDir; + string _MapsDir; + string _HomeDir; + public: + Path(); + virtual ~Path(); + static Path* getInstance(); + + void setRootDir(const string& iRootDir) ; + void setHomeDir(const string& iHomeDir) ; + + const string& getProjectDir() const {return _ProjectDir;} + const string& getModelsPath() const {return _ModelsPath;} + const string& getPatternsPath() const {return _PatternsPath;} + const string& getBrushesPath() const {return _BrushesPath;} + const string& getPythonPath() const {return _PythonPath;} + const string& getBrowserCmd() const {return _BrowserCmd;} + const string& getHelpIndexpath() const {return _HelpIndexPath;} + const string& getEnvMapDir() const {return _EnvMapDir;} + const string& getMapsDir() const {return _MapsDir;} + const string& getHomeDir() const {return _HomeDir;} + + static string getEnvVar(const string& iEnvVarName); + + }; + + // + // Configuration, default values + // + ////////////////////////////////////////////////////////////// + + // Application + static const string APPLICATION_NAME("APPNAME"); + static const string APPLICATION_VERSION("APPVERSION"); + + // ViewMap + static const string VIEWMAP_EXTENSION("vm"); + static const string VIEWMAP_MAGIC("ViewMap File"); + static const string VIEWMAP_VERSION("1.9"); + + // Style modules + static const string STYLE_MODULE_EXTENSION("py"); + static const string STYLE_MODULES_LIST_EXTENSION("sml"); + + // Options + static const string OPTIONS_DIR("." + APPLICATION_NAME); + static const string OPTIONS_FILE("options.xml"); + static const string OPTIONS_CURRENT_DIRS_FILE("current_dirs.xml"); + static const string OPTIONS_QGLVIEWER_FILE("qglviewer.xml"); + + // Default options + static const real DEFAULT_SPHERE_RADIUS = 1.0; + static const real DEFAULT_DKR_EPSILON = 0.0; + +} // End of namepace Config + +#endif // APP_CONFIG_H diff --git a/source/blender/freestyle/intern/application/AppView.cpp b/source/blender/freestyle/intern/application/AppView.cpp new file mode 100644 index 00000000000..8f918e64038 --- /dev/null +++ b/source/blender/freestyle/intern/application/AppView.cpp @@ -0,0 +1,176 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#include <iostream> +#include "../stroke/Canvas.h" +#include "AppView.h" +#include "../scene_graph/NodeLight.h" +#include "Controller.h" +#include "../view_map/Silhouette.h" +#include "../view_map/ViewMap.h" +#include "../scene_graph/LineRep.h" +#include "../scene_graph/NodeShape.h" +#include "../scene_graph/VertexRep.h" +#include "AppConfig.h" + +#include "../system/StringUtils.h" + +extern "C" { +#include "BLI_blenlib.h" +#include "BLI_jitter.h" +#include "IMB_imbuf.h" +#include "IMB_imbuf_types.h" +#if 1 // FRS_antialiasing +#include "BKE_global.h" +#include "DNA_scene_types.h" +#endif + +#include "../../FRS_freestyle.h" + +} + +AppView::AppView(const char *iName) +{ + _Fovy = 30.f * M_PI / 180.0; + _ModelRootNode = new NodeDrawingStyle; + _SilhouetteRootNode = new NodeDrawingStyle; + _DebugRootNode = new NodeDrawingStyle; + + _RootNode.AddChild(_ModelRootNode); + _SilhouetteRootNode->setStyle(DrawingStyle::LINES); + _SilhouetteRootNode->setLightingEnabled(false); + _SilhouetteRootNode->setLineWidth(2.f); + _SilhouetteRootNode->setPointSize(3.f); + + _RootNode.AddChild(_SilhouetteRootNode); + + _DebugRootNode->setStyle(DrawingStyle::LINES); + _DebugRootNode->setLightingEnabled(false); + _DebugRootNode->setLineWidth(1.f); + + _RootNode.AddChild(_DebugRootNode); + + _minBBox = __min(__min(_ModelRootNode->bbox().getMin()[0], + _ModelRootNode->bbox().getMin()[1]), + _ModelRootNode->bbox().getMin()[2]); + _maxBBox = __max(__max(_ModelRootNode->bbox().getMax()[0], + _ModelRootNode->bbox().getMax()[1]), + _ModelRootNode->bbox().getMax()[2]); + + _maxAbs = __max(rabs(_minBBox), rabs(_maxBBox)); + _minAbs = __min(rabs(_minBBox), rabs(_maxBBox)); + + _p2DSelectionNode = new NodeDrawingStyle; + _p2DSelectionNode->setLightingEnabled(false); + _p2DSelectionNode->setStyle(DrawingStyle::LINES); + _p2DSelectionNode->setLineWidth(5.f); + + _p2DNode.AddChild(_p2DSelectionNode); + + + NodeLight *light = new NodeLight; + _Light.AddChild(light); +} + +AppView::~AppView() +{ + int ref = _RootNode.destroy(); + + _Light.destroy(); + ref = _p2DNode.destroy(); + +} + +real AppView::distanceToSceneCenter() { + BBox<Vec3r> bbox = _ModelRootNode->bbox(); + + Vec3r v( freestyle_viewpoint[0], freestyle_viewpoint[1], freestyle_viewpoint[2]); + v -= 0.5 * (bbox.getMin() + bbox.getMax()); + + return v.norm(); +} + + +real AppView::znear() { + + BBox<Vec3r> bbox = _ModelRootNode->bbox(); + Vec3r u = bbox.getMin(); + Vec3r v = bbox.getMax(); + Vec3r cameraCenter( freestyle_viewpoint[0], freestyle_viewpoint[1], freestyle_viewpoint[2]); + + Vec3r w1( u[0], u[1], u[2] ); + Vec3r w2( v[0], u[1], u[2] ); + Vec3r w3( u[0], v[1], u[2] ); + Vec3r w4( v[0], v[1], u[2] ); + Vec3r w5( u[0], u[1], v[2] ); + Vec3r w6( v[0], u[1], v[2] ); + Vec3r w7( u[0], v[1], v[2] ); + Vec3r w8( v[0], v[1], v[2] ); + + real _znear = __min( (w1-cameraCenter).norm(), + __min( (w2-cameraCenter).norm(), + __min( (w3-cameraCenter).norm(), + __min( (w4-cameraCenter).norm(), + __min( (w5-cameraCenter).norm(), + __min( (w6-cameraCenter).norm(), + __min( (w7-cameraCenter).norm(), + (w8-cameraCenter).norm() ))))))); + + return __max(_znear, 0.001); + + } + + real AppView::zfar() { + + BBox<Vec3r> bbox = _ModelRootNode->bbox(); + Vec3r u = bbox.getMin(); + Vec3r v = bbox.getMax(); + Vec3r cameraCenter( freestyle_viewpoint[0], freestyle_viewpoint[1], freestyle_viewpoint[2]); + + Vec3r w1( u[0], u[1], u[2] ); + Vec3r w2( v[0], u[1], u[2] ); + Vec3r w3( u[0], v[1], u[2] ); + Vec3r w4( v[0], v[1], u[2] ); + Vec3r w5( u[0], u[1], v[2] ); + Vec3r w6( v[0], u[1], v[2] ); + Vec3r w7( u[0], v[1], v[2] ); + Vec3r w8( v[0], v[1], v[2] ); + + real _zfar = __max( (w1-cameraCenter).norm(), + __max( (w2-cameraCenter).norm(), + __max( (w3-cameraCenter).norm(), + __max( (w4-cameraCenter).norm(), + __max( (w5-cameraCenter).norm(), + __max( (w6-cameraCenter).norm(), + __max( (w7-cameraCenter).norm(), + (w8-cameraCenter).norm() ))))))); + + return _zfar; + + } + + real AppView::GetFocalLength() + { + real Near = __max(0.1,(real)(-2.f*_maxAbs+ distanceToSceneCenter() )); + return Near; + } + + diff --git a/source/blender/freestyle/intern/application/AppView.h b/source/blender/freestyle/intern/application/AppView.h new file mode 100644 index 00000000000..b6a5dfcf1cc --- /dev/null +++ b/source/blender/freestyle/intern/application/AppView.h @@ -0,0 +1,221 @@ +#ifndef APPVIEW_H +# define APPVIEW_H + +# if !defined(WIN32) || defined(__GNUC__) +# include <algorithm> +using namespace std; +# define __min(x,y) (min(x,y)) +# define __max(x,y) (max(x,y)) +# endif // WIN32 + +# include "../geometry/Geom.h" +# include "../geometry/BBox.h" +# include "../scene_graph/NodeDrawingStyle.h" +# include "../system/Precision.h" +# include "AppConfig.h" + +using namespace Geometry; + +class AppView +{ + +public: + + AppView(const char *iName = 0); + virtual ~AppView(); + +public: + + //inherited + inline unsigned int width() { return _width; } + inline unsigned int height() { return _height; } + inline void setWidth( unsigned int width ) { _width = width; } + inline void setHeight( unsigned int height ) { _height = height; } + +protected: + unsigned int _width, _height; + +public: + + /*! Sets the model to draw in the viewer + * iModel + * The Root Node of the model + */ + inline void setModel(NodeGroup *iModel) + { + if(0 != _ModelRootNode->numberOfChildren()) + { + _ModelRootNode->DetachChildren(); + _ModelRootNode->clearBBox(); + } + + AddModel(iModel); + } + + /*! Adds a model for displaying in the viewer */ + inline void AddModel(NodeGroup *iModel) + { + _ModelRootNode->AddChild(iModel); + + _ModelRootNode->UpdateBBox(); + + _minBBox = __min(__min(_ModelRootNode->bbox().getMin()[0], + _ModelRootNode->bbox().getMin()[1]), + _ModelRootNode->bbox().getMin()[2]); + _maxBBox = __max(__max(_ModelRootNode->bbox().getMax()[0], + _ModelRootNode->bbox().getMax()[1]), + _ModelRootNode->bbox().getMax()[2]); + + _maxAbs = __max(rabs(_minBBox), rabs(_maxBBox)); + + _minAbs = __min(rabs(_minBBox), rabs(_maxBBox)); + + } + + inline void AddSilhouette(NodeGroup* iSilhouette) + { + _SilhouetteRootNode->AddChild(iSilhouette); + } + + inline void Add2DSilhouette(NodeGroup *iSilhouette) + { + //_pFENode->AddChild(iSilhouette); + } + + inline void Add2DVisibleSilhouette(NodeGroup *iVSilhouette) + { + //_pVisibleSilhouetteNode->AddChild(iVSilhouette); + } + + inline void setDebug(NodeGroup* iDebug) + { + if(0 != _DebugRootNode->numberOfChildren()) + { + _DebugRootNode->DetachChildren(); + _DebugRootNode->clearBBox(); + } + + AddDebug(iDebug); + } + + inline void AddDebug(NodeGroup* iDebug) + { + _DebugRootNode->AddChild(iDebug); + } + + inline void DetachModel(Node *iModel) + { + _ModelRootNode->DetachChild(iModel); + _ModelRootNode->UpdateBBox(); + + _minBBox = __min(__min(_ModelRootNode->bbox().getMin()[0], + _ModelRootNode->bbox().getMin()[1]), + _ModelRootNode->bbox().getMin()[2]); + _maxBBox = __max(__max(_ModelRootNode->bbox().getMax()[0], + _ModelRootNode->bbox().getMax()[1]), + _ModelRootNode->bbox().getMax()[2]); + + _maxAbs = __max(rabs(_minBBox), rabs(_maxBBox)); + _minAbs = __min(rabs(_minBBox), rabs(_maxBBox)); + } + + inline void DetachModel() + { + _ModelRootNode->DetachChildren(); + _ModelRootNode->clearBBox(); + + // 2D Scene + //_p2DNode.DetachChildren(); + //_pFENode->DetachChildren(); + //_pVisibleSilhouetteNode->DetachChildren(); + + } + + inline void DetachSilhouette() + { + _SilhouetteRootNode->DetachChildren(); + //_pFENode->DetachChildren(); + //_pVisibleSilhouetteNode->DetachChildren(); + _p2DSelectionNode->destroy(); + } + + inline void DetachVisibleSilhouette() + { + //_pVisibleSilhouetteNode->DetachChildren(); + _p2DSelectionNode->destroy(); + } + + inline void DetachDebug() + { + _DebugRootNode->DetachChildren(); + } + + + + real distanceToSceneCenter(); + real GetFocalLength(); + + inline real GetAspect() const + { + return ((real) _width/(real) _height); + } + + void setHorizontalFov( float hfov ) +{ + _Fovy = 2.0 * atan (tan(hfov / 2.0) / GetAspect()); +} + inline real GetFovyRadian() const + { + return _Fovy; + } + + inline real GetFovyDegrees() const + { + return _Fovy * 180.0 / M_PI; + } + + BBox<Vec3r> scene3DBBox() const { return _ModelRootNode->bbox(); } + + real znear(); + real zfar(); + + +public: + /*! Core scene drawing */ + void DrawScene(SceneVisitor *iRenderer); + + /*! 2D Scene Drawing */ + void Draw2DScene(SceneVisitor *iRenderer); + + +protected: + + /*! fabs or abs */ + inline int rabs(int x) {return abs(x);} + inline real rabs(real x) {return fabs(x);} + + +protected: + float _Fovy; + + //The root node container + NodeGroup _RootNode; + NodeDrawingStyle *_ModelRootNode; + NodeDrawingStyle *_SilhouetteRootNode; + NodeDrawingStyle *_DebugRootNode; + + NodeGroup _Light; + + real _minBBox; + real _maxBBox; + real _maxAbs; + real _minAbs; + + // 2D Scene + bool _Draw2DScene; + bool _Draw3DScene; NodeGroup _p2DNode; + NodeDrawingStyle *_p2DSelectionNode; + +}; + +#endif // APPVIEW_H diff --git a/source/blender/freestyle/intern/application/Controller.cpp b/source/blender/freestyle/intern/application/Controller.cpp new file mode 100755 index 00000000000..b1ea43befef --- /dev/null +++ b/source/blender/freestyle/intern/application/Controller.cpp @@ -0,0 +1,852 @@ + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +// Must be included before any QT header, because of moc +#include "../system/PythonInterpreter.h" + +#include <string> +#include <fstream> +#include <float.h> + +#include "AppView.h" +#include "AppCanvas.h" +#include "AppConfig.h" + + +#include "../system/StringUtils.h" +#include "../scene_graph/NodeShape.h" +#include "../scene_graph/NodeTransform.h" +#include "../scene_graph/NodeDrawingStyle.h" +#include "../winged_edge/WingedEdgeBuilder.h" +#include "../winged_edge/WEdge.h" +#include "../scene_graph/VertexRep.h" +#include "../winged_edge/WXEdgeBuilder.h" +#include "../scene_graph/ScenePrettyPrinter.h" +#include "../winged_edge/WFillGrid.h" + +#include "../view_map/ViewMapTesselator.h" +#include "../stroke/StrokeTesselator.h" +#include "../view_map/ViewMapIO.h" +#include "Controller.h" +#include "../view_map/ViewMap.h" +#include "../winged_edge/Curvature.h" +#include "../image/Image.h" +#include "../view_map/SteerableViewMap.h" +#include "../stroke/PSStrokeRenderer.h" +#include "../stroke/TextStrokeRenderer.h" +#include "../stroke/StyleModule.h" + +#include "../system/StringUtils.h" + +#include "../scene_graph/BlenderFileLoader.h" +#include "../stroke/BlenderStrokeRenderer.h" + +#ifdef __cplusplus +extern "C" { +#endif + + #include "../../FRS_freestyle.h" + +#ifdef __cplusplus +} +#endif + + + +Controller::Controller() +{ + + const string sep(Config::DIR_SEP.c_str()); + //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); + + _RootNode = new NodeGroup; + _RootNode->addRef(); + + _SilhouetteNode = NULL; + //_ProjectedSilhouette = NULL; + //_VisibleProjectedSilhouette = NULL; + + _DebugNode = new NodeGroup; + _DebugNode->addRef(); + + _winged_edge = NULL; + + _pView = NULL; + + _edgeTesselationNature = (Nature::SILHOUETTE | Nature::BORDER | Nature::CREASE); + + _ProgressBar = new ProgressBar; + _SceneNumFaces = 0; + _minEdgeSize = DBL_MAX; + _bboxDiag = 0; + + _ViewMap = 0; + + _Canvas = 0; + + _VisibilityAlgo = ViewMapBuilder::ray_casting; + //_VisibilityAlgo = ViewMapBuilder::ray_casting_fast; + + _Canvas = new AppCanvas; + + _inter = new PythonInterpreter; + _EnableQI = true; + _ComputeRidges = true; + _ComputeSteerableViewMap = false; + _ComputeSuggestive = true; + _sphereRadius = 1.0; + + init_options(); +} + +Controller::~Controller() +{ + if(NULL != _RootNode) + { + int ref = _RootNode->destroy(); + if(0 == ref) + delete _RootNode; + } + + if(NULL != _SilhouetteNode) + { + int ref = _SilhouetteNode->destroy(); + if(0 == ref) + delete _SilhouetteNode; + } + + if(NULL != _DebugNode) + { + int ref = _DebugNode->destroy(); + if(0 == ref) + delete _DebugNode; + } + + 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; + } + + //delete _current_dirs; +} + +void Controller::setView(AppView *iView) +{ + if(NULL == iView) + return; + + _pView = iView; + _Canvas->setViewer(_pView); +} + +int Controller::LoadMesh(Render *re, SceneRenderLayer* srl) +{ + + BlenderFileLoader loader(re, srl); + + _Chrono.start(); + + NodeGroup *blenderScene = loader.Load(); + + if (blenderScene == NULL) { + cout << "Cannot load scene" << endl; + return 1; + } + + if( blenderScene->numberOfChildren() < 1) { + cout << "Empty scene" << endl; + blenderScene->destroy(); + delete blenderScene; + return 1; + } + + cout << "Scene loaded" << endl; + printf("Mesh cleaning : %lf\n", _Chrono.stop()); + _SceneNumFaces += loader.numFacesRead(); + + if(loader.minEdgeSize() < _minEdgeSize) + { + _minEdgeSize = loader.minEdgeSize(); + _EPSILON = _minEdgeSize*1e-6; + if(_EPSILON < DBL_MIN) + _EPSILON = 0.0; + } + + cout << "Epsilon computed : " << _EPSILON << endl; + + // DEBUG + // ScenePrettyPrinter spp; + // blenderScene->accept(spp); + + _RootNode->AddChild(blenderScene); + _RootNode->UpdateBBox(); // FIXME: Correct that by making a Renderer to compute the bbox + + _pView->setModel(_RootNode); + //_pView->FitBBox(); + + + _Chrono.start(); + + + WXEdgeBuilder wx_builder; + blenderScene->accept(wx_builder); + _winged_edge = wx_builder.getWingedEdge(); + + printf("WEdge building : %lf\n", _Chrono.stop()); + + _Chrono.start(); + + _Grid.clear(); + Vec3r size; + for(unsigned int i=0; i<3; i++) + { + size[i] = fabs(_RootNode->bbox().getMax()[i] - _RootNode->bbox().getMin()[i]); + size[i] += size[i]/10.0; // let make the grid 1/10 bigger to avoid numerical errors while computing triangles/cells intersections + if(size[i]==0){ + cout << "Warning: the bbox size is 0 in dimension "<<i<<endl; + } + } + _Grid.configure(Vec3r(_RootNode->bbox().getMin() - size / 20.0), size, + _SceneNumFaces); + + // Fill in the grid: + WFillGrid fillGridRenderer(&_Grid, _winged_edge); + fillGridRenderer.fillGrid(); + + printf("Grid building : %lf\n", _Chrono.stop()); + + // DEBUG + _Grid.displayDebug(); + // + // _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 = StringUtils::toAscii( string(cleaned) ); + + _ListOfModels.push_back("Blender_models"); + + cout << "Triangles nb : " << _SceneNumFaces << endl; + _bboxDiag = (_RootNode->bbox().getMax()-_RootNode->bbox().getMin()).norm(); + cout << "Bounding Box : " << _bboxDiag << endl; + return 0; +} + + +void Controller::CloseFile() +{ + WShape::setCurrentId(0); + _pView->DetachModel(); + _ListOfModels.clear(); + if(NULL != _RootNode) + { + int ref = _RootNode->destroy(); + if(0 == ref) + _RootNode->addRef(); + + _RootNode->clearBBox(); + } + + _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(); + } + + if(_winged_edge) { + delete _winged_edge; + _winged_edge = NULL; + } + + // We deallocate the memory: + if(NULL != _ViewMap) + { + delete _ViewMap; + _ViewMap = 0; + } + + // clears the canvas + _Canvas->Erase(); + + // clears the grid + _Grid.clear(); + _SceneNumFaces = 0; + _minEdgeSize = DBL_MAX; + +} + + + +void Controller::ComputeViewMap() +{ + + if (!_ListOfModels.size()) + return; + + if(NULL != _ViewMap) + { + delete _ViewMap; + _ViewMap = 0; + } + + _pView->DetachDebug(); + if(NULL != _DebugNode) + { + int ref = _DebugNode->destroy(); + if(0 == ref) + _DebugNode->addRef(); + } + + + _pView->DetachSilhouette(); + if (NULL != _SilhouetteNode) + { + int ref = _SilhouetteNode->destroy(); + if(0 == ref) + delete _SilhouetteNode; + } + // if(NULL != _ProjectedSilhouette) + // { + // int ref = _ProjectedSilhouette->destroy(); + // if(0 == ref) + // delete _ProjectedSilhouette; + // } + // if(NULL != _VisibleProjectedSilhouette) + // { + // int ref = _VisibleProjectedSilhouette->destroy(); + // if(0 == ref) + // { + // delete _VisibleProjectedSilhouette; + // _VisibleProjectedSilhouette = 0; + // } + // } + + // 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. + Vec3r vp( freestyle_viewpoint[0], freestyle_viewpoint[1], freestyle_viewpoint[2]); + + //cout << "mv" << endl; + real mv[4][4]; + for( int i= 0; i < 4; i++) { + for( int j= 0; j < 4; j++) { + mv[i][j] = freestyle_mv[i][j]; + //cout << mv[i][j] << " "; + } + // cout << endl; + } + + //cout << "\nproj" << endl; + real proj[4][4]; + for( int i= 0; i < 4; i++) { + for( int j= 0; j < 4; j++) { + proj[i][j] = freestyle_proj[i][j]; + //cout << proj[i][j] << " "; + } + //cout << endl; + } + + int viewport[4]; + for( int i= 0; i < 4; i++) + viewport[i] = freestyle_viewport[i]; + + //cout << "\nfocal:" << _pView->GetFocalLength() << endl << endl; + + + + // Flag the WXEdge structure for silhouette edge detection: + //---------------------------------------------------------- + + cout << "\n=== Detecting silhouette edges ===" << endl; + _Chrono.start(); + + edgeDetector.setViewpoint(Vec3r(vp)); + edgeDetector.enableRidgesAndValleysFlag(_ComputeRidges); + edgeDetector.enableSuggestiveContours(_ComputeSuggestive); + edgeDetector.setSphereRadius(_sphereRadius); + edgeDetector.setSuggestiveContourKrDerivativeEpsilon(_suggestiveContourKrDerivativeEpsilon); + edgeDetector.processShapes(*_winged_edge); + + real duration = _Chrono.stop(); + printf("Feature lines : %lf\n", duration); + + // Builds the view map structure from the flagged WSEdge structure: + //---------------------------------------------------------- + ViewMapBuilder vmBuilder; + vmBuilder.setEnableQI(_EnableQI); + vmBuilder.setViewpoint(Vec3r(vp)); + vmBuilder.setTransform( mv, proj,viewport, _pView->GetFocalLength(), _pView->GetAspect(), _pView->GetFovyRadian()); + vmBuilder.setFrustum(_pView->znear(), _pView->zfar()); + vmBuilder.setGrid(&_Grid); + + // Builds a tesselated form of the silhouette for display purpose: + //--------------------------------------------------------------- + ViewMapTesselator3D sTesselator3d; + //ViewMapTesselator2D sTesselator2d; + //sTesselator2d.setNature(_edgeTesselationNature); + sTesselator3d.setNature(_edgeTesselationNature); + + cout << "\n=== Building the view map ===" << endl; + _Chrono.start(); + // Build View Map + _ViewMap = vmBuilder.BuildViewMap(*_winged_edge, _VisibilityAlgo, _EPSILON); + _ViewMap->setScene3dBBox(_RootNode->bbox()); + + printf("ViewMap edge count : %i\n", _ViewMap->viewedges_size() ); + + //Tesselate the 3D edges: + _SilhouetteNode = sTesselator3d.Tesselate(_ViewMap); + _SilhouetteNode->addRef(); + + // Tesselate 2D edges + // _ProjectedSilhouette = sTesselator2d.Tesselate(_ViewMap); + // _ProjectedSilhouette->addRef(); + + duration = _Chrono.stop(); + printf("ViewMap building : %lf\n", duration); + + + _pView->AddSilhouette(_SilhouetteNode); + //_pView->AddSilhouette(_WRoot); + //_pView->Add2DSilhouette(_ProjectedSilhouette); + //_pView->Add2DVisibleSilhouette(_VisibleProjectedSilhouette); + _pView->AddDebug(_DebugNode); + + // Draw the steerable density map: + //-------------------------------- + if(_ComputeSteerableViewMap){ + ComputeSteerableViewMap(); + } + // Reset Style modules modification flags + resetModified(true); +} + +void Controller::ComputeSteerableViewMap(){ +//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.f/255.f; // 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]); + // //img[i] = new GrayImage(_pView->width(), _pView->height()); + // //offscreenBuffer.readPixels(0,0,_pView->width(), _pView->height(), img[i]->getArray()); + // pm = offscreenBuffer.renderPixmap(_pView->width(), _pView->height()); + // + // if(pm.isNull()) + // 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 y=0;y<img[i]->height();++y){ + // for(unsigned x=0;x<img[i]->width();++x){ + // //img[i]->setPixel(x,y,(float)qGray(qimg.pixel(x,y))/255.f); + // 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 + // // qimg = QImage(_pView->width(), _pView->height(), 32); + // // for(y=0;y<img[i]->height();++y){ + // // for(unsigned 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"); + // } + // + // + // svm->buildImagesPyramids(img,false,0,1.f); +} + +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; + } +} + +void Controller::setQuantitativeInvisibility(bool iBool) +{ + _EnableQI = iBool; +} + +bool Controller::getQuantitativeInvisibility() const +{ + return _EnableQI; +} + +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::setComputeSteerableViewMapFlag(bool iBool){ + _ComputeSteerableViewMap = iBool; +} + +bool Controller::getComputeSteerableViewMapFlag() const { + return _ComputeSteerableViewMap; +} + +void Controller::DrawStrokes() +{ + if(_ViewMap == 0) + return; + + cout << "\n=== Stroke drawing ===" << endl; + _Chrono.start(); + _Canvas->Draw(); + real d = _Chrono.stop(); + cout << "Strokes generation : " << d << endl; + cout << "Stroke count : " << _Canvas->stroke_count << endl; + resetModified(); +} + +Render* Controller::RenderStrokes(Render *re) { + BlenderStrokeRenderer* blenderRenderer = new BlenderStrokeRenderer(re); + _Canvas->Render( blenderRenderer ); + Render* freestyle_render = blenderRenderer->RenderScene(re); + delete blenderRenderer; + + return freestyle_render; +} + +void Controller::InsertStyleModule(unsigned index, const char *iFileName) +{ + if( !BLI_testextensie(iFileName, ".py") ) { + cerr << "Error: Cannot load \"" << StringUtils::toAscii( string(iFileName) ) + << "\", unknown extension" << endl; + return; + } + + StyleModule* sm = new StyleModule(iFileName, _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::setHelpIndex(const string& index) { + _help_index = index; +} + +string Controller::getHelpIndex() const { + return _help_index; +} + +void Controller::setBrowserCmd(const string& cmd) { + _browser_cmd = cmd; +} + +string Controller::getBrowserCmd() const { + return _browser_cmd; +} + +void Controller::resetInterpreter() { + if (_inter) + _inter->reset(); +} + + +void Controller::displayDensityCurves(int x, int y){ + SteerableViewMap * svm = _Canvas->getSteerableViewMap(); + if(!svm) + return; + + unsigned 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 + // 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(); +} + +void Controller::init_options(){ +// from AppOptionsWindow.cpp +// Default init options + + Config::Path * cpath = Config::Path::getInstance(); + + // Directories + ViewMapIO::Options::setModelsPath( StringUtils::toAscii( cpath->getModelsPath() ) ); + PythonInterpreter::Options::setPythonPath( StringUtils::toAscii( cpath->getPythonPath() ) ); + TextureManager::Options::setPatternsPath( StringUtils::toAscii( cpath->getPatternsPath() ) ); + TextureManager::Options::setBrushesPath( StringUtils::toAscii( 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(); +} diff --git a/source/blender/freestyle/intern/application/Controller.h b/source/blender/freestyle/intern/application/Controller.h new file mode 100755 index 00000000000..46d08d0c686 --- /dev/null +++ b/source/blender/freestyle/intern/application/Controller.h @@ -0,0 +1,230 @@ +// +// Filename : Controller.h +// Author : Stephane Grabli +// Purpose : The spinal tap of the system +// Date of creation : 01/07/2002 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef CONTROLLER_H +# define CONTROLLER_H + +# include <string> +//# include "ConfigIO.h" +# include "../geometry/FastGrid.h" +# include "../geometry/HashGrid.h" +# include "../view_map/ViewMapBuilder.h" +# include "../system/TimeUtils.h" +# include "../system/ProgressBar.h" +# include "../system/Precision.h" +# include "../system/Interpreter.h" +# include "../view_map/FEdgeXDetector.h" + +class AppView; +class NodeGroup; +class WShape; +class SShape; +class ViewMap; +class ViewEdge; +class AppCanvas; +class InteractiveShader; +class Shader; +class StrokeRenderer; + +#ifdef __cplusplus +extern "C" { +#endif + + #include "render_types.h" + #include "DNA_scene_types.h" + +#ifdef __cplusplus +} +#endif + +class Controller +{ +public: + Controller() ; + ~Controller() ; + + void setView(AppView *iView); + + //soc + void init_options(); + + int LoadMesh( Render *re, SceneRenderLayer* srl ); + int Load3DSFile(const char *iFileName); + void CloseFile(); + void ComputeViewMap(); + void ComputeSteerableViewMap(); + void saveSteerableViewMapImages(); + void toggleEdgeTesselationNature(Nature::EdgeNature iNature); + void DrawStrokes(); + Render* RenderStrokes(Render *re); + void SwapStyleModules(unsigned i1, unsigned i2); + void InsertStyleModule(unsigned index, const char *iFileName); + void AddStyleModule(const char *iFileName); + void RemoveStyleModule(unsigned index); + void ReloadStyleModule(unsigned index, const char * iFileName); + void Clear(); + void toggleLayer(unsigned index, bool iDisplay); + void setModified(unsigned index, bool iMod); + void resetModified(bool iMod=false); + void updateCausalStyleModules(unsigned index); + void displayDensityCurves(int x, int y); + + + ViewEdge * SelectViewEdge(real x, real y); + FEdge * SelectFEdge(real x, real y); + NodeGroup* BuildRep(vector<ViewEdge*>::iterator vedges_begin, + vector<ViewEdge*>::iterator vedges_end) ; + + NodeGroup* debugNode() {return _DebugNode;} + AppView * view() {return _pView;} + NodeGroup* debugScene() {return _DebugNode;} + Grid& grid() {return _Grid;} + + void toggleVisibilityAlgo(); + + void setQuantitativeInvisibility(bool iBool); // if true, we compute quantitativeInvisibility + bool getQuantitativeInvisibility() const; + + void setComputeRidgesAndValleysFlag(bool b); + bool getComputeRidgesAndValleysFlag() const ; + void setComputeSuggestiveContoursFlag(bool b); + bool getComputeSuggestiveContoursFlag() const ; + + void setComputeSteerableViewMapFlag(bool iBool); + bool getComputeSteerableViewMapFlag() const; + void setSphereRadius(real s){_sphereRadius=s;} + real getSphereRadius() const {return _sphereRadius;} + void setSuggestiveContourKrDerivativeEpsilon(real dkr){_suggestiveContourKrDerivativeEpsilon=dkr;} + real getSuggestiveContourKrDerivativeEpsilon() const {return _suggestiveContourKrDerivativeEpsilon;} + + void setModelsDir(const string& dir); + string getModelsDir() const; + void setModulesDir(const string& dir); + string getModulesDir() const; + void setHelpIndex(const string& dir); + string getHelpIndex() const; + void setBrowserCmd(const string& cmd); + string getBrowserCmd() const; + + void resetInterpreter(); + +public: + // Viewmap data structure + ViewMap * _ViewMap; + + // Canvas + AppCanvas *_Canvas; + +private: + + // Main Window: + //AppMainWindow *_pMainWindow; + + // List of models currently loaded + vector<string> _ListOfModels; + + // Current directories + //ConfigIO* _current_dirs; + + + + //View + // 3D + AppView *_pView; + + // 2D + //Viewer2DWindow *_pView2DWindow; + //Viewer2D *_pView2D; + + //Model + // Drawing Structure + NodeGroup *_RootNode; + + // Winged-Edge structure + WingedEdge* _winged_edge; + + // Silhouette structure: + //std::vector<SShape*> _SShapes; + //NodeGroup *_SRoot; + + // Silhouette + NodeGroup *_SilhouetteNode; + NodeGroup *_ProjectedSilhouette; + NodeGroup *_VisibleProjectedSilhouette; + + // more Debug info + NodeGroup *_DebugNode; + + // debug + // NodeUser<ViewMap> *_ViewMapNode; // FIXME + + // Chronometer: + Chronometer _Chrono; + + // Progress Bar + ProgressBar *_ProgressBar; + + // edges tesselation nature + int _edgeTesselationNature; + + FastGrid _Grid; + //HashGrid _Grid; + + unsigned int _SceneNumFaces; + real _minEdgeSize; + real _EPSILON; + real _bboxDiag; + + + //AppStyleWindow *_pStyleWindow; + //AppOptionsWindow *_pOptionsWindow; + //AppDensityCurvesWindow *_pDensityCurvesWindow; + + ViewMapBuilder::visibility_algo _VisibilityAlgo; + + // Script Interpreter + Interpreter* _inter; + + string _help_index; + string _browser_cmd; + + bool _EnableQI; + bool _ComputeRidges; + bool _ComputeSuggestive; + real _sphereRadius; + real _suggestiveContourKrDerivativeEpsilon; + + bool _ComputeSteerableViewMap; + + FEdgeXDetector edgeDetector; +}; + +extern Controller *g_pController; + +#endif // CONTROLLER_H diff --git a/source/blender/freestyle/intern/application/FRS_freestyle.cpp b/source/blender/freestyle/intern/application/FRS_freestyle.cpp new file mode 100644 index 00000000000..b88e750687e --- /dev/null +++ b/source/blender/freestyle/intern/application/FRS_freestyle.cpp @@ -0,0 +1,329 @@ +#include "AppView.h" +#include "Controller.h" +#include "AppConfig.h" +#include "AppCanvas.h" + +#include <iostream> +#include <map> +#include <set> +using namespace std; + +#ifdef __cplusplus +extern "C" { +#endif + +#include "MEM_guardedalloc.h" + +#include "DNA_camera_types.h" +#include "DNA_freestyle_types.h" + +#include "BKE_main.h" +#include "BLI_blenlib.h" +#include "BPY_extern.h" + +#include "renderpipeline.h" +#include "pixelblending.h" + +#include "../../FRS_freestyle.h" +#include "../../FRS_freestyle_config.h" + + // Freestyle configuration + short freestyle_is_initialized = 0; + static Config::Path *pathconfig = NULL; + static Controller *controller = NULL; + static AppView *view = NULL; + static Scene *current_scene = NULL; + + // camera information + float freestyle_viewpoint[3]; + float freestyle_mv[4][4]; + float freestyle_proj[4][4]; + int freestyle_viewport[4]; + + // Panel configuration + char* freestyle_current_module_path = NULL; + SceneRenderLayer* freestyle_current_layer = NULL; + + ListBase* freestyle_modules; + int* freestyle_flags; + float* freestyle_sphere_radius; + float* freestyle_dkr_epsilon; + + string default_module_path; + + //======================================================= + // Initialization + //======================================================= + + void FRS_initialize(bContext* C){ + + if( !freestyle_is_initialized ) { + + pathconfig = new Config::Path; + controller = new Controller; + view = new AppView; + controller->setView(view); + + default_module_path = pathconfig->getProjectDir() + Config::DIR_SEP + "style_modules" + Config::DIR_SEP + "contour.py"; + + freestyle_is_initialized = 1; + } + + current_scene = CTX_data_scene(C); + if( !current_scene ) + current_scene = (Scene*) CTX_data_main(C)->scene.first; + + FRS_select_layer( (SceneRenderLayer*) BLI_findlink(¤t_scene->r.layers, current_scene->r.actlay) ); + + } + + void FRS_exit() { + delete pathconfig; + delete controller; + delete view; + } + + //======================================================= + // Rendering + //======================================================= + + void init_view(Render* re){ + int width = re->scene->r.xsch; + int height = re->scene->r.ysch; + + freestyle_viewport[0] = freestyle_viewport[1] = 0; + freestyle_viewport[2] = width; + freestyle_viewport[3] = height; + + view->setWidth( width ); + view->setHeight( height ); + } + + void init_camera(Render* re){ + Object* maincam_obj = re->scene->camera; + // Camera *cam = (Camera*) maincam_obj->data; + + freestyle_viewpoint[0] = maincam_obj->obmat[3][0]; + freestyle_viewpoint[1] = maincam_obj->obmat[3][1]; + freestyle_viewpoint[2] = maincam_obj->obmat[3][2]; + + for( int i = 0; i < 4; i++ ) + for( int j = 0; j < 4; j++ ) + freestyle_mv[i][j] = re->viewmat[i][j]; + + for( int i = 0; i < 4; i++ ) + for( int j = 0; j < 4; j++ ) + freestyle_proj[i][j] = re->winmat[i][j]; + } + + + void prepare(Render* re, SceneRenderLayer* srl ) { + + // clear canvas + controller->Clear(); + + // load mesh + if( controller->LoadMesh(re, srl) ) // returns if scene cannot be loaded or if empty + return; + + // add style modules + FreestyleConfig* config = &srl->freestyleConfig; + + cout << "\n=== Rendering options ===" << endl; + cout << "Modules :"<< endl; + int layer_count = 0; + + + for( FreestyleModuleConfig* module_conf = (FreestyleModuleConfig *)config->modules.first; module_conf; module_conf = module_conf->next ) { + if( module_conf->is_displayed ) { + cout << " " << layer_count+1 << ": " << module_conf->module_path << endl; + controller->InsertStyleModule( layer_count, module_conf->module_path ); + controller->toggleLayer(layer_count, true); + layer_count++; + } + } + cout << endl; + + // set parameters + controller->setSphereRadius( config->sphere_radius ); + controller->setComputeRidgesAndValleysFlag( (config->flags & FREESTYLE_RIDGES_AND_VALLEYS_FLAG) ? true : false); + controller->setComputeSuggestiveContoursFlag( (config->flags & FREESTYLE_SUGGESTIVE_CONTOURS_FLAG) ? true : false); + controller->setSuggestiveContourKrDerivativeEpsilon( config->dkr_epsilon ) ; + + cout << "Sphere radius : " << controller->getSphereRadius() << endl; + cout << "Redges and valleys : " << (controller->getComputeRidgesAndValleysFlag() ? "enabled" : "disabled") << endl; + cout << "Suggestive contours : " << (controller->getComputeSuggestiveContoursFlag() ? "enabled" : "disabled") << endl; + cout << "Suggestive contour dkr epsilon : " << controller->getSuggestiveContourKrDerivativeEpsilon() << endl; + + // compute view map + controller->ComputeViewMap(); + } + + void composite_result(Render* re, SceneRenderLayer* srl, Render* freestyle_render) + { + + RenderLayer *rl; + float *src, *dest, *pixSrc, *pixDest; + int x, y, rectx, recty; + + if( freestyle_render == NULL || freestyle_render->result == NULL ) + return; + + rl = render_get_active_layer( freestyle_render, freestyle_render->result ); + if( !rl || rl->rectf == NULL) { cout << "Cannot find Freestyle result image" << endl; return; } + src = rl->rectf; + + rl = RE_GetRenderLayer(re->result, srl->name); + if( !rl || rl->rectf == NULL) { cout << "No layer to composite to" << endl; return; } + dest = rl->rectf; + + rectx = re->rectx; + recty = re->recty; + + for( y = 0; y < recty; y++) { + for( x = 0; x < rectx; x++) { + + pixSrc = src + 4 * (rectx * y + x); + if( pixSrc[3] > 0.0) { + pixDest = dest + 4 * (rectx * y + x); + addAlphaOverFloat(pixDest, pixSrc); + } + } + } + + } + + int displayed_layer_count( SceneRenderLayer* srl ) { + int count = 0; + + for( FreestyleModuleConfig* module_conf = (FreestyleModuleConfig *)srl->freestyleConfig.modules.first; module_conf; module_conf = module_conf->next ) { + if( module_conf->is_displayed ) + count++; + } + return count; + } + + void FRS_add_Freestyle(Render* re) { + + SceneRenderLayer *srl; + Render* freestyle_render = NULL; + + // init + cout << "\n#===============================================================" << endl; + cout << "# Freestyle" << endl; + cout << "#===============================================================" << endl; + + init_view(re); + init_camera(re); + + for(srl= (SceneRenderLayer *)current_scene->r.layers.first; srl; srl= srl->next) { + if( !(srl->layflag & SCE_LAY_DISABLE) && + srl->layflag & SCE_LAY_FRS && + displayed_layer_count(srl) > 0 ) + { + cout << "\n----------------------------------------------------------" << endl; + cout << "| "<< srl->name << endl; + cout << "----------------------------------------------------------" << endl; + + // prepare Freestyle: + // - clear canvas + // - load mesh + // - add style modules + // - set parameters + // - compute view map + prepare(re, srl); + + // render and composite Freestyle result + if( controller->_ViewMap ) { + + // render strokes + controller->DrawStrokes(); + freestyle_render = controller->RenderStrokes(re); + controller->CloseFile(); + + // composite result + composite_result(re, srl, freestyle_render); + + // free resources + RE_FreeRender(freestyle_render); + } + } + } + + } + + //======================================================= + // Freestyle Panel Configuration + //======================================================= + + void FRS_add_freestyle_config( SceneRenderLayer* srl ) + { + FreestyleConfig* config = &srl->freestyleConfig; + + config->modules.first = config->modules.last = NULL; + config->flags = 0; + config->sphere_radius = 1.0; + config->dkr_epsilon = 0.001; + } + + void FRS_free_freestyle_config( SceneRenderLayer* srl ) + { + BLI_freelistN( &srl->freestyleConfig.modules ); + } + + void FRS_select_layer( SceneRenderLayer* srl ) + { + FreestyleConfig* config = &srl->freestyleConfig; + + freestyle_modules = &config->modules; + freestyle_flags = &config->flags; + freestyle_sphere_radius = &config->sphere_radius; + freestyle_dkr_epsilon = &config->dkr_epsilon; + + freestyle_current_layer = srl; + current_scene->freestyle_current_layer_number = BLI_findindex(¤t_scene->r.layers, freestyle_current_layer); + } + + void FRS_add_module() + { + FreestyleModuleConfig* module_conf = (FreestyleModuleConfig*) MEM_callocN( sizeof(FreestyleModuleConfig), "style module configuration"); + BLI_addtail(freestyle_modules, (void*) module_conf); + + strcpy( module_conf->module_path, default_module_path.c_str() ); + module_conf->is_displayed = 1; + } + + void FRS_delete_module(void *module_index_ptr, void *unused) + { + FreestyleModuleConfig* module_conf = (FreestyleModuleConfig*) BLI_findlink(freestyle_modules, (intptr_t)module_index_ptr); + + BLI_freelinkN( freestyle_modules, module_conf); + } + + void FRS_move_up_module(void *module_index_ptr, void *unused) + { + FreestyleModuleConfig* module_conf = (FreestyleModuleConfig*) BLI_findlink(freestyle_modules, (intptr_t)module_index_ptr); + + BLI_remlink(freestyle_modules, module_conf); + BLI_insertlink(freestyle_modules, module_conf->prev->prev, module_conf); + } + + void FRS_move_down_module(void *module_index_ptr, void *unused) + { + FreestyleModuleConfig* module_conf = (FreestyleModuleConfig*) BLI_findlink(freestyle_modules, (intptr_t)module_index_ptr); + + BLI_remlink(freestyle_modules, module_conf); + BLI_insertlink(freestyle_modules, module_conf->next, module_conf); + } + + void FRS_set_module_path(void *module_index_ptr, void *unused) + { + FreestyleModuleConfig* module_conf = (FreestyleModuleConfig*) BLI_findlink(freestyle_modules, (intptr_t)module_index_ptr); + freestyle_current_module_path = module_conf->module_path; + } + + + +#ifdef __cplusplus +} +#endif |