David48 wrote:
On Sat, Apr 26, 2008 at 9:33 AM, Andrew Coppin
<[EMAIL PROTECTED]> wrote:
> Personally, I don't see the point in rendering a couple of million
> mathematically flat surfaces,
What about speed ?
That is a good point. Ray tracing may give you a better image
approximation than rasterizing triangles, but unless you're tracing an
infinite number of rays, it is still just an approximation. Some shapes
(like spheres) can be rendered more quickly in a ray tracer than
triangles, and they use less memory as well, so if you really want a
sphere, there's no reason to approximate it with triangles. For other
objects, the trade-offs are more complex.
...
Unfortunately, the SDL is so complex it's well-nigh impossible to
support in other third-party applications.
I don't think it would be "impossible" to support in 3rd party apps. A
lot of work, certainly! Especially the way the parser does parsing and
macro expansion in the same pass, so a macro body need not contain a
syntactically-complete code fragment. I think if somebody sat down and
wrote something that would do all the macro expansion, variable
substitution and so forth to leave just few geometry descriptions,
*those* would be quite easy to parse and manipulate for 3rd parties.
I guess a pov importer wouldn't necessarily be all that difficult, or an
exporter, for that matter. (Supporting every single primitive type,
texture, and rendering feature would be a daunting challenge, but just
supporting the basics might be relatively simple.) The problem comes
when you want to import a nice short hand-edited script, and then do a
few things to it and export it again: suddenly the file turns into a
multi-megabyte monstrosity with all the loops unrolled and all the
recursive macros expanded and you lose the ability to hand-edit the
scene. Depending on what you're doing, this might not be a problem.
Personally, I'd quite like to write my own ray tracer to address
some of these limitations. But every time I try, I end up hitting
design issues [Haskell works very differently to Java] or
performance issues [which I don't even know how to begin debugging].
Not to mention that POV-Ray uses sophisticated techniques like
volume bounding that I know nothing about. (There's nothing like
using an inherantly superior algorithm to make your code orders of
magnitude faster...)
I haven't really run into any issues where Haskell didn't let me do
what I want, except for the performance counters thing mentioned way
back at the beginning of this thread (and which I've more or less
given up on for now, since the acceleration structure seems to be
working okay and I have other things to work on).
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:
data Solid = Sphere {center :: Vec,
radius, invradius :: Flt}
| Triangle {v1, v2, v3 :: Vec}
| TriangleNorm {v1, v2, v3, n1, n2, n3 :: Vec}
| Disc Vec Vec Flt -- position, normal, r*r
| Cylinder Flt Flt Flt -- radius height1 height2
| Cone Flt Flt Flt Flt -- r clip1 clip2 height
| Plane Vec Flt -- normal, offset from origin
| Box Bbox
| Group [Solid]
| Intersection [Solid]
| Bound Solid Solid
| Difference Solid Solid
| Bih {bihbb :: Bbox, bihroot :: BihNode}
| Instance Solid Xfm
| Tex Solid Texture
| Nothing deriving Show
etc...
(strictness annotations and a few broken primitives omitted for brevity)
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...
Cones and spheres and boxes and the like can be made into some fairly
elaborate scenes, but you can't really make, say, a realistic human
figure out of those sorts of primitives.
No, but with things like isosurfaces and parametric surfaces, the
world is your oyster. And you can do a surprising amount of things
with blobs. I understand that all those curved surfaces which are
currently popular in consumer electronics are done with splines, not
triangles...
That world is a very slow oyster. I've used blobs and isosurfaces in
POV-Ray, and they're wonderfully expressive but also incredibly slow.
(The water in this scene, for instance, is an isosurface, and the boat
hull is a blob and some CSG: http://syn.cs.pdx.edu/~jsnow/castle-crop.jpg)
There are also other problems: the isosurface solvers are sometimes
wrong, leading to ugly artifacts (and a lot of manual tweaking to make
them go away), and applying a texture to an isosurface or blob isn't
necessarily straightforward.
Another issue is that isosurfaces are great for filling the scene with
procedurally-generated complexity, but sometimes you need to do actual
physics computations in order to make the object do the right thing.
For instance, in the image I linked above, the water looks pretty good,
but the waves should really be reflecting off of the castle when they
hit it, and there's no way I know of to do that without actually doing
some sort of finite-element fluid simulation. And since that's already
an approximation, and it's already taking up a lot of memory, you might
as well just represent it as a triangle mesh (or whatever happens to be
the easiest representation to render efficiently).
There's really a trade-off here between quality, time, and space. Any
blob or isosurface can be approximated with triangles, and if the
triangles are smaller than a pixel (or sometimes even if they're quite a
bit bigger) the difference isn't going to be noticeable. However, using
huge numbers of triangles consumes a ridiculous amount of memory, so you
often have to use a coarser representation. (Here's an interesting
paper about doing this sort of thing in a clever way:
http://www.llnl.gov/graphics/ROAM/roam.pdf)
Isosurfaces and blobs
(http://povray.org/documentation/view/3.6.1/71/,
http://povray.org/documentation/view/3.6.1/73/) are two features I
really like about POV-Ray, but they're very CPU intensive.
In other news, I have the beginnings of a tutorial up on the Haskell
wiki that describes how to write your own scene with Glome:
http://www.haskell.org/haskellwiki/Glome_tutorial
-jim
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe