Assignment 2 - Animating a Clock Escapement
Due Date: Thursday January 25th, 11:59PM
Questions? Check out the Assignment 2 FAQ and discussion page.
We've posted solutions to the Assignment 2 questions on the Assignment 2 Solutions page.
In this assignment you will practice working with transformations. You will use OpenGL to create an animation of a pendulum clock by specifying the transformations that need to be applied to a number of simple 2D shapes. Also in this assignment you'll learn to work with several classes from the Stanford Toolkit library (libST). These classes provide you the ability to load and save graphical objects, such shapes and images, from disk and to organize the graphical components of a scene using a scene graph. As a bonus, you'll get to learn a bit about how a clock works (the TAs did!).
About Clock Escapements
In high school physics, you probably saw an experiment demonstrating how the period of a swinging pendulum is dependent only on the length of the pendulum (not on how hard or high you swing it). Because of this property, clock designers have long used pendulums to keep accurate time. In a pendulum clock, an energy source, such as a falling weight or coiled spring, drives the rotation of a gear. A device called an escapement utilizes the periodic motion of the pendulum to reliably limit the speed at which the gear turns. This gear drives other gears which spin the various hands of a clock. For example, clock's second hand is attached to a gear that rotates one complete revolution per minute. Before being coding on this assignment, take a few minutes to read the simple explanation of how pendulum clocks work at HowStuffWorks.com. You also might want to check out the clock escapement animations here.
In this assignment you will animate a pendulum clock with two hands (a second and a minute hand).
Download and build the starter code
We've created a library of C++ classes that are designed to be simple to use and handy for graphics (we called it libST, for Stanford Toolkit). You'll use parts of this libary in most of the remaining assignments in the class. Download the assigment 2 starter code and libST source here.
Build the toolkit. libST source code is located in the /libst subdirectory. In this directory there is a Makefile for building with g++. Solution files for Visual Studio 2003 and 2005 are located in the /libst/vc2003 and /libst/vc2005 directories respectively (Mac support coming soon, although you should be able to use the Linux Makefile as the basis for a Mac build). A Visual Studio build of the library should result in the creation of /libst/lib/libst.lib (If you are using g++, building the library will produce /libst/lib/libst.a).
Build the clock application. The starter code for assignment 2 is located in the directory /assignment2. For this assignment you will modify clock.cpp to produce your clock animation. This directory also contains a number of text files with a .shp extension. These files describe 2D shapes that can be loaded and drawn by the STShape class. Again a g++ Makefile and Visual Studio project files are provided so you should be able to build the clock application on your platform of choice. Running the provided sample code will produce an animation of a clockwise rotating yellow gear and a counter-clockwise rotating circle and rectangle. It should look like this:
Understanding the Stanford Toolkit
You will need to use several libST classes in this assignment. The following is a brief overview of what the necessary classes do:
STImage - STImage is capable of reading and writing common image file formats, and drawing these images to the screen. In this assignment, you'll use STImage to capture the contents of your OpenGL window and save off the image as a file on disk.
STShape - STShape loads and draws 2D shapes.
STScene/STSceneNode - STScene is an implementation of a scene graph. A scene graph is a data structure that organizes all objects to be drawn on the screen into hierarchies of nodes. Nodes may contain objects (like STImages or STShapes) or they may contain other nodes. Each node in the scene graph has a transform associated with it.
STTimer - a simple class for timing. You will need to keep track of elapsed time on this assignment to ensure the hands of your clock are moving at the correct rate.
STTransform - In libST, transform data is encapsulated in the STTransform class. STTransform can represent scales, translations, or rotations.
Answer These Questions
libST is written to be easy to understand. You should be able to scan through the code and quickly get a sense of what it does. Please clearly answer the following questions about libST, and include your answers as part of your submission.
- In order to complete this assignment you'll have to understand the STTransform class. Describe libST's representation of a transform and compare it's flexibility to an alternative representation, such as the 4x4 matrix representation Pat discussed in class. For example, can you name a type of transformation that STTransform cannot represent. Describe the order that the STSceneNode class performs the various rotate/scale/translate transforms when drawing the scene (ie. what is the first operation performed on the shapes vertices? what is the second? third?). Are there other orderings that would produce the same result?
- Note that graphical objects, such as instances of the STImage and STShape class are not scene graph nodes (but they can be contained within STSceneNodes). By inspecting the implementation of STSceneNode, determine if it permissable to add the same object to the scene multiple times (Eg. Can multiple scene nodes contain the same shape object)? Why would one want to do this?
Assume you had an STSceneNode n, and a STShape s. How would you add this shape as the first child node of n? How would you add it as the last child node of n?
The STImage::read() method doesn't read data off disk, it reads it from the OpenGL framebuffer. The method takes 4 integer arguments. Describe the meaning of these arguments. You will call this method as part of the required code for this assignment. How are the values you pass to STImage::read() determined in clock.cpp?
Drawing the Clock
The provided clock.cpp contains code to serve as an example of creating libST image and shape objects, and placing these objects in the scene. You will need to add code that loads all the appropriate shapes and inserts them into the scene graph with the appropriate transformations (scales, rotations, and translations) so that your final image looks like this:
Note that in our simple clock, unlike most clocks you see, the second and minute hands don't have the same axis of rotation. The image you see above is rendered from a total of 10 shapes:
- 5 of the shapes are gears
1 gear with 60 pointed teeth (escapement_gear_60.shp)
1 gear with 80 flat teeth (gear_80.shp)
1 gear with 48 flat teeth (gear_48.shp)
2 small gears with 8 flat teeth (gear_8.shp). These gears are attached to larger (the blue and yellow) gears , and therefore rotate with the corresponding large gear as if they were glued together.
3 rectangles representing clock hands and the rod of the pendulum (see STShape::Rect()).
1 circle representing the weight of the pendulum (see STShape::Circle)
1 shape forming the part of the escapement the utilizes pendulum motion to limit the yellow gear's rate of rotation (escapement_ticktock.shp) In a real clock, it is the contact of this piece with the escapement gear that makes the tick-tock sound of the clock.
To help you along, here are a few hints:
- The data in the gear shape files is such that the teeth are all the same size. Therefore, no relative scaling of the gears should occur.
- The escapement piece does need to be scaled relative to the gears. Scaling by 50% should do the trick.
- You are free to choose the size of your clock's pendulum (recall, in a real clock, this would not alter the period of the perdulum's swing).
- You will need to scale the entire scene to get it to fit in the window. In the example above the entire scene is scales and translated for a good fit.
- Below is a diagram showing distances between gear centers. The red dots show the axis of rotation for each of the gears and the pendulum structure.
Animating the clock
It's now time to put your clock in motion. The start code already contains an event handler, timerTick() for GLUT timer events. The event is set up to occur 'framesPerSecond' times a second. You'll need to modify the code in this function to swing the pendulum and rotate the clock gears and hands at the correct rate.
Clock hands are attached to gears, and therefore the big yellow gear on the right must spin at a rate of one revolution per minute. Since the gear has 60 teeth, it rotates at one tooth per second. Since the escapement is designed to allow one tooth to pass with each full swing by the pendulum, the period of your pendulum must also be one second. In your animation, set the peak of the pendulums swing to be 5 degrees from vertical.
The rotation of the rest of the gears can be derived from the rotation of the big yellow gear based on gear ratios (recall that the ratio between two gears is the ratio of their number of teeth). In the end, your minute hand should rotate at a rate that is 60 times slower than the second hand.
Here are a few tips:
- The angle of rotation of the pendulum can easily be modeled as a trigonometic function
- Use the STTimer class to determine the amount of elapsed time between two timer events. Do not make assumptions about elapsed time based on the delay specified for GLUT events.
- The '+/-' keys are set up to increase and decrease the rate at which time passes for your clock. This is useful for debugging.
Saving frames from your animation
The last step in the assignment is to use the STImage class save images of the screen. This will require modification to the writeFrame() function to create an STImage object and correctly invoke the Read() and Save() methods. Pressing the 's' key will now save the current frame to a .png file.
Extras For Personal Kicks
- Add an hour hand to your clock (you'll need more gears--notice we gave you an 16 tooth gear shape file).
- See if you can figure out how to make the minute and second hands of your clock display the correct time (as obtained from the system time)
Note that it should be easy to modify clock.cpp to save out a sequence of frames that you can then combine into a movie. If you do this, we'd like to see your movies!
This assignment will be graded on a scale of 1-4.
- 1 -- correct answers to assignment questions
- 2 -- correct answers to assignment questions + ability to write images + clock correctly draws but does not animate
- 3 -- correct answers to assignment questions + ability to write images + minor problems in clock animation
- 4 -- Correctly animating clock using hierarchical transforms (correct appearance and rate) + ability to write images + correct answers to assignment questions
We would like submission to be in the form of a single .zip archive. This archive should contain your modified version of clock.cpp, a text file containing answers to assignment questions, and at least one image saved using your program. If you did any ungraded extras on the project, don't include them in the zip file, just create a wiki page to show them to the class and let us know in your submission email.
Please email this zip file to firstname.lastname@example.org before the deadline. Please make the subject line of this email "CS148 Assignment 2 Handin".