Most of us are familiar with "flying logos" - the short video segments that are used to introduce television news shows, sports segments, etc. In these short animated films, typically there are several geometric objects moving in front of some textured background. They may be abstract objects, or letters in some text font, or whole words (if "WMFE-TV" counts as a word.) A common characteristic of flying logos is that they go through a series of motions and settle into a static final scene, which the viewer admires (?) for a second or two before the video cuts to the next segment.
Our Lab 3 will consist of constructing a software package, using the OpenGL language, which can be used to construct, preview and (possibly) render flying logos. During the month of October we will work in small teams to design this system. Then in November, once the design is well understood and expressed, we will implement parts of the system.
Basic Architecture will consist of a set of core data structures which all modules must support; a set of basic actions including saving to disk and loading from disk, which should serve all modules; and an overall approach to the user interface. The design of the basic architecture is so important that we will work on it as a separate activity from the modular break-out teams.
We expect that everyone will belong to one (of perhaps three) Core Teams. All three Core Teams will implement the Basic Architecture we jointly designed. (This reduces our risk of not having any one system that works well enough to support the modules.) Within your Core Team of around 10 people, two to three of them will be chosen to build the core functionalities of the basic architecture.
Functional Modules are parts of the overall system that
correspond naturally to kinds of activities. We also expect that
ultimately these will be the units which students construct for
their Lab 3 (unless they're core-builders.) In our first brainstorming
session, we came up with the following functional areas:
Based on your interests you wrote down for me, I assigned each of you to a Design Team associated with one of the above topics. The work of the Design Teams will occupy three weeks (including this one). During each of these weeks, we will alternate between whole-group and breakout meetings. (While I'm gone, Dr. Hughes will lecture on VRML, but your design groups can keep on thinking.) Then, when I return from the OOPSLA conference, we'll see how far we've gotten.
There are many ways of organizing an object-oriented design process. One of the simplest is to successively describe the objects, what they must be able to do, and what they must "know" (what data they must get from elsewhere) to accomplish their missions. You probably have to jump back and forth among these three headings many times during a single design step. You then subject this design to some kind of a test or evaluation, which could range from a team-based simulation to a presentation to an external review team. You then go around that design process several times, in order to bring the results to closure.
How do you know when you're done? When you have a written description of the software which survives the evaluative phase without major changes, and which (seems to be) unambiguous enough that different programmers, given the same description, would produce code with the same external behavior.
Bottom-up vs. top-down. This sounds like a top-down design process, because we're asking that the whole thing be designed before any of it is implemented. Not so. You are free to make prototypes of any idea you want to insert into the design process, as long as you don't marry it. That is, don't let your ownership of the prototype force its inclusion into the final product, if it shouldn't be there.
Prototyping of "small ideas" is the key to the bottom-up process. Small ideas don't necessarily mean small isolated pieces of the final product; they may represent major pieces of the user interface. But they're lightweight in that they can be tried out well before you spend serious energy and permanently commit your project to one way of doing things.
Testing by simulation. When you think you have a good design, write each object's behavior on a piece of paper and assign each object to one team member. Have the tester "execute" the code by handing the first object a written input. WITHOUT SPEAKING, have that object write down the messages it would send to each of the other objects, and pass them over to the humans playing those roles.
When the result comes back, if the test person agrees it's right, then the design passed the test. If anyone had to speak to clarify their module's behavior, then that module's behavior description needs rewriting and the whole test should be redone, with different data.
Let's do a dummied-up design on the Polyhedral Objects component, just to set the flavor of how your group should work. We first chant the mantra:
Objects. We want to be able to bind together arbitrary rectangular-solid ("block") primitives, into rigid structures. We immediately observe two contradictory desires:
1. A result-oriented goal: These objects should be slightly better-drawn than those in the Lab 2 example, in that we would like to be able to delete interior join-marks; I. e. to unify the objects into a single polygonal structure. For instance a doughnut should look like one continuous (square) "circle" of material, rather than four blocks sitting together. (By "result-oriented", I mean: "It makes nice pictures.") BUT -
2. A process-oriented goal: The nice concrete "feel" of Lab 2's working with solid objects, rather than polygons, as its primitives, provides us with a motivation to stay away from polygons as our only primitives. It would therefore be nice to have a constructive-solid-geometry "layer" to our objects, so that we can avoid polygons as long as possible. (By "process oriented goal", I mean "it's easier to use than a polygon based system.")
Compromise/synthesis: We decide to work with solid cubes as primitives, but not to use auxSolidCube directly. Instead, we'll use our own UCFsolidCube, which could in turn either call auxSolidCube, or implement its own smarter polygon-based cube primitive.
Behaviors. Step 1: We want to be able to create, color, scale, rotate and translate solid block-primitives. We want to be able to specify any of the existing blocks as the "active block" and modify its position, color, etc.
Step 2: We want to be able to designate a second active block and instruct the system to bind it rigidly to the previous active block. The new object will be called a Composite. Composites will be able to operform the same actions as block-primitives.
Step 3. We realize that this means that blocks, and composites, are subclasses of the same -something- namely the things that can receive the commands we described above. So we decide that the hierarchy will look like
Lump: Block-primitive Composite
with Lump as the superclass, and Block-primitive and Composite as subclasses.
We can now formally list the behaviors of these classes:
Lump: SetColor(r,g,b); Translate(x,y,z); Rotate(angle, xa,ya,za); where xa, ya, za specify the components of the rotation axis Scale(sx, sy, sz); AddtoLump(b:Block-primitive) Block-primitive: New(); we have to be able to make new blocks.
But on reflection, we realize that we should be able to Add not only Block-primitives, but other Lumps, to a Lump. So we go back and change AddtoLump to take a Lump, rather than a Block, as its input.
Inputs. We pause to consider that once a Lump is built, it will be used by other elements of the Flying Logo system. What kinds of commands will THEY want to be able to ask a Lump to do? We decide that we will offer them (the other teams) a subset of the commands we're building for our own internal activities; excluding the ones like AddtoLump that make topological changes to the Lump's structure. When we put this proposal out to the other groups, we can expect that they will request extensions.
Where's the User Interface? Notice that we're not thinking about how to control this stuff from the user viewpoint, at all - yet. We are focusing on what the system should DO, first. The UI can only be designed after you have clarified what you want the system to accomplish.
Testing. So, we decide to do a simple two-person test. Angela and Bill (imaginary students) divide up the tasks. Angela will try to issue commands to Bill, to construct a castle, and Bill will accept her written instructions and (using a whiteboard) draw what her commands call for.
Angela calls for a new block named A. Bill draws a black cube at the center of the workspace.
Angela sets its color to red. Bill recolors it.
Angela sets its x,y,z scales to make a 20 x 2 x 20 "sheet". Bill redraws it.
Angela realizes that she wishes she could make the edges of the sheet different from its top color, but that there is no way to do so, given the current set of commands. She makes a note: "consider adding per-surface color for primitives."
She then orders up three blocks to be placed upon the base, to form a small arch. She gets the position of the third block wrong, but cannot tell because the view Bill is drawing doesn't show her the Z position of the blocks. She doesn't notice, but Bill does, so HE makes a note: "consider multiple-view user interface."
She combines the three objects into an arch, then tells the arch to rotate 90 degrees. She MEANT to rotate it around its vertical axis, but instead (of course) rotated it around the world coordinates' vertical axis. It goes out of sight. Bill laughs. They talk about it, and agree to add a Lump-behavior which rotates an object about its centroid. Rather than starting over, he adds such a behavior "on the fly":
Lump: RotateCentroid(angle,xa,ya,za)
When Angela calls for a RotateCentroid on the Y axis, she discovers that her block is out of place. She then realizes that she wants to take the block loose from the Lump, but there is no primitive for such an operation. She notes the problem.
---- this kind of role-playing rapidly identifies the desired behaviors of the objects. In successive rounds, issues which come up include
UNDO: should we provide a way for the calling-program to reverse the last action? We think through how such a calling program would solve the problem if we don't provide that resource for them. Since we're working on implicit data structures (that is, our commands don't receive the objects themselves as parameters, or emit new objects), we can't assume that the users would be able to hold a previous-version of the current Lump, to which to revert. So we have to decide whether to produce a "gimme-the-object" command which delivers a handle to the object, or keep it all encapsulated and just give the user an "UNDO" command.
If we give them an UNDO, we want to ask, "how? One layer? Toggle back? Multi-layer?"
PERSISTENCE: We will need to be able to store objects somehow,
if the ultimate system is to actually be a work-tool. It would
be good if the Global Architecture had some kind of a class which
handled storage of objects, but we don't yet know what ours would
look like, as data structures, so we don't know what to tell those
folks.
DATA STRUCTURE: We want a structure that is flexible enough to include polygonal representations, since we're realizing that our "color-the-faces" requirement can't be met by AuxSolidCube. But it also has to be able to deal with the CSG (constructive solid geometry) level of representation. Along in the third round of design, we settle on the idea of recommending to the outer group that we emulate the MIME system used on the Web.
Namely, the Solid Object team proposes a FLOSS (Flying Logo Object
Storage System) Type. The only thing that FLOSS would know about
an object was that it would consist of a one-byte FLOSS Type
classifier (0..7 reserved for system purposes; 8=Lump, etc.),
a two byte integer Length field, and then however many four byte
words the Length field specifies. It's up to the FLOSS system
to safely store and retrieve the record. It's up to the owner
of the FLOSS Type to provide code to re-cast, pack and unpack
objects into this common format.
Obviously, we aren't going to build a comprehensive 3d CAD system in half a semester. We are going to try to keep the specifications for each Functionality, down to a manageable level of complexity. The above Lump system has about ten behaviors and three classes, and that seems like enough.
By publishing your DESIGN early on, others will be able to do their design work with some confidence that they will be able to call on your objects to do things. For instance, the AnimationPath folks will know how they can position Lumps and fly them along the path, because they will know what routines you are providing. They can then "dummy up" animations, using a simple cube primitive and a trivial API built to resemble yours (maybe you'll even give it to them?).
Another kind of cross connection will occur when other object-builders (like the Font team) want to consider how they will compose their primitives into text strings. They may propose a command structure similar to yours. It would be a great kindness to the interface designers, if the teams building movable objects had a conference and hammered out a common protocol for such things.
Let's design the functionalities in October, and then once we
come to a common understanding about how the basic stuff works,
we can design the interfaces in November while we're implementing
the functionalities. We probably will mix-and-remix the teams
after the design activity is over, to give you a chance to move
to the things you find most interesting.
And now for the Team Assignments? If I missed anyone, we'll deal with it, or make new teams.
| TEAM | Members | ||||
| Typing/AniPaths | Uschold, Richard | Chassee, Earl | Zhang, Dan | Zhang, Dan | |
| Font Making | Rothrock, Michael | Zaheer, Ayesha | DiMicco, Ron | Deng, Ziqiang | DiMicco, Ron |
| Scene Editor | Cross, Peter | Wang, XiaoLu | Harrell, Lamar | Martin, Glenn | |
| Special Effects | Wilson, Kathleen | Stober, David | Gullette, Chris | ||
| Spline Based Objs | Avinash | Wirthlin, Ralph | Cui, Wei | ||
| Core Architecture | Vo, Van | Davis, Joel | Nelson, Dwayne |