The goal of this assignment is to try your hand at various mesh processing tasks. A half-edge mesh adjacency data structure is provided, along with a very simple .obj mesh parser. As you modify the triangle mesh, it is critical that the manifold properties of the input surface are maintained, and that the adjacency data structure remains consistent. Throughout this assignment you are asked to consider the efficiency of various mesh operations (is something quadratic, linear, constant, etc.). Since this assignment is rather long, it's ok if you don't always implement the most efficient strategy (which may require additional data structures), but please discuss the tradeoffs in your README.txt file.
This assignment is probably way too long. Start early, and just get the basics working first. Spend a reasonable amount of time coding and write about what you've learned in your README.txt file.
adjacency -input cube.obj -size 300 adjacency -input cube.obj -size 300 -wireframe adjacency -input open_box.obj -size 300 adjacency -input open_box.obj -size 300 -wireframe
Notice that the adjacency data structure detects boundaries in the mesh and draws them with thicker red lines in the wireframe visualization:
adjacency -input bunny_1k.obj -size 500 adjacency -input bunny_1k.obj -size 500 -gouraud
Describe in your README.txt file any helper functions you created to implement this shading. Comment on the efficiency of your implementation.
adjacency -input open_box.obj -size 300 -wirefame
Once you have the correct topology and vertex sharing, you can adjust vertex positions according to the Loop Subdivision rules. To handle general shapes you must implement the rules for regular vertices (valence = 6, i.e., 6 edges meeting at a vertex), extraordinary vertices (valence != 6), and boundary conditions. For reference, check out the "Subdivision Zoo" from the SIGGRAPH 99 course notes - Subdivision for Modeling and Animation.
Finish off your subdivision surface code by implementing the simple binary (infinitely sharp or infinitely smooth) crease method described in: "Surface reconstruction from unorganized points" H. Hoppe, T. DeRose, T. Duchamp, J. McDonald, W. Stuetzle. ACM SIGGRAPH 1992, 71-78.
adjacency -input creased_cube.obj -size 300 -wirefame
First implement the topology of an edge collapse. Identify a target edge to collapse. For now you may want to use the function Bag::ChooseRandom() to pick a random edge in the mesh. Using the adjacency data structure, identify which two triangles will be removed permanently from the model, and which other triangles will change. For now, choose a simple location for the remaining vertex (e.g., it's old position, or a position averaged with the deleted vertex). Note: in the provided adjacency data structure you will delete and then re-create triangles rather than modify them. For now you may want to just collapse one edge each time the "d" key is pressed. In your README.txt file, describe any helper functions you create.
adjacency -input bunny_1k.obj -size 500 -wireframe
Even though a single random collapse works great, you will probably quickly run into problems: the mesh looks bad with small triangles and big triangles that don't represent the high-resolution model very well, it creates self intersections of the surface (it turns itself inside out and you can see the blue side), and (worst-of-all) it crashes with an error like:
assertion "opposite == NULL" failed: file "edge.h", line XXX
Think about what that error might indicate is wrong with your implementation. (If you get a different error, of course, try to explain that one.) Certain edges should not be collapsed because it would cause the surface to become non-manifold. Write code to check for these conditions. NOTE: This code can be very complicated. It's ok if you only just catch some of these conditions and your program still crashes. Don't spend too long making it perfect. Discuss this in your README.txt file.
Finally, implement something to make a smarter choice for which edge to collapse (this might also minimize the occurance of lingering bugs from the previous part). Collapsing the shortest edge first (or actually make that the shortest legal edge) will usually do a very good job at preserving overall surface shape. Done naively, selecting the shortest edge for collapse can be an expensive operation. That's fine for now, you can implement something very inefficient. Discuss these performance issues in your README.txt file and what common data structures would help.
The array class is a simple dynamically resizeable array. The bag class is for unordered data. For efficient (constant time) retrieval and removal of elements, the bag class is implemented with a hash table. The "extract" function allows special lookup. See how it's used by the Mesh code to efficiently find pairings between opposite edges.
Please read the assignment information again before submitting.