Lab 05: Subdivision SurfacesGoalsBy the end of this lab, you will:
|
In this lab, you will implement the Loop subdivision scheme. All of the code you will write will be in the loopSubdivision
function in the subdivision.js
file. The implementation will be very similar to what we implemented in the exercise on Tuesday (subdividing an icosahedron to approximate a sphere). There are a few differences, however, since the Loop subdivision scheme (1) uses a different scheme to calculate the coordinates of vertices added on edges and (2) moves vertices in the original mesh using information about the surrounding vertices.
Please start by copying over what you had from the exercise on Tuesday for subdividing a sphere mesh. Place new edge vertices at the midpoints of the edge - do not normalize the coordinates like we did at the end of class since we don't want to place the edge vertices on the unit sphere in the Loop subdivision scheme.
Now we will calculate the coordinates of the newly created edge vertices using the Loop subdivision scheme. Please refer to the left-most figure at the top of this lab description. The coordinates of the blue vertex
How I suggest implementing this: There are many ways to implement this scheme, some of which involve setting up additional data structures to keep track of triangle-to-triangle, edge-to-triangle or triangle-to-edge adjacencies. We will not do that here since our meshes are always closed. We can actually calculate the coordinates of the blue vertex on the fly as we iterate through the edges of each triangle:
key
is not in edgeMap
, or !(key in edgeMap)
), initialize the coordinates to the contributions from the edge endpoint: if-else
blocks, add the contributions from the "opposite" vertex: i.e. add edgeMap[key] + nVertices
, assuming you added vertices similar to what was done in the exercise earlier in the week. The first time we encounter the edge, this adds the contribution from either Before adding the contribution from the opposite vertex, you should see a pretty spiky-looking mesh at various levels of subdivision:
And after adding the contributions from the opposite vertices, it should look a bit less spiky:
Finally, this last stage involves updating the existing vertex coordinates to const oldVertices = vertices.slice()
) and use oldVertices
when calculating
Recall that this step requires the vertex-to-vertex (v2v
) information. Please see the notes for a description of how to calculate this v2v
data structure. When this works, you should see the following for the initial icosahedron mesh:
and the following for the Stanford Bunny mesh which I found here (the right-most picture has the edge visibility turned off):
For this part, we will work with the Stanford Bunny mesh ("bunny" option in the dropdown in your lab) which initially has 500 triangles (
Question 1: Assume that vertex coordinates (float) are always stored with a Float32
, i.e. 4 bytes of memory. You may also assume that the indices for triangles and edges are unsigned 32-bit integers UInt32
(also 4 bytes). Please complete the table in the questions.md
file by reporting the number of vertices, edges and triangles and the total memory consumed by the Stanford Bunny mesh at each level of subdivision (for 5 subdivisions). Note that
Question 2: Using the data you found in Question 1, notice that
The initial submission for the lab is due on Wednesday 10/25 at 11:59pm EDT. I will then provide feedback within 1 week so you can edit your submission.
When you and your partner are ready, please submit the assignment on replit
. I will then make comments (directly on your repl
) and enter your current grade status at the top of the index.html
file.
Please also remember to submit your reflection for this week in this Google Form.
© Philip Claude Caplan, 2023 (Last updated: 2023-10-19)