diff --git a/hw2/.DS_Store b/hw2/.DS_Store new file mode 100644 index 00000000..7877fe42 Binary files /dev/null and b/hw2/.DS_Store differ diff --git a/hw2/images/beziercurve_6.png b/hw2/images/beziercurve_6.png new file mode 100644 index 00000000..96396c26 Binary files /dev/null and b/hw2/images/beziercurve_6.png differ diff --git a/hw2/images/beziercurve_6_curve.png b/hw2/images/beziercurve_6_curve.png new file mode 100644 index 00000000..f69cf941 Binary files /dev/null and b/hw2/images/beziercurve_6_curve.png differ diff --git a/hw2/images/beziercurve_6_step1.png b/hw2/images/beziercurve_6_step1.png new file mode 100644 index 00000000..14b70959 Binary files /dev/null and b/hw2/images/beziercurve_6_step1.png differ diff --git a/hw2/images/beziercurve_6_step2.png b/hw2/images/beziercurve_6_step2.png new file mode 100644 index 00000000..e8c8001c Binary files /dev/null and b/hw2/images/beziercurve_6_step2.png differ diff --git a/hw2/images/beziercurve_6_step3.png b/hw2/images/beziercurve_6_step3.png new file mode 100644 index 00000000..082d41ed Binary files /dev/null and b/hw2/images/beziercurve_6_step3.png differ diff --git a/hw2/images/beziercurve_6_step4.png b/hw2/images/beziercurve_6_step4.png new file mode 100644 index 00000000..7a3512d5 Binary files /dev/null and b/hw2/images/beziercurve_6_step4.png differ diff --git a/hw2/images/beziercurve_6_step5.png b/hw2/images/beziercurve_6_step5.png new file mode 100644 index 00000000..ecc32dd4 Binary files /dev/null and b/hw2/images/beziercurve_6_step5.png differ diff --git a/hw2/images/beziercurve_6_step5_curve.png b/hw2/images/beziercurve_6_step5_curve.png new file mode 100644 index 00000000..20a25800 Binary files /dev/null and b/hw2/images/beziercurve_6_step5_curve.png differ diff --git a/hw2/images/cube1.png b/hw2/images/cube1.png new file mode 100644 index 00000000..90f6be8d Binary files /dev/null and b/hw2/images/cube1.png differ diff --git a/hw2/images/cube2.png b/hw2/images/cube2.png new file mode 100644 index 00000000..5a30e4f5 Binary files /dev/null and b/hw2/images/cube2.png differ diff --git a/hw2/images/cube3.png b/hw2/images/cube3.png new file mode 100644 index 00000000..ed9cfca7 Binary files /dev/null and b/hw2/images/cube3.png differ diff --git a/hw2/images/cube4.png b/hw2/images/cube4.png new file mode 100644 index 00000000..9b1d0bda Binary files /dev/null and b/hw2/images/cube4.png differ diff --git a/hw2/images/cube5.png b/hw2/images/cube5.png new file mode 100644 index 00000000..ce6ccad0 Binary files /dev/null and b/hw2/images/cube5.png differ diff --git a/hw2/images/part1_downscroll.png b/hw2/images/part1_downscroll.png new file mode 100644 index 00000000..df3e70ff Binary files /dev/null and b/hw2/images/part1_downscroll.png differ diff --git a/hw2/images/part1_scroll.png b/hw2/images/part1_scroll.png new file mode 100644 index 00000000..2b5d81c3 Binary files /dev/null and b/hw2/images/part1_scroll.png differ diff --git a/hw2/images/part1_upscroll.png b/hw2/images/part1_upscroll.png new file mode 100644 index 00000000..920a855c Binary files /dev/null and b/hw2/images/part1_upscroll.png differ diff --git a/hw2/images/part2_teapot.png b/hw2/images/part2_teapot.png new file mode 100644 index 00000000..cd2ef782 Binary files /dev/null and b/hw2/images/part2_teapot.png differ diff --git a/hw2/images/part3_flat.png b/hw2/images/part3_flat.png new file mode 100644 index 00000000..bd603835 Binary files /dev/null and b/hw2/images/part3_flat.png differ diff --git a/hw2/images/part3_phong.png b/hw2/images/part3_phong.png new file mode 100644 index 00000000..dfbd8d77 Binary files /dev/null and b/hw2/images/part3_phong.png differ diff --git a/hw2/images/part4_beforeFilp.png b/hw2/images/part4_beforeFilp.png new file mode 100644 index 00000000..8d55b8ee Binary files /dev/null and b/hw2/images/part4_beforeFilp.png differ diff --git a/hw2/images/part4_flipped.png b/hw2/images/part4_flipped.png new file mode 100644 index 00000000..6a724f5f Binary files /dev/null and b/hw2/images/part4_flipped.png differ diff --git a/hw2/images/part5_sf.png b/hw2/images/part5_sf.png new file mode 100644 index 00000000..4d9214e4 Binary files /dev/null and b/hw2/images/part5_sf.png differ diff --git a/hw2/images/part5_splitEdge.png b/hw2/images/part5_splitEdge.png new file mode 100644 index 00000000..1a9ecc9c Binary files /dev/null and b/hw2/images/part5_splitEdge.png differ diff --git a/hw2/images/preprocess.png b/hw2/images/preprocess.png new file mode 100644 index 00000000..171513e9 Binary files /dev/null and b/hw2/images/preprocess.png differ diff --git a/hw2/index.html b/hw2/index.html index 13b78467..99a81b0e 100644 --- a/hw2/index.html +++ b/hw2/index.html @@ -1,7 +1,482 @@ - - - - - Homework 2 index.html here - + + + + +CS 184 Mesh Edit + + + + + + + + + + + +

