diff --git a/Bih.hs b/Bih.hs
deleted file mode 100644
--- a/Bih.hs
+++ /dev/null
@@ -1,332 +0,0 @@
-module Bih (bih) where
-import Vec
-import Solid
-import Data.List hiding (group) -- for "partition"
-
-import Control.Concurrent.MVar
-import System.IO.Unsafe
-
-
--- Bounding Interval Heirarchy
--- http://en.wikipedia.org/wiki/Bounding_interval_hierarchy
-
-data Bih = Bih {bihbb :: Bbox, bihroot :: BihNode} deriving Show
-data BihNode = BihLeaf !SolidItem 
-             | BihBranch {lmax :: !Flt, rmin :: !Flt, ax :: !Int, 
-                          l :: BihNode, r :: BihNode} deriving Show
-
--- bih construction
-build_leaf :: [(Bbox, SolidItem)] -> BihNode
-build_leaf objs =
- BihLeaf (group (map snd objs))
-
--- tuning parameter that controls threshold for separating
--- large objects from small objects instead of usual left/right
--- sorting 
-max_bih_sa = 0.3 :: Flt
-
-build_rec :: [(Bbox,SolidItem)] -> Bbox -> Bbox -> Int -> BihNode
-build_rec objs nodebox splitbox depth = 
- -- if (null objs) || (null $ tail objs) || 
- --    (null $ tail $ tail objs)
- if length objs < 2
- then build_leaf objs
- else
-  let (Bbox nodeboxp1 nodeboxp2) = nodebox
-      (Bbox splitboxp1 splitboxp2) = splitbox
-      axis  = vmaxaxis (vsub splitboxp2 splitboxp1)
-      bbmin = va splitboxp1 axis
-      bbmax = va splitboxp2 axis
-      candidate = (bbmin + bbmax) * 0.5
-  in
-   if candidate > (va nodeboxp2 axis) then
-    build_rec objs nodebox 
-              (Bbox splitboxp1 (vset splitboxp2 axis candidate)) 
-              depth
-   else
-    if candidate < (va nodeboxp1 axis) then
-     build_rec objs nodebox (
-               Bbox (vset splitboxp1 axis candidate) splitboxp2) 
-               depth
-    else
-     -- not sure if this is a big win
-     let nbsa = bbsa nodebox
-         (big,small) = partition (\ (bb,_) -> 
-                                   (bbsa bb) > (nbsa * max_bih_sa)) objs
-     in 
-      if (not $ null big) && ((length big) < ((length small)*2))
-      then (BihBranch (va nodeboxp2 0) (va nodeboxp1 0) 0
-                      (build_rec big nodebox splitbox (depth+1))
-                      (build_rec small nodebox splitbox (depth+1)) )
-      else
-       let (l,r) = partition (\((Bbox bbp1 bbp2),_)-> 
-                               (((va bbp1 axis)+(va bbp2 axis))*0.5) 
-                                 < candidate ) objs
-           lmax = foldl fmax (-infinity) (map (\((Bbox _ p2),_) -> va p2 axis) l)
-           rmin = foldl fmin   infinity  (map (\((Bbox p1 _),_) -> va p1 axis) r)
-           (lsplit,rsplit) = bbsplit splitbox axis candidate
-           lnb  = (Bbox nodeboxp1 (vset nodeboxp2 axis lmax))
-           rnb  = (Bbox (vset nodeboxp1 axis rmin) nodeboxp2)
-       in
-        -- stop if there's no progress being made
-        if ((null l) && (rmin <= bbmin)) ||
-           ((null r) && (lmax >= bbmax))
-        then build_leaf objs
-        else
-         (BihBranch (lmax+delta) (rmin-delta) axis
-                    (build_rec l lnb lsplit (depth+1))
-                    (build_rec r rnb rsplit (depth+1)) )
-
-bih :: [SolidItem] -> SolidItem
-bih [] = SolidItem Void
--- bih (sld:[]) = sld  -- sometimes we'd like to be able to use a
-                       -- single object bih just for its aabb
-bih slds =
- let objs = map (\x -> ((bound x),x)) (flatten_group slds)
-     bb   = foldl bbjoin empty_bbox (map (\(b,_)->b) objs)
-     root = build_rec objs bb bb 0
-     (Bbox (Vec p1x p1y p1z) (Vec p2x p2y p2z)) = bb
- in
-  if p1x == (-infinity) || p1y == (-infinity) || p1z == (-infinity) ||
-     p2x == infinity    || p2y == infinity    || p2z == infinity
-  then
-   error $ "bih: infinite bounding box " ++ (show objs)
-  else
-   SolidItem (Bih bb root)
-
-rayint_bih :: Bih -> Ray -> Flt -> Texture -> Rayint 
-rayint_bih (Bih bb root) r d t =
- let Ray orig dir = r
-     dir_rcp = vrcp dir
-     Interval near far = bbclip r bb
-     traverse (BihLeaf s) near far = rayint s r (fmin d far) t
-     traverse (BihBranch lsplit rsplit axis l r) near far =
-       let dirr = va dir_rcp axis
-           o    = va orig axis
-           dl   = (lsplit - o) * dirr
-           dr   = (rsplit - o) * dirr
-       in  
-           if near > far 
-           then RayMiss
-           else
-            if dirr > 0
-            then 
-             (nearest
-              (if near < dl
-               then traverse l near (fmin dl far)
-               else RayMiss)
-              (if dr < far
-               then traverse r (fmax dr near) far
-               else RayMiss))
-            else
-             (nearest
-              (if near < dr
-               then traverse r near (fmin dr far)
-               else RayMiss)
-              (if dl < far
-               then traverse l (fmax dl near) far
-               else RayMiss))
- in
-  traverse root near far
-
-rayint_debug_bih :: Bih -> Ray -> Flt -> Texture -> (Rayint,Int) 
-rayint_debug_bih (Bih bb root) r d t =
- let Ray orig dir = r
-     dir_rcp = vrcp dir
-     Interval near far = bbclip r bb
-     traverse (BihLeaf s) near far = rayint_debug s r (fmin d far) t
-     traverse (BihBranch lsplit rsplit axis l r) near far =
-       let dirr = va dir_rcp axis
-           o    = va orig axis
-           dl   = (lsplit - o) * dirr
-           dr   = (rsplit - o) * dirr
-       in 
-         debug_wrap 
-          (if near > far 
-           then (RayMiss,0)
-           else
-            if dirr > 0
-            then 
-             (nearest_debug
-              (if near < dl
-               then traverse l near (fmin dl far)
-               else (RayMiss,0))
-              (if dr < far
-               then traverse r (fmax dr near) far
-               else (RayMiss,0)))
-            else
-             (nearest_debug
-              (if near < dr
-               then traverse r near (fmin dr far)
-               else (RayMiss,0))
-              (if dl < far
-               then traverse l (fmax dl near) far
-               else (RayMiss,0))))
-          1  
- in
-  traverse root near far
-
--- This is unwieldy, but the performance gains
--- make it worthwhile.  By testing 4 rays against 
--- each cell, we (theoretically) do ~1/4 the 
--- memory accesses. 
-
--- One simplifying assumption we make that adds a 
--- little bit of overhead:  If one ray hits a cell, 
--- we act as though they all do.  For that reason,
--- this only works well with coherent rays.
-
-packetint_bih :: Bih -> Ray -> Ray -> Ray -> Ray -> Flt -> Texture -> PacketResult
-packetint_bih (Bih bb root) !r1 !r2 !r3 !r4 !d t =
- let bih = Bih bb root
-     Ray orig1 dir1 = r1
-     Ray orig2 dir2 = r2
-     Ray orig3 dir3 = r3
-     Ray orig4 dir4 = r4
-
-     dir_rcp1 = vrcp dir1
-     dir_rcp2 = vrcp dir2
-     dir_rcp3 = vrcp dir3
-     dir_rcp4 = vrcp dir4
- in
-  -- We want all the ray components to have
-  -- at least the same sign.
-  if not $ veqsign dir_rcp1 dir_rcp2 &&
-           veqsign dir_rcp1 dir_rcp3 &&
-           veqsign dir_rcp1 dir_rcp4
-  then
-   PacketResult (rayint bih r1 d t)
-                (rayint bih r2 d t)
-                (rayint bih r3 d t)
-                (rayint bih r4 d t)
-  else 
-   let Interval near1 far1 = bbclip r1 bb
-       Interval near2 far2 = bbclip r2 bb
-       Interval near3 far3 = bbclip r3 bb
-       Interval near4 far4 = bbclip r4 bb
-
-       near = fmin (fmin near1 near2) (fmin near3 near4)
-       far =  fmax (fmax far1  far2)  (fmax far3  far4)
-
-       traverse (BihLeaf s) near far = packetint s r1 r2 r3 r4 (fmin d far) t
-       traverse (BihBranch lsplit rsplit axis l r) near far =
-        if near > far 
-        then packetmiss
-        else
-         let dirr1 = va dir_rcp1 axis
-             dirr2 = va dir_rcp2 axis
-             dirr3 = va dir_rcp3 axis
-             dirr4 = va dir_rcp4 axis
-                     
-             o1    = va orig1 axis
-             o2    = va orig2 axis
-             o3    = va orig3 axis
-             o4    = va orig4 axis
-
-             dl1   = (lsplit - o1) * dirr1
-             dl2   = (lsplit - o2) * dirr2
-             dl3   = (lsplit - o3) * dirr3
-             dl4   = (lsplit - o4) * dirr4
-
-             dr1   = (rsplit - o1) * dirr1
-             dr2   = (rsplit - o2) * dirr2
-             dr3   = (rsplit - o3) * dirr3
-             dr4   = (rsplit - o4) * dirr4
-
-         in  
-          if dirr1 > 0  -- true for all, since signs match
-          then 
-           let dl = fmax4 dl1 dl2 dl3 dl4
-               dr = fmin4 dr1 dr2 dr3 dr4
-           in
-            (nearest_packetresult
-             (if near < dl
-              then traverse l near (fmin dl far)
-              else packetmiss)
-             (if dr < far
-              then traverse r (fmax dr near) far
-              else packetmiss))
-          else
-           let dl = fmin4 dl1 dl2 dl3 dl4
-               dr = fmax4 dr1 dr2 dr3 dr4
-           in
-            (nearest_packetresult
-             (if near < dr
-              then traverse r near (fmin dr far)
-              else packetmiss)
-             (if dl < far
-              then traverse l (fmax dl near) far
-              else packetmiss))
-
-   in
-    traverse root near far
-
-shadow_bih :: Bih -> Ray -> Flt -> Bool
-shadow_bih (Bih bb root) r d =
- let (Ray orig dir) = r
-     dir_rcp = vrcp dir
-     Interval near far = bbclip r bb
-     traverse (BihLeaf s) near far = shadow s r (fmin d far)
-     traverse (BihBranch lsplit rsplit axis l r) near far =
-      let dirr = va dir_rcp axis
-          o  = va orig axis
-          dl = (lsplit - o) * dirr
-          dr = (rsplit - o) * dirr
-      in  
-          if near > far 
-          then False
-          else
-           if dirr > 0
-           then
-            ((if near < dl
-              then traverse l near (fmin dl far)
-              else False) 
-             ||
-             (if dr < far
-              then traverse r (fmax dr near) far
-              else False))
-           else
-            ((if near < dr
-              then traverse r near (fmin dr far)
-              else False)
-             ||
-             (if dl < far
-              then traverse l (fmax dl near) far
-              else False))
-
- in traverse root near far
-
-inside_bih :: Bih -> Vec -> Bool
-inside_bih (Bih (Bbox (Vec x1 y1 z1) (Vec x2 y2 z2)) root) pt =
- let (Vec x y z) = pt
-     traverse (BihLeaf s) = inside s pt
-     traverse (BihBranch lsplit rsplit axis l r) =
-       let o = va pt axis
-       in (if o < lsplit
-           then (traverse l)
-           else False) 
-          ||
-          (if o > rsplit 
-           then (traverse r)
-           else False)
- in
-  (x > x1) && (x < x2) && 
-  (y > y1) && (y < y2) && 
-  (z > z1) && (z < z2) && (traverse root)
-
-bound_bih :: Bih -> Bbox
-bound_bih (Bih bb root) = bb
-
-primcount_bih :: Bih -> Pcount
-primcount_bih (Bih bb root) = pcadd (bihcount root) pcsinglebound
- where bihcount (BihLeaf s) = primcount s
-       bihcount (BihBranch _ _ _ l r) = pcadd (pcadd (bihcount l) (bihcount r)) pcsinglebound
-
-instance Solid Bih where
- rayint = rayint_bih
- rayint_debug = rayint_debug_bih
- packetint = packetint_bih
- shadow = shadow_bih
- inside = inside_bih
- bound = bound_bih
- primcount = primcount_bih
diff --git a/Bound.hs b/Bound.hs
deleted file mode 100644
--- a/Bound.hs
+++ /dev/null
@@ -1,73 +0,0 @@
-module Bound (bound_object) where
-import Vec
-import Solid
-
--- Bounding objects: we can use any object as a bounding
--- object for any other object; if a ray misses the
--- bounding object, we can assume it missed the bounded
--- object as well.  Unlike bih, setting up bounds is a manual
--- process.  It is important that the bounded object is
--- completely inside the bounding object.
-
--- The bounding object should have a cheaper intersection test than
--- the bounded object for this to be useful.
-
--- The first SolidItem is the bounding object, the second
--- is the bounded object.
-data Bound = Bound SolidItem SolidItem deriving Show
-
-bound_object :: SolidItem -> SolidItem -> SolidItem
-bound_object a b = SolidItem $ Bound a b
-
-rayint_bound :: Bound -> Ray -> Flt -> Texture -> Rayint
-rayint_bound (Bound sa sb) r d t =
- let (Ray orig _) = r
- in if inside sa orig || shadow sa r d
-    then rayint sb r d t
-    else RayMiss
-
-rayint_debug_bound :: Bound -> Ray -> Flt -> Texture -> (Rayint,Int)
-rayint_debug_bound (Bound sa sb) r d t =
- let (Ray orig _) = r
- in if inside sa orig || shadow sa r d
-    then (debug_wrap (rayint_debug sb r d t) 1)
-    else (RayMiss,0)
-
-shadow_bound :: Bound -> Ray -> Flt -> Bool
-shadow_bound (Bound sa sb) r d =
- let (Ray orig _ ) = r
- in if inside sa orig || shadow sa r d
-    then shadow sb r d
-    else False
-
-inside_bound :: Bound -> Vec -> Bool
-inside_bound (Bound sa sb) pt = inside sa pt && inside sb pt
-
--- if this is too slow, we could just take the bounding box for sa
-bound_bound :: Bound -> Bbox
-bound_bound (Bound sa sb) = bboverlap (bound sa) (bound sb)
-
--- remove bounding objects when we flatten transformations
--- (this is so that the accelleration structure can 
--- build an automatic bounding hierarchy rather than
--- a manual one)
-
-transform_leaf_bound :: Bound -> [Xfm] -> SolidItem
-transform_leaf_bound (Bound sa sb) xfms =
- transform_leaf sb xfms
-
-flatten_transform_bound :: Bound -> [SolidItem]
-flatten_transform_bound (Bound sa sb) = flatten_transform sb
-
-primcount_bound :: Bound -> Pcount
-primcount_bound (Bound sa sb) = pcadd (asbound (primcount sa)) (primcount sb)
-
-instance Solid Bound where
- rayint = rayint_bound
- rayint_debug = rayint_debug_bound
- shadow = shadow_bound
- inside = inside_bound
- bound = bound_bound
- flatten_transform = flatten_transform_bound
- transform_leaf = transform_leaf_bound
- primcount = primcount_bound
diff --git a/Box.hs b/Box.hs
deleted file mode 100644
--- a/Box.hs
+++ /dev/null
@@ -1,68 +0,0 @@
-module Box (box) where
-import Vec
-import Solid
-
--- Simple, axis-aligned bounding box defined with two points at opposing corners.
-
-data Box = Box !Bbox deriving Show
-
-box :: Vec -> Vec -> SolidItem
-box (Vec x1 y1 z1) (Vec x2 y2 z2) =
- SolidItem (Box (Bbox (Vec (fmin x1 x2) (fmin y1 y2) (fmin z1 z2))
-                      (Vec (fmax x1 x2) (fmax y1 y2) (fmax z1 z2))))
-
--- this could be optimized a bit more
-rayint_box :: Box -> Ray -> Flt -> Texture -> Rayint
-rayint_box (Box (Bbox (Vec p1x p1y p1z) (Vec p2x p2y p2z))) r d t =
- let (Ray orig dir) = r
-     (Vec ox oy oz) = orig
-     (Vec dx dy dz) = dir
-     dxrcp = 1/dx
-     dyrcp = 1/dy
-     dzrcp = 1/dz
-     Interval inx outx = if dx > 0 
-                         then Interval ((p1x-ox)*dxrcp) ((p2x-ox)*dxrcp)
-                         else Interval ((p2x-ox)*dxrcp) ((p1x-ox)*dxrcp)
-     Interval iny outy = if dy > 0
-                         then Interval ((p1y-oy)*dyrcp) ((p2y-oy)*dyrcp)
-                         else Interval ((p2y-oy)*dyrcp) ((p1y-oy)*dyrcp)
-     Interval inz outz = if dz > 0
-                         then Interval ((p1z-oz)*dzrcp) ((p2z-oz)*dzrcp)
-                         else Interval ((p2z-oz)*dzrcp) ((p1z-oz)*dzrcp)
-     lastin   = (fmax3 inx iny inz)
-     firstout = (fmin3 outx outy outz)
- in if lastin > firstout || firstout < 0 || lastin > d
-    then RayMiss
-    else 
-     let n = if inx == lastin 
-             then if dx > 0 then nvx else vx
-             else if iny == lastin
-                  then if dy > 0 then nvy else vy
-                  else if dz > 0 then nvz else vz
-         norm = if lastin > 0 then n else vinvert n
-         hitdepth = fmax 0 lastin
-     in
-         RayHit hitdepth (vscaleadd orig dir hitdepth) norm t 
-
-shadow_box :: Box -> Ray -> Flt -> Bool
-shadow_box (Box box) r d =
- let Interval near far = bbclip r box 
- in
-  if (near > far) || far <= 0 || far > d
-  then False
-  else True
-
-inside_box :: Box -> Vec -> Bool
-inside_box (Box (Bbox (Vec x1 y1 z1) (Vec x2 y2 z2))) (Vec x y z) =
- x > x1 && x < x2 && 
- y > y1 && y < y2 && 
- z > z1 && z < z2
-
-bound_box :: Box -> Bbox
-bound_box (Box box) = box
-
-instance Solid Box where
- rayint = rayint_box
- shadow = shadow_box
- inside = inside_box
- bound = bound_box
diff --git a/COPYING b/COPYING
deleted file mode 100644
--- a/COPYING
+++ /dev/null
@@ -1,340 +0,0 @@
-	    GNU GENERAL PUBLIC LICENSE
-		       Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-			    Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users.  This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it.  (Some other Free Software Foundation software is covered by
-the GNU Lesser General Public License instead.)  You can apply it to
-your programs, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
-  To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
-  For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have.  You must make sure that they, too, receive or can get the
-source code.  And you must show them these terms so they know their
-rights.
-
-  We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
-  Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software.  If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
-  Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary.  To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.
-
-		    GNU GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License.  The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language.  (Hereinafter, translation is included without limitation in
-the term "modification".)  Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
-  1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
-  2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) You must cause the modified files to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    b) You must cause any work that you distribute or publish, that in
-    whole or in part contains or is derived from the Program or any
-    part thereof, to be licensed as a whole at no charge to all third
-    parties under the terms of this License.
-
-    c) If the modified program normally reads commands interactively
-    when run, you must cause it, when started running for such
-    interactive use in the most ordinary way, to print or display an
-    announcement including an appropriate copyright notice and a
-    notice that there is no warranty (or else, saying that you provide
-    a warranty) and that users may redistribute the program under
-    these conditions, and telling the user how to view a copy of this
-    License.  (Exception: if the Program itself is interactive but
-    does not normally print such an announcement, your work based on
-    the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
-    a) Accompany it with the complete corresponding machine-readable
-    source code, which must be distributed under the terms of Sections
-    1 and 2 above on a medium customarily used for software interchange; or,
-
-    b) Accompany it with a written offer, valid for at least three
-    years, to give any third party, for a charge no more than your
-    cost of physically performing source distribution, a complete
-    machine-readable copy of the corresponding source code, to be
-    distributed under the terms of Sections 1 and 2 above on a medium
-    customarily used for software interchange; or,
-
-    c) Accompany it with the information you received as to the offer
-    to distribute corresponding source code.  (This alternative is
-    allowed only for noncommercial distribution and only if you
-    received the program in object code or executable form with such
-    an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it.  For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable.  However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-  4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License.  Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
-  5. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Program or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
-  6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
-  7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-  8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded.  In such case, this License incorporates
-the limitation as if written in the body of this License.
-
-  9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time.  Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation.  If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
-  10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission.  For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this.  Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
-			    NO WARRANTY
-
-  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
-  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
-		     END OF TERMS AND CONDITIONS
-
-	    How to Apply These Terms to Your New Programs
-
-  If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
-  To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License along
-    with this program; if not, write to the Free Software Foundation, Inc.,
-    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
-    Gnomovision version 69, Copyright (C) year name of author
-    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
-    This is free software, and you are welcome to redistribute it
-    under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License.  Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
-  `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
-  <signature of Ty Coon>, 1 April 1989
-  Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs.  If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library.  If this is what you want to do, use the GNU Lesser General
-Public License instead of this License.
-
diff --git a/Clr.hs b/Clr.hs
deleted file mode 100644
--- a/Clr.hs
+++ /dev/null
@@ -1,41 +0,0 @@
-module Clr where
-
-type CFlt = Double
-data Color = Color {r,g,b :: !CFlt} deriving Show
-
-c_black = Color 0 0 0
-c_white = Color 1 1 1
-c_red   = Color 1 0 0
-c_green = Color 0 1 0
-c_blue  = Color 0 0 1
-
-cadd :: Color -> Color -> Color
-cadd (Color r1 g1 b1) (Color r2 g2 b2) =
- Color (r1+r2) (g1+g2) (b1+b2)
-
-cdiv :: Color -> CFlt -> Color
-cdiv c1 div =
- cscale c1 (1/div)
-
-cscale :: Color -> CFlt -> Color
-cscale (Color r g b) mul =
- Color (r * mul)
-       (g * mul)
-       (b * mul)
-
-cmul :: Color -> Color -> Color
-cmul (Color r1 g1 b1) (Color r2 g2 b2) =
- Color (r1*r2) (g1*g2) (b1*b2)
-
-cavg :: Color -> Color -> Color
-cavg c1 c2 = cscale (cadd c1 c2) 0.5
-
-cscaleadd :: Color -> Color -> CFlt -> Color
-cscaleadd (Color r1 g1 b1) (Color r2 g2 b2) mul =
- Color (r1+(r2*mul)) (g1+(g2*mul)) (b1+(b2*mul))
-
-cclamp :: Color -> Color
-cclamp (Color r g b) = 
- Color (if r > 0.0 then r else 0.0)
-       (if g > 0.0 then g else 0.0)
-       (if b > 0.0 then b else 0.0)
diff --git a/Cone.hs b/Cone.hs
deleted file mode 100644
--- a/Cone.hs
+++ /dev/null
@@ -1,262 +0,0 @@
-module Cone (disc, cone, cylinder) where
-import Vec
-import Solid
-import Sphere -- for disc bounding box
-
--- We define "Cone", "Cylinder", and "Disc" in this module.
--- A Cone is really a tapered cylinder with a different radius
--- at each end, though the underlying representation is a
--- clipped cone.
-
--- We represent Cylinders and Cones as transformations of axis-aligned
--- primitives.
-
--- Todo: cylinder shadow test
-
-data Disc = Disc !Vec !Vec !Flt deriving Show -- position, normal, r*r
-data Cylinder = Cylinder !Flt !Flt !Flt deriving Show -- radius height1 height2
-data Cone = Cone !Flt !Flt !Flt !Flt deriving Show -- r clip1 clip2 height
-
--- CONSTRUCTORS --
-
-disc :: Vec -> Vec -> Flt -> SolidItem
-disc pos norm r =
- SolidItem $ Disc pos norm (r*r)
-
-cylinder_z :: Flt -> Flt -> Flt -> SolidItem
-cylinder_z r h1 h2 = SolidItem (Cylinder r h1 h2)
-
-cone_z :: Flt -> Flt -> Flt -> Flt -> SolidItem
-cone_z r h1 h2 height = SolidItem (Cone r h1 h2 height)
-
--- construct a general cylinder from p1 to p2 with radius r
-cylinder :: Vec -> Vec -> Flt -> SolidItem
-cylinder p1 p2 r =
- let axis = vsub p2 p1
-     len  = vlen axis
-     ax1  = vscale axis (1/len)
-     (ax2,ax3) = orth ax1 
- in transform (cylinder_z r 0 len)
-              [ (xyz_to_uvw ax2 ax3 ax1),
-                (translate p1) ]
-                        
--- similar for cone
-cone :: Vec -> Flt -> Vec -> Flt -> SolidItem
-cone p1 r1 p2 r2 =
- if r1 < r2 
- then cone p2 r2 p1 r1
- else if r1-r2 < delta
-      then cylinder p1 p2 r2
-      else
-        let axis = vsub p2 p1
-            len  = vlen axis
-            ax1  = vscale axis (1/len)
-            (ax2,ax3) = orth ax1 
-            height = (r1*len)/(r1-r2) -- distance to end point
-        in
-         transform (cone_z r1 0 len height)
-                   [ (xyz_to_uvw ax2 ax3 ax1),
-                     (translate p1) ]                 
-
-rayint_disc :: Disc -> Ray -> Flt -> Texture -> Rayint
-rayint_disc (Disc point norm radius_sqr) r d t =
- let (Ray orig dir) = r
-     dist = plane_int_dist r point norm 
- in if dist < 0 || dist > d 
-    then RayMiss
-    else let pos = vscaleadd orig dir dist
-             offset = vsub pos point
-         in 
-          if (vdot offset offset) > radius_sqr
-          then RayMiss
-          else RayHit dist pos norm t
-
-shadow_disc :: Disc -> Ray -> Flt -> Bool
-shadow_disc (Disc point norm radius_sqr) r d =
- let (Ray orig dir) = r
-     dist = plane_int_dist r point norm 
- in if dist < 0 || dist > d 
-    then False
-    else let pos = vscaleadd orig dir dist
-             offset = vsub pos point
-         in 
-          if (vdot offset offset) > radius_sqr
-          then False
-          else True
-
-bound_disc :: Disc -> Bbox
-bound_disc (Disc pos norm rsqr) =
- bound (sphere pos (sqrt rsqr))
-
-instance Solid Disc where
- rayint = rayint_disc
- shadow = shadow_disc
- inside (Disc _ _ _) _ = False
- bound = bound_disc
-
-
-rayint_cylinder :: Cylinder -> Ray -> Flt -> Texture -> Rayint
-rayint_cylinder (Cylinder r h1 h2) (Ray orig dir) d t =
- let Vec ox oy oz = orig
-     Vec dx dy dz = dir
-     a = dx*dx + dy*dy
-     b = 2*(dx*ox + dy*oy)
-     c = ox*ox + oy*oy - r*r
-     disc = b*b - 4*a*c
- in  if disc < 0 
-     then RayMiss
-     else 
-      let discsqrt = sqrt disc 
-          q = if b < 0 
-              then (b-discsqrt)*(-0.5)
-              else (b+discsqrt)*(-0.5)
-          t0' = q/a
-          t1' = c/q
-          t0  = fmin t0' t1'
-          t1  = fmax t0' t1'
-      in if t1 < 0 || t0 > d 
-         then RayMiss
-         else let dist = if t0 < 0
-                         then t1
-                         else t0
-              in if dist < 0 || dist > d
-                 then RayMiss
-                 else let pos = vscaleadd orig dir dist
-                          Vec posx posy posz = pos
-                      in if posz > h1 && posz < h2
-                         then RayHit dist pos (Vec (posx/r) (posy/r) 0) t
-                         else if dz > 0 -- ray pointing up from bottom
-                              then if oz < h1
-                                   then rayint_disc (Disc (Vec 0 0 h1) nvz (r*r)) (Ray orig dir) d t
-                                   --then rayint_aadisc h1 r (Ray orig dir) d t
-                                   else RayMiss
-                              else if oz > h2
-                                   then rayint_disc (Disc (Vec 0 0 h2) vz (r*r)) (Ray orig dir) d t
-                                   --rayint_aadisc h2 r (Ray orig dir) d t -- todo: fix normal
-                                   else RayMiss
-
-inside_cylinder :: Cylinder -> Vec -> Bool
-inside_cylinder (Cylinder r h1 h2) (Vec x y z) =
- z > h1 && z < h2 && x*x + y*y < r*r
-  
-bound_cylinder :: Cylinder -> Bbox
-bound_cylinder (Cylinder r h1 h2) =
- Bbox (Vec (-r) (-r) h1) (Vec r r h2)
-
-instance Solid Cylinder where
- rayint = rayint_cylinder
- inside = inside_cylinder
- bound = bound_cylinder
-
-
-rayint_cone :: Cone -> Ray -> Flt -> Texture -> Rayint
-rayint_cone (Cone r clip1 clip2 height) (Ray orig dir) d t =
- let Vec ox oy oz = orig
-     Vec dx dy dz = dir
-     k' = (r/height)
-     k = k'*k'
-     a = dx*dx + dy*dy - k*dz*dz
-     b = 2*(dx*ox + dy*oy - k*dz*(oz-height))
-     c = ox*ox + oy*oy - k*(oz-height)*(oz-height)
-     disc = b*b - 4*a*c
- in if disc < 0
-    then RayMiss
-    else
-     let discsqrt = sqrt disc
-         q = if b < 0
-             then (b-discsqrt)*(-0.5)
-             else (b+discsqrt)*(-0.5)
-         t0' = q/a
-         t1' = c/q
-         t0  = fmin t0' t1'
-         t1  = fmax t0' t1'
-     in if t1 < 0 || t0 > d 
-        then RayMiss
-        else let dist = if t0 < 0
-                        then t1
-                        else t0
-             in if dist < 0 || dist > d
-                then RayMiss
-                else
-                 let pos = vscaleadd orig dir dist
-                     Vec posx posy posz = pos
-                 in if posz > clip1 && posz < clip2
-                    then let invhyp = 1 / (sqrt (height*height + r*r))
-                             up  = r * invhyp
-                             out = height * invhyp
-                             r_ = sqrt (posx*posx + posy*posy)
-                             correction = (out)/(r_)
-                         in RayHit dist pos (Vec (posx*correction) (posy*correction) up) t
-                    else 
-                     if dz > 0 -- ray pointing up from bottom
-                     then if oz < clip1
-                          then rayint_disc (Disc (Vec 0 0 clip1) nvz (r*r)) (Ray orig dir) d t
-                          else RayMiss
-                     else if oz > clip2
-                          then let r2 = r*(1-((clip2-clip1)/(height)))
-                               in rayint_disc (Disc (Vec 0 0 clip2) vz (r2*r2)) (Ray orig dir) d t
-                                   --rayint_aadisc clip2 r2 (Ray orig dir) d t
-                          else RayMiss
-                             -- then rayint_aadisc clip1 r (Ray orig dir) d t
-                             -- else RayMiss -- rayint_aadisc clip2 
-                                              --   (r*((clip2-clip1)/height)) 
-                                               --  (Ray orig dir) d t -- todo: fix normal
-
-shadow_cone :: Cone -> Ray -> Flt -> Bool
-shadow_cone (Cone r clip1 clip2 height) (Ray orig dir) d =
- let Vec ox oy oz = orig
-     Vec dx dy dz = dir
-     k' = (r/height)
-     k = k'*k'
-     a = dx*dx + dy*dy - k*dz*dz
-     b = 2*(dx*ox + dy*oy - k*dz*(oz-height))
-     c = ox*ox + oy*oy - k*(oz-height)*(oz-height)
-     disc = b*b - 4*a*c
- in if disc < 0
-    then False
-    else
-     let discsqrt = sqrt disc
-         q = if b < 0
-             then (b-discsqrt)*(-0.5)
-             else (b+discsqrt)*(-0.5)
-         t0' = q/a
-         t1' = c/q
-         t0  = fmin t0' t1'
-         t1  = fmax t0' t1'
-     in if t1 < 0 || t0 > d 
-        then False
-        else let dist = if t0 < 0
-                        then t1
-                        else t0
-             in if dist < 0 || dist > d
-                then False
-                else
-                 let pos = vscaleadd orig dir dist
-                     Vec posx posy posz = pos
-                 in if posz > clip1 && posz < clip2
-                    then True
-                    else 
-                     if dz > 0 -- ray pointing up from bottom
-                     then if oz < clip1
-                          then shadow (Disc (Vec 0 0 clip1) nvz (r*r)) (Ray orig dir) d
-                          else False
-                     else if oz > clip2
-                          then let r2 = r*(1-((clip2-clip1)/(height)))
-                               in shadow (Disc (Vec 0 0 clip2) vz (r2*r2)) (Ray orig dir) d
-                          else False
-
-
-inside_cone :: Cone -> Vec -> Bool
-inside_cone (Cone rbase h1 h2 height) (Vec x y z) =
- let r = rbase*(1-(((z-h1)/height)))
- in z > h1 && z < h2 && x*x + y*y < r*r
-
-bound_cone :: Cone -> Bbox
-bound_cone (Cone r h1 h2 height) =
- Bbox (Vec (-r) (-r) h1) (Vec r r h2)
-
-instance Solid Cone where
- rayint = rayint_cone
- shadow = shadow_cone
- inside = inside_cone
- bound  = bound_cone
diff --git a/Csg.hs b/Csg.hs
deleted file mode 100644
--- a/Csg.hs
+++ /dev/null
@@ -1,111 +0,0 @@
-module Csg (difference, intersection) where
-import Vec
-import Solid
-import Data.List
-
--- Constructive Solid Geometry
--- (boolean operations for solids)
-
--- todo: implement shadow tests
-
-data Difference = Difference SolidItem SolidItem deriving Show
-data Intersection = Intersection [SolidItem] deriving Show
-
---Difference--
--- csg of object b subtracted from object a --
-difference :: SolidItem -> SolidItem -> SolidItem
-difference a b = SolidItem $ Difference a b
-
-rayint_difference :: Difference -> Ray -> Flt -> Texture -> Rayint
-rayint_difference dif r d t =
- let Difference sa sb = dif
-     Ray orig dir = r
-     ria = rayint sa r d t
- in
-  case ria of
-   RayMiss -> RayMiss
-   RayHit ad ap an at ->
-    if inside sb orig 
-    then
-     case rayint sb r d t of
-      RayMiss -> RayMiss 
-      RayHit bd bp bn bt ->
-       if bd < ad 
-       then if inside sa bp 
-            then RayHit bd bp (vinvert bn) bt
-            else rayint_advance (SolidItem dif) r d t bd
-       else rayint_advance (SolidItem dif) r d t bd
-    else 
-     if inside sb ap
-     then rayint_advance (SolidItem dif) r d t ad
-     else RayHit ad ap an at
-
-
---Intersection--
-intersection :: [SolidItem] -> SolidItem
-intersection slds = SolidItem $ Intersection slds
-
--- fixme: there's some numerical instability near edges
-rayint_intersection :: Intersection -> Ray -> Flt -> Texture -> Rayint
-rayint_intersection (Intersection slds) r d t =
- let (Ray orig dir) = r 
- in
-  if null slds || d < 0
-  then RayMiss
-  else 
-   let s = head slds 
-   in case tail slds of
-       [] -> rayint s r d t
-       ss -> if inside s orig
-             then case rayint s r d t of 
-                   RayMiss -> rayint (Intersection ss) r d t
-                   RayHit sd sp sn st -> 
-                    case rayint (Intersection ss) r sd t of
-                     RayMiss -> rayint_advance (SolidItem (Intersection slds)) 
-                                               r d t sd 
-                     hit -> hit
-             else case rayint s r d t of
-                   RayMiss -> RayMiss
-                   RayHit sd sp sn st ->
-                    if inside (Intersection ss) sp
-                    then RayHit sd sp sn st
-                    else rayint_advance (SolidItem (Intersection slds))
-                                        r d t sd
-
-inside_difference :: Difference -> Vec -> Bool
-inside_difference (Difference sa sb) pt =
- (inside sa pt) && (not $ inside sb pt)
-
--- note: inside is True for an empty intersection.
--- this is actually the preferred semantics in 
--- some cases, strange as it may seem.
-inside_intersection :: Intersection -> Vec -> Bool
-inside_intersection (Intersection slds) pt =
- foldl' (&&) True (map (\x -> inside x pt) slds) 
-
-bound_difference :: Difference -> Bbox
-bound_difference (Difference sa sb) = bound sa
-
-bound_intersection :: Intersection -> Bbox
-bound_intersection (Intersection slds) =
- if null slds 
- then empty_bbox
- else foldl' bboverlap everything_bbox (map bound slds)
-
-primcount_difference :: Difference -> Pcount
-primcount_difference (Difference sa sb) = pcadd (primcount sa) (primcount sb)
-
-primcount_intersection :: Intersection -> Pcount
-primcount_intersection (Intersection slds) = foldl (pcadd) pcnone (map primcount slds)
-
-instance Solid Difference where
- rayint = rayint_difference
- inside = inside_difference
- bound  = bound_difference
- primcount = primcount_difference
-
-instance Solid Intersection where
- rayint = rayint_intersection
- inside = inside_intersection
- bound  = bound_intersection
- primcount = primcount_intersection
diff --git a/Glome.hs b/Glome.hs
--- a/Glome.hs
+++ b/Glome.hs
@@ -1,6 +1,10 @@
-import Scene
-import Trace
-import Spd
+{-# OPTIONS_GHC -fexcess-precision #-}
+{-# OPTIONS_GHC -funbox-strict-fields #-}
+{-# LANGUAGE BangPatterns #-}
+
+import Data.Glome.Scene as Scene
+import Data.Glome.Trace as Trace
+import Data.Glome.Spd as Spd
 import TestScene
 import Graphics.Rendering.OpenGL
 import Graphics.UI.GLUT as GLUT
@@ -13,6 +17,7 @@
 import System.Console.GetOpt
 import Data.Maybe( fromMaybe )
 -- import OpenEXR -- work in progress
+import Unsafe.Coerce
 
 -- import Debug.Trace
 -- import Data.ByteString 
@@ -44,9 +49,12 @@
 
 -- convert trace result to 
 -- appropriate float type for OpenGL
-fc :: Flt -> Float
+fc :: Flt -> GLfloat
 fc x = realToFrac x
 
+--fc :: Flt -> GLfloat
+--fc = unsafeCoerce
+
 -- given a block of screen coordinates, return list of pixels
 gen_pixel_list :: Flt -> Flt -> Flt -> Flt -> Flt -> Flt -> Scene -> [(Flt,Flt,Flt,Flt,Flt,Flt)]
 gen_pixel_list curx cury stopx stopy maxx maxy scene =
@@ -59,7 +67,7 @@
        if x >= stopx 
         then
          gp curx (y+1)
-        else 
+        else
          let scx = (x-midx) / midx
              scy = (y-midy) / midy
              --(Clr.Color r g b) = get_color scx (scy*(midy/midx)) scene
@@ -107,8 +115,8 @@
                                   (\y -> (x*block_size,y*block_size) ) 
                                    [0..yblocks-1] ) 
                                  [0..xblocks-1]
-     pixels  = map -- (parMap rnf) 
-               (\(x,y) -> gen_pixel_list_packet x y (x+block_size) (y+block_size) maxx maxy scene)
+     pixels  = (parMap rnf) 
+               (\(x,y) -> gen_pixel_list x y (x+block_size) (y+block_size) maxx maxy scene)
                (blocks)
  in
   do
@@ -138,8 +146,8 @@
   print $ "(primitives,transforms,bounding objects): " ++ (show (primcount_scene scene))
   t2 <-  getPOSIXTime
   print $ "scene setup: " ++ (show (t2-t1))
-  let sx = 720 :: GLsizei
-  let sy = 480 :: GLsizei
+  let sx = 1280 :: GLsizei
+  let sy = 720 :: GLsizei
   let sizex = fromIntegral sx
   let sizey = fromIntegral sy
   (name, _) <- getArgsAndInitialize
diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-    This program, Glome.hs, is copyright 2008 Jim Snow
+    This library, GlomeVec, is copyright 2008 Jim Snow
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of version 2 of the GNU General Public License as 
diff --git a/Plane.hs b/Plane.hs
deleted file mode 100644
--- a/Plane.hs
+++ /dev/null
@@ -1,45 +0,0 @@
-module Plane (plane, plane_offset) where
-import Vec
-import Solid
-
--- A plane is effectively a half-space; everything below the plane is
--- "inside", everything above is "outside".
-
-data Plane = Plane Vec Flt deriving Show -- normal, perpendicular offset from origin
-
--- Usually, the most convenient way to define a plane is 
--- by specifying a point on the plane and a normal
-
-plane :: Vec -> Vec -> SolidItem
-plane orig norm_ = SolidItem $ Plane norm d
- where norm = vnorm norm_
-       d = vdot orig norm
-
--- we can also specify a point and a perpindicular offset:
-
-plane_offset :: Vec -> Flt -> SolidItem
-plane_offset pt off = SolidItem $ Plane pt off
-
-rayint_plane :: Plane -> Ray -> Flt -> Texture -> Rayint
-rayint_plane (Plane norm offset) (Ray orig dir) d t =
- let hit = -(((vdot norm orig)-offset) / (vdot norm dir))
- in if hit < 0 || hit > d 
-    then RayMiss
-    else RayHit hit (vscaleadd orig dir hit) norm t
-
-inside_plane :: Plane -> Vec -> Bool
-inside_plane (Plane norm offset) pt =
- let onplane = (vscale norm offset)
-     newvec = vsub onplane pt
- in vdot newvec norm > 0
-
--- Note: attempting to use an infinite object (such as
--- a plane) inside a bih will cause an exception.
-
-bound_plane :: Plane -> Bbox
-bound_plane (Plane norm offset) = everything_bbox
-
-instance Solid Plane where
- rayint = rayint_plane
- inside = inside_plane
- bound = bound_plane
diff --git a/README b/README
deleted file mode 100644
--- a/README
+++ /dev/null
@@ -1,43 +0,0 @@
-Glome.hs is a haskell port of my ocaml raytracer, glome. 
-(http://syn.cs.pdx.edu/~jsnow/glome)
-
-To compile on unix-type systems, execute "./make", to run, execute "./run".  
-Otherwise, invoke compiler commands manually.
-
-Update: glome has been converted over to cabal, so you can now invoke
-
-> runhaskell Setup.lhs configure --prefix=$HOME --user
-> runhaskell Setup.lhs build
-> runhaskell Setup.lhs install
-
-(The "make" and "run" scripts should still work.)
-
-Glome.hs depends on opengl bindings, which come in the standard ghc distribution.
-Glome has been tested with ghc 6.8.2.
-
-Features: 
-- can load files in NFF format
-- handles diffuse illumination, shadows, and reflection
-- renders triangles, spheres, cylinders, cones, disks, boxes
-  and planes as base primitives
-- supports csg group, difference, and intersection primitives
-- supports transformations (rotate, scale, translate) of 
-  arbitrary geometry
-- perlin noise and a few basic textures are implemented
-- uses a bounding interval heirarchy acceleration structure
-  or you can construct a BVH manually with the "Bound" primitive
-- multiprocessor support is available, but it leaks memory
-  and scaling is sub-linear
-- packet tracing (2x2) of primary rays is enabled by default
-- as of 0.5, glome uses type classes, and new primitives can
-  be defined in their own module
-
-Using: to load an NFF scene, run "./Glome -n [filename]".
-Otherwise, a default scene is rendered, defined in "TestScene.hs".
-
-Many of the features are only accessible by programming directly in
-Haskell via TestScene.hs, as NFF does not support CSG or textures.
-
-Refraction and photon mapping are not yet implemented.
-
--jim
diff --git a/README.txt b/README.txt
new file mode 100644
--- /dev/null
+++ b/README.txt
@@ -0,0 +1,12 @@
+
+This is GlomeView, a graphical frontend to Glome, my raytracer.  Originally, Glome was a monolithic program, but I have now moved most of the internals to a couple of libraries, GlomeVec and GlomeTrace.
+
+GlomeView requires HOpenGL.
+
+This was one of the first things I wrote in Haskell.  As such, it has a few rough edges.
+
+http://www.haskell.org/haskellwiki/Glome
+
+Direct all questions to:
+Jim Snow
+jsnow@cs.pdx.edu
diff --git a/Scene.hs b/Scene.hs
deleted file mode 100644
--- a/Scene.hs
+++ /dev/null
@@ -1,77 +0,0 @@
-module Scene (Scene(Scene), Light(Light), Camera(Camera),
-              scene, camera, light, 
-              sld, lits, cam, dtex, bground,
-              primcount_scene,
-              module Clr,
-              module Vec,
-              module Solid,
-              module Sphere,
-              module Triangle,
-              module Bih,
-              module Csg,
-              module Plane,
-              module Box,
-              module Bound,
-              module Cone,
-              module Tex) where
-import Clr
-import Vec
-import Solid
-import Sphere
-import Triangle
-import Bih
-import Csg
-import Plane
-import Box
-import Bound
-import Cone
-import Tex
-
--- This is the module to import if you want to have
--- access to all the Solid constructors and scene
--- defininition code.
-
---LIGHTS--
-data Light = Light {litpos :: !Vec,
-                    litcol :: !Color} deriving Show
-
-light :: Vec -> Color -> Light
-light pos clr = Light pos clr
-
--- CAMERA --
-data Camera = Camera {campos, fwd, up, right :: !Vec} 
-              deriving Show
-
-default_cam = (Camera (vec 0.0 0.0 (-3.0)) 
-                      (vec 0.0 0.0 1.0) 
-                      (vec 0.0 1.0 0.0) 
-                      (vec 1.0 0.0 0.0) )
-
-camera :: Vec -> Vec -> Vec -> Flt -> Camera
-camera pos at up angle =
- let fwd   = vnorm $ vsub at pos
-     right = vnorm $ vcross up fwd
-     up_   = vnorm $ vcross fwd right
-     cam_scale = tan ((pi/180)*(angle/2))
- in
-  Camera pos fwd
-         (vscale up_ cam_scale) 
-         (vscale right cam_scale)
-
---SCENE--
-data Scene = Scene {sld     :: SolidItem,
-                    lits    :: [Light], 
-                    cam     :: Camera, 
-                    dtex    :: Texture, 
-                    bground :: Color} deriving Show
-
-scene :: SolidItem -> [Light] -> Camera -> Texture -> Color -> Scene
-scene s l cam t clr = Scene s l cam t clr
-
-primcount_scene :: Scene -> Pcount
-primcount_scene (Scene sld _ _ _ _) = primcount sld
-
-{-
-default_scene = (Scene (sphere (vec 0.0 0.0 0.0) 1.0) 
-                       [] default_cam t_white c_white)
--}
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,6 @@
+module Main (main) where
+
+import Distribution.Simple
+
+main :: IO ()
+main = defaultMain
diff --git a/Setup.lhs b/Setup.lhs
deleted file mode 100644
--- a/Setup.lhs
+++ /dev/null
@@ -1,4 +0,0 @@
-#! /usr/bin/env runhaskell
-
-> import Distribution.Simple
-> main = defaultMain
diff --git a/Solid.hs b/Solid.hs
deleted file mode 100644
--- a/Solid.hs
+++ /dev/null
@@ -1,522 +0,0 @@
-module Solid where
-import Vec
-import Clr
-import Data.List hiding (group)
-
---COMMON DATATYPES AND UTILITY FUNCTIONS--
-data Bbox = Bbox {p1 :: !Vec, p2 :: !Vec} deriving Show
-data Interval = Interval !Flt !Flt deriving Show -- used instead of a tuple
-
---union of two bounding boxes
-bbjoin :: Bbox -> Bbox -> Bbox
-bbjoin (Bbox p1a p2a) (Bbox p1b p2b) =
- (Bbox (vmin p1a p1b) (vmax p2a p2b))
-
---overlap of two bounding boxes
-bboverlap :: Bbox -> Bbox -> Bbox
-bboverlap (Bbox p1a p2a) (Bbox p1b p2b) =
- (Bbox (vmax p1a p1b) (vmin p2a p2b))
-
---split a bounding box into two
-bbsplit :: Bbox -> Int -> Flt -> (Bbox,Bbox)
-bbsplit (Bbox p1 p2) axis offset =
- if (offset < (va p1 axis)) || (offset > (va p2 axis))
- then error "degenerate bounding box split"
- else ((Bbox p1 (vset p2 axis offset)),
-       (Bbox (vset p1 axis offset) p2))
-
--- generate a bounding box from a list of points
-bbpts :: [Vec] -> Bbox
-bbpts [] = empty_bbox
-bbpts ((Vec x y z):[]) =
- Bbox (Vec (x-delta) (y-delta) (z-delta)) 
-      (Vec (x+delta) (y+delta) (z+delta))
-
-bbpts ((Vec x y z):pts) =
- let (Bbox (Vec p1x p1y p1z) (Vec p2x p2y p2z)) = bbpts pts
-     minx = fmin (x-delta) p1x
-     miny = fmin (y-delta) p1y
-     minz = fmin (z-delta) p1z
-     maxx = fmax (x+delta) p2x
-     maxy = fmax (y+delta) p2y
-     maxz = fmax (z+delta) p2z in
- Bbox (Vec minx miny minz) (Vec maxx maxy maxz)
-
--- surface area, volume of bounding boxes
-bbsa :: Bbox -> Flt
-bbsa (Bbox p1 p2) =
- let Vec dx dy dz = vsub p2 p1 
- in dx*dy + dx*dz + dy*dz
-
-bbvol :: Bbox -> Flt
-bbvol (Bbox p1 p2) =
- let (Vec dx dy dz) = vsub p2 p1
- in dx*dy*dz
-
-empty_bbox = 
- Bbox (Vec infinity infinity infinity) 
-      (Vec (-infinity) (-infinity) (-infinity))
-
-everything_bbox =
- Bbox (Vec (-infinity) (-infinity) (-infinity))
-      (Vec infinity infinity infinity)
-
--- Find a ray's entrance and exit from a bounding 
--- box.  If last entrance is before the first exit,
--- we hit.  Otherwise, we miss. (It's up to the 
--- caller to figure that out.)
-
-bbclip :: Ray -> Bbox -> Interval
-bbclip (Ray (Vec ox oy oz) (Vec dx dy dz)) 
-       (Bbox (Vec p1x p1y p1z) (Vec p2x p2y p2z)) =
- let dxrcp = 1/dx
-     dyrcp = 1/dy
-     dzrcp = 1/dz
-     Interval inx outx = if dx > 0 
-                         then Interval ((p1x-ox)*dxrcp) ((p2x-ox)*dxrcp)
-                         else Interval ((p2x-ox)*dxrcp) ((p1x-ox)*dxrcp)
-     Interval iny outy = if dy > 0
-                         then Interval ((p1y-oy)*dyrcp) ((p2y-oy)*dyrcp)
-                         else Interval ((p2y-oy)*dyrcp) ((p1y-oy)*dyrcp)
-     Interval inz outz = if dz > 0
-                         then Interval ((p1z-oz)*dzrcp) ((p2z-oz)*dzrcp)
-                         else Interval ((p2z-oz)*dzrcp) ((p1z-oz)*dzrcp)
- in
-   Interval (fmax3 inx iny inz) (fmin3 outx outy outz)
-
-data Rayint = RayHit {
- depth    :: !Flt,
- pos      :: !Vec,
- norm     :: !Vec,
- texture  :: Texture
-} | RayMiss deriving Show
-
-nearest :: Rayint -> Rayint -> Rayint
-nearest a RayMiss = a
-nearest RayMiss b = b
-nearest !(RayHit da pa na ta) !(RayHit db pb nb tb) =
- if da < db
- then RayHit da pa na ta
- else RayHit db pb nb tb
-
-furthest :: Rayint -> Rayint -> Rayint
-furthest !a !RayMiss = RayMiss
-furthest !RayMiss !b = RayMiss
-furthest !(RayHit da pa na ta) !(RayHit db pb nb tb) =
- if da > db
- then RayHit da pa na ta
- else RayHit db pb nb tb
-
-hit :: Rayint -> Bool
-hit (RayHit _ _ _ _) = True
-hit RayMiss = False
-
-dist :: Rayint -> Flt
-dist RayMiss = infinity
-dist (RayHit d _ _ _) = d
-
---Packet Types--
-data PacketResult = PacketResult !Rayint !Rayint !Rayint !Rayint
-packetmiss = PacketResult RayMiss RayMiss RayMiss RayMiss
-
-
-nearest_packetresult :: PacketResult -> PacketResult -> PacketResult
-nearest_packetresult !(PacketResult a1 a2 a3 a4) !(PacketResult b1 b2 b3 b4) =
- PacketResult (nearest a1 b1)
-              (nearest a2 b2)
-              (nearest a3 b3)
-              (nearest a4 b4)
-
--- move ray forward, intersect, fix result
--- useful in csg
-rayint_advance :: SolidItem -> Ray -> Flt -> Texture -> Flt -> Rayint
-rayint_advance s r d t adv =
- let a = adv+delta
- in
-  case (rayint s (ray_move r a) (d-a) t) of
-   RayMiss -> RayMiss
-   RayHit depth pos norm tex -> RayHit (depth+a) pos norm tex
-
-
---MATERIALS--
-data Material = Material {clr :: Color, 
-                          refl, refr, ior, 
-                          kd, shine :: !Flt} deriving Show
-type Texture = Rayint -> Material
-
--- this is sort of a no-op; we don't have a
--- good way to show an arbitrary function
-showTexture :: Texture -> String
-showTexture t = show $ t RayMiss
-
-instance Show Texture where
- show = showTexture
-
-m_white = (Material c_white 0 0 0 1 2)
-t_white ri = m_white
-
-t_uniform :: Material -> Texture
-t_uniform m = \x -> m
-
-interp :: Flt -> Flt -> Flt -> Flt
-interp scale a b =
- scale*a + (1-scale)*b
-
---not really correct, but we'll go with it for now
-m_interp :: Material -> Material -> Flt -> Material
-m_interp m1 m2 scale =
- let (Material m1c m1refl m1refr m1ior m1kd m1shine) = m1
-     (Material m2c m2refl m2refr m2ior m2kd m2shine) = m2
-     intp  = interp scale
-     c     = cadd (cscale m1c scale) (cscale m2c (1-scale))
-     refl  = intp m1refl m2refl
-     refr  = intp m1refr m2refr
-     ior   = intp m1ior m2ior
-     kd    = intp m1kd m2kd
-     shine = intp m1shine m2shine
- in (Material c refl refr ior kd shine)
-
---utility functions for "primcount"
-newtype Pcount = Pcount (Int,Int,Int) deriving Show
-
-pcadd :: Pcount -> Pcount -> Pcount
-pcadd (Pcount (a1,a2,a3)) (Pcount (b1,b2,b3)) = Pcount (a1+b1, a2+b2, a3+b3)
-
-asbound :: Pcount -> Pcount
-asbound (Pcount (a,b,c)) = Pcount (0,b,a+c)
-
-pcsinglexfm ::  Pcount
-pcsinglexfm = Pcount (0,1,0)
-
-pcsingleprim :: Pcount
-pcsingleprim = Pcount (1,0,0)
-
-pcsinglebound :: Pcount
-pcsinglebound = Pcount (0,0,1)
-
-pcnone :: Pcount
-pcnone = Pcount (0,0,0)
-
--- utility functions for rayint_debug
-debug_wrap :: (Rayint,Int) -> Int -> (Rayint,Int)
-debug_wrap (ri,a) b = (ri,(a+b))
-
-nearest_debug :: (Rayint,Int) -> (Rayint,Int) -> (Rayint,Int)
-nearest_debug (ari, an) (bri, bn) = ((nearest ari bri),(an+bn))
-
---SOLID CLASS--
-
-class (Show a) => Solid a where
- rayint :: a -> Ray -> Flt -> Texture -> Rayint
- rayint_debug :: a -> Ray -> Flt -> Texture -> (Rayint, Int)
- packetint :: a -> Ray -> Ray -> Ray -> Ray -> Flt -> Texture -> PacketResult 
- shadow :: a -> Ray -> Flt -> Bool
- inside :: a -> Vec -> Bool
- bound  :: a -> Bbox
- tolist :: a -> [SolidItem]
- transform :: a -> [Xfm] -> SolidItem
- transform_leaf :: a -> [Xfm] -> SolidItem
- flatten_transform :: a -> [SolidItem]
- primcount :: a -> Pcount
-
- -- This is for counting bih split planes ands the like.
- -- We have to provide an implementation for most composite
- -- primitives.
- rayint_debug s !r !d t = ((rayint s r d t),0)
-
- -- Sometimes, we can improve performance by 
- -- intersecting 4 rays at once.  This is 
- -- especially true of acceleration structures.
- -- By default, we fall back on mono-rays.
- packetint s !r1 !r2 !r3 !r4 !d t = 
-  PacketResult (rayint s r1 d t)
-               (rayint s r2 d t)
-               (rayint s r3 d t)
-               (rayint s r4 d t)
-
- -- if there is no shadow function, we fall back on rayint
- shadow s !r !d =
-  case (rayint s r d t_white) of
-   RayHit _ _ _ _ -> True
-   RayMiss -> False
-
- -- This is here so we can flatten a group of groups
- -- into a single group; the default is fine for everything
- -- but groups and Void and SolidItem
- tolist a = [SolidItem (a)]
- 
- -- Method to transform an object; the default works fine
- -- except for instances themselves, which will want to
- -- collapse the two transformations into a sigle transform.
- transform a xfm = SolidItem $ Instance (SolidItem a) (compose xfm)
-
- -- This is used by flatten_transform below.  For simple objects, it 
- -- works the same as transform, but for groups it transforms all the
- -- objects individually.
- transform_leaf = transform
-
- -- This prepares a composite primitive to be fed into the bih constructor
- -- by pushing all the transformations out to the leaves and 
- -- throwing away manual bounding structures.  For simple primitives, this
- -- is a no-op.
- flatten_transform = tolist
-
- -- Figure out how complicated the scene really is.
- -- Returns (primitives, matricies, bounding objects/planes).
- -- Also, it forces the full construction of acceleration structures.
- primcount s = pcsingleprim
-
--- Existential type so we can make a heterogeneous list of solids,
--- and embed them in composite types.
--- http://notes-on-haskell.blogspot.com/2007/01/proxies-and-delegation-vs-existential.html
-
-data SolidItem = forall a. Solid a => SolidItem a
-
-instance Solid SolidItem where
- rayint (SolidItem s) !r !d t = rayint s r d t
- packetint (SolidItem s) !r1 !r2 !r3 !r4 !d t = packetint s r1 r2 r3 r4 d t
- rayint_debug (SolidItem s) r d t = rayint_debug s r d t
- shadow (SolidItem s) !r !d = shadow s r d
- inside (SolidItem s) pt = inside s pt
- bound  (SolidItem s) = bound s
- tolist (SolidItem s) = tolist s -- don't wrap in a redundant SolidItem like everything else
- transform (SolidItem s) xfm = transform s xfm -- same here
- transform_leaf (SolidItem s) xfm = transform_leaf s xfm -- and here
- flatten_transform (SolidItem s) = [SolidItem (flatten_transform s)] -- and here
- primcount (SolidItem s) = primcount s
-
-instance Show SolidItem where
- show (SolidItem s) = "SI " ++ show s
-
--- we implement "group", "void", and "instance" here because they're
--- used by some of the other primitives
-
--- GROUP --
-
-group :: [SolidItem] -> SolidItem
-group [] = SolidItem Void
-group (sld:[]) = sld
-group slds = SolidItem (flatten_group slds)
-
--- smash a group of groups into a single group,
--- so we can build an efficient bounding heirarchy
-flatten_group :: [SolidItem] -> [SolidItem]
-flatten_group slds = concat (map tolist slds)
-
--- this lets us treat lists of SolidItems as regular Solids
-rayint_group :: [SolidItem] -> Ray -> Flt -> Texture -> Rayint
-rayint_group [] _ _ _ = RayMiss
-rayint_group (x:xs) !r !d t = nearest (rayint x r d t) (rayint_group xs r d t)
-
-packetint_group :: [SolidItem] -> Ray -> Ray -> Ray -> Ray -> Flt -> Texture -> PacketResult
-packetint_group [] !r1 !r2 !r3 !r4 !d t = packetmiss
-packetint_group (x:xs) !r1 !r2 !r3 !r4 !d t = 
- nearest_packetresult (packetint x r1 r2 r3 r4 d t) 
-                      (packetint_group xs r1 r2 r3 r4 d t)
-
-rayint_debug_group :: [SolidItem] -> Ray -> Flt -> Texture -> (Rayint,Int)
-rayint_debug_group [] _ _ _ = (RayMiss,0)
-rayint_debug_group (x:xs) !r !d t = 
- nearest_debug (rayint_debug x r d t) 
-               (rayint_debug_group xs r d t)
-
-shadow_group :: [SolidItem] -> Ray -> Flt -> Bool
-shadow_group [] !r !d = False
-shadow_group (x:xs) r d = (shadow x r d) || (shadow_group xs r d)
-
-inside_group :: [SolidItem] -> Vec -> Bool
-inside_group slds pt =
- foldl' (||) False (map (\x -> inside x pt) slds)
-
-bound_group :: [SolidItem] -> Bbox
-bound_group slds = 
- foldl' bbjoin empty_bbox (map bound slds)
-
-transform_leaf_group :: [SolidItem] -> [Xfm] -> SolidItem
-transform_leaf_group slds xfms =
- SolidItem $ map (\x -> transform_leaf x xfms) (tolist slds)
-
-primcount_group :: [SolidItem] -> Pcount
-primcount_group slds = foldl (pcadd) (Pcount (0,0,0)) (map primcount slds)
-
-instance Solid [SolidItem] where
- rayint = rayint_group
- packetint = packetint_group
- rayint_debug = rayint_debug_group
- shadow = shadow_group
- inside = inside_group
- bound = bound_group
- tolist a = concat $ map tolist a
- transform_leaf = transform_leaf_group
- flatten_transform a = concat $ map flatten_transform a
- primcount = primcount_group
-
--- VOID --
--- non-object (originally called "Nothing", but that
--- conflicted with the prelude maybe type, so we call
--- it "Void" instead) 
-data Void = Void deriving Show
-
-nothing = SolidItem Void
-
-instance Solid Void where
- rayint Void _ _ _ = RayMiss
- packetint Void _ _ _ _ _ _ = packetmiss
- shadow Void _ _ = False
- inside Void _ = False
- bound  Void = empty_bbox
- tolist Void = []
- transform Void xfms = SolidItem Void 
-
--- INSTANCE --
--- this would be better in its own module, but we need
--- "Instance" to be defined here for the default implementation
--- of "transform".  (I tried mutually recursive modules, it
--- didn't work.  http://www.haskell.org/ghc/docs/latest/html/
---  users_guide/separate-compilation.html#mutual-recursion ) 
-
--- Another good reason to include Instance in Solid.hs
--- is that it's referenced from Cone.hs
-
--- An instance is a primitive that has been modified
--- by a transformation (i.e. some combination of
--- translation, rotation, and scaling).  This is a
--- reasonably space-efficient way of making multiple copies
--- of a complex object.
-
--- It's unfortunate that "instance" is also a reserved word.  
--- "instance Solid Instance where..." is a little confusing.
-
-data Instance = Instance SolidItem Xfm deriving Show
-
-rayint_instance :: Instance -> Ray -> Flt -> Texture -> Rayint
-rayint_instance (Instance sld xfm) (Ray orig dir) d t =
- let newdir  = invxfm_vec xfm dir
-     neworig = invxfm_point xfm orig
-     lenscale = vlen newdir
-     invlenscale = 1/lenscale
- in
-  case (rayint sld (Ray neworig (vscale newdir invlenscale)) (d*lenscale) t) of
-   RayMiss -> RayMiss
-   RayHit depth pos n tex -> RayHit (depth*invlenscale) 
-                                    (xfm_point xfm pos) 
-                                    (vnorm (invxfm_norm xfm n)) 
-                                    tex
-
-packetint_instance :: Instance -> Ray -> Ray -> Ray -> Ray -> Flt -> Texture -> PacketResult
-packetint_instance (Instance sld xfm) !(Ray orig1 dir1) !(Ray orig2 dir2) 
-                                      !(Ray orig3 dir3) !(Ray orig4 dir4) d t =
- let newdir1  = invxfm_vec xfm dir1
-     newdir2  = invxfm_vec xfm dir2
-     newdir3  = invxfm_vec xfm dir3
-     newdir4  = invxfm_vec xfm dir4
-     neworig1 = invxfm_point xfm orig1
-     neworig2 = invxfm_point xfm orig2
-     neworig3 = invxfm_point xfm orig3
-     neworig4 = invxfm_point xfm orig4
-     lenscale1 = vlen newdir1
-     lenscale2 = vlen newdir2
-     lenscale3 = vlen newdir3
-     lenscale4 = vlen newdir4
-     invlenscale1 = 1/lenscale1
-     invlenscale2 = 1/lenscale2
-     invlenscale3 = 1/lenscale3
-     invlenscale4 = 1/lenscale4
- in
-  let pr = packetint sld (Ray neworig1 (vscale newdir1 invlenscale1)) 
-                         (Ray neworig2 (vscale newdir2 invlenscale2)) 
-                         (Ray neworig3 (vscale newdir3 invlenscale3)) 
-                         (Ray neworig4 (vscale newdir4 invlenscale4)) 
-                         (d*lenscale1) t
-      PacketResult ri1 ri2 ri3 ri4 = pr 
-      fix ri ils = 
-       case ri of 
-        RayMiss -> RayMiss
-        RayHit depth pos n tex -> RayHit (depth*ils) 
-                                         (xfm_point xfm pos) 
-                                         (vnorm (invxfm_norm xfm n)) 
-                                         tex
-  in PacketResult (fix ri1 invlenscale1)
-                  (fix ri2 invlenscale2)
-                  (fix ri3 invlenscale3)
-                  (fix ri4 invlenscale4)
-
--- ugh, code duplication
-rayint_debug_instance :: Instance -> Ray -> Flt -> Texture -> (Rayint,Int)
-rayint_debug_instance (Instance sld xfm) (Ray orig dir) d t =
- let newdir  = invxfm_vec xfm dir
-     neworig = invxfm_point xfm orig
-     lenscale = vlen newdir
-     invlenscale = 1/lenscale
- in
-  case (rayint_debug sld (Ray neworig (vscale newdir invlenscale)) (d*lenscale) t) of
-   (RayMiss, count) -> (RayMiss, count)
-   (RayHit depth pos n tex, count) -> (RayHit (depth*invlenscale) 
-                                         (xfm_point xfm pos) 
-                                         (vnorm (invxfm_norm xfm n)) 
-                                         tex, count)
-
-shadow_instance :: Instance -> Ray -> Flt -> Bool
-shadow_instance (Instance sld xfm) (Ray orig dir) d =
- let newdir  = invxfm_vec xfm dir
-     neworig = invxfm_point xfm orig
-     lenscale = vlen newdir
-     invlenscale = 1/lenscale
- in
-  shadow sld (Ray neworig (vscale newdir invlenscale)) (d*lenscale)
-
-inside_instance :: Instance -> Vec -> Bool
-inside_instance (Instance s xfm) pt =
- inside s (xfm_point xfm pt)
-
-bound_instance :: Instance -> Bbox
-bound_instance (Instance sld xfm) =
- let (Bbox (Vec p1x p1y p1z) (Vec p2x p2y p2z)) = bound sld
-     pxfm = xfm_point xfm
- in
-     bbpts  [(pxfm (Vec x y z)) | x <- [p1x,p2x],
-                                  y <- [p1y,p2y],
-                                  z <- [p1z,p2z]]
-
--- If we try to create a transformation of
--- a transformation, we can merge those
--- into a single transformation.
-
--- This ought to be tested to verify this
--- is really applying transforms in the
--- correct order...
-
-transform_instance :: Instance -> [Xfm] -> SolidItem
-transform_instance (Instance s xfm2) xfm1 =
- transform s [compose ([xfm2]++xfm1) ]
-
-transform_leaf_instance :: Instance -> [Xfm] -> SolidItem
-transform_leaf_instance (Instance s xfm2) xfm1 =
- transform_leaf s [compose ([xfm2]++xfm1) ]
-
--- Flatten_transform attempts to push all transformations 
--- in a heirarchy out to the leaf nodes.  The case we're
--- interested in here is an instance of a group, and we 
--- want to replace that with a group of individually 
--- transformed instances.  This could be construed as a
--- waste of memory, but in some cases it's necessary.
-
-flatten_transform_instance :: Instance -> [SolidItem]
-flatten_transform_instance (Instance s xfm) = 
- [SolidItem $ transform_leaf s [xfm]]
- -- group $ map (\x -> transform (flatten_transform x) [xfm]) (tolist s)
-
-primcount_instance :: Instance -> Pcount
-primcount_instance (Instance s xfm) = pcadd (primcount s) pcsinglexfm
-
-instance Solid Instance where
- rayint = rayint_instance
- packetint = packetint_instance
- rayint_debug = rayint_debug_instance
- shadow = shadow_instance
- inside = inside_instance
- bound  = bound_instance
- transform = transform_instance
- transform_leaf = transform_leaf_instance
- flatten_transform = flatten_transform_instance
- primcount = primcount_instance
diff --git a/SolidTexture.hs b/SolidTexture.hs
deleted file mode 100644
--- a/SolidTexture.hs
+++ /dev/null
@@ -1,127 +0,0 @@
-{-
-module SolidTexture (square_wave, triangle_wave, sine_wave, 
-                     stripe, noise, turbulence
-                    ) where -}
-
-module SolidTexture where
-import Clr
-import Vec
-import Data.Array.IArray
-
--- INTERPOLATION FUNCTIONS --
-square_wave :: Flt -> Flt
-square_wave x =
- let offset = x - (fromIntegral (floor x))
- in if offset < 0.5 then 0 else 1
-
-triangle_wave :: Flt -> Flt
-triangle_wave x =
- let offset = x - (fromIntegral (floor x))
- in if offset < 0.5 
-    then (offset*2)
-    else (2-(offset*2))
-
-sine_wave :: Flt -> Flt
-sine_wave x = (sin (x*2*pi))*0.5 + 0.5
-
-
-lump_wave :: Flt -> Flt
-lump_wave x = 1 - x*x*x
-
--- SCALAR TEXTURE FUNCTIONS --
-
--- These are simple solid texture functions that take a 
--- point as argument and return a number 0 < n < 1
-
-stripe :: Vec -> (Flt -> Flt) -> (Vec -> Flt)
-stripe axis interp =
- let len = vlen axis 
- in
-  (\pos -> let offset = vdot pos axis 
-           in interp offset)
-
-
--- PERLIN NOISE --
-
--- (-6 t^5 + 15 t^4 - 10t^3 +1)
--- "realistic ray tracing 2nd edition" inconsistent 
--- on whether it should be t^5 or t^6,
--- but t^5 works and t^6 doesn't.
-omega :: Flt -> Flt
-omega t_ = 
- let t     = fabs t_
-     tsqr  = t*t
-     tcube = tsqr*t
- in (-6)*tcube*tsqr + 15*tcube*t - 10*tcube + 1
-
--- questionably random
-phi :: Array Int Int
-phi = listArray (0,11) [3,0,2,7,4,1,5,11,8,10,9,6]
-
-grad :: Array Int Vec
-grad = listArray (0,11) 
-         $ filter (\x -> let l = vlen x in l < 1.5 && l > 1.1) 
-                  [Vec x y z | x <- [(-1),0,1],
-                               y <- [(-1),0,1],
-                               z <- [(-1),0,1]] 
-
-gamma :: Int -> Int -> Int -> Vec
-gamma i j k =
- let a = phi!(mod (iabs k) 12)
-     b = phi!(mod (iabs (j+a)) 12)
-     c = phi!(mod (iabs (i+b)) 12)
- in grad!c
-
-knot :: Int -> Int -> Int -> Vec -> Flt
-knot i j k v =
- let Vec x y z = v
- in (omega x) * (omega y) * (omega z) * (vdot (gamma i j k) v)
-
-intGamma :: Int -> Int -> Int
-intGamma i j =
- let a = phi!(mod (iabs j) 16)
-     b = phi!(mod (iabs (i+a)) 16)
- in b
-
-turbulence :: Vec -> Int -> Flt
-turbulence p 1 = fabs(noise(p))
-turbulence p n =
- let newp = vscale p 0.5
-     t = fabs (noise p)
- in t + (0.5 * (turbulence newp (n-1)))
-
-noise :: Vec -> Flt 
-noise (Vec x y z) =
- let i = floor x
-     j = floor y
-     k = floor z
-     u = x-(fromIntegral i)
-     v = y-(fromIntegral j)
-     w = z-(fromIntegral k)
- in knot i j k             (Vec u v w) +
-    knot (i+1) j k         (Vec (u-1) v w) +
-    knot i (j+1) k         (Vec u (v-1) w) +
-    knot i j (k+1)         (Vec u v (w-1)) +
-    knot (i+1) (j+1) k     (Vec (u-1) (v-1) w) +
-    knot (i+1) j (k+1)     (Vec (u-1) v (w-1)) +
-    knot i (j+1) (k+1)     (Vec u (v-1) (w-1)) +
-    knot (i+1) (j+1) (k+1) (Vec (u-1) (v-1) (w-1))
-
-perlin :: Vec -> Flt
-perlin v =
- let p = ((noise v)+1)*0.5
- in if p > 1 
-    then error $ "perlin noise error, 1 < " ++ (show p)
-    else if p < 0 
-         then error $ "perlin noise error, 0 > " ++ (show p)
-         else p
-
---untested
-perlin_turb :: Vec -> Int -> Flt
-perlin_turb v l =
- let p = turbulence v l
- in if p > 1 
-    then error $ "perlin turbulence error, 1 < " ++ (show p)
-    else if p < 0 
-         then error $ "perlin turbulence error, 0 > " ++ (show p)
-         else p
diff --git a/Spd.hs b/Spd.hs
deleted file mode 100644
--- a/Spd.hs
+++ /dev/null
@@ -1,244 +0,0 @@
-module Spd where
-import Scene
-
--- NFF file format description:
--- http://tog.acm.org/resources/SPD/NFF.TXT
-
--- this would probably be much shorter if I used scanf instead of lex
-
-lexignore s =
- let t = lex s 
- in
-  case t of 
-   [] -> [] -- newline
-   [("",s1)] -> lexcr s1
-   [(_,s1)] -> lexignore s1 
-
-lexcr s = 
- let t = lex s
- in 
-  case t of
-   [(s1,[])] -> t
-   [("",s1)] -> lexcr s1
-   [("#",s1)] -> lexignore s1
-   _ -> t
-
-data BgColor = BgColor(Color)
-
-readsSpdVec :: ReadS Vec
-readsSpdVec s = [((Vec x y z),s3) | (x,s1) <- reads s  :: [(Flt,String)], 
-                                    (y,s2) <- reads s1 :: [(Flt,String)],
-                                    (z,s3) <- reads s2 :: [(Flt,String)] ]
-instance Read Vec where
- readsPrec _ = readsSpdVec
-
-readsSpdVecNorm :: ReadS (Vec,Vec)
-readsSpdVecNorm s = [(((Vec x y z),(Vec nx ny nz)),s6) 
-                     | (x,s1) <- reads s  :: [(Flt,String)], 
-                       (y,s2) <- reads s1 :: [(Flt,String)],
-                       (z,s3) <- reads s2 :: [(Flt,String)],
-                       (nx,s4) <- reads s3  :: [(Flt,String)],
-                       (ny,s5) <- reads s4  :: [(Flt,String)],
-                       (nz,s6) <- reads s5  :: [(Flt,String)] ]
-
-instance Read (Vec,Vec) where
- readsPrec _ = readsSpdVecNorm
-
-
--- if this seems intuitive, there's something wrong with you
-readsSpdVecs :: ReadS [Vec]
-readsSpdVecs s =
- let parses = reads s :: [(Vec,String)]
- in
- if null parses
- then [([],s)]
- else
-  let (v,rest) = head parses
-      (vs,returns) = head (readsSpdVecs rest)
-  in [((v:vs),returns)]
-
-instance Read [Vec] where
- readsPrec _ = readsSpdVecs
-
-readsSpdVecsNorms :: ReadS [(Vec,Vec)]
-readsSpdVecsNorms s = 
- let parses = readsSpdVecNorm s :: [((Vec,Vec),String)]
- in
- if null parses
- then [([],s)]
- else
-  let (v,rest) = head parses
-      (vs,returns) = head (readsSpdVecsNorms rest)
-  in [((v:vs),returns)]
-
-instance Read [(Vec,Vec)] where
- readsPrec _ = readsSpdVecsNorms
-
-{- "v"
-   "from" Fx Fy Fz
-   "at" Ax Ay Az
-   "up" Ux Uy Uz
-   "angle" angle
-   "hither" hither
-   "resolution" xres yres -}
-readsSpdCam :: ReadS Camera
-readsSpdCam s = [ (camera from at up angle,s14) | ("v", s1)      <- lexcr s,
-                                                  ("from", s2)   <- lexcr s1,
-                                                  (from, s3)     <- reads s2 :: [(Vec,String)],
-                                                  ("at", s4)     <- lexcr s3,
-                                                  (at, s5)       <- reads s4 :: [(Vec,String)],
-                                                  ("up", s6)     <- lexcr s5,
-                                                  (up, s7)       <- reads s6 :: [(Vec,String)],
-                                                  ("angle", s8)  <- lexcr s7,
-                                                  (angle, s9)    <- reads s8 :: [(Flt,String)],
-                                                  ("hither", s10)<- lexcr s9,
-                                                  (_,s11)        <- lexcr s10,
-                                                  ("resolution", s12) <- lexcr s11,
-                                                  (_, s13)       <- lexcr s12,
-                                                  (_, s14)       <- lexcr s13 ]
-instance Read Camera where
- readsPrec _ = readsSpdCam
-
-
-
-readsSpdClr :: ReadS Color
-readsSpdClr s = [((Color r g b), s3) | (r, s1)  <- reads s  :: [(Flt,String)],
-                                       (g, s2)  <- reads s1 :: [(Flt,String)],
-                                       (b, s3)  <- reads s2 :: [(Flt,String)] ]
-instance Read Color where
- readsPrec _ = readsSpdClr
-
-
--- "b" R G B
-readsSpdBackground :: ReadS BgColor
-readsSpdBackground s = [((BgColor clr), s2) | ("b", s1) <- lexcr s,
-                                     (clr, s2) <- reads s1 :: [(Color,String)] ]
-instance Read BgColor where
- readsPrec _ = readsSpdBackground
-
-
--- "l" X Y Z [R G B]
-readsSpdLight :: ReadS Light
-readsSpdLight s = [((Light pos clr),s3) | ("l", s1) <- lexcr s,
-                                          (pos, s2) <- reads s1 :: [(Vec,String)],
-                                          (clr, s3) <- reads s2 :: [(Color,String)] ]
-                  ++
-                  [((Light pos (Color 1 1 1)),s2) | ("l", s1) <- lexcr s,
-                                                    (pos, s2) <- reads s1 :: [(Vec,String)] ]
-instance Read Light where
- readsPrec _ = readsSpdLight
-
--- "f" red green blue Kd Ks Shine T index_of_refraction
--- data Material = Material {clr :: Color, reflect, refract, ior, kd, ks, shine :: Flt}
-readsSpdFill :: ReadS Texture
-readsSpdFill s = [(\ri->Material clr ks (1-trans) ior kd shine, s7) | ("f", s1)    <- lexcr s,
-                                    (clr, s2)    <- reads s1 :: [(Color,String)],
-                                    (kd, s3)     <- reads s2 :: [(Flt,String)],
-                                    (ks, s4)     <- reads s3 :: [(Flt,String)],
-                                    (shine, s5)  <- reads s4 :: [(Flt,String)],
-                                    (trans, s6)  <- reads s5 :: [(Flt,String)],
-                                    (ior, s7)    <- reads s6 :: [(Flt,String)] ]
-
-instance Read (Rayint -> Material) where
- readsPrec _ = readsSpdFill
-
-
--- "s" center.x center.y center.z radius
-
--- "c"
--- base.x base.y base.z base_radius
--- apex.x apex.y apex.z apex_radius
-
--- "p" total_vertices
--- vert1.x vert1.y vert1.z
--- [etc. for total_vertices vertices]
-
-readsSpdSolid :: ReadS SolidItem
-readsSpdSolid s = [((sphere center radius),s3) | ("s", s1) <- lexcr s,
-                                                 (center,s2) <- reads s1 :: [(Vec,String)],
-                                                 (radius,s3) <- reads s2 :: [(Flt,String)] ]
-                  ++
-                  [((cone e1 r1 e2 r2),s5) | ("c",s1) <- lexcr s,
-                                             (e1,s2)  <- reads s1 :: [(Vec,String)],
-                                             (r1,s3)  <- reads s2 :: [(Flt,String)],
-                                             (e2,s4)  <- reads s3 :: [(Vec,String)],
-                                             (r2,s5)  <- reads s4 :: [(Flt,String)] ]
-                  ++
-                  [(group (triangles verts),s3) | ("p",s1) <- lexcr s,
-                                                  (n,s2) <- reads s1 :: [(Int,String)],
-                                                  (verts,s3) <- readsSpdVecs s2 :: [([Vec],String)] ]
-                  ++
-                  [(group (trianglesnorms (vns)),s3) | ("pp",s1) <- lexcr s,
-                                                       (n,s2) <- reads s1 :: [(Int,String)],
-                                                       (vns,s3) <- readsSpdVecsNorms s2 :: [([(Vec,Vec)],String)] ]
-                  {- ++
-                  [(tex(Void,t),s1) | (t,s1) <- reads s :: [(Texture,String)]] -}
-
-
--- instance Read Solid where
--- readsPrec _ = readsSpdSolid
-
-
--- same as readSpdVecs, just different types
-readsSpdPrims :: ReadS [SolidItem]
-readsSpdPrims s =
- let parses = readsSpdSolid s :: [(SolidItem,String)]
- in
- if null parses
- then [([],s)]
- else
-  let (v,rest) = head parses
-      (vs,returns) = head (readsSpdPrims rest)
-  in [((v:vs),returns)]
-
-instance Read [SolidItem] where
- readsPrec _ = readsSpdPrims
-
-
-readsSpdTextureGroup :: ReadS SolidItem
-readsSpdTextureGroup s =
- [((tex (bih prims) t),s2) | (t,s1)     <- reads s :: [(Texture,String)],
-                               (prims,s2) <- readsSpdPrims s1 :: [([SolidItem],String)] ]
- 
-instance Read SolidItem where
- readsPrec _ = readsSpdTextureGroup
-
-accum_rss :: [Camera] -> [Light] -> [SolidItem] -> [BgColor] -> String -> ([Camera],[Light],[SolidItem],[BgColor],String)
-accum_rss cams lights prims background s = 
-  if null s
-   then (cams,lights,prims,background,s)
-  else
-   let cam = reads s :: [(Camera,String)]
-       sld = reads s :: [(SolidItem,String)]
-       lit = reads s :: [(Light,String)]
-       bgc = reads s :: [(BgColor,String)]
-   in
-     if not $ null cam
-     then
-       let (c1,s1) = head cam
-      in accum_rss (c1:cams) lights prims background s1
-     else
-      if not $ null sld
-      then
-       let (s2,s1) = head sld 
-       in  accum_rss cams lights (s2:prims) background s1
-      else
-       if not $ null lit
-       then
-        let (l1,s1) = head lit
-        in accum_rss cams (l1:lights) prims background s1
-       else
-        if not $ null bgc
-        then
-         let (b1,s1) = head bgc
-         in accum_rss cams lights prims (b1:background) s1
-        else
-         (cams,lights,prims,background,s)
-
-readsSpdScene :: ReadS Scene
-readsSpdScene s = 
-  let ((cam:cams),lights,prims,(BgColor(bgc):bgcs),s1) = accum_rss [] [] [] [] s
-  in [((scene (bih prims) lights cam t_white bgc),s1)]
-
-instance Read Scene where
- readsPrec _ = readsSpdScene
diff --git a/Sphere.hs b/Sphere.hs
deleted file mode 100644
--- a/Sphere.hs
+++ /dev/null
@@ -1,75 +0,0 @@
-module Sphere (sphere) where
-import Vec
-import Solid
-
-data Sphere = Sphere !Vec !Flt !Flt deriving Show
-
-sphere :: Vec -> Flt -> SolidItem
-sphere c r =
- SolidItem (Sphere c r (1.0/r))
-
--- adapted from graphics gems volume 1
-rayint_sphere :: Sphere -> Ray -> Flt -> Texture -> Rayint
-rayint_sphere (Sphere center r invr) (Ray e dir) dist t = 
- let eo = vsub center e
-     v  = vdot eo dir
- in
- if (dist >= (v - r)) && (v > 0.0)
- then
-  let vsqr = v*v
-      csqr = vdot eo eo
-      rsqr = r*r
-      disc = rsqr - (csqr - vsqr) in
-  if disc < 0.0 then
-   RayMiss
-  else
-   let d = sqrt disc
-       hitdist = if (v-d) > 0 then (v-d) else (v+d)
-   in if (hitdist < 0) || (hitdist > dist)
-      then RayMiss
-      else
-       let p = vscaleadd e dir hitdist
-           -- n = vscale (vsub p center) invr in
-           -- n = vsub (vscale p invr) (vscale center invr) in
-           n = vnorm (vsub p center) 
-       in RayHit hitdist p n t
- else
-  RayMiss
-
-shadow_sphere :: Sphere -> Ray -> Flt -> Bool
-shadow_sphere (Sphere center r invr) (Ray e dir) dist = 
- let eo = vsub center e
-     v  = vdot eo dir
- in
- if (dist >= (v - r)) && (v > 0.0)
- then
-  let vsqr = v*v
-      csqr = vdot eo eo
-      rsqr = r*r
-      disc = rsqr - (csqr - vsqr) in
-  if disc < 0.0 then
-  False
-  else
-   let d = sqrt disc
-       hitdist = if (v-d) > 0 then (v-d) else (v+d)
-   in if (hitdist < 0) || (hitdist > dist)
-      then False
-      else True
- else
-  False
-
-inside_sphere :: Sphere -> Vec -> Bool
-inside_sphere (Sphere center r invr) pt =
- let offset = vsub center pt 
- in (vdot offset offset) < r*r
-
-bound_sphere :: Sphere -> Bbox
-bound_sphere (Sphere center r invr) =
- let offset = (vec r r r) in
- (Bbox (vsub center offset) (vadd center offset))
-
-instance Solid Sphere where 
- rayint = rayint_sphere
- shadow = shadow_sphere
- inside = inside_sphere
- bound  = bound_sphere
diff --git a/TestScene.hs b/TestScene.hs
--- a/TestScene.hs
+++ b/TestScene.hs
@@ -1,7 +1,9 @@
+{-# LANGUAGE ScopedTypeVariables #-}
+
 module TestScene (scn) where
-import Scene
+import Data.Glome.Scene
 import Data.List hiding (group)
-import SolidTexture
+import Data.Glome.Texture
 import System.Random
 
 lights = [ Light (Vec (-100) 70 (140)) (cscale (Color 1 0.8 0.8) 2500)
@@ -130,13 +132,13 @@
 
 -- some textures
 m_shiny_white :: Material
-m_shiny_white = (Material c_white 0.3 0 0 0.7 10)
+m_shiny_white = (Material c_white 0.3 0 0 0.7 0.8 10)
 
 t_shiny_white :: Texture
 t_shiny_white ri = m_shiny_white
 
 m_dull_gray :: Material
-m_dull_gray = (Material (Color 0.4 0.3 0.35) 0 0 0 0.2 1)
+m_dull_gray = (Material (Color 0.4 0.3 0.35) 0 0 0 0.2 0 1)
 
 t_mottled (RayHit _ pos norm _) =
  --let scale = (stripe (Vec 1 1 1) sine_wave) pos
@@ -159,13 +161,14 @@
 --shouldn't happen
 t_stripe RayMiss = m_shiny_white 
 
-
-m_matte c = (Material c 0 0 0 1 2)
+m_matte :: Color -> Material
+m_matte c = (Material c 0 0 0 1 0 2)
 
+t_matte :: Color -> Texture
 t_matte c = 
- (\ri -> (Material c 0 0 0 1 2)) 
+ (\ri -> (Material c 0 0 0 1 0 2)) 
 
-m_mirror = (Material (Color 0.8 0.8 1) 1 0 0 0.2 1000)
+m_mirror = (Material (Color 0.8 0.8 1) 1 0 0 0.2 0.8 1000)
 t_mirror = 
  (\ri -> m_mirror)
 
diff --git a/Tex.hs b/Tex.hs
deleted file mode 100644
--- a/Tex.hs
+++ /dev/null
@@ -1,55 +0,0 @@
-module Tex (tex) where
-import Vec
-import Solid
-
--- Textured objects --
--- The type "Texture" is used elsewhere, so
--- we just call a textured object a "Tex".
-
--- How textured objects work is a little strange:
--- instead of having a texture applied to every object,
--- which seems rather wastefull, we use the container 
--- object "Tex"; anything contained in that Tex has 
--- that texture.
-
--- In the case of nested Tex objects, the innermost 
--- texture has precedence.  Textures are implemented
--- by passing a Texture in to the rayint function.
--- Most objects just return the Texture unchanged (as
--- part of the RayHit record) but Tex overwrites the 
--- texture with its own.
-
-data Tex = Tex SolidItem Texture deriving Show
-
-tex :: SolidItem -> Texture -> SolidItem
-tex s t = SolidItem $ Tex s t
-
-rayint_tex :: Tex -> Ray -> Flt -> Texture -> Rayint
-rayint_tex (Tex s tex) r d t = rayint s r d tex
-
-rayint_debug_tex :: Tex -> Ray -> Flt -> Texture -> (Rayint,Int)
-rayint_debug_tex (Tex s tex) r d t = rayint_debug s r d tex
-
-packetint_tex :: Tex -> Ray -> Ray -> Ray -> Ray -> Flt -> Texture -> PacketResult
-packetint_tex (Tex s tx) r1 r2 r3 r4 d t = packetint s r1 r2 r3 r4 d tx
-
-shadow_tex :: Tex -> Ray -> Flt -> Bool
-shadow_tex (Tex s _) r d = shadow s r d
-
-inside_tex :: Tex -> Vec -> Bool
-inside_tex (Tex s _) pt = inside s pt
-
-bound_tex :: Tex -> Bbox 
-bound_tex (Tex s _) = bound s
-
-primcount_tex :: Tex -> Pcount
-primcount_tex (Tex s _) = primcount s
-
-instance Solid Tex where
- rayint = rayint_tex
- rayint_debug = rayint_debug_tex
- packetint = packetint_tex
- shadow = shadow_tex
- inside = inside_tex
- bound = bound_tex
- primcount = primcount_tex
diff --git a/Trace.hs b/Trace.hs
deleted file mode 100644
--- a/Trace.hs
+++ /dev/null
@@ -1,143 +0,0 @@
-module Trace where
-import Scene
-import Data.List
-import Control.Concurrent.MVar
-import System.IO.Unsafe
---import Packet
-
-{-
-We put lighting code in this file because it needs to be 
-mutually recursive with the trace function, for refraction
-and reflection.
- -}
-
-data PacketColor = PacketColor !Color !Color !Color !Color
-
-
-{-
-simple_shade :: Rayint -> [Light] -> Solid -> Color -> Color
-simple_shade ri lights s bg =
- case ri of
-  (RayHit d p n t) ->
-   let (Material clr refl refr ior kd shine) = t ri
-   in cscale clr (vdot n (Vec 0.0 1.0 0.0))
-  (RayMiss) -> bg
--}
-
--- set rgb to normal's xyz coordinates
--- as a debugging aid
-debug_norm_shade :: Rayint -> Ray -> Scene -> Int -> Int -> Color
-debug_norm_shade ri (Ray o indir) scn recurs debug =
- case ri of
-  RayHit d p (Vec nx ny nz) t -> (Color (fabs $ nx/2) (fabs $ ny/2) (fabs $ nz/2))
-  RayMiss -> bground scn
-
--- no shadows, reflection, or lighting
-flat_shade :: Rayint -> Ray -> Scene -> Int -> Int -> Color
-flat_shade ri (Ray o indir) scn recurs debug =
- case ri of
-  RayMiss -> bground scn
-  RayHit d p n t -> 
-   let (Material clr refl refr ior kd shine) = t ri
-   in clr
-
--- handles diffuse light, shadows, specular highlights and reflection
--- todo: refraction
-shade :: Rayint -> Ray -> Scene -> Int -> Int -> Color
-shade ri (Ray o indir) scn recurs !debug = 
- case ri of
-  (RayHit d p n t) ->
-   let (Material clr refl_ refr ior kd shine) = t ri
-       s    = sld scn
-       lights = lits scn
-       direct = foldl' cadd c_black 
-                 (map (\ (Light lp lc) ->
-                   let eyedir = vinvert indir
-                       lvec = vsub lp p
-                       llen = vlen lvec
-                       ldir = vscale lvec (1.0/llen)   
-                       halfangle = bisect ldir eyedir
-                       ldotn  = fmax 0 $ vdot ldir n
-                       -- blinn  = fmax 0 ((vdot halfangle n)**(shine*3))
-                       blinn = fmax 0 $ ((vdot halfangle n) ** shine) * ldotn
-                       blinn_correct = if isNaN blinn then 0 else blinn
-                       -- indotn = fmax 0 $ vdot eyedir n
-                       intensity = 5.0 / (llen*llen)
-                       --intensity = 0.2
-                   in
-                    if vdot n lvec < 0 
-                    then c_black
-                    else
-                     if not $ shadow s (Ray (vscaleadd p n delta) ldir) (llen-(2*delta))
-                     then
-                       cadd 
-                        -- diffuse
-                        --c_black
-                        (cmul clr $ cscale lc $ ldotn * intensity)
-                        -- blinn/torrance-sparrow  highlight (pbrt p 440)
-                        (cscale lc $ blinn_correct * intensity)
-                        -- c_black
-                     else 
-                       c_black) lights)
-       reflect_ = 
-         if (refl_ > delta) && (recurs > 0)
-         then let outdir = reflect indir n 
-              in cscale (trace scn 
-                               (Ray (vscaleadd p outdir delta) outdir) 
-                               infinity (recurs-1) ) refl_
-         else c_black
-       refract = 
-         if (refr > delta) && (recurs > 0)
-         then c_black
-         else c_black
-       in
-         cadd direct $ cadd reflect_ refract
-
-  (RayMiss) -> bground scn
-
-trace :: Scene -> Ray -> Flt -> Int -> Color
-trace scn ray depth recurs =
- let (Scene sld lights cam dtex bgcolor) = scn 
- in shade (rayint sld ray depth dtex) ray scn recurs 0
-         
--- return depth as well as color, for post-processing effects
-trace_depth :: Scene -> Ray -> Flt -> Int -> (Color,Flt)
-trace_depth scn ray depth recurs =
- let (Scene sld lights cam dtex bgcolor) = scn 
-     ri = rayint sld ray depth dtex 
-     d = case ri of
-          RayHit d_ _ _ _ -> d_
-          RayMiss -> infinity
-     clr = shade ri ray scn recurs 0
- in (clr,d)
-
--- return hit position as well as color
-trace_pos :: Scene -> Ray -> Flt -> Int -> (Color,Vec)
-trace_pos scn ray depth recurs =
- let (Scene sld lights cam dtex bgcolor) = scn 
-     ri = rayint sld ray depth dtex 
-     p = case ri of
-          RayHit _ p _ _ -> p
-          RayMiss -> (Vec 0 0 0) -- fixme
-     clr = shade ri ray scn recurs 0
- in (clr,p)
-
-trace_debug :: Scene -> Ray -> Flt -> Int -> Color
-trace_debug scn ray depth recurs =
- let (Scene sld lights cam dtex bgcolor) = scn
-     (ri,n) = rayint_debug sld ray depth dtex
- in 
-  -- unsafePerformIO $
-  -- do
-  --  print n
-  --  return $ 
-  cadd (shade ri ray scn recurs 0) (Color 0 ((fromIntegral (Prelude.abs n)) * 0.01) 0)
-
-trace_packet :: Scene -> Ray -> Ray -> Ray -> Ray -> Flt -> Int -> PacketColor
-trace_packet scn ray1 ray2 ray3 ray4 depth recurs =
- let (Scene sld lights cam dtex bgcolor) = scn
-     PacketResult ri1 ri2 ri3 ri4 = packetint sld ray1 ray2 ray3 ray4 depth dtex
- in PacketColor (shade ri1 ray1 scn recurs 0)
-                (shade ri2 ray2 scn recurs 0)
-                (shade ri3 ray3 scn recurs 0)
-                (shade ri4 ray4 scn recurs 0)
diff --git a/Triangle.hs b/Triangle.hs
deleted file mode 100644
--- a/Triangle.hs
+++ /dev/null
@@ -1,135 +0,0 @@
-module Triangle where
-import Vec
-import Solid
-
--- Simple triangles, and triangles with normal vectors
--- specified at each vertex.
-
-data Triangle = Triangle Vec Vec Vec deriving Show
-data TriangleNorm = TriangleNorm Vec Vec Vec Vec Vec Vec deriving Show
-
-triangle :: Vec -> Vec -> Vec -> SolidItem
-triangle v1 v2 v3 =
- SolidItem (Triangle v1 v2 v3)
-
-triangles :: [Vec] -> [SolidItem]
-triangles (v1:vs) =
- zipWith (\v2 v3 -> triangle v1 v2 v3) vs (tail vs)  
-
-trianglenorm v1 v2 v3 n1 n2 n3 =
- SolidItem (TriangleNorm v1 v2 v3 n1 n2 n3)
-
-trianglesnorms :: [(Vec,Vec)] -> [SolidItem]
-trianglesnorms (vn1:vns) =
- zipWith (\vn2 vn3 -> trianglenorm (fst vn1) (fst vn2) (fst vn3)
-                                   (snd vn1) (snd vn2) (snd vn3))
-         vns (tail vns)
-
--- adaptation of Moller and Trumbore from pbrt page 127
-rayint_triangle :: Triangle -> Ray -> Flt -> Texture -> Rayint
-rayint_triangle (Triangle p1 p2 p3) (Ray o dir) dist tex =
- let e1 = vsub p2 p1
-     e2 = vsub p3 p1
-     s1 = vcross dir e2
-     divisor = vdot s1 e1
- in 
-   if (divisor == 0)
-   then RayMiss
-   else
-     let invdivisor = 1.0 / divisor
-         d = vsub o p1 
-         b1 = (vdot d s1) * invdivisor
-     in
-       if (b1 < 0) || (b1 > 1) 
-       then RayMiss 
-       else
-         let s2 = vcross d e1
-             b2 = (vdot dir s2) * invdivisor
-         in
-           if (b2 < 0) || (b1 + b2 > 1) 
-           then RayMiss
-           else
-             let t = (vdot e2 s2) * invdivisor
-           in
-             if (t < 0) || (t > dist)
-             then RayMiss
-             else
-               RayHit t (vscaleadd o dir t) (vnorm (vcross e1 e2)) tex
-
-rayint_trianglenorm :: TriangleNorm -> Ray -> Flt -> Texture -> Rayint
-rayint_trianglenorm (TriangleNorm p1 p2 p3 n1 n2 n3) (Ray o dir) dist tex =
- let e1 = vsub p2 p1
-     e2 = vsub p3 p1
-     s1 = vcross dir e2
-     divisor = vdot s1 e1
- in 
-   if (divisor == 0)
-   then RayMiss
-   else
-     let invdivisor = 1.0 / divisor
-         d = vsub o p1 
-         b1 = (vdot d s1) * invdivisor
-     in
-       if (b1 < 0) || (b1 > 1) 
-       then RayMiss 
-       else
-         let s2 = vcross d e1
-             b2 = (vdot dir s2) * invdivisor
-         in
-           if (b2 < 0) || (b1 + b2 > 1) 
-           then RayMiss
-           else
-             let t = (vdot e2 s2) * invdivisor
-           in
-             if (t < 0) || (t > dist)
-             then RayMiss
-             else
-               let n1scaled = (vscale n1 (1-(b1+b2))) 
-                   n2scaled = (vscale n2 b1)
-                   n3scaled = (vscale n3 b2)
-                   norm = vnorm $ vadd3 n1scaled n2scaled n3scaled
-               in RayHit t (vscaleadd o dir t) norm  tex
-
-bound_triangle :: Triangle -> Bbox
-bound_triangle (Triangle (Vec v1x v1y v1z) 
-                (Vec v2x v2y v2z) 
-                (Vec v3x v3y v3z)) =
- Bbox
-  (Vec ((fmin (fmin v1x v2x) v3x) - delta)
-       ((fmin (fmin v1y v2y) v3y) - delta)
-       ((fmin (fmin v1z v2z) v3z) - delta) )
-
-  (Vec ((fmax (fmax v1x v2x) v3x) + delta)
-       ((fmax (fmax v1y v2y) v3y) + delta)
-       ((fmax (fmax v1z v2z) v3z) + delta) )
-
-bound_trianglenorm :: TriangleNorm -> Bbox
-bound_trianglenorm (TriangleNorm v1 v2 v3 n1 n2 n3) =
- bound (Triangle v1 v2 v3)
-
-transform_triangle :: Triangle -> [Xfm] -> SolidItem
-transform_triangle (Triangle p1 p2 p3) xfms =
- SolidItem $ Triangle (xfm_point (compose xfms) p1)
-                      (xfm_point (compose xfms) p2)
-                      (xfm_point (compose xfms) p3)
-
-transform_trianglenorm :: TriangleNorm -> [Xfm] -> SolidItem
-transform_trianglenorm (TriangleNorm p1 p2 p3 n1 n2 n3) xfms =
- SolidItem $ TriangleNorm (xfm_point (compose xfms) p1)
-                          (xfm_point (compose xfms) p2)
-                          (xfm_point (compose xfms) p3)
-                          (vnorm $ xfm_vec (compose xfms) n1)
-                          (vnorm $ xfm_vec (compose xfms) n2)
-                          (vnorm $ xfm_vec (compose xfms) n3)
-
-instance Solid Triangle where
- rayint = rayint_triangle
- inside _ _ = False
- bound = bound_triangle
- transform = transform_triangle
-
-instance Solid TriangleNorm where
- rayint = rayint_trianglenorm
- inside _ _ = False
- bound = bound_trianglenorm
- transform = transform_trianglenorm
diff --git a/Vec.hs b/Vec.hs
deleted file mode 100644
--- a/Vec.hs
+++ /dev/null
@@ -1,525 +0,0 @@
-{-# OPTIONS_GHC -fexcess-precision #-}
--- make sure it gets enabled
--- (doesn't seem to help much, though)
-
-module Vec where
-
--- Performance is pretty similar with Floats or Doubles
--- best performance seems to be doubles with -fvia-C
-type Flt = Double
-
--- This is unnecessary, because haskell has sane mod
--- semantics, unlike ocaml and c.
-sane_mod :: Int -> Int -> Int
-sane_mod a b =
- let modres = mod a b in
-  if modres < 0 
-  then modres + b
-  else modres
-
--- maybe this is defined somewhere?
-infinity :: Flt
---infinity = 1.0 / 0.0
-infinity = 1000000.0
-
--- convert from degrees to native angle format (radians)
-deg :: Flt -> Flt
-deg !x = (x*3.1415926535897)/180
-
--- convert from radians (noop)
-rad :: Flt -> Flt
-rad !x = x
-
--- convert from rotations
-rot :: Flt -> Flt
-rot !x = x*3.1415926535897*2
-
-{-abs_sub :: Flt -> Flt -> Flt
-abs_sub a b =
- if a > 0.0
- then 
-  if b < a 
-  then a-b
-  else 0.0
- else
-  if b < (-a)
-  then a+b
-  else 0.0
--}
-
-clamp :: Flt -> Flt -> Flt -> Flt
-clamp !min !x !max
- | x < min = min
- | x > max = max
- | otherwise = x
-
--- delta = 0.00001 :: Flt
-delta = 0.0001 :: Flt
-
--- non-polymorphic versions; this speeds
--- things up in ocaml, not sure about haskell
-fmin :: Flt -> Flt -> Flt
-fmin !a !b = if a > b then b else a
-
-fmax :: Flt -> Flt -> Flt
-fmax !a !b = if a > b then a else b
-
-fmin3 :: Flt -> Flt -> Flt -> Flt
-fmin3 !a !b !c = if a > b 
-                 then if b > c 
-                      then c
-                      else b
-                 else if a > c
-                      then c
-                      else a
-
-fmax3 :: Flt -> Flt -> Flt -> Flt
-fmax3 !a !b !c = if a > b
-                 then if a > c
-                      then a
-                      else c
-                 else if b > c
-                      then b
-                      else c
-
-fmin4 :: Flt -> Flt -> Flt -> Flt -> Flt
-fmin4 !a !b !c !d = fmin (fmin a b) (fmin c d)
-
-fmax4 :: Flt -> Flt -> Flt -> Flt -> Flt
-fmax4 !a !b !c !d = fmax (fmax a b) (fmax c d)
-
-fabs :: Flt -> Flt
-fabs !a = 
- if a < 0 then (-a) else a
-
-iabs :: Int -> Int
-iabs !a =
- if a < 0 then (-a) else a
-
-abs a = error "use non-polymorphic version, fabs"
-
--- true if a and b are "almost" equal
--- the (abs $ a-b) test doesn't work if
--- a and b are large
-about_equal :: Flt -> Flt -> Bool
-about_equal !a !b =
- if a > 1 
- then
-  fabs (1 - (a/b)) < (delta*10) 
- else
-  (fabs $ a - b) < (delta*10)
-
-
-data Vec = Vec {x, y, z :: !Flt} deriving Show
-data Ray = Ray {origin, dir :: !Vec} deriving Show
---data Plane = Plane {norm :: !Vec, offset :: !Flt} deriving Show
-
-vec !x !y !z = (Vec x y z)
-vzero = Vec 0.0 0.0 0.0
-
--- for when we need a unit vector, but we 
--- don't care where it points
-vunit = vx
-
--- unit axis vectors
-vx  = Vec 1 0 0
-vy  = Vec 0 1 0
-vz  = Vec 0 0 1
-nvx = Vec (-1) 0 0
-nvy = Vec 0 (-1) 0
-nvz = Vec 0 0 (-1)
-
--- this actually accounts for a
--- noticeable amount of cpu time
-va :: Vec -> Int -> Flt
-va !(Vec x y z) !n = 
- case n of
-  0 -> x
-  1 -> y
-  2 -> z
-
-vset :: Vec -> Int -> Flt -> Vec
-vset !(Vec x y z) !i !f =
- case i of
-  0 -> Vec f y z
-  1 -> Vec x f z
-  2 -> Vec x y f
-
-vdot :: Vec -> Vec -> Flt
-vdot !(Vec x1 y1 z1) !(Vec x2 y2 z2) =
- (x1*x2)+(y1*y2)+(z1*z2)
-
-vcross :: Vec -> Vec -> Vec
-vcross !(Vec x1 y1 z1) !(Vec x2 y2 z2) =
- Vec 
-  ((y1 * z2) - (z1 * y2))
-  ((z1 * x2) - (x1 * z2))
-  ((x1 * y2) - (y1 * x2))
-
-vmap :: (Flt -> Flt) -> Vec -> Vec
-vmap f !v1 = 
- Vec (f (x v1)) (f (y v1)) (f (z v1))
-
-vmap2 :: (Flt -> Flt -> Flt) -> Vec -> Vec -> Vec
-vmap2 f !v1 !v2 =
- Vec (f (x v1) (x v2)) 
-     (f (y v1) (y v2)) 
-     (f (z v1) (z v2))
-
-vinvert :: Vec -> Vec
-vinvert !(Vec x1 y1 z1) =
- Vec (-x1) (-y1) (-z1)
-
-vlensqr :: Vec -> Flt
-vlensqr !v1 = vdot v1 v1
-
-vlen :: Vec -> Flt
-vlen !v1 = sqrt (vdot v1 v1)
-
-vadd :: Vec -> Vec -> Vec
-vadd !(Vec x1 y1 z1) !(Vec x2 y2 z2) =
- Vec (x1 + x2)
-     (y1 + y2)
-     (z1 + z2)
-
-vadd3 :: Vec -> Vec -> Vec -> Vec
-vadd3 !(Vec x1 y1 z1) !(Vec x2 y2 z2) !(Vec x3 y3 z3) =
-    Vec (x1 + x2 + x3)
-        (y1 + y2 + y3)
-        (z1 + z2 + z3)
-
-vsub :: Vec -> Vec -> Vec
-vsub !(Vec x1 y1 z1) !(Vec x2 y2 z2) =
- Vec (x1 - x2)
-     (y1 - y2)
-     (z1 - z2)
-
-vmul :: Vec -> Vec -> Vec
-vmul !(Vec x1 y1 z1) !(Vec x2 y2 z2) =
- Vec (x1 * x2)
-     (y1 * y2)
-     (z1 * z2)
-
-vinc :: Vec -> Flt -> Vec
-vinc !(Vec x y z) !n =
- Vec (x + n)
-     (y + n)
-     (z + n)
-
-vdec :: Vec -> Flt -> Vec
-vdec !(Vec x y z) !n =
- Vec (x - n)
-     (y - n)
-     (z - n)
-
-vmax :: Vec -> Vec -> Vec
-vmax !(Vec x1 y1 z1) !(Vec x2 y2 z2) =
- Vec (fmax x1 x2)
-     (fmax y1 y2)
-     (fmax z1 z2)
-
-vmin :: Vec -> Vec -> Vec
-vmin !(Vec x1 y1 z1) !(Vec x2 y2 z2) =
- Vec (fmin x1 x2)
-     (fmin y1 y2)
-     (fmin z1 z2)
-
-vmaxaxis :: Vec -> Int
-vmaxaxis !(Vec x y z) =
- if (x > y) 
- then if (x > z) 
-      then 0
-      else 2
- else if (y > z) 
-      then 1
-      else 2
-
-vscale :: Vec -> Flt -> Vec
-vscale !(Vec x y z) !fac =
- Vec (x * fac)
-     (y * fac)
-     (z * fac)
-
-vscaleadd :: Vec -> Vec -> Flt -> Vec
-vscaleadd !(Vec x1 y1 z1) !(Vec x2 y2 z2) fac =
- Vec (x1 + (x2 * fac))
-     (y1 + (y2 * fac))
-     (z1 + (z2 * fac))
-            
-vnorm :: Vec -> Vec
-vnorm !(Vec x1 y1 z1) = 
- let invlen = 1.0 / (sqrt ((x1*x1)+(y1*y1)+(z1*z1))) in
- Vec (x1*invlen) (y1*invlen) (z1*invlen)
-
-assert_norm :: Vec -> Vec
-assert_norm v =
- let l = vdot v v
- in if l > (1+delta) 
-    then error $ "vector too long" ++ (show v)
-    else if l < (1-delta)
-         then error $ "vector too short: " ++ (show v)
-         else v
-
-bisect :: Vec -> Vec -> Vec
-bisect !v1 !v2 = vnorm (vadd v1 v2)
-
-vdist :: Vec -> Vec -> Flt
-vdist v1 v2 = 
- let d = vsub v2 v1 in vlen d
-
-reflect :: Vec -> Vec -> Vec
-reflect !v !norm =
-  -- vadd v $ vscale norm $ (-2) * (vdot v norm)
-  vscaleadd v norm $ (-2) * (vdot v norm)
-
-vrcp :: Vec -> Vec
-vrcp !(Vec x y z) =
- Vec (1/x) (1/y) (1/z)
-
--- test for equality
-veq :: Vec -> Vec -> Bool
-veq !(Vec ax ay az) !(Vec bx by bz) =
- (about_equal ax bx) && (about_equal ay by) && (about_equal az bz)
-
---returns false on zero value
-veqsign :: Vec -> Vec -> Bool
-veqsign !(Vec ax ay az) !(Vec bx by bz) =
- ax*bx > 0 && ay*by > 0 && az*bz > 0
-
--- translate a ray's origin in ray's direction by d amount
-ray_move :: Ray -> Flt -> Ray
-ray_move !(Ray orig dir) !d =
- (Ray (vscaleadd orig dir d) dir)
-
--- find orthogonal vectors
-orth :: Vec -> (Vec,Vec)
-orth v1 =
- if about_equal (vdot v1 v1) 1
- then
-  let x = (Vec 1 0 0)
-      y = (Vec 0 1 0)
-      dvx = vdot v1 x
-      v2 = if dvx < 0.8 && dvx > (-0.8) -- don't want to cross with a
-           then vnorm $ vcross v1 x     -- vector that's too similar
-           else vnorm $ vcross v1 y
-      v3 = vcross v1 v2
-  in (v2,v3)
- else error $ "orth: unnormalized vector" ++ (show v1)
-
--- intersect a ray with a plane 
--- defined by a point and a normal
--- (ray need not be normalized)
-plane_int :: Ray -> Vec -> Vec -> Vec
-plane_int !(Ray orig dir) !p !norm =
- let newo = vsub orig p
-     dist = -(vdot norm newo) / (vdot norm dir)
- in vscaleadd orig dir dist
-
-plane_int_dist :: Ray -> Vec -> Vec -> Flt
-plane_int_dist !(Ray orig dir) !p !norm =
- let newo = vsub orig p
- in -(vdot norm newo) / (vdot norm dir)
-
--- find intersection with plane
--- from graphics gems -- an efficient ray-polygon intersection
--- it seems that the ray need not be normalized
--- let plane_intersect ray (n,d) =
---  let t = -.((d +. (vdot n ray.origin)) /. (vdot n ray.dir))
---  in vadd ray.origin (vscale ray.dir t)
-
-
--- TRANSFORMATIONS --
-
-data Matrix = Matrix !Flt !Flt !Flt !Flt  
-                     !Flt !Flt !Flt !Flt  
-                     !Flt !Flt !Flt !Flt deriving Show
-data Xfm = Xfm !Matrix !Matrix deriving Show
-
-ident_matrix = (Matrix 1 0 0 0  0 1 0 0  0 0 1 0)
-ident_xfm = Xfm ident_matrix ident_matrix
-
-mat_mult :: Matrix -> Matrix -> Matrix
-mat_mult (Matrix a00 a01 a02 a03  a10 a11 a12 a13  a20 a21 a22 a23)
-         (Matrix b00 b01 b02 b03  b10 b11 b12 b13  b20 b21 b22 b23) =
- Matrix
-   (a00*b00 + a01*b10 + a02*b20)
-   (a00*b01 + a01*b11 + a02*b21)
-   (a00*b02 + a01*b12 + a02*b22)
-   (a00*b03 + a01*b13 + a02*b23 + a03)
-
-   (a10*b00 + a11*b10 + a12*b20)
-   (a10*b01 + a11*b11 + a12*b21)
-   (a10*b02 + a11*b12 + a12*b22)
-   (a10*b03 + a11*b13 + a12*b23 + a13)
-
-   (a20*b00 + a21*b10 + a22*b20)
-   (a20*b01 + a21*b11 + a22*b21)
-   (a20*b02 + a21*b12 + a22*b22)
-   (a20*b03 + a21*b13 + a22*b23 + a23)
-
-xfm_mult :: Xfm -> Xfm -> Xfm
-xfm_mult (Xfm a inva) (Xfm b invb) =
- Xfm (mat_mult a b) (mat_mult invb inva)
-
--- TRANSFORM UTILITY FUNCTIONS --
-
--- If we multiply two transformation matricies, we get
--- a transformation matrix equivalent to applying the 
--- second then the first.
-
--- By reversing the list, the transforms are applied in the expected order.
-compose :: [Xfm] -> Xfm
-compose xfms = check_xfm $ foldr xfm_mult ident_xfm (reverse xfms)
-
-check_xfm :: Xfm -> Xfm
-check_xfm (Xfm m i) = 
- let (Matrix m00 m01 m02 m03  
-             m10 m11 m12 m13  
-             m20 m21 m22 m23) = mat_mult m i
-     ae = about_equal
- in
-  if ae m00 1 && ae m01 0 && ae m02 0 && ae m03 0 &&
-     ae m10 0 && ae m11 1 && ae m12 0 && ae m13 0 &&
-     ae m20 0 && ae m21 0 && ae m22 1 && ae m23 0
-  then (Xfm m i)
-  else error $ "corrupt matrix " ++ (show (Xfm m i)) ++ "\n" ++ (show (mat_mult m i)) 
-
--- rotate point (or vector) a about ray b by angle c
-vrotate :: Vec -> Ray -> Flt -> Vec
-vrotate pt (Ray orig axis_) angle =
- let axis = assert_norm axis_
-     transform = compose [ translate (vinvert orig)
-                         , rotate axis angle
-                         , translate orig
-                         ]
-     new_pt = xfm_point transform pt
- in if about_equal (vlen (vsub orig pt)) (vlen (vsub orig new_pt))
-    then new_pt
-    else error $ "something is wrong with vrotate" ++ 
-                 (show $ vlen (vsub orig pt)) ++ " " ++ 
-                 (show $ vlen (vsub orig new_pt))
-
-
--- TRANSFORM APPLICATION --
--- these need to be fast
-
--- point is treated as (x y z 1)
-xfm_point :: Xfm -> Vec -> Vec
-xfm_point !(Xfm (Matrix m00 m01 m02 m03  
-                        m10 m11 m12 m13  
-                        m20 m21 m22 m23) inv) 
-          !(Vec x y z) =
- Vec (m00*x + m01*y + m02*z + m03)
-     (m10*x + m11*y + m12*z + m13)
-     (m20*x + m21*y + m22*z + m23)
-
-invxfm_point :: Xfm -> Vec -> Vec
-invxfm_point !(Xfm fwd (Matrix i00 i01 i02 i03  
-                               i10 i11 i12 i13  
-                               i20 i21 i22 i23)) 
-             !(Vec x y z) =
-  Vec (i00*x + i01*y + i02*z + i03)
-      (i10*x + i11*y + i12*z + i13)
-      (i20*x + i21*y + i22*z + i23)
-
--- vector is treated as (x y z 0)
-xfm_vec :: Xfm -> Vec -> Vec
-xfm_vec !(Xfm (Matrix m00 m01 m02 m03  
-                      m10 m11 m12 m13  
-                      m20 m21 m22 m23) inv) 
-        !(Vec x y z) =
- Vec (m00*x + m01*y + m02*z)
-     (m10*x + m11*y + m12*z)
-     (m20*x + m21*y + m22*z)
-
-invxfm_vec :: Xfm -> Vec -> Vec
-invxfm_vec !(Xfm fwd (Matrix i00 i01 i02 i03  
-                             i10 i11 i12 i13  
-                             i20 i21 i22 i23)) 
-           !(Vec x y z) =
-  Vec (i00*x + i01*y + i02*z)
-      (i10*x + i11*y + i12*z)
-      (i20*x + i21*y + i22*z)
-
--- this one is tricky
--- we transform by the inverse transpose
-invxfm_norm :: Xfm -> Vec -> Vec
-invxfm_norm !(Xfm fwd (Matrix i00 i01 i02 i03  
-                              i10 i11 i12 i13  
-                              i20 i21 i22 i23)) 
-            !(Vec x y z) =
- Vec (i00*x + i10*y + i20*z)
-     (i01*x + i11*y + i21*z)
-     (i02*x + i12*y + i22*z)
-
-xfm_ray :: Xfm -> Ray -> Ray
-xfm_ray !xfm !(Ray orig dir) =
- Ray (xfm_point xfm orig) (vnorm (xfm_vec xfm dir))
-
-invxfm_ray !xfm !(Ray orig dir) =
- Ray (invxfm_point xfm orig) (vnorm (invxfm_vec xfm dir))
-
--- BASIC TRANSFORMS --
--- move
-translate :: Vec -> Xfm
-translate (Vec x y z) =
- check_xfm $ Xfm (Matrix 1 0 0   x   0 1 0   y   0 0 1   z) 
-                 (Matrix 1 0 0 (-x)  0 1 0 (-y)  0 0 1 (-z))
-
--- strectch along three axes (if x==y==z, then it's uniform scaling)
-scale :: Vec -> Xfm
-scale (Vec x y z) =
- check_xfm $ Xfm (Matrix   x  0 0 0  0   y  0 0  0 0   z  0)
-                (Matrix (1/x) 0 0 0  0 (1/y) 0 0  0 0 (1/z) 0)
-
--- rotate about an arbitrary axis and angle
-rotate :: Vec -> Flt -> Xfm
-rotate (Vec x y z) angle =
- if not $ (vlen (Vec x y z)) `about_equal` 1
- then error $ "please use a normalized vector for rotation: " ++ (show (vlen (Vec x y z)))
- else 
-  let s = sin angle
-      c = cos angle 
-
-      m00 = ((x*x)+((1-(x*x))*c)) 
-      m01 = (((x*y)*(1-c))-(z*s)) 
-      m02 = ((x*z*(1-c))+(y*s))
-
-      m10 = (((x*y)*(1-c))+(z*s))
-      m11 = ((y*y)+((1-(y*y))*c))
-      m12 = ((y*z*(1-c))-(x*s))
-
-      m20 = ((x*z*(1-c))-(y*s))
-      m21 = ((y*z*(1-c))+(x*s))
-      m22 = ((z*z)+((1-(z*z))*c))
-  in
-  check_xfm $ Xfm (Matrix m00 m01 m02 0  m10 m11 m12 0  m20 m21 m22 0)
-                  (Matrix m00 m10 m20 0  m01 m11 m21 0  m02 m12 m22 0)
-
--- convert canonical coordinates to uvw coordinates
-xyz_to_uvw :: Vec -> Vec -> Vec -> Xfm
-xyz_to_uvw u v w =
- let Vec ux uy uz = u
-     Vec vx vy vz = v
-     Vec wx wy wz = w
- in if (vdot u u) `about_equal` 1
-    then
-     if (vdot v v) `about_equal` 1
-     then
-      if (vdot w w) `about_equal` 1
-      then 
-       if ((vdot u v) `about_equal` 0) && 
-          ((vdot u w) `about_equal` 0) && 
-          ((vdot v w) `about_equal` 0)
-       then
-        check_xfm $ Xfm (Matrix ux vx wx 0  uy vy wy 0  uz vz wz 0)
-                        (Matrix ux uy uz 0  vx vy vz 0  wx wy wz 0)
-       else error  "vectors aren't orthogonal"
-      else error $ "unnormalized w " ++ (show w)
-     else error $ "unnormalized v " ++ (show v)
-    else error $ "unnormalized u " ++ (show u)
-
-uvw_to_xyz :: Vec -> Vec -> Vec -> Xfm
-uvw_to_xyz (Vec ux uy uz) (Vec vx vy vz) (Vec wx wy wz) =
- check_xfm $ Xfm (Matrix ux uy uz 0  vx vy vz 0  wx wy wz 0)
-                 (Matrix ux vx wx 0  uy vy wy 0  uz vz wz 0)
diff --git a/balls3.spd b/balls3.spd
deleted file mode 100644
--- a/balls3.spd
+++ /dev/null
@@ -1,838 +0,0 @@
-b 0.078 0.361 0.753
-v
-from 2.1 1.3 1.7
-at 0 0 0
-up 0 0 1
-angle 45
-hither 0.01
-resolution 512 512
-l 4 3 2
-l 1 -4 4
-l -3 1 5
-f 1 0.75 0.33 0.8 0 100000 0 1
-p 4
-12 12 -0.5
--12 12 -0.5
--12 -12 -0.5
-12 -12 -0.5
-f 1 0.9 0.7 0.5 0.5 3.0827 0 1
-s 0 0 0 0.5
-s 0.272166 0.272166 0.544331 0.166667
-s 0.420314 0.420314 0.618405 0.0555556
-s 0.470715 0.470715 0.598245 0.0185185
-s 0.461623 0.409245 0.557924 0.0185185
-s 0.409245 0.461623 0.557924 0.0185185
-s 0.429405 0.481784 0.658726 0.0185185
-s 0.367935 0.472692 0.618405 0.0185185
-s 0.379004 0.431383 0.678886 0.0185185
-s 0.481784 0.429405 0.658726 0.0185185
-s 0.431383 0.379004 0.678886 0.0185185
-s 0.472692 0.367935 0.618405 0.0185185
-s 0.461844 0.304709 0.43322 0.0555556
-s 0.492085 0.33495 0.372739 0.0185185
-s 0.424345 0.305171 0.369341 0.0185185
-s 0.435193 0.368397 0.406378 0.0185185
-s 0.529584 0.334488 0.436618 0.0185185
-s 0.472692 0.367935 0.470257 0.0185185
-s 0.499343 0.304247 0.497099 0.0185185
-s 0.518736 0.271262 0.399581 0.0185185
-s 0.488495 0.241021 0.460062 0.0185185
-s 0.450996 0.241483 0.396183 0.0185185
-s 0.304709 0.461844 0.43322 0.0555556
-s 0.33495 0.492085 0.372739 0.0185185
-s 0.368397 0.435193 0.406378 0.0185185
-s 0.305171 0.424345 0.369341 0.0185185
-s 0.271262 0.518736 0.399581 0.0185185
-s 0.241483 0.450996 0.396183 0.0185185
-s 0.241021 0.488495 0.460062 0.0185185
-s 0.334488 0.529584 0.436618 0.0185185
-s 0.304247 0.499343 0.497099 0.0185185
-s 0.367935 0.472692 0.470257 0.0185185
-s 0.230635 0.38777 0.729516 0.0555556
-s 0.2506 0.446614 0.769837 0.0185185
-s 0.301839 0.407906 0.732914 0.0185185
-s 0.253236 0.449775 0.695877 0.0185185
-s 0.179397 0.426478 0.766439 0.0185185
-s 0.182032 0.429639 0.692479 0.0185185
-s 0.159431 0.367634 0.726118 0.0185185
-s 0.227999 0.384609 0.803476 0.0185185
-s 0.208034 0.325765 0.763155 0.0185185
-s 0.279238 0.345901 0.766553 0.0185185
-s 0.115031 0.4293 0.544331 0.0555556
-s 0.102505 0.502308 0.544331 0.0185185
-s 0.160392 0.474661 0.581368 0.0185185
-s 0.160392 0.474661 0.507294 0.0185185
-s 0.0571437 0.456947 0.507294 0.0185185
-s 0.115031 0.4293 0.470257 0.0185185
-s 0.0696698 0.383939 0.507294 0.0185185
-s 0.0571437 0.456947 0.581368 0.0185185
-s 0.0696698 0.383939 0.581368 0.0185185
-s 0.115031 0.4293 0.618405 0.0185185
-s 0.082487 0.239622 0.655442 0.0555556
-s 0.0438957 0.258053 0.715923 0.0185185
-s 0.117687 0.252557 0.719322 0.0185185
-s 0.0863845 0.308551 0.682285 0.0185185
-s 0.00869528 0.245118 0.652044 0.0185185
-s 0.0511841 0.295616 0.618405 0.0185185
-s 0.0472866 0.226687 0.591563 0.0185185
-s 0.0399982 0.189123 0.689081 0.0185185
-s 0.0785895 0.170692 0.6286 0.0185185
-s 0.11379 0.183628 0.692479 0.0185185
-s 0.38777 0.230635 0.729516 0.0555556
-s 0.446614 0.2506 0.769837 0.0185185
-s 0.449775 0.253236 0.695877 0.0185185
-s 0.407906 0.301839 0.732914 0.0185185
-s 0.384609 0.227999 0.803476 0.0185185
-s 0.345901 0.279238 0.766553 0.0185185
-s 0.325765 0.208034 0.763155 0.0185185
-s 0.426478 0.179397 0.766439 0.0185185
-s 0.367634 0.159431 0.726118 0.0185185
-s 0.429639 0.182032 0.692479 0.0185185
-s 0.239622 0.082487 0.655442 0.0555556
-s 0.258053 0.0438957 0.715923 0.0185185
-s 0.308551 0.0863845 0.682285 0.0185185
-s 0.252557 0.117687 0.719322 0.0185185
-s 0.189123 0.0399982 0.689081 0.0185185
-s 0.183628 0.11379 0.692479 0.0185185
-s 0.170692 0.0785895 0.6286 0.0185185
-s 0.245118 0.00869528 0.652044 0.0185185
-s 0.226687 0.0472866 0.591563 0.0185185
-s 0.295616 0.0511841 0.618405 0.0185185
-s 0.4293 0.115031 0.544331 0.0555556
-s 0.502308 0.102505 0.544331 0.0185185
-s 0.474661 0.160392 0.507294 0.0185185
-s 0.474661 0.160392 0.581368 0.0185185
-s 0.456947 0.0571437 0.581368 0.0185185
-s 0.4293 0.115031 0.618405 0.0185185
-s 0.383939 0.0696698 0.581368 0.0185185
-s 0.456947 0.0571437 0.507294 0.0185185
-s 0.383939 0.0696698 0.507294 0.0185185
-s 0.4293 0.115031 0.470257 0.0185185
-s 0.643951 0.172546 1.11022e-16 0.166667
-s 0.802608 0.281471 -0.111111 0.0555556
-s 0.824035 0.30566 -0.177765 0.0185185
-s 0.787796 0.241352 -0.171592 0.0185185
-s 0.752156 0.305221 -0.15987 0.0185185
-s 0.838847 0.34578 -0.117284 0.0185185
-s 0.766968 0.345341 -0.099389 0.0185185
-s 0.817421 0.321591 -0.0506299 0.0185185
-s 0.874487 0.28191 -0.129006 0.0185185
-s 0.853061 0.257721 -0.062352 0.0185185
-s 0.838248 0.217602 -0.122833 0.0185185
-s 0.643951 0.172546 -0.222222 0.0555556
-s 0.61371 0.202787 -0.282703 0.0185185
-s 0.5724 0.191718 -0.222222 0.0185185
-s 0.624779 0.244096 -0.222222 0.0185185
-s 0.68526 0.183615 -0.282703 0.0185185
-s 0.696329 0.224924 -0.222222 0.0185185
-s 0.715501 0.153374 -0.222222 0.0185185
-s 0.632882 0.131237 -0.282703 0.0185185
-s 0.663122 0.100996 -0.222222 0.0185185
-s 0.591572 0.120168 -0.222222 0.0185185
-s 0.594141 0.358439 -0.111111 0.0555556
-s 0.619127 0.408291 -0.15987 0.0185185
-s 0.665691 0.37761 -0.111111 0.0185185
-s 0.638217 0.337042 -0.166667 0.0185185
-s 0.547576 0.389119 -0.15987 0.0185185
-s 0.566667 0.317871 -0.166667 0.0185185
-s 0.522591 0.339267 -0.111111 0.0185185
-s 0.57505 0.429687 -0.104315 0.0185185
-s 0.550064 0.379835 -0.0555556 0.0185185
-s 0.621614 0.399007 -0.0555556 0.0185185
-s 0.802608 0.281471 0.111111 0.0555556
-s 0.858698 0.329459 0.104938 0.0185185
-s 0.845371 0.280879 0.0506299 0.0185185
-s 0.798572 0.337088 0.062352 0.0185185
-s 0.815936 0.330051 0.165419 0.0185185
-s 0.75581 0.33768 0.122833 0.0185185
-s 0.759846 0.282063 0.171592 0.0185185
-s 0.862735 0.273842 0.153697 0.0185185
-s 0.806645 0.225855 0.15987 0.0185185
-s 0.849407 0.225263 0.099389 0.0185185
-s 0.594141 0.358439 0.111111 0.0555556
-s 0.613592 0.428945 0.122833 0.0185185
-s 0.665691 0.37761 0.111111 0.0185185
-s 0.621614 0.399007 0.0555556 0.0185185
-s 0.542042 0.409774 0.122833 0.0185185
-s 0.550064 0.379835 0.0555556 0.0185185
-s 0.522591 0.339267 0.111111 0.0185185
-s 0.586119 0.388377 0.178389 0.0185185
-s 0.566667 0.317871 0.166667 0.0185185
-s 0.638217 0.337042 0.166667 0.0185185
-s 0.643951 0.172546 0.222222 0.0555556
-s 0.674191 0.202787 0.282703 0.0185185
-s 0.715501 0.191718 0.222222 0.0185185
-s 0.663122 0.244096 0.222222 0.0185185
-s 0.602641 0.183615 0.282703 0.0185185
-s 0.591572 0.224924 0.222222 0.0185185
-s 0.5724 0.153374 0.222222 0.0185185
-s 0.655019 0.131237 0.282703 0.0185185
-s 0.624779 0.100996 0.222222 0.0185185
-s 0.696329 0.120168 0.222222 0.0185185
-s 0.852418 0.0955788 1.89979e-16 0.0555556
-s 0.922609 0.11107 -0.0178949 0.0185185
-s 0.867231 0.135698 -0.0604812 0.0185185
-s 0.877966 0.164775 0.00679642 0.0185185
-s 0.907797 0.0709499 0.0425863 0.0185185
-s 0.863153 0.124655 0.0672777 0.0185185
-s 0.837606 0.0554592 0.0604812 0.0185185
-s 0.897062 0.0418734 -0.0246914 0.0185185
-s 0.826871 0.0263827 -0.00679642 0.0185185
-s 0.841683 0.0665023 -0.0672777 0.0185185
-s 0.69376 -0.0133465 0.111111 0.0555556
-s 0.740325 -0.0440268 0.15987 0.0185185
-s 0.76531 0.0058253 0.111111 0.0185185
-s 0.721234 0.0272215 0.166667 0.0185185
-s 0.668775 -0.0631985 0.15987 0.0185185
-s 0.649684 0.00804971 0.166667 0.0185185
-s 0.62221 -0.0325183 0.111111 0.0185185
-s 0.712851 -0.0845947 0.104315 0.0185185
-s 0.666287 -0.0539145 0.0555556 0.0185185
-s 0.737837 -0.0347427 0.0555556 0.0185185
-s 0.69376 -0.0133465 -0.111111 0.0555556
-s 0.745859 -0.0646815 -0.122833 0.0185185
-s 0.76531 0.0058253 -0.111111 0.0185185
-s 0.737837 -0.0347427 -0.0555556 0.0185185
-s 0.674309 -0.0838533 -0.122833 0.0185185
-s 0.666287 -0.0539145 -0.0555556 0.0185185
-s 0.62221 -0.0325183 -0.111111 0.0185185
-s 0.701782 -0.0432853 -0.178389 0.0185185
-s 0.649684 0.00804971 -0.166667 0.0185185
-s 0.721234 0.0272215 -0.166667 0.0185185
-s 0.172546 0.643951 1.11022e-16 0.166667
-s 0.281471 0.802608 -0.111111 0.0555556
-s 0.30566 0.824035 -0.177765 0.0185185
-s 0.305221 0.752156 -0.15987 0.0185185
-s 0.241352 0.787796 -0.171592 0.0185185
-s 0.28191 0.874487 -0.129006 0.0185185
-s 0.217602 0.838248 -0.122833 0.0185185
-s 0.257721 0.853061 -0.062352 0.0185185
-s 0.34578 0.838847 -0.117284 0.0185185
-s 0.321591 0.817421 -0.0506299 0.0185185
-s 0.345341 0.766968 -0.099389 0.0185185
-s 0.358439 0.594141 -0.111111 0.0555556
-s 0.408291 0.619127 -0.15987 0.0185185
-s 0.337042 0.638217 -0.166667 0.0185185
-s 0.37761 0.665691 -0.111111 0.0185185
-s 0.429687 0.57505 -0.104315 0.0185185
-s 0.399007 0.621614 -0.0555556 0.0185185
-s 0.379835 0.550064 -0.0555556 0.0185185
-s 0.389119 0.547576 -0.15987 0.0185185
-s 0.339267 0.522591 -0.111111 0.0185185
-s 0.317871 0.566667 -0.166667 0.0185185
-s 0.172546 0.643951 -0.222222 0.0555556
-s 0.142305 0.674191 -0.282703 0.0185185
-s 0.100996 0.663122 -0.222222 0.0185185
-s 0.153374 0.715501 -0.222222 0.0185185
-s 0.213855 0.655019 -0.282703 0.0185185
-s 0.224924 0.696329 -0.222222 0.0185185
-s 0.244096 0.624779 -0.222222 0.0185185
-s 0.161477 0.602641 -0.282703 0.0185185
-s 0.191718 0.5724 -0.222222 0.0185185
-s 0.120168 0.591572 -0.222222 0.0185185
-s 0.0955788 0.852418 1.03629e-16 0.0555556
-s 0.11107 0.922609 -0.0178949 0.0185185
-s 0.164775 0.877966 0.00679642 0.0185185
-s 0.135698 0.867231 -0.0604812 0.0185185
-s 0.0418734 0.897062 -0.0246914 0.0185185
-s 0.0665023 0.841683 -0.0672777 0.0185185
-s 0.0263827 0.826871 -0.00679642 0.0185185
-s 0.0709499 0.907797 0.0425863 0.0185185
-s 0.0554592 0.837606 0.0604812 0.0185185
-s 0.124655 0.863153 0.0672777 0.0185185
-s -0.0133465 0.69376 -0.111111 0.0555556
-s -0.0646815 0.745859 -0.122833 0.0185185
-s -0.0347427 0.737837 -0.0555556 0.0185185
-s 0.0058253 0.76531 -0.111111 0.0185185
-s -0.0432853 0.701782 -0.178389 0.0185185
-s 0.0272215 0.721234 -0.166667 0.0185185
-s 0.00804971 0.649684 -0.166667 0.0185185
-s -0.0838533 0.674309 -0.122833 0.0185185
-s -0.0325183 0.62221 -0.111111 0.0185185
-s -0.0539145 0.666287 -0.0555556 0.0185185
-s -0.0133465 0.69376 0.111111 0.0555556
-s -0.0440268 0.740325 0.15987 0.0185185
-s 0.0272215 0.721234 0.166667 0.0185185
-s 0.0058253 0.76531 0.111111 0.0185185
-s -0.0845947 0.712851 0.104315 0.0185185
-s -0.0347427 0.737837 0.0555556 0.0185185
-s -0.0539145 0.666287 0.0555556 0.0185185
-s -0.0631985 0.668775 0.15987 0.0185185
-s -0.0325183 0.62221 0.111111 0.0185185
-s 0.00804971 0.649684 0.166667 0.0185185
-s 0.281471 0.802608 0.111111 0.0555556
-s 0.329459 0.858698 0.104938 0.0185185
-s 0.337088 0.798572 0.062352 0.0185185
-s 0.280879 0.845371 0.0506299 0.0185185
-s 0.273842 0.862735 0.153697 0.0185185
-s 0.225263 0.849407 0.099389 0.0185185
-s 0.225855 0.806645 0.15987 0.0185185
-s 0.330051 0.815936 0.165419 0.0185185
-s 0.282063 0.759846 0.171592 0.0185185
-s 0.33768 0.75581 0.122833 0.0185185
-s 0.172546 0.643951 0.222222 0.0555556
-s 0.202787 0.674191 0.282703 0.0185185
-s 0.244096 0.663122 0.222222 0.0185185
-s 0.191718 0.715501 0.222222 0.0185185
-s 0.131237 0.655019 0.282703 0.0185185
-s 0.120168 0.696329 0.222222 0.0185185
-s 0.100996 0.624779 0.222222 0.0185185
-s 0.183615 0.602641 0.282703 0.0185185
-s 0.153374 0.5724 0.222222 0.0185185
-s 0.224924 0.591572 0.222222 0.0185185
-s 0.358439 0.594141 0.111111 0.0555556
-s 0.428945 0.613592 0.122833 0.0185185
-s 0.399007 0.621614 0.0555556 0.0185185
-s 0.37761 0.665691 0.111111 0.0185185
-s 0.388377 0.586119 0.178389 0.0185185
-s 0.337042 0.638217 0.166667 0.0185185
-s 0.317871 0.566667 0.166667 0.0185185
-s 0.409774 0.542042 0.122833 0.0185185
-s 0.339267 0.522591 0.111111 0.0185185
-s 0.379835 0.550064 0.0555556 0.0185185
-s -0.371785 0.0996195 0.544331 0.166667
-s -0.393621 0.220501 0.729516 0.0555556
-s -0.368601 0.279642 0.766439 0.0185185
-s -0.321889 0.238665 0.726118 0.0185185
-s -0.372464 0.281062 0.692479 0.0185185
-s -0.440333 0.261479 0.769837 0.0185185
-s -0.444196 0.262898 0.695877 0.0185185
-s -0.465353 0.202338 0.732914 0.0185185
-s -0.389758 0.219082 0.803476 0.0185185
-s -0.414778 0.15994 0.766553 0.0185185
-s -0.343046 0.178104 0.763155 0.0185185
-s -0.191247 0.166275 0.655442 0.0555556
-s -0.130089 0.20793 0.652044 0.0185185
-s -0.154295 0.172673 0.591563 0.0185185
-s -0.192135 0.230419 0.618405 0.0185185
-s -0.167041 0.201532 0.715923 0.0185185
-s -0.229087 0.224021 0.682285 0.0185185
-s -0.228199 0.159877 0.719322 0.0185185
-s -0.129201 0.143787 0.689081 0.0185185
-s -0.190359 0.102131 0.692479 0.0185185
-s -0.153407 0.108529 0.6286 0.0185185
-s -0.31427 0.31427 0.544331 0.0555556
-s -0.277961 0.367156 0.507294 0.0185185
-s -0.252306 0.297666 0.507294 0.0185185
-s -0.31427 0.31427 0.470257 0.0185185
-s -0.339925 0.383759 0.544331 0.0185185
-s -0.376234 0.330873 0.507294 0.0185185
-s -0.376234 0.330873 0.581368 0.0185185
-s -0.277961 0.367156 0.581368 0.0185185
-s -0.31427 0.31427 0.618405 0.0185185
-s -0.252306 0.297666 0.581368 0.0185185
-s -0.574159 0.153845 0.618405 0.0555556
-s -0.612768 0.202534 0.658726 0.0185185
-s -0.543919 0.184086 0.678886 0.0185185
-s -0.554987 0.225396 0.618405 0.0185185
-s -0.643008 0.172294 0.598245 0.0185185
-s -0.585228 0.195155 0.557924 0.0185185
-s -0.6044 0.123605 0.557924 0.0185185
-s -0.631939 0.130984 0.658726 0.0185185
-s -0.593331 0.0822954 0.618405 0.0185185
-s -0.56309 0.112536 0.678886 0.0185185
-s -0.494808 0.247614 0.43322 0.0555556
-s -0.494287 0.313607 0.399581 0.0185185
-s -0.452978 0.302539 0.460062 0.0185185
-s -0.434629 0.269833 0.396183 0.0185185
-s -0.536117 0.258683 0.372739 0.0185185
-s -0.476459 0.214908 0.369341 0.0185185
-s -0.536638 0.19269 0.406378 0.0185185
-s -0.554467 0.291389 0.436618 0.0185185
-s -0.554987 0.225396 0.470257 0.0185185
-s -0.513157 0.28032 0.497099 0.0185185
-s -0.552323 0.0329639 0.43322 0.0555556
-s -0.625877 0.0248832 0.436618 0.0185185
-s -0.584567 0.0138144 0.497099 0.0185185
-s -0.593331 0.0822954 0.470257 0.0185185
-s -0.593633 0.0440327 0.372739 0.0185185
-s -0.561087 0.101445 0.406378 0.0185185
-s -0.520079 0.0521134 0.369341 0.0185185
-s -0.584869 -0.0244483 0.399581 0.0185185
-s -0.511316 -0.0163676 0.396183 0.0185185
-s -0.54356 -0.0355172 0.460062 0.0185185
-s -0.451136 0.0058509 0.729516 0.0555556
-s -0.447081 0.0051487 0.803476 0.0185185
-s -0.386138 0.0172804 0.763155 0.0185185
-s -0.439178 0.0688765 0.766553 0.0185185
-s -0.512079 -0.00628079 0.769837 0.0185185
-s -0.504176 0.0574471 0.732914 0.0185185
-s -0.516134 -0.00557859 0.695877 0.0185185
-s -0.459039 -0.0578769 0.766439 0.0185185
-s -0.463094 -0.0571747 0.692479 0.0185185
-s -0.398096 -0.0457452 0.726118 0.0185185
-s -0.4293 -0.115031 0.544331 0.0555556
-s -0.424299 -0.178985 0.581368 0.0185185
-s -0.367336 -0.131634 0.581368 0.0185185
-s -0.4293 -0.115031 0.618405 0.0185185
-s -0.486264 -0.162382 0.544331 0.0185185
-s -0.491265 -0.0984274 0.581368 0.0185185
-s -0.491265 -0.0984274 0.507294 0.0185185
-s -0.424299 -0.178985 0.507294 0.0185185
-s -0.4293 -0.115031 0.470257 0.0185185
-s -0.367336 -0.131634 0.507294 0.0185185
-s -0.248762 -0.0483751 0.655442 0.0555556
-s -0.183785 -0.0599222 0.689081 0.0185185
-s -0.187119 -0.0172857 0.6286 0.0185185
-s -0.215921 0.00673113 0.692479 0.0185185
-s -0.245428 -0.0910116 0.715923 0.0185185
-s -0.277564 -0.0243582 0.719322 0.0185185
-s -0.310405 -0.0794645 0.682285 0.0185185
-s -0.216626 -0.115028 0.652044 0.0185185
-s -0.281603 -0.103481 0.618405 0.0185185
-s -0.21996 -0.0723919 0.591563 0.0185185
-s -0.471405 0.471405 1.11022e-16 0.166667
-s -0.508983 0.690426 8.51251e-17 0.0555556
-s -0.484794 0.755941 -0.0246914 0.0185185
-s -0.436283 0.7029 -0.00679642 0.0185185
-s -0.478434 0.695668 -0.0672777 0.0185185
-s -0.557494 0.743468 -0.0178949 0.0185185
-s -0.551134 0.683194 -0.0604812 0.0185185
-s -0.581682 0.677953 0.00679642 0.0185185
-s -0.515343 0.7507 0.0425863 0.0185185
-s -0.539531 0.685185 0.0672777 0.0185185
-s -0.466832 0.697658 0.0604812 0.0185185
-s -0.335322 0.607487 0.111111 0.0555556
-s -0.283164 0.659645 0.104315 0.0185185
-s -0.286452 0.603979 0.0555556 0.0185185
-s -0.33883 0.656357 0.0555556 0.0185185
-s -0.332034 0.663153 0.15987 0.0185185
-s -0.3877 0.659866 0.111111 0.0185185
-s -0.384191 0.610996 0.166667 0.0185185
-s -0.279656 0.610775 0.15987 0.0185185
-s -0.331813 0.558618 0.166667 0.0185185
-s -0.282943 0.555109 0.111111 0.0185185
-s -0.335322 0.607487 -0.111111 0.0555556
-s -0.313405 0.629404 -0.178389 0.0185185
-s -0.331813 0.558618 -0.166667 0.0185185
-s -0.384191 0.610996 -0.166667 0.0185185
-s -0.316914 0.678274 -0.122833 0.0185185
-s -0.3877 0.659866 -0.111111 0.0185185
-s -0.33883 0.656357 -0.0555556 0.0185185
-s -0.264535 0.625895 -0.122833 0.0185185
-s -0.286452 0.603979 -0.0555556 0.0185185
-s -0.282943 0.555109 -0.111111 0.0185185
-s -0.645066 0.554344 -0.111111 0.0555556
-s -0.681385 0.616373 -0.129006 0.0185185
-s -0.649723 0.609912 -0.062352 0.0185185
-s -0.607573 0.617144 -0.122833 0.0185185
-s -0.676727 0.560805 -0.177765 0.0185185
-s -0.602915 0.561576 -0.171592 0.0185185
-s -0.640408 0.498776 -0.15987 0.0185185
-s -0.718878 0.553573 -0.117284 0.0185185
-s -0.682558 0.491544 -0.099389 0.0185185
-s -0.687216 0.547112 -0.0506299 0.0185185
-s -0.471405 0.471405 -0.222222 0.0555556
-s -0.501645 0.501645 -0.282703 0.0185185
-s -0.542955 0.490576 -0.222222 0.0185185
-s -0.490576 0.542955 -0.222222 0.0185185
-s -0.430095 0.482473 -0.282703 0.0185185
-s -0.419026 0.523783 -0.222222 0.0185185
-s -0.399854 0.452233 -0.222222 0.0185185
-s -0.482473 0.430095 -0.282703 0.0185185
-s -0.452233 0.399854 -0.222222 0.0185185
-s -0.523783 0.419026 -0.222222 0.0185185
-s -0.607487 0.335322 -0.111111 0.0555556
-s -0.659645 0.283164 -0.104315 0.0185185
-s -0.603979 0.286452 -0.0555556 0.0185185
-s -0.656357 0.33883 -0.0555556 0.0185185
-s -0.663153 0.332034 -0.15987 0.0185185
-s -0.659866 0.3877 -0.111111 0.0185185
-s -0.610996 0.384191 -0.166667 0.0185185
-s -0.610775 0.279656 -0.15987 0.0185185
-s -0.558618 0.331813 -0.166667 0.0185185
-s -0.555109 0.282943 -0.111111 0.0185185
-s -0.645066 0.554344 0.111111 0.0555556
-s -0.668521 0.610229 0.153697 0.0185185
-s -0.598918 0.585648 0.15987 0.0185185
-s -0.619787 0.622977 0.099389 0.0185185
-s -0.714669 0.578925 0.104938 0.0185185
-s -0.665934 0.591673 0.0506299 0.0185185
-s -0.691213 0.52304 0.062352 0.0185185
-s -0.6938 0.541596 0.165419 0.0185185
-s -0.670344 0.48571 0.122833 0.0185185
-s -0.624197 0.517014 0.171592 0.0185185
-s -0.607487 0.335322 0.111111 0.0555556
-s -0.629404 0.313405 0.178389 0.0185185
-s -0.558618 0.331813 0.166667 0.0185185
-s -0.610996 0.384191 0.166667 0.0185185
-s -0.678274 0.316914 0.122833 0.0185185
-s -0.659866 0.3877 0.111111 0.0185185
-s -0.656357 0.33883 0.0555556 0.0185185
-s -0.625895 0.264535 0.122833 0.0185185
-s -0.603979 0.286452 0.0555556 0.0185185
-s -0.555109 0.282943 0.111111 0.0185185
-s -0.471405 0.471405 0.222222 0.0555556
-s -0.441164 0.501645 0.282703 0.0185185
-s -0.399854 0.490576 0.222222 0.0185185
-s -0.452233 0.542955 0.222222 0.0185185
-s -0.512714 0.482473 0.282703 0.0185185
-s -0.523783 0.523783 0.222222 0.0185185
-s -0.542955 0.452233 0.222222 0.0185185
-s -0.460336 0.430095 0.282703 0.0185185
-s -0.490576 0.399854 0.222222 0.0185185
-s -0.419026 0.419026 0.222222 0.0185185
-s -0.643951 -0.172546 1.11022e-16 0.166667
-s -0.835815 -0.157543 0.111111 0.0555556
-s -0.871646 -0.122136 0.165419 0.0185185
-s -0.799077 -0.135649 0.171592 0.0185185
-s -0.82339 -0.0854653 0.122833 0.0185185
-s -0.908384 -0.14403 0.104938 0.0185185
-s -0.860128 -0.107359 0.062352 0.0185185
-s -0.872552 -0.179437 0.0506299 0.0185185
-s -0.884071 -0.194213 0.153697 0.0185185
-s -0.84824 -0.229621 0.099389 0.0185185
-s -0.811502 -0.207727 0.15987 0.0185185
-s -0.643951 -0.172546 0.222222 0.0555556
-s -0.61371 -0.142305 0.282703 0.0185185
-s -0.5724 -0.153374 0.222222 0.0185185
-s -0.624779 -0.100996 0.222222 0.0185185
-s -0.68526 -0.161477 0.282703 0.0185185
-s -0.696329 -0.120168 0.222222 0.0185185
-s -0.715501 -0.191718 0.222222 0.0185185
-s -0.632882 -0.213855 0.282703 0.0185185
-s -0.663122 -0.244096 0.222222 0.0185185
-s -0.591572 -0.224924 0.222222 0.0185185
-s -0.69376 0.0133465 0.111111 0.0555556
-s -0.674309 0.0838533 0.122833 0.0185185
-s -0.62221 0.0325183 0.111111 0.0185185
-s -0.666287 0.0539145 0.0555556 0.0185185
-s -0.745859 0.0646815 0.122833 0.0185185
-s -0.737837 0.0347427 0.0555556 0.0185185
-s -0.76531 -0.0058253 0.111111 0.0185185
-s -0.701782 0.0432853 0.178389 0.0185185
-s -0.721234 -0.0272215 0.166667 0.0185185
-s -0.649684 -0.00804971 0.166667 0.0185185
-s -0.835815 -0.157543 -0.111111 0.0555556
-s -0.899353 -0.119969 -0.117284 0.0185185
-s -0.868703 -0.130205 -0.0506299 0.0185185
-s -0.836885 -0.0844101 -0.099389 0.0185185
-s -0.866465 -0.147308 -0.177765 0.0185185
-s -0.803997 -0.111748 -0.15987 0.0185185
-s -0.802927 -0.184881 -0.171592 0.0185185
-s -0.898283 -0.193102 -0.129006 0.0185185
-s -0.834745 -0.230676 -0.122833 0.0185185
-s -0.867633 -0.203337 -0.062352 0.0185185
-s -0.69376 0.0133465 -0.111111 0.0555556
-s -0.668775 0.0631985 -0.15987 0.0185185
-s -0.62221 0.0325183 -0.111111 0.0185185
-s -0.649684 -0.00804971 -0.166667 0.0185185
-s -0.740325 0.0440268 -0.15987 0.0185185
-s -0.721234 -0.0272215 -0.166667 0.0185185
-s -0.76531 -0.0058253 -0.111111 0.0185185
-s -0.712851 0.0845947 -0.104315 0.0185185
-s -0.737837 0.0347427 -0.0555556 0.0185185
-s -0.666287 0.0539145 -0.0555556 0.0185185
-s -0.643951 -0.172546 -0.222222 0.0555556
-s -0.674191 -0.202787 -0.282703 0.0185185
-s -0.715501 -0.191718 -0.222222 0.0185185
-s -0.663122 -0.244096 -0.222222 0.0185185
-s -0.602641 -0.183615 -0.282703 0.0185185
-s -0.591572 -0.224924 -0.222222 0.0185185
-s -0.5724 -0.153374 -0.222222 0.0185185
-s -0.655019 -0.131237 -0.282703 0.0185185
-s -0.624779 -0.100996 -0.222222 0.0185185
-s -0.696329 -0.120168 -0.222222 0.0185185
-s -0.786005 -0.343435 7.89572e-17 0.0555556
-s -0.82165 -0.392454 0.0425863 0.0185185
-s -0.753118 -0.370774 0.0604812 0.0185185
-s -0.80984 -0.323622 0.0672777 0.0185185
-s -0.854538 -0.365116 -0.0178949 0.0185185
-s -0.842728 -0.296284 0.00679642 0.0185185
-s -0.818893 -0.316097 -0.0604812 0.0185185
-s -0.797815 -0.412267 -0.0246914 0.0185185
-s -0.76217 -0.363249 -0.0672777 0.0185185
-s -0.729282 -0.390587 -0.00679642 0.0185185
-s -0.594141 -0.358439 -0.111111 0.0555556
-s -0.542042 -0.409774 -0.122833 0.0185185
-s -0.522591 -0.339267 -0.111111 0.0185185
-s -0.550064 -0.379835 -0.0555556 0.0185185
-s -0.613592 -0.428945 -0.122833 0.0185185
-s -0.621614 -0.399007 -0.0555556 0.0185185
-s -0.665691 -0.37761 -0.111111 0.0185185
-s -0.586119 -0.388377 -0.178389 0.0185185
-s -0.638217 -0.337042 -0.166667 0.0185185
-s -0.566667 -0.317871 -0.166667 0.0185185
-s -0.594141 -0.358439 0.111111 0.0555556
-s -0.547576 -0.389119 0.15987 0.0185185
-s -0.522591 -0.339267 0.111111 0.0185185
-s -0.566667 -0.317871 0.166667 0.0185185
-s -0.619127 -0.408291 0.15987 0.0185185
-s -0.638217 -0.337042 0.166667 0.0185185
-s -0.665691 -0.37761 0.111111 0.0185185
-s -0.57505 -0.429687 0.104315 0.0185185
-s -0.621614 -0.399007 0.0555556 0.0185185
-s -0.550064 -0.379835 0.0555556 0.0185185
-s 0.0996195 -0.371785 0.544331 0.166667
-s 0.220501 -0.393621 0.729516 0.0555556
-s 0.279642 -0.368601 0.766439 0.0185185
-s 0.281062 -0.372464 0.692479 0.0185185
-s 0.238665 -0.321889 0.726118 0.0185185
-s 0.219082 -0.389758 0.803476 0.0185185
-s 0.178104 -0.343046 0.763155 0.0185185
-s 0.15994 -0.414778 0.766553 0.0185185
-s 0.261479 -0.440333 0.769837 0.0185185
-s 0.202338 -0.465353 0.732914 0.0185185
-s 0.262898 -0.444196 0.695877 0.0185185
-s 0.31427 -0.31427 0.544331 0.0555556
-s 0.367156 -0.277961 0.507294 0.0185185
-s 0.31427 -0.31427 0.470257 0.0185185
-s 0.297666 -0.252306 0.507294 0.0185185
-s 0.367156 -0.277961 0.581368 0.0185185
-s 0.297666 -0.252306 0.581368 0.0185185
-s 0.31427 -0.31427 0.618405 0.0185185
-s 0.383759 -0.339925 0.544331 0.0185185
-s 0.330873 -0.376234 0.581368 0.0185185
-s 0.330873 -0.376234 0.507294 0.0185185
-s 0.166275 -0.191247 0.655442 0.0555556
-s 0.20793 -0.130089 0.652044 0.0185185
-s 0.230419 -0.192135 0.618405 0.0185185
-s 0.172673 -0.154295 0.591563 0.0185185
-s 0.143787 -0.129201 0.689081 0.0185185
-s 0.108529 -0.153407 0.6286 0.0185185
-s 0.102131 -0.190359 0.692479 0.0185185
-s 0.201532 -0.167041 0.715923 0.0185185
-s 0.159877 -0.228199 0.719322 0.0185185
-s 0.224021 -0.229087 0.682285 0.0185185
-s 0.0058509 -0.451136 0.729516 0.0555556
-s 0.0051487 -0.447081 0.803476 0.0185185
-s 0.0688765 -0.439178 0.766553 0.0185185
-s 0.0172804 -0.386138 0.763155 0.0185185
-s -0.0578769 -0.459039 0.766439 0.0185185
-s -0.0457452 -0.398096 0.726118 0.0185185
-s -0.0571747 -0.463094 0.692479 0.0185185
-s -0.00628079 -0.512079 0.769837 0.0185185
-s -0.00557859 -0.516134 0.695877 0.0185185
-s 0.0574471 -0.504176 0.732914 0.0185185
-s -0.0483751 -0.248762 0.655442 0.0555556
-s -0.0599222 -0.183785 0.689081 0.0185185
-s 0.00673113 -0.215921 0.692479 0.0185185
-s -0.0172857 -0.187119 0.6286 0.0185185
-s -0.115028 -0.216626 0.652044 0.0185185
-s -0.0723919 -0.21996 0.591563 0.0185185
-s -0.103481 -0.281603 0.618405 0.0185185
-s -0.0910116 -0.245428 0.715923 0.0185185
-s -0.0794645 -0.310405 0.682285 0.0185185
-s -0.0243582 -0.277564 0.719322 0.0185185
-s -0.115031 -0.4293 0.544331 0.0555556
-s -0.178985 -0.424299 0.581368 0.0185185
-s -0.115031 -0.4293 0.618405 0.0185185
-s -0.131634 -0.367336 0.581368 0.0185185
-s -0.178985 -0.424299 0.507294 0.0185185
-s -0.131634 -0.367336 0.507294 0.0185185
-s -0.115031 -0.4293 0.470257 0.0185185
-s -0.162382 -0.486264 0.544331 0.0185185
-s -0.0984274 -0.491265 0.507294 0.0185185
-s -0.0984274 -0.491265 0.581368 0.0185185
-s 0.153845 -0.574159 0.618405 0.0555556
-s 0.202534 -0.612768 0.658726 0.0185185
-s 0.225396 -0.554987 0.618405 0.0185185
-s 0.184086 -0.543919 0.678886 0.0185185
-s 0.130984 -0.631939 0.658726 0.0185185
-s 0.112536 -0.56309 0.678886 0.0185185
-s 0.0822954 -0.593331 0.618405 0.0185185
-s 0.172294 -0.643008 0.598245 0.0185185
-s 0.123605 -0.6044 0.557924 0.0185185
-s 0.195155 -0.585228 0.557924 0.0185185
-s 0.0329639 -0.552323 0.43322 0.0555556
-s 0.0248832 -0.625877 0.436618 0.0185185
-s 0.0822954 -0.593331 0.470257 0.0185185
-s 0.0138144 -0.584567 0.497099 0.0185185
-s -0.0244483 -0.584869 0.399581 0.0185185
-s -0.0355172 -0.54356 0.460062 0.0185185
-s -0.0163676 -0.511316 0.396183 0.0185185
-s 0.0440327 -0.593633 0.372739 0.0185185
-s 0.0521134 -0.520079 0.369341 0.0185185
-s 0.101445 -0.561087 0.406378 0.0185185
-s 0.247614 -0.494808 0.43322 0.0555556
-s 0.313607 -0.494287 0.399581 0.0185185
-s 0.269833 -0.434629 0.396183 0.0185185
-s 0.302539 -0.452978 0.460062 0.0185185
-s 0.291389 -0.554467 0.436618 0.0185185
-s 0.28032 -0.513157 0.497099 0.0185185
-s 0.225396 -0.554987 0.470257 0.0185185
-s 0.258683 -0.536117 0.372739 0.0185185
-s 0.19269 -0.536638 0.406378 0.0185185
-s 0.214908 -0.476459 0.369341 0.0185185
-s -0.172546 -0.643951 1.11022e-16 0.166667
-s -0.157543 -0.835815 0.111111 0.0555556
-s -0.122136 -0.871646 0.165419 0.0185185
-s -0.0854653 -0.82339 0.122833 0.0185185
-s -0.135649 -0.799077 0.171592 0.0185185
-s -0.194213 -0.884071 0.153697 0.0185185
-s -0.207727 -0.811502 0.15987 0.0185185
-s -0.229621 -0.84824 0.099389 0.0185185
-s -0.14403 -0.908384 0.104938 0.0185185
-s -0.179437 -0.872552 0.0506299 0.0185185
-s -0.107359 -0.860128 0.062352 0.0185185
-s 0.0133465 -0.69376 0.111111 0.0555556
-s 0.0838533 -0.674309 0.122833 0.0185185
-s 0.0539145 -0.666287 0.0555556 0.0185185
-s 0.0325183 -0.62221 0.111111 0.0185185
-s 0.0432853 -0.701782 0.178389 0.0185185
-s -0.00804971 -0.649684 0.166667 0.0185185
-s -0.0272215 -0.721234 0.166667 0.0185185
-s 0.0646815 -0.745859 0.122833 0.0185185
-s -0.0058253 -0.76531 0.111111 0.0185185
-s 0.0347427 -0.737837 0.0555556 0.0185185
-s -0.172546 -0.643951 0.222222 0.0555556
-s -0.142305 -0.61371 0.282703 0.0185185
-s -0.100996 -0.624779 0.222222 0.0185185
-s -0.153374 -0.5724 0.222222 0.0185185
-s -0.213855 -0.632882 0.282703 0.0185185
-s -0.224924 -0.591572 0.222222 0.0185185
-s -0.244096 -0.663122 0.222222 0.0185185
-s -0.161477 -0.68526 0.282703 0.0185185
-s -0.191718 -0.715501 0.222222 0.0185185
-s -0.120168 -0.696329 0.222222 0.0185185
-s -0.343435 -0.786005 7.27893e-17 0.0555556
-s -0.392454 -0.82165 0.0425863 0.0185185
-s -0.323622 -0.80984 0.0672777 0.0185185
-s -0.370774 -0.753118 0.0604812 0.0185185
-s -0.412267 -0.797815 -0.0246914 0.0185185
-s -0.390587 -0.729282 -0.00679642 0.0185185
-s -0.363249 -0.76217 -0.0672777 0.0185185
-s -0.365116 -0.854538 -0.0178949 0.0185185
-s -0.316097 -0.818893 -0.0604812 0.0185185
-s -0.296284 -0.842728 0.00679642 0.0185185
-s -0.358439 -0.594141 0.111111 0.0555556
-s -0.389119 -0.547576 0.15987 0.0185185
-s -0.317871 -0.566667 0.166667 0.0185185
-s -0.339267 -0.522591 0.111111 0.0185185
-s -0.429687 -0.57505 0.104315 0.0185185
-s -0.379835 -0.550064 0.0555556 0.0185185
-s -0.399007 -0.621614 0.0555556 0.0185185
-s -0.408291 -0.619127 0.15987 0.0185185
-s -0.37761 -0.665691 0.111111 0.0185185
-s -0.337042 -0.638217 0.166667 0.0185185
-s -0.358439 -0.594141 -0.111111 0.0555556
-s -0.409774 -0.542042 -0.122833 0.0185185
-s -0.379835 -0.550064 -0.0555556 0.0185185
-s -0.339267 -0.522591 -0.111111 0.0185185
-s -0.388377 -0.586119 -0.178389 0.0185185
-s -0.317871 -0.566667 -0.166667 0.0185185
-s -0.337042 -0.638217 -0.166667 0.0185185
-s -0.428945 -0.613592 -0.122833 0.0185185
-s -0.37761 -0.665691 -0.111111 0.0185185
-s -0.399007 -0.621614 -0.0555556 0.0185185
-s -0.157543 -0.835815 -0.111111 0.0555556
-s -0.119969 -0.899353 -0.117284 0.0185185
-s -0.0844101 -0.836885 -0.099389 0.0185185
-s -0.130205 -0.868703 -0.0506299 0.0185185
-s -0.193102 -0.898283 -0.129006 0.0185185
-s -0.203337 -0.867633 -0.062352 0.0185185
-s -0.230676 -0.834745 -0.122833 0.0185185
-s -0.147308 -0.866465 -0.177765 0.0185185
-s -0.184881 -0.802927 -0.171592 0.0185185
-s -0.111748 -0.803997 -0.15987 0.0185185
-s -0.172546 -0.643951 -0.222222 0.0555556
-s -0.202787 -0.61371 -0.282703 0.0185185
-s -0.244096 -0.624779 -0.222222 0.0185185
-s -0.191718 -0.5724 -0.222222 0.0185185
-s -0.131237 -0.632882 -0.282703 0.0185185
-s -0.120168 -0.591572 -0.222222 0.0185185
-s -0.100996 -0.663122 -0.222222 0.0185185
-s -0.183615 -0.68526 -0.282703 0.0185185
-s -0.153374 -0.715501 -0.222222 0.0185185
-s -0.224924 -0.696329 -0.222222 0.0185185
-s 0.0133465 -0.69376 -0.111111 0.0555556
-s 0.0631985 -0.668775 -0.15987 0.0185185
-s -0.00804971 -0.649684 -0.166667 0.0185185
-s 0.0325183 -0.62221 -0.111111 0.0185185
-s 0.0845947 -0.712851 -0.104315 0.0185185
-s 0.0539145 -0.666287 -0.0555556 0.0185185
-s 0.0347427 -0.737837 -0.0555556 0.0185185
-s 0.0440268 -0.740325 -0.15987 0.0185185
-s -0.0058253 -0.76531 -0.111111 0.0185185
-s -0.0272215 -0.721234 -0.166667 0.0185185
-s 0.471405 -0.471405 1.11022e-16 0.166667
-s 0.690426 -0.508983 1.83812e-16 0.0555556
-s 0.755941 -0.484794 -0.0246914 0.0185185
-s 0.695668 -0.478434 -0.0672777 0.0185185
-s 0.7029 -0.436283 -0.00679642 0.0185185
-s 0.7507 -0.515343 0.0425863 0.0185185
-s 0.697658 -0.466832 0.0604812 0.0185185
-s 0.685185 -0.539531 0.0672777 0.0185185
-s 0.743468 -0.557494 -0.0178949 0.0185185
-s 0.677953 -0.581682 0.00679642 0.0185185
-s 0.683194 -0.551134 -0.0604812 0.0185185
-s 0.607487 -0.335322 -0.111111 0.0555556
-s 0.629404 -0.313405 -0.178389 0.0185185
-s 0.610996 -0.384191 -0.166667 0.0185185
-s 0.558618 -0.331813 -0.166667 0.0185185
-s 0.625895 -0.264535 -0.122833 0.0185185
-s 0.555109 -0.282943 -0.111111 0.0185185
-s 0.603979 -0.286452 -0.0555556 0.0185185
-s 0.678274 -0.316914 -0.122833 0.0185185
-s 0.656357 -0.33883 -0.0555556 0.0185185
-s 0.659866 -0.3877 -0.111111 0.0185185
-s 0.607487 -0.335322 0.111111 0.0555556
-s 0.659645 -0.283164 0.104315 0.0185185
-s 0.656357 -0.33883 0.0555556 0.0185185
-s 0.603979 -0.286452 0.0555556 0.0185185
-s 0.610775 -0.279656 0.15987 0.0185185
-s 0.555109 -0.282943 0.111111 0.0185185
-s 0.558618 -0.331813 0.166667 0.0185185
-s 0.663153 -0.332034 0.15987 0.0185185
-s 0.610996 -0.384191 0.166667 0.0185185
-s 0.659866 -0.3877 0.111111 0.0185185
-s 0.554344 -0.645066 0.111111 0.0555556
-s 0.610229 -0.668521 0.153697 0.0185185
-s 0.622977 -0.619787 0.099389 0.0185185
-s 0.585648 -0.598918 0.15987 0.0185185
-s 0.541596 -0.6938 0.165419 0.0185185
-s 0.517014 -0.624197 0.171592 0.0185185
-s 0.48571 -0.670344 0.122833 0.0185185
-s 0.578925 -0.714669 0.104938 0.0185185
-s 0.52304 -0.691213 0.062352 0.0185185
-s 0.591673 -0.665934 0.0506299 0.0185185
-s 0.471405 -0.471405 0.222222 0.0555556
-s 0.501645 -0.441164 0.282703 0.0185185
-s 0.542955 -0.452233 0.222222 0.0185185
-s 0.490576 -0.399854 0.222222 0.0185185
-s 0.430095 -0.460336 0.282703 0.0185185
-s 0.419026 -0.419026 0.222222 0.0185185
-s 0.399854 -0.490576 0.222222 0.0185185
-s 0.482473 -0.512714 0.282703 0.0185185
-s 0.452233 -0.542955 0.222222 0.0185185
-s 0.523783 -0.523783 0.222222 0.0185185
-s 0.335322 -0.607487 0.111111 0.0555556
-s 0.313405 -0.629404 0.178389 0.0185185
-s 0.384191 -0.610996 0.166667 0.0185185
-s 0.331813 -0.558618 0.166667 0.0185185
-s 0.264535 -0.625895 0.122833 0.0185185
-s 0.282943 -0.555109 0.111111 0.0185185
-s 0.286452 -0.603979 0.0555556 0.0185185
-s 0.316914 -0.678274 0.122833 0.0185185
-s 0.33883 -0.656357 0.0555556 0.0185185
-s 0.3877 -0.659866 0.111111 0.0185185
-s 0.554344 -0.645066 -0.111111 0.0555556
-s 0.616373 -0.681385 -0.129006 0.0185185
-s 0.617144 -0.607573 -0.122833 0.0185185
-s 0.609912 -0.649723 -0.062352 0.0185185
-s 0.553573 -0.718878 -0.117284 0.0185185
-s 0.547112 -0.687216 -0.0506299 0.0185185
-s 0.491544 -0.682558 -0.099389 0.0185185
-s 0.560805 -0.676727 -0.177765 0.0185185
-s 0.498776 -0.640408 -0.15987 0.0185185
-s 0.561576 -0.602915 -0.171592 0.0185185
-s 0.335322 -0.607487 -0.111111 0.0555556
-s 0.283164 -0.659645 -0.104315 0.0185185
-s 0.33883 -0.656357 -0.0555556 0.0185185
-s 0.286452 -0.603979 -0.0555556 0.0185185
-s 0.279656 -0.610775 -0.15987 0.0185185
-s 0.282943 -0.555109 -0.111111 0.0185185
-s 0.331813 -0.558618 -0.166667 0.0185185
-s 0.332034 -0.663153 -0.15987 0.0185185
-s 0.384191 -0.610996 -0.166667 0.0185185
-s 0.3877 -0.659866 -0.111111 0.0185185
-s 0.471405 -0.471405 -0.222222 0.0555556
-s 0.441164 -0.441164 -0.282703 0.0185185
-s 0.399854 -0.452233 -0.222222 0.0185185
-s 0.452233 -0.399854 -0.222222 0.0185185
-s 0.512714 -0.460336 -0.282703 0.0185185
-s 0.523783 -0.419026 -0.222222 0.0185185
-s 0.542955 -0.490576 -0.222222 0.0185185
-s 0.460336 -0.512714 -0.282703 0.0185185
-s 0.490576 -0.542955 -0.222222 0.0185185
-s 0.419026 -0.523783 -0.222222 0.0185185
diff --git a/glome-hs.cabal b/glome-hs.cabal
--- a/glome-hs.cabal
+++ b/glome-hs.cabal
@@ -1,22 +1,24 @@
 Name:                glome-hs
-Version:             0.51
+Version:             0.60
 Synopsis:            ray tracer
 Description:         Ray Tracer capable of rendering a variety of primitives,
                      with support for CSG (difference and intersection of solids),
                      BIH-based acceleration structure, and ability to load NFF
-                     format files.
+                     format files.  The rendering algorithms have been abstracted
+                     to an external library, GlomeTrace.  This is just a front-end
+                     to the library that renders scenes into an opengl window.
 License:             GPL
 License-file:        LICENSE
 Author:              Jim Snow
 Maintainer:          Jim Snow <jsnow@cs.pdx.edu>
-Copyright:           Copyright 2008 Jim Snow
-Homepage:            http://syn.cs.pdx.edu/~jsnow/glome
+Copyright:           Copyright 2008,2010 Jim Snow
+Homepage:            http://haskell.org/haskellwiki/Glome
 Stability:           experimental
 Category:            graphics
-Build-Depends:       base,haskell98,time,parallel,GLUT,OpenGL,random,array
+Build-Depends:       base >= 3 && < 4, haskell98, time, parallel, GLUT, OpenGL, random, array, GlomeVec, GlomeTrace
 build-type:          Simple
-Executable:          glome
-ghc-options:         -fglasgow-exts -funbox-strict-fields -threaded
 extensions:          BangPatterns 
-Main-is:             Glome.hs
-
+Cabal-Version: >= 1.2
+extra-source-files:  README.txt,TestScene.hs
+executable:          Glome
+main-is:             Glome.hs
diff --git a/make b/make
deleted file mode 100644
--- a/make
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/bash
-#rm *.o
-#ghc -O3 --make Glome.hs
-#ghc Glome.hs --make -O2 -threaded -fasm -optc-march=athlon64 -XFlexibleInstances -XTypeSynonymInstances
-#ghc Glome.hs --make -O2 -fvia-c -fglasgow-exts -funbox-strict-fields -fbang-patterns -fexcess-precision -optc-ffast-math -optc-O2 -optc-mfpmath=sse -optc-msse2
-#ghc Glome.hs --make -O2 -fasm -fglasgow-exts -funbox-strict-fields -fbang-patterns -fexcess-precision -prof -auto-all
-
-runhaskell Setup.lhs configure --prefix=$HOME --user
-runhaskell Setup.lhs build
diff --git a/run b/run
deleted file mode 100644
--- a/run
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/bash
-#./Glome +RTS -N2 -sstderr -RTS
-#./Glome +RTS
-./dist/build/glome/glome
