Ejemplo n.º 1
0
void Curve2D::_bake_segment2d(
	std::map<float, Vector2>& r_bake, float p_begin,
	float p_end,
	const Vector2& p_a,
	const Vector2& p_out,
	const Vector2& p_b,
	const Vector2& p_in,
	int p_depth,
	int p_max_depth,
	float p_tol
) const {

	float mp = p_begin + (p_end - p_begin) * 0.5;
	Vector2 beg = _bezier_interp(p_begin, p_a, p_a + p_out, p_b + p_in, p_b);
	Vector2 mid = _bezier_interp(mp, p_a, p_a + p_out, p_b + p_in, p_b);
	Vector2 end = _bezier_interp(p_end, p_a, p_a + p_out, p_b + p_in, p_b);

	Vector2 na =(mid - beg).normalized();
	Vector2 nb =(end - mid).normalized();
	float dp = na.dot(nb);

	if(dp < cos(deg2rad(p_tol))) {
		r_bake[mp]=mid;
	}

	if(p_depth<p_max_depth) {
		_bake_segment2d(r_bake, p_begin, mp, p_a, p_out, p_b, p_in, p_depth + 1, p_max_depth, p_tol);
		_bake_segment2d(r_bake, mp, p_end, p_a, p_out, p_b, p_in, p_depth + 1, p_max_depth, p_tol);
	}
}
Ejemplo n.º 2
0
void Curve3D::_bake_segment3d(Map<float,Vector3>& r_bake, float p_begin, float p_end,const Vector3& p_a,const Vector3& p_out,const Vector3& p_b, const Vector3& p_in,int p_depth,int p_max_depth,float p_tol) const {

	float mp = p_begin+(p_end-p_begin)*0.5;
	Vector3 beg = _bezier_interp(p_begin,p_a,p_a+p_out,p_b+p_in,p_b);
	Vector3 mid = _bezier_interp(mp,p_a,p_a+p_out,p_b+p_in,p_b);
	Vector3 end = _bezier_interp(p_end,p_a,p_a+p_out,p_b+p_in,p_b);

	Vector3 na = (mid-beg).normalized();
	Vector3 nb = (end-mid).normalized();
	float dp = na.dot(nb);

	if (dp<Math::cos(Math::deg2rad(p_tol))) {

		r_bake[mp]=mid;
	}
	if (p_depth<p_max_depth) {
		_bake_segment3d(r_bake,p_begin,mp,p_a,p_out,p_b,p_in,p_depth+1,p_max_depth,p_tol);
		_bake_segment3d(r_bake,mp,p_end,p_a,p_out,p_b,p_in,p_depth+1,p_max_depth,p_tol);
	}
}
Ejemplo n.º 3
0
void GraphEdit::_bake_segment2d(CanvasItem *p_where, float p_begin, float p_end, const Vector2 &p_a, const Vector2 &p_out, const Vector2 &p_b, const Vector2 &p_in, int p_depth, int p_min_depth, int p_max_depth, float p_tol, const Color &p_color, const Color &p_to_color, int &lines) const {

	float mp = p_begin + (p_end - p_begin) * 0.5;
	Vector2 beg = _bezier_interp(p_begin, p_a, p_a + p_out, p_b + p_in, p_b);
	Vector2 mid = _bezier_interp(mp, p_a, p_a + p_out, p_b + p_in, p_b);
	Vector2 end = _bezier_interp(p_end, p_a, p_a + p_out, p_b + p_in, p_b);

	Vector2 na = (mid - beg).normalized();
	Vector2 nb = (end - mid).normalized();
	float dp = Math::rad2deg(Math::acos(na.dot(nb)));

	if (p_depth >= p_min_depth && (dp < p_tol || p_depth >= p_max_depth)) {

		p_where->draw_line(beg, end, p_color.linear_interpolate(p_to_color, mp), 2, true);
		lines++;
	} else {
		_bake_segment2d(p_where, p_begin, mp, p_a, p_out, p_b, p_in, p_depth + 1, p_min_depth, p_max_depth, p_tol, p_color, p_to_color, lines);
		_bake_segment2d(p_where, mp, p_end, p_a, p_out, p_b, p_in, p_depth + 1, p_min_depth, p_max_depth, p_tol, p_color, p_to_color, lines);
	}
}
Ejemplo n.º 4
0
void GraphEdit::_bake_segment2d(Vector<Vector2> &points, Vector<Color> &colors, float p_begin, float p_end, const Vector2 &p_a, const Vector2 &p_out, const Vector2 &p_b, const Vector2 &p_in, int p_depth, int p_min_depth, int p_max_depth, float p_tol, const Color &p_color, const Color &p_to_color, int &lines) const {

	float mp = p_begin + (p_end - p_begin) * 0.5;
	Vector2 beg = _bezier_interp(p_begin, p_a, p_a + p_out, p_b + p_in, p_b);
	Vector2 mid = _bezier_interp(mp, p_a, p_a + p_out, p_b + p_in, p_b);
	Vector2 end = _bezier_interp(p_end, p_a, p_a + p_out, p_b + p_in, p_b);

	Vector2 na = (mid - beg).normalized();
	Vector2 nb = (end - mid).normalized();
	float dp = Math::rad2deg(Math::acos(na.dot(nb)));

	if (p_depth >= p_min_depth && (dp < p_tol || p_depth >= p_max_depth)) {

		points.push_back((beg + end) * 0.5);
		colors.push_back(p_color.linear_interpolate(p_to_color, mp));
		lines++;
	} else {
		_bake_segment2d(points, colors, p_begin, mp, p_a, p_out, p_b, p_in, p_depth + 1, p_min_depth, p_max_depth, p_tol, p_color, p_to_color, lines);
		_bake_segment2d(points, colors, mp, p_end, p_a, p_out, p_b, p_in, p_depth + 1, p_min_depth, p_max_depth, p_tol, p_color, p_to_color, lines);
	}
}
Ejemplo n.º 5
0
Vector3 Curve3D::interpolate(int p_index, float p_offset) const {

	int pc = points.size();
	ERR_FAIL_COND_V(pc==0,Vector3());

	if (p_index >= pc-1)
		return points[pc-1].pos;
	else if (p_index<0)
		return points[0].pos;

	Vector3 p0 = points[p_index].pos;
	Vector3 p1 = p0+points[p_index].out;
	Vector3 p3 = points[p_index+1].pos;
	Vector3 p2 = p3+points[p_index+1].in;

	return _bezier_interp(p_offset,p0,p1,p2,p3);
}
Ejemplo n.º 6
0
Vector2 Curve2D::interpolate(int p_index, float p_offset) const {

	int pc = points.size();
	if(pc == 0)
		return Vector2();

	if(p_index >= pc-1)
		return points[pc-1].pos;
	else if(p_index<0)
		return points[0].pos;

	Vector2 p0 = points[p_index].pos;
	Vector2 p1 = p0 + points[p_index].out;
	Vector2 p3 = points[p_index+1].pos;
	Vector2 p2 = p3 + points[p_index+1].in;

	return _bezier_interp(p_offset, p0, p1, p2, p3);
}
Ejemplo n.º 7
0
DVector<Point2> Curve2D::bake(int p_subdivs) const {

	int pc = points.size();

	DVector<Point2> ret;
	if (pc<2)
		return ret;

	ret.resize((pc-1)*p_subdivs+1);

	DVector<Point2>::Write w = ret.write();
	const Point *r = points.ptr();

	for(int i=0;i<pc;i++) {

		int ofs = pc*p_subdivs;

		int limit=(i==pc-1)?p_subdivs+1:p_subdivs;

		for(int j=0;j<limit;j++) {

			Vector2 p0 = r[i].pos;
			Vector2 p1 = p0+r[i].out;
			Vector2 p3 = r[i].pos;
			Vector2 p2 = p3+r[i].in;
			real_t t = j/(real_t)p_subdivs;

			w[ofs+j]=_bezier_interp(t,p0,p1,p2,p3);

		}
	}

	w = DVector<Point2>::Write();

	return ret;
}
Ejemplo n.º 8
0
void Curve2D::_bake() const {

	if(!baked_cache_dirty)
		return;

	baked_max_ofs = 0;
	baked_cache_dirty = false;

	if(points.size() == 0) {
		baked_point_cache.resize(0);
		return;
	}

	if(points.size()==1) {

		baked_point_cache.resize(1);
		baked_point_cache[0] = points[0].pos;
		return;
	}

	Vector2 pos=points[0].pos;
	std::list<Vector2> pointlist;

	pointlist.push_back(pos); //start always from origin

	for(int i=0;i<points.size()-1;i++) {

		float step = 0.1; // at least 10 substeps ought to be enough?
		float p = 0;

		while(p<1.0) {

			float np=p+step;
			if(np>1.0)
				np=1.0;


			Vector2 npp = _bezier_interp(np, points[i].pos,points[i].pos+points[i].out,points[i+1].pos+points[i+1].in,points[i+1].pos);
			float d = pos.distance_to(npp);

			if(d>bake_interval) {
				// OK! between P and NP there _has_ to be Something, let's go searching!

				int iterations = 10; //lots of detail!

				float low = p;
				float hi = np;
				float mid = low+(hi-low)*0.5;

				for(int j=0;j<iterations;j++) {


					npp = _bezier_interp(mid, points[i].pos,points[i].pos+points[i].out,points[i+1].pos+points[i+1].in,points[i+1].pos);
					d = pos.distance_to(npp);

					if(bake_interval < d)
						hi=mid;
					else
						low=mid;
					mid = low+(hi-low)*0.5;

				}

				pos=npp;
				p=mid;
				pointlist.push_back(pos);
			} else {

				p=np;
			}

		}
	}

	Vector2 lastpos = points[points.size()-1].pos;

	float rem = pos.distance_to(lastpos);
	baked_max_ofs=(pointlist.size()-1)*bake_interval+rem;
	pointlist.push_back(lastpos);

	baked_point_cache.resize(pointlist.size());
	int idx=0;

	for(std::list<Vector2>::const_iterator itr = pointlist.begin(); itr != pointlist.end(); ++itr) {

		baked_point_cache[idx] = *itr;
		idx++;
	}
}
Ejemplo n.º 9
0
void Curve3D::_bake() const {

	if (!baked_cache_dirty)
		return;

	baked_max_ofs=0;
	baked_cache_dirty=false;

	if (points.size()==0) {
		baked_point_cache.resize(0);
		baked_tilt_cache.resize(0);
		return;
	}

	if (points.size()==1) {

		baked_point_cache.resize(1);
		baked_point_cache.set(0,points[0].pos);
		baked_tilt_cache.resize(1);
		baked_tilt_cache.set(0,points[0].tilt);
		return;
	}


	Vector3 pos=points[0].pos;
	List<Plane> pointlist;
	pointlist.push_back(Plane(pos,points[0].tilt));

	for(int i=0;i<points.size()-1;i++) {

		float step = 0.1; // at least 10 substeps ought to be enough?
		float p = 0;

		while(p<1.0) {

			float np=p+step;
			if (np>1.0)
				np=1.0;


			Vector3 npp = _bezier_interp(np, points[i].pos,points[i].pos+points[i].out,points[i+1].pos+points[i+1].in,points[i+1].pos);
			float d = pos.distance_to(npp);

			if (d>bake_interval) {
				// OK! between P and NP there _has_ to be Something, let's go searching!

				int iterations = 10; //lots of detail!

				float low = p;
				float hi = np;
				float mid = low+(hi-low)*0.5;

				for(int j=0;j<iterations;j++) {


					npp = _bezier_interp(mid, points[i].pos,points[i].pos+points[i].out,points[i+1].pos+points[i+1].in,points[i+1].pos);
					d = pos.distance_to(npp);

					if (bake_interval < d)
						hi=mid;
					else
						low=mid;
					mid = low+(hi-low)*0.5;

				}

				pos=npp;
				p=mid;
				Plane post;
				post.normal=pos;
				post.d=Math::lerp(points[i].tilt,points[i+1].tilt,mid);
				pointlist.push_back(post);
			} else {

				p=np;
			}

		}
	}

	Vector3 lastpos = points[points.size()-1].pos;
	float lastilt = points[points.size()-1].tilt;

	float rem = pos.distance_to(lastpos);
	baked_max_ofs=(pointlist.size()-1)*bake_interval+rem;
	pointlist.push_back(Plane(lastpos,lastilt));

	baked_point_cache.resize(pointlist.size());
	Vector3Array::Write w = baked_point_cache.write();
	int idx=0;

	baked_tilt_cache.resize(pointlist.size());
	RealArray::Write wt = baked_tilt_cache.write();

	for(List<Plane>::Element *E=pointlist.front();E;E=E->next()) {

		w[idx]=E->get().normal;
		wt[idx]=E->get().d;
		idx++;
	}

}