summaryrefslogtreecommitdiff
path: root/progs/demo/X11/animation/r_inbetween.hs
diff options
context:
space:
mode:
Diffstat (limited to 'progs/demo/X11/animation/r_inbetween.hs')
-rw-r--r--progs/demo/X11/animation/r_inbetween.hs82
1 files changed, 82 insertions, 0 deletions
diff --git a/progs/demo/X11/animation/r_inbetween.hs b/progs/demo/X11/animation/r_inbetween.hs
new file mode 100644
index 0000000..a7fb7d3
--- /dev/null
+++ b/progs/demo/X11/animation/r_inbetween.hs
@@ -0,0 +1,82 @@
+{-******************************************************************
+ MODULE R_INBETWEEN
+
+ This module takes care of interpolation functions. Basically,
+ given two Pics, inbetween will give you a movie gradually
+ converting from one Pic to the other Pic, using linear interpolation.
+ Tween will take two Movies, and append them, interpolating n
+ frames between the last Pic of the first Movie and the first Pic of
+ the last Movie.
+
+******************************************************************-}
+
+module R_Inbetween (inbetween,tween) where
+
+import R_Ptypes
+import R_Utility
+import R_Picture
+import R_Behaviour
+
+ -- inbetween takes an int and two Pics, and interpolates n Pics
+ -- of interpolated Pics.
+inbetween :: Int -> Pic -> Pic -> Movie
+inbetween n p1 p2 | (length p1 == length p2) =
+ ((zip1.(map (inbetweenp n))).zip1) [p1,p2]
+inbetween n p1 p2 = inbetween n [(col,p1')] [(col,p2')]
+ where p1' = concat [ vs | (c,vs) <- p1]
+ p2' = concat [ vs | (c,vs) <- p2]
+ col = head [ c | (c,vs) <- p1 ]
+
+ -- inbetweenp takes a list of 2 Polygons ([[Vec]]) and returns a
+ -- sequence of interpolated Polygons. Should the Number of vertices
+ -- of one Polygon be less than those in the other, it splits it so
+ -- as to have two Polygons of the same length.
+inbetweenp :: Int -> Pic -> Pic
+inbetweenp n [(c1,vs),(c2,ws)] =
+ if ((length vs) < (length ws)) then
+ inbetween1 (split (length ws) (c1,vs)) (c2,ws) 0 n
+ else if ((length vs) > (length ws)) then
+ inbetween1 (c1,vs) (split (length vs) (c2,ws)) 0 n
+ else inbetween1 (c1,vs) (c2,ws) 0 n
+
+
+ -- inbetween1 returns a sequence of interpolated Polygons.
+inbetween1 :: Poly -> Poly -> Int -> Int -> Pic
+inbetween1 p1 p2 m n | m>n || n<=0 = []
+inbetween1 p1 p2 m n = inbetween2 p1 p2 m n
+ :inbetween1 p1 p2 (m+1) n
+
+ -- inbetween2 returns ONE of the required sequence of
+ -- interpolated Polygons.
+inbetween2 :: Poly -> Poly -> Int -> Int -> Poly
+inbetween2 (c1,vs) (c2,ws) p q = (c1, map (partway p q) (zip1 [vs,ws]))
+
+ -- split splits up a Polygon so as to have the given #vertices.
+split :: Int -> Poly -> Poly
+split n (c,vs) = (c, split' n vs)
+
+split' :: Int -> [Vec] -> [Vec]
+split' n vs | n<= (length vs) = vs
+split' n vs = if (n>double) then
+ split' n (split' double vs)
+ else
+ v1:(mid v1 v2):(split' (n-2) (v2:vss))
+ where double = 2*((length vs)) - 1
+ (v1:v2:vss) = vs
+
+
+ -- tween will interpolate n Pics transforming the last Pic of
+ -- the first Movie into the first Pic of the second Movie, and
+ -- then run the second Movie
+tween :: Int -> Movie -> Movie -> Movie
+tween n m1 [] = m1
+tween n m1 m2 = m1 ++ (inbetween n (last m1) (head m2')) ++ (tail m2')
+ where m2' = apply (mov (repeat v)) m2
+ v = vmin (orig_Pic (last m1)) (orig_Pic (head m2))
+
+ -- tweens will take a list of Movies and append them all, interpolating
+ -- n frames between every Movie.
+tweens :: Int -> [Movie] -> Movie
+tweens n = foldr (tween n) []
+
+