X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=synfig-core%2Ftags%2Fsynfig_0_61_03%2Fsynfig-core%2Fsrc%2Fmodules%2Flyr_std%2Fsphere_distort.cpp;fp=synfig-core%2Ftags%2Fsynfig_0_61_03%2Fsynfig-core%2Fsrc%2Fmodules%2Flyr_std%2Fsphere_distort.cpp;h=0000000000000000000000000000000000000000;hb=6fa8f2f38d4b0b35f8539bf94e27ae27015c7689;hp=cf37a99c2a526f149cdbaaa79d3c730e883a26a2;hpb=47fce282611fbba1044921d22ca887f9b53ad91a;p=synfig.git diff --git a/synfig-core/tags/synfig_0_61_03/synfig-core/src/modules/lyr_std/sphere_distort.cpp b/synfig-core/tags/synfig_0_61_03/synfig-core/src/modules/lyr_std/sphere_distort.cpp deleted file mode 100644 index cf37a99..0000000 --- a/synfig-core/tags/synfig_0_61_03/synfig-core/src/modules/lyr_std/sphere_distort.cpp +++ /dev/null @@ -1,575 +0,0 @@ -/* === S Y N F I G ========================================================= */ -/*! \file sphere_distort.cpp -** \brief Sphere Distort File -** -** $Id: sphere_distort.cpp,v 1.2 2005/01/24 05:00:18 darco Exp $ -** -** \legal -** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley -** -** 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. -** -** 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 -*/ -/* ========================================================================= */ - -/* === H E A D E R S ======================================================= */ - -#ifdef USING_PCH -# include "pch.h" -#else -#ifdef HAVE_CONFIG_H -# include -#endif - -#include "sphere_distort.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#endif - -/* === U S I N G =========================================================== */ - -using namespace std; -using namespace etl; -using namespace synfig; - -/* === M A C R O S ========================================================= */ - -#ifndef PI -const double PI = 3.14159265; -#endif - -enum -{ - TYPE_NORMAL = 0, - TYPE_DISTH = 1, //axe the horizontal axis - TYPE_DISTV = 2, //axe the vertical axis - N_TYPES -}; - -/* === G L O B A L S ======================================================= */ - -SYNFIG_LAYER_INIT(Layer_SphereDistort); -SYNFIG_LAYER_SET_NAME(Layer_SphereDistort,"spherize"); -SYNFIG_LAYER_SET_LOCAL_NAME(Layer_SphereDistort,_("Spherize")); -SYNFIG_LAYER_SET_CATEGORY(Layer_SphereDistort,_("Distortions")); -SYNFIG_LAYER_SET_VERSION(Layer_SphereDistort,"0.2"); -SYNFIG_LAYER_SET_CVS_ID(Layer_SphereDistort,"$Id: sphere_distort.cpp,v 1.2 2005/01/24 05:00:18 darco Exp $"); - -/* === P R O C E D U R E S ================================================= */ - -/* === M E T H O D S ======================================================= */ - -/* === E N T R Y P O I N T ================================================= */ - -Layer_SphereDistort::Layer_SphereDistort() -:Layer_Composite(1.0,Color::BLEND_STRAIGHT), -center(0,0), -radius(1), -percent(1.0), -type(TYPE_NORMAL), -clip(false) -{ -} - - -bool -Layer_SphereDistort::set_param(const String & param, const ValueBase &value) -{ - IMPORT_PLUS(center,sync()); - IMPORT_PLUS(radius,sync()); - IMPORT(type); - IMPORT_AS(percent,"amount"); - IMPORT(clip); - - if(param=="percent") - { - if(dynamic_param_list().count("percent")) - { - connect_dynamic_param("amount",dynamic_param_list().find("percent")->second); - disconnect_dynamic_param("percent"); - synfig::warning("Layer_SphereDistort::::set_param(): Updated valuenode connection to use the new \"amount\" parameter."); - } - else - synfig::warning("Layer_SphereDistort::::set_param(): The parameter \"segment_list\" is deprecated. Use \"bline\" instead."); - } - - return false; -} - -ValueBase -Layer_SphereDistort::get_param(const String ¶m)const -{ - EXPORT(center); - EXPORT(radius); - EXPORT(type); - EXPORT_AS(percent,"amount"); - EXPORT(clip); - - EXPORT_NAME(); - EXPORT_VERSION(); - - return ValueBase(); -} - -void -Layer_SphereDistort::sync() -{ -} - -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) - ); - - 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")) - .set_hint("enum") - .add_enum_value(TYPE_NORMAL,"normal",_("Spherize")) - .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) - 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) -{ - if(f > -1 && f < 1 && f!=0) - return sinf(f*(PI/2)); - else return f; -} - -inline float unspherify(float f) -{ - if(f > -1 && f < 1 && f!=0) - return asin(f)/(PI/2); - else return f; -} - -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; - return newp; - }else - if(m==0) - return newp; - else - if(t > 0) - { - 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); - if(v[0] <= -1 || v[0] >= 1) - { - clipped=true; - return newp; - }else - if(v[0]==0) - return newp; - else - if(t > 0) - { - lerp = (t*unspherify(v[0]) + (1-t)*v[0]); - }else if(t < 0) - { - 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); - if(v[1] <= -1 || v[1] >= 1) - { - clipped=true; - return newp; - } - else - if(v[1]==0) - return newp; - else - if(t > 0) - { - lerp = (t*unspherify(v[1]) + (1-t)*v[1]); - }else if(t < 0) - { - 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, - const Real &percent, int type) -{ - bool tmp; - return sphtrans(p, center, radius, percent, type, tmp); -} - -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)); - if(clip && clipped) - return 0; - return context.hit_check(point); -} - -Color -Layer_SphereDistort::get_color(Context context, const Point &pos)const -{ - bool clipped; - Point point(sphtrans(pos,center,radius,percent,type,clipped)); - if(clip && clipped) - return Color::alpha(); - return context.get_color(point); -} - -#if 1 -bool Layer_SphereDistort::accelerated_render(Context context,Surface *surface,int quality, const RendDesc &renddesc, ProgressCallback *cb)const -{ - /* Things to consider: - 1) Block expansion for distortion (ouch... quality level??) - 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 - Rect windr; - - //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)) ) - { - //synfig::warning("Spherize: Bounding box reject"); - return context.accelerated_render(surface,quality,renddesc,cb); - } - - //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]); - - //synfig::warning("Spherize: Loop through lines and stuff"); - for(int i=0; i<4; ++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 - Point p = sphtrans(close,center,radius,percent,type); - expandr.expand(p[0],p[1]); - p = sphtrans(origin[i],center,radius,percent,type); - expandr.expand(p[0],p[1]); - p = sphtrans(origin[i]+v[i],center,radius,percent,type); - expandr.expand(p[0],p[1]); - } - - /*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...) - //order it so that it's in the same orientation as the tl,br pair - - //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; - } - - //sort y - if(tl[1] < br[1]) - { - ntl[1] = expandr.miny; - nbr[1] = expandr.maxy; - } - else - { - ntl[1] = expandr.maxy; - 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; - - //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;*/ - } - - //synfig::warning("Spherize: render background"); - if(!context.accelerated_render(&background,quality,r,cb)) - { - 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(); - - //synfig::warning("Spherize: About to transform"); - - for(y = 0; y < h; ++y, sample[1] += ph, p.inc_y()) - { - sub = sample; - for(x = 0; x < w; ++x, sub[0] += pw, p.inc_x()) - { - bool clipped; - trans=sphtrans(sub,center,radius,percent,type,clipped); - if(clip && clipped) - { - p.put_value(Color::alpha()); - continue; - } - - xs = (trans[0]-rtl[0])*invpw; - ys = (trans[1]-rtl[1])*invph; - - if(!(xs >= 0 && xs < nw && ys >= 0 && ys < nh)) - { - //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 - { - p.put_value(background.cubic_sample(xs,ys)); - }else if(quality <= 5) //cosine - { - p.put_value(background.cosine_sample(xs,ys)); - }else if(quality <= 6) //linear - { - p.put_value(background.linear_sample(xs,ys)); - }else //nearest - { - p.put_value(background[round_to_int(ys)][round_to_int(xs)]); - } - } - p.dec_x(w); - } - - return true; -} -#endif - -class synfig::Spherize_Trans : public synfig::Transform -{ - etl::handle layer; -public: - Spherize_Trans(const Layer_SphereDistort* x):Transform(x->get_guid()),layer(x) { } - - synfig::Vector perform(const synfig::Vector& x)const - { - return sphtrans(x,layer->center,layer->radius,-layer->percent,layer->type); - } - - synfig::Vector unperform(const synfig::Vector& x)const - { - return sphtrans(x,layer->center,layer->radius,layer->percent,layer->type); - } -}; - -etl::handle -Layer_SphereDistort::get_transform()const -{ - return new Spherize_Trans(this); -} - -Rect -Layer_SphereDistort::get_bounding_rect()const -{ - Rect bounds(Rect::full_plane()); - switch(type) - { - case TYPE_NORMAL: - bounds=Rect( - center[0]+(radius), - center[1]+(radius), - center[0]-(radius), - center[1]-(radius) - ); - break; - case TYPE_DISTH: - break; - case TYPE_DISTV: - break; - default: - break; - } - - return bounds; -} -