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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
|
% This is obsolete regarding the X system -- jcp
% -*-latex-*-
% Creator: John Tinmouth
% Creation Date: Thu May 9 1991
\documentstyle[11pt]{article}
\newcommand{\X}[1]{{#1}\index{{#1}}}
\begin{document}
\title{A Functional Animation Package in Haskell}
\author{
John Tinmouth\\
Computer Science Senior Project\\
Yale University\\
Professor Paul Hudak }
\date{9 May 1991}
\maketitle
\section{Introduction}
In his paper "A Functional Animation Starter Kit" [ARYA88], Kevi Arya
proposes an approach to animation that uses functional languages. As
Arya describes, the cost of computing power is falling. This is making
the use of computer animation much more prevalent. However, languages
such as C make it difficult to program animations. What is needed is
a simpler, faster and more accessible way to program graphics. Functional
languages are a very effective means for this, due to their higher order
functions.
Kevi Arya goes on to provide such a functional animation package in
the language Miranda. Haskell in particular is good functional language for
two reasons. It is a completely functional language, doing even I/O in a
functional manner. Variables are evaluated in a lazy manner allowing infinite
lists to be manipulated easily, which suits the infinite frames format
of animation. As it is now possible to complete the implementation of
this package is Haskell, my work has been converting these Miranda programs
to Haskell version 1.0-0, Yale Haskell Group.
\section{How to Use the Graphics: Overview}
By using higher order functions, it becomes very easy to do rapid
prototyping of animations. You can quickly throw out an animation of
simple images manipulated in simple ways. For example, if there was
an image of a car, and you wanted it to move left, you could almost
just describe it in english, and that would be the animation.
\begin{verbatim}
movie = apply left car
\end{verbatim}
After the simple model is done, converting it to a more complex model
is simple. Simply make the image, "car" in this case, more complex, and
then modify the "left" function, and you are done.
There are three stages in making a movie. First of all, you must
define your basic images. These will tend to be Pics put into lists, either
finite or infinite, to be basic Movies. Second, you decide precisely
what kind of motion you want in animation. These are behaviours. A behaviour
modifies a movie over time, changing each successive frame. This includes
motion, changing size, changing from one image to another and so forth. These
are applied to your basic Movies. Third, you must combine your basic Movies
into your final Movie. If you want a scene of clouds and a man walking, you
must overlay your basic Movie of clouds with your Movie of a walking man.
\section {Original Images or Pics}
A Movie is a list of frames called Pics. Each of these Pics is a list
of colored polygons. The Pic is a Color followed by a list of Vectors,
representing the vertices of the Polygon. The original Pic usually must
be entered by hand, although simple generation routines for boxes,
triangles and circles are available. You need to produce some of these
basic images in one way or another, so that you have something to
manipulate.
To make a Movie, you need a list of these Pics. With a single Pic, you
can generate a sequence of that Pic. With several Pics, you can oscillate
through the Pics in an inifinite list. To generate an infinite list of
Pics of p1, define a Movie, m1 = i p1.
The following datatypes are used in this package:
\begin{verbatim}
type Vec = (Int,Int)
type Color = Int
type Poly = (Color,[Vec])
type Pic = [Poly]
type Movie = [Pic]
type Behaviour = [Pic -> Pic]
\end{verbatim}
\subsection {Modifying Pics}
Starting with a single Pic, it is possible to create a short list of
Pics to oscillate on. You can flip it, scale it, or otherwise modify the
original Pic (p1) in some way to create another Pic (p2). You can either
keep doing this and produce N images for a Movie of [p1,p2,...,pN], or use
the interpolation functions available to shift from p1 to p2 in N frames,
resulting in a Movie [p1,interp1,interp2,...,interpN-2,p2].
The list of specific Pic-to-Pic functions is included in the next section,
along with short explanations of what they do.
\subsection {Pic-to-Pic Functions Available}
\begin{verbatim}
overlay_Pic Args: Pic Pic
This takes 2 Pics and just puts them together into one Pic.
module: R_Picture
put_Pic Args: Vec Pic Pic
This overlays the two Pics, putting Pic-1's center the Vec
distance away from Pic-2's center.
module: R_Picture
over_Pic Args: Pic Pic
This puts two images on top of one another, explicitly
centering the first on top of the second and forms one Pic.
module: R_Picture
above_Pic Args: Pic Pic
This puts the first Pic above the second Pic, at a distance
of half the combined heights of the Pics and overlays them
to form one Pic.
module: R_Picture
beside_Pic Args: Pic Pic
This puts the first Pic to the right of the second Pic, at
a distance of half the combined widths of the Pics and
overlays them to form one Pic.
module: R_Picture
beside2_Pic Args: Pic Pic
Withouth analysing the widths of the Pics, it puts the
first Pic the width of the second Pic to the right and
overlays them to form one Pic.
module: R_Picture
scale_Pic Args: Int Pic
This scales the picture in elevenths around its own origin
and returns that Pic. So if the Int is 22, the Pic will
scaled by a factor of 2 (22/11).
module: R_Picture
scale_rel_Pic Args: Vev Int Pic
This is another scaling function, but it scales the image
from the Vec, treating it as the origin.
module: R_Picture
mov_Pic Args: Vec Pic
This moves the Pic by the amount of the vector.
module: R_Picture
movto_Pic Args: Vec Pic
This moves the Pic's center to the Vec.
module: R_Picture
to_orig Args: Pic
This moves the Pic's center to the lower,left side of
the Pic.
module: R_Picture
rot_Pic Args: Vec Float Pic
This rotates the Pic by the Float in radians, using the Vec
as the origin of rotation.
module: R_Picture
twist_Pic Args: Float Pic
This rotates the Pic by the Float amount of radians around
its own center.
module: R_Picture
rot_Pic' Args: Vec Pic
This rotates the Pic by a certain amount (set in R_Constants)
using the Vec as the center of rotation. The set amount of
rotation makes it faster than rot_Pic.
module: R_Picture
twist_Pic' Args: Pic
This rotates the Pic by a certain amoutn (set in R_Constants)
around the Pic's origin. The set amount of rotation makes
it faster than twist_Pic.
module: R_Picture
flipx_Pic Args: Int Pic
This flips the Pic around the line x=Int, essentially giving
a mirror image of the Pic, reversing right and left.
module: R_Picture
flipy_Pic Args: Int Pic
This flips the Pic around the line y=Int, mirror-imaging the
Pic, reversing up and down.
module: R_Picture
flip_Pic Args: Pic
This flips the Pic around its own x-origin, reversing
left and right.
module: R_Picture
flock_Pic Args: Int Pic
This takes the image Pic and copies it out Int*Int times in
a Int by Int grid pattern, and returns that as an Pic.
module: R_Picture
set_Color Args: Int Pic
This takes an Int standing for a color, and changes the
color of the Pic to that.
module: R_Picture
\end{verbatim}
\subsection{Other Functions for Manipulating Pics}
\begin{verbatim}
i Args: Any
This will take anything and return an infinite stream of them.
module: R_Utility
osc Args: [Any]
This will take a Movie, which is a list of Pics and
oscillate them.
[p1] will give [p1,p1,p1,p1....]
[p1,p2,p3,p4] will give [p1,p2,p3,p4,p3,p2,p1,p2...]
module: R_Utility
\end{verbatim}
\section{Behaviours and their Application to Movies}
A Behaviour is a list of functions that will convert one Pic to
another Pic. This list then can be applied to any Movie with one
of the application functions (most often apply). The beauty of the Behaviour
is that once you have a behaviour for moving left, you can move any
Movie left without rewriting the routine every time.
There are specific functions that take a Behaviour and a Movie and
return a new Movie. These are apply and while. If you had a Movie of a
man walking in place, and a Behaviour called left that moves Pics ever
increasing distances left, then you could create a man walking left by:
\begin{verbatim}
apply left man
\end{verbatim}
If you want to apply more than one Behaviour to a Movie, you must first
decide whether to do that in sequence or in parallel, and use bSeq and bPar
to reduce the list of Behaviours to a single Behaviour, and then apply
that to a movie. For example:
\begin{verbatim}
apply (bPar left up) gull
\end{verbatim}
will take a Movie of a gull and move the Pics up and left.
Most of the basic Behaviours are defined in R\_Behaviour.
\subsection{Defining Customized Packages of Behaviours}
Often you will have more specialized, or just simpler Behaviours you
want to use. Using the Behaviours and Pic-to-Pic functions, it is very
easy to create your own small library of Behaviours. R\_Defaults is a
module of such Behaviours. For example, to create a Behaviour to move
a Movie right, you would create a list of mov\_Pic's, each taking a
everincreasingly large x-coordinate.
\begin{verbatim}
right = [ mov_Pic (x,y) | (x,y) <- zip [0,10,..] [0,..] ]
\end{verbatim}
Or if you wanted a behavour to place a Movie at (100,100) twice as
large as before, you could create a new Behaviour from old ones as:
scaleat= bPar [movto (i (100,100)), scale (i 22)]
\subsection{Behaviours Available}
\begin{verbatim}
flip Args: none
This will flip every Pic around its x-origin, resulting in
mirror images reversing left and right.
module: R_Behaviour
twist' Args: none
This will rotate each Pic by the amount rotunit (see
R_Constants) around its origin.
module: R_Behaviour
mov Args: [Vec]
This will move each Pic by its corresponding vector.
module: R_Behaviour
movto Args: [Vec]
This will move each Pic's origin to its corresponding vector.
module: R_Behaviour
circ_mov Args: Float Float
This will move each Pic in a circle, of radius of the first
Float and by an increment of the second Float, using (0,0)
as the origin of rotation.
module: R_Behaviour
scale Args: [Int]
Scales every Pic on its origin by the the corresponding Int
in the list. These Ints represents elevenths, so that a
[2,2,...] will scale every Pic by 2/11 .
module: R_Behaviour
scale_rel Args: Vec [Int]
Same as scale, except that the Pics are all scaled using the
Vec as the point of origin.
module: R_Behaviour
twist Args: [Float]
This will rotate every Pic by its corresponding Float from
the list in radians.
module: R_Behaviour
set_color Args: [Int]
This sets each Pic to the color indicated by its
corresponding int in the list.
module: R_Behaviour
rot Args: [Vec] [Float]
This will rotate each Pic around its corresponding Vec by
its corresponding Float in radians.
module: R_Behaviour
big Args: none
Scales every Pic up by scaleunit
module: R_Defaults
huge Args: none
This scales every Pic up by 2*scaleunit
module: R_Defaults
small Args: none
This scales every Pic down by 10/11
module: R_Defaults
tiny Args: none
This scale every Pic down by 5/11
module: R_Defaults
bigger Args: none
This scales every Pic in the list by scaleunit more
than the previous Pic, so that the n-th element is
scaled up by (n-1)*scaleunit
module: R_Defaults
smaller Args: none
This scales every Pic down, so that the n-th element
is scaled down by (n-1)*(10/11)
module: R_Defaults
ccw Args: none
This rotates every Pic by one rotunit more than the
previous Pic, in a counterclockwise fashion.
module: R_Defaults
cw Args: none
This rotates every Pic by one rotunit more than the
previous Pic, in a clockwise fashion.
module: R_Defaults
up Args: none
This moves every Pic up by one unit more than the
Previous Pic, so that the n-th element is moved up
(n-1) units.
module: R_Defaults
down Args: none
This is same as up, but the Pics move down.
module: R_Defaults
right Args: none
This is same as up, but the Pics move right.
module: R_Defaults
left Args: none
This is same as up, but the Pics move left.
module: R_Defaults
\end{verbatim}
\subsection{Functions For Behaviours}
\begin{verbatim}
do Args: Int Behaviour
This takes the first Int elements of the Behaviour and
return that.
module: R_Behaviour
rpt Args: Int Behaviour
This takes an Int and returns a Behaviour of length Int.
However, the n-th Pic-to-Pic in the Behaviour returned
is made up of the first through (n-1)the Pic-to-Pics of
the input list.
module: R_Behaviour
forever Args: Behaviour
This makes a finite Behaviour list an infinite one by
appending the list to itself endlessly.
module: R_Behaviour
apply Args: Behaviour Movie
This takes a Behaviour and applies it to a Movie
module: R_Behaviour
while Args: (Boolean function) Behaviour Movie
As long as the Boolean function evaluates true, this
takes a Behaviour and applies it to a Movie. When it
evaluates to false, no more Pics are produced and
the Movie is cut short there.
module: R_Behaviour
bseq Args: Behaviour Behaviour
This takes two Behaviour and creates one Behaviour made
up of the two inputs applies in sequence.
module: R_Behaviour
bSeq Args: [Behaviour] Behaviour
This takes two Behaviour and creates one Behaviour made
up of the two inputs applies in sequence.
module: R_Behaviour
bpar Args: Behaviour Behaviour
This takes two Behaviour and creates one Behaviour made
up of the two inputs applies in parallel.
module: R_Behaviour
bPar Args: [Behaviour] Behaviour
This takes two Behaviour and creates one Behaviour made
up of the two inputs applies in parallel.
module: R_Behaviour
\end{verbatim}
\section{Creating the Final Movie}
Finally, you have your basic Movies made up of Pictures and Behaviours.
Now you need to combine them into one Movie. The functions that do this
are found in the module R\_Movie. These functions will take a list of
Movies and return a single Movie combining all the Movies in the list.
How they are combined can be controlled to some extent. Usually they are
just overlayed, but they can be put beside one another, or on top of
one another, or put a Vec distance apart.
It is also possible to use a combination of these forms. If you wanted
to overaly M1 and M2, and then put that beside M3, you would do:
\begin{verbatim}
rBESIDE [M3, rOVERLAY [M1,M2] ]
\end{verbatim}
This is acceptable as rOVERLAY will return a single Movie.
\subsection{Movie Combining Functions}
\begin{verbatim}
rABOVE Args: [Movie]
Puts all the Movies into one movie, all above one another.
module: R_Movie
rBESIDE Args: [Movie]
Puts all the Movies into one movie, all beside one another.
module: R_Movie
rBESIDE2 Args: [Movie]
Using their absolute coordinates, puts all the Movies
beside one another.
module: R_Movie
rOVER Args: [Movie]
This lays the Movies on top of one another, centering
each Pic so that they share the same origin.
module: R_Movie
rOVERLAY Args: [Movie]
This lays the Movies on top of one another, centering
each Pic so that they share the smae origin.
module: R_Movie
pUT Args: [Vec] Movie Movie
This takes a list of Vec, and puts each Pic of the
first Movie in the location of the corresponding
Vec on top of the Pic of the second Movie and
returns that list as the new Movie.
module: R_Movie
\end{verbatim}
\section{Displaying Your Movie}
Once you have your function for the Movie defined, you need to output
it in some way. Currently, this is done by outputting characters to a file and
running a C Program in X-Windows that displays the contents of the file
as a graphic in the X system. First of all, you must convert the
Movie variable to a stream of characters. This is done by running
"showm" on the Movie. Be carefull you don't try to convert an infinite list
into characters as the compiler will take awhile to do this. Instead, take
a certain number of frames and convert them with "showm".
\begin{verbatim}
man\_vm = rOVERLAY [man,vm]
man\_vmstring = showm (take 20 man&vm)
\end{verbatim}
Now that you have this string, you need to write it to disk. The
"writetofile" function does this. It takes a characater string(ie [Char] )
as an argument, and then prompts you for a filename. It then writes the
string to the filename. So to put man\_vm string into a file:
\begin{verbatim}
main = writetofile man_vmstring
\end{verbatim}
and run the program, where you will prompted for the filename. Or you could:
\begin{verbatim}
main = writetofile (showm (take 20 man_vm))
\end{verbatim}
to make it more compact.
\subsection{Miscellaneous Usefull Functions}
\begin{verbatim}
inbetween Args: Int Pic Pic
This takes an Int and two Pics and returns a Movie
with Int Pics interpolating between the two Pics.
module: R_Inbetween
tween Args: Int Movie Movie
This takes an Int and two Movies and returns one
Movie made up of the first Movie, Int number of
frames of Pics interpolating between the last
Pic of the first Movie and the first Pic of the
second Movie, followed by the second Movie
module: R_Inbetween
box Args: Int Int Int
This takes 3 Ints, the color, width and height of
the box and returns a Pic of a box
module: R_Shapes
tri Args: Int Vec Vec Vec
This takes a color and three vectors and returns a
Pic of a triangle of that colour with those vertices.
module: R_Shapes
circ Args: Int Int Int
This takes a color, the radius and the number of points
around the circle, and returns a circle with origin at
(0,0).
module: R_Shapes
\end{verbatim}
\pagebreak
\large {\bf Appendix: C Programs to Display on X-Windows}
\\
\\
The program currently used to run these graphics is called "xcshow".
This takes one argument, the name of the file to be run. When run
in X-Windows, it will produce a window with the first Pic. To run it, click
on the left mouse button inside the window. Clicking again will freeze it.
This will keep cycling through the file, replaying again when it hits the
end of the file, until the window is killed.
There is also "xshow" which is used to run the monochrome Movies, as
"xcshow" is used to run the color Movies. As this animation package
only produces color Movies, it isn't too usefull.
\pagebreak
\large {\bf References}
\\
\\
\begin{verbatim}
[ARYA88] "The Formal Analysis of a Functiona Animation System", Kevi Arya,
DPhil,Thesis,Oxford University, Programming Research Group,
April 1988
[ARYA89] "Processes In A Functional Animation System", Kevi Arya,IBM
T.J. Research Center, 1989
[HASK90] "Report On The Programming Language Haskell, Version 1.0",
YALEU/DCS/RR-777,Yale University,1990
\end{verbatim}
\end{document}
|