Dark Bit Factory & Gravity
PROGRAMMING => General coding questions => Topic started by: relsoft on January 16, 2009
-
Beziers are kinda sexier than Catmull Roms but Catmull's behavior are easy to predict(visualize) since they (catmulls) would follow a set of points while B-splines are vector based. Preferably just a single bezier to got through all the points.
What I'm trying to achieve is for a Bezier to follow the trajectory the catmull in this demo does.
Or I'm shooting myself in the knee for even attempting this?
FreeBasic code
Type Tpoint
x as single
y as single
end type
function catmull_rom(byval p0 as TPoint, byval p1 as TPoint, byval p2 as TPoint, byval p3 as TPoint, byval t as single) as Tpoint
dim as single t2 = t * t
dim as single t3 = t2 * t
dim as Tpoint catmull_point
catmull_point.x = 0.5f * ( ( 2.0 * p1.x ) +_
( -p0.x + p2.x ) * t +_
( 2.0 * p0.x - 5.0 * p1.x + 4 * p2.x - p3.x ) * t2 +_
( -p0.x + 3.0 * p1.x - 3.0 * p2.x + p3.x ) * t3 )
catmull_point.y = 0.5 * ( ( 2.0 * p1.y ) +_
( -p0.y + p2.y ) * t +_
( 2.0 * p0.y - 5.0 * p1.y + 4 * p2.y - p3.y ) * t2 +_
( -p0.y + 3.0 * p1.y - 3.0 * p2.y + p3.y ) * t3 )
return catmull_point
end function
function cosine_spline(byval p0 as TPoint, byval p1 as TPoint, byval t as single) as Tpoint
dim as Tpoint cosine_point
dim as single ft,f
ft = t * 3.1415927
f = (1 - cos(ft)) * 0.5
cosine_point.x = p0.x *(1-f) + p1.x *f
cosine_point.y = p0.y *(1-f) + p1.y *f
return cosine_point
end function
function bezier(byval p0 as TPoint, byval p1 as TPoint, byval p2 as TPoint, byval p3 as TPoint, byval t as single) as Tpoint
dim as Tpoint bez
dim as single b
'A = p1
'B = p0
'C = p3
'D = p2
b = 1 - t
bez.x = p1.x*b^3 + 3*p0.x*(b^2)*t + 3*p3.x*(b)*(t^2) + p2.x*(t^3)
bez.y = p1.y*b^3 + 3*p0.y*(b^2)*t + 3*p3.y*(b)*(t^2) + p2.y*(t^3)
return bez
end function
cls
screen 18,,2
randomize timer
const as integer MAXPOINTS = 5
dim i as integer
dim points(0 to (MAXPOINTS-1)) as Tpoint
dim p as Tpoint
dim p0 as Tpoint
dim p1 as Tpoint
dim p2 as Tpoint
dim p3 as Tpoint
for i = 0 to MAXPOINTS-1
points(i).x = rnd * 640
points(i).y = rnd * 480
next i
'points(MAXPOINTS-1).x = points(0).x
'points(MAXPOINTS-1).y = points(0).y
dim current_color as integer
current_color = 2
dim index as integer
index = 0' maxpoints+1
do
locate 1,1
print index
for i = 0 to MAXPOINTS - 1
circle (points(i).x,points(i).y), 5, i+1
next i
p0.x = points(index).x
p0.y = points(index).y
p1.x = points((index + 1) mod MAXPOINTS).x
p1.y = points((index + 1) mod MAXPOINTS).y
p2.x = points((index + 2) mod MAXPOINTS).x
p2.y = points((index + 2) mod MAXPOINTS).y
p3.x = points((index + 3) mod MAXPOINTS).x
p3.y = points((index + 3) mod MAXPOINTS).y
for i = 0 to 99
dim as single t
t = i/100
p = catmull_rom(p0,p1,p2,p3,t)
if i = 0 then
pset (p.x,p.y), current_color
else
line -(p.x,p.y), current_color
end if
sleep 5
next i
index += 1
if index > MAXPOINTS-1 then
index = 0
current_color = 1 + (current_color + 1) and 15
end if
loop until inkey <> ""
Thanks!!!
-
Hey Rel, you're a maths professor and I am not, but I'd stick to Catmul rom splines to be sure that it intersects the control points, unless you're trying to do this as a mathematical excercise.
I think it is going to be highly difficult to make a bezier behave like a catmul, although you do know that it's going to hit the start and end points so maybe you can connect several beziers and mess around with the control points to create some nice movements?
I atteched an exe of your nice catmul rom routine for peeps without FB to try it :)
-
What I'm trying to achieve is for a Bezier to follow the trajectory the catmull
But what's the benefit of bezier then?
If you just want more control over your catmull-path, you can simply specify tangents like eg. kochanek-bartels splines.
Preferably just a single bezier to got through all the points
So you want to calculate a set of (bezier-)points approximating a given curve?
Since the bezier is basically a polynomial, you can find a best-regression polynomial of given degree (cholesky decomposition) and solve the control-points from its' coefficients.
-
After hours of trying with disastrous results, I think I'll stick with multiple catmulls. :*(
I tried brute force, I tried DeCasteljau interpolation and the best result I got is still with Catmull roms. :*(
:whack:
Hell fire: I don't know both (cholesky decomposition) and kochanek-bartels splines. You have a link to those?
[edit]
Ive just read kochanek-bartels splines and they seem to he Hermite based as is the Catmull and the sample curves they do wouldn't look good at all.
Cholesky decomposition seems to be hermite in nature too.
-
I'm still not quite sure what you're trying to do or why you're trying it.
What I suggested was: get a couple of sample points from your catmull spline, calculate a regression polynomial through these samples and solve the bezier-controlpoints from the polynomial's equation.
Kochanek-Bartels is exactly the same as catmull-rom except that you can modify the orientation and weighting of the tangents (which makes the curve more flexible) - in catmull-rom they're fixed.
Cholesky solves a linear system of equations which you'll get for the regression polynomial.