> || Produce an animation of the cse logo >%include "graphics.m" || Definitions of graphics constructors >%include "myenv.m" || Stuff I think should be in the standard ev=nvironment >%include "vector.m" || Vector abstract data type. A point in 3 dimensions is a triple. > point3d == (num,num,num) Each cube is represented by its centre > cube == point3d The logo is a list of cubes. > cubelist == [cube] The radius of each cube > cr = 0.35 > logooops || Oops! logo except x and z are swapped > = [(4,0,0),(4,0,1),(4,0,2),(4,0,3),(4,0,4), ||Bottom of S > (4,2,0),(4,2,1),(4,2,2),(4,2,3),(4,2,4), ||Middle of S > (4,4,0),(4,4,1),(4,4,2),(4,4,3),(4,4,4), ||Top of S > (4,1,4),(4,3,0), || Rest of S > (3,0,4),(2,0,4),(1,0,4),(0,0,4), || Bottom of E > (3,2,4),(2,2,4),(1,2,4),(0,2,4), || Middle of E > (3,4,4),(2,4,4),(1,4,4),(0,4,4), || Top of E > (3,4,0),(2,4,0),(1,4,0),(0,4,0), || Top of C > (0,4,1),(0,4,3)] || Rest of C We want the origin (0,0,0) to be right in the middle so rotations look better. > logo = [(z-2,y-2,x-2) | (x,y,z) <-logooops] ortho projects 3d points onto plane given unit normal We project (0,1,0) parallel to y axis. > projection == point3d -> point > ortho :: vector -> projection > ortho n (x,y,z) > = (u \$dot p, v' \$dot p) > where v' = normalize(up \$subvec (scalevec (n' \$dot up) n')) > n' = normalize n > u = v' \$cross n' > up = vz, if n = vy > = vy, otherwise > p = v[x,y,z] isodraw draws a list of cubes using an isometric projection. > isodraw :: cubelist -> [sys_message] > isodraw = draw . logopic (v[1,1,1]) logopic is given a 3d point that represent a normal and draws a list of cubes with a parallel projection parallel to that normal. Hidden surface removal courtesy of the painter's algorithm -- we sort the cubes by distance in viewing direction (csort is the sorted cube list) > logopic n cs > = (concat [[Attrib [col] [f] | (col,f) <-zip2 colours (acube c)] | c<-csort]) > where > csort = map snd (sort [(n \$dot v[x,y,z],(x,y,z)) | (x,y,z) <- cs]) > proj = ortho n > acube (cx,cy,cz) > = map (Line.map proj.f) > [[(cx+cr,cy+cr,cz+cr),(cx-cr,cy+cr,cz+cr), > (cx-cr,cy-cr,cz+cr),(cx+cr,cy-cr,cz+cr)], > [(cx+cr,cy+cr,cz+cr),(cx+cr,cy-cr,cz+cr), > (cx+cr,cy-cr,cz-cr),(cx+cr,cy+cr,cz-cr)], > [(cx+cr,cy+cr,cz+cr),(cx+cr,cy+cr,cz-cr), > (cx-cr,cy+cr,cz-cr),(cx-cr,cy+cr,cz+cr)]] > f xs = xs ++ [hd xs] > colours = [Colour 1 0 0, Colour 0 0 1, Colour 1 1 0] logopics is given a number of steps and two view directions and rotates between them. We use a light grey background 'cos that's the default for most www browsers. > logopics n v1 v2 > = [background:(logopic (fromspherical (s1 \$addvec (i \$scalevec sd))) logo) | i<-[0..n]] > where > s1 = tospherical v1 > sd = (1/n) \$scalevec ((tospherical v2) \$subvec s1) > background = fill_polygon 0.75 [(-4.1,-4.1),(4.1,-4.1),(4.1,4.1),(-4.1,4.1)] > logoanimation > = (logopics 7 (v[1,1,1]) vy) ++ tl (logopics 7 vy (v[1,1,1])) ++ > tl (logopics 7 (v[1,1,1]) vz) ++ > tl (logopics 12 vz vx) ++ tl (logopics 7 vx (v[1,1,1]))