28. Isn’t That Where Superman Lives?
Mike and I thought we could make a difference by designing a 3D system that was more advanced than anything out there. Coming off our stints at Softimage, we were confident we could do better. Just the two of us.
The idea wasn't as far fetched as it sounds. After all, Softimage had been developed by four programmers, and we were two of them. We had this. More tea, please.
The design of the system began to take shape over our weekend lunch meetings. I did most of the talking, and Mike (who had difficulty speaking) made his points by typing on his Tandy TRS-80 Model 100, which was an early laptop with an 8-line LCD display. Or he would just laugh and give a thumbs up if he particularly liked an idea.
I wish I had the design documents from those sessions, but a house fire in 2007 destroyed everything.
Our system would consist of modeling, animation, rendering, and paint modules. It would be extensible so technical users could exploit the full power of the system. We were using the Symbolics S-packages as the gold standard for extensibility.
I brought up one of my ideas from my Neo-Visuals days: the idea of intelligent objects that the user could interact with like a film director, not just on a frame-by-frame basis like a traditional animator. Mike gave the idea a thumbs up.
Objects would have internal logic and be able to plan and execute their own motions. A human character would know how to sit, stand, walk, open a door, and make a plan from stated goals. I wanted to be able to tell a character “get a drink from the fridge” and have it plan, sequence, and execute the animation.
We were nothing if not ambitious. And for the record, I still think the idea has merit.
We called our company Metropolis Graphics.
Design & Code
The image above consists of several circles of differing resolutions. What makes them interesting is that the shapes automatically recompute their points if any of their slots change, as indicated in the code listing.
I wanted a mechanism for implementing procedural geometry, which means some slots of an object depend on other slots.
After some thought, I implmented the procedural-mixin
class. Guess I’m really embracing CLOS’s multiple inheritance. In fact, I’ve decided to make use of as much of the functionality of the object system (and Common Lisp in general) as possible. I wonder what I could do with reader macros.
This dependency mechanism is implemented using a mixin class and method combinations on accessors, all wrapped up in macros.
Each “input” slot defined by def-procedural-input
gets an after method on its setter, which sets the mixin’s dirty flag. And each “output” slot defined by def-procedural-output
gets a before method on its getter which calls the mixin’s compute method if the dirty flag is set.
I’m curious to see how this design holds up, and whether I can extend it to dependencies between different objects.
Also curious to know if this can be implemented in a simpler way in some other language.