Compact Component ComposabilityPosted: April 14, 2012
What’s that? Finally able to display 3D again? Well yah. Given the way HeadsUp works these days, a CAD program, or at least a simple STL Viewer, is just a few lines of “sample app” code. It looks like this:
require "STLCodec" require "Scene" require "SceneViewer" local defaultscene = Scene(); local sceneviewer = SceneViewer(); -- Typical rendering initialization stuff function init() -- create a mesh to be rendered local mesh = import_stl_mesh("bowl_12.stl"); -- Add the mesh into the scene defaultscene:appendCommand(CADVM.mesh(mesh)) end function reshape(w, h) if h == 0 then h = 1 end gl.glViewport(0, 0, w, h) sceneviewer:SetSize(w, h) end function display() sceneviewer:Render(defaultscene); end
So, for roughly 25 lines of code, you can load and display STL files. The SceneViewer object takes care of displaying the scene, including zooming, rotating around and all that. To load the stl in the first place, I’m using the import_stl_mesh() function, which comes from the STLCodec class. That’s a nicely isolated component. It can deal with reading and writing STL files. Right now it only does ASCII forms, but a little bit of code will enable binary as well. It’s nice because it’s totally isolated from the rest of the code, so it can easily be improved.
Another bit of isolation comes from the Scene and SceneViewer objects. The scene is a simple repository for things like shapes, and meshes, and other things, like rotations, translations, and the like. Your basic scene manager. The SceneViewer knows how to take a scene, and render it. It starts with a default camera and position, and color scheme. All of those things are changeable, but the defaults are good enough for most uses.
And that’s about it. All the little pieces are fairly small. Nothing more than 400 lines of code, but how they compose is the key here.
Now, to add another format, such as VRML, is a matter of adding a VRML codec. It would load into a TriangleMesh just like the stl codec does. One of the nice benefits of the separability of concerns is that you can deal with things at whatever level you like. For example, once you load a mesh in, you don’t have to render it at all. You can simply run some routines over it, and save it out again. For example, if you wanted to eliminate duplicate vertices from a mesh, you might do something like:
local mesh = import_stl_mesh("bowl.stl"); export_stl_mesh("bowl_new.stl", eliminate_duplicate_vertices(mesh));
…and you’re done. I’ve written about the desire for this kind of composability previously, but now it’s actually achievable. This kind of composability also makes for a ready made “extensions” capability for the CAD program. Since the CAD program BanateCAD is nothing more than the composition of a few different things, they can be reshaped into any configuration, and any part can load any new modules it feels like, without the primary app having to intervene in any way.