[REQ] Curvespace for bezierspline.rb
-
While struggling with animation paths i discovered a way to use the Polyline Divider tool combined with the flightpath script to bake every frame of an animation.
The Polyline Divider however only draws straight lines that make a bit jumpy animations at bends. After a little Googling I found some code for something called Curvespace. Could this be implemented as a addon to beziercurve.rb?If this could be done and perhaps add the possibility to use different interpolations like smoothstep for the distance between point one might just be able to do some smooooooth animation.
Here's the code:
function q = curvspace(p,N) % CURVSPACE Evenly spaced points along an existing curve in 2D or 3D. % CURVSPACE(P,N) generates N points that interpolates a curve % (represented by a set of points) with an equal spacing. Each % row of P defines a point, which means that P should be a n x 2 % (2D) or a n x 3 (3D) matrix. % % (Example) % x = -2*pi;0.5;2*pi; % y = 10*sin(x); % z = linspace(0,10,length(x)); % N = 50; % p = [x',y',z']; % q = curvspace(p,N); % figure; % plot3(p(;,1),p(;,2),p(;,3),'*b',q(;,1),q(;,2),q(;,3),'.r'); % axis equal; % legend('Original Points','Interpolated Points'); % % See also LINSPACE. % % 22 Mar 2005, Yo Fukushima %% initial settings %% currentpt = p(1,;); % current point indfirst = 2; % index of the most closest point in p from curpt len = size(p,1); % length of p q = currentpt; % output point k = 0; %% distance between points in p %% for k0 = 1;len-1 dist_bet_pts(k0) = distance(p(k0,;),p(k0+1,;)); end totaldist = sum(dist_bet_pts); %% interval %% intv = totaldist./(N-1); %% iteration %% for k = 1;N-1 newpt = []; distsum = 0; ptnow = currentpt; kk = 0; pttarget = p(indfirst,;); remainder = intv; % remainder of distance that should be accumulated while isempty(newpt) % calculate the distance from active point to the most % closest point in p disttmp = distance(ptnow,pttarget); distsum = distsum + disttmp; % if distance is enough, generate newpt. else, accumulate % distance if distsum >= intv newpt = interpintv(ptnow,pttarget,remainder); else remainder = remainder - disttmp; ptnow = pttarget; kk = kk + 1; if indfirst+kk > len newpt = p(len,;); else pttarget = p(indfirst+kk,;); end end end % add to the output points q = [q; newpt]; % update currentpt and indfirst currentpt = newpt; indfirst = indfirst + kk; end %%%%%%%%%%%%%%%%%%%%%%%%% %% SUBFUNCTIONS %% %%%%%%%%%%%%%%%%%%%%%%%%% function l = distance(x,y) % DISTANCE Calculate the distance. % DISTANCE(X,Y) calculates the distance between two % points X and Y. X should be a 1 x 2 (2D) or a 1 x 3 (3D) % vector. Y should be n x 2 matrix (for 2D), or n x 3 matrix % (for 3D), where n is the number of points. When n > 1, % distance between X and all the points in Y are returned. % % (Example) % x = [1 1 1]; % y = [1+sqrt(3) 2 1]; % l = distance(x,y) % % 11 Mar 2005, Yo Fukushima %% calculate distance %% if size(x,2) == 2 l = sqrt((x(1)-y(;,1)).^2+(x(2)-y(;,2)).^2); elseif size(x,2) == 3 l = sqrt((x(1)-y(;,1)).^2+(x(2)-y(;,2)).^2+(x(3)-y(;,3)).^2); else error('Number of dimensions should be 2 or 3.'); end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function newpt = interpintv(pt1,pt2,intv) % Generate a point between pt1 and pt2 in such a way that % the distance between pt1 and new point is intv. % pt1 and pt2 should be 1x3 or 1x2 vector. dirvec = pt2 - pt1; dirvec = dirvec./norm(dirvec); l = dirvec(1); m = dirvec(2); newpt = [intv*l+pt1(1),intv*m+pt1(2)]; if length(pt1) == 3 n = dirvec(3); newpt = [newpt,intv*n+pt1(3)]; end
-
Who wrote beziercurve.rb? IS that the one that @Last released? Or is it by Fredo or Didier or something?
Since most of the bezier curve scripts keep splines that are editable after they are created, I am guessing that the beziercurve script is writing it definition parameters to an Attribute Dictionary. You might check the attributes of the bezier and see if it doesn't have some [x,y,z] infos associated with it. A simple bezier should have 4 sets of x,y,z info with it. If the curve does have it, then you can use it to reproduce the bezier with as many segments as you would like.
But that is only if the bezier has stored its start point, endpoint, start_handle, and end_handle (I've been calling them handles because of Illustrator, but I don't if they have a real name).
Thats just a thought, maybe it doesn't work like that.
Chris
-
I mean Fredos BezierSpline tools that is made for extending with other curves.
-
@pixero said:
While struggling with animation paths i discovered a way to use the Polyline Divider tool combined with the flightpath script to bake every frame of an animation.
The Polyline Divider however only draws straight lines that make a bit jumpy animations at bends. After a little Googling I found some code for something called Curvespace. Could this be implemented as a addon to beziercurve.rb?If this could be done and perhaps add the possibility to use different interpolations like smoothstep for the distance between point one might just be able to do some smooooooth animation.
Pixero,
It would be easy to integrate, but I am afraid that this code does not do anything different from the Divider.
What I would suggest is that you design your path with a F Spline (or a Polyline converetd to a F-Spline), and then convert it via Polyline Divider, so that all segments have the same length. If you take a small enough length dimension, it will preserve the smooth shape of the curve.Attached is a file showing the 3 steps:
Indeed, this could be automated in one type of curve (say Divider-F-Spline) if you really need this frequently.
Fredo
PS: I remember there is also a script called BezierFlightPath or so that creates Bezier curves with equal segments.
-
Wow, didnt know it was possible with the current tools.
Another question.
Would it be possible to have the choice of other than linear distance distribution of the points?
And set a min distance and a max distance.
That would make it possible to smooth the animation by accelerating or decelerating.I'm getting exited here...
Like this:
### INTERPOLATIONS ### t is the current time, between 0 and duration inclusive. b is the initial value of the animation property. c is the total change in the animation property. d is the duration of the motion. # Linear interpolation (even spacing) def lerp(t, b, c) return ((b.to_f) * (1.0 - t.to_f) + c.to_f * t.to_f) end # EaseIn equation function for a quadratic (t^2) easing in; accelerating from zero velocity. def easeInQuad(t, b, c, d) return c*(t/=d)*t + b; end#def # EaseOut equation function for a quadratic (t^2) easing out; decelerating to zero velocity. def easeOutQuad(t, b, c, d) return -c *(t/=d)*(t-2) + b; end#def # Smoothstep interpolation def smooth(t, b, c) r=(t.to_f-b.to_f)/(c.to_f-b.to_f) return r*r*(3.0-2.0*r) end
-
@pixero said:
Another question.
Would it be possible to have the choice of other than linear distance distribution of the points?
And set a min distance and a max distance.
That would make it possible to smooth the animation by accelerating or decelerating.Evrything is possible. The question is to specify it.
I can easily make the Divider with an increasing or decreasing step following any mathematical equation. Alternatively, this could be based on angles so that it speeds up in the straight sections and slows down in the curves.
Fredo
-
The thing is that I have found a way to control animation in SU and if I could specify a min length, a max length and one of the interpolations in my post above (when linear only one length of cause)when converting to polyline divider everything would work. Of cause a curve based alternative could also be handy. This would mean a huge step forwards for animation in SU.
I'll try to make a tutorial if/when I have this last piece of the puzzle.Here's a link to some more interpolations:
http://library.sfug.ch/trac/browser/trunk/branches/1.x/doc/as3/benchmarks/tweener/caurina/transitions/Equations.as?rev=219
Advertisement