Commit 053b8bed authored by Sanjay Salem's avatar Sanjay Salem
Browse files

new meshedit functions

parent 126e7de8
......@@ -4,3 +4,4 @@ plugins:
- jekyll-sitemap
- jekyll-remote-theme
logo: '/assets/spot.png'
favicon: 'assets/favicon.ico'
\ No newline at end of file
......@@ -78,8 +78,6 @@ Where:
* <img src="task2_media/0075.png" style="height:24px"> is the axis of rotation
* <img src="task2_media/0076.png" style="height:24px"> is the vector from the base of joint <img src="task2_media/0077.png" style="height:24px"> to the end point of the target joint
Note that <img src="task2_media/0076.png" style="height:24px"> and <img src="task2_media/0054.png" style="height:24px"> (from above) are not the same!
For a more in-depth derivation of Jacobian transpose (and a look into other inverse kinematics algorithms), please check out [this presentation](https://web.archive.org/web/20190501035728/https://autorob.org/lectures/autorob_11_ik_jacobian.pdf). (Pages 45-56 in particular)
Now, all of this will work for updating the angle along a single axis, but we have 3 axes to deal with. Luckily, extending it to 3 dimensions isn't very difficult, we just need to update the angle along each axis independently.
......
......@@ -59,6 +59,8 @@ There are three possible types of bevels:
vertices are connected to the edges originally incident on _v_. The new face is
inset (i.e., shunken or expanded) by a user-controllable amount.
- Vertex Extrude: The selected vertex _v_ is beveled by a flat amount (we use 1/3 the length of the edge from the original vertex _v_ to an adjacent vertex endpoint as the tangential offset), a new vertex _v'_ is inserted into the resulting face, and _v'_ is offset in its normal direction by a user-controllable amount.
<video src="{{ site.baseurl }}/guide/model_mode/vertex_bevel.mp4" controls preload muted loop style="max-width: 100%; margin: 0 auto;"></video>
- Edge Bevel: The selected edge _e_ is replaced by a face _f_ whose
......@@ -73,6 +75,10 @@ as a ring of faces around _g_, such that the vertices of _g_ connect to the
original vertices of _f_. The new face is inset and offset by some
user-controllable amount.
- Face Extrude: The selected face _f_ is replaced by a new face _g_ as in Face Bevel, and _g_ is offset only in the normal direction by some user-controllable amount.
- Face Inset: The selected face _f_ is replaced by a new face _g_ as in Face Bevel, but its vertices are only offset in the tangent direction by a constant factor (we use 1/3 in the example).
<video src="{{ site.baseurl }}/guide/model_mode/face_bevel.mp4" controls preload muted loop style="max-width: 100%; margin: 0 auto;"></video>
### Local Connectivity Editing
......@@ -108,6 +114,8 @@ _v_.
<video src="{{ site.baseurl }}/guide/model_mode/collapse_face.mp4" controls preload muted loop style="max-width: 100%; margin: 0 auto;"></video>
- Vertex Inset: A new vertex _v_ is inset at the center of the selected face _f_, dividing _f_ into _n_ triangles (where _n_ is the degree of _f_).
- Edge Flip: The selected edge _e_ is "rotated" around the face, in the
sense that each endpoint moves to the next vertex (in counter-clockwise order)
along the boundary of the two polygons containing _e_.
......@@ -120,6 +128,8 @@ to the two opposite vertices (or one in the case of a surface with boundary).
<video src="{{ site.baseurl }}/guide/model_mode/edge_split.mp4" controls preload muted loop style="max-width: 100%; margin: 0 auto;"></video>
- Edge Bisect: The selected edge _e_ is split at its midpoint, and the new vertex _v_ at the split is returned. Note that the new vertex _v_ is not connected to the two opposite vertices as in Edge Split.
### Global Mesh Processing
A number of commands can be used to create a more global change in the mesh
......
......@@ -13,7 +13,9 @@ Here we provide some additional detail about the bevel operations and their impl
1. a method that modifies the _connectivity_ of the mesh, creating new beveled elements, and
2. a method the updates the _geometry_ of the mesh, insetting and offseting the new vertices according to user input.
The methods that update the connectivity are `HalfedgeMesh::bevel_vertex`, `halfedgeMesh::bevel_edge`, and `HalfedgeMesh::bevel_face`. The methods that update geometry are `HalfedgeMesh::bevel_vertex_positions`, `HalfedgeMesh::bevel_edge_positions`, and `HalfedgeMesh::bevel_face_positions`.
The methods that update the connectivity are `HalfedgeMesh::bevel_vertex`, `halfedgeMesh::bevel_edge`, and `HalfedgeMesh::bevel_face`. The methods that update geometry are `HalfedgeMesh::bevel_vertex_positions`, `HalfedgeMesh::extruve_vertex_position`, `HalfedgeMesh::bevel_edge_positions`, and `HalfedgeMesh::bevel_face_positions`.
`HalfedgeMesh::extrude_vertex` will update both connectivity and geometry, as it should first perform a flat bevel on the vertex, and then insert a vertex into the new face.
The methods for updating connectivity can be implemented following the general strategy outlined in [edge flip tutorial](edge_flip). **Note that the methods that update geometry will be called repeatedly for the same bevel, in order to adjust positions according to user mouse input. See the gif in the [User Guide](/Scotty3D/guide/model_mode).**
......
......@@ -37,6 +37,10 @@ See the [User Guide](/Scotty3D/guide/model_mode) for demonstrations of each loca
![](split_edge.svg)
* `Halfedge_Mesh::bisect_edge` - should bisect the edge and return the inserted vertex
![](bisect_edge.svg)
* `Halfedge_Mesh::collapse_edge` - should return the new vertex, corresponding to the collapsed edge
![](collapse_edge.svg)
......@@ -45,6 +49,10 @@ See the [User Guide](/Scotty3D/guide/model_mode) for demonstrations of each loca
![](collapse_face.svg)
* `Halfedge_Mesh::inset_vertex` - should return the newly inserted vertex
![](inset_vertex.svg)
* `Halfedge_Mesh::erase_vertex` - should return the new face, corresponding to the faces originally containing the vertex
![](erase_vertex.svg)
......@@ -61,7 +69,10 @@ See the [User Guide](/Scotty3D/guide/model_mode) for demonstrations of each loca
![](bevel_edge.svg)
* `Halfedge_Mesh::bevel_face` - should return the new, inset face
* `Halfedge_Mesh::bevel_face` / `Halfedge_Mesh::extrude_face` / `Halfedge_Mesh::inset_face` - should return the new, inset face
![](bevel_face.svg)
* `Halfedge_Mesh::extrude_vertex` - should return the new vertex
![](extrude_vertex.svg)
\ No newline at end of file
<svg width="263.926" height="141.333" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g>
<title>Layer 1</title>
<polygon id="svg_1" opacity="0.2" fill="#1B1F8A" points="43.931,2 0.598,68 47.265,139.333 78.598,61.333"/>
<g id="svg_2">
<g id="svg_3">
<path id="svg_4" fill="none" stroke="#000000" stroke-width="3" stroke-miterlimit="10" d="m191.836,21.504c-18.175,-6.461 -37.742,-9.979 -58.135,-9.979c-20.524,0 -40.22,3.564 -58.494,10.107"/>
<g id="svg_5">
<polygon id="svg_6" points="201.702,25.356 189.934,14.34 191.068,21.3 185.586,25.733"/>
</g>
</g>
</g>
<polygon id="svg_7" fill="none" stroke="#000000" stroke-miterlimit="10" points="43.931,2 0.598,68 47.265,139.333 78.598,61.333"/>
<line id="svg_8" fill="none" stroke="#000000" stroke-width="4" stroke-linecap="round" stroke-miterlimit="10" x1="43.931" y1="2" x2="47.265" y2="139.333"/>
<g id="svg_9">
<g id="svg_10">
<g id="svg_11">
<defs>
<rect id="SVGID_1_" x="52.827" y="64.676" width="6" height="8"/>
</defs>
<clipPath id="SVGID_2_">
<use id="svg_12" xlink:href="#SVGID_1_"/>
</clipPath>
<path id="svg_13" clip-path="url(#SVGID_2_)" d="m54.612,68.122c0.293,-1.092 0.61,-1.784 1.063,-2.184c0.293,-0.267 0.771,-0.453 1.146,-0.453c0.479,0 0.771,0.32 0.771,0.826c0,0.691 -0.561,1.438 -1.385,1.836c-0.452,0.24 -1.013,0.399 -1.73,0.561l0.135,-0.586m3.435,2.583l-0.398,0.267c-0.825,0.612 -1.598,0.932 -2.156,0.932c-0.745,0 -1.226,-0.586 -1.226,-1.543c0,-0.398 0.055,-0.825 0.133,-1.277l1.307,-0.318c0.267,-0.08 0.69,-0.24 1.092,-0.399c1.357,-0.587 1.971,-1.332 1.971,-2.317c0,-0.745 -0.531,-1.225 -1.331,-1.225c-1.039,0 -2.797,1.092 -3.407,2.104c-0.479,0.799 -0.959,2.689 -0.959,3.756c0,1.252 0.691,1.971 1.838,1.971c0.903,0 1.812,-0.452 3.273,-1.625l-0.137,-0.326z"/>
</g>
</g>
</g>
<polygon id="svg_14" opacity="0.2" fill="#1B1F8A" points="227.26,2 183.926,68 230.593,139.333 261.926,61.333"/>
<polygon id="svg_15" fill="none" stroke="#000000" stroke-miterlimit="10" points="227.26,2 183.926,68 230.593,139.333 261.926,61.333"/>
<line id="svg_27" fill="none" stroke="#000000" stroke-miterlimit="10" x1="227.259" y1="2" x2="230.593" y2="139.333"/>
<circle id="svg_28" cx="228.925" cy="64.675" r="5.318"/>
<g id="svg_29">
<defs>
<rect id="SVGID_5_" x="216.107" y="70.946" width="8" height="8"/>
</defs>
<clipPath id="SVGID_6_">
<use id="svg_30" xlink:href="#SVGID_5_"/>
</clipPath>
<path id="svg_31" clip-path="url(#SVGID_6_)" d="m221.193,72.022l0.16,0.293c0.16,-0.079 0.293,-0.133 0.426,-0.133c0.426,0 0.693,0.373 0.693,1.012c0,2.344 -1.545,4.926 -2.93,4.926c-0.799,0 -1.278,-0.665 -1.278,-1.704c0,-1.65 0.612,-3.115 2.184,-5.032l-0.159,-0.293c-0.32,0.133 -0.533,0.187 -0.986,0.187c-0.426,0 -1.117,-0.026 -1.57,-0.08l-0.187,-0.026c-0.106,0 -0.187,0 -0.187,0c-0.186,0 -0.346,0.026 -0.506,0.106c-0.24,0.426 -0.399,1.012 -0.612,1.864l0.347,0l0.266,-0.666c0.133,-0.267 0.426,-0.426 0.826,-0.426c0.079,0 0.213,0 0.426,0c0.133,0.026 0.239,0.026 0.452,0.026c0.319,0 0.586,-0.026 0.985,-0.08c-1.758,1.917 -2.424,3.249 -2.424,4.819c0,1.226 0.72,2.104 1.758,2.104c0.666,0 1.252,-0.292 1.998,-0.932c0.745,-0.692 1.49,-1.757 1.996,-2.849c0.347,-0.799 0.613,-1.864 0.613,-2.503c0,-0.905 -0.4,-1.545 -0.986,-1.545c-0.213,0 -0.398,0.054 -0.506,0.187l-0.799,0.745"/>
</g>
<text stroke="#000000" transform="matrix(0.7107555866241455,0,0,0.7107555866241455,17.187445376068354,20.721650552004576) " font-weight="normal" xml:space="preserve" text-anchor="middle" font-family="Serif" font-size="24" id="svg_32" y="17.132886" x="166.307152" stroke-width="0" fill="#000000">EdgeBisect</text>
</g>
</svg>
\ No newline at end of file
<svg width="349.88" height="119.336" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g>
<title>Layer 1</title>
<g id="svg_1">
<g id="svg_2">
<polygon id="svg_3" opacity="0.2" fill="#1B1F8A" points="52.667,118.825 19.741,90.492 0.667,45.513 29.396,35.193 31.167,16.367 54.48,0.658 68.487,16.367 100.167,6.158 107.579,35.193 136.333,50.825 117.234,77.493 109.333,99.158 90.182,116.492"/>
<polygon id="svg_4" fill="none" stroke="#000000" stroke-miterlimit="10" points="52.667,118.825 19.741,90.492 0.667,45.513 29.396,35.193 31.167,16.367 54.48,0.658 68.487,16.367 100.167,6.158 107.579,35.193 136.333,50.825 117.234,77.493 109.333,99.158 90.182,116.492"/>
<line id="svg_5" fill="none" stroke="#000000" stroke-miterlimit="10" x1="76.167" y1="55.658" x2="68.487" y2="16.367"/>
<line id="svg_6" fill="none" stroke="#000000" stroke-miterlimit="10" x1="76.167" y1="55.658" x2="107.579" y2="35.193"/>
<line id="svg_7" fill="none" stroke="#000000" stroke-miterlimit="10" x1="76.167" y1="55.658" x2="117.234" y2="77.493"/>
<line id="svg_8" fill="none" stroke="#000000" stroke-miterlimit="10" x1="76.167" y1="55.658" x2="90.182" y2="116.492"/>
<line id="svg_9" fill="none" stroke="#000000" stroke-miterlimit="10" x1="76.167" y1="55.658" x2="52.667" y2="118.825"/>
<line id="svg_10" fill="none" stroke="#000000" stroke-miterlimit="10" x1="76.167" y1="55.658" x2="19.741" y2="90.492"/>
<line id="svg_11" fill="none" stroke="#000000" stroke-miterlimit="10" x1="76.167" y1="55.658" x2="29.396" y2="35.193"/>
<circle id="svg_12" cx="76.167" cy="55.658" r="3.671"/>
</g>
<g id="svg_13">
<defs>
<rect id="SVGID_1_" x="76.774" y="40.104" width="8" height="8"/>
</defs>
<clipPath id="SVGID_2_">
<use id="svg_14" xlink:href="#SVGID_1_"/>
</clipPath>
<path id="svg_15" clip-path="url(#SVGID_2_)" d="m81.86,41.181l0.16,0.293c0.16,-0.079 0.293,-0.133 0.426,-0.133c0.426,0 0.692,0.373 0.692,1.012c0,2.344 -1.544,4.926 -2.929,4.926c-0.799,0 -1.278,-0.665 -1.278,-1.704c0,-1.65 0.613,-3.115 2.184,-5.032l-0.16,-0.293c-0.32,0.133 -0.533,0.187 -0.985,0.187c-0.426,0 -1.118,-0.026 -1.571,-0.08l-0.187,-0.026c-0.106,0 -0.187,0 -0.187,0c-0.186,0 -0.346,0.026 -0.506,0.106c-0.24,0.426 -0.399,1.012 -0.612,1.864l0.346,0l0.266,-0.666c0.133,-0.267 0.426,-0.426 0.826,-0.426c0.08,0 0.213,0 0.426,0c0.133,0.026 0.24,0.026 0.453,0.026c0.32,0 0.586,-0.026 0.985,-0.08c-1.757,1.917 -2.423,3.249 -2.423,4.819c0,1.226 0.719,2.104 1.758,2.104c0.666,0 1.251,-0.292 1.997,-0.932c0.746,-0.692 1.491,-1.757 1.997,-2.849c0.346,-0.799 0.612,-1.864 0.612,-2.503c0,-0.905 -0.399,-1.545 -0.985,-1.545c-0.213,0 -0.399,0.054 -0.506,0.187l-0.799,0.745"/>
</g>
<g id="svg_60">
<defs id="svg_61">
<rect id="svg_62" x="76.774" y="40.104" width="8" height="8"/>
</defs>
<clipPath id="svg_63">
<use id="svg_64" xlink:href="#SVGID_1_"/>
</clipPath>
<path id="svg_65" clip-path="url(#SVGID_2_)" d="m81.86,41.181l0.16,0.293c0.16,-0.079 0.293,-0.133 0.426,-0.133c0.426,0 0.692,0.373 0.692,1.012c0,2.344 -1.544,4.926 -2.929,4.926c-0.799,0 -1.278,-0.665 -1.278,-1.704c0,-1.65 0.613,-3.115 2.184,-5.032l-0.16,-0.293c-0.32,0.133 -0.533,0.187 -0.985,0.187c-0.426,0 -1.118,-0.026 -1.571,-0.08l-0.187,-0.026c-0.106,0 -0.187,0 -0.187,0c-0.186,0 -0.346,0.026 -0.506,0.106c-0.24,0.426 -0.399,1.012 -0.612,1.864l0.346,0l0.266,-0.666c0.133,-0.267 0.426,-0.426 0.826,-0.426c0.08,0 0.213,0 0.426,0c0.133,0.026 0.24,0.026 0.453,0.026c0.32,0 0.586,-0.026 0.985,-0.08c-1.757,1.917 -2.423,3.249 -2.423,4.819c0,1.226 0.719,2.104 1.758,2.104c0.666,0 1.251,-0.292 1.997,-0.932c0.746,-0.692 1.491,-1.757 1.997,-2.849c0.346,-0.799 0.612,-1.864 0.612,-2.503c0,-0.905 -0.399,-1.545 -0.985,-1.545c-0.213,0 -0.399,0.054 -0.506,0.187l-0.799,0.745"/>
</g>
</g>
<g id="svg_16">
<g id="svg_17">
<polygon id="svg_18" opacity="0.2" fill="#1B1F8A" points="265.477,118.825 232.551,90.492 213.477,45.513 242.206,35.193 243.977,16.367 267.291,0.658 281.298,16.367 312.977,6.158 320.39,35.193 349.144,50.825 330.044,77.493 322.144,99.158 302.992,116.492"/>
<polygon id="svg_19" fill="none" stroke="#000000" stroke-miterlimit="10" points="265.477,118.825 232.551,90.492 213.477,45.513 242.206,35.193 243.977,16.367 267.291,0.658 281.298,16.367 312.977,6.158 320.39,35.193 349.144,50.825 330.044,77.493 322.144,99.158 302.992,116.492"/>
<line id="svg_20" fill="none" stroke="#000000" stroke-miterlimit="10" x1="288.978" y1="55.658" x2="281.298" y2="16.367"/>
<line id="svg_21" fill="none" stroke="#000000" stroke-miterlimit="10" x1="288.978" y1="55.658" x2="320.39" y2="35.193"/>
<line id="svg_22" fill="none" stroke="#000000" stroke-miterlimit="10" x1="288.978" y1="55.658" x2="330.044" y2="77.493"/>
<line id="svg_23" fill="none" stroke="#000000" stroke-miterlimit="10" x1="288.978" y1="55.658" x2="302.992" y2="116.492"/>
<line id="svg_24" fill="none" stroke="#000000" stroke-miterlimit="10" x1="288.978" y1="55.658" x2="265.477" y2="118.825"/>
<line id="svg_25" fill="none" stroke="#000000" stroke-miterlimit="10" x1="288.978" y1="55.658" x2="232.551" y2="90.492"/>
<line id="svg_26" fill="none" stroke="#000000" stroke-miterlimit="10" x1="288.978" y1="55.658" x2="242.206" y2="35.193"/>
<polygon id="svg_27" fill="none" stroke="#000000" stroke-miterlimit="10" points="283.766,28.996 264.088,44.768 265.591,70.095 279.503,81.125 295.076,82.129 312.965,68.413 311.736,40.831"/>
<circle id="svg_28" cx="288.978" cy="55.658" r="3.671"/>
</g>
<g id="svg_29">
<defs>
<rect id="SVGID_3_" x="282.648" y="48.78" width="10" height="17"/>
</defs>
<clipPath id="SVGID_4_">
<use id="svg_30" xlink:href="#SVGID_3_"/>
</clipPath>
</g>
</g>
<g id="svg_31">
<g id="svg_32">
<path id="svg_33" fill="none" stroke="#000000" stroke-width="3" stroke-miterlimit="10" d="m227.278,19.637c-18.174,-6.461 -37.744,-9.979 -58.134,-9.979c-20.525,0 -40.219,3.564 -58.494,10.107"/>
<g id="svg_34">
<polygon id="svg_35" points="237.145,23.491 225.375,12.474 226.51,19.434 221.028,23.868"/>
</g>
</g>
</g>
<g id="svg_48">
<g id="svg_49">
<polyline id="svg_50" fill="none" stroke="#000000" stroke-width="0.5" stroke-miterlimit="10" points="71.827,29.386 70.906,28.996 70.126,29.622"/>
<line id="svg_51" fill="none" stroke="#000000" stroke-width="0.5" stroke-miterlimit="10" stroke-dasharray="2.1108,2.1108" x1="68.479" y1="30.941" x2="52.832" y2="43.482"/>
<polyline id="svg_52" fill="none" stroke="#000000" stroke-width="0.5" stroke-miterlimit="10" points="52.008,44.142 51.228,44.768 51.287,45.766"/>
<line id="svg_53" fill="none" stroke="#000000" stroke-width="0.5" stroke-miterlimit="10" stroke-dasharray="2.1247,2.1247" x1="51.413" y1="47.887" x2="52.609" y2="68.036"/>
<polyline id="svg_54" fill="none" stroke="#000000" stroke-width="0.5" stroke-miterlimit="10" points="52.672,69.097 52.731,70.095 53.515,70.716"/>
<polyline id="svg_55" fill="none" stroke="#000000" stroke-width="0.5" stroke-miterlimit="10" stroke-dasharray="1.9964,1.9964" points="55.08,71.956 66.643,81.125 82.216,82.129 98.52,69.628"/>
<polyline id="svg_56" fill="none" stroke="#000000" stroke-width="0.5" stroke-miterlimit="10" points="99.312,69.021 100.105,68.413 100.061,67.414"/>
<line id="svg_57" fill="none" stroke="#000000" stroke-width="0.5" stroke-miterlimit="10" stroke-dasharray="1.97,1.97" x1="99.973" y1="65.446" x2="98.965" y2="42.813"/>
<polyline id="svg_58" fill="none" stroke="#000000" stroke-width="0.5" stroke-miterlimit="10" points="98.921,41.83 98.876,40.831 97.956,40.441"/>
<line id="svg_59" fill="none" stroke="#000000" stroke-width="0.5" stroke-miterlimit="10" stroke-dasharray="1.8914,1.8914" x1="96.213" y1="39.704" x2="72.698" y2="29.754"/>
</g>
</g>
<text stroke="#000000" transform="matrix(0.7381818294525146,0,0,0.7381818294525146,42.1118163689971,18.830453734844923) " font-style="italic" xml:space="preserve" text-anchor="middle" font-family="serif" font-size="24" id="svg_67" y="41.59275" x="343.24467" stroke-linecap="null" stroke-linejoin="null" stroke-dasharray="null" stroke-width="0" fill="#000000">v&#x27;</text>
<text font-weight="normal" stroke="#000000" transform="matrix(0.6658574739613954,0,0,0.6658574739613954,28.789668928185858,15.939601665728237) " xml:space="preserve" text-anchor="middle" font-family="serif" font-size="24" id="svg_68" y="21.82054" x="215.67801" stroke-linecap="null" stroke-linejoin="null" stroke-dasharray="null" stroke-width="0" fill="#000000">VertexExtrude</text>
</g>
</svg>
\ No newline at end of file
<svg width="349.88" height="119.336" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g>
<title>Layer 1</title>
<g id="svg_1">
<g id="svg_2">
<polygon id="svg_3" opacity="0.4" fill="#1B1F8A" points="52.66699981689453,118.82499694824219 19.740999221801758,90.49199676513672 0.6670000553131104,45.51300048828125 29.395999908447266,35.19300079345703 31.16699981689453,16.367000579833984 54.47999954223633,0.6580000519752502 68.48699951171875,16.367000579833984 100.16699981689453,6.1579999923706055 107.5790023803711,35.19300079345703 136.33299255371094,50.82500076293945 117.23400115966797,77.49299621582031 109.33300018310547,99.15799713134766 90.18199920654297,116.49199676513672 "/>
<polygon id="svg_4" fill="none" stroke="#000000" stroke-miterlimit="10" points="52.66699981689453,118.82499694824219 19.740999221801758,90.49199676513672 0.6670000553131104,45.51300048828125 29.395999908447266,35.19300079345703 31.16699981689453,16.367000579833984 54.47999954223633,0.6580000519752502 68.48699951171875,16.367000579833984 100.16699981689453,6.1579999923706055 107.5790023803711,35.19300079345703 136.33299255371094,50.82500076293945 117.23400115966797,77.49299621582031 109.33300018310547,99.15799713134766 90.18199920654297,116.49199676513672 "/>
</g>
</g>
<g id="svg_16">
<g id="svg_17">
<polygon id="svg_18" opacity="0.2" fill="#1B1F8A" points="265.47698974609375,118.82499694824219 232.55099487304688,90.49199676513672 213.4770050048828,45.51300048828125 242.20599365234375,35.19300079345703 243.9770050048828,16.367000579833984 267.2909851074219,0.6580000519752502 281.2980041503906,16.367000579833984 312.97698974609375,6.1579999923706055 320.3900146484375,35.19300079345703 349.1440124511719,50.82500076293945 330.04400634765625,77.49299621582031 322.1440124511719,99.15799713134766 302.99200439453125,116.49199676513672 "/>
<polygon id="svg_19" fill="none" stroke="#000000" stroke-miterlimit="10" points="265.47698974609375,118.82499694824219 232.55099487304688,90.49199676513672 213.4770050048828,45.51300048828125 242.20599365234375,35.19300079345703 243.9770050048828,16.367000579833984 267.2909851074219,0.6580000519752502 281.2980041503906,16.367000579833984 312.97698974609375,6.1579999923706055 320.3900146484375,35.19300079345703 349.1440124511719,50.82500076293945 330.04400634765625,77.49299621582031 322.1440124511719,99.15799713134766 302.99200439453125,116.49199676513672 "/>
<line id="svg_20" fill="none" stroke="#000000" stroke-miterlimit="10" x1="288.978" y1="55.658" x2="281.298" y2="16.367"/>
<line id="svg_21" fill="none" stroke="#000000" stroke-miterlimit="10" x1="288.978" y1="55.658" x2="320.39" y2="35.193"/>
<line id="svg_22" fill="none" stroke="#000000" stroke-miterlimit="10" x1="288.978" y1="55.658" x2="330.044" y2="77.493"/>
<line id="svg_23" fill="none" stroke="#000000" stroke-miterlimit="10" x1="288.978" y1="55.658" x2="302.992" y2="116.492"/>
<line id="svg_24" fill="none" stroke="#000000" stroke-miterlimit="10" x1="288.978" y1="55.658" x2="265.477" y2="118.825"/>
<line id="svg_25" fill="none" stroke="#000000" stroke-miterlimit="10" x1="288.978" y1="55.658" x2="232.551" y2="90.492"/>
<line id="svg_26" fill="none" stroke="#000000" stroke-miterlimit="10" x1="288.978" y1="55.658" x2="242.206" y2="35.193"/>
<circle id="svg_28" cx="288.978" cy="55.658" r="3.671"/>
</g>
<g id="svg_29">
<defs>
<rect id="SVGID_3_" x="282.648" y="48.78" width="10" height="17"/>
</defs>
<clipPath id="SVGID_4_">
<use x="0" y="0" transform="matrix(1,0,0,1,0,0) " id="svg_30" xlink:href="#SVGID_3_"/>
</clipPath>
</g>
</g>
<g id="svg_31">
<g id="svg_32">
<path id="svg_33" fill="none" stroke="#000000" stroke-width="3" stroke-miterlimit="10" d="m227.278,19.637c-18.174,-6.461 -37.744,-9.979 -58.134,-9.979c-20.525,0 -40.219,3.564 -58.494,10.107"/>
<g id="svg_34">
<polygon id="svg_35" points="237.14500427246094,23.490999221801758 225.375,12.473999977111816 226.50999450683594,19.43400001525879 221.0279998779297,23.868000030517578 "/>
</g>
</g>
</g>
<text stroke="#000000" transform="matrix(0.7381818294525146,0,0,0.7381818294525146,42.1118163689971,18.830453734844923) " font-style="italic" xml:space="preserve" text-anchor="middle" font-family="serif" font-size="24" id="svg_67" y="41.59275" x="343.24467" stroke-linecap="null" stroke-linejoin="null" stroke-dasharray="null" stroke-width="0" fill="#000000">v</text>
<text stroke="#000000" transform="matrix(0.7381818294525146,0,0,0.7381818294525146,42.1118163689971,18.830453734844923) " font-style="italic" xml:space="preserve" text-anchor="middle" font-family="serif" font-size="24" id="svg_67" y="61.59275" x="43.24467" stroke-linecap="null" stroke-linejoin="null" stroke-dasharray="null" stroke-width="0" fill="#000000">f</text>
<text font-weight="normal" stroke="#000000" transform="matrix(0.6658574739613954,0,0,0.6658574739613954,28.789668928185858,15.939601665728237) " xml:space="preserve" text-anchor="middle" font-family="serif" font-size="24" id="svg_68" y="21.82054" x="215.67801" stroke-linecap="null" stroke-linejoin="null" stroke-dasharray="null" stroke-width="0" fill="#000000">VertexInsert</text>
</g>
</svg>
\ No newline at end of file
......@@ -17,18 +17,18 @@ permalink: /pathtracer/camera_rays
---
## Step 1: `Pathtracer::trace_pixel`
The job of this function is to compute the amount of energy arriving at this pixel of the image. Take a look at `Pathtracer::trace_pixel` in `student/pathtracer.cpp`. Conveniently, we've given you a function `Pathtracer::trace(r)` that provides a measurement of incoming scene radiance along the direction given by ray `r`, split into emissive and reflected components. See `lib/ray.h` for the interface of ray.
Take a look at `Pathtracer::trace_pixel` in `student/pathtracer.cpp`. The job of this function is to compute the amount of energy arriving at this pixel of the image. Conveniently, we've given you a function `Pathtracer::trace(r)` that provides a measurement of incoming scene radiance along the direction given by ray `r`, split into emissive (direct) and reflected (indirect) components. See `lib/ray.h` for the interface of ray.
Given the width and height of the screen, and a point's _screen space_ coordinates (`size_t x, size_t y`), compute the point's _normalized_ ([0-1] x [0-1]) screen space coordinates in `Pathtracer::trace_pixel`. Pass these coordinates to the camera via `Camera::generate_ray` in `camera.cpp` (note that `Camera::generate_ray` accepts a `Vec2` object as its input argument)
## Step 2: `Camera::generate_ray`
Implement `Camera::generate_ray`. This function should return a ray **in world space** that reaches the given sensor sample point, i.e. the input argument. Compute this ray in **camera space** (where the camera pinhole is at the origin, the camera is looking down the -Z axis, and +Y is at the top of the screen.). In `util/camera.h`, the `Camera` class stores `vert_fov` and `aspect_ratio` indicating the vertical field of view of the camera (in degrees, not radians) as well as the aspect ratio.
Implement `Camera::generate_ray`. This function should return a ray **in world space** that reaches the given sensor sample point, i.e. the input argument. We recommend that you compute this ray in camera space (where the camera pinhole is at the origin, the camera is looking down the -Z axis, and +Y is at the top of the screen.). In `util/camera.h`, the `Camera` class stores `vert_fov` and `aspect_ratio` indicating the vertical field of view of the camera (in degrees, not radians) as well as the aspect ratio. Note that the camera maintains camera-space-to-world space transform matrix `iview` that will come in handy. Note that since `iview` is a transform matrix, it contains translation, rotation, and scale factors. Be careful in how you use it directly on specific objects, and take a look at `lib/ray.h` and `lib/mat4.h` to see what functions are available for the `Ray` and `Mat4` objects.
<center><img src="images/camera_coordinate_system.png" ></center>
Note that the camera maintains camera-space-to-world space transform matrix `iview` that you will need to use in order to get the new ray back into **world space**. Note that since `iview` is a transform matrix, it contains translation, rotation, and scale factors. Be careful in how you use it on specific objects, and take a look at `lib/ray.h` and `lib/mat4.h` to see what functions are available for the `Ray` and `Mat4` objects.
Note that the camera maintains camera-space-to-world space transform matrix `iview` that you will need to use in order to get the new ray back into **world space**.
Once you have implemented `Pathtracer::trace_pixel`, `Rect::sample` and `Camera::generate_ray`ou should now have a camera that can shoot rays into the scene! See the
Once you have implemented `Pathtracer::trace_pixel`, `Rect::Uniform::sample` and `Camera::generate_ray`ou should now have a camera that can shoot rays into the scene! See the
**Raytracing Visualization** below to confirm this.
## Step 3: `Pathtracer::trace_pixel` &#8594; Super-sampling
......@@ -36,7 +36,7 @@ Your implementation of `Pathtracer::trace_pixel` must support super-sampling. Th
To choose a sample within the pixel, you should implement `Rect::sample` (see `src/student/samplers.cpp`), such that it provides (random) uniformly distributed 2D points within the rectangular region specified by the origin and the member `Rect::size`. Then you may then create a `Rect` sampler with a one-by-one region and call `sample()` to obtain randomly chosen offsets within the pixel.
---
Once you have implemented `Pathtracer::trace_pixel`, `Rect::sample` and `Camera::generate_ray`, you should have a working camera (see **Raytracing Visualization** section below to confirm that your camera is indeed working).
### Tips
......
......@@ -218,6 +218,11 @@ public:
*/
std::optional<VertexRef> collapse_face(FaceRef f);
/*
Insets a vertex into the given face, returning a pointer to the new center
*/
std::optional<VertexRef> inset_vertex(FaceRef f);
/*
Flip an edge, returning a pointer to the flipped edge
*/
......@@ -230,6 +235,21 @@ public:
*/
std::optional<VertexRef> split_edge(EdgeRef e);
/*
Bisect an edge, returning a pointer to the new inserted midpoint vertex
*/
std::optional<VertexRef> bisect_edge(EdgeRef e);
/*
Insets a face into the given face, but performs a flat operation
*/
std::optional<FaceRef> inset_face(FaceRef f);
/*
Bevels a vertex and inserts a vertex onto the new face, returning a pointer to that vertex
*/
std::optional<VertexRef> extrude_vertex(VertexRef v);
/*
Creates a face in place of the vertex, returning a pointer to the new face
*/
......@@ -252,6 +272,15 @@ public:
void bevel_vertex_positions(const std::vector<Vec3>& start_positions, FaceRef face,
float tangent_offset);
/*
Computes vertex position for the new extruded vertex created
in the center of the temporary beveled face
*/
void extrude_vertex_position(const Vec3& start_positions, FaceRef face);
void extrude_vertex_pos(const std::vector<Vec3>& start_positions, VertexRef v, float normal_offset) {
v->pos = start_positions[0] + v->normal() * normal_offset;
}
/*
Computes vertex positions for a face that was just created by beveling an edge,
but not yet confirmed.
......
......@@ -927,6 +927,10 @@ void Manager::UIsettings() {
ImGui::Begin("Settings", &settings_shown,
ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings);
// TODO How can we use this checkbox to set this flag for all cameras?
//ImGui::Text("Camera");
//ImGui::Checkbox("Flip Vertical Rotation", &TODO);
ImGui::Text("Scene Importer");
ImGui::Checkbox("Drop Normals", &load_opt.drop_normals);
ImGui::Checkbox("Join Identical Vertices", &load_opt.join_verts);
......
......@@ -107,6 +107,10 @@ void Model::apply_transform(Widgets& widgets) {
if(action == Widget_Type::move) {
vert->pos = abs_pos;
}
if(action == Widget_Type::extrude) {
my_mesh->extrude_vertex_pos(trans_begin.verts, vert,
delta.pos.x);
}
update_vertex(vert);
},
......@@ -170,6 +174,12 @@ void Model::apply_transform(Widgets& widgets) {
my_mesh->bevel_face_positions(trans_begin.verts, face, delta.pos.x,
delta.pos.y);
}
} else if(action == Widget_Type::extrude) {
if(beveling == Bevel::face) {
my_mesh->bevel_face_positions(trans_begin.verts, face, 0.0f,
delta.pos.y);
}
}
h = face->halfedge();
......@@ -459,6 +469,71 @@ bool Model::begin_bevel(std::string& err) {
}
}
bool Model::begin_extrude(std::string& err) {
auto sel = selected_element();
if(!sel.has_value()) return false;
std::optional<Halfedge_Mesh::ElementRef> ref, ref2;
Halfedge_Mesh::FaceRef f;
my_mesh->copy_to(old_mesh);
auto new_obj = std::visit(overloaded{[&](Halfedge_Mesh::FaceRef face) {
beveling = Bevel::face;
ref2 = my_mesh->bevel_face(face);
return ref2;
},
[&](Halfedge_Mesh::VertexRef vert) {
beveling = Bevel::vert;
ref2 = my_mesh->extrude_vertex(vert);
return ref2;
},
[&](auto) -> std::optional<Halfedge_Mesh::ElementRef> { return std::nullopt; }},
*sel);
if(!new_obj.has_value()) return false;
Halfedge_Mesh::ElementRef elem = new_obj.value();
return std::visit(overloaded{[&](Halfedge_Mesh::VertexRef vert) {
err = validate();
if(!err.empty()) {
*my_mesh = std::move(old_mesh);
return false;
} else {
my_mesh->render_dirty_flag = true;
set_selected(vert);
trans_begin = {};
trans_begin.verts.push_back(vert->pos);
return true;
}
},
[&](Halfedge_Mesh::FaceRef face) {
err = validate();
if(!err.empty()) {
*my_mesh = std::move(old_mesh);
return false;
} else {
my_mesh->render_dirty_flag = true;
set_selected(face);
trans_begin = {};
auto h = face->halfedge();
trans_begin.center = face->center();
do {
trans_begin.verts.push_back(h->vertex()->pos);
h = h->next();
} while(h != face->halfedge());
return true;
}
},
[&](auto) -> bool { return false; }},
elem);
}
bool Model::keydown(Widgets& widgets, SDL_Keysym key, Camera& cam) {
auto sel = selected_element();
......@@ -486,6 +561,7 @@ bool Model::keydown(Widgets& widgets, SDL_Keysym key, Camera& cam) {
switch(key.sym) {
case SDLK_b: widgets.active = Widget_Type::bevel; return true;
case SDLK_e: widgets.active = Widget_Type::extrude; return true;
case SDLK_c: zoom_to(*sel, cam); return true;
case SDLK_h: {
std::visit(
......@@ -676,7 +752,7 @@ std::string Model::UIsidebar(Undo& undo, Widgets& widgets, Scene_Maybe obj_opt,
widgets.action_button(Widget_Type::rotate, "Rotate [r]");
widgets.action_button(Widget_Type::scale, "Scale [s]");
widgets.action_button(Widget_Type::bevel, "Bevel [b]");
widgets.action_button(Widget_Type::extrude, "Extrude [e]");
std::string err = std::visit(
overloaded{
[&](Halfedge_Mesh::VertexRef vert) -> std::string {
......@@ -723,6 +799,14 @@ std::string Model::UIsidebar(Undo& undo, Widgets& widgets, Scene_Maybe obj_opt,
return m.split_edge(std::get<Halfedge_Mesh::EdgeRef>(edge));
});
}
if(Manager::wrap_button("Bisect")) {
mesh.copy_to(before);
return update_mesh(
undo, obj, std::move(before), edge,
[](Halfedge_Mesh& m, Halfedge_Mesh::ElementRef edge) {
return m.bisect_edge(std::get<Halfedge_Mesh::EdgeRef>(edge));
});
}
return {};
},
[&](Halfedge_Mesh::FaceRef face) -> std::string {
......@@ -734,6 +818,22 @@ std::string Model::UIsidebar(Undo& undo, Widgets& widgets, Scene_Maybe obj_opt,
return m.collapse_face(std::get<Halfedge_Mesh::FaceRef>(face));
});
}
if(ImGui::Button("Inset")) {
mesh.copy_to(before);
return update_mesh(
undo, obj, std::move(before), face,
[](Halfedge_Mesh& m, Halfedge_Mesh::ElementRef face) {
return m.inset_face(std::get<Halfedge_Mesh::FaceRef>(face));
});
}
if(ImGui::Button("Inset Vertex")) {
mesh.copy_to(before);
return update_mesh(
undo, obj, std::move(before), face,
[](Halfedge_Mesh& m, Halfedge_Mesh::ElementRef face) {
return m.inset_vertex(std::get<Halfedge_Mesh::FaceRef>(face));
});
}
return {};
},
[&](auto) -> std::string { return {}; }},
......@@ -944,6 +1044,28 @@ std::string Model::select(Widgets& widgets, Scene_ID click, Vec3 cam, Vec2 spos,
apply_transform(widgets);
}
} else if(click && widgets.active == Widget_Type::extrude && click == selected_elem_id) {
std::string err;
if(!begin_extrude(err)) {
widgets.end_drag();
return err;
} else {
std::visit(overloaded{[&](Halfedge_Mesh::VertexRef vert) {
widgets.start_drag(Halfedge_Mesh::center_of(vert), cam, spos, dir);
apply_transform(widgets);
},
[&](Halfedge_Mesh::FaceRef face) {
widgets.start_drag(Halfedge_Mesh::center_of(face), cam, spos,
dir);
apply_transform(widgets);
},
[](auto) { return; }},
selected_element().value());
}
} else if(!widgets.is_dragging() && click >= n_Widget_IDs) {
selected_elem_id = (unsigned int)click;
}
......@@ -952,7 +1074,7 @@ std::string Model::select(Widgets& widgets, Scene_ID click, Vec3 cam, Vec2 spos,
auto e = selected_element();
if(e.has_value() && !std::holds_alternative<Halfedge_Mesh::HalfedgeRef>(*e)) {
widgets.start_drag(Halfedge_Mesh::center_of(*e), cam, spos, dir);
if(widgets.active != Widget_Type::bevel) {
if(widgets.active != Widget_Type::bevel && widgets.active != Widget_Type::extrude) {
begin_transform();
}
}
......
......@@ -47,6 +47,7 @@ private:
void zoom_to(Halfedge_Mesh::ElementRef ref, Camera& cam);
void begin_transform();
bool begin_bevel(std::string& err);
bool begin_extrude(std::string& err);
void set_selected(Halfedge_Mesh::ElementRef elem);
std::optional<std::reference_wrapper<Scene_Object>> set_my_obj(Scene_Maybe obj_opt);
std::optional<Halfedge_Mesh::ElementRef> selected_element();
......
......@@ -197,6 +197,10 @@ Pose Widgets::apply_action(const Pose& pose) {
Vec2 off = bevel_start - bevel_end;
result.pos = 2.0f * Vec3(off.x, -off.y, 0.0f);
} break;
case Widget_Type::extrude: {
Vec2 off = bevel_start - bevel_end;
result.pos = 2.0f * Vec3(off.x, -off.y, 0.0f);
} break;
default: assert(false);
}
......@@ -315,7 +319,7 @@ void Widgets::start_drag(Vec3 pos, Vec3 cam, Vec2 spos, Vec3 dir) {
drag_end = Vec3{1.0f};
}
if(active != Widget_Type::bevel) generate_lines(pos);
if(active != Widget_Type::bevel && active != Widget_Type::extrude) generate_lines(pos);
}
}
......@@ -334,7 +338,7 @@ void Widgets::drag_to(Vec3 pos, Vec3 cam, Vec2 spos, Vec3 dir, bool scale_invert
Vec3 norm;
norm[(int)axis] = 1.0f;
if(active == Widget_Type::bevel) {
if(active == Widget_Type::bevel || active == Widget_Type::extrude) {
bevel_end = spos;
......
......@@ -14,7 +14,7 @@ class Animate;
enum class Axis { X, Y, Z };
enum class Widget_Type { move, rotate, scale, bevel, count };
enum class Widget_Type { move, rotate, scale, bevel, extrude, count };
static const int n_Widget_Types = (int)Widget_Type::count;
enum class Widget_IDs : Scene_ID {
......
......@@ -70,6 +70,14 @@ std::optional<Halfedge_Mesh::VertexRef> Halfedge_Mesh::collapse_face(Halfedge_Me
return std::nullopt;
}
/*
Insets a vertex into the given face, returning a pointer to the new center vertex
*/
std::optional<Halfedge_Mesh::VertexRef> Halfedge_Mesh::inset_vertex(FaceRef f) {
(void)f;
return std::nullopt;
}
/*
This method should flip the given edge and return an iterator to the
flipped edge.
......@@ -91,6 +99,32 @@ std::optional<Halfedge_Mesh::VertexRef> Halfedge_Mesh::split_edge(Halfedge_Mesh:
return std::nullopt;
}
/*
This method splits the given edge in half, but does not split the
adjacent faces. Returns an iterator to the new vertex which splits
the original edge.
*/
std::optional<Halfedge_Mesh::VertexRef> Halfedge_Mesh::bisect_edge(EdgeRef e) {
(void)e;
return std::nullopt;
}
std::optional<Halfedge_Mesh::FaceRef> Halfedge_Mesh::inset_face(Halfedge_Mesh::FaceRef f) {
// hint: use bevel_face positions as a helper function here
(void)f;
return std::nullopt;
}
/*
Bevels a vertex and inserts a vertex into the new vertex, returning a pointer to that vertex
*/
std::optional<Halfedge_Mesh::VertexRef> Halfedge_Mesh::extrude_vertex(VertexRef v) {
(void)v;
return std::nullopt;
}
/* Note on the beveling process:
Each of the bevel_vertex, bevel_edge, and bevel_face functions do not represent
......@@ -194,6 +228,14 @@ void Halfedge_Mesh::bevel_vertex_positions(const std::vector<Vec3>& start_positi
(void)tangent_offset;
}
/*
Updates the position of v using the given start_position
*/
void Halfedge_Mesh::extrude_vertex_position(const Vec3& start_positions, Halfedge_Mesh::FaceRef face) {
(void)start_positions;
(void)face;
}
/*
Compute new vertex positions for the vertices of the beveled edge.
......
......@@ -56,7 +56,11 @@ void Camera::reset() {
void Camera::mouse_orbit(Vec2 off) {
float up_rot = -off.x * orbit_sens;
float right_rot = off.y * orbit_sens;
float right_rot = -off.y * orbit_sens;
if( orbit_flip_vertical ) {
right_rot = -right_rot;
}
Vec3 up = rot.rotate(UP);
Vec3 f = front();
......
......@@ -57,6 +57,9 @@ public:
float get_h_fov() const;
float get_near() const;
// swap orbit behavior for vertical mouse motion
bool orbit_flip_vertical = false;
private:
void update_pos();
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment