[Haskell-cafe] Glome.hs-0.3 (bounding objects, heterogeneous lists)

Jim Snow jsnow at cs.pdx.edu
Mon Apr 28 18:49:59 EDT 2008


Andrew Coppin wrote:
>>> Well, for example, Haskell doesn't have hetrogenous lists - which 
>>> are trivial in any OOP language. That's quite awkward to get around. 
>>> Also, both spheres and cylinders have a "radius" property, but then 
>>> you end up with name clashes. Again, a non-issue in OOP languages. 
>>> [I gather there's some new GHC language extension to partially solve 
>>> this one - but only when types are statically known. In the general 
>>> case, you'd have to write a "radius class" and define instances... 
>>> yuck!]
>>>
>> It's funny you mention that, those are actually problems I ran into, 
>> but (having learned my lesson the hard way in Ocaml), I decided not 
>> to try and force the language to do things my way, but instead try to 
>> do things in a way that Haskell makes easy.
>> For instance, I started out by making each primitive a separate type 
>> (Sphere, Triangle, etc...), and then made a type class that defines a 
>> ray intersection method (and a few other odds and ends), but then I 
>> realized that I can't do something as simple as store a list of 
>> primitives (or if there is in fact a way, I'm not aware of it).
>> Instead, I made a single large sum type with all my primitives:
>> so that now I can easily make a list of primitives.  (In fact, that's 
>> what a Group is.)  I also gave up on using named fields, since coming 
>> up with a separate name for each one gets ugly:  instead of radius, 
>> you have sphere_radius, cylinder_radius, cone_radius disc_radius, etc...
>
> All of which works, but now it's a pain to add new primitives. And 
> *all* supported primitives must be defined in a single monolithic 
> module. And you can't reuse spheres as bounding volumes without either 
> reimplementing them or loosing type safety.
The part about spheres and bounding spheres is actually not so much of a 
problem:  I implemented a general "Bound" primitive that can bound any 
primitive with any other.  In general, you would use a simple object 
like a sphere or box as the left argument and a complex object as the 
right argument.

data Solid =  ...
            | Bound Solid Solid
              ...

and then to intersect the "Bound" object, you first do a shadow test on 
the left object before testing the right object:

rayint :: Solid -> Ray -> Flt -> Texture -> Rayint
rayint (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

Some kinds of primitives aren't likely to work well for bounding since 
they don't have a well-defined inside and outside (like triangles and 
discs), but I'd rather provide maximum flexibility and assume that users 
know how to use it sensibly.

http://www.haskell.org/haskellwiki/Glome_tutorial#Bounding_Objects

As for the maintenance issues, that is still a problem.  It would be 
nice to split all the individual primitives into their own modules.

Sebastian Sylvan wrote:

> On 4/27/08, Jim Snow <jsnow at cs.pdx.edu> wrote:
>   
>> > For instance, I started out by making each primitive a separate type
>> > (Sphere, Triangle, etc...), and then made a type class that defines a
>> > ray intersection method (and a few other odds and ends), but then I
>> > realized that I can't do something as simple as store a list of
>> > primitives (or if there is in fact a way, I'm not aware of it).
>>     
>
> You can, by using a "wrapper" type which wraps up any instance of the
> Intersect class:
>
> data Intersectable = forall a. Intersect a => MkIntersectable a
>
> For convenience you probably want to instantiate this wrapper in the
> class itself:
>
> instance Intersect Intersectable where
>   rayIntersection (MkIntersectable x) ray = rayIntersection x ray
>   boundingVolume (MkIntersectable x) = boundingVolume x
>   -- etc...
>
> Now you can stick Intersectables in lists etc.
>
>   
I think that sounds like what I ought to be doing.

-jim




More information about the Haskell-Cafe mailing list