From 053b8bed7b0290df37660110ec2d7f2a9a395f41 Mon Sep 17 00:00:00 2001 From: Sanjay Salem Date: Mon, 31 Jan 2022 15:52:39 -0600 Subject: [PATCH] new meshedit functions --- docs/_config.yml | 1 + docs/animation/skeleton_kinematics.md | 2 - docs/{ => assets}/favicon.ico | Bin docs/guide/model.md | 10 ++ docs/meshedit/bevel.md | 4 +- docs/meshedit/local.md | 13 ++- docs/meshedit/local/bisect_edge.svg | 43 +++++++++ docs/meshedit/local/extrude_vertex.svg | 84 +++++++++++++++++ docs/meshedit/local/inset_vertex.svg | 48 ++++++++++ docs/pathtracer/camera_rays.md | 10 +- src/geometry/halfedge.h | 29 ++++++ src/gui/manager.cpp | 4 + src/gui/model.cpp | 126 ++++++++++++++++++++++++- src/gui/model.h | 1 + src/gui/widgets.cpp | 8 +- src/gui/widgets.h | 2 +- src/student/meshedit.cpp | 42 +++++++++ src/util/camera.cpp | 6 +- src/util/camera.h | 3 + 19 files changed, 421 insertions(+), 15 deletions(-) rename docs/{ => assets}/favicon.ico (100%) create mode 100644 docs/meshedit/local/bisect_edge.svg create mode 100644 docs/meshedit/local/extrude_vertex.svg create mode 100644 docs/meshedit/local/inset_vertex.svg diff --git a/docs/_config.yml b/docs/_config.yml index 8b77c05..667c468 100644 --- a/docs/_config.yml +++ b/docs/_config.yml @@ -4,3 +4,4 @@ plugins: - jekyll-sitemap - jekyll-remote-theme logo: '/assets/spot.png' +favicon: 'assets/favicon.ico' \ No newline at end of file diff --git a/docs/animation/skeleton_kinematics.md b/docs/animation/skeleton_kinematics.md index b6fd7f4..bb876a4 100644 --- a/docs/animation/skeleton_kinematics.md +++ b/docs/animation/skeleton_kinematics.md @@ -78,8 +78,6 @@ Where: * is the axis of rotation * is the vector from the base of joint to the end point of the target joint -Note that and (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. diff --git a/docs/favicon.ico b/docs/assets/favicon.ico similarity index 100% rename from docs/favicon.ico rename to docs/assets/favicon.ico diff --git a/docs/guide/model.md b/docs/guide/model.md index 85778b3..1382dd1 100644 --- a/docs/guide/model.md +++ b/docs/guide/model.md @@ -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. + - 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). + ### Local Connectivity Editing @@ -108,6 +114,8 @@ _v_. +- 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). +- 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 diff --git a/docs/meshedit/bevel.md b/docs/meshedit/bevel.md index 8ab32fb..144e42d 100644 --- a/docs/meshedit/bevel.md +++ b/docs/meshedit/bevel.md @@ -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).** diff --git a/docs/meshedit/local.md b/docs/meshedit/local.md index 30378cd..6afc26f 100644 --- a/docs/meshedit/local.md +++ b/docs/meshedit/local.md @@ -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 diff --git a/docs/meshedit/local/bisect_edge.svg b/docs/meshedit/local/bisect_edge.svg new file mode 100644 index 0000000..d281ce2 --- /dev/null +++ b/docs/meshedit/local/bisect_edge.svg @@ -0,0 +1,43 @@ + + + Layer 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + EdgeBisect + + \ No newline at end of file diff --git a/docs/meshedit/local/extrude_vertex.svg b/docs/meshedit/local/extrude_vertex.svg new file mode 100644 index 0000000..fae0173 --- /dev/null +++ b/docs/meshedit/local/extrude_vertex.svg @@ -0,0 +1,84 @@ + + + Layer 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + v' + VertexExtrude + + \ No newline at end of file diff --git a/docs/meshedit/local/inset_vertex.svg b/docs/meshedit/local/inset_vertex.svg new file mode 100644 index 0000000..3094b3e --- /dev/null +++ b/docs/meshedit/local/inset_vertex.svg @@ -0,0 +1,48 @@ + + + Layer 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + v + f + VertexInsert + + \ No newline at end of file diff --git a/docs/pathtracer/camera_rays.md b/docs/pathtracer/camera_rays.md index 6aecd65..70f9491 100644 --- a/docs/pathtracer/camera_rays.md +++ b/docs/pathtracer/camera_rays.md @@ -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.
-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` → 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 diff --git a/src/geometry/halfedge.h b/src/geometry/halfedge.h index 32f8171..e109438 100644 --- a/src/geometry/halfedge.h +++ b/src/geometry/halfedge.h @@ -218,6 +218,11 @@ public: */ std::optional collapse_face(FaceRef f); + /* + Insets a vertex into the given face, returning a pointer to the new center + */ + std::optional inset_vertex(FaceRef f); + /* Flip an edge, returning a pointer to the flipped edge */ @@ -230,6 +235,21 @@ public: */ std::optional split_edge(EdgeRef e); + /* + Bisect an edge, returning a pointer to the new inserted midpoint vertex + */ + std::optional bisect_edge(EdgeRef e); + + /* + Insets a face into the given face, but performs a flat operation + */ + std::optional inset_face(FaceRef f); + + /* + Bevels a vertex and inserts a vertex onto the new face, returning a pointer to that vertex + */ + std::optional 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& 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& 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. diff --git a/src/gui/manager.cpp b/src/gui/manager.cpp index 293be70..2f045b5 100644 --- a/src/gui/manager.cpp +++ b/src/gui/manager.cpp @@ -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); diff --git a/src/gui/model.cpp b/src/gui/model.cpp index 4d2082f..95a245c 100644 --- a/src/gui/model.cpp +++ b/src/gui/model.cpp @@ -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 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 { 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(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(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(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(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(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(*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(); } } diff --git a/src/gui/model.h b/src/gui/model.h index 081ac08..3aec480 100644 --- a/src/gui/model.h +++ b/src/gui/model.h @@ -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> set_my_obj(Scene_Maybe obj_opt); std::optional selected_element(); diff --git a/src/gui/widgets.cpp b/src/gui/widgets.cpp index 5cdf7ef..d5f09c4 100644 --- a/src/gui/widgets.cpp +++ b/src/gui/widgets.cpp @@ -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; diff --git a/src/gui/widgets.h b/src/gui/widgets.h index f0b1c85..cd7a3e9 100644 --- a/src/gui/widgets.h +++ b/src/gui/widgets.h @@ -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 { diff --git a/src/student/meshedit.cpp b/src/student/meshedit.cpp index e8e657a..b23d553 100644 --- a/src/student/meshedit.cpp +++ b/src/student/meshedit.cpp @@ -70,6 +70,14 @@ std::optional 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::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::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::bisect_edge(EdgeRef e) { + + (void)e; + return std::nullopt; +} + +std::optional 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::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& 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. diff --git a/src/util/camera.cpp b/src/util/camera.cpp index b2d02f4..e4a8542 100644 --- a/src/util/camera.cpp +++ b/src/util/camera.cpp @@ -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(); diff --git a/src/util/camera.h b/src/util/camera.h index 3863623..87e26dd 100644 --- a/src/util/camera.h +++ b/src/util/camera.h @@ -56,6 +56,9 @@ public: float get_fov() const; 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(); -- GitLab