CS 184: Computer Graphics and Imaging, Spring 2018

+

Project 2: Mesh Edit

+

Jacqueline Perez

+ +

+ +
+ +

Overview

+

+ This assignment implements various aspects in modifying meshes. The first section deals with Bezier curves and de Casteljau Subdivision, which are used + to model smooth curves and surfaces, first in 1D then in more dimensions. The second section is on triangle meshes and halfedge data structure, where functions on + Phong shading, edge flip and split, and loop subdivision are implemented. These functions modify meshes in order for them to appear more accurate and smoother. +

+
+ + +

Section I: Bezier Curves and Surfaces

+ +

Part 1: Bezier Curves with 1D de Casteljau Subdivision

+ + + + Briefly explain de Casteljau's algorithm and how you implemented it in order to evaluate Bezier curves. + +

+ De Casteljau's algorithm is a recursive algorithm that splits line segments (in this case line segments between points of the Bezier curve) + with points and continues to do so with the new points generated from the previous recursive step until it converges to the single desired final point. + This desired final point is the point that lies on the Bezier curve at the parameter t. + + For Part 1, in BezierCurve::evaluateStep(...) I implemented a for loop which iterated through the parameter vector "points" which consists of + Vector2D elements that represent coordinate points. While iterating through each point in "points", a linear interpolation was calculated with + the current point and next point (i + 1). The resulting point was then added to a vector of intermediate points which is returned at the end + of the function, populated with all the intermediate points evaluated at the step of the de Cateljau's algorithm. + +

+
+
+ + + + Take a look at the provided .bzc files and create your own Bezier curve with 6 control points of your choosing. Use this Bezier curve for your screenshots below. + +

+ I created this Bezier curve with 6 control points. Control points (0.200, 0.850), (0.300, 0.400), (0.500, 0.550), (0.700, 0.850), (1.000, 0.900), (1.300, 0.200). +

+ +
+ +
+
+
+
+ + + Show screenshots of each step / level of the evaluation from the original control points down to the final evaluated point. Press E to step through. Toggle C to show the completed Bezier curve as well. + + +
+ + + + + +
+ + + + +
+ + + + +
+ + + +
+ +
Level 0
+
+ +
Level 1
+
+ +
Level 2
+
+ +
Level 3
+
+ +
Level 4
+
+ +
With curve
+
+ +
Bezier Curve
+
+
+
+
+
+ + + + Show a screenshot of a slightly different Bezier curve by moving the original control points around and modifying the parameter \(t\) via mouse scrolling. + +
+ + + + + +
+ + + +
+ +
Slightly different Bezier curve
+
+ +
t less than 0.5
+
+ +
t greater than 0.5
+
+
+
+ + +

Part 2: Bezier Surfaces with Separable 1D de Casteljau

+ + Briefly explain how de Casteljau algorithm extends to Bezier surfaces and how you implemented it in order to evaluate Bezier surfaces. + +

