In this assignment, you will implement a basic particle system. The program will read in a scene file with particle commands and then draw particles as they move over time in an interactive viewer. 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 scene 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.
You should use the following skeleton code (COS426_assignment4.zip) as a starting point for your assignment. We provide you with several files, but you should mainly change
particleview.cpp: interactive scene viewing program (similar to rayview.cpp).
particle.[h/cpp]: core file for simulating and drawing particles.
R3Scene.[h/cpp]: code to support reading and representing scenes (augmented to handle particles).
R2: code to support operations on 2D points, vectors, lines, segments, and images
R3: code to support operations on 3D points, vectors, lines, segments, planes, and meshes.
jpeg: code to read/write JPEG files
particleview.[vcproj/sln]: Project file for Visual Studio .NET 2005 on Windows.
Makefile: Make file for Linux.
After you copy the provided files to your diectory, the first thing to do is compile the program. If you are developing on a Windows machine and have Visual Studio .NET 2005 installed, use the provided project files to build the program. If you are developing on a UNIX/Linux machine, type
makein the assignment4 directory. In either case, one executable will be created:
The skeleton code is able to read scene files (like in assignment 3) augmented to support particle systems. Specifically, the scene file format now supports three new commands: particle, particle_source, and particle_sink. We provide the sample scenes from the last assignment; you can add particles to these. We also provide some scenes including particles in the
scenesdirectory of the zip file.
particleviewis executed, it reads a scene file and spawns a window.In the provided version of the program, the scene is drawn (with particles shown as white points), but the particles are not animated. Your job is to update the code to generate, update, and render particles at each time step of the simulation (in
% particleview in.scn
particleviewallows the camera to be moved interactively with the mouse -- i.e., dragging with the left, middle, and right mouse buttons down rotates, scales, and translates the scene, respectively. Also, hitting the 'P', 'F', and 'E' keys toggle drawing particles, faces, and edges of the scene, respectively, and hitting the 'S' key saves an image of the window to a file. Of course, you are welcome to create your own program arguments, scene commands, and interactive commands - please provide documentation of them with your writeup.
The particle system should be implemented in
particle.cpp. For every refresh of the window in
DrawParticlesfunction is called. It reads the current time (in seconds since the start of the program) and calls three functions:
UpdateParticlesshould update the position (and possibly other parameters) of every particle at the current time.
GenerateParticlesshould create new particles for every particle source.
RenderParticlesshould use OpenGL commands to draw every particle on the screen. Shells are provided for these three functions, but you must fill in the details.
The assignment is worth 20 points. The following is a list of features that you may implement (listed roughly from easiest to hardest within each group). The number in front of the feature corresponds to how many points the feature is worth. The features in bold face are required. The other ones are optional.
You should include a screenshot for each implemented feature; features without screenshots will not be graded.
- Particle sources:
- (1) Point sources. Modify the GenerateParticles function to create particles for every source at every time step and add them to the scene. To get credit for this option, you must respect the source parameters for rate of generation and center position.
- (1) Nozzle sources. Augment the previous option to support source parameters for particle source direction, angle cutoff, and speed.
- (1) Solid sources. Augment the previous options to support generating particles in the interior of a shape specified as the second parameter of the particle_source command in the scene file. The shape should be translated so that its origin is at the position of the source. For each particle, you should pick a random point in the shape's interior volume (with the positions distributed uniformly). To get one point for this option, you must support at least boxes, spheres, cylinders, and cones. You can also get three additional points for supporting arbitrary meshes.
- (1) Surface sources. Augment the previous options to support generating particles on the surface of a shape specified as the second parameter of the particle_source command in the scene file. For each particle, you should pick a random point on the shape's surface (with the positions distributed uniformly with respect to surface area). To get one point for this option, you must support at least boxes and spheres. You can also get one additional point for each of cylinders, cones, and meshes, but for a maximum of 3 points total. Remember that points must be distributed uniformly with respect to surface area on the shape to get credit.
- (2) Particles that generate particles. Augment the scene description to include a new type of particle that provides a source for other particles. Use your implementation to create a fireworks simulation.
- Particle simulation:
- (1) Particle lifetimes. Remove particles when their lifetimes expire.
- (1) Global forces. Modify the UpdateParticles function to update the center position of every particle according to its velocity, its gravitational force, and a drag force determined by its drag coefficient using the simple forward Euler integration technique.
- (1) Midpoint integration. Improve the accuracy of your simulation by implementing the midpoint integration scheme (second-order Runge Kutta).
- (2) Adaptive step sizes. Further improve the accuracy of your simulation by implementing the adaptive step size technique. You should be able to implement this technique without changing the global time step by taking multiple substeps for every particle during each time step.
- Particle sinks:
- (1) Particle death. Remove particles that arrive at a sink (within some small distance).
- (1) Point sinks. Modify the UpdateParticles function to apply a force that attracts all particles towards the positions of the particle sinks. The magnitude of the force applied to each particle should be force*1.0/ (ca + la*d + qa*d*d), where force indicated in the scene file (note that it can be negative), d is the distance from a particle to the sink position, and ca, la, and qa specify the attenuation of the force with distance.
- (1) Surface sinks. Augment your code to handle sinks of arbitrary shapes (specified in the second parameter of the source_sink command). The shape should be translated so that its origin is at the position of the source, and then the attenuation with distance should be computed based on the distance between each particle and the closest point on the shape's surface. To get one point, you must handle at least boxes and spheres. You can also get one additional point for each of cylinders, cones, and meshes, but for a maximum of 3 points total.
- Collision detection:
- (2) Particle-scene collisions. Handle particle-surface collisions for obstacles specified in a scene file. For each particle, in each time step, you should use ray-surface interesection to determine whether the particle traveling along its current trajectory will collide with the static scene, and if so where and when. When particles collide with a surface, they should bounce off in the specular reflection direction with a velocity scaled by the specular reflection coefficient of the collision point in the scene. To get full credit, you must ensure that the particles never pass through a solid shape.
- (2) Particle-particle collisions. For each particle, in each time step, you should determine whether a collision will occur with other particles (within some distance tolerance), and if so where and when. When particles collide, they should bounce off each other according to Newton's Second Law, taking into account momentums.
- Particle interaction:
- (2) Particle attraction and repulsion. Augment your simulation to allow particles to apply simple attraction or repulsion forces to one another. The direction of the force should be along the vector between the particles, and the magnitude should diminish with the inverse squared distance.
- (2) Rope. Create 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. Your simulation should be stable, which requires implementing adaptive time steps.
- (3) Cloth. Create a cloth surface in a manner similar to the rope, except in two dimensions. Create a 2D square of particles, and connect them using springs. Your simulation should be stable, which requires implementing adaptive time steps.
- (3) Flocking. Implement a system similar to Boids. 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 rendering particles as animated geometry, you can make a reasonably convincing simulation of a flock of birds or a school of fish.
- Scene animation:
- (1) Animated camera. Augment
particleview.cppto move the camera automatically along a path specified with a Hermite, B-Spline, or Bezier curve.
- (1) Animated obstacles: Make a scene with a hierarchy of transformations (using begin and end commands) and then animate the scene by changing transformations as a function of time. You can use this feature to create simple rotating parts like a spinning wheel, flapping wing, ceiling fan, etc. You get an additional point if particles collide correctly with the animated scene elements.
- Particle rendering:
- (1) Materials. Modify the RenderParticles function to use OpenGL to render every particle with the material specified by m_id in the scene file.
- (1) Textures. Replace the code in RenderParticles to render a small square polygon centered at every particle position oriented towards the viewer and apply a texture (included as the last field of the material) when rendering the polygon. You should be able to use this feature to generate interesting visual effects like snow flakes and smoke (with partially transparent textures).
- (1) Shapes. Support rendering of every particle with the geometric shape specified as its last parameter in the scene file. The shape should be centered at the particle position and oriented according to the velocity vector of the particle (the last degree of rotational freedom - roll - can be set based on the "up" direction, but you get an additional point if you set it based on the curvature of the particle path).
- (1) Glow. Use the glEnable(GL_BLEND) and glBlend function so that overlapping particles add their colors in the framebuffer instead of overwriting each other. This can give the effect of glowing particles.
- (1) Trails. Modify you particle rendering so that each particle leaves a trail behind it as it moves. You will have to remember previous positions for each particle and use GL_POINTS or GL_LINE_STRIP to achieve this effect. Try storing only the last K positions and fading out the color towards the end of the trail.
- (1) Dynamic materials. Scale the material properties of every particle based on its velocity and/or lifetime.
- (2) Animated materials. Augment the scene description and parser to associate multiple materials with every particle and then cycle through them at regular time slices over the lifetime of the particle. Combining this feature with textures, you should be able to get a reasonable approximation of fire.
- (2) Responsive materials. Change the material properties of every particle based on its proximity to static shapes in the scene.
- Interactive control:
- (1) Source control. Allow the user to click with the mouse to select a particle source. Then, when a particle source is selected and the simulation is running, keyboard commands should allow the user to increase/decrease the rate of generated particles ("R" increases by 10% and "r" decreases by 10%). Also support keyboard commands to increase/decrease the speed ("V" increases by 10% and "v" decreases by 10%), mass ("M" increases by 10% and "m" decreases by 10%), drag ("D" increases by 10% and "d" decreases by 10%), elasticity ("B" increases by 10% and "b" decreases by 10%), and lifetime ("L" increases by 10% and "l" decreases by 10%) of particles generated by the selected source.
- (1) Sink control. Allow the user to click with the mouse to select a particle sink. Then, when a particle sink is selected and the simulation is running, keyboard commands should allow the user to increase/decrease the force associated with the sink ("I" increases by 10% and "i" decreases by 10%).
- (2) Source and sink dragging. Allow the user to move particle sources and sinks by selecting them and dragging with the mouse.
- (2) 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.
- (3) Graphical user interface. Use any GUI toolkit (e.g., glui) to implement sliders to control parameters of sources and sinks as the simulation runs. When the user selects a particle source and/or sink, the interface elements should change to provide sliders to adjust the parameters of that source or sink. (note: this option is recommended)
By implementing all the required features, you get 10 points. There are many ways to get more points:
You should provide a working program with scripts to run it, along with short movies to demonstrate that your program works. For each movie that you submit, you also have to submit the sequence of commands used to created it, otherwise it will not be considered valid.
- implementing the optional features listed above;
- (1) submitting one or more movies for the art contest,
- (2) winning the art contest.
It is possible to get more than 20 points. However, after 20 points, each point is divided by 2, and after 22 points, each point is divided by 4. If your raw score is 19, your final score will be 19. If the raw score is 23, you'll get 21.25. For a raw score of 26, you'll get 22.
Extra credit points cannot replace the required features (bold items). Your final score will be calculated by adding 10 to the number of extra credit points you achieve, applying the above formula for diminishing returns, and then subtracting the number of required points that you missed.
You must submit one archive (zip or tar file). It needs to have the following directory structure inside the zip:
- [your username]/ (i.e. cdecoro/)
- the complete source code, along with an updated Visual Studio project file (if you added any source files);
- the movies for the art contest (optional)
- assignment4.html, containing the writeup (see below)
- all images and movies linked from assignment4.html.
- runparticle.[bat|sh], a test script that will run in this directory, and take all its inputs from this directory.
- all input files for the test script
The writeup should be a HTML document called assignment4.html. You will use the writeup to demonstrate the effects of the features you have implemented. List each implemented feature in the format given above, and for each feature, include a screenshot that demonstrates it. The caption must indicate the regions of interest. If it is reasonable to demonstrate multiple features with a single picture, or movie, you may do so.
Features that improve simuluation quality (e.g., midpoint integration and adaptive time steps) will require a comparison of two or more movies. Features that improve speed do not require a picture, but should include a brief comparison of performance on a scene with and without acceleration.
The included script must run the program with parameters and scenes that could generate all movies linked from the writeup. It must run entirely in the script/ directory. Please make sure that you include all input files.
NOTE: Please compress your art contest and writeup movies before submitting them (to save space).
Should you choose to create a video, there are many options for video encoders available, however we have found that FFMPEG works well and runs on both Windows and linux. MEncoder is another option.
Always remember the late policy and the collaboration policy.
A few hints:
- Do the simplest steps first and test/debug every step before going to the next one.
- There are functions to manipulate 3D geometric primitives in
- Send mail to the cos426 staff.
- The code should compile and link as-is (make sure to try it out before adding your own code!). If you have problems linking to libjpeg, you can simply remove the -DUSE_JPEG flag from the makefile (or #undef USE_JPEG in your code) to disable JPEG support.
- If you should happen stumble upon anything that you suspect is a bug in the framework code (we're not perfect either!) please mail the preceptor as soon as possible so that it can be corrected.
- If you are stuck/confused/lost/having a problem, meet with the preceptor. He is readily available most days of the week.
mencoder mf://*.jpg -mf w=640:h=480:fps=25:type=jpg -ovc lavc -lavcopts vcodec=mpeg4 -nosound -o movie.avi(You may wish to use the RAW data reader options for mencoder or ffmpeg, so you can use the unmodified output of glReadPixels()). On Windows, the VirtualDub program also allows encoding of movies. If you know of any other simple methods for making videos, please send email to the class list.