CS 106 Winter 2016
Assignment 03: Basic physics
Question 1 Dynadraw
Introduction
In a normal drawing program, the virtual paintbrush follows the mouse (or stylus, or finger) exactly: it tries to move perfectly in sync with the user's gestures. Imagine what would happen, though, If the paintbrush were connected to the mouse location via a spring: as the mouse moved, the spring would stretch, and the brush would rush to catch up with the mouse. It might even overshoot the mouse, and get pulled back the other way. The result would be a curve that doesn't exactly do what you tell it, but that looks very smooth and elegant.
This was the idea behind Dynadraw, a great old technique by the same Paul Haeberli who invented Impressionist in the previous assignment. The easiest way to try Dynadraw is to visit the Javascript version by Roger Allen (go try it!)
In this assignment you'll implement Dynadraw using a physical simulation (which, after all, is precisely what Dynadraw is).
Requirements
- Create a sketch of size at least 800×600, with a white background.
- Pressing any key should clear the painting area of the screen to white so that the user can begin a new drawing.
- When the user presses the mouse button in the painting area, begin a spring simulation. Set the pen location to the mouse location and the pen velocity to (0,0).
- In every frame, perform a spring simulation. The start of the spring is the current mouse position. The end of the spring is the current pen position. The pen is trying to get back to the mouse (so the spring has a rest length of zero).
- The simulation will tell you the new position for the pen. Draw a line segment from the old pen position to the new one. Don't clear the sketch window every frame!
- When the user releases the mouse button, the simulation stops and no more drawing happens until the next button press.
- The sketch must include two sliders. One controls the spring's stiffness, and the other controls the spring's damping factor. As in Assignment 02, you must use ControlP5 to manage these sliders. Put them in reasonable locations, and as in A02 draw a dark rectangle under them.
Tips
- Like many other simulations we've seen in class, Dynadraw really only depends on six numbers that change every frame: the position of the mouse (two numbers), the position of the pen (two numbers), and the velocity of the pen (two numbers). The position of the mouse is built in to Processing; you can use global variables for the other four numbers.
- You'll probably end up with a few other global variables. Two obvious ones would be the stiffness and damping values for the spring. You'll probably also need a boolean to keep track of whether you're currently painting, as in Assignment 02 (so that you don't start painting when you click on a slider).
- Choose reasonable initial values for stiffness and damping, and reasonable ranges for the sliders that control them. I use 0.05 and 0.1 as initial values. Make sure the sliders show these initial values when the sketch starts.
- The spring simulation is very similar to the DampedSpring sample sketch. The big difference is that this simulation is two dimensional. But converting from one dimension to two can be done as in the other examples discussed in class (see SecondLaw and SecondLaw2D, for example). Another difference is that this spring has a rest length of zero: it wants to return to having no length at all. Finally, remember that the displacement of the Dynadraw spring depends on the current mouse location.
- The ControlP5 aspects of this assignment are nothing new, they're just the usual sliders used in Lab 02 and Assignment 02. If you had trouble implementing them previously, be sure to refer to the sample solutions.
- If you feel completely lost, remember that there are a lot of parts of this sketch that you already know how to write. You'll certainly need setup() and draw() functions. You learned how to set up sliders in Lab 02 and Assignment 02. You'll need mousePressed() and mouseReleased() hooks, as well as keyPressed(). You have a pretty good idea of what global variables you need. You know how to clear the sketch window when the user presses a key. Even if you just throw empty functions into a sketch to start, you'll already have most of the structure you need in place.
Enhancements
- One way to add a lot of visual appeal to Dynadraw's curves is to use the paintbrush's speed to control the width of the painted stroke. Define a maximum brush width for when the brush isn't moving. As the brush moves faster, draw a progressively thinner stroke, down to some predefined minimum for any speeds beyond a threshold. I'll award a small bonus to implementations that control the brush width in a nice way.
- If you write the sketch as above, you discover a problem in the output. When the stroke curves around too tightly, it looks "polygonal"—that is, it looks like it's made from a sequence of short lines, instead of a smooth curve. For another bonus, figure out an effective way to make the curve really look smooth, or at least a lot smoother. There's no one way to do this, and it's even harder if you vary the line thickness too.
- If you want to get really fancy, add the ability to undo the user's most recent stroke. The easiest way to do that is probably to keep a snapshot of the sketch window before the start of each stroke; then you can just revert to that snapshot when the user wants to undo a stroke.
Submission
Remember to review the Code Style Guide and use Processing's built-in auto format tool. Then review the How To Submit document. At the top of all of your source files, be sure to include a comment with your name and student ID number. When you're ready, zip up the Dynadraw sketch (which could, but need not, live in an A03/ folder, and upload that file to LEARN.