Well I've been hashing out how to use bezier curves. I came up with these two classes.
The first class is a basic bezier curve, the second is a cubic bezier curve. The paramaters are the same for both
CP1 - CP4 : sets the X,Y for the control points
set_steps : Sets the number of steps
There are two more methods
update : call this after all of the control points, and steps have been set.
draw_curve : Just draws a 2D representation of the curve to the screen.
Basic Bezier Class
Public Class basic_bezier
Structure controlpoint
Dim x As Double
Dim y As Double
End Structure
Public cp1 As controlpoint
Public cp2 As controlpoint
Public cp3 As controlpoint
Private steps As Integer
Dim values() As controlpoint
Dim draw_2d As TVScreen2DImmediate
Sub New()
draw_2d = New TVScreen2DImmediate
End Sub
Public Sub update()
Dim x(3) As Double
Dim y(3) As Double
Dim j As Double
Dim i As Double
Dim t As Double
Dim inc As Integer
x(0) = cp1.x : y(0) = cp1.y
x(1) = cp2.x : y(1) = cp2.y
x(2) = cp3.x : y(2) = cp3.y
For t = 0 To 1 Step 1 / steps
j = (1 - t) ^ 2 * x(0) + 2 * t * (1 - t) * x(1) + t ^ 2 * x(2)
i = (1 - t) ^ 2 * y(0) + 2 * t * (1 - t) * y(1) + t ^ 2 * y(2)
values(inc).x = j
values(inc).y = i
inc = inc + 1
Next t
End Sub
Public Sub set_steps(ByVal x As Integer)
ReDim values(x)
steps = x
End Sub
Public Sub draw_curve()
Dim j As Integer
draw_2d.Action_Begin2D()
For j = 0 To steps
draw_2d.Draw_FilledCircle(values(j).x, values(j).y, 2)
Next
draw_2d.Draw_Line(cp1.x, cp1.y, cp2.x, cp2.y)
draw_2d.Draw_Line(cp2.x, cp2.y, cp3.x, cp3.y)
draw_2d.Action_End2D()
End Sub
End Class
Cubic Bezier Code
Class Cubic_Bezier
Structure controlpoint
Dim x As Double
Dim y As Double
End Structure
Public cp1 As controlpoint
Public cp2 As controlpoint
Public cp3 As controlpoint
Public cp4 As controlpoint
Private steps As Integer
Dim values() As controlpoint
Dim draw_2d As TVScreen2DImmediate
Sub New()
draw_2d = New TVScreen2DImmediate
End Sub
Public Sub update()
Dim ax, bx, cx As Double
Dim ay, by, cy As Double
Dim j, i As Double
Dim tsqd, tcube As Double
Dim t As Double
Dim x(3) As Double
Dim y(3) As Double
Dim inc As Integer
x(0) = cp1.x : y(0) = cp1.y
x(1) = cp2.x : y(1) = cp2.y
x(2) = cp3.x : y(2) = cp3.y
x(3) = cp4.x : y(3) = cp4.y
For t = 0 To 1 Step 1 / steps
cx = 3.0 * (x(1) - x(0))
bx = 3.0 * (x(2) - x(1)) - cx
ax = x(3) - x(0) - cx - bx
cy = 3.0 * (y(1) - y(0))
by = 3.0 * (y(2) - y(1)) - cy
ay = y(3) - y(0) - cy - by
tsqd = t ^ 2
tcube = t ^ 3
j = (ax * tcube) + (bx * tsqd) + (cx * t) + x(0)
i = (ay * tcube) + (by * tsqd) + (cy * t) + y(0)
values(inc).x = j
values(inc).y = i
inc = inc + 1
Next t
End Sub
Public Sub set_steps(ByVal x As Integer)
ReDim values(x)
steps = x
End Sub
Public Sub draw_curve()
Dim j As Integer
draw_2d.Action_Begin2D()
For j = 0 To steps
draw_2d.Draw_FilledCircle(values(j).x, values(j).y, 2)
Next
draw_2d.Draw_Line(cp1.x, cp1.y, cp2.x, cp2.y)
draw_2d.Draw_Line(cp2.x, cp2.y, cp3.x, cp3.y)
draw_2d.Draw_Line(cp3.x, cp3.y, cp4.x, cp4.y)
draw_2d.Action_End2D()
End Sub
End Class
Here is some code to set it up
Dim mycurve As Cubic_Bezier
mycurve = New Cubic_Bezier
With mycurve
.cp1.x = 100 : .cp1.y = 100
.cp2.x = 200 : .cp2.y = 100
.cp3.x = 200 : .cp3.y = 500
.cp4.x = 300 : .cp4.y = 500
.set_steps(1000)
End With
mycurve.update()
mycurve.draw_curve()
Drop the murcurve.draw_curve() line in your main loop and watch the action.
I've played around with this a little bit, and it seems pretty quick.
I'm looking for input to make these a little more efficient if possible. Or critiques on the way it is coded.
I plan on developing two more classes to go along with these. One to generate surface curves, and another that will allow you to have as many control points as you want.
I've already made some pretty looking terrain using these. Nice smooth rolling hills. I'll post some images once I get a better looking interface for them.