Q Solutions |
Traditional 2D animation systems rely on sprites. All we have to do is move rectangular bitmaps around the screne to create effects. With 3D we have to create objects and apply geometric transformations to those objects to create the effect we desire.
The challenge for an animation system in Tcl is to minimumise the amount of work to be done for each frame.
The entire system is about building display lists. Some display lists call other display lists, some generate transformations, some define colours or textures, and others privide the infrastructure for viewing. To allocate a new display list we simply type
This would create a list and assign a name that can be used to reference the list in other parts of the system.
Most of the time you can specify either a name or a number when referencing a display list.
We use display lists in Tcl because they are cheap and efficient to manage. Once built the openGL commands can be called apon everytime the scene needs to be redisplayed and we do not need to build the display list each time if the scene is static. This reduces the work load that Tcl has to do each frame.
We abstract the display lists, by using named shapes. To make a box we would issue:
$scene shape define MyBox { glutSolidCube 1 }This would create a new shape item with the name MyBox and place the enclosed openGL commands in it. Inside the braces we may type a mixture of Tcl commands and shape primitive commands.
Shapes may be called multiple times. Unlike other systems, we do not need to create a new shape behind every object on the screen.
For example, to create a shape that displays two boxes, one red and one green we could:
$scene shape define ABox { glutSolidCube 1 } $scene shape define TwoBoxes { Translate y 2 Colour r 1 Shape ABox Translate y -4 Colour g 1 Shape ABox }We see that the ABox shape was called two times from within the TwoBoxes shape so it will appear in two places in the scene. Since the shape ABox does not contain any commands that affect it's colour, it will use the colour as defined by the TwoBoxes shape. This allows us to draw an object with different properties with ease.
There are no conditions placed on what openGL commands can be placed in a display list so we could issue commands that change the viewport, or projection matrix. We could render an object multiple times to simulate motion.
The most common usage of shapes other than for placing drawing commands are for animating the properties of the displayed shapes.
Consider the following:
$scene shape define Colour {} $scene shape define AnotherBox { Shape Colour glutSolidCube 1 }Now lets change the colour of the box, lets make it green
$scene shape define Colour { glColour3f 0 1 0 }Without changing the drawing commands that make up the AnotherBox shape we have changed it's colour. We at anytime can change the Colour shape and it will affect the AnotherBox shape. We could place commands that change a shapes size, or location.
The above is such a common task that we have a special shape to make it easier to do all the above:
An attributed shape is a shape that holds a number of other display lists in addition to the one used to store the drawing commands. We can define a shape as follows:
$scene ashape define AnimatedBox {position rotation colour} { glutSolidCube 1 }In addition to the drawing commands that you specify for the shape, there are calls to the attribute display lists placed before your first drawing command.
$scene ashape update AnimatedBox position { glTranslatef 3 0 0 }This moves the box shape three units to the right. At some later time we can change the rotation
$scene ashape update AnimatedBox rotation { glRotatef 45 0 1 0 }Which would rotate the box 45 degress around the Y axis, while keeping the original translation intact.
We can even place drawing commands inside attribute display lists if we so wish to do so. We could use this to create a shpe made of multiple parts and update part of the shape independantly of the others.
$scene vlist add MyList Shape1 $scene vlist add MyList Shape2 $scene vlist add MyList Shape3 $scene vlist add MyList Shape4When we add shapes to a VList the list is automatically rebuilt. In the above case it would be as if the following was typed:
glNewList [$scene ~MyList] GL_COMPILE glCallList [$scene ~Shape1] glCallList [$scene ~Shape2] glCallList [$scene ~Shape3] glCallList [$scene ~Shape4] glEndListThe mechanism used is much more efficient than the above, and can rebuild a vlist containing thousands of shapes using one openGL command.
To get the above displayed on the scene we would issue:
$scene vlist create Shape1 $scene vlist add Shape1 Wheel $scene vlist add Shape1 Body $scene vlist add Shape1 EngineThis creates a heirarchy of shapes all indirectly linked to the Objects display list.
One other piece of good news is that we can rebuild a shape that is called from another display list and the other display list will render the new version of the shape.
This means for example, if we changed the Engine shape in the above example, the change would be reflected on screen the next time the display is redrawn. We do not need to rebuild the lists that contain the shape we have modified.
Each of the above lists can be either a number of openGL commands, or a VList which calls any number of other display lists.
The ClearDisplay list normally contains:
glClear GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BITThis is the command we normally use to begin each frame of an animation. We could add to this list the commands for setting the clear colour and anything else we may require for specialised situations.
The list Objects is the VList where we would normally add all our other shapes and vlists that make up our scene that we are currently displaying.
Images are trivial to use in Qanim. Tclogl allows loading Tk photo images as textures. These textures can be mapped to any shape.
In normal useage, we would map the four corners of the image to the four corners of a QUAD.
All transformations such as rotation and scaling can be applied to the Textured shape.
Based on the texFont system developed by SGI, these are alpha maps converted into textures. Each characters position in the texture is recorded so these can be used to map in individual character to an shape such as a QUAD. Since they are apha maps, the shape becomes transparent except for the shape of the character.
Multitexturing allows us to apply textures to the glyphs to make textured characters.
The scene is normally redrawn only when the viewpoint changes. If events are created then an after event is triggered that causes the display to be redrawn at the rate required while events pending.
The after event requests that the togl widget redraws itself. When the redraw procedure is called it calls the event loop to process any pending events. The event callbacks should update any display lists they are queued for at this time.
After all events have been processed the scene is redrawn. All events know the relative time that has elapsed since the event was first created. This allows the event to recreate the display list to represent the point in time for the effect being drawn.
Events are placed in the queue with a simple call, for example:
$scene event timer 10000 100 MyTick args ... argsThe above registers the callback MyTick to be run every 100 mS for 10 seconds.
QAnim currently supports three types of events
Every event can be called at three distint times, a mode variable is passed to the callback to signify the reason for being called:
Every callback can take additional arguments as defined in the event proc definition. Like a normal Tcl proc, these arguments can be mandatory or optional. If an error occurs during processing of the event, the event will be dequeued.
QAnim is designed to be be extended at all levels. All features are implemented as Tcl procs with a structured name.
If we wanted to add a feature to shapes called wobbleme then we could simply create a proc as:
proc Shape/wobbleme { ....} {....}After definition it can be used by calling:
$scene shape wobbleme Shape args ....
All primatives that can be called from shapes such as boxes, balls, rods, cones, spirals, images, to name a few are just procs that are loaded at runtime. The user can design their own primatives by simply creating a proc.
To help users do this we have already defined a primative to make this simple:
$scene shape primative wobbleme {args} {.....}
Every feature of the Qanim system is in fact an extension, this includes Fonts, Textures, Shapes , Sound. They just happen to be defined by default. Every existing command can be changed or extended as the user desires.
We can render a shape to the feedback buffer and read back the 's vertex, colour and texture data.
This has numerous uses, some of them are:
We use a general callback method to transform coordinates. We use callbacks to generate a list of coordinates, colours, texture coordinates, and normals which can be then used for mapping text, images or other shapes. This can be used to map:
Copyright © ![]() |