
This implements several methods for non-photorealistic rendering. The first way is a simple tone based shading scheme, which makes a model appear warmer closer to a light, and colder away from the light. The next ways are a combination of silhouette contour rendering with either gaussian suggestive contours, or full suggestive contours. Gaussian suggestive contours use simple gaussian curvature normal to compute suggestive contours. The full suggestive contour method computes the full curvature tensor, from which the principle curvatures are extracted, and used to compute true suggestive contours. Constraints are placed on viewing angles to try to minimize artifacts.
Code may be found here: hw6.tar.gz
If you have used Peters interface before, this interface should be immediately apparent. Menu items are all self-explanatory, and still run as ./frames with a mesh.obj passed in on stdin.
The code is really built on top of Peter's original mesh code. Most of the contour drawing that was added is done in Draw.cpp, and most of curvature tensor computation is in MGeom.cpp. Several things were added to Quaternion/Matrix3x3/Vertex/a few others to help out. I.e., eigenvector decomposition is done in quatmat.cpp (really nifty code found online, uses quaternions to find eigenvectors for 3x3 symmetric matrix).
For all tests shown, Theta_c is chosen to be Pi/4. This is the angle used to prevent 'barely contours' appearing.
The visualizations shown below are the tone shading, the gaussian shading with silhouette contours, the full suggestive shading with silhouette contours, and a visualization which shows the color of the mesh to be the gaussian curvature at each vertex, and small lines of direction and magnitude of k1 and k2 at each vertex. From the visualization, you can see how the curvature is actually evolving on the surface.
All rendering/algorithms done on CPU, nothing moved to GPU. This is a thus a bit slower than it could be, but everything is realtime at least.
![]() |
![]() |
![]() |
![]() |
| |
|
|
|
![]() |
![]() |
![]() |
![]() |
| |
|
|
|
![]() |
![]() |
![]() |
![]() |
| |
|
|
|
![]() |
![]() |
![]() |
![]() |
| |
|
|
|
![]() |
![]() |
![]() |
![]() |
| |
|
|
|
I decided to make a short attempt at mean curvature flow. The results seem somewhat valid, but are very slow for large meshes. Instead of using the cotan formula, I use the actual k1, k2 from the curvature tensor to get the mean curvature H = (k1+k2)/2. I then do an explicit step in the negative H*Normal direction. This is slow because the curvature tensor has to be recalculated at every step, and unless cdt is very small, the explicit step blows up. In any case, here are some results.
To do mean curvature flow in the code, press 'f', and it will take a few steps.
Notice in the third image, the torus has shrunk. This is from several mean curvature flow steps.
![]() |
![]() |
![]() |
![]() |
| |
|
|
|
Similarly in the third image, the curvature has clearly decreased.
![]() |
![]() |
![]() |
![]() |
| |
|
|
|