REM ***********************************************
REM Title: Hermite Spline
REM Author: Phaelax
REM Downloaded from: http://dbcc.zimnox.com/
REM ***********************************************
 
rem catmullrom vector order: control, pt1, pt2, control
rem hermite vector order: pt1, control, pt2, control
 
set display mode 800,600,32
 
randomize timer()
 
rem 2d vector type
type vector
   x as float
   y as float
   w as float
endtype
 
 
rem 2 vectors as line segment's endpoints, 2 vectors for control points
type hermiteline
   a as vector
   b as vector
   c as vector
   d as vector
endtype
 
 
rem number of points defining hermite spline
spline_total = 5
 
rem get screen dimensions
width = screen width()
height = screen height()
 
rem array of hermite splines
dim spline(spline_total) as hermiteline
 
for t = 1 to spline_total
   if t > 1
      spline(t).a.x = spline(t-1).c.x
      spline(t).a.y = spline(t-1).c.y
      spline(t).b.x = spline(t-1).d.x
      spline(t).b.y = spline(t-1).d.y
   else
      spline(t).a.x = rnd(width)
      spline(t).a.y = rnd(height)
      spline(t).b.x = (rnd(200)-100) + spline(t).a.x
      spline(t).b.y = (rnd(200)-100) + spline(t).a.y
   endif
   spline(t).c.x = rnd(width)
   spline(t).c.y = rnd(height)
   spline(t).d.x = (rnd(200)-100) + spline(t).c.x
   spline(t).d.y = (rnd(200)-100) + spline(t).c.y
next t
 
 
rem vector points for hermite splines
null = make vector2(1)
null = make vector2(2)
null = make vector2(3)
null = make vector2(4)
 
rem result vector
null = make vector2(5)
null = make vector2(6)
 
 
rem more steps mean a smoother curve in the spline
steps = 20
 
rem colors of rainbow
dim colors(7) as dword
colors(1) = rgb(255,0,0)
colors(2) = rgb(213,0,213)
colors(3) = rgb(0,0,255)
colors(4) = rgb(0,255,255)
colors(5) = rgb(0,255,0)
colors(6) = rgb(255,255,0)
colors(7) = rgb(255,0,0)
 
p_total = 100
dim particles(p_total) as vector
for t = 1 to p_total
   particles(t).x = rnd(width)
   particles(t).y = 0
   particles(t).w = rnd(5)+1
next t
 
DO
   cls
 
   for t = 1 to spline_total
      rem allow user to click on spline point
      if mouseclick() and movePoint = 0
         if abs(mousex()-spline(t).a.x) < 4 and abs(mousey()-spline(t).a.y) < 4 then movePoint = t
      endif
 
      rem create hermite spline
      for s = 1 to steps
         rem get the 4 vectors
         set vector2 1,spline(t).a.x,spline(t).a.y
         set vector2 2,spline(t).b.x,spline(t).b.y
         set vector2 3,spline(t).c.x,spline(t).c.y
         set vector2 4,spline(t).d.x,spline(t).d.y
 
         time# = s
         hermite vector2 5,1,2,3,4,(time#-1.0)/steps
         hermite vector2 6,1,2,3,4, time#/steps
 
         rem make rainbow
         offset = -6
         c = 1
         for r = 1 to 6
            ink colors(c),0
            line x vector2(5), y vector2(5)+offset,x vector2(6), y vector2(6)+offset
            line x vector2(5), y vector2(5)+offset+1,x vector2(6), y vector2(6)+offset+1
            inc offset,2
            inc c
         next r
 
         rem draw circle to show spline points
         ink rgb(255,255,255),0
         circle spline(t).a.x,spline(t).a.y,4
         circle spline(t).c.x,spline(t).c.y,4
 
      next s
   next t
 
 
   rem rain particles
   lock pixels
      for p = 1 to p_total
 
      particles(p).y = particles(p).y + particles(p).w
 
      for t = 1 to spline_total
 
         rem create hermite spline
         for s = 1 to steps
            rem get the 4 vectors
            set vector2 1,spline(t).a.x,spline(t).a.y
            set vector2 2,spline(t).b.x,spline(t).b.y
            set vector2 3,spline(t).c.x,spline(t).c.y
            set vector2 4,spline(t).d.x,spline(t).d.y
 
            time# = s
            hermite vector2 5,1,2,3,4,(time#-1.0)/steps
            hermite vector2 6,1,2,3,4, time#/steps
 
            x1 = x vector2(5)
            y1 = y vector2(5)
            x2 = x vector2(6)
            y2 = y vector2(6)
            rem keep low to high order of points
            if x2 < x1
               temp = x1
               x1 = x2
               x2 = temp
               temp = y1
               y1 = y2
               y2 = temp
            endif
 
            if particles(p).x >= x1 and particles(p).x <= x2
               if point_line(particles(p).x, particles(p).y, x1, y1, x2, y2) >= 0
                  particles(p).x = rnd(width)
                  particles(p).y = 0
               endif
            endif
 
            if particles(p).y >= height
               particles(p).x = rnd(width)
               particles(p).y = 0
               particles(p).w = rnd(5)+1
            endif
 
         next s
      next t
      rem draw raindrop
      set_locked_pixel(particles(p).x, particles(p).y, rgb(255,255,255))
   next p
   unlock pixels
 
 
 
   rem allow user to move spline points (control points stay in original locations)
   if movePoint > 0
      spline(movePoint).a.x = mousex()
      spline(movePoint).a.y = mousey()
      if movePoint > 1
         spline(movePoint-1).c.x = spline(movePoint).a.x
         spline(movePoint-1).c.y = spline(movePoint).a.y
      endif
   endif
 
   if mouseclick() = 0 then movePoint = 0
 
   if spacekey() then resetSplines(spline_total)
 
loop
 
 
 
REM give new random coordinates for points
function resetSplines(spline_total as integer )
   for t = 1 to spline_total
      if t > 1
         spline(t).a.x = spline(t-1).c.x
         spline(t).a.y = spline(t-1).c.y
         spline(t).b.x = spline(t-1).d.x
         spline(t).b.y = spline(t-1).d.y
      else
         spline(t).a.x = rnd(width)
         spline(t).a.y = rnd(height)
         spline(t).b.x = (rnd(200)-100) + spline(t).a.x
         spline(t).b.y = (rnd(200)-100) + spline(t).a.y
      endif
      spline(t).c.x = rnd(width)
      spline(t).c.y = rnd(height)
      spline(t).d.x = (rnd(200)-100) + spline(t).c.x
      spline(t).d.y = (rnd(200)-100) + spline(t).c.y
   next t
endfunction
 
 
REM if point(px,py) is right or left of line segment (x1,y1),(x2,y2)
REM return negative if left, positive if right, 0 if on
function point_line(px#,py#, x1#,y1#,x2#,y2#)
   dp# = (x2# - x1#) * (py# - y1#) - (px# - x1#) * (y2# - y1#)
endfunction dp#
 
 
REM function borrowed from Coding Fodder's Rain code
function set_locked_pixel(x as integer, y as integer, color_value as dword )
   start = get pixels pointer()
   repeat_number = get pixels pitch()
   bits_per_pixel = bitmap depth(num)/8
   pointer = start + y*repeat_number + x*bits_per_pixel
   *pointer = color_value
endfunction