CS 294 Project 1Steve MartinU.C. Berkeley, Fall 2003
For this project, I implemented a small OpenGL program in Windows that does the following basic tasks:
In addition, it can also do the following more interesting things, all of which are explained in detail in later sections:
This document will present my results in three sections. First I will demonstrate basic functionality as specified in the assignment file. Next, I will show and explain the extra features implemented in my program, along with what I learned from each. I will then close with a few comments about the assignment in general, followed by references.
Required Features Immediately upon execution, the program reads in a file containing a set of points describing Bezier patches. These patches make up a surface to display, created using uniform subdivision at a resolution determined at compile time. The surface can be displayed in points-only, wire-frame, or fully shaded mode via keyboard commands. The below images show the mesh resulting from "teapot.bez", with lighting provided by two infinite lights.
Keyboard switches allow changing of the vertex color scheme to show different curvature values at each point. These curvatures were calculated using methods discussed in class. The following figures show color maps for maximum curvature, minimum curvature, Gaussian curvature, and mean curvature. The map from colors to rough curvature values is displayed to the left of each row, with values ranging from large negative numbers through zero to large positive numbers.
In addition to coloring vertices according to various types of curvature, line textures showing the normal, tangent direction, or principle curvature directions at each point on the surface can be applied via keyboard commands. The following figures show the normal direction, u and v tangent directions, and principle curvature directions at each point.
Additional Features Outline Generation Two dimensional outlines of the surface can be rendered and applied using two different methods. The first algorithm uses vectors describing the camera view and the surface normals. The first step of my algorithm calculates a vector between the camera and the object is calculated and normalizes it. This vector is then dotted with the normal at each point in the mesh, which was pre-computed and stored at startup. When the dot product of the normal of a vertex and the camera vector is within a small margin of error of 0 (the error margin is necessary because even with fine meshes the results will have major holes otherwise), the vertex is added into a linked list of similar vertices. A linked list is used because it will make sorting quicker later, as points on the outline of the surface will likely not be in order. Next, the linked list of vertices is 'distance' sorted, meaning that each vertex is moved next to the vertex closest to it, via the distance function, within the list. This is an easy way to order the vertices for drawing lines, but it is obvious that it will only work reliably at high resolutions. Finally, the vertices are connected with lines and the outline appears. Figures 15 and 16 give an example of this technique in action.
Note that even with a fine mesh, this method does not give extremely good results. In addition, it was difficult to 'tune' the margin of error such that all points on the outline were chosen correctly without extra vertices being added. As an example, the edge along the spout of the teapot in figure 16 shows what happens to the outline when there is no point close enough on the edge of the viewable surface to be picked up as part of the outline. The spout curves more quickly than the edge of the teapot, making resolution more important there. Finally, because of the extra sorting done to make up for the default vertex ordering, the algorithm doesn't give very good frame rates. The other method implemented to trace the outline of an object made use of OpenGL's stencil buffers. The algorithm is simple. First, the surface mesh is rendered into the stencil buffer. Next, the mesh is rendered again to the screen, only this time in thick wire-frame. OpenGL then compares each rendered wire-frame pixel with what is in the stencil buffer, and replaces it with the contents of the stencil buffer where applicable. The result is a thick outline around the object which is much cleaner and cheaper than the first outline method. The idea for this came from reading various OpenGL help pages, along with [1]--although this paper doesn't quite use the same technique described here. Figures 17 and 18 give some examples of this method in action.
Sketch Rendering The other extra feature implemented in my program is an option to render the surface using a sketch-like rendering effect. The idea for this came from [2] along with lecture materials, and there are also some great examples in books in the engineering library. The algorithm I created to do this kind of rendering works as follows:
Figures 19-23 present comparisons of normal shading verses renders by the sketch algorithm for the teapot surface.
Because most of the complex values, such as curvature, are pre-calculated and stored on load, 'sketch rendering' ends up being quick even on high-resolution meshes. Also, its highly customizable; tweaking the parameters can give some very interesting effects.
Conclusion I really enjoyed this project. It was fun to create all of this from scratch, learn the math, and then implement interesting extensions to what was presented in class. The part that took me the longest was trying to figure out what all the different types of curvature actually 'meant,' as this was the first time I had seen these terms. My only regret is that I couldn't spend more time tweaking my methods and adding more features. I look forward to getting started on my semester project soon.
References [1] J. Rossignac and M. van Emmerik. Hidden Contours on a Framebuffer. In Proceedings of the 7th Workshop on Computer Graphics Hardware, Eurographics, September 1992. [2] Winkenbach, G. and Salesin, D. H. Rendering Parametric Surfaces in Pen and Ink. Computer Graphics Proceedings, SIGGRAPH 1996. (also various OpenGL web pages) |
||||||||||||||||||||||||||||||||||||||||||||||||||||