X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=synfig-core%2Ftrunk%2Fsrc%2Fmodules%2Flyr_std%2Fsphere_distort.cpp;h=9c0003e677e2c6141fbf216e8fb691f4fbca51db;hb=9459638ad6797b8139f1e9f0715c96076dbf0890;hp=af4c3c728e121b81eb657a9c2243ca98fe4eed50;hpb=16b3beced25134bef064705568ecb893a6be4e79;p=synfig.git diff --git a/synfig-core/trunk/src/modules/lyr_std/sphere_distort.cpp b/synfig-core/trunk/src/modules/lyr_std/sphere_distort.cpp index af4c3c7..9c0003e 100644 --- a/synfig-core/trunk/src/modules/lyr_std/sphere_distort.cpp +++ b/synfig-core/trunk/src/modules/lyr_std/sphere_distort.cpp @@ -1,20 +1,22 @@ -/* === S I N F G =========================================================== */ +/* === S Y N F I G ========================================================= */ /*! \file sphere_distort.cpp -** \brief Sphere Distort File +** \brief Implementation of the "Spherize" layer ** -** $Id: sphere_distort.cpp,v 1.2 2005/01/24 05:00:18 darco Exp $ +** $Id$ ** ** \legal -** Copyright (c) 2002 Robert B. Quattlebaum Jr. +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** Copyright (c) 2007, 2008 Chris Moore ** -** This software and associated documentation -** are CONFIDENTIAL and PROPRIETARY property of -** the above-mentioned copyright holder. +** This package 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. ** -** You may not copy, print, publish, or in any -** other way distribute this software without -** a prior written agreement with -** the copyright holder. +** This package 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. ** \endlegal */ /* ========================================================================= */ @@ -29,17 +31,17 @@ #endif #include "sphere_distort.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include #endif @@ -47,7 +49,7 @@ using namespace std; using namespace etl; -using namespace sinfg; +using namespace synfig; /* === M A C R O S ========================================================= */ @@ -65,12 +67,12 @@ enum /* === G L O B A L S ======================================================= */ -SINFG_LAYER_INIT(Layer_SphereDistort); -SINFG_LAYER_SET_NAME(Layer_SphereDistort,"spherize"); -SINFG_LAYER_SET_LOCAL_NAME(Layer_SphereDistort,_("Spherize")); -SINFG_LAYER_SET_CATEGORY(Layer_SphereDistort,_("Distortions")); -SINFG_LAYER_SET_VERSION(Layer_SphereDistort,"0.2"); -SINFG_LAYER_SET_CVS_ID(Layer_SphereDistort,"$Id: sphere_distort.cpp,v 1.2 2005/01/24 05:00:18 darco Exp $"); +SYNFIG_LAYER_INIT(Layer_SphereDistort); +SYNFIG_LAYER_SET_NAME(Layer_SphereDistort,"spherize"); +SYNFIG_LAYER_SET_LOCAL_NAME(Layer_SphereDistort,N_("Spherize")); +SYNFIG_LAYER_SET_CATEGORY(Layer_SphereDistort,N_("Distortions")); +SYNFIG_LAYER_SET_VERSION(Layer_SphereDistort,"0.2"); +SYNFIG_LAYER_SET_CVS_ID(Layer_SphereDistort,"$Id$"); /* === P R O C E D U R E S ================================================= */ @@ -79,16 +81,15 @@ SINFG_LAYER_SET_CVS_ID(Layer_SphereDistort,"$Id: sphere_distort.cpp,v 1.2 2005/0 /* === E N T R Y P O I N T ================================================= */ Layer_SphereDistort::Layer_SphereDistort() -:Layer_Composite(1.0,Color::BLEND_STRAIGHT), -center(0,0), +:center(0,0), radius(1), -percent(1,1), +percent(1.0), type(TYPE_NORMAL), clip(false) { } - + bool Layer_SphereDistort::set_param(const String & param, const ValueBase &value) { @@ -104,13 +105,13 @@ Layer_SphereDistort::set_param(const String & param, const ValueBase &value) { connect_dynamic_param("amount",dynamic_param_list().find("percent")->second); disconnect_dynamic_param("percent"); - sinfg::warning("Layer_SphereDistort::::set_param(): Updated valuenode connection to use the new \"amount\" parameter."); + synfig::warning("Layer_SphereDistort::::set_param(): Updated valuenode connection to use the new \"amount\" parameter."); } else - sinfg::warning("Layer_SphereDistort::::set_param(): The parameter \"segment_list\" is deprecated. Use \"bline\" instead."); + synfig::warning("Layer_SphereDistort::::set_param(): The parameter \"segment_list\" is deprecated. Use \"bline\" instead."); } - - return false; + + return false; } ValueBase @@ -121,10 +122,10 @@ Layer_SphereDistort::get_param(const String ¶m)const EXPORT(type); EXPORT_AS(percent,"amount"); EXPORT(clip); - + EXPORT_NAME(); EXPORT_VERSION(); - + return ValueBase(); } @@ -137,17 +138,17 @@ Layer::Vocab Layer_SphereDistort::get_param_vocab()const { Layer::Vocab ret; - + ret.push_back(ParamDesc("center") .set_local_name(_("Position")) ); - + ret.push_back(ParamDesc("radius") .set_local_name(_("Radius")) .set_origin("center") .set_is_distance() ); - + ret.push_back(ParamDesc("amount") .set_local_name(_("Amount")) .set_is_distance(false) @@ -156,7 +157,7 @@ Layer_SphereDistort::get_param_vocab()const ret.push_back(ParamDesc("clip") .set_local_name(_("Clip")) ); - + ret.push_back(ParamDesc("type") .set_local_name(_("Distort Type")) .set_description(_("The direction of the distortion")) @@ -165,30 +166,30 @@ Layer_SphereDistort::get_param_vocab()const .add_enum_value(TYPE_DISTH,"honly",_("Vertical Bar")) .add_enum_value(TYPE_DISTV,"vonly",_("Horizontal Bar")) ); - + return ret; } /* Spherical Distortion: maps an image onto a ellipsoid of some sort - - so the image coordinate (i.e. distance away from the center) + + so the image coordinate (i.e. distance away from the center) will determine how things get mapped - + so with the radius and position the mapping would go as follows - + r = (pos - center) / radius clamped to [-1,1] - + if it's outside of that range then it's not distorted but if it's inside of that range then it goes as follows - + angle = r * pi/2 (-pi/2,pi/2) - + newr = cos(angle)*radius - + the inverse of this is (which is actually what we'd be transforming it from - + */ inline float spherify(float f) @@ -205,21 +206,21 @@ inline float unspherify(float f) else return f; } -Point sphtrans(const Point &p, const Point ¢er, const float &radius, +Point sphtrans(const Point &p, const Point ¢er, const float &radius, const Real &percent, int type, bool& clipped) { const Vector v = (p - center) / radius; - + Point newp = p; const float t = percent; - + clipped=false; - + if(type == TYPE_NORMAL) { const float m = v.mag(); float lerp(0); - + if(m <= -1 || m >= 1) { clipped=true; @@ -232,14 +233,14 @@ Point sphtrans(const Point &p, const Point ¢er, const float &radius, { lerp = (t*unspherify(m) + (1-t)*m); }else if(t < 0) - { + { lerp = ((1+t)*m - t*spherify(m)); }else lerp = m; - + const float d = lerp*radius; newp = center + v*(d/m); } - + else if(type == TYPE_DISTH) { float lerp(0); @@ -258,10 +259,10 @@ Point sphtrans(const Point &p, const Point ¢er, const float &radius, { lerp = ((1+t)*v[0] - t*spherify(v[0])); }else lerp = v[0]; - + newp[0] = center[0] + lerp*radius; } - + else if(type == TYPE_DISTV) { float lerp(0); @@ -281,22 +282,22 @@ Point sphtrans(const Point &p, const Point ¢er, const float &radius, { lerp = ((1+t)*v[1] - t*spherify(v[1])); }else lerp = v[1]; - + newp[1] = center[1] + lerp*radius; } - + return newp; } -inline Point sphtrans(const Point &p, const Point ¢er, const Real &radius, +inline Point sphtrans(const Point &p, const Point ¢er, const Real &radius, const Real &percent, int type) { bool tmp; return sphtrans(p, center, radius, percent, type, tmp); } -sinfg::Layer::Handle -Layer_SphereDistort::hit_check(sinfg::Context context, const sinfg::Point &pos)const +synfig::Layer::Handle +Layer_SphereDistort::hit_check(synfig::Context context, const synfig::Point &pos)const { bool clipped; Point point(sphtrans(pos,center,radius,percent,type,clipped)); @@ -323,78 +324,85 @@ bool Layer_SphereDistort::accelerated_render(Context context,Surface *surface,in 2) Bounding box clipping 3) Super sampling for better visual quality (based on the quality level?) 4) Interpolation type for sampling (based on quality level?) - + //things to defer until after super sampling, non-linear interpolation */ - + //bounding box reject { Rect sphr; - + sphr.set_point(center[0]-radius,center[1]-radius); sphr.expand(center[0]+radius,center[1]+radius); - //get the bounding box of the transform + //get the bounding box of the transform Rect windr; - - //and the bounding box of the rendering + + //and the bounding box of the rendering windr.set_point(renddesc.get_tl()[0],renddesc.get_tl()[1]); windr.expand(renddesc.get_br()[0],renddesc.get_br()[1]); - + //test bounding boxes for collision if( (type == TYPE_NORMAL && !intersect(sphr,windr)) || (type == TYPE_DISTH && (sphr.minx >= windr.maxx || windr.minx >= sphr.maxx)) || (type == TYPE_DISTV && (sphr.miny >= windr.maxy || windr.miny >= sphr.maxy)) ) { - //sinfg::warning("Spherize: Bounding box reject"); - return context.accelerated_render(surface,quality,renddesc,cb); + //synfig::warning("Spherize: Bounding box reject"); + if (clip) + { + surface->set_wh(renddesc.get_w(), renddesc.get_h()); + surface->clear(); + return true; + } + else + return context.accelerated_render(surface,quality,renddesc,cb); } - - //sinfg::warning("Spherize: Bounding box accept"); + + //synfig::warning("Spherize: Bounding box accept"); } - + //Ok, so we overlap some... now expand the window for rendering RendDesc r = renddesc; Surface background; Real pw = renddesc.get_pw(),ph = renddesc.get_ph(); - + int nl=0,nt=0,nr=0,nb=0, nw=0,nh=0; Point tl = renddesc.get_tl(), br = renddesc.get_br(); - - { + + { //must enlarge window by pixel coordinates so go! - + //need to figure out closest and farthest point and distort THOSE - + Point origin[4] = {tl,tl,br,br}; Vector v[4] = {Vector(0,br[1]-tl[1]), Vector(br[0]-tl[0],0), Vector(0,tl[1]-br[1]), Vector(tl[0]-br[0],0)}; - + Point close(0,0); Real t = 0; Rect expandr(tl,br); - + //expandr.set_point(tl[0],tl[1]); //expandr.expand(br[0],br[1]); - //sinfg::warning("Spherize: Loop through lines and stuff"); + //synfig::warning("Spherize: Loop through lines and stuff"); for(int i=0; i<4; ++i) { - //sinfg::warning("Spherize: %d", i); + //synfig::warning("Spherize: %d", i); Vector p_o = center-origin[i]; - + //project onto left line t = (p_o*v[i])/v[i].mag_squared(); - + //clamp if(t < 0) t = 0; if(t > 1) t = 1; - + close = origin[i] + v[i]*t; - - //now get transforms and expand the rectangle to accomodate + + //now get transforms and expand the rectangle to accommodate Point p = sphtrans(close,center,radius,percent,type); expandr.expand(p[0],p[1]); p = sphtrans(origin[i],center,radius,percent,type); @@ -402,83 +410,83 @@ bool Layer_SphereDistort::accelerated_render(Context context,Surface *surface,in p = sphtrans(origin[i]+v[i],center,radius,percent,type); expandr.expand(p[0],p[1]); } - - /*sinfg::warning("Spherize: Bounding box (%f,%f)-(%f,%f)", + + /*synfig::warning("Spherize: Bounding box (%f,%f)-(%f,%f)", expandr.minx,expandr.miny,expandr.maxx,expandr.maxy);*/ - - //now that we have the bouding rectangle of ALL the pixels (should be...) + + //now that we have the bounding rectangle of ALL the pixels (should be...) //order it so that it's in the same orientation as the tl,br pair - //sinfg::warning("Spherize: Organize like tl,br"); + //synfig::warning("Spherize: Organize like tl,br"); Point ntl(0,0),nbr(0,0); - + //sort x if(tl[0] < br[0]) - { + { ntl[0] = expandr.minx; nbr[0] = expandr.maxx; } else { ntl[0] = expandr.maxx; - nbr[0] = expandr.minx; + nbr[0] = expandr.minx; } - + //sort y if(tl[1] < br[1]) - { + { ntl[1] = expandr.miny; nbr[1] = expandr.maxy; } else { ntl[1] = expandr.maxy; - nbr[1] = expandr.miny; + nbr[1] = expandr.miny; } - + //now expand the window as needed Vector temp = ntl-tl; - + //pixel offset nl = (int)(temp[0]/pw)-1; nt = (int)(temp[1]/ph)-1; - + temp = nbr - br; nr = (int)(temp[0]/pw)+1; nb = (int)(temp[1]/ph)+1; - + nw = renddesc.get_w() + nr - nl; nh = renddesc.get_h() + nb - nt; - - //sinfg::warning("Spherize: Setting subwindow (%d,%d) (%d,%d) (%d,%d)",nl,nt,nr,nb,nw,nh); + + //synfig::warning("Spherize: Setting subwindow (%d,%d) (%d,%d) (%d,%d)",nl,nt,nr,nb,nw,nh); r.set_subwindow(nl,nt,nw,nh); - + /*r = renddesc; nw = r.get_w(), nh = r.get_h(); nl = 0, nt = 0;*/ } - - //sinfg::warning("Spherize: render background"); + + //synfig::warning("Spherize: render background"); if(!context.accelerated_render(&background,quality,r,cb)) { - sinfg::warning("SphereDistort: Layer below failed"); + synfig::warning("SphereDistort: Layer below failed"); return false; } - + //now distort and check to make sure we aren't overshooting our bounds here int w = renddesc.get_w(), h = renddesc.get_h(); surface->set_wh(w,h); - + Point sample = tl, sub = tl, trans(0,0); float xs = 0,ys = 0; int y=0,x=0; Real invpw = 1/pw, invph = 1/ph; Surface::pen p = surface->begin(); - + Point rtl = r.get_tl(); - - //sinfg::warning("Spherize: About to transform"); - + + //synfig::warning("Spherize: About to transform"); + for(y = 0; y < h; ++y, sample[1] += ph, p.inc_y()) { sub = sample; @@ -494,48 +502,43 @@ bool Layer_SphereDistort::accelerated_render(Context context,Surface *surface,in xs = (trans[0]-rtl[0])*invpw; ys = (trans[1]-rtl[1])*invph; - + if(!(xs >= 0 && xs < nw && ys >= 0 && ys < nh)) { - //sinfg::warning("Spherize: we failed to account for %f,%f",xs,ys); + //synfig::warning("Spherize: we failed to account for %f,%f",xs,ys); p.put_value(context.get_color(trans));//Color::alpha()); continue; } - - //sample at that pixel location based on the quality - if(quality <= 4) //cubic - { + + //sample at that pixel location based on the quality + if(quality <= 4) // cubic p.put_value(background.cubic_sample(xs,ys)); - }else if(quality <= 5) //cosine - { + else if(quality <= 5) // cosine p.put_value(background.cosine_sample(xs,ys)); - }else if(quality <= 6) //linear - { + else if(quality <= 6) // linear p.put_value(background.linear_sample(xs,ys)); - }else //nearest - { + else // nearest p.put_value(background[round_to_int(ys)][round_to_int(xs)]); - } } p.dec_x(w); } - - return true; + + return true; } #endif -class Spherize_Trans : public Transform +class synfig::Spherize_Trans : public synfig::Transform { etl::handle layer; public: Spherize_Trans(const Layer_SphereDistort* x):Transform(x->get_guid()),layer(x) { } - - sinfg::Vector perform(const sinfg::Vector& x)const + + synfig::Vector perform(const synfig::Vector& x)const { return sphtrans(x,layer->center,layer->radius,-layer->percent,layer->type); } - - sinfg::Vector unperform(const sinfg::Vector& x)const + + synfig::Vector unperform(const synfig::Vector& x)const { return sphtrans(x,layer->center,layer->radius,layer->percent,layer->type); } @@ -551,24 +554,25 @@ Rect Layer_SphereDistort::get_bounding_rect()const { Rect bounds(Rect::full_plane()); + + if (clip) + return bounds; + switch(type) { case TYPE_NORMAL: - bounds=Rect( - center[0]+(radius), - center[1]+(radius), - center[0]-(radius), - center[1]-(radius) - ); + bounds=Rect(center[0]+radius, center[1]+radius, + center[0]-radius, center[1]-radius); break; case TYPE_DISTH: + bounds = Rect::vertical_strip(center[0]-radius, center[0]+radius); break; case TYPE_DISTV: + bounds = Rect::horizontal_strip(center[1]-radius, center[1]+radius); break; default: break; } - + return bounds; } -