Fundamental Concepts of Animation: Frames, Layers and Layer FoldersBy Yatin S. Shelke
The science of animation is now nearly a century old. It started with simple animated cartoons on movie projectors but today it is a cutting edge technology using powerful computers and display devices. The basic technique of animation remains a continuous loop of two steps:
The concept of a Frame is of fundamental importance to animation.
A frame is uniquely defined by a combination of the image to be displayed and the time the image is to be displayed. A sequence of frames makes an animation. Each frame is displayed on the screen until the next frame overwrites it. Since each frame remains displayed on the screen for a tiny but finite time period, you can think of an animation as frames displayed at discreet intervals of time in a continued sequence.
Any scene change happens by drawing a whole new frame. Even changing a single pixel requires drawing the next frame in its entirety. Furthermore, even if the image of the scene remains constant, identical content must be drawn in subsequent frames as long as the still scene is needed.
In practice, the time needed to refresh the screen must be negligible compared to the time the frame remains on the screen. If this were not so, the viewer would notice the individual scene changes, which would be an awful animation experience. In the case of a movie projector, the refresh time is the time that the shutter remains closed while the next frame of film is loaded. In case of the computer monitor, it is the time required for the monitor's electron gun to traverse the entire screen from left to right and up to down to draw each pixel on the screen.
The content of the frame is the image (every pixel on the screen) to be displayed. It is possible for one monolithic function in an animation engine to draw all the pixels of each frame. The movie projector is like this kind of monolithic function, as it loads an entire image for each frame. The movie projector can do this because the content of each frame is available as a separate image. However, it is a completely different situation in a video game. Let's say that the player is sitting still in a closed room. The screen will display a still image of the room view. Now the player gives some input to turn around the room gradually. For example, right-click-and-drag in SPORE turns the player gradually, at the speed of the mouse. The view of the virtual world needs to change as the turn progresses. It would be impossible to store every possible image of the virtual world and then load the right image for each part of the turn. Instead, the content of each frame, while turning, must first be computed and before it is copied into video memory. The term for this computation is Rendering the frame.
The imagery in the 3D games available today is very realistic and detailed. In DOOM 3, almost every object in the game is a 3D object and there are lots and lots of objects in any one scene of the game. Every object requires code to be drawn. The final image of each scene is a composite of the images of individual objects drawn in a particular sequence. A possible drawing sequence is the walls, floor, ceiling, the fixtures on the walls, the pictures on the walls, the doors, windows, the furniture of the room, the objects on the floor, the objects on the furniture, the monsters in the room and finally the player's hands and weapon. The order is important because, for example, the furniture must be drawn after the walls and floor, otherwise when the walls and floor were drawn, they would overwrite the furniture. The player's hands and weapons must be drawn last as they should always be visible. To achieve this proper layering, you can write separate functions for drawing each object and have the main frame drawing function call these individual functions in a particular sequence. Since each object being drawn can be mapped to an Animation Object, you can think of a "Layer" abstraction that holds the Animation Object and provides the animation engine the image for the Animation Object. The animation engine asks the Layer to draw its contribution to the frame image content. The abstract class Layer should have a generic method to get the image contents of that layer e.g. Layer::get_image_content(). This method would call AnimationObject::get_next_frame() on the animation object that it contains.
The layer based drawing technique actually comes from the film making industry. The title and credits for a film provide an excellent example: the title and credits are drawn on one layer of transparent film, which is then superimposed on a layer of the film images. The composite image is then transferred to the final film reel. In films, this process is done for all frames of the film before the final film is created. In video games, the superimposition of different layers happens just before each frame is displayed.
But why do you need both a Layer and an Animation Object? After all, what does the method Layer::get_image_content() add over and above AnimationObject::get_next_frame()? The answer comes from the idea of Layer Folders.
Image a creature that you can build in the game SPORE. The creature consists of many body parts, including a torso, head, arms, legs, feet, and eyes. The creature editor allows you to customize each body part. By clicking on the arms, you can resize and rotate the arms. By clicking on the torso, you can lengthen and twist the torso. When you lengthen the torso, the position of the arms is automatically adjusted. There must be a logical connection between the animation objects for the torso and the arms. When the torso is resized, the arms must be repositioned. The animation object for the torso must be able to locate the Animation Object for the arms, so it can call GraphicObject::reposition() on the arms. Although the game SPORE may have a very different implementation, one way to let the torso animation object get the arms animation object (without hard-coding the refernece) is to put the two layers containing the torso and the arms into a "Layer Folder". The method that resizes the torso can then loop through each layer in the same "Layer Folder" as the torso, locate the Animation Object and the Graphic Object and then call GraphicObject::reposition().
Layer Folders are also used to group pieces of a composite animation object together. The Layer Folder contains a list of objects that are either Layer objects or Layer Folder objects. The abstract class LayerFolder needs a method get_image_content(), just like Layer::get_image_content(). The method LayerFolder::get_image_content() would go through a list of the Layer and LayerFolder objects held in a given LayerFoldre and call get_image_content() on each of them. Because Layer and LayerFolder share the common abstract method get_image_content(), it is simple to organize a complex scene with multiple objects into a hierarchy and be able to get the final image content of the frame by calling get_image_content() for the root object of this hierarchy.
Frames are a fundamental concept in animation. A frame contains the image to be displayed at a unique time in the animation. A sequence of discreet frames constitutes an animation.
Layers are containers for animation objects. By containing animation objects in layers and ordering the layers in a sequence, it is possible to manage the correct drawing of the image content of each frame.
Layer Folders contain Layers and other Layer Folders. By organizing animation objects into layers, and layers into layer folders, it is possible to create composite animation objects which can be managed in isolation from the rest of the scene.
The abstractions of Graphic Object, Animation Object, Layers and Layer Folders will be used to discuss how to build an Object Oriented Animation Engine in the next two articles.
Back to part 1: Object Oriented Animation Design