コード例 #1
0
ValueBase
ValueNode_WPList::operator()(Time t)const
{
	if (getenv("SYNFIG_DEBUG_VALUENODE_OPERATORS"))
		printf("%s:%d operator()\n", __FILE__, __LINE__);

	std::vector<WidthPoint> ret_list;

	std::vector<ListEntry>::const_iterator iter;
	bool rising;

	WidthPoint curr;

	// go through all the list's entries
	for(iter=list.begin();iter!=list.end();++iter)
	{
		// how 'on' is this widthpoint?
		float amount(iter->amount_at_time(t,&rising));
		assert(amount>=0.0f);
		assert(amount<=1.0f);
		// we store the current width point
		curr=(*iter->value_node)(t).get(curr);
		// it's fully on
		if (amount > 1.0f - 0.0000001f)
		{
			// push back to the returning list
			ret_list.push_back(curr);
		}
		// it's partly on
		else if(amount>0.0f)
		{
			// This is where the interesting stuff happens
			Time off_time, on_time;
			if(!rising)	// if not rising, then we were fully 'on' in the past, and will be fully 'off' in the future
			{
				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 // otherwise we were fully 'off' in the past, and will be fully 'on' in the future
			{
				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(); }
			}
			// i_width is the interpolated width at current time given by fully 'on' surrounding width points
			Real i_width(interpolated_width(curr.get_norm_position(get_loop()), t));
			Real curr_width(curr.get_width());
			// linear interpolation by amount
			curr.set_width(i_width*(1.0-amount)+(curr_width)*amount);
			// now insert the calculated width point into the widht list
			ret_list.push_back(curr);
		}
	}
	if(list.empty())
		synfig::warning(string("ValueNode_WPList::operator()():")+_("No entries in list"));
	else
	if(ret_list.empty())
		synfig::warning(string("ValueNode_WPList::operator()():")+_("No entries in ret_list"));

	return ValueBase(ret_list,get_loop());
}
コード例 #2
0
	/*!
	 * @param prev previous withpoint
	 * @param next next withpoint
	 * @param p position to calculate the new width between previous position and next position
	 * @param smoothness [0,1] how much linear (0) or smooth (1) the interpolation is
	 * @return the interpolated width
	*/
Real
synfig::widthpoint_interpolate(const WidthPoint& prev, const WidthPoint& next, const Real p, const Real smoothness)
{
	// Smoothness gives linear interpolation  between
	// the result of the linear interpolation between the withpoints
	// and the interpolation based on a 5th degree polynomial that matches
	// following rules:
	// q [0,1]
	// p(0)= 0    p(1)= 1
	// p'(0)= 0   p'(1)= 0
	// p''(0)= 0  p''(1)= 0
	// It is: p(q) = 6*q^5-15*q^4+10*q^3 = q*q*q*(10+q*(6*q-15)
	WidthPoint::SideType side_int(WidthPoint::TYPE_INTERPOLATE);
	int nsb, nsa, psb, psa;
	Real pp, np;
	Real nw, pw, rw(0.0);
	const Real epsilon(0.0000001f);
	np=next.get_position();
	pp=prev.get_position();
	nw=next.get_width();
	pw=prev.get_width();
	nsb=next.get_side_type_before();
	nsa=next.get_side_type_after();
	psb=prev.get_side_type_before();
	psa=prev.get_side_type_after();

	if(p==np)
		return nw;
	if(p==pp)
		return pw;
	// Normal case: previous position is lower than next position
	if(np > pp)
	{
		if(np > p && p > pp )
		{
			Real q;
			if(nsb != side_int)
				nw=0.0;
			if(psa != side_int)
				pw=0.0;
			if(np-pp < epsilon)
				q=0.5;
			else
				q=(p-pp)/(np-pp);
			rw=pw+(nw-pw)*(q*(1.0-smoothness)+q*q*q*(10+q*(6*q-15))*smoothness);
		}
		else if(p < pp)
		{
			if(psb != side_int)
				pw=0.0;
			rw=pw;
		}
		else if(p > np)
		{
			if(nsa != side_int)
				nw=0.0;
			rw=nw;
		}
	}
	// particular case: previous position is higher than next position
	else
	if(p > pp || np > p)
	{
		Real q(0);
		if(nsb != side_int)
			nw=0.0;
		if(psa != side_int)
			pw=0.0;
		if(np+1.0-pp < epsilon)
			q=0.5;
		else
		{
			if(p > pp)
				q=(p-pp)/(np+1.0-pp);
			if(np > p)
				q=(p+1.0-pp)/(np+1.0-pp);
		}
		rw=pw+(nw-pw)*(q*(1.0-smoothness)+q*q*q*(10+q*(6*q-15))*smoothness);
	}
	else
	if(p > np && p < pp)
	{
		Real q;
		if(nsa != side_int)
			nw=0.0;
		if(psb != side_int)
			pw=0.0;
		if(pp-np < epsilon)
			q=0.5;
		else
			q=(p-np)/(pp-np);
		rw=nw+(pw-nw)*(q*(1.0-smoothness)+q*q*q*(10+q*(6*q-15))*smoothness);
	}
	return rw;
}