This software considers bending forces, twisting forces, and an optional gravity force
to model discrete elastic rod visualized in OpenGL.
To implement the constraint that edge lengths remain constant, a stretching force is also
implemented. Besides the added forces, the lab improves on last week's in several ways. First,
the rotation gesture was made a bit more intuitive. Second, I replaced the force implementing
the stretching constraint to weight smaller edge's forces higher because I wanted to punish
small edges that became a certain amount larger more than large edges that became the
same amount larger. Third and most imortantly, I replaced the Euler integrator with a
Runge-Kutta integrator that converges faster and allows me to use a smaller timestep while
This lab uses GLUT, which means the user interface is not nearly as intuitive or powerful
as the Cocoa apps.
Click and drag the left mouse button to rotate around the origin. Click and drag the right mouse
button to translate the object. Clicking and dragging the right mouse button while holding down
shift translates on a different axis. These controls are still rather unintuitive, but are
slightly better than last week.
Press 'c' to toggle recording to ppm files named frame#.ppm in the working directory.
Press 'r' to reset the vertices to their input-file-specified locations.
Press 'f' to toggle display of the bending, stretching, and twisting force vectors.
Press 'g' to toggle gravity forces on the vertices.
Press 'v' to toggle showing vertices.
Press 'q' to get out when you become bored.
The input files consist of a gravity vector (x, y, z), a twisting amount (theta_n - theta_0),
and then list of quadruplets, one per line, that describe each vertex:
x, y, z, followed by a boolean value indicating whether the vertex is fixed or not (1 means fixed,
0 means unfixed). Here is an example input using just basic bending forces (no twisting), and the
resulting output movie:
1 0 0
0 2 0 0
0.000000 1.755165 0.958851 0
0.000000 1.080605 1.682942 0
0.000000 0.141474 1.994990 0
0.000000 -0.832294 1.818595 0
0.000000 -1.602287 1.196944 0
0.000000 -1.979985 0.282240 0
0.000000 -1.872913 -0.701566 0
0.000000 -1.307287 -1.513605 0
0.000000 -0.421592 -1.955060 0
0.000000 0.567324 -1.917849 0
0.000000 1.417340 -1.411081 0
0.000000 1.920341 -0.558831 0
0 2 0 0
Movie of expanding cut ring
(bending and stretching forces).
The following video demonstrates the effect of gravity forces applied perpendicularly to a rod with
two fixed endpoints. As expected, the rod sags, suspended at the fixed points.
Movie of straight rod under gravity.
The following three videos demonstrate the effect of twisting forces. The first two videos mimic
the setup of Figure 9 in the paper by Bergou et. al. Of course, because I do not detect edge collisions,
I cannot achieve the exact same results. However, given the twisting behavior, it seems reasonable that
I would get something similar to Figure 9 if the edges were prevented from passing trhough each other.
The first demonstrates the effect of a relatively low twisting force, while the second demonstrates a
|Movie of weak twisting forces.
|Movie of strong twisting forces.
The third movie mimics (or attempts to mimic) the behavior in Figure 8 of Bergou et. al.
Again, the lack of collision detection prevents matching the behavior exactly, but my implementation
appears to give reasonable results. While I was recording the video I manually moved the ring around
so that it could be seen from different angles. This is the cause of the jerky motions.
Movie of elastic ring under twisting force.
I have small utilities for creating the input files used above and for proceessing the .ppm
files captured from OpenGL in capture mode.
To create the input files, run:
> make TestFiles
This will generate all the text files using generate_test_files.c.
The utilities to process the .ppm files are process_capture.sh and process_capture_nocrop.sh.
They both convert all the .ppms in the current directory into pngs that can be stitched together
by Quicktime Pro. The difference is process_capture.sh crops the frames to the region in which
most of my test files appear, while process_capture_nocrop.sh converts the frames without
For example, you can run:
in the directory holding all the frame*.ppm files to crop them and convert them all into
pngs stored in frame*.ppm.png.
This program is written in C++ using GLUT. It should compile on most Linux, Windows,
and Mac OS X machines if the proper libraries are installed.
- The source code and example files can be downloaded here.
You should be able to run the program by running:
> ./elasticRods window_width window_height timeStep lambda input_filename
Where timeStep is the step size used by the Runge-Kutta integrator, and lambda sets the
ratio of the total stretching forces to the total bending + twisting forces.
Lambda typically should just be 1.0, and the step size will be around 1e-4. In some cases,
the step size can be made larger while retaining stability, and in others it might need to
be made smaller. It all depends on the input configuration.
As usual, please be aware that this is by no means polished software; it was written for a weekly
Design and code ©2012 Julian Panetta