
This assignment will allow you to implement a basic particle system. At its simplest, your program will be able to spawn particles, apply forces such as gravity and drag to them, and bounce them off of geometry. Once you have the basic system in place, you have a broad selection of options to improve your system. You can choose to focus on the rendering or the physics of the particles. Improved rendering will allow for more convincing simulation of phenomena such as smoke, fire, and sparks. Improved physics will allow simulation of rope and cloth, or even flocks of birds or schools of fish.
We provide you with an OpenGL skeleton program that uses GLUT and GLUI. GLUI is a simple library that provides interface controls such as check boxes and sliders for your program. Your program will read .ray files, so that you have a source for your scene geometry. The skeleton code shares the .ray file reading and writing code with assignment 2, although we will extend the .ray format with several new classes to handle particle generation and management. Be sure to read the .ray particle extensions specification, along with the .ray file format specification and the assignment 2 code explanation if you need help. We provide you with a few scenes that may be useful in debugging your program. This assignment is fairly open-ended, however, so you should be prepared to create your own .ray files to better show off your new features.
NOTE: This is the first year that this assignment has been used. As a result, there may very well be bugs or unclear or unnecessarily difficult areas. If you run into problems that you don't think you should have, please email cos426@cs.princeton.edu.
You should use the code available here (4.tar.gz, 4.zip), as a starting point for your assignment. Most of the source files should be familiar from assignment 2. In addition, we provide you with a copy of GLUI, which is a user interface toolkit based on GLUT. We have included binaries for both Windows and Linux. Hopefully, these will be all that you need. If you find you need to build GLUI yourself, you can find the source at the GLUI sourceforge page. The Microsoft Visual Studio files included in the zip file are for .NET 2005. There are also project files and a GLUI binary for .NET 2003, if you use that instead (4_vc7.zip).
The program takes in one argument, the name of the .ray file to read:% particle in.rayFeel free to add new arguments to deal with the new features you are implementing. Just make sure they are documented.
Hit p to pause the simulation and p again to unpause.
The following is a list of features that you may implement. We strongly advise that you implement the features roughly in the order they are described, and test your code after you implement each feature.
The assignment is worth 20 points. The number in parentheses corresponds to how many points a feature is worth. Options in bold are mandatory.
- (1) Drawing particles. Implement the Particle::draw function to draw particles as GL_POINTS.
- (1) Particle forces. Modify the Particle::update function to move the particle according to its velocity and the global gravity and drag forces. Use the simple forward Euler integration technique. At this point, you should be able to see some falling particles in simple_test.ray
- (1) Particle nozzles. Modify the ParticleNozzle class to create a stream of Particle objects and add them to the scene. Be sure to respect the nozzle's parameters for initial velocity and rate of generation.
- (1) Particle lifetimes. Modify the Particle::update and ParticleNozzle::update function to remove the particle when its lifetime expires.
- (4) Sphere and triangle collision and response. Modify the sphere and triangle intersection code (or use your assignment 2 code) to handle ray intersections. Modify the Particle::update function so that the particles bounce off of the shapes in the reflection direction. Be careful not to add energy or visually pop the particles from one position to the next when you perform the collision response. The particles should never pass through a solid shape. You can test your collision detection and response with fountain_1.ray and fountain_2.ray.
- (1) Box distribution. Modify the ParticleBox class to generate particles inside of a box. You should pick a random point inside the box uniformly to generate each particle. After implementing the box distribution, you should be able to run waterfall.ray.
- (1) Particle attractors. Implement the ParticleSink class to pull or push particles towards or away from a point. You should then be able to run sinkhole.ray.
- (2) Interactive control. Modify the example GLUI controls to control at least five aspects of your particle simulation. Examples include modifying the gravity and drag forces, modifying the initial velocity of the particles, and modifying the lifetime of the particles. Try to implement your controls in a flexible way, so that they cannot be easily broken by a complex or non-standard .ray file.
Numerical Integration:
- (1) Midpoint integration. Improve the accuracy of your simulation by implementing the midpoint integration scheme (second-order Runge Kutta).
- (1) Adaptive step sizes. Implement the adaptive step size technique to further improve accuracy. You should be able to implement a simple form of this technique without changing the global time step.
Rendering:
- (1) Trails. Modify you particle rendering so that each particle leaves a trail behind it as it moves. You could use GL_POINTS or a GL_LINE_STRIP to achieve this effect. Try fading out the color towards the end of the trail.
- (1) Glow. Change the GL_BLEND function so that overlapping particles add their color in the framebuffer instead of overwriting each other. This can give the effect of glowing particles.
- (2) Textures. Draw each particle as a textured quad or triangle, instead of a point. Draw each quad so that it always faces the camera, no matter how the camera is rotated.
- (1) Animated textures. Load multiple textures and cycle through them over the lifetime of the particle. With some tuning, you should be able to get a reasonable approximation of fire using this technique.
- (1) Particles that generate particles. Add a new type of particle nozzle that generates particle nozzles. Use this class to create fireworks type effects where certain particles spawn other particles.
- (2) Geometry: Draw each particle as a piece of geometry, such as a cone, box, or triangulated mesh. Rotate the geometry so that the particle always "faces" the direction it is travelling.
- (2) Animated Geometry: Make a simple shape with a few parts and animate it over time. For example, a butterfly made from two flapping polygons.
- (4) Sophisticated animation: Implement a skeletal system and Catmull-Rom spline interpolation. Use your system to create a school of fish or a flock of birds.
Interactive Control:
- (1) Nozzle selection. Allow the user to click with the mouse to select a nozzle or box. When the user selects a particle generator, the interface elements should change to adjust the parameters of that generator.
- (1) Dragging. Allow the user to move particle generators by selecting them and dragging with the mouse.
- (1) Rope or cloth manipulation. If implementing rope or cloth, allow the user to pick a point on the rope or cloth and drag it around.
Particle Interaction:
- (3) Flocking. Implement a system similar to Boids. You may wish to create a new class, e.g. FlockMember, with static members to keep track of the other members of the flock. Make sure that your boids try to avoid geometry in the scene; you can accomplish this by allowing them to look a bit ahead of themselves by shooting a ray. Combined with drawing particles as animated geometry, you can make a reasonably convincing simulation of a flock of birds or a school of fish.
- (4) Rope (HARD). Create a Rope class and add it as a new shape primitive to the .ray file format. A rope is a string of particles connected by springs. Fix the first particle in space, and determine the position of the remaining particles by their spring connections. Use explicit Euler integration as a first step, but your rope will be very unstable until you implement a more advanced integration scheme.
- (4) Cloth (HARDER). Create a Cloth class. Coth can be simulated similarly to rope, except in two dimensions. Create a 2D square of particles, and connect them using springs. You will likely need one of the more advanced integration schemes to make cloth work. Ignore self-intersection of the cloth.
By implementing all the required features, you get 12 points. There are many ways to get more points:
- implementing the optional features listed above,
- (1) submitting images for the art contest,
- (1) submitting a movie of your particle system in action, and
- (2) winning the art contest.
It is possible to get more than 20 points. However, as in the previous assignment, after 20 points, each point is divided by 2, and after 22 points, each point is divided by 4.
The following functions have not been completely implemented:
- Sphere::intersect(Ray ray, IntersectionInfo& iInfo) (in sphere.[cpp/h])
- Sphere::getBoundingBox(void)(in sphere.[cpp/h])
- Triangle::intersect(Ray ray, IntersectionInfo& iInfo) (in triangle.[cpp/h])
- Triangle::getBoundingBox(void) (in triangle.[cpp/h])
- Group::intersect(Ray ray, IntersectionInfo& iInfo) (in group.[cpp/h])
- Group::getForce(Point3D position, Point3D& forceVec) (in group.[cpp/h])
- Group::getBoundingBox(void) (in group.[cpp/h])
- Particle::draw(void) (in particle.[cpp/h])
- Particle::update(void) (in particle.[cpp/h])
- ParticleNozzle::draw(void) (in particleNozzle.[cpp/h])
- ParticleNozzle::update(void) (in particleNozzle.[cpp/h])
- ParticleBox::draw(void) (in particleBox.[cpp/h])
- ParticleBox::update(void) (in particleBox.[cpp/h])
- ParticleSink::draw(void) (in particleSink.[cpp/h])
- ParticleSink::getForce(Point3D position, Point3D& forceVec) (in particleSink.[cpp/h])
You should submit:
- the complete source code with a Makefile,
- any *.ray files you created (optional),
- the movie for the movie feature (optional),
- the images for the art contest (optional), and
- a writeup.
The writeup should be a HTML document called assignment4.html which may include other documents or pictures. It should be brief, describing what you have implemented, what works and what doesn't, how you created the art contest images and/or movies, and any relevant instructions on how to run your interface.
Make sure the source code compiles on the machines in Friend 017. Always remember the late policy and the collaboration policy.
- The code base for this assignment is very similar to the code for assignment 2. There are a couple significant changes, however.
- The static function Scene::getTopScene() returns the first scene created by the program. You can use this function to call the appropriate Shape::intersect() function from your Particle class.
- The Shape::getForce() function is designed to compute and return a force vector at a certain point in space. The result should at the least be the sum of the forces from all the ParticleSinks in the area.
- It is best if you keep track of the particles generated by a ParticleNozzle or a ParticleBox in the particle generator class itself, rather than adding them to the top level scene graph.
- Where can I get ideas for other features to implement?
David McAllister's Particle Systems API has many features and may be a good resource.
- What the heck is GLUI and how do I use it?
GLUI is a library that manages user interface widgets inside a GLUT program. It is very simple to use once you have a bit of boilerplate in place. Hopefully the couple of example widgets in main.cpp will be enough to get you started. Check out the glui_manual.pdf (included in the skeleton code) for more details. In particular, the GLUI arcball widget may be useful for setting nozzle directions.