X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=synfig-core%2Ftrunk%2Fsrc%2Fsynfig%2Fvaluenode_bline.cpp;h=b0b7de1dacaf95d454b192df27fe82af6cd68c36;hb=3980247b910d8d75f85a1f444e03f5973a0e21ea;hp=0852ed4397e6519ae1405ee6c592fd397df46d1a;hpb=e8a065f2385c219c511b57dac52786120bfa097d;p=synfig.git diff --git a/synfig-core/trunk/src/synfig/valuenode_bline.cpp b/synfig-core/trunk/src/synfig/valuenode_bline.cpp index 0852ed4..b0b7de1 100644 --- a/synfig-core/trunk/src/synfig/valuenode_bline.cpp +++ b/synfig-core/trunk/src/synfig/valuenode_bline.cpp @@ -2,7 +2,7 @@ /*! \file valuenode_bline.cpp ** \brief Template File ** -** $Id: valuenode_bline.cpp,v 1.1.1.1 2005/01/04 01:23:15 darco Exp $ +** $Id$ ** ** \legal ** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley @@ -63,12 +63,16 @@ linear_interpolation(const Vector& a, const Vector& b, float c) inline Vector radial_interpolation(const Vector& a, const Vector& b, float c) { + // if either extreme is zero then use linear interpolation instead + if (a.is_equal_to(Vector::zero()) || b.is_equal_to(Vector::zero())) + return linear_interpolation(a, b, c); + affine_combo mag_combo; affine_combo ang_combo; - + Real mag(mag_combo(a.mag(),b.mag(),c)); Angle ang(ang_combo(Angle::tan(a[1],a[0]),Angle::tan(b[1],b[0]),c)); - + return Point( mag*Angle::cos(ang).get(),mag*Angle::sin(ang).get() ); } @@ -78,19 +82,19 @@ ValueBase synfig::convert_bline_to_segment_list(const ValueBase& bline) { std::vector ret; - + // std::vector list(bline.operator std::vector()); //std::vector list(bline); std::vector list(bline.get_list().begin(),bline.get_list().end()); std::vector::const_iterator iter; BLinePoint prev,first; - + //start with prev = first and iter on the second... - + if(list.empty()) return ValueBase(ret,bline.get_loop()); first = prev = list.front(); - + for(iter=++list.begin();iter!=list.end();++iter) { ret.push_back( @@ -102,7 +106,7 @@ synfig::convert_bline_to_segment_list(const ValueBase& bline) ) ); prev=*iter; - } + } if(bline.get_loop()) { ret.push_back( @@ -125,10 +129,10 @@ synfig::convert_bline_to_width_list(const ValueBase& bline) //std::vector list(bline); std::vector list(bline.get_list().begin(),bline.get_list().end()); std::vector::const_iterator iter; - + if(bline.empty()) return ValueBase(ValueBase::TYPE_LIST); - + for(iter=list.begin();iter!=list.end();++iter) ret.push_back(iter->get_width()); @@ -156,7 +160,7 @@ ValueNode_BLine::create(const ValueBase &value) { if(value.get_type()!=ValueBase::TYPE_LIST) return 0; - + ValueNode_BLine* value_node(new ValueNode_BLine()); if(!value.empty()) @@ -171,7 +175,7 @@ ValueNode_BLine::create(const ValueBase &value) std::vector::const_iterator iter; for(iter=bline_points.begin();iter!=bline_points.end();iter++) - { + { value_node->add(ValueNode::Handle(ValueNode_Composite::create(*iter))); } value_node->set_loop(value.get_loop()); @@ -183,7 +187,7 @@ ValueNode_BLine::create(const ValueBase &value) // into a list of BLinePoints. We make an assumption // that the segment list is continuous(sp), but not necessarily // smooth. - + value_node->set_loop(false); // std::vector segments(value.operator std::vector()); // std::vector segments(value); @@ -191,9 +195,9 @@ ValueNode_BLine::create(const ValueBase &value) std::vector::const_iterator iter,last(segments.end()); --last; ValueNode_Const::Handle prev,first; - + for(iter=segments.begin();iter!=segments.end();iter++) - { + { #define PREV_POINT prev->get_value().get(BLinePoint()) #define FIRST_POINT first->get_value().get(BLinePoint()) #define CURR_POINT curr->get_value().get(BLinePoint()) @@ -202,7 +206,7 @@ ValueNode_BLine::create(const ValueBase &value) prev=ValueNode_Const::create(ValueBase::TYPE_BLINEPOINT); { BLinePoint prev_point(PREV_POINT); - prev_point.set_vertex(iter->p1); + prev_point.set_vertex(iter->p1); prev_point.set_tangent1(iter->t1); prev_point.set_width(0.01); prev_point.set_origin(0.5); @@ -211,7 +215,7 @@ ValueNode_BLine::create(const ValueBase &value) } first=prev; value_node->add(ValueNode::Handle(prev)); - + } if(iter==last && iter->p2.is_equal_to(FIRST_POINT.get_vertex())) { @@ -224,12 +228,12 @@ ValueNode_BLine::create(const ValueBase &value) } continue; } - + ValueNode_Const::Handle curr; curr=ValueNode_Const::create(ValueBase::TYPE_BLINEPOINT); { BLinePoint curr_point(CURR_POINT); - curr_point.set_vertex(iter->p2); + curr_point.set_vertex(iter->p2); curr_point.set_tangent1(iter->t2); curr_point.set_width(0.01); curr_point.set_origin(0.5); @@ -246,7 +250,7 @@ ValueNode_BLine::create(const ValueBase &value) value_node->add(ValueNode::Handle(curr)); prev=curr; } - + } break; default: @@ -256,8 +260,8 @@ ValueNode_BLine::create(const ValueBase &value) break; } } - - + + return value_node; } @@ -266,7 +270,7 @@ ValueNode_BLine::create_list_entry(int index, Time time, Real origin) { ValueNode_BLine::ListEntry ret; - + synfig::BLinePoint prev,next; int prev_i,next_i; @@ -282,12 +286,12 @@ ValueNode_BLine::create_list_entry(int index, Time time, Real origin) else next_i=index; prev_i=find_prev_valid_entry(index,time); - + synfig::info("index=%d, next_i=%d, prev_i=%d",index,next_i,prev_i); - + next=(*list[next_i].value_node)(time); prev=(*list[prev_i].value_node)(time); - + etl::hermite curve(prev.get_vertex(),next.get_vertex(),prev.get_tangent2(),next.get_tangent1()); etl::derivative< etl::hermite > deriv(curve); @@ -298,9 +302,9 @@ ValueNode_BLine::create_list_entry(int index, Time time, Real origin) bline_point.set_tangent2(bline_point.get_tangent1()); bline_point.set_split_tangent_flag(false); bline_point.set_origin(origin); - + ret.value_node=ValueNode_Composite::create(bline_point); - + return ret; } @@ -308,23 +312,23 @@ ValueBase ValueNode_BLine::operator()(Time t)const { std::vector ret_list; - + std::vector::const_iterator iter,first_iter; bool first_flag(true); bool rising; int index(0); float next_scale(1.0f); - + BLinePoint prev,first; first.set_origin(100.0f); - + for(iter=list.begin();iter!=list.end();++iter,index++) { float amount(iter->amount_at_time(t,&rising)); - + assert(amount>=0.0f); assert(amount<=1.0f); - + if(amount==1.0f) { if(first_flag) @@ -335,10 +339,10 @@ ValueNode_BLine::operator()(Time t)const ret_list.push_back(first); continue; } - + BLinePoint curr; curr=(*iter->value_node)(t).get(prev); - + if(next_scale!=1.0f) { ret_list.back().set_split_tangent_flag(true); @@ -355,73 +359,69 @@ ValueNode_BLine::operator()(Time t)const else { ret_list.push_back(curr); - } - + prev=curr; } else if(amount>0.0f) { std::vector::const_iterator begin_iter,end_iter; - + // This is where the interesting stuff happens // We need to seek forward in the list to see what the next // active point is - + BLinePoint curr; BLinePoint begin; // begin of dynamic group - BLinePoint end; // End of dynamic group - Time blend_time; + BLinePoint end; // end of dynamic group int dist_from_begin(0), dist_from_end(0); BLinePoint ret; - - Time begin_time; - Time end_time; - + + Time off_time, on_time; + if(!rising) { - try{ end_time=iter->find_prev(t)->get_time(); } - catch(...) { end_time=Time::begin(); } - try{ begin_time=iter->find_next(t)->get_time(); } - catch(...) { begin_time=Time::end(); } + try{ on_time=iter->find_prev(t)->get_time(); } + catch(...) { on_time=Time::begin(); } + try{ off_time=iter->find_next(t)->get_time(); } + catch(...) { off_time=Time::end(); } } else { - try{ begin_time=iter->find_prev(t)->get_time(); } - catch(...) { begin_time=Time::begin(); } - try{ end_time=iter->find_next(t)->get_time(); } - catch(...) { end_time=Time::end(); } + try{ off_time=iter->find_prev(t)->get_time(); } + catch(...) { off_time=Time::begin(); } + try{ on_time=iter->find_next(t)->get_time(); } + catch(...) { on_time=Time::end(); } } - blend_time=begin_time; - curr=(*iter->value_node)(end_time).get(curr); + curr=(*iter->value_node)(on_time).get(curr); // curr=(*iter->value_node)(t).get(curr); - + // Find "end" of dynamic group end_iter=iter; // for(++end_iter;begin_iter!=list.end();++end_iter) for(++end_iter;end_iter!=list.end();++end_iter) if(end_iter->amount_at_time(t)>amount) { - end=(*end_iter->value_node)(blend_time).get(prev); + end=(*end_iter->value_node)(off_time).get(prev); break; } - + // If we did not find an end of the dynamic group... if(end_iter==list.end()) { if(get_loop()) { end_iter=first_iter; - end=(*end_iter->value_node)(blend_time).get(prev); + end=(*end_iter->value_node)(off_time).get(prev); // end=first; } else { // Writeme! end_iter=first_iter; - end=(*end_iter->value_node)(blend_time).get(prev); + end=(*end_iter->value_node)(off_time).get(prev); // end=first; } } @@ -438,54 +438,54 @@ ValueNode_BLine::operator()(Time t)const else break; } - + --begin_iter; dist_from_begin++; - + if(begin_iter==iter) break; if(begin_iter->amount_at_time(t)>amount) { - begin=(*begin_iter->value_node)(blend_time).get(prev); + begin=(*begin_iter->value_node)(off_time).get(prev); break; } }while(begin_iter!=iter); - + // If we did not find a begin if(begin.get_origin()==100.0f) { if(get_loop()) { begin_iter=first_iter; - begin=(*begin_iter->value_node)(blend_time).get(prev); + begin=(*begin_iter->value_node)(off_time).get(prev); // begin=first; } else { // Writeme! begin_iter=first_iter; - begin=(*begin_iter->value_node)(blend_time).get(prev); + begin=(*begin_iter->value_node)(off_time).get(prev); // begin=first; } } - + etl::hermite curve(begin.get_vertex(),end.get_vertex(),begin.get_tangent2(),end.get_tangent1()); etl::derivative< etl::hermite > deriv(curve); - + ret.set_vertex(curve(curr.get_origin())); ret.set_width((end.get_width()-begin.get_width())*curr.get_origin()+begin.get_width()); ret.set_tangent1(deriv(curr.get_origin())); ret.set_tangent2(deriv(curr.get_origin())); - + float prev_tangent_scalar(1.0f); float next_tangent_scalar(1.0f); - + //synfig::info("index_%d:dist_from_begin=%d",index,dist_from_begin); //synfig::info("index_%d:dist_from_end=%d",index,dist_from_end); - + // If we are the next to the begin if(begin_iter==--std::vector::const_iterator(iter) || dist_from_begin==1) { @@ -494,7 +494,7 @@ ValueNode_BLine::operator()(Time t)const else { float origin=curr.get_origin()-prev.get_origin(); - prev_tangent_scalar=(1.0f-origin)*amount+origin; + prev_tangent_scalar=(1.0f-origin)*amount+origin; } // If we are the next to the end @@ -509,24 +509,31 @@ ValueNode_BLine::operator()(Time t)const BLinePoint next; next=((*(++std::vector::const_iterator(iter))->value_node)(t).get(prev)); float origin=next.get_origin()-curr.get_origin(); - next_tangent_scalar=(1.0f-origin)*amount+origin; + next_tangent_scalar=(1.0f-origin)*amount+origin; + } + else + { + //! \todo this isn't quite right; we should handle looped blines identically no matter where the loop happens + //! and we currently don't. this at least makes it a lot better than it was before + float origin=end.get_origin()-curr.get_origin(); + next_tangent_scalar=(1.0f-origin)*amount+origin; } next_scale=next_tangent_scalar; - + //ret.set_vertex((curr.get_vertex()-ret.get_vertex())*amount+ret.get_vertex()); if(false) { // My first try Point ref_point_begin( ( - (*begin_iter->value_node)(begin_time).get(prev).get_vertex() + - (*end_iter->value_node)(begin_time).get(prev).get_vertex() + (*begin_iter->value_node)(off_time).get(prev).get_vertex() + + (*end_iter->value_node)(off_time).get(prev).get_vertex() ) * 0.5 ); Point ref_point_end( ( - (*begin_iter->value_node)(end_time).get(prev).get_vertex() + - (*end_iter->value_node)(end_time).get(prev).get_vertex() + (*begin_iter->value_node)(on_time).get(prev).get_vertex() + + (*end_iter->value_node)(on_time).get(prev).get_vertex() ) * 0.5 ); Point ref_point_now( @@ -549,143 +556,133 @@ ValueNode_BLine::operator()(Time t)const else { // My second try - Point begin_cord_sys[2], begin_cord_origin; - Point end_cord_sys[2], end_cord_origin; - Point curr_cord_sys[2], curr_cord_origin; - - { - const Point a((*end_iter->value_node)(begin_time).get(prev).get_vertex()); - const Point b((*begin_iter->value_node)(begin_time).get(prev).get_vertex()); - begin_cord_origin=(a+b)/2; - begin_cord_sys[0]=( b - a ).norm(); - begin_cord_sys[1]=begin_cord_sys[0].perp(); - } - { - const Point a((*end_iter->value_node)(end_time).get(prev).get_vertex()); - const Point b((*begin_iter->value_node)(end_time).get(prev).get_vertex()); - end_cord_origin=(a+b)/2; - end_cord_sys[0]=( b - a ).norm(); - end_cord_sys[1]=end_cord_sys[0].perp(); - } + + // define 3 coordinate systems: + Point off_coord_sys[2], off_coord_origin; // when the current vertex is completely off + Point on_coord_sys[2] , on_coord_origin; // when the current vertex is completely on + Point curr_coord_sys[2], curr_coord_origin; // the current state - somewhere in between + + // for each of the 3 systems, the origin is half way between the previous and next active point + // and the axes are based on a vector from the next active point to the previous { - const Point a((*end_iter->value_node)(t).get(prev).get_vertex()); - const Point b((*begin_iter->value_node)(t).get(prev).get_vertex()); - curr_cord_origin=(a+b)/2; - curr_cord_sys[0]=( b - a ).norm(); - curr_cord_sys[1]=curr_cord_sys[0].perp(); + const Point end_pos_at_off_time(( *end_iter->value_node)(off_time).get(prev).get_vertex()); + const Point begin_pos_at_off_time((*begin_iter->value_node)(off_time).get(prev).get_vertex()); + off_coord_origin=(begin_pos_at_off_time + end_pos_at_off_time)/2; + off_coord_sys[0]=(begin_pos_at_off_time - end_pos_at_off_time).norm(); + off_coord_sys[1]=off_coord_sys[0].perp(); + + const Point end_pos_at_on_time(( *end_iter->value_node)(on_time).get(prev).get_vertex()); + const Point begin_pos_at_on_time((*begin_iter->value_node)(on_time).get(prev).get_vertex()); + on_coord_origin=(begin_pos_at_on_time + end_pos_at_on_time)/2; + on_coord_sys[0]=(begin_pos_at_on_time - end_pos_at_on_time).norm(); + on_coord_sys[1]=on_coord_sys[0].perp(); + + const Point end_pos_at_current_time(( *end_iter->value_node)(t).get(prev).get_vertex()); + const Point begin_pos_at_current_time((*begin_iter->value_node)(t).get(prev).get_vertex()); + curr_coord_origin=(begin_pos_at_current_time + end_pos_at_current_time)/2; + curr_coord_sys[0]=(begin_pos_at_current_time - end_pos_at_current_time).norm(); + curr_coord_sys[1]=curr_coord_sys[0].perp(); } - - /* - end_cord_origin=(*end_iter->value_node)(end_time).get(prev).get_vertex(); - end_cord_sys[0]=( - (*begin_iter->value_node)(end_time).get(prev).get_vertex() - - end_cord_origin - ).norm(); - end_cord_sys[1]=end_cord_sys[0].perp(); - - curr_cord_origin=(*end_iter->value_node)(t).get(prev).get_vertex(); - curr_cord_sys[0]=( - (*begin_iter->value_node)(t).get(prev).get_vertex() - - curr_cord_origin - ).norm(); - curr_cord_sys[1]=curr_cord_sys[0].perp(); - */ - - // Convert start point - Point a; - Vector at1,at2; + + /* The code that was here before used just end_iter as the origin, rather than the mid-point */ + + // For each of the 3 coordinate systems we've just defined, we convert a point and tangent(s) into that system + + // Convert point where vertex is fully 'off' + Point trans_off_point; + Vector trans_off_t1,trans_off_t2; { - Point tmp(ret.get_vertex()-begin_cord_origin); - a[0]=tmp*begin_cord_sys[0]; - a[1]=tmp*begin_cord_sys[1]; + Point tmp(ret.get_vertex()-off_coord_origin); + trans_off_point[0]=tmp*off_coord_sys[0]; + trans_off_point[1]=tmp*off_coord_sys[1]; #define COORD_SYS_RADIAL_TAN_INTERP 1 - + #ifdef COORD_SYS_RADIAL_TAN_INTERP - tmp=ret.get_tangent1()+ret.get_vertex()-begin_cord_origin; - at1[0]=tmp*begin_cord_sys[0]; - at1[1]=tmp*begin_cord_sys[1]; - + tmp=ret.get_tangent1()+ret.get_vertex()-off_coord_origin; + trans_off_t1[0]=tmp*off_coord_sys[0]; + trans_off_t1[1]=tmp*off_coord_sys[1]; + if(curr.get_split_tangent_flag()) { - tmp=ret.get_tangent2()+ret.get_vertex()-begin_cord_origin; - at2[0]=tmp*begin_cord_sys[0]; - at2[1]=tmp*begin_cord_sys[1]; + tmp=ret.get_tangent2()+ret.get_vertex()-off_coord_origin; + trans_off_t2[0]=tmp*off_coord_sys[0]; + trans_off_t2[1]=tmp*off_coord_sys[1]; } #endif } - - // Convert finish point - Point b; - Vector bt1,bt2; + + // Convert point where vertex is fully 'on' + Point trans_on_point; + Vector trans_on_t1,trans_on_t2; { - Point tmp(curr.get_vertex()-end_cord_origin); - b[0]=tmp*end_cord_sys[0]; - b[1]=tmp*end_cord_sys[1]; - + Point tmp(curr.get_vertex()-on_coord_origin); + trans_on_point[0]=tmp*on_coord_sys[0]; + trans_on_point[1]=tmp*on_coord_sys[1]; + #ifdef COORD_SYS_RADIAL_TAN_INTERP - tmp=curr.get_tangent1()+curr.get_vertex()-end_cord_origin; - bt1[0]=tmp*end_cord_sys[0]; - bt1[1]=tmp*end_cord_sys[1]; + tmp=curr.get_tangent1()+curr.get_vertex()-on_coord_origin; + trans_on_t1[0]=tmp*on_coord_sys[0]; + trans_on_t1[1]=tmp*on_coord_sys[1]; if(curr.get_split_tangent_flag()) { - tmp=curr.get_tangent2()+curr.get_vertex()-end_cord_origin; - bt2[0]=tmp*end_cord_sys[0]; - bt2[1]=tmp*end_cord_sys[1]; + tmp=curr.get_tangent2()+curr.get_vertex()-on_coord_origin; + trans_on_t2[0]=tmp*on_coord_sys[0]; + trans_on_t2[1]=tmp*on_coord_sys[1]; } #endif } - + // Convert current point - Point c; - Vector ct1,ct2; + Point trans_curr_point; + Vector trans_curr_t1,trans_curr_t2; { // Transpose (invert) - swap(curr_cord_sys[0][1],curr_cord_sys[1][0]); + swap(curr_coord_sys[0][1],curr_coord_sys[1][0]); - Point tmp((b-a)*amount+a); - c[0]=tmp*curr_cord_sys[0]; - c[1]=tmp*curr_cord_sys[1]; - c+=curr_cord_origin; + Point tmp((trans_on_point-trans_off_point)*amount+trans_off_point); + trans_curr_point[0]=tmp*curr_coord_sys[0]; + trans_curr_point[1]=tmp*curr_coord_sys[1]; + trans_curr_point+=curr_coord_origin; #define INTERP_FUNCTION radial_interpolation //#define INTERP_FUNCTION linear_interpolation - + #ifdef COORD_SYS_RADIAL_TAN_INTERP - tmp=INTERP_FUNCTION(at1,bt1,amount); - ct1[0]=tmp*curr_cord_sys[0]; - ct1[1]=tmp*curr_cord_sys[1]; - ct1+=curr_cord_origin; - ct1-=c; - + tmp=INTERP_FUNCTION(trans_off_t1,trans_on_t1,amount); + trans_curr_t1[0]=tmp*curr_coord_sys[0]; + trans_curr_t1[1]=tmp*curr_coord_sys[1]; + trans_curr_t1+=curr_coord_origin; + trans_curr_t1-=trans_curr_point; + if(curr.get_split_tangent_flag()) { - tmp=INTERP_FUNCTION(at2,bt2,amount); - ct2[0]=tmp*curr_cord_sys[0]; - ct2[1]=tmp*curr_cord_sys[1]; - ct2+=curr_cord_origin; - ct2-=c; + tmp=INTERP_FUNCTION(trans_off_t2,trans_on_t2,amount); + trans_curr_t2[0]=tmp*curr_coord_sys[0]; + trans_curr_t2[1]=tmp*curr_coord_sys[1]; + trans_curr_t2+=curr_coord_origin; + trans_curr_t2-=trans_curr_point; } #endif } - ret.set_vertex(c); + ret.set_vertex(trans_curr_point); #ifndef COORD_SYS_RADIAL_TAN_INTERP ret.set_tangent1(radial_interpolation(ret.get_tangent1(),curr.get_tangent1(),amount)); ret.set_split_tangent_flag(curr.get_split_tangent_flag()); if(ret.get_split_tangent_flag()) ret.set_tangent2(radial_interpolation(ret.get_tangent2(),curr.get_tangent2(),amount)); -#else - ret.set_tangent1(ct1); +#else + ret.set_tangent1(trans_curr_t1); ret.set_split_tangent_flag(curr.get_split_tangent_flag()); if(ret.get_split_tangent_flag()) - ret.set_tangent2(ct2); + ret.set_tangent2(trans_curr_t2); #endif } - + ret.set_origin(curr.get_origin()); ret.set_width((curr.get_width()-ret.get_width())*amount+ret.get_width()); - + // Handle the case where we are the first vertex if(first_flag) @@ -708,7 +705,7 @@ ValueNode_BLine::operator()(Time t)const prev=ret; } } - + if(next_scale!=1.0f) { ret_list.back().set_split_tangent_flag(true); @@ -728,7 +725,7 @@ ValueNode_BLine::operator()(Time t)const ); } */ - + if(list.empty()) synfig::warning(string("ValueNode_BLine::operator()():")+_("No entries in list")); else @@ -743,7 +740,7 @@ ValueNode_BLine::link_local_name(int i)const { assert(i>=0 && (unsigned)iset_guid(get_guid()^deriv_guid); - + std::vector::const_iterator iter; for(iter=list.begin();iter!=list.end();++iter) @@ -770,7 +767,7 @@ ValueNode_BLine::clone(const GUID& deriv_guid)const } } ret->set_loop(get_loop()); - + return ret; }