diff --git a/Occlusion/Cell.hs b/Occlusion/Cell.hs
new file mode 100644
--- /dev/null
+++ b/Occlusion/Cell.hs
@@ -0,0 +1,47 @@
+
+module Cell
+	( Cell (..)
+	, readCell 
+	, pictureOfCell
+	, cellShape)
+where
+import Data.Char
+import Graphics.Gloss
+
+-- | A terrain cell in the world.
+data Cell
+	= CellEmpty
+	| CellWall
+	deriving (Show, Eq)
+
+
+-- | Read a cell from a character.
+readCell :: Char -> Cell
+readCell c
+ = case c of
+	'.'	-> CellEmpty
+	'#'	-> CellWall
+	_	-> error $ "readCell: no match for char " ++ show (ord c) ++ " " ++ show c
+
+
+-- | The basic shape of a cell.
+cellShape :: Int -> Int -> Int -> Picture
+cellShape cellSize posXi posYi
+ = let 	cs	= fromIntegral cellSize
+	posX	= fromIntegral posXi
+	posY	= fromIntegral posYi
+	x1	= posX
+	x2	= posX + 1
+	y1	= posY 
+	y2	= posY + 1
+   in	Polygon [(x1, y1), (x1, y2), (x2, y2), (x2, y1)]
+		
+
+-- | Convert a cell to a picture, based on a primitive shape.
+--	We pass the shape in to avoid recomputing it for each cell.
+pictureOfCell ::  Int -> Int -> Int -> Cell -> Picture
+pictureOfCell cellSize posX posY cell
+ = case cell of
+	CellEmpty	-> Color (greyN 0.2)	(cellShape cellSize posX posY)
+	CellWall 	-> Color white 		(cellShape cellSize posX posY)
+
diff --git a/Occlusion/Data.hs b/Occlusion/Data.hs
new file mode 100644
--- /dev/null
+++ b/Occlusion/Data.hs
@@ -0,0 +1,40 @@
+
+module Data where
+
+worldData
+ 	= unlines
+	[ "WORLD"
+	, "32 32"
+	, " 01234567890123456789012345678901"
+	, "0#..............................#"
+	, "1.....................#####......"
+	, "2....#.#.#.#..#.#.#.............."
+	, "3....#######...#.#....#.#.#......"
+	, "4....#######..#.#.#.............."
+	, "5....#######...#.#...###.###....."
+	, "6................................"
+	, "7......#.#.............#.#......."
+	, "8......#.#.............#.#......."
+	, "9......#.#.............#.#......."
+	, "0......#.#####.........#.#......."
+	, "1......#.....#.........#.#......."
+	, "2......#.###.#.........#.#......."
+	, "3......#.#.#.###########.#######."
+	, "4......#.#.#...................#."
+	, "5......#.#.#####################."
+	, "6......#.#......................."
+	, "7......#.#...########............"
+	, "8......#.#...#......#............"
+	, "9......#.#...########............"
+	, "0......#.#................####..."
+	, "1......#.#.........#####..#..#..."
+	, "2......#.###########...####..#..."
+	, "3......#.....................#..."
+	, "4..#####.###########...####..#..."
+	, "5..#.....#.........#####..#..#..."
+	, "6..#.#####.....#..........####..."
+	, "7..#.#.........#................."
+	, "8..#.#......#######.............."
+	, "9..#.#.........#................."
+	, "0..............#................."
+	, "1#..............................#" ]
diff --git a/Occlusion/Main.hs b/Occlusion/Main.hs
new file mode 100644
--- /dev/null
+++ b/Occlusion/Main.hs
@@ -0,0 +1,122 @@
+{-# LANGUAGE PatternGuards #-}
+
+import World
+import Data
+import State
+import Cell
+import Graphics.Gloss.Game
+import Graphics.Gloss.Data.QuadTree
+import Graphics.Gloss.Data.Extent
+import Graphics.Gloss.Shapes
+import System.Environment
+import Data.Maybe
+import Data.List
+import Data.Function
+
+main 
+ = do	args	<- getArgs
+	case args of
+	 [fileName] 	
+	  -> do	world	<- loadWorld fileName
+		mainWithWorld world
+		
+	 _ -> do
+		let world = readWorld worldData
+		mainWithWorld world
+	
+	
+mainWithWorld world
+ = do	let gameState	= initState world
+	gameInWindow 
+		"Occlusion"
+		(windowSizeOfWorld world)
+		(10, 10)
+		black 
+		10
+		gameState
+		drawState
+		(handleInput world)
+		(\_ -> id)
+				
+				
+-- | Convert the state to a picture.
+drawState :: State -> Picture
+drawState state
+ = let	
+	world		= stateWorld state
+
+	-- The ray cast by the user.
+	p1		= stateLineStart state
+	p2		= stateLineEnd   state
+	picRay		= drawRay world p1 p2
+
+	-- The cell hit by the ray (if any)
+	mHitCell	= castSegIntoWorld world p1 p2
+	hitCells	= maybeToList mHitCell
+	picCellsHit	= Pictures $ map (drawHitCell world) hitCells
+
+	-- All the cells in the world.
+	cellsAll	= flattenQuadTree (worldExtent world) (worldTree world)
+	picCellsAll	= Pictures $ map (uncurry (drawCell False world)) cellsAll
+
+	-- The cells visible from the designated point.
+	cellsVisible	= [ (coord, cell)
+				| (coord, cell)	<- flattenQuadTree (worldExtent world) (worldTree world)
+				, cellAtCoordIsVisibleFromPoint world p1 coord ]
+
+	picCellsVisible	= Pictures $ map (uncurry (drawCell True world)) cellsVisible
+
+	-- How big to draw the cells.
+	scale		= fromIntegral $ worldCellSize world
+
+	(windowSizeX, windowSizeY)	
+		= windowSizeOfWorld
+		$ stateWorld state
+		
+	-- Shift the cells so they are centered in the window.
+	offsetX	= - (fromIntegral $ windowSizeX `div` 2)
+	offsetY	= - (fromIntegral $ windowSizeY `div` 2)
+
+   in	Translate offsetX offsetY
+		$ Scale scale scale
+		$ Pictures [ picCellsAll, picCellsVisible, picCellsHit, picRay ]
+
+
+-- | Draw the cell hit by the ray defined by the user.
+drawHitCell :: World -> (Point, Extent, Cell) -> Picture
+drawHitCell world (pos@(px, py), extent, cell)
+ = let	(n, s, e, w)	= takeExtent extent
+	x		= w
+	y		= s
+
+	posX	= fromIntegral x 
+	posY	= fromIntegral y
+	
+   in	Pictures [ Color blue $ cellShape 1 posX posY ]
+
+
+-- | Draw the ray defined by the user.
+drawRay :: World -> Point -> Point -> Picture 
+drawRay world p1@(x, y) p2
+ = Pictures
+	[ Color red $ Line [p1, p2]
+	, Color cyan 
+		$ Translate x y 
+		$ Pictures 
+			[ Line [(-0.3, -0.3), (0.3,  0.3)]
+			, Line [(-0.3,  0.3), (0.3, -0.3)] ] ]
+
+
+-- | Draw a cell in the world.
+drawCell :: Bool -> World -> Coord -> Cell -> Picture
+drawCell visible world (x, y) cell 
+ = let	cs	= fromIntegral (worldCellSize world)
+	cp	= fromIntegral (worldCellSpace world)
+
+	posX	= fromIntegral x 
+	posY	= fromIntegral y
+
+   in	if visible
+	  then pictureOfCell (worldCellSize world) posX posY cell
+	  else Color (greyN 0.4) (cellShape cs posX posY)
+ 	
diff --git a/Occlusion/State.hs b/Occlusion/State.hs
new file mode 100644
--- /dev/null
+++ b/Occlusion/State.hs
@@ -0,0 +1,42 @@
+{-# LANGUAGE PatternGuards #-}
+
+module State where
+import World
+import Graphics.Gloss.Game
+
+-- | The game state.
+data State
+	= State
+	{ stateWorld		:: World
+	, stateLineStart	:: Point
+	, stateLineEnd		:: Point }
+
+
+-- | Initial game state.
+initState world
+	= State
+	{ stateWorld		= world
+	, stateLineStart	= (10, 10)
+	, stateLineEnd		= (10, 10) }
+	
+
+-- | Handle an input event.
+handleInput :: World -> Event -> State -> State
+handleInput world (EventKey key keyState mods pos) state
+	| MouseButton LeftButton	<- key
+	, Down				<- keyState
+	, shift mods == Down	
+	= state { stateLineEnd = worldPosOfWindowPos world pos }
+
+	| MouseButton LeftButton	<- key
+	, Down				<- keyState
+	= state { stateLineStart 	= worldPosOfWindowPos world pos 
+		, stateLineEnd		= worldPosOfWindowPos world pos }
+
+	| MouseButton RightButton	<- key
+	, Down				<- keyState
+	= state { stateLineEnd 		= worldPosOfWindowPos world pos }
+
+handleInput _ _ state
+	= state
+
diff --git a/Occlusion/World.hs b/Occlusion/World.hs
new file mode 100644
--- /dev/null
+++ b/Occlusion/World.hs
@@ -0,0 +1,156 @@
+{-# LANGUAGE ScopedTypeVariables #-}
+
+module World where
+import Cell
+import Graphics.Gloss.Game
+import Graphics.Gloss.Data.Extent
+import Graphics.Gloss.Data.QuadTree
+import Graphics.Gloss.Algorithms.RayCast
+import System.IO
+import Control.Monad
+
+
+-- | The game world.
+data World	
+	= World
+	{ worldWidth		:: Int
+	, worldHeight		:: Int
+	, worldTree		:: QuadTree Cell
+	, worldCellSize		:: Int
+	, worldCellSpace	:: Int }
+	deriving Show
+
+
+-- | Get the extent covering the entire world.
+worldExtent :: World -> Extent
+worldExtent world
+	= makeExtent (worldWidth world) 0 (worldHeight world) 0
+
+
+-- | Load a world from a file.	
+loadWorld :: FilePath -> IO World
+loadWorld fileName
+ = do	str	<- readFile fileName
+	return	$ readWorld str
+	
+	
+-- | Read a world from a string.
+readWorld :: String -> World
+readWorld str
+ = let	("WORLD" : strWidthHeight : skip : cellLines)	
+			= lines str
+	
+	[width, height]	= map read $ words strWidthHeight
+	rows	= take height $ cellLines
+
+	cells	= concat 
+		$ map (readLine width) 
+		$ reverse rows
+
+	extent	= makeExtent height 0 width 0
+
+   in	World	{ worldWidth		= width
+		, worldHeight		= height
+		, worldTree		= makeWorldTree extent cells
+		, worldCellSize		= 20
+		, worldCellSpace	= 0 }
+
+readLine :: Int -> String -> [Cell]
+readLine width (s:str)
+	= map readCell
+	$ take width str
+
+
+
+-- | Get the size of the window needed to display a world.
+windowSizeOfWorld :: World -> (Int, Int)
+windowSizeOfWorld world
+ = let	cellSize	= worldCellSize world
+	cellSpace	= worldCellSpace world
+ 	cellPad		= cellSize + cellSpace
+ 	height		= cellPad * (worldHeight world) + cellSpace
+	width		= cellPad * (worldWidth  world) + cellSpace
+   in	(width, height)
+
+
+-- | Create the tree representing the world from a list of all its cells.
+makeWorldTree :: Extent -> [Cell] -> QuadTree Cell
+makeWorldTree extent cells
+ = foldr insert' emptyTree nonEmptyPosCells
+ where 
+	insert' (pos, cell) tree
+	 = case insertByCoord extent pos cell tree of
+		Nothing		-> tree
+		Just tree'	-> tree'
+	
+	(width, height)	
+		= sizeOfExtent extent
+	
+	posCells	
+		= zip	[(x, y) | y <- [0 .. height - 1]
+				, x <- [0 .. width - 1]]
+			cells
+	
+	nonEmptyPosCells 
+	 	= filter (\x -> snd x /= CellEmpty) posCells
+
+
+-- | Get the world position coresponding to a point in the window.
+worldPosOfWindowPos :: World -> Point -> Point
+worldPosOfWindowPos world (x, y)
+ = let	(windowSizeX, windowSizeY)
+		= windowSizeOfWorld world
+		
+	offsetX	= fromIntegral $ windowSizeX `div` 2
+	offsetY	= fromIntegral $ windowSizeY `div` 2
+	
+	scale	= fromIntegral $ worldCellSize world
+	
+	x'	= (x + offsetX) / scale
+	y'	= (y + offsetY) / scale
+
+  in	(x', y')
+
+
+-- | Check if a the cell at a given coordinate is visible from a point.
+cellAtCoordIsVisibleFromCoord :: World -> Coord -> Coord -> Bool
+cellAtCoordIsVisibleFromCoord world cFrom cTo
+ = let	(cx, cy)	= cFrom
+	pFrom		= (fromIntegral cx + 0.5 , fromIntegral cy + 0.5)
+   in	cellAtCoordIsVisibleFromPoint world pFrom cTo
+
+
+-- | Check if a cell at a given coordinate is visible from a point.
+--	We say it's visible if the center of any of its faces is visible.
+cellAtCoordIsVisibleFromPoint :: World -> Point -> Coord -> Bool
+cellAtCoordIsVisibleFromPoint world pFrom (x', y')
+ = or $ map (cellAtPointIsVisibleFromPoint world pFrom) [pa, pb, pc, pd]
+ where 	x :: Float	= fromIntegral x' + 0.5
+	y :: Float	= fromIntegral y' + 0.5
+	pa	= (x - 0.4999, y)
+	pb	= (x + 0.4999, y)
+	pc	= (x, y - 0.4999)
+	pd	= (x, y + 0.4999)
+ 
+		
+-- | Check if a point on some cell (P2) is visible from some other point (P1).
+cellAtPointIsVisibleFromPoint :: World -> Point -> Point -> Bool
+cellAtPointIsVisibleFromPoint world p1 p2
+ = let	mOccluder	= castSegIntoWorld world p1 p2
+   in	case mOccluder of
+	 Nothing 			-> False
+	 Just (pos, extent, cell)	-> pointInExtent extent p2
+
+
+-- | Given a line segment (P1-P2) get the cell closest to P1 that intersects the segment.
+castSegIntoWorld :: World -> Point -> Point -> Maybe (Point, Extent, Cell)
+castSegIntoWorld world p1 p2
+	= castSegIntoCellularQuadTree p1 p2 (worldExtent world) (worldTree world)
+
+
+-- | Given a line segment (P1-P2) get the cell closest to P1 that intersects the segment.
+traceSegIntoWorld :: World -> Point -> Point -> [(Point, Extent, Cell)]
+traceSegIntoWorld world p1 p2
+	= traceSegIntoCellularQuadTree p1 p2 (worldExtent world) (worldTree world)
+
+
diff --git a/Styrene/Contact.hs b/Styrene/Contact.hs
--- a/Styrene/Contact.hs
+++ b/Styrene/Contact.hs
@@ -102,7 +102,7 @@
 	closeEnough	= distancePP_contact pBead pClosest `ltFloat#` radius#
 
 	-- uParam gives where pClosest is relative to the endponts of the wall
-	uParam		= closestPointOnLine_param pWall1 pWall2 pBead
+	uParam		= closestPointOnLineParam pWall1 pWall2 pBead
 
 	-- pClosest needs to lie on the line segment between pWal1 and pWall2
 	inSegment	= uParam >= 0 && uParam <= 1
diff --git a/gloss-examples.cabal b/gloss-examples.cabal
--- a/gloss-examples.cabal
+++ b/gloss-examples.cabal
@@ -1,9 +1,9 @@
 Name:                gloss-examples
-Version:             1.0.1.0
+Version:             1.1.0.0
 License:             MIT
 License-file:        LICENSE
 Author:              Ben Lippmeier
-Maintainer:          gloss@ouroborus.net
+Maintainer:          benl@ouroborus.net
 Build-Type:          Simple
 Cabal-Version:       >=1.6
 Stability:           experimental
@@ -20,21 +20,21 @@
 Executable gloss-easy
   Build-depends: 
         base            >= 3 && < 5, 
-        gloss           >= 1.0 && < 1.1
+        gloss           >= 1.0 && < 1.2
   Main-is: Easy/Main.hs
   ghc-options: -O2
 
 Executable gloss-clock
   Build-depends: 
         base            >= 3 && < 5, 
-        gloss           >= 1.0 && < 1.1
+        gloss           >= 1.0 && < 1.2
   Main-is: Clock/Main.hs
   ghc-options: -O2
 
 Executable gloss-eden
   Build-depends: 
         base            >= 3 && < 5, 
-        gloss           >= 1.0 && < 1.1, 
+        gloss           >= 1.0 && < 1.2, 
         random          >  1.0 && < 1.1
   Main-is: Main.hs
   other-modules: Cell Community World
@@ -44,21 +44,21 @@
 Executable gloss-flake
   Build-depends: 
         base            >= 3 && < 5, 
-        gloss           >= 1.0 && < 1.1
+        gloss           >= 1.0 && < 1.2
   Main-is: Flake/Main.hs
   ghc-options: -O2
 
 Executable gloss-hello
   Build-depends: 
         base            >= 3 && < 5, 
-        gloss           >= 1.0 && < 1.1
+        gloss           >= 1.0 && < 1.2
   Main-is: Hello/Main.hs
   ghc-options: -O2
 
 Executable gloss-lifespan
   Build-depends: 
         base            >= 3 && < 5, 
-        gloss           >= 1.0 && < 1.1, 
+        gloss           >= 1.0 && < 1.2, 
         random          >  1.0 && < 1.1
   Main-is: Main.hs
   other-modules: Cell Community World
@@ -68,7 +68,7 @@
 Executable gloss-styrene
   Build-depends: 
         base            >= 3 && < 5,
-        gloss           >= 1.0 && < 1.1,
+        gloss           >= 1.0 && < 1.2,
         containers      >= 0.2 && < 0.4,
         ghc-prim        >= 0.1 && < 0.3
   Main-is: Main.hs
@@ -79,30 +79,39 @@
 Executable gloss-tree
   Build-depends: 
         base            >= 3 && < 5, 
-        gloss           >= 1.0 && < 1.1
+        gloss           >= 1.0 && < 1.2
   Main-is: Tree/Main.hs
   ghc-options: -O2
 
 Executable gloss-zen
   Build-depends: 
         base            >= 3 && < 5, 
-        gloss           >= 1.0 && < 1.1
+        gloss           >= 1.0 && < 1.2
   Main-is: Zen/Main.hs
   ghc-options: -O2
 
 Executable gloss-machina
   Build-depends: 
         base            >= 3 && < 5, 
-        gloss           >= 1.0 && < 1.1
+        gloss           >= 1.0 && < 1.2
   Main-is: Machina/Main.hs
   ghc-options: -O2
 
 Executable gloss-conway
   Build-depends: 
         base            >= 3 && < 5, 
-        gloss           >= 1.0 && < 1.1,
+        gloss           >= 1.0 && < 1.2,
         vector          >= 0.5 && < 0.6
   Main-is: Main.hs
   other-modules: Cell World
   hs-source-dirs: Conway
+  ghc-options: -O2
+
+Executable gloss-occlusion
+  Build-depends: 
+        base            >= 3    && < 5, 
+        gloss           >= 1.1  && < 1.2
+  Main-is: Main.hs
+  other-modules: Cell World State Data
+  hs-source-dirs: Occlusion
   ghc-options: -O2