+ Bezier surfaces can also be evaluated by de Casteljau's algorithm, one must linearly interpolate first in one direction and then in the other, + in this case we do it through (u, v), and we are also working with Vector3D coordinates rather than Vector2D coordinates. In separable 1D de + Casteljau's algorithm the coordinates are first evaluated through the in u space, once all the final points are found in the u space they are + then passed in to be linearly interpolated in the v space. This then results in a surface point, thus the de Casteljau algorithm being applied + to a Bezier surface. + +

+ +

+ Implementation for BezierPatch::evaluateStep(...) is very similar to Part 1, although in this case the parameter is a Vector3D not Vector2D. It + is a for loop that goes through all the points, linearly interpolates them with their next neighboring point and returns its intermediate + points. + + For BezierPatch::evaluate1D(...), I implemented a while loop that continues to interate until a single point remains (the final point). Within + the while loop BezierPatch::evaluateStep(...) is called on the "points" parameter and its result is assigned back to "points" to be passed in + at the next step (iteration of loop) until the result converges to a single coordinate point, which is then returned. + + BezierPatch::evaluate(...) deals with the u and v spaces, for this function I interated through the 2D controlPoints vector passing in the + vector at each index into evaluate1D with u as the scalar interpolation parameter. The resulting points are added to a vector of Vector3D + points, where after the for loop terminates it is passed in to evaluate1D with the v scalar interpolation parameter. This produces the + point on the surface and is returned. +

+
+
+
+ + + Show a screenshot of bez/teapot.bez (not .dae) evaluated by your implementation. + +
+ +
Teapot result of evaluated Bezier surfaces.
+
+
+ + +

Section II: Triangle Meshes and Half-Edge Data Structure

+ +

Part 3: Area-Weighted Vertex Normals

+ + + Briefly explain how you implemented the area-weighted vertex normals. + +

+ To compute the area-weighted avergae of normals at this vertex I intereated through all the current halfedge's neighboring triangles by its halfedges and corresponding vertices. + Since the halfedges iterate in a single direction, this prevent double counting of triangles when computing the area + weighted total. In the while loop the directional vectors of the edges are computed by subtracting the two vertices of the incident + triangle from the originating vertex. The cross product of these edge length vectors is then + divided by the magnitude of the cross product and multiplied by 1/2 to get the area of the triangle. This is then multipled to the + triangle's face's normal and added to the area-weighted total Vector3D, where then outside the loop it is divided by its magitude to + normalize the result. Finally, the function returns this result which is the approximate unit normal at this vertex. + +

+
+
+
+ + + + Show screenshots of dae/teapot.dae (not .bez) comparing teapot shading with and without vertex normals. Use Q to toggle default flat shading and Phong shading. + +
+ + + + + +
+ +
Flat Shading
+
+ +
Phong Shading
+
+
+
+ + +

Part 4: Edge Flip

+ + Briefly explain how you implemented the edge flip operation and describe any interesting implementation / debugging tricks you have used. + +

+ To implement the flipEdge function I first drew the diagram provided of the two triangles with a shared edge and labeled every part of it according to the flipEdge rules. + From there I created various varibles to label the pointers of each part of the diagram and used them to when reassigning. I reassigned the vertices' and faces' + halfegdes first and then used setNeighbors to reassign the halfedges (its next, twin, vertex, edge, and face). Finally, I return the edge that was intially passed in but + updated now with its reassignments. + +

+
+
+
+ + + + Show screenshots of the teapot before and after some edge flips. + +
+ + + + + +
+ +
No edge flipping
+
+ +
Multiple edge flips
+
+
+
+
+
+ + + + Write about your eventful debugging journey, if you have experienced one. + +

+ A bug I had trouble with was only using the setNeighbors() function to update the halfedges and forgetting to assign the vertices' and faces' halfedge attribute to its + new flipped value as well, which was causing incorrect and odd flips like disapearing faces. +

+
+ + +

Part 5: Edge Split

+ + Briefly explain how you implemented the edge split operation and describe any interesting implementation / debugging tricks you have used. + +

+ Following the same process as in part 4, I drew the diagram of an edge split, labeled all new elements and relabeled elements that would need to be reassigned + and used this diagram as a guide to write the function. In the function, I first declared all the variables that would represent the pointers, then created the new faces, + edges, and vertex. For the edges that were created, I also set its "isNew" attribute to true to be later used in part 6. + Then assigned the vertices', faces', and edges' corresponding halfedges. Afterwards, I assigned all of the halfegdes' new corresponding attributes after the split + with setNeighbors(). + +

