The first thing we’re going to need is some geometry to shoot our rays at:

class Solid a where intersect :: Ray -> a -> Maybe Intersection |

Basically something is a solid if we can shoot rays at it and possibly get back an Intersection (we may miss and not get back an intersection).

An Intersection is just what a record of a Ray hitting a Solid, defined as:

data Intersection = Intersection {t :: Float, loc :: Vec3f, normal :: Vec3f} deriving (Show) |

Right now it only records the parameter of the ray, the location of the intersection and the normal. We’re going to need to extend that to get more sophisticated effects but we can get some simple stuff going with this.

Now that we have that we can implement our first actual primitive solid, a sphere:

data Sphere = Sphere Vec3f Float deriving (Show) instance Solid Sphere where intersect (Ray p0 d) (Sphere c r) = case t of Nothing -> Nothing Just s -> Just (Intersection s pt (normed (pt <-> c))) where pt = (at (Ray p0 d) s) where t = (min_over_zero (real_quadratic (d <.> d) ((2 <*> d) <.> (p0 <-> c)) (((p0 <-> c) <.> (p0 <-> c)) - r ^ 2))) |