Come up with another whistle and implement it.  A whistle is something that extends the use of one of the things you are already doing. It is part of the basic model construction, but extended or cloned and modified in an interesting way. Ask your TAs to make sure this whistle is valid.

Enhance the required spline options. Some of these will require alterations to the user interface, which involves learning Qt and the UI framework.  If you want to access mouse events in the graph window, look at the CurvesPlot function in the GraphWidget class.  Also, look at the Curve class to see what control point manipulation functions are already provided.  These could be helpful, and will likely give you a better understanding of how to modify or extend your program's behavior.  A maximum of 3 whistles will be given out in this category.

Let the user control the tension of the Catmull-Rom spline.

Implement one of the standard subdivision curves (e.g., Lane-Riesenfeld or Dyn-Levin-Gregory).

Add options to the user interface to enforce C1 or C2 continuity between adjacent Bezier curve segments automatically. (It should also be possible to override this feature in cases where you don't want this type of continuity.)

Add the ability to add a new control point to any curve type without changing the curve at all.

The linear curve code provided in the skeleton can be "wrapped," which means that the curve has C0 continuity between the end of the animation and the beginning. As a result, looping the animation does not result in abrupt jumps. You will be given a whistle for each (nonlinear) curve that you wrap.

Modify your particle system so that the particles' velocities get initialized with the velocity of the hierarchy component from which they are emitted. The particles may still have their own inherent initial velocity. For example, if your model is a helicopter with a cannon launching packages out if it, each package's velocity will need to be initialized to the sum of the helicopter's velocity and the velocity imparted by the cannon. You'll probably want to do this in the EmitParticles or InitParticles function.

Particles rendered as points or spheres may not look that realistic.  You can achieve more spectacular effects with a simple technique called billboarding.  A billboarded quad (aka "sprite") is a textured square that always faces the camera.  See the sprites demo.  For full credit, you should load a texture with transparency (sample textures), and use the Textured Material or your own Material that has alpha blending (see this tutorial for more information).  Hint:  When rotating your particles to face the camera, it's helpful to know the camera's up and right vectors in world-coordinates. Do this in glRenderer::Render(SceneObject&, ParticleSystem).

Use the billboarded quads you implemented above to render the following effects.  Each of these effects is worth one whistle provided you have put in a whistle worth of effort making the effect look good.

Fire (example) (You'll probably want to use additive blending for your particles -glBlendFunc(GL_SRC_ALPHA,GL_ONE);)

Snow (example)

Water fountain (example)

Fireworks (example)

Add baking to your particle system.  For simulations that are expensive to process, some systems allow you to cache the results of a simulation.  This is called "baking."  After simulating once, the cached simulation can then be played back without having to recompute the particle properties at each time step.  See this page for more information on how to implement particle baking (although, note that this is an old webpage that refers to an older version of Animator. The function names may not apply, but the general logic for integrating baking is still useful).    

Implement a motion blur effect (example).  The easy way to implement motion blur is using an accumulation buffer - however, consumer grade graphics cards do not implement an accumulation buffer.  You'll need to simulate an accumulation buffer by rendering individual frames to a texture, then combining those textures.  See this tutorial for an example of rendering to a texture.

Euler's method is a very simple technique for solving the system of differential equations that defines particle motion.  However, more powerful methods can be used to get better, more accurate results.  Implement your simulation engine using a higher-order method such as the Runge-Kutta technique.  ( Numerical Recipes, Sections 16.0, 16.1) has a description of Runge-Kutta and pseudo-code.

Implement adaptive Bezier curve generation: Use a recursive, divide-and-conquer, de Casteljau algorithm to produce Bézier curves, rather than just sampling them at some arbitrary interval. You are required to provide some way to change the flatness parameter and maximum recursion depth, with a keystroke or mouse click.  In addition, you should have some way of showing (a debug print statement is fine) the number of points generated for a curve to demonstrate your adaptive algorithm at work. 

To get an extra whistle, provide visual controls in the UI (i.e. sliders) to modify the flatness parameter and maximum recursion depth, and also display the number of points generated for each curve in the UI.

Extend the spring particle system with good results. For example, a pony tail can be simulated with a simple spring system where one spring endpoint is attached to the character's head, while the others are floating in space. For one more bell, implement spring-based cloth.  For 2 more bells, implement spring-based fur.  The fur must respond to collisions with other geometry and interact with at least two forces like wind and gravity.

Allow for particles to bounce off each other by detecting collisions when updating their positions and velocities.  Although it is difficult to make this very robust, your system should behave reasonably.

Implement the "Hitchcock Effect" described in class, where the camera zooms in on an object, whilst at the same time pulling away from it (the effect can also be reversed--zoom out and pull in). The transformation should fix one plane in the scene--show this plane. Make sure that the effect is dramatic--adding an interesting background will help, otherwise it can be really difficult to tell if it's being done correctly.

Implement a "general" subdivision curve, so the user can specify an arbitrary averaging mask  You will receive still more credit if you can generate, display, and apply the evaluation masks as well.  There's a site at Caltech with a few interesting applets that may be useful.

Perform collision detection with more complicated shapes.  For complex scenes, you can even use the accelerated ray tracer and ray casting to determine if a collision is going to occur.  Credit will vary with the complexity shapes and the sophistication of the scheme used for collision detection.

If you find something you don't like about the interface, or something you think you could do better, change it!  Any really good changes will be incorporated into the next Animator.  Credit varies with the quality of the improvement.

If you'd like, go back and implement any of the extra credit for Modeler in your Animator project. You'll receive half of the stated credit (so one whistle instead of one bell, etc.). Obviously, you'll only receive credit for features that you didn't originally implement for Modeler.

x2

If you implemented billboarded quads with transparent textures, you may notice issues with the alpha blending. OpenGL renders objects out in a certain order and for proper alpha blending, you must render out all opaque objects first before you draw any objects that have transparency, which should then be drawn from farthest to closest to the camera. Do this with your billboards for the additional two bells.

x2

Currently, the code makes a draw call for each particle in the system, which is really expensive. A more performant way of doing this is using "instanced rendering", which is rendering a single mesh more than one time using a single draw call. Draw Particle Systems using Instanced Rendering in glrenderer.cpp to see much better performance.

x2

Add flocking behaviors to your particles to simulate creatures moving in flocks, herds, or schools.  A convincing way of doing this is called "boids"  (see here for a short flocking guide made by 457 staff, and here for a demo and for more information).  For full credit, use a model for your creatures that makes it easy to see their direction and orientation (as a minimal example, you could show this with colored pyramids, oriented towards the direction in which the creatures are pointing).  For up to one more bell, make a realistic creature model and have it move realistically according to its motion path.  For example, a bird model would flap its wings to gain speed and rise in the air, and hold its wings outstretched when turning or gliding.

x2

Implement a C2-Interpolating curve.  You'll need to add it to the drop-down selection. See this handout.

x2

Add the ability to edit Catmull-Rom curves using the two "inner" Bezier control points as "handles" on the interpolated "outer" Catmull-Rom control points. After the user tugs on handles, the curve may no longer be Catmull-Rom.  In other words, the user is really drawing a C1 continuous curve that starts off with the Catmull-Rom choice for the inner Bezier points, but can then be edited by selecting and editing the handles.  The user should be allowed to drag the interpolated point in a manner that causes the inner Bezier points to be dragged along.  See PowerPoint and Illustrator pencil-drawn curves for an example.

x3

An alternative way to do animations is to transform an already existing animation by way of motion warping (animations). Extend the animator to support this type of motion editing.

x4

Incorporate rigid-body simulations into your program, so that you can correctly simulate collisions and response between rigid objects in your scene.  You should be able to specify a set of objects in your model to be included in the simulation, and the user should have the ability to enable and disable the simulation either using the existing "Simulate" button, or with a new button.