+
+
+
+ + + + Show screenshots of a mesh before and after some edge splits. + +
+ + + + + +
+
+ +
Slightly different Bezier curve
+
+ +
t less than 0.5
+
+
+
+ + + + Show screenshots of a mesh before and after a combination of both edge splits and edge flips. + +
+ + + + + +
+
+ +
Slightly different Bezier curve
+
+ +
t less than 0.5
+
+
+
+ + + + Write about your eventful debugging journey, if you have experienced one. + +

+ Intially I was adding too many new edges since I had diffculty with reassigning some of the edges that were already in the mesh and although in part 5 the + function seemed to be work correctly, these bugs presented themselves in part 6. I then figured out how to correctly reassign the edge to be split and kept all + the edges the mesh originally had and reduced the new edges I was adding down to 2 rather than 4. This fix then allowed my part 6 to work as well. +

+
+ + + +

Part 6: Loop Subdivision for Mesh Upsampling

+ + Briefly explain how you implemented the loop subdivision and describe any interesting implementation / debugging tricks you have used. + +

+ For Part 6, I closely followed the workflow provided in the doc-string of the function. First, I iterated through all the vertices with a for loop and calculated its new + position with the formula provided in the spec and for retrieving all its neighboring vertices for "original_neighbor_postion_sum" part of the formula, I had a while loop inside each iteration + of the for loop. At the end of this for loop I set all the vertices to isNew = false since they are the original vertices of the mesh and assign its newPosition to the calculated + position. I then loop through all the edges of the mesh with a while loop and calculated the positions of all the new vertices with the other formula provided and set this value to + the newPosition value of the edge. Afterwards is the loop that deals with splitting the edges. Orginally I had a for loop when dealing with edges but that lead to infinite loops + since splitting the edges kept creating more therefore the increment of the for loop kept on going since it never met the edgesEnd() condition. To fix this I then implemented it through + a while loop, in the while loop I checked if both vertices of the edge were from the original mesh and if so split the edge and set the returned vertex to isNew true and its newPosition to + the edges newPosition. I also had a bug here where I just directly set the position of the new vertex and disregarded the newPosition so fixed it by setting the newPosition. I then looped through the + + edges again to flip them here I checked the conditions where if the edge was new and if one vertex was new and the other old, if so then it'd flip the edge. Finally I iterate through all the vertices again + and set it's position to the value in its newPosition. The final bug I encountered was forgetting to set the original edges in the mesh to isNew = false so I added that in a while + loop before the splitting loop and that allowed Part 6 to function properly. +

+
+
+
+
+ + + Take some notes, as well as some screenshots, of your observations on how meshes behave after loop subdivision. What happens to sharp corners and edges? Can you reduce this effect by pre-splitting some edges? + +
+ + + + + +
+
+ +
No preprocess
+
+ +
Preprocessed
+
+
+

+ The sharp corners and edges after loop subdivision appear to become more smooth and rounded. By pre-splitting some edges before the loop subdivision does reduce this effect, the pre-split edges after loop + subdivision seem to retain a more flat shape. +

+
+
+
+ + + + Load dae/cube.dae. Perform several iterations of loop subdivision on the cube. Notice that the cube becomes slightly asymmetric after repeated subdivisions. + Can you pre-process the cube with edge flips and splits so that the cube subdivides symmetrically? Document these effects and explain why they occur. Also + explain how your pre-processing helps alleviate the effects. + +
+ + + + + +
+ + + + +
+ + + + +
+
+ +
Orignial
+
+ +
Loop subdivision 1
+
+ +
Loop subdivision 2
+
+ +
Loop subdivision 3
+
+ +
Loop subdivision 4
+
+
+
+

+ Pre-processing the cube with edge splits and flips does aid in the cube being subdivided more symmetrically since it helps it keep its flat sides. Since the original + mesh does not have many triangles to begin with when they are all split and flipped in a loop they tend to lose shape since loop subdivision creates a mesh with increased + equal sized triangles thus losing information and symmetry the original shape had. By splitting and flipping before loop subdivision it creates more triangles that then keep more + information of their original shape. For example, in the cube each side face is represented by two triangles, when in a loop you split + these triangles and then flip them so the cube losses its original corners since the single triangles + of the corner were split and flipped making them more rounded. With more triangles that are smaller and closer to the corner the rounded effect of splititng and + fliiping is on a much smaller scale thus + the overall mesh keeps more of its shape. +

+
+ + + + \ No newline at end of file