-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathindex.html
More file actions
623 lines (563 loc) · 27.9 KB
/
index.html
File metadata and controls
623 lines (563 loc) · 27.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
<!DOCTYPE html><html><head>
<title>CS184 Project 2 Meshedit Writeup</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="../css/katex.min.css">
<style>
/**
* prism.js Github theme based on GitHub's theme.
* @author Sam Clarke
*/
code[class*="language-"],
pre[class*="language-"] {
color: #333;
background: none;
font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
line-height: 1.4;
-moz-tab-size: 8;
-o-tab-size: 8;
tab-size: 8;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
/* Code blocks */
pre[class*="language-"] {
padding: .8em;
overflow: auto;
/* border: 1px solid #ddd; */
border-radius: 3px;
/* background: #fff; */
background: #f5f5f5;
}
/* Inline code */
:not(pre) > code[class*="language-"] {
padding: .1em;
border-radius: .3em;
white-space: normal;
background: #f5f5f5;
}
.token.comment,
.token.blockquote {
color: #969896;
}
.token.cdata {
color: #183691;
}
.token.doctype,
.token.punctuation,
.token.variable,
.token.macro.property {
color: #333;
}
.token.operator,
.token.important,
.token.keyword,
.token.rule,
.token.builtin {
color: #a71d5d;
}
.token.string,
.token.url,
.token.regex,
.token.attr-value {
color: #183691;
}
.token.property,
.token.number,
.token.boolean,
.token.entity,
.token.atrule,
.token.constant,
.token.symbol,
.token.command,
.token.code {
color: #0086b3;
}
.token.tag,
.token.selector,
.token.prolog {
color: #63a35c;
}
.token.function,
.token.namespace,
.token.pseudo-element,
.token.class,
.token.class-name,
.token.pseudo-class,
.token.id,
.token.url-reference .token.variable,
.token.attr-name {
color: #795da3;
}
.token.entity {
cursor: help;
}
.token.title,
.token.title .token.punctuation {
font-weight: bold;
color: #1d3e81;
}
.token.list {
color: #ed6a43;
}
.token.inserted {
background-color: #eaffea;
color: #55a532;
}
.token.deleted {
background-color: #ffecec;
color: #bd2c00;
}
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
/* JSON */
.language-json .token.property {
color: #183691;
}
.language-markup .token.tag .token.punctuation {
color: #333;
}
/* CSS */
code.language-css,
.language-css .token.function {
color: #0086b3;
}
/* YAML */
.language-yaml .token.atrule {
color: #63a35c;
}
code.language-yaml {
color: #183691;
}
/* Ruby */
.language-ruby .token.function {
color: #333;
}
/* Markdown */
.language-markdown .token.url {
color: #795da3;
}
/* Makefile */
.language-makefile .token.symbol {
color: #795da3;
}
.language-makefile .token.variable {
color: #183691;
}
.language-makefile .token.builtin {
color: #0086b3;
}
/* Bash */
.language-bash .token.keyword {
color: #0086b3;
}
/* highlight */
pre[data-line] {
position: relative;
padding: 1em 0 1em 3em;
}
pre[data-line] .line-highlight-wrapper {
position: absolute;
top: 0;
left: 0;
background-color: transparent;
display: block;
width: 100%;
}
pre[data-line] .line-highlight {
position: absolute;
left: 0;
right: 0;
padding: inherit 0;
margin-top: 1em;
background: hsla(24, 20%, 50%,.08);
background: linear-gradient(to right, hsla(24, 20%, 50%,.1) 70%, hsla(24, 20%, 50%,0));
pointer-events: none;
line-height: inherit;
white-space: pre;
}
pre[data-line] .line-highlight:before,
pre[data-line] .line-highlight[data-end]:after {
content: attr(data-start);
position: absolute;
top: .4em;
left: .6em;
min-width: 1em;
padding: 0 .5em;
background-color: hsla(24, 20%, 50%,.4);
color: hsl(24, 20%, 95%);
font: bold 65%/1.5 sans-serif;
text-align: center;
vertical-align: .3em;
border-radius: 999px;
text-shadow: none;
box-shadow: 0 1px white;
}
pre[data-line] .line-highlight[data-end]:after {
content: attr(data-end);
top: auto;
bottom: .4em;
}html body{font-family:"Helvetica Neue",Helvetica,"Segoe UI",Arial,freesans,sans-serif;font-size:16px;line-height:1.6;color:#333;background-color:#fff;overflow:initial;box-sizing:border-box;word-wrap:break-word}html body>:first-child{margin-top:0}html body h1,html body h2,html body h3,html body h4,html body h5,html body h6{line-height:1.2;margin-top:1em;margin-bottom:16px;color:#000}html body h1{font-size:2.25em;font-weight:300;padding-bottom:.3em}html body h2{font-size:1.75em;font-weight:400;padding-bottom:.3em}html body h3{font-size:1.5em;font-weight:500}html body h4{font-size:1.25em;font-weight:600}html body h5{font-size:1.1em;font-weight:600}html body h6{font-size:1em;font-weight:600}html body h1,html body h2,html body h3,html body h4,html body h5{font-weight:600}html body h5{font-size:1em}html body h6{color:#5c5c5c}html body strong{color:#000}html body del{color:#5c5c5c}html body a:not([href]){color:inherit;text-decoration:none}html body a{color:#08c;text-decoration:none}html body a:hover{color:#00a3f5;text-decoration:none}html body img{max-width:100%}html body>p{margin-top:0;margin-bottom:16px;word-wrap:break-word}html body>ul,html body>ol{margin-bottom:16px}html body ul,html body ol{padding-left:2em}html body ul.no-list,html body ol.no-list{padding:0;list-style-type:none}html body ul ul,html body ul ol,html body ol ol,html body ol ul{margin-top:0;margin-bottom:0}html body li{margin-bottom:0}html body li.task-list-item{list-style:none}html body li>p{margin-top:0;margin-bottom:0}html body .task-list-item-checkbox{margin:0 .2em .25em -1.8em;vertical-align:middle}html body .task-list-item-checkbox:hover{cursor:pointer}html body blockquote{margin:16px 0;font-size:inherit;padding:0 15px;color:#5c5c5c;background-color:#f0f0f0;border-left:4px solid #d6d6d6}html body blockquote>:first-child{margin-top:0}html body blockquote>:last-child{margin-bottom:0}html body hr{height:4px;margin:32px 0;background-color:#d6d6d6;border:0 none}html body table{margin:10px 0 15px 0;border-collapse:collapse;border-spacing:0;display:block;width:100%;overflow:auto;word-break:normal;word-break:keep-all}html body table th{font-weight:bold;color:#000}html body table td,html body table th{border:1px solid #d6d6d6;padding:6px 13px}html body dl{padding:0}html body dl dt{padding:0;margin-top:16px;font-size:1em;font-style:italic;font-weight:bold}html body dl dd{padding:0 16px;margin-bottom:16px}html body code{font-family:Menlo,Monaco,Consolas,'Courier New',monospace;font-size:.85em !important;color:#000;background-color:#f0f0f0;border-radius:3px;padding:.2em 0}html body code::before,html body code::after{letter-spacing:-0.2em;content:"\00a0"}html body pre>code{padding:0;margin:0;font-size:.85em !important;word-break:normal;white-space:pre;background:transparent;border:0}html body .highlight{margin-bottom:16px}html body .highlight pre,html body pre{padding:1em;overflow:auto;font-size:.85em !important;line-height:1.45;border:#d6d6d6;border-radius:3px}html body .highlight pre{margin-bottom:0;word-break:normal}html body pre code,html body pre tt{display:inline;max-width:initial;padding:0;margin:0;overflow:initial;line-height:inherit;word-wrap:normal;background-color:transparent;border:0}html body pre code:before,html body pre tt:before,html body pre code:after,html body pre tt:after{content:normal}html body p,html body blockquote,html body ul,html body ol,html body dl,html body pre{margin-top:0;margin-bottom:16px}html body kbd{color:#000;border:1px solid #d6d6d6;border-bottom:2px solid #c7c7c7;padding:2px 4px;background-color:#f0f0f0;border-radius:3px}@media print{html body{background-color:#fff}html body h1,html body h2,html body h3,html body h4,html body h5,html body h6{color:#000;page-break-after:avoid}html body blockquote{color:#5c5c5c}html body pre{page-break-inside:avoid}html body table{display:table}html body img{display:block;max-width:100%;max-height:100%}html body pre,html body code{word-wrap:break-word;white-space:pre}}.markdown-preview{width:100%;height:100%;box-sizing:border-box}.markdown-preview .pagebreak,.markdown-preview .newpage{page-break-before:always}.markdown-preview pre.line-numbers{position:relative;padding-left:3.8em;counter-reset:linenumber}.markdown-preview pre.line-numbers>code{position:relative}.markdown-preview pre.line-numbers .line-numbers-rows{position:absolute;pointer-events:none;top:1em;font-size:100%;left:0;width:3em;letter-spacing:-1px;border-right:1px solid #999;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.markdown-preview pre.line-numbers .line-numbers-rows>span{pointer-events:none;display:block;counter-increment:linenumber}.markdown-preview pre.line-numbers .line-numbers-rows>span:before{content:counter(linenumber);color:#999;display:block;padding-right:.8em;text-align:right}.markdown-preview .mathjax-exps .MathJax_Display{text-align:center !important}.markdown-preview:not([for="preview"]) .code-chunk .btn-group{display:none}.markdown-preview:not([for="preview"]) .code-chunk .status{display:none}.markdown-preview:not([for="preview"]) .code-chunk .output-div{margin-bottom:16px}.markdown-preview .md-toc{padding:0}.markdown-preview .md-toc .md-toc-link-wrapper .md-toc-link{display:inline;padding:.25rem 0}.markdown-preview .md-toc .md-toc-link-wrapper .md-toc-link p,.markdown-preview .md-toc .md-toc-link-wrapper .md-toc-link div{display:inline}.markdown-preview .md-toc .md-toc-link-wrapper.highlighted .md-toc-link{font-weight:800}.scrollbar-style::-webkit-scrollbar{width:8px}.scrollbar-style::-webkit-scrollbar-track{border-radius:10px;background-color:transparent}.scrollbar-style::-webkit-scrollbar-thumb{border-radius:5px;background-color:rgba(150,150,150,0.66);border:4px solid rgba(150,150,150,0.66);background-clip:content-box}html body[for="html-export"]:not([data-presentation-mode]){position:relative;width:100%;height:100%;top:0;left:0;margin:0;padding:0;overflow:auto}html body[for="html-export"]:not([data-presentation-mode]) .markdown-preview{position:relative;top:0}@media screen and (min-width:914px){html body[for="html-export"]:not([data-presentation-mode]) .markdown-preview{padding:2em calc(50% - 457px + 2em)}}@media screen and (max-width:914px){html body[for="html-export"]:not([data-presentation-mode]) .markdown-preview{padding:2em}}@media screen and (max-width:450px){html body[for="html-export"]:not([data-presentation-mode]) .markdown-preview{font-size:14px !important;padding:1em}}@media print{html body[for="html-export"]:not([data-presentation-mode]) #sidebar-toc-btn{display:none}}html body[for="html-export"]:not([data-presentation-mode]) #sidebar-toc-btn{position:fixed;bottom:8px;left:8px;font-size:28px;cursor:pointer;color:inherit;z-index:99;width:32px;text-align:center;opacity:.4}html body[for="html-export"]:not([data-presentation-mode])[html-show-sidebar-toc] #sidebar-toc-btn{opacity:1}html body[for="html-export"]:not([data-presentation-mode])[html-show-sidebar-toc] .md-sidebar-toc{position:fixed;top:0;left:0;width:300px;height:100%;padding:32px 0 48px 0;font-size:14px;box-shadow:0 0 4px rgba(150,150,150,0.33);box-sizing:border-box;overflow:auto;background-color:inherit}html body[for="html-export"]:not([data-presentation-mode])[html-show-sidebar-toc] .md-sidebar-toc::-webkit-scrollbar{width:8px}html body[for="html-export"]:not([data-presentation-mode])[html-show-sidebar-toc] .md-sidebar-toc::-webkit-scrollbar-track{border-radius:10px;background-color:transparent}html body[for="html-export"]:not([data-presentation-mode])[html-show-sidebar-toc] .md-sidebar-toc::-webkit-scrollbar-thumb{border-radius:5px;background-color:rgba(150,150,150,0.66);border:4px solid rgba(150,150,150,0.66);background-clip:content-box}html body[for="html-export"]:not([data-presentation-mode])[html-show-sidebar-toc] .md-sidebar-toc a{text-decoration:none}html body[for="html-export"]:not([data-presentation-mode])[html-show-sidebar-toc] .md-sidebar-toc .md-toc{padding:0 16px}html body[for="html-export"]:not([data-presentation-mode])[html-show-sidebar-toc] .md-sidebar-toc .md-toc .md-toc-link-wrapper .md-toc-link{display:inline;padding:.25rem 0}html body[for="html-export"]:not([data-presentation-mode])[html-show-sidebar-toc] .md-sidebar-toc .md-toc .md-toc-link-wrapper .md-toc-link p,html body[for="html-export"]:not([data-presentation-mode])[html-show-sidebar-toc] .md-sidebar-toc .md-toc .md-toc-link-wrapper .md-toc-link div{display:inline}html body[for="html-export"]:not([data-presentation-mode])[html-show-sidebar-toc] .md-sidebar-toc .md-toc .md-toc-link-wrapper.highlighted .md-toc-link{font-weight:800}html body[for="html-export"]:not([data-presentation-mode])[html-show-sidebar-toc] .markdown-preview{left:300px;width:calc(100% - 300px);padding:2em calc(50% - 457px - 300px/2);margin:0;box-sizing:border-box}@media screen and (max-width:1274px){html body[for="html-export"]:not([data-presentation-mode])[html-show-sidebar-toc] .markdown-preview{padding:2em}}@media screen and (max-width:450px){html body[for="html-export"]:not([data-presentation-mode])[html-show-sidebar-toc] .markdown-preview{width:100%}}html body[for="html-export"]:not([data-presentation-mode]):not([html-show-sidebar-toc]) .markdown-preview{left:50%;transform:translateX(-50%)}html body[for="html-export"]:not([data-presentation-mode]):not([html-show-sidebar-toc]) .md-sidebar-toc{display:none}
/* Please visit the URL below for more information: */
/* https://shd101wyy.github.io/markdown-preview-enhanced/#/customize-css */
</style>
</head>
<body for="html-export">
<div class="mume markdown-preview ">
<h1 class="mume-header" id="-cs184-project-2-meshedit-writeup-">CS184 Project 2 (MeshEdit) Writeup</h1>
<blockquote>
<p>Spring 2023, Yunhao Cao and Yuqi Zhai</p>
</blockquote>
<h2 class="mume-header" id="-overview-">Overview</h2>
<p>In this project, we implemented a mesh editing tool that allows users to edit a mesh in a 3D space. The tool supports the following operations:</p>
<ol>
<li><strong>Bezier Curve/Surface</strong> visualization and editing</li>
<li><strong>3D Vertex / Edge</strong> visualization and editing</li>
<li><strong>Vertex Normal</strong> visualization</li>
<li><strong>Mesh upsampling</strong> using Loop subdivision</li>
</ol>
<p>The skeleton code for this project is basically a 99.9% complete 3d engine, we just need to fill in a few functions to make interpolations/editing work.</p>
<h3 class="mume-header" id="-part-i-bezier-curves-with-1d-de-casteljau-subdivision-">Part I: Bezier Curves with 1D de Casteljau Subdivision</h3>
<p>De Casteljau’s algorithm recursively calculates the Bezier Curve through a series of linear interpolations.</p>
<ol>
<li>On each level, we do linear interpolation on the line segments between 2 points available through a predetermined parameter of t to find the new point that we would use to linearly interpolate for the next level.</li>
<li>Eventually, we will end up with only 1 point, where this point is actually on the Bezier Curve that we want to find. Together with the starting and ending points (in our case of a cubic spline, b0 and b3), we could find the unique cubic function that passes through all three points, which will serve as the Bezier Curve for this section.</li>
</ol>
<p>Each step-level of evaluation:</p>
<table>
<thead>
<tr>
<th>step</th>
<th>images</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td><img src="images/task1-question2-picture1.png" alt></td>
</tr>
<tr>
<td>2</td>
<td><img src="images/task1-question2-picture2.png" alt></td>
</tr>
<tr>
<td>3</td>
<td><img src="images/task1-question2-picture3.png" alt></td>
</tr>
<tr>
<td>4</td>
<td><img src="images/task1-question2-picture4.png" alt></td>
</tr>
<tr>
<td>5</td>
<td><img src="images/task1-question2-picture5.png" alt></td>
</tr>
<tr>
<td>6</td>
<td><img src="images/task1-question2-picture6.png" alt></td>
</tr>
<tr>
<td>with curve</td>
<td><img src="images/task1-question2-picture7.png" alt></td>
</tr>
<tr>
<td>hiding intermediate points</td>
<td><img src="images/task1-question2-picture8.png" alt></td>
</tr>
</tbody>
</table>
<p>Scrolling <code>t</code>:</p>
<table>
<thead>
<tr>
<th>step</th>
<th>images</th>
</tr>
</thead>
<tbody>
<tr>
<td>before</td>
<td><img src="images/task1-question2-picture7.png" alt></td>
</tr>
<tr>
<td>after</td>
<td><img src="images/task1-question3-picture1.png" alt></td>
</tr>
</tbody>
</table>
<p>Changing control points:</p>
<table>
<thead>
<tr>
<th>step</th>
<th>images</th>
</tr>
</thead>
<tbody>
<tr>
<td>before</td>
<td><img src="images/task1-question2-picture7.png" alt></td>
</tr>
<tr>
<td>after</td>
<td><img src="images/task1-question3-picture2.png" alt></td>
</tr>
</tbody>
</table>
<h3 class="mume-header" id="-part-ii-bezier-surfaces-with-separable-1d-de-casteljau-">Part II: Bezier Surfaces with Separable 1D de Casteljau</h3>
<p>In this part we implemented Bezier surfaces.</p>
<ol>
<li>De Casteljau algorithm could easily be extended to Bezier surfaces by essentially doing the De Casteljau algorithm twice over the surface, once along the row direction, then using the interpolated curves in the row direction do once more to get the column direction, which combined to be the Bezier surface.</li>
<li>More specifically for each <code>(u,v)</code> , We will interpolate each row in the n x n grid of control points at parameter u specified, which will get us one 3D point per row evaluated by the Bezier curve at parameter <code>u</code>. Then using those <code>n</code> points to do once more the de Casteljau algorithm with parameter <code>v</code> to get the point we want that corresponds to <code>(u, v)</code>.</li>
</ol>
<p>Rendering of teapot:</p>
<p><img src="images/task2-question2-picture1.png" alt></p>
<h3 class="mume-header" id="-part-iii-area-weighted-vertex-normals-">Part III: Area-Weighted Vertex Normals</h3>
<p>Phong shading provides a better shading for smooth surfaces by taking into account the surface normal at each vertex. In this part, we implemented area-weighted vertex normals.</p>
<p>We implemented the area-weighted vertex normals through the following steps.</p>
<ol>
<li>First we find the vertices of the current face (triangle) that we are trying to calculate the area-weighted face normals. The vertex that we want to get the normal of (call it v0) for should always be one of the vertices, since we want the normals for faces that the vertex is incident to.</li>
<li>Then the remaining 2 vertices we retrieve by using the vertex of the next halfedge of the halfedge initiated at v0 (call this vertex v1), and by using the vertex of the next halfedge of the next halfedge of the current halfedge starting at v0 (call this vertex v2).</li>
<li>After that, we constructed 2 vectors, from v1 - v0 and v2 - v1. And we calculate the cross product of the 2 vectors without normalizing.
<ol>
<li>We did not use the normal encoded in the Face structure because it is the same as multiplying the normalized normal with the area (only by a factor of 2, since area of a triangle is the norm of the cross product of 2 vectors of the sides divided by 2).</li>
</ol>
</li>
<li>Lastly, we add the cross product to the result 3D vector and normalize at the end.</li>
</ol>
<blockquote>
<p>It is clear that without vertex normals, the teapot appears to have clear boundaries for each triangle mesh. However, with the vertex normals implemented, the teapot looks like a round object.</p>
</blockquote>
<table>
<thead>
<tr>
<th>Surface Normals</th>
<th>Vertex Normals</th>
</tr>
</thead>
<tbody>
<tr>
<td><img src="images/task3-question2-picture1.png" alt></td>
<td><img src="images/task3-question2-picture2.png" alt></td>
</tr>
</tbody>
</table>
<h3 class="mume-header" id="-part-iv-edge-flip-">Part IV: Edge Flip</h3>
<blockquote>
<p>We followed closely by the steps outlined in the spec, where we listed all mesh elements from halfedges, edges, vertices, to faces, number them in a way that we could visualize more clearly, and perform the flip.</p>
</blockquote>
<p><img src="images/task4-question1-picture1.jpeg" alt></p>
<ol>
<li>We check whether both faces involved are not boundaries, through calling is_boundary() for the face mesh.</li>
<li>Then we begin the flip by modifying the halfedges 0 to 5 first by resetting the next, twin, vertex, face, and edge according to the graph we drew where I linked below.</li>
<li>After that, we modify the halfedges associated with each vertex. We move on to modify the halfedges associated with edges and last for the faces.</li>
<li>We did not use any interesting implementations, and the debugging tricks I used are mainly through check_for function and the graph we drew on our notebook to begin with (going over the assignments one by one to make sure the pointers are pointing to the correct mesh element).</li>
</ol>
<table>
<thead>
<tr>
<th>Before</th>
<th>After</th>
</tr>
</thead>
<tbody>
<tr>
<td><img src="images/task4-question2-picture1.png" alt></td>
<td><img src="images/task4-question2-picture2.png" alt></td>
</tr>
<tr>
<td><img src="images/task4-question2-picture1.png" alt></td>
<td><img src="images/task4-question2-picture3.png" alt></td>
</tr>
</tbody>
</table>
<p>The debugging journey was a tough one. First we fell into the pitfall where we thought similarly to the last few tasks, we have to create a new EdgeIter instance to return, which ends up with weird overlapping happening on the teapot. Then after carefully examining the spec, we noticed that and changed that.</p>
<p>After that, we failed on the point where I did not update the vertices and faces halfedges, and when I do flips on the teapot, there may appear some new edges after flipping (check_for returns weird number of meshes for the edge), where those new edges with black color filling in will disappear after 4 flips. Then we add in the full assignments of halfedges to all faces and edges (before we thought the halfedges assigned will not change, so we did not bother to reassign), the whole edge flip is complete. In order to make sure, we did flipping multiple times and it seems to be fine.</p>
<h3 class="mume-header" id="-part-v-edge-split-">Part V: Edge Split</h3>
<p>In this part, we are asked to implement the edge split operation: selecting an edge and spliting it into two edges, while preserving the mesh connectivity.</p>
<ol>
<li>We implemented this by first checking whether the edge is a boundary edge. If it is, then we process it with a special rule described in the EC section</li>
<li>When we split one edge into two, we need to create a new vertex in the middle, the originall edge splits into two edges to connect the new vertex to two vertices that the edge is previously connected to.</li>
<li>We also need to add in two more edges to connect the new vertex to two top vertices of the two faces that the edge is incident to.</li>
<li>Then we need to add in two more faces to account for the original two faces splitting.</li>
<li>Finally we add in corresponding halfedges into the mesh</li>
</ol>
<p>Before and After Edge Splits</p>
<table>
<thead>
<tr>
<th>Before</th>
<th>After</th>
</tr>
</thead>
<tbody>
<tr>
<td><img src="images/task5_before.png" alt></td>
<td><img src="images/task5_aftersplit.png" alt></td>
</tr>
</tbody>
</table>
<p>Edge Splits + Flip</p>
<table>
<thead>
<tr>
<th>Before</th>
<th>Split</th>
<th>Flip</th>
</tr>
</thead>
<tbody>
<tr>
<td><img src="images/task5_before_split_flip.png" alt></td>
<td><img src="images/task5_after_split_before_flip.png" alt></td>
<td><img src="images/task5_after_split_flip.png" alt></td>
</tr>
</tbody>
</table>
<p>Eventful Journey:</p>
<ol>
<li>It is extremely important for this part to be implemented correctly since the next part heavily depends on this part. I made sure that all halfedges have twins in the inverse direction, and all pointer relaitonships are correct between vertices, halfedges, edges, and faces.</li>
</ol>
<h4 class="mume-header" id="-ec-splitting-on-boundary-edge-">EC: Splitting on boundary edge</h4>
<ol>
<li>This case is actually relatively simpler than the general case, because instead of splitting two face into four faces, we only need to split one face into two faces.</li>
<li>One thing special in the implementation is that we need to check which side of the halfedge lying on the splitting edge is inside the mesh and which is outside. Then we just draw out the diagram and figure out relationships between vertices, edges, halfedges, and faces before and after the split.</li>
<li>Once we figured out that, we can simply add two new edges, four new halfedges, and one new face to the mesh.</li>
</ol>
<table>
<thead>
<tr>
<th>Before</th>
<th>After</th>
</tr>
</thead>
<tbody>
<tr>
<td><img src="images/task5_ec_before.png" alt></td>
<td><img src="images/task5_ec_after.png" alt></td>
</tr>
</tbody>
</table>
<h3 class="mume-header" id="-part-vi-loop-subdivision-for-mesh-upsampling-">Part VI: Loop Subdivision for Mesh Upsampling</h3>
<p>In this part, we implemented the Loop subdivision algorithm for mesh upsampling. The algorithm calculates new positions for existing vertices and creates new vertices in the middle of each edge.</p>
<ol>
<li>I implemented the subloop algorithm by first iterating through the mesh and calculating the new position for each old and new vertex. For the new position of the new vertex, I store it in its corresponding splitting edge's <code>newPosition</code> attribute.</li>
<li>Then I iterate through the mesh and start dividing each edge. The challenging point here is that we need to make sure we don't divide on new edges otherwise we will end up in an infinite loop.</li>
<li>Then I iterate through the mesh again and flip new edges that connects an old vertex with a new vertex.</li>
<li>Finally I update the position of all vertices in the mesh</li>
</ol>
<p>Debugging thoughts:</p>
<ol>
<li>Once I was able to think about the algorithm throughly I was able to fix every bug I encountered. The tips on the project website was extremely helpful. I also have a screenshot of a bug I encountered.</li>
</ol>
<p><img src="images/task6-bug.png" alt="Task 6 Bug"></p>
<p>Some observations:</p>
<p>Beetle</p>
<table>
<thead>
<tr>
<th>Before</th>
<th>After</th>
</tr>
</thead>
<tbody>
<tr>
<td><img src="images/task6_beetle_1.png" alt></td>
<td><img src="images/task6_beetle_2.png" alt></td>
</tr>
</tbody>
</table>
<p>Icosahedron</p>
<table>
<thead>
<tr>
<th>Before</th>
<th>After</th>
</tr>
</thead>
<tbody>
<tr>
<td><img src="images/task6_icosahedron_1.png" alt></td>
<td><img src="images/task6_icosahedron_2.png" alt></td>
</tr>
</tbody>
</table>
<p>I think one important thing to notice is that on sharp corners after the split the corner will be more prominent than other corners. Depending on the number of neighbours a sharp corner has, the corner will be more or less prominent.</p>
<p>Subdivisions on cube</p>
<table>
<thead>
<tr>
<th>Step</th>
<th>Image</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td><img src="images/task6_cube_1.png" alt></td>
</tr>
<tr>
<td>2</td>
<td><img src="images/task6_cube_2.png" alt></td>
</tr>
<tr>
<td>3</td>
<td><img src="images/task6_cube_3.png" alt></td>
</tr>
<tr>
<td>4</td>
<td><img src="images/task6_cube_4.png" alt></td>
</tr>
<tr>
<td>5</td>
<td><img src="images/task6_cube_5.png" alt></td>
</tr>
</tbody>
</table>
<p>Preprocess Ideas:</p>
<blockquote>
<p>I think the asymmetric behavior of the subdivision algorithm is due to the fact that the edges on each surface of the cube is not symmetric, and our algorithm depends on the position of neighbouring vertices to calculate the new position of the vertex. So I did exactly that to make the subdivision symmetric</p>
</blockquote>
<table>
<thead>
<tr>
<th>Step</th>
<th>Image</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td><img src="images/task6_cube_preprocess_1.png" alt></td>
</tr>
<tr>
<td>2</td>
<td><img src="images/task6_cube_preprocess_2.png" alt></td>
</tr>
<tr>
<td>3</td>
<td><img src="images/task6_cube_preprocess_3.png" alt></td>
</tr>
<tr>
<td>4</td>
<td><img src="images/task6_cube_preprocess_4.png" alt></td>
</tr>
</tbody>
</table>
<h3 class="mume-header" id="-credit-and-site-notes-">Credit and site notes:</h3>
<blockquote>
<p>Webpage hosted at <a href="https://quantumcookie.xyz/Opensourced-Study-Notes-Berkeley/CS184/proj2-meshedit-writeup">quantumcookie.xyz/Opensourced-Study-Notes-Berkeley/CS184/proj2-meshedit-writeup</a></p>
</blockquote>
</div>
</body></html>