PDA

View Full Version : Catmull-Rom spline



Michael Hartlef
26-12-2009, 15:18
Here is a little sample code, to produce a catmull-rom spline with TBGL. This algorythm will be used to add another variaty to create a path in the next update of TBAI.




'*********************************************************
'
' catmull_rom_spline interpretation for thinBasic
' by Michael Hartlef
'
'*********************************************************


Uses "TBGL"

Type point
x As Single
y As Single
End Type
%numPoints = 6
Dim pa(%numPoints) As point
Global width, height As Long

'*********************************************************
Function TBMAIN()
'*********************************************************
Local hWnd As DWord

' -- Create and show window
hWnd = TBGL_CREATEWINDOWEX("TBGL catmull-rom spline script - press Q to quit, P to calculate a new curve", 640, 480, 32, %TBGL_WS_WINDOWED Or %TBGL_WS_CLOSEBOX)
TBGL_GETWINDOWCLIENT( hWnd, width, height )
SetupPoints()

TBGL_SHOWWINDOW

' -- Resets status of all keys
TBGL_RESETKEYSTATE()

' -- Set the resolution and the coordinate system
TBGL_RENDERMATRIX2D (0,height,width,0)

' -- Main loop
While TBGL_ISWINDOW(hWnd)

' -- clear the background
TBGL_CLEARFRAME

' -- Draw the line
DrawSpline()
' -- Flip the framebuffer
TBGL_DRAWFRAME

' -- Q key to exit application
If TBGL_GETWINDOWKEYSTATE(hWnd, %VK_Q) Then Exit While
If TBGL_GETWINDOWKEYONCE(hWnd,%VK_P) Then SetupPoints()
Wend

TBGL_DESTROYWINDOW
End Function

'*********************************************************
Sub GetPointOnSpline(pn As point, t As Single, p0 As point, p1 As point, p2 As point, p3 As point)
'*********************************************************
Local t2,t3 As Single
t2 = t * t
t3 = t2 * t
pn.x = 0.5 * ( ( 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 )
pn.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 )
End Sub


'*********************************************************
Sub SetupPoints()
'*********************************************************
Local i As Long
For i = 1 To %numPoints
pa(i).x = i*width/(%numPoints+1)
pa(i).y = Rnd(50,height-50)
Next
End Sub

'*********************************************************
Sub DrawSpline()
'*********************************************************
Local i As Long
Local dt As Single
Local dp As point

Local div As Long = 50

' -- Draw the curve
TBGL_COLOR 255,255,255
For i = 1 To div
dt = i/div
GetPointOnSpline(dp, dt, pa(1), pa(1), pa(2), pa(3))
TBGL_POINT(dp.x, dp.y)
GetPointOnSpline(dp, dt, pa(1), pa(2), pa(3), pa(4))
TBGL_POINT(dp.x, dp.y)
GetPointOnSpline(dp, dt, pa(2), pa(3), pa(4), pa(5))
TBGL_POINT(dp.x, dp.y)
GetPointOnSpline(dp, dt, pa(3), pa(4), pa(5), pa(6))
TBGL_POINT(dp.x, dp.y)
GetPointOnSpline(dp, dt, pa(4), pa(5), pa(6), pa(6))
TBGL_POINT(dp.x, dp.y)
Next

' -- Draw some red points for the six points of the curve
TBGL_COLOR 255,0,0
For i = 1 To %numPoints
TBGL_NGON(pa(i).x, pa(i).y, 5,16)
Next

End Sub

Petr Schreiber
26-12-2009, 19:47
Fantastic Mike,

this kind of spline is used in many commercial PC games, and works just great.


Petr

kryton9
28-12-2009, 07:47
Nice code and example Mike, thanks!