git.fiddlerwoaroof.com
Raw Blame History
%  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}