2008-05-18 13:01:52 +00:00
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// 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>
|
|
|
|
|
|
2008-12-10 21:51:58 +00:00
|
|
|
#include "AppView.h"
|
2008-05-18 13:01:52 +00:00
|
|
|
#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"
|
|
|
|
|
|
2009-10-05 01:27:35 +00:00
|
|
|
#include "../blender_interface/BlenderFileLoader.h"
|
|
|
|
|
#include "../blender_interface/BlenderStrokeRenderer.h"
|
2008-12-10 21:51:58 +00:00
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
|
extern "C" {
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#include "../../FRS_freestyle.h"
|
|
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2008-08-07 15:04:25 +00:00
|
|
|
|
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
|
|
|
|
2009-11-10 00:03:31 +00:00
|
|
|
Controller::Controller()
|
2008-05-18 13:01:52 +00:00
|
|
|
{
|
2008-05-25 17:34:21 +00:00
|
|
|
|
2008-05-18 13:01:52 +00:00
|
|
|
const string sep(Config::DIR_SEP.c_str());
|
2008-05-25 17:34:21 +00:00
|
|
|
//const string filename = Config::Path::getInstance()->getHomeDir() + sep + Config::OPTIONS_DIR + sep + Config::OPTIONS_CURRENT_DIRS_FILE;
|
2008-05-18 13:01:52 +00:00
|
|
|
//_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);
|
|
|
|
|
|
2008-05-25 17:34:21 +00:00
|
|
|
_ProgressBar = new ProgressBar;
|
2008-05-18 13:01:52 +00:00
|
|
|
_SceneNumFaces = 0;
|
|
|
|
|
_minEdgeSize = DBL_MAX;
|
|
|
|
|
_bboxDiag = 0;
|
|
|
|
|
|
|
|
|
|
_ViewMap = 0;
|
|
|
|
|
|
|
|
|
|
_Canvas = 0;
|
|
|
|
|
|
|
|
|
|
_VisibilityAlgo = ViewMapBuilder::ray_casting;
|
|
|
|
|
//_VisibilityAlgo = ViewMapBuilder::ray_casting_fast;
|
|
|
|
|
|
|
|
|
|
_Canvas = new AppCanvas;
|
|
|
|
|
|
2009-11-10 00:03:31 +00:00
|
|
|
_inter = new PythonInterpreter();
|
2008-05-18 13:01:52 +00:00
|
|
|
_EnableQI = true;
|
|
|
|
|
_ComputeRidges = true;
|
|
|
|
|
_ComputeSteerableViewMap = false;
|
|
|
|
|
_ComputeSuggestive = true;
|
|
|
|
|
_sphereRadius = 1.0;
|
2008-05-26 16:19:30 +00:00
|
|
|
|
|
|
|
|
init_options();
|
2008-05-18 13:01:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-10 21:51:58 +00:00
|
|
|
void Controller::setView(AppView *iView)
|
2008-05-18 13:01:52 +00:00
|
|
|
{
|
|
|
|
|
if(NULL == iView)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
_pView = iView;
|
2008-07-21 21:24:37 +00:00
|
|
|
_Canvas->setViewer(_pView);
|
2008-05-18 13:01:52 +00:00
|
|
|
}
|
|
|
|
|
|
2009-11-10 00:03:31 +00:00
|
|
|
void Controller::setContext(bContext *C)
|
|
|
|
|
{
|
|
|
|
|
PythonInterpreter* py_inter = dynamic_cast<PythonInterpreter*>(_inter);
|
|
|
|
|
assert(py_inter != 0);
|
|
|
|
|
py_inter->setContext(C);
|
|
|
|
|
}
|
|
|
|
|
|
SUMMARY:
Freestyle's pipeline is now fully controllable at the layer level. It can be used:
- in any render layer
- with as many style modules per layer
DETAILS:
Freestyle usage has not changed:
- all the configuration happens in the "Freestyle" render panel, after it is enabled in the "Output" panel with the 'Freestyle' toggle.
- each render layer can choose to render Freestyle strokes by togglingo on 'FrSt' (in the "Render Layers" panel)
- it is fully compatible with compositor nodes
In the "Freestyle" panel, a render layer is selected via the menu list next to the "Render Layer:" label. The options displayed below are those of the currently selected render layer (and are not global to all render layers, as was previously the case).
Style modules are added by pressing the lower button "Add style module". Once added, the following operations are possible:
- deletion (cross)
- reordering (up/down arrows)
- toggling of display (check)
The order of the style modules follows Freestyle's original convention: the modules in the list from top to bottom are respectively the first to the last composited in the render layer. For example, if the module list is "contour" followed by "cartoon", the "cartoon" strokes are rendered on top of the "contour" strokes.
The "Freestyle" panel is constantly synchronized with the "Render Layers" panel: if render layers are added, deleted or toggled off display, Freestyle will take note of the changes.
The current pipeline works as follows:
----------------------------------------------------------------------------------------------
for every scene that is being rendered
if Freestyle is enabled globally
Freestyle is initialized
camera and view settings are transferred from Blender to Freestyle
for every render layer
if: - layer is enabled
- layer enabled Freestyle
- the number of displayed style modules is non-zero
canvas is cleared
geometry is transferred from Blender to Freestyle
settings are fixed for current iteration
view map is calculated
strokes are computed in the canvas (based on view map and style modules)
strokes are rendered in separate Blender scene
scene is composited in current layer
----------------------------------------------------------------------------------------------
A number of changes were made on the codebase:
- the rendering interface between Freestyle and Blender was simplified. The following naming convention was used: functions that are called from within Blender pipeline are prefixed with 'FRS_', while the variables are prefixed with 'freestyle_'
- Freestyle data structures that were put in Blender's render pipeline were removed
- Freestyle cleans up its data structures on Blender exit and shouldn't leak memory
- to ease the configuration in the "Freestyle" panel, a centralized configuration data structure was used and can be easily extended
LIMITATIONS
Even though the current commit is stable and achieves the intended result, it is not as efficient as it could be:
- the canvas and the style modules are at cleared at each layer-level render
- geometry is reloaded at each frame and is duplicated across render layers
This revision clarifies my understanding of the future role of the view map in the compositor. Unfortunately, contrary to what the original proposal said, it is impossible to provide the view map as a render pass because render passes are defined (RE_pipeline.h) as raw floating-point rects. We will have to determine whether or not to extend the notion of render pass to fully integrate the view map in the compositor.
2009-04-07 18:38:23 +00:00
|
|
|
int Controller::LoadMesh(Render *re, SceneRenderLayer* srl)
|
2008-08-07 15:04:25 +00:00
|
|
|
{
|
|
|
|
|
|
SUMMARY:
Freestyle's pipeline is now fully controllable at the layer level. It can be used:
- in any render layer
- with as many style modules per layer
DETAILS:
Freestyle usage has not changed:
- all the configuration happens in the "Freestyle" render panel, after it is enabled in the "Output" panel with the 'Freestyle' toggle.
- each render layer can choose to render Freestyle strokes by togglingo on 'FrSt' (in the "Render Layers" panel)
- it is fully compatible with compositor nodes
In the "Freestyle" panel, a render layer is selected via the menu list next to the "Render Layer:" label. The options displayed below are those of the currently selected render layer (and are not global to all render layers, as was previously the case).
Style modules are added by pressing the lower button "Add style module". Once added, the following operations are possible:
- deletion (cross)
- reordering (up/down arrows)
- toggling of display (check)
The order of the style modules follows Freestyle's original convention: the modules in the list from top to bottom are respectively the first to the last composited in the render layer. For example, if the module list is "contour" followed by "cartoon", the "cartoon" strokes are rendered on top of the "contour" strokes.
The "Freestyle" panel is constantly synchronized with the "Render Layers" panel: if render layers are added, deleted or toggled off display, Freestyle will take note of the changes.
The current pipeline works as follows:
----------------------------------------------------------------------------------------------
for every scene that is being rendered
if Freestyle is enabled globally
Freestyle is initialized
camera and view settings are transferred from Blender to Freestyle
for every render layer
if: - layer is enabled
- layer enabled Freestyle
- the number of displayed style modules is non-zero
canvas is cleared
geometry is transferred from Blender to Freestyle
settings are fixed for current iteration
view map is calculated
strokes are computed in the canvas (based on view map and style modules)
strokes are rendered in separate Blender scene
scene is composited in current layer
----------------------------------------------------------------------------------------------
A number of changes were made on the codebase:
- the rendering interface between Freestyle and Blender was simplified. The following naming convention was used: functions that are called from within Blender pipeline are prefixed with 'FRS_', while the variables are prefixed with 'freestyle_'
- Freestyle data structures that were put in Blender's render pipeline were removed
- Freestyle cleans up its data structures on Blender exit and shouldn't leak memory
- to ease the configuration in the "Freestyle" panel, a centralized configuration data structure was used and can be easily extended
LIMITATIONS
Even though the current commit is stable and achieves the intended result, it is not as efficient as it could be:
- the canvas and the style modules are at cleared at each layer-level render
- geometry is reloaded at each frame and is duplicated across render layers
This revision clarifies my understanding of the future role of the view map in the compositor. Unfortunately, contrary to what the original proposal said, it is impossible to provide the view map as a render pass because render passes are defined (RE_pipeline.h) as raw floating-point rects. We will have to determine whether or not to extend the notion of render pass to fully integrate the view map in the compositor.
2009-04-07 18:38:23 +00:00
|
|
|
BlenderFileLoader loader(re, srl);
|
2008-08-07 15:04:25 +00:00
|
|
|
|
|
|
|
|
_Chrono.start();
|
|
|
|
|
|
|
|
|
|
NodeGroup *blenderScene = loader.Load();
|
|
|
|
|
|
|
|
|
|
if (blenderScene == NULL) {
|
|
|
|
|
cout << "Cannot load scene" << endl;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-10 15:30:43 +00:00
|
|
|
if( blenderScene->numberOfChildren() < 1) {
|
|
|
|
|
cout << "Empty scene" << endl;
|
2009-07-25 10:44:10 +00:00
|
|
|
blenderScene->destroy();
|
|
|
|
|
delete blenderScene;
|
2008-12-10 15:30:43 +00:00
|
|
|
return 1;
|
|
|
|
|
}
|
2008-08-07 15:04:25 +00:00
|
|
|
|
2008-12-10 15:30:43 +00:00
|
|
|
cout << "Scene loaded" << endl;
|
2008-08-07 15:04:25 +00:00
|
|
|
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
|
2008-08-07 16:15:10 +00:00
|
|
|
// ScenePrettyPrinter spp;
|
|
|
|
|
// blenderScene->accept(spp);
|
2008-08-07 15:04:25 +00:00
|
|
|
|
|
|
|
|
_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
|
2008-08-07 16:15:10 +00:00
|
|
|
_Grid.displayDebug();
|
|
|
|
|
//
|
|
|
|
|
// _pView->setDebug(_DebugNode);
|
2008-08-07 15:04:25 +00:00
|
|
|
|
|
|
|
|
//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;
|
|
|
|
|
}
|
|
|
|
|
|
2008-05-18 13:01:52 +00:00
|
|
|
|
|
|
|
|
void Controller::CloseFile()
|
|
|
|
|
{
|
2008-07-21 21:24:37 +00:00
|
|
|
WShape::setCurrentId(0);
|
2008-05-18 13:01:52 +00:00
|
|
|
_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;
|
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
|
|
|
|
2008-05-18 13:01:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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.
|
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
|
|
|
Vec3r vp( freestyle_viewpoint[0], freestyle_viewpoint[1], freestyle_viewpoint[2]);
|
|
|
|
|
|
2009-04-12 07:12:59 +00:00
|
|
|
//cout << "mv" << endl;
|
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
|
|
|
real mv[4][4];
|
2009-04-12 07:02:03 +00:00
|
|
|
for( int i= 0; i < 4; i++) {
|
|
|
|
|
for( int j= 0; j < 4; j++) {
|
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
|
|
|
mv[i][j] = freestyle_mv[i][j];
|
2009-04-12 07:12:59 +00:00
|
|
|
//cout << mv[i][j] << " ";
|
2009-04-12 07:02:03 +00:00
|
|
|
}
|
2009-04-12 07:12:59 +00:00
|
|
|
// cout << endl;
|
2009-04-12 07:02:03 +00:00
|
|
|
}
|
|
|
|
|
|
2009-04-12 07:12:59 +00:00
|
|
|
//cout << "\nproj" << endl;
|
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
|
|
|
real proj[4][4];
|
2009-04-12 07:02:03 +00:00
|
|
|
for( int i= 0; i < 4; i++) {
|
|
|
|
|
for( int j= 0; j < 4; j++) {
|
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
|
|
|
proj[i][j] = freestyle_proj[i][j];
|
2009-04-12 07:12:59 +00:00
|
|
|
//cout << proj[i][j] << " ";
|
2009-04-12 07:02:03 +00:00
|
|
|
}
|
2009-04-12 07:12:59 +00:00
|
|
|
//cout << endl;
|
2009-04-12 07:02:03 +00:00
|
|
|
}
|
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] = freestyle_viewport[i];
|
2009-04-12 07:02:03 +00:00
|
|
|
|
2009-04-12 07:12:59 +00:00
|
|
|
//cout << "\nfocal:" << _pView->GetFocalLength() << endl << endl;
|
2009-04-12 07:02:03 +00:00
|
|
|
|
|
|
|
|
|
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
|
|
|
|
2008-05-18 13:01:52 +00:00
|
|
|
// Flag the WXEdge structure for silhouette edge detection:
|
|
|
|
|
//----------------------------------------------------------
|
|
|
|
|
|
2008-12-10 21:51:58 +00:00
|
|
|
cout << "\n=== Detecting silhouette edges ===" << endl;
|
2008-05-18 13:01:52 +00:00
|
|
|
_Chrono.start();
|
|
|
|
|
|
2008-07-21 21:24:37 +00:00
|
|
|
edgeDetector.setViewpoint(Vec3r(vp));
|
2008-05-18 13:01:52 +00:00
|
|
|
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;
|
2008-07-21 21:24:37 +00:00
|
|
|
vmBuilder.setEnableQI(_EnableQI);
|
|
|
|
|
vmBuilder.setViewpoint(Vec3r(vp));
|
2008-12-10 21:51:58 +00:00
|
|
|
vmBuilder.setTransform( mv, proj,viewport, _pView->GetFocalLength(), _pView->GetAspect(), _pView->GetFovyRadian());
|
|
|
|
|
vmBuilder.setFrustum(_pView->znear(), _pView->zfar());
|
2008-07-21 21:24:37 +00:00
|
|
|
vmBuilder.setGrid(&_Grid);
|
2008-05-18 13:01:52 +00:00
|
|
|
|
|
|
|
|
// Builds a tesselated form of the silhouette for display purpose:
|
|
|
|
|
//---------------------------------------------------------------
|
|
|
|
|
ViewMapTesselator3D sTesselator3d;
|
|
|
|
|
//ViewMapTesselator2D sTesselator2d;
|
2008-07-21 21:24:37 +00:00
|
|
|
//sTesselator2d.setNature(_edgeTesselationNature);
|
|
|
|
|
sTesselator3d.setNature(_edgeTesselationNature);
|
2008-05-18 13:01:52 +00:00
|
|
|
|
2008-12-10 21:51:58 +00:00
|
|
|
cout << "\n=== Building the view map ===" << endl;
|
2008-05-18 13:01:52 +00:00
|
|
|
_Chrono.start();
|
|
|
|
|
// Build View Map
|
|
|
|
|
_ViewMap = vmBuilder.BuildViewMap(*_winged_edge, _VisibilityAlgo, _EPSILON);
|
|
|
|
|
_ViewMap->setScene3dBBox(_RootNode->bbox());
|
|
|
|
|
|
2008-08-07 15:04:25 +00:00
|
|
|
printf("ViewMap edge count : %i\n", _ViewMap->viewedges_size() );
|
|
|
|
|
|
2008-05-18 13:01:52 +00:00
|
|
|
//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;
|
2008-07-21 21:24:37 +00:00
|
|
|
// completeNS->material().setDiffuse(c,c,c,1);
|
2008-05-18 13:01:52 +00:00
|
|
|
// 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;
|
2008-07-21 21:24:37 +00:00
|
|
|
// ns->material().setDiffuse(wc, wc, wc, 1);
|
2008-05-18 13:01:52 +00:00
|
|
|
// 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;
|
|
|
|
|
|
2009-04-08 17:32:56 +00:00
|
|
|
cout << "\n=== Stroke drawing ===" << endl;
|
2008-05-18 13:01:52 +00:00
|
|
|
_Chrono.start();
|
|
|
|
|
_Canvas->Draw();
|
|
|
|
|
real d = _Chrono.stop();
|
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
|
|
|
cout << "Strokes generation : " << d << endl;
|
2008-12-10 22:06:27 +00:00
|
|
|
cout << "Stroke count : " << _Canvas->stroke_count << endl;
|
2008-05-18 13:01:52 +00:00
|
|
|
resetModified();
|
|
|
|
|
}
|
|
|
|
|
|
SUMMARY:
Freestyle's pipeline is now fully controllable at the layer level. It can be used:
- in any render layer
- with as many style modules per layer
DETAILS:
Freestyle usage has not changed:
- all the configuration happens in the "Freestyle" render panel, after it is enabled in the "Output" panel with the 'Freestyle' toggle.
- each render layer can choose to render Freestyle strokes by togglingo on 'FrSt' (in the "Render Layers" panel)
- it is fully compatible with compositor nodes
In the "Freestyle" panel, a render layer is selected via the menu list next to the "Render Layer:" label. The options displayed below are those of the currently selected render layer (and are not global to all render layers, as was previously the case).
Style modules are added by pressing the lower button "Add style module". Once added, the following operations are possible:
- deletion (cross)
- reordering (up/down arrows)
- toggling of display (check)
The order of the style modules follows Freestyle's original convention: the modules in the list from top to bottom are respectively the first to the last composited in the render layer. For example, if the module list is "contour" followed by "cartoon", the "cartoon" strokes are rendered on top of the "contour" strokes.
The "Freestyle" panel is constantly synchronized with the "Render Layers" panel: if render layers are added, deleted or toggled off display, Freestyle will take note of the changes.
The current pipeline works as follows:
----------------------------------------------------------------------------------------------
for every scene that is being rendered
if Freestyle is enabled globally
Freestyle is initialized
camera and view settings are transferred from Blender to Freestyle
for every render layer
if: - layer is enabled
- layer enabled Freestyle
- the number of displayed style modules is non-zero
canvas is cleared
geometry is transferred from Blender to Freestyle
settings are fixed for current iteration
view map is calculated
strokes are computed in the canvas (based on view map and style modules)
strokes are rendered in separate Blender scene
scene is composited in current layer
----------------------------------------------------------------------------------------------
A number of changes were made on the codebase:
- the rendering interface between Freestyle and Blender was simplified. The following naming convention was used: functions that are called from within Blender pipeline are prefixed with 'FRS_', while the variables are prefixed with 'freestyle_'
- Freestyle data structures that were put in Blender's render pipeline were removed
- Freestyle cleans up its data structures on Blender exit and shouldn't leak memory
- to ease the configuration in the "Freestyle" panel, a centralized configuration data structure was used and can be easily extended
LIMITATIONS
Even though the current commit is stable and achieves the intended result, it is not as efficient as it could be:
- the canvas and the style modules are at cleared at each layer-level render
- geometry is reloaded at each frame and is duplicated across render layers
This revision clarifies my understanding of the future role of the view map in the compositor. Unfortunately, contrary to what the original proposal said, it is impossible to provide the view map as a render pass because render passes are defined (RE_pipeline.h) as raw floating-point rects. We will have to determine whether or not to extend the notion of render pass to fully integrate the view map in the compositor.
2009-04-07 18:38:23 +00:00
|
|
|
Render* Controller::RenderStrokes(Render *re) {
|
2009-09-28 03:56:31 +00:00
|
|
|
BlenderStrokeRenderer* blenderRenderer = new BlenderStrokeRenderer(re);
|
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
|
|
|
_Canvas->Render( blenderRenderer );
|
SUMMARY:
Freestyle's pipeline is now fully controllable at the layer level. It can be used:
- in any render layer
- with as many style modules per layer
DETAILS:
Freestyle usage has not changed:
- all the configuration happens in the "Freestyle" render panel, after it is enabled in the "Output" panel with the 'Freestyle' toggle.
- each render layer can choose to render Freestyle strokes by togglingo on 'FrSt' (in the "Render Layers" panel)
- it is fully compatible with compositor nodes
In the "Freestyle" panel, a render layer is selected via the menu list next to the "Render Layer:" label. The options displayed below are those of the currently selected render layer (and are not global to all render layers, as was previously the case).
Style modules are added by pressing the lower button "Add style module". Once added, the following operations are possible:
- deletion (cross)
- reordering (up/down arrows)
- toggling of display (check)
The order of the style modules follows Freestyle's original convention: the modules in the list from top to bottom are respectively the first to the last composited in the render layer. For example, if the module list is "contour" followed by "cartoon", the "cartoon" strokes are rendered on top of the "contour" strokes.
The "Freestyle" panel is constantly synchronized with the "Render Layers" panel: if render layers are added, deleted or toggled off display, Freestyle will take note of the changes.
The current pipeline works as follows:
----------------------------------------------------------------------------------------------
for every scene that is being rendered
if Freestyle is enabled globally
Freestyle is initialized
camera and view settings are transferred from Blender to Freestyle
for every render layer
if: - layer is enabled
- layer enabled Freestyle
- the number of displayed style modules is non-zero
canvas is cleared
geometry is transferred from Blender to Freestyle
settings are fixed for current iteration
view map is calculated
strokes are computed in the canvas (based on view map and style modules)
strokes are rendered in separate Blender scene
scene is composited in current layer
----------------------------------------------------------------------------------------------
A number of changes were made on the codebase:
- the rendering interface between Freestyle and Blender was simplified. The following naming convention was used: functions that are called from within Blender pipeline are prefixed with 'FRS_', while the variables are prefixed with 'freestyle_'
- Freestyle data structures that were put in Blender's render pipeline were removed
- Freestyle cleans up its data structures on Blender exit and shouldn't leak memory
- to ease the configuration in the "Freestyle" panel, a centralized configuration data structure was used and can be easily extended
LIMITATIONS
Even though the current commit is stable and achieves the intended result, it is not as efficient as it could be:
- the canvas and the style modules are at cleared at each layer-level render
- geometry is reloaded at each frame and is duplicated across render layers
This revision clarifies my understanding of the future role of the view map in the compositor. Unfortunately, contrary to what the original proposal said, it is impossible to provide the view map as a render pass because render passes are defined (RE_pipeline.h) as raw floating-point rects. We will have to determine whether or not to extend the notion of render pass to fully integrate the view map in the compositor.
2009-04-07 18:38:23 +00:00
|
|
|
Render* freestyle_render = blenderRenderer->RenderScene(re);
|
2009-04-08 21:44:38 +00:00
|
|
|
delete blenderRenderer;
|
|
|
|
|
|
SUMMARY:
Freestyle's pipeline is now fully controllable at the layer level. It can be used:
- in any render layer
- with as many style modules per layer
DETAILS:
Freestyle usage has not changed:
- all the configuration happens in the "Freestyle" render panel, after it is enabled in the "Output" panel with the 'Freestyle' toggle.
- each render layer can choose to render Freestyle strokes by togglingo on 'FrSt' (in the "Render Layers" panel)
- it is fully compatible with compositor nodes
In the "Freestyle" panel, a render layer is selected via the menu list next to the "Render Layer:" label. The options displayed below are those of the currently selected render layer (and are not global to all render layers, as was previously the case).
Style modules are added by pressing the lower button "Add style module". Once added, the following operations are possible:
- deletion (cross)
- reordering (up/down arrows)
- toggling of display (check)
The order of the style modules follows Freestyle's original convention: the modules in the list from top to bottom are respectively the first to the last composited in the render layer. For example, if the module list is "contour" followed by "cartoon", the "cartoon" strokes are rendered on top of the "contour" strokes.
The "Freestyle" panel is constantly synchronized with the "Render Layers" panel: if render layers are added, deleted or toggled off display, Freestyle will take note of the changes.
The current pipeline works as follows:
----------------------------------------------------------------------------------------------
for every scene that is being rendered
if Freestyle is enabled globally
Freestyle is initialized
camera and view settings are transferred from Blender to Freestyle
for every render layer
if: - layer is enabled
- layer enabled Freestyle
- the number of displayed style modules is non-zero
canvas is cleared
geometry is transferred from Blender to Freestyle
settings are fixed for current iteration
view map is calculated
strokes are computed in the canvas (based on view map and style modules)
strokes are rendered in separate Blender scene
scene is composited in current layer
----------------------------------------------------------------------------------------------
A number of changes were made on the codebase:
- the rendering interface between Freestyle and Blender was simplified. The following naming convention was used: functions that are called from within Blender pipeline are prefixed with 'FRS_', while the variables are prefixed with 'freestyle_'
- Freestyle data structures that were put in Blender's render pipeline were removed
- Freestyle cleans up its data structures on Blender exit and shouldn't leak memory
- to ease the configuration in the "Freestyle" panel, a centralized configuration data structure was used and can be easily extended
LIMITATIONS
Even though the current commit is stable and achieves the intended result, it is not as efficient as it could be:
- the canvas and the style modules are at cleared at each layer-level render
- geometry is reloaded at each frame and is duplicated across render layers
This revision clarifies my understanding of the future role of the view map in the compositor. Unfortunately, contrary to what the original proposal said, it is impossible to provide the view map as a render pass because render passes are defined (RE_pipeline.h) as raw floating-point rects. We will have to determine whether or not to extend the notion of render pass to fully integrate the view map in the compositor.
2009-04-07 18:38:23 +00:00
|
|
|
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
|
|
|
}
|
|
|
|
|
|
2008-05-18 13:01:52 +00:00
|
|
|
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)
|
|
|
|
|
{
|
2008-07-21 21:24:37 +00:00
|
|
|
_Canvas->setVisible(index, iDisplay);
|
2008-05-18 13:01:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
2008-08-07 15:04:25 +00:00
|
|
|
FrsMaterial mat;
|
2008-07-21 21:24:37 +00:00
|
|
|
mat.setDiffuse(1,1,0.3,1);
|
2008-08-07 15:04:25 +00:00
|
|
|
tesselator2D.setFrsMaterial(mat);
|
2008-05-18 13:01:52 +00:00
|
|
|
|
|
|
|
|
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)
|
2008-07-21 21:24:37 +00:00
|
|
|
// _pDensityCurvesWindow->setOrientationCurve(i, Vec2d(0,0), Vec2d(nbPoints, 1), curves[i], "scale", "density");
|
2008-05-18 13:01:52 +00:00
|
|
|
// for(i=1; i<=8; ++i)
|
2008-07-21 21:24:37 +00:00
|
|
|
// _pDensityCurvesWindow->setLevelCurve(i, Vec2d(0,0), Vec2d(nbCurves, 1), curvesDirection[i], "orientation", "density");
|
2008-05-18 13:01:52 +00:00
|
|
|
// _pDensityCurvesWindow->show();
|
|
|
|
|
}
|
2008-05-26 16:19:30 +00:00
|
|
|
|
|
|
|
|
void Controller::init_options(){
|
2008-05-26 19:52:55 +00:00
|
|
|
// from AppOptionsWindow.cpp
|
|
|
|
|
// Default init options
|
|
|
|
|
|
|
|
|
|
Config::Path * cpath = Config::Path::getInstance();
|
2008-06-13 22:23:24 +00:00
|
|
|
|
2008-05-26 19:52:55 +00:00
|
|
|
// 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);
|
|
|
|
|
|
2008-05-27 14:13:16 +00:00
|
|
|
// soc: initialize canvas
|
|
|
|
|
_Canvas->init();
|
2008-05-26 16:19:30 +00:00
|
|
|
}
|