You can call me RayPosted: February 13, 2012
What is that? Well, it’s a bunch of spheres that have been RayTraced in BanateCAD!
I’ve been going on a very interesting trip of late. What I have been pondering on my walkabout is the following:
Is it possible to support – 3D CSG, Isosurface, Solid Modeling, Perspective, Orthographic, Arbitrary Bump Mapped surfaces, collaboration, and 2D UI, all in a single environment, written almost exclusively in Lua, in less than 256K of source code?
It’s a challenging endeavor. Every new feature adds code. I’ve been following a simple principle. For every expansion of code, there must be an equal and opposite constriction of code.
I am looking at Ray Tracing as a relatively quick way to display a scene. The first time I even played with ray tracing was probably back in 1994, playing with whatever version of POV-Ray was available at that time. On my standard issue PC of the day, I would setup a semi-translucent sphere on checkered floor scene, and let it run overnight! Wow, how times have changed. Given all the processor performance doubling in the intervening years, machines are certainly capable of rendering much more complex scenes in a fraction of the time. My thinking is, Ray tracing is the way to go for instant display, and I don’t deal with meshes at all until I absolutely need to. That might only be at export time in most cases. At the same time, it will make displaying isosurfaces in general much easier.
When it comes to the simple ‘scenes’ in 3D modeling, a fraction of a second to render an interesting model should not be unheard of.
Ray tracing is interesting. Similar to 3D modeling, there are some core geometries that you want to deal with. Ellipsoid, cube, cylinder, etc, and of course some interesting surfaces. This implies a certain kind of ‘world’ model. Some sort of data structure that exists so that when it comes time to cast rays, you can walk that structure, calling an “intersect()” function for each object.
Similarly, you have the same thing for 3D modeling, but you’re a bit more concerned with a mesh representation, as you’re going for 2-manifold solids so you can actually print things out. That implies a representation that favors some mesh like thing.
And finally, there’s the 2D UI world. Not 2-manifold, so no mesh required, and instead of a “hit”, which is concerned with hit a boundary of an element, you have “contains()”, which is concerned with whether a mouse click is ‘inside’ or ‘outside’ the object in question.
Yep, quite a lot to balance there.
There are essentially three different kinds of renderers, and at least 2 different types of UI interactors (2D vs 3D).
So, some basic things will help here. First of all, there needs to be a fundamental way of organizing ‘scenes’ that’s universal. I can default to the 3D representation because I can always assume ‘z==0’ for the 2D world, with some arbitrary non-zero thickness. That’s nice. And how about the actual structure itself? How about a k-d tree? That seems to be a nice universal structure that can be applied to the 3D scene. It can nicely deal with quickly isolating which objects are in which part of a scene, without having to traverse the whole scene graph. This is critical for fast rendering updates. OK, that’s good, and I can reduce a lot of code.
How about basic data structures? Well, I started out with a ‘vec’ object. A basic one dimensional array that deals with doing some basic linear algebra. Then I added Vector3D, Point3D, Normal3D, and Ray3D. All very similar, but slightly different. And then, I added the Matrix class, which deals with 1D or 2D arrays (1D being a degenerate case). Well, there’s really no difference between the Matrix class and the vec class, so I think the vec class can disappear, or rather simply become a wrapper for the Matrix class. Same goes for the other ones, although, they are presently just wrappers for vec anyway. So, more reduction.
At present, the ray tracer is so rudimentary it’s not even worth calling it a ray tracer, but it is extremely small (80 lines of code). As it expands in features, it will more than double, and perhaps triple in size. Given that I won’t need to introduce any new geometry, this expansion is not that bad. I’ll pay for the expansion through consolidation of the aforementioned vector/matrix objects, and savings elsewhere.
In other news, I’ve been playing with LuaJIT some more, and have a basic Pixel/PixelBuffer thing working. It’s fast as can be, and can already be used as an output surface for any of the 3D modeling that I’m currently doing. This bodes well since I can cut the number of dependencies (CD and IM Libraries), which makes the code that much smaller and portable.