1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
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) []
|