diff options
author | Maxime Curioni <maxime.curioni@gmail.com> | 2008-05-08 23:16:40 +0400 |
---|---|---|
committer | Maxime Curioni <maxime.curioni@gmail.com> | 2008-05-08 23:16:40 +0400 |
commit | 64e4a3ec9aed6c8abe095e2cd1fe1552f7cde51c (patch) | |
tree | 6c77358bd447b6c2d215324ef48fc12d1f5ae5ca /source/blender/freestyle/intern/stroke/Canvas.cpp | |
parent | cf2e1e2857cfc5b3c2848c7fc6c9d919ac72fabb (diff) | |
parent | 106974a9d2d5caa5188322507980e3d57d2e3517 (diff) |
soc-2008-mxcurioni: merged changes to revision 14747, cosmetic changes for source/blender/freestyle
Diffstat (limited to 'source/blender/freestyle/intern/stroke/Canvas.cpp')
-rwxr-xr-x | source/blender/freestyle/intern/stroke/Canvas.cpp | 427 |
1 files changed, 427 insertions, 0 deletions
diff --git a/source/blender/freestyle/intern/stroke/Canvas.cpp b/source/blender/freestyle/intern/stroke/Canvas.cpp new file mode 100755 index 00000000000..ecb76c4a015 --- /dev/null +++ b/source/blender/freestyle/intern/stroke/Canvas.cpp @@ -0,0 +1,427 @@ + +// +// 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 <vector> +#include "../system/FreestyleConfig.h" +#include "StrokeRenderer.h" +#include "../system/TimeStamp.h" +#include "../system/PseudoNoise.h" +#include "Canvas.h" +#include <qimage.h> +#include <QString> +#include "../image/Image.h" +#include "../image/GaussianFilter.h" +#include "../image/ImagePyramid.h" +#include "../view_map/SteerableViewMap.h" +#include "StyleModule.h" + +using namespace std; + +LIB_STROKE_EXPORT +Canvas * Canvas::_pInstance = 0; + +LIB_STROKE_EXPORT +const char * Canvas::_MapsPath = 0; + +using namespace std; + +Canvas::Canvas() +{ + _SelectedFEdge = 0; + _pInstance = this; + PseudoNoise::init(42); + _paperTextureIndex = 0; + _Renderer = 0; + _drawPaper = true; + _current_sm = NULL; + _steerableViewMap = new SteerableViewMap(NB_STEERABLE_VIEWMAP-1); +} + +Canvas::Canvas(const Canvas& iBrother) +{ + _SelectedFEdge = iBrother._SelectedFEdge; + _pInstance = this; + PseudoNoise::init(42); + _paperTextureIndex = iBrother._paperTextureIndex; + _Renderer = iBrother._Renderer; + _drawPaper = iBrother._drawPaper; + _current_sm = iBrother._current_sm; + _steerableViewMap = new SteerableViewMap(*(iBrother._steerableViewMap)); + +} + +Canvas::~Canvas() +{ + _pInstance = 0; + + Clear(); + if(_Renderer) + { + delete _Renderer; + _Renderer = 0; + } + // FIXME: think about an easy control + // for the maps memory management... + if(!_maps.empty()){ + for(mapsMap::iterator m=_maps.begin(), mend=_maps.end(); + m!=mend; + ++m){ + delete ((*m).second); + } + _maps.clear(); + } + if(_steerableViewMap) + delete _steerableViewMap; +} + +void Canvas::preDraw() {} + +void Canvas::Draw() +{ + if(_StyleModules.empty()) + return; + preDraw(); + TimeStamp *timestamp = TimeStamp::instance(); + + for(unsigned i = 0; i < _StyleModules.size(); i++) { + _current_sm = _StyleModules[i]; + if (!_StyleModules[i]->getModified()) + { + if (_StyleModules[i]->getDrawable() && _Layers[i]) + _Layers[i]->Render(_Renderer); + continue; + } + if (i < _Layers.size() && _Layers[i]) + delete _Layers[i]; + + _Layers[i] = _StyleModules[i]->execute(); + + if (_StyleModules[i]->getDrawable() && _Layers[i]) + _Layers[i]->Render(_Renderer); + + timestamp->increment(); + } + postDraw(); +} + +void Canvas::postDraw() +{ + update(); +} + + +void Canvas::Clear() +{ + if(!_Layers.empty()) { + for (deque<StrokeLayer*>::iterator sl=_Layers.begin(), slend=_Layers.end(); + sl != slend; + ++sl) + if (*sl) + delete (*sl); + _Layers.clear(); + } + + if(!_StyleModules.empty()) { + for (deque<StyleModule*>::iterator s=_StyleModules.begin(), send=_StyleModules.end(); + s != send; + ++s) + if (*s) + delete (*s); + _StyleModules.clear(); + } + if(_steerableViewMap) + _steerableViewMap->Reset(); +} + +void Canvas::Erase() +{ + if(!_Layers.empty()) + { + for (deque<StrokeLayer*>::iterator sl=_Layers.begin(), slend=_Layers.end(); + sl != slend; + ++sl) + if (*sl) + (*sl)->clear(); + } + if(_steerableViewMap) + _steerableViewMap->Reset(); + update(); +} + +void Canvas::InsertStyleModule(unsigned index, StyleModule *iStyleModule) { + unsigned size = _StyleModules.size(); + StrokeLayer* layer = new StrokeLayer(); + if((_StyleModules.empty()) || (index == size)) { + _StyleModules.push_back(iStyleModule); + _Layers.push_back(layer); + return; + } + _StyleModules.insert(_StyleModules.begin() + index, iStyleModule); + _Layers.insert(_Layers.begin()+index, layer); +} + +void Canvas::RemoveStyleModule(unsigned index) +{ + unsigned i=0; + if (!_StyleModules.empty()) + { + for(deque<StyleModule*>::iterator s=_StyleModules.begin(), send=_StyleModules.end(); + s!=send; + ++s) + { + if(i == index) + { + // remove shader + if (*s) + delete *s; + _StyleModules.erase(s); + break; + } + ++i; + } + } + i=0; + if(!_Layers.empty()) + { + for(deque<StrokeLayer*>::iterator sl=_Layers.begin(), slend=_Layers.end(); + sl!=slend; + ++sl) + { + if(i == index) + { + // remove layer + if (*sl) + delete *sl; + _Layers.erase(sl); + break; + } + ++i; + } + } +} + + +void Canvas::SwapStyleModules(unsigned i1, unsigned i2) +{ + StyleModule* tmp; + tmp = _StyleModules[i1]; + _StyleModules[i1] = _StyleModules[i2]; + _StyleModules[i2] = tmp; + + StrokeLayer* tmp2; + tmp2 = _Layers[i1]; + _Layers[i1] = _Layers[i2]; + _Layers[i2] = tmp2; +} + +void Canvas::ReplaceStyleModule(unsigned index, StyleModule *iStyleModule) +{ + unsigned i=0; + for(deque<StyleModule*>::iterator s=_StyleModules.begin(), send=_StyleModules.end(); + s != send; + ++s) + { + if(i == index) + { + if (*s) + delete *s; + *s = iStyleModule; + break; + } + ++i; + } +} + +void Canvas::SetVisible(unsigned index, bool iVisible) { + _StyleModules[index]->setDisplayed(iVisible); +} + +void Canvas::setModified(unsigned index, bool iMod) +{ + _StyleModules[index]->setModified(iMod); +} + +void Canvas::resetModified(bool iMod/* =false */) +{ + unsigned size = _StyleModules.size(); + for(unsigned i = 0; i < size; ++i) + setModified(i,iMod); +} + +void Canvas::causalStyleModules(vector<unsigned>& vec, unsigned index) { + unsigned size = _StyleModules.size(); + + for(unsigned i = index; i < size; ++i) + if (_StyleModules[i]->getCausal()) + vec.push_back(i); +} + +void Canvas::changePaperTexture(bool increment) +{ + if(increment) + _paperTextureIndex = (_paperTextureIndex+1) % TextureManager::getPaperTexturesNumber(); + else + { + _paperTextureIndex--; + if(_paperTextureIndex < 0) + _paperTextureIndex = TextureManager::getPaperTexturesNumber() - 1; + } +} + +void Canvas::Render(const StrokeRenderer *iRenderer) +{ + for (unsigned i = 0; i < _StyleModules.size(); i++) { + if(!_StyleModules[i]->getDisplayed() || !_Layers[i]) + continue; + _Layers[i]->Render(iRenderer); + } +} + +void Canvas::RenderBasic(const StrokeRenderer *iRenderer) + +{ + for (unsigned i = 0; i < _StyleModules.size(); i++) { + if(!_StyleModules[i]->getDisplayed() || !_Layers[i]) + continue; + _Layers[i]->RenderBasic(iRenderer); + } +} + +void Canvas::loadMap(const char *iFileName, const char *iMapName, unsigned int iNbLevels, float iSigma){ + // check whether this map was already loaded: + if(!_maps.empty()){ + mapsMap::iterator m = _maps.find(iMapName); + if(m!=_maps.end()){ + // lazy check for size changes + ImagePyramid * pyramid = (*m).second; + if((pyramid->width() != width()) || (pyramid->height() != height())){ + delete pyramid; + }else{ + return; + } + } + } + string filePath; + if(_MapsPath){ + filePath = _MapsPath; + filePath += iFileName; + }else{ + filePath = iFileName; + } + QImage * qimg; + QImage newMap(filePath.c_str()); + if(newMap.isNull()){ + cout << "Could not load image file " << filePath << endl; + return; + } + qimg = &newMap; + + //resize + QImage scaledImg; + if((newMap.width()!=width()) || (newMap.height()!=height())){ + scaledImg = newMap.scaled(width(), height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + qimg = &scaledImg; + } + + // deal with color image + // if(newMap->depth() != 8){ + // int w = newMap->width(); + // int h = newMap->height(); + // QImage *tmp = new QImage(w, h, 8); + // for(unsigned y=0;y<h;++y){ + // for(unsigned x=0;x<w;++x){ + // int c = qGray(newMap->pixel(x,y)); + // tmp->setPixel(x,y,c); + // } + // } + // delete newMap; + // newMap = tmp; + // } + + unsigned x,y; + int w = qimg->width(); + int h = qimg->height(); + GrayImage tmp(w,h); + for(y=0; y<h;++y){ + for(x=0;x<w;++x){ + float c = qGray(qimg->pixel(x,y));// /255.f; + tmp.setPixel(x,y,c); + } + } + + // GrayImage blur(w,h); + // GaussianFilter gf(4.f); + // //int bound = gf.getBound(); + // for(y=0; y<h;++y){ + // for(x=0;x<w;++x){ + // int c = gf.getSmoothedPixel<GrayImage>(&tmp, x,y); + // blur.setPixel(x,y,c); + // } + // } + + GaussianPyramid *pyramid = new GaussianPyramid(tmp, iNbLevels, iSigma); + int ow = pyramid->width(0); + int oh = pyramid->height(0); + QString base(iMapName); + for(unsigned i=0; i<pyramid->getNumberOfLevels(); ++i){ + // save each image: + // w = pyramid.width(i); + // h = pyramid.height(i); + QImage qtmp(ow, oh, QImage::Format_RGB32); + //int k = (1<<i); + for(y=0;y<oh;++y){ + for(x=0;x<ow;++x){ + int c = pyramid->pixel(x,y,i);//255*pyramid->pixel(x,y,i); + qtmp.setPixel(x,y,qRgb(c,c,c)); + } + } + qtmp.save(base+QString::number(i)+".bmp", "BMP"); + } + // QImage *qtmp = new QImage(w, h, 32); + // for(y=0;y<h;++y){ + // for(x=0;x<w;++x){ + // int c = (int)blur.pixel(x,y); + // qtmp->setPixel(x,y,qRgb(c,c,c)); + // } + // } + // delete newMap; + // newMap = qtmp; + // + _maps[iMapName] = pyramid; + // newMap->save("toto.bmp", "BMP"); +} + +float Canvas::readMapPixel(const char *iMapName, int level, int x, int y){ + if(_maps.empty()){ + cout << "readMapPixel warning: no map was loaded "<< endl; + return -1; + } + mapsMap::iterator m = _maps.find(iMapName); + if(m==_maps.end()){ + cout << "readMapPixel warning: no map was loaded with the name " << iMapName << endl; + return -1; + } + ImagePyramid *pyramid = (*m).second; + if((x<0) || (x>=pyramid->width()) || (y<0) || (y>=pyramid->height())) + return 0; + + return pyramid->pixel(x,height()-1-y,level); +} |