Commit 5917989f authored by Hui Wang's avatar Hui Wang
Browse files

update doc files

parent f12b4efc
# Scotty3D # Scotty3D
![Ubuntu Build Status](https://github.com/CMU-Graphics/Scotty3D/workflows/Ubuntu/badge.svg) ![MacOS Build Status](https://github.com/CMU-Graphics/Scotty3D/workflows/MacOS/badge.svg) ![Windows Build Status](https://github.com/CMU-Graphics/Scotty3D/workflows/Windows/badge.svg) <!-- ![Ubuntu Build Status](https://github.com/CMU-Graphics/Scotty3D/workflows/Ubuntu/badge.svg) ![MacOS Build Status](https://github.com/CMU-Graphics/Scotty3D/workflows/MacOS/badge.svg) ![Windows Build Status](https://github.com/CMU-Graphics/Scotty3D/workflows/Windows/badge.svg) -->
Welcome to Scotty3D! This 3D graphics software package includes components for interactive mesh Welcome to Scotty3D! This 3D graphics software package includes components for interactive mesh
editing, realistic path tracing, and dynamic animation. Implementing functionality in each of these areas editing, realistic path tracing, and dynamic animation. Implementing functionality in each of these areas
constitutes the majority of the coursework for 15-462/662 (Computer Graphics) at Carnegie Mellon University constitutes the majority of the coursework for 15-462/662 (Computer Graphics) at Carnegie Mellon University
Please visit the [documentation website](https://cmu-graphics.github.io/Scotty3D/). Pleas read the [documentation](docs/index.md)
<!-- Please visit the [documentation website](https://cmu-graphics.github.io/Scotty3D/). -->
## Sampled Student Work (Fall 2020) ## Sampled Student Work (Fall 2020)
......
...@@ -7,9 +7,9 @@ permalink: /build/ ...@@ -7,9 +7,9 @@ permalink: /build/
# Building Scotty3D # Building Scotty3D
![Ubuntu Build Status](https://github.com/CMU-Graphics/Scotty3D/workflows/Ubuntu/badge.svg) ![MacOS Build Status](https://github.com/CMU-Graphics/Scotty3D/workflows/MacOS/badge.svg) ![Windows Build Status](https://github.com/CMU-Graphics/Scotty3D/workflows/Windows/badge.svg) <!-- ![Ubuntu Build Status](https://github.com/CMU-Graphics/Scotty3D/workflows/Ubuntu/badge.svg) ![MacOS Build Status](https://github.com/CMU-Graphics/Scotty3D/workflows/MacOS/badge.svg) ![Windows Build Status](https://github.com/CMU-Graphics/Scotty3D/workflows/Windows/badge.svg) -->
To get a copy of the codebase, see [Git Setup](/Scotty3D/git). To get a copy of the codebase, see [Git Setup](git).
Note: the first build on any platform will be very slow, as it must compile most dependencies. Subsequent builds will only need to re-compile your edited Scotty3D code. Note: the first build on any platform will be very slow, as it must compile most dependencies. Subsequent builds will only need to re-compile your edited Scotty3D code.
......
...@@ -21,18 +21,18 @@ To create a keyframe for an object: ...@@ -21,18 +21,18 @@ To create a keyframe for an object:
To remove a keyframe in the timeline, click on it and press `Clear` to remove it. Press `Clear All` to clear the current keyframe of every object in the scene. To remove a keyframe in the timeline, click on it and press `Clear` to remove it. Press `Clear All` to clear the current keyframe of every object in the scene.
![animating-cow](../../animation/task1_media/animate_cow.gif) ![animating-cow](../animation/task1_media/animate_cow.gif)
To see your animation, press `Play [space]` . Once you've implemented **spline interpolation**, intermediate frames are generated by interpolating object poses between keyframes. To see your animation, press `Play [space]` . Once you've implemented **spline interpolation**, intermediate frames are generated by interpolating object poses between keyframes.
Check `Draw Splines` to visualize the spline along which objects are animated. Check `Draw Splines` to visualize the spline along which objects are animated.
![view-spline](../animate_mode/guide-animate-spline.png) ![view-spline](animate_mode/guide-animate-spline.png)
`Add Frames` inserts 90 empty frames into the timeline. `Crop End` deletes frames from the selected location to the end of the timeline. `Add Frames` inserts 90 empty frames into the timeline. `Crop End` deletes frames from the selected location to the end of the timeline.
### Posing ### Posing
Once you have [rigged](../rig) an object with a skeleton, it can now be posed by selecting a joint and changing its pose i.e., rotating the joint. This is called Forward Kinematics. Once you have [rigged](rig) an object with a skeleton, it can now be posed by selecting a joint and changing its pose i.e., rotating the joint. This is called Forward Kinematics.
Joint poses can also be indirectly changed by using the IK (Inverse Kinematics) handles to provide target positions. Joint poses can also be indirectly changed by using the IK (Inverse Kinematics) handles to provide target positions.
Note that IK handles need to be explicitly enabled using the checkbox. Note that IK handles need to be explicitly enabled using the checkbox.
......
...@@ -38,7 +38,7 @@ toggle through by pressing the `r` key. ...@@ -38,7 +38,7 @@ toggle through by pressing the `r` key.
- `Rotate`: click and drag on the red (X), green (Y), or blue (Z) loop to rotate the object about the X/Y/Z axis. Note that these rotations are applied relative to the current pose, so they do not necessarily correspond to smooth transformations of the X/Y/Z Euler angles. - `Rotate`: click and drag on the red (X), green (Y), or blue (Z) loop to rotate the object about the X/Y/Z axis. Note that these rotations are applied relative to the current pose, so they do not necessarily correspond to smooth transformations of the X/Y/Z Euler angles.
- `Scale`: click and drag on the red (X), green (Y), or blue(Z) block to scale the object about the X/Y/Z axis. Again note that this scale is applied relative to the current pose. - `Scale`: click and drag on the red (X), green (Y), or blue(Z) block to scale the object about the X/Y/Z axis. Again note that this scale is applied relative to the current pose.
![selecting an edge](model_select.png) ![selecting an edge](model_mode/model_select.png)
### Beveling ### Beveling
...@@ -61,14 +61,14 @@ inset (i.e., shunken or expanded) by a user-controllable amount. ...@@ -61,14 +61,14 @@ 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. - 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> <video src="./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 - Edge Bevel: The selected edge _e_ is replaced by a face _f_ whose
vertices are connected to the edges originally incident on the endpoints of _e_. vertices are connected to the edges originally incident on the endpoints of _e_.
The new face is inset and offset by some user-controllable amount, as with the The new face is inset and offset by some user-controllable amount, as with the
vertex bevel. vertex bevel.
<video src="{{ site.baseurl }}/guide/model_mode/edge_bevel.mp4" controls preload muted loop style="max-width: 100%; margin: 0 auto;"></video> <video src="./model_mode/edge_bevel.mp4" controls preload muted loop style="max-width: 100%; margin: 0 auto;"></video>
- Face Bevel: The selected face _f_ is replaced by a new face _g_, as well - Face Bevel: The selected face _f_ is replaced by a new face _g_, as well
as a ring of faces around _g_, such that the vertices of _g_ connect to the as a ring of faces around _g_, such that the vertices of _g_ connect to the
...@@ -79,7 +79,7 @@ user-controllable amount. ...@@ -79,7 +79,7 @@ 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). - 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> <video src="./model_mode/face_bevel.mp4" controls preload muted loop style="max-width: 100%; margin: 0 auto;"></video>
### Local Connectivity Editing ### Local Connectivity Editing
...@@ -92,13 +92,13 @@ appropriate key, as listed below. Local mesh editing operations include: ...@@ -92,13 +92,13 @@ appropriate key, as listed below. Local mesh editing operations include:
and faces will be replaced with a single face _f_, that is the union of all and faces will be replaced with a single face _f_, that is the union of all
faces originally incident on _v_. faces originally incident on _v_.
<video src="{{ site.baseurl }}/guide/model_mode/erase_vertex.mp4" controls preload muted loop style="max-width: 100%; margin: 0 auto;"></video> <video src="./model_mode/erase_vertex.mp4" controls preload muted loop style="max-width: 100%; margin: 0 auto;"></video>
- Erase Edge: The selected edge _e_ will be replaced with the union of the - Erase Edge: The selected edge _e_ will be replaced with the union of the
faces containing it, producing a new face _e_ (if _e_ is a boundary edge, faces containing it, producing a new face _e_ (if _e_ is a boundary edge,
nothing happens). nothing happens).
<video src="{{ site.baseurl }}/guide/model_mode/erase_edge.mp4" controls preload muted loop style="max-width: 100%; margin: 0 auto;"></video> <video src="./model_mode/erase_edge.mp4" controls preload muted loop style="max-width: 100%; margin: 0 auto;"></video>
- Edge Collapse: The selected edge _e_ is replaced by a single vertex _v_. - Edge Collapse: The selected edge _e_ is replaced by a single vertex _v_.
This vertex is connected by edges to all vertices previously connected to either This vertex is connected by edges to all vertices previously connected to either
...@@ -106,13 +106,13 @@ endpoint of _e_. Moreover, if either of the polygons containing _e_ was a ...@@ -106,13 +106,13 @@ endpoint of _e_. Moreover, if either of the polygons containing _e_ was a
triangle, it will be replaced by an edge (rather than a degenerate polygon with triangle, it will be replaced by an edge (rather than a degenerate polygon with
only two edges). only two edges).
<video src="{{ site.baseurl }}/guide/model_mode/collapse_edge.mp4" controls preload muted loop style="max-width: 100%; margin: 0 auto;"></video> <video src="./model_mode/collapse_edge.mp4" controls preload muted loop style="max-width: 100%; margin: 0 auto;"></video>
- Face Collapse: The selected face _f_ is replaced by a single vertex _v_. - Face Collapse: The selected face _f_ is replaced by a single vertex _v_.
All edges previously connected to vertices of _f_ are now connected directly to All edges previously connected to vertices of _f_ are now connected directly to
_v_. _v_.
<video src="{{ site.baseurl }}/guide/model_mode/collapse_face.mp4" controls preload muted loop style="max-width: 100%; margin: 0 auto;"></video> <video src="./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_). - 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_).
...@@ -120,13 +120,13 @@ _v_. ...@@ -120,13 +120,13 @@ _v_.
sense that each endpoint moves to the next vertex (in counter-clockwise order) sense that each endpoint moves to the next vertex (in counter-clockwise order)
along the boundary of the two polygons containing _e_. along the boundary of the two polygons containing _e_.
<video src="{{ site.baseurl }}/guide/model_mode/edge_flip.mp4" controls preload muted loop style="max-width: 100%; margin: 0 auto;"></video> <video src="./model_mode/edge_flip.mp4" controls preload muted loop style="max-width: 100%; margin: 0 auto;"></video>
- Edge Split: [Note: this method is for triangle meshes only!] The - Edge Split: [Note: this method is for triangle meshes only!] The
selected edge _e_ is split at its midpoint, and the new vertex _v_ is connected selected edge _e_ is split at its midpoint, and the new vertex _v_ is connected
to the two opposite vertices (or one in the case of a surface with boundary). 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> <video src="./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. - 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.
...@@ -139,14 +139,14 @@ the path tracer), this command will be applied only to the selected mesh. ...@@ -139,14 +139,14 @@ the path tracer), this command will be applied only to the selected mesh.
- Triangulate: Each polygon is split into triangles. - Triangulate: Each polygon is split into triangles.
<video src="{{ site.baseurl }}/guide/model_mode/triangulate.mp4" controls preload muted loop style="max-width: 100%; margin: 0 auto;"></video> <video src="./model_mode/triangulate.mp4" controls preload muted loop style="max-width: 100%; margin: 0 auto;"></video>
- Linear Subdivision: Each polygon in the selected mesh is split into - Linear Subdivision: Each polygon in the selected mesh is split into
quadrilaterals by inserting a vertex at the midpoint and connecting it to the quadrilaterals by inserting a vertex at the midpoint and connecting it to the
midpoint of all edges. New vertices are placed at the average of old vertices so midpoint of all edges. New vertices are placed at the average of old vertices so
that, e.g., flat faces stay flat, and old vertices remain where they were. that, e.g., flat faces stay flat, and old vertices remain where they were.
<video src="{{ site.baseurl }}/guide/model_mode/linear_subd.mp4" controls preload muted loop style="max-width: 100%; margin: 0 auto;"></video> <video src="./model_mode/linear_subd.mp4" controls preload muted loop style="max-width: 100%; margin: 0 auto;"></video>
- Catmull-Clark Subdivision: _[Note: this method is for meshes without boundary only!]_ - Catmull-Clark Subdivision: _[Note: this method is for meshes without boundary only!]_
Just as with linear subdivision, each Just as with linear subdivision, each
...@@ -155,27 +155,27 @@ updated according to the [Catmull-Clark subdivision ...@@ -155,27 +155,27 @@ updated according to the [Catmull-Clark subdivision
rules](https://en.wikipedia.org/wiki/Catmull-Clark_subdivision_surface), rules](https://en.wikipedia.org/wiki/Catmull-Clark_subdivision_surface),
ultimately generating a nice rounded surface. ultimately generating a nice rounded surface.
<video src="{{ site.baseurl }}/guide/model_mode/catmull_subd.mp4" controls preload muted loop style="max-width: 100%; margin: 0 auto;"></video> <video src="./model_mode/catmull_subd.mp4" controls preload muted loop style="max-width: 100%; margin: 0 auto;"></video>
- Loop Subdivision: _[Note: this method is for triangle meshes without boundary only!]_ - Loop Subdivision: _[Note: this method is for triangle meshes without boundary only!]_
Each triangle is split into four by connecting the edge midpoints. Vertex Each triangle is split into four by connecting the edge midpoints. Vertex
positions are updated according to the [Loop subdivision positions are updated according to the [Loop subdivision
rules](https://en.wikipedia.org/wiki/Loop_subdivision_surface). rules](https://en.wikipedia.org/wiki/Loop_subdivision_surface).
<video src="{{ site.baseurl }}/guide/model_mode/loop_subd.mp4" controls preload muted loop style="max-width: 100%; margin: 0 auto;"></video> <video src="./model_mode/loop_subd.mp4" controls preload muted loop style="max-width: 100%; margin: 0 auto;"></video>
- Isotropic Remeshing: _[Note: this method is for triangle meshes only!]_ - Isotropic Remeshing: _[Note: this method is for triangle meshes only!]_
The mesh is resampled so that triangles all have roughly the same size and The mesh is resampled so that triangles all have roughly the same size and
shape, and vertex valence is close to regular (i.e., about six edges incident on shape, and vertex valence is close to regular (i.e., about six edges incident on
every vertex). every vertex).
<video src="{{ site.baseurl }}/guide/model_mode/remesh.mp4" controls preload muted loop style="max-width: 100%; margin: 0 auto;"></video> <video src="./model_mode/remesh.mp4" controls preload muted loop style="max-width: 100%; margin: 0 auto;"></video>
- Simplification _[Note: this method is for triangle meshes only!]_ The - Simplification _[Note: this method is for triangle meshes only!]_ The
number of triangles in the mesh is reduced by a factor of about four, aiming to number of triangles in the mesh is reduced by a factor of about four, aiming to
preserve the appearance of the original mesh as closely as possible. preserve the appearance of the original mesh as closely as possible.
<video src="{{ site.baseurl }}/guide/model_mode/simplify.mp4" controls preload muted loop style="max-width: 100%; margin: 0 auto;"></video> <video src="./model_mode/simplify.mp4" controls preload muted loop style="max-width: 100%; margin: 0 auto;"></video>
### Key Bindings ### Key Bindings
......
...@@ -13,7 +13,7 @@ Welcome! This is Scotty3D's realistic, globally illuminated renderer, capable of ...@@ -13,7 +13,7 @@ Welcome! This is Scotty3D's realistic, globally illuminated renderer, capable of
In render mode, click on "Open Render Window", and you will be able to set the parameters to render your model. Enjoy the excitement of seeing the images becoming clearer and clearer ;-) In render mode, click on "Open Render Window", and you will be able to set the parameters to render your model. Enjoy the excitement of seeing the images becoming clearer and clearer ;-)
![light](window.png) ![light](render_mode/window.png)
## Moving Camera ## Moving Camera
...@@ -27,7 +27,7 @@ To freely move the camera without updating its field of view/aspect ratio to mat ...@@ -27,7 +27,7 @@ To freely move the camera without updating its field of view/aspect ratio to mat
To add lighting to the scene, simply go to the menu on the left side, click "New Light", and you will be able to choose from a variety of point objects and infinite environment lights. (To implement support for environment lights, see PathTracer task 7.) To add lighting to the scene, simply go to the menu on the left side, click "New Light", and you will be able to choose from a variety of point objects and infinite environment lights. (To implement support for environment lights, see PathTracer task 7.)
![light](light.png) ![light](render_mode/light.png)
Additionally, any object can be made into an emissive area light by changing its material to `Diffuse Light`. Mesh-based area lights can produce much more realistic lighting conditions. Additionally, any object can be made into an emissive area light by changing its material to `Diffuse Light`. Mesh-based area lights can produce much more realistic lighting conditions.
...@@ -35,16 +35,16 @@ Additionally, any object can be made into an emissive area light by changing its ...@@ -35,16 +35,16 @@ Additionally, any object can be made into an emissive area light by changing its
In Render mode, simply check the box for "Logged Rays", and you would be able to see the camera rays that you generated in task 1 when you start render. In Render mode, simply check the box for "Logged Rays", and you would be able to see the camera rays that you generated in task 1 when you start render.
![ray](ray_log.png) ![ray](render_mode/ray_log.png)
## Visualize BVH ## Visualize BVH
In Render mode, simply check the box for "BVH", and you would be able to see the BVH you generated in task 3 when you start rendering. You can click on the horizontal bar to see each level of your BVH. In Render mode, simply check the box for "BVH", and you would be able to see the BVH you generated in task 3 when you start rendering. You can click on the horizontal bar to see each level of your BVH.
![ray](bvh.png) ![ray](render_mode/bvh.png)
## Materials and Other Object Options ## Materials and Other Object Options
You can change the material and other property of your mesh by selecting the object and choose "Edit Pose", "Edit Mesh", and "Edit Material". For example, you can make a colored cow by "Edit Material" -> "Diffuse light", and pick a color that you like. You can change the material and other property of your mesh by selecting the object and choose "Edit Pose", "Edit Mesh", and "Edit Material". For example, you can make a colored cow by "Edit Material" -> "Diffuse light", and pick a color that you like.
![material](material.png) ![material](render_mode/material.png)
...@@ -14,12 +14,12 @@ Select the `Rig` tab to create a skeletal rig for an object. ...@@ -14,12 +14,12 @@ Select the `Rig` tab to create a skeletal rig for an object.
You can create new bone by first selecting a parent joint and pressing `New Bone`, then click anywhere else on the object to place the bone. From thereon, you can repeat this process to create a chain of bones connected along the selected joint. You can create new bone by first selecting a parent joint and pressing `New Bone`, then click anywhere else on the object to place the bone. From thereon, you can repeat this process to create a chain of bones connected along the selected joint.
If you want to branch off at a joint, simply click on the joint to branch off of, then start another chain by adding a new bone from there. If you want to branch off at a joint, simply click on the joint to branch off of, then start another chain by adding a new bone from there.
<video src="{{ site.baseurl }}/guide/rigging_mode/guide-rigging-1.mov" controls preload muted loop style="max-width: 100%; margin: 0 auto;"></video> <video src="rigging_mode/guide-rigging-1.mov" controls preload muted loop style="max-width: 100%; margin: 0 auto;"></video>
To view a rigged example, see `media/human.dae` example and select the object in the Rig tab to view its joints. To view a rigged example, see `media/human.dae` example and select the object in the Rig tab to view its joints.
Once you've implemented forward kinematics the skeleton should be setup like so: Once you've implemented forward kinematics the skeleton should be setup like so:
![rigged-human](guide-rigging-human.png) ![rigged-human](rigging_mode/guide-rigging-human.png)
...@@ -27,18 +27,18 @@ Once you've implemented forward kinematics the skeleton should be setup like so: ...@@ -27,18 +27,18 @@ Once you've implemented forward kinematics the skeleton should be setup like so:
Each joint has an associated `Radius` which controls the part of the mesh influenced by the selected bone during animaton. The radius is visualized by the blue capsule around each bone and can be edited using the menu. The position of the joint can also be edited using the `Extent` values in the menu. Each joint has an associated `Radius` which controls the part of the mesh influenced by the selected bone during animaton. The radius is visualized by the blue capsule around each bone and can be edited using the menu. The position of the joint can also be edited using the `Extent` values in the menu.
<video src="{{ site.baseurl }}/guide/rigging_mode/guide-rigging-2.mov" controls preload muted loop style="max-width: 100%; margin: 0 auto;"></video> <video src="rigging_mode/guide-rigging-2.mov" controls preload muted loop style="max-width: 100%; margin: 0 auto;"></video>
Note that rigging only uses extents of the bone for skeleton setup, joint pose does not influence the skeleton. Once rigging is done, the object can be posed by changing joint rotations in the [animate](../animate_mode) mode. Note that rigging only uses extents of the bone for skeleton setup, joint pose does not influence the skeleton. Once rigging is done, the object can be posed by changing joint rotations in the [animate](animate) mode.
## Inverse Kinematics ## Inverse Kinematics
Instead of computing the positions of the bones from the joint poses (forward kinematics), in inverse kinematics, joint positions are computed from target positions. Instead of computing the positions of the bones from the joint poses (forward kinematics), in inverse kinematics, joint positions are computed from target positions.
To associate a target position with a joint, select `Add IK` and edit the target position. Multiple target positions can be associated with the same joint but targets need to be explicitly enabled using the checkbox. To associate a target position with a joint, select `Add IK` and edit the target position. Multiple target positions can be associated with the same joint but targets need to be explicitly enabled using the checkbox.
In the [animate](../animate_mode) mode, once inverse kinematics is implemented, joint rotation(pose) is updated based on the enabled IK handles. In the [animate](animate) mode, once inverse kinematics is implemented, joint rotation(pose) is updated based on the enabled IK handles.
<video src="{{ site.baseurl }}/guide/rigging_mode/guide-ik.mp4" controls preload muted loop style="max-width: 100%; margin: 0 auto;"></video> <video src="rigging_mode/guide-ik.mp4" controls preload muted loop style="max-width: 100%; margin: 0 auto;"></video>
......
...@@ -25,7 +25,7 @@ Once an enabled emitter is added to the scene (and animation task 4: particle si ...@@ -25,7 +25,7 @@ Once an enabled emitter is added to the scene (and animation task 4: particle si
For example, the `particles.dae` test scene: For example, the `particles.dae` test scene:
<video src="{{ site.baseurl }}/guide/simulate_mode/guide-simulate-1.mp4" controls preload muted loop style="max-width: 100%; margin: 0 auto;"></video> <video src="simulate_mode/guide-simulate-1.mp4" controls preload muted loop style="max-width: 100%; margin: 0 auto;"></video>
Finally, note that you can render particles just like any other scene objects. Rendering `particles.dae` with depth of field: Finally, note that you can render particles just like any other scene objects. Rendering `particles.dae` with depth of field:
......
...@@ -15,13 +15,13 @@ constitutes the majority of the coursework for 15-462/662 (Computer Graphics) at ...@@ -15,13 +15,13 @@ constitutes the majority of the coursework for 15-462/662 (Computer Graphics) at
These pages describe how to set up and use Scotty3D. Start here! These pages describe how to set up and use Scotty3D. Start here!
- [Git Setup](git): create a private git mirror that can pull changes from Scotty3D. - [Git Setup](git): create a private git mirror that can pull changes from Scotty3D.
- [Building Scotty3D](build): build and run Scotty3D on various platforms. - [Building Scotty3D](building): build and run Scotty3D on various platforms.
- [User Guide](guide): learn the intended functionality for end users. - [User Guide](guide/guide): learn the intended functionality for end users.
The developer manual describes what you must implement to complete Scotty3D. It is organized under the three main components of the software: The developer manual describes what you must implement to complete Scotty3D. It is organized under the three main components of the software:
- [MeshEdit](meshedit) - [MeshEdit](meshedit/overview)
- [PathTracer](pathtracer) - [PathTracer](pathtracer/overview)
- [Animation](animation) - [Animation](animation/overview)
## Project Philosophy ## Project Philosophy
...@@ -31,7 +31,7 @@ Scotty3D, which is a modern package for 3D modeling, rendering, and animation. ...@@ -31,7 +31,7 @@ Scotty3D, which is a modern package for 3D modeling, rendering, and animation.
In terms of basic structure, this package doesn't look much different from In terms of basic structure, this package doesn't look much different from
"real" 3D tools like Maya, Blender, modo, or Houdini. Your overarching goal is "real" 3D tools like Maya, Blender, modo, or Houdini. Your overarching goal is
to use the developer manual to implement a package that to use the developer manual to implement a package that
works as described in the [User Guide](guide), much as you would at a real works as described in the [User Guide](guide/guide), much as you would at a real
software company (more details below). software company (more details below).
Note that the User Guide is **not** an Assignment Writeup. The User Guide Note that the User Guide is **not** an Assignment Writeup. The User Guide
......
...@@ -17,7 +17,7 @@ The methods that update the connectivity are `HalfedgeMesh::bevel_vertex`, `half ...@@ -17,7 +17,7 @@ The methods that update the connectivity are `HalfedgeMesh::bevel_vertex`, `half
`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. `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).** 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](../guide/model).**
To update the _geometry_ of a beveled element, you are provided with the following data: To update the _geometry_ of a beveled element, you are provided with the following data:
...@@ -35,7 +35,7 @@ Also note that we provide code to gather the halfedges contained in the beveled ...@@ -35,7 +35,7 @@ Also note that we provide code to gather the halfedges contained in the beveled
The reason for storing `new_halfedges` and `start_positions` in an array is that it makes it easy to access positions "to the left" and "to the right" of a given vertex. For instance, suppose we want to figure out the offset from the corner of a polygon. We might want to compute some geometric quantity involving the three vertex positions `start_positions[i-1]`, `start_positions[i]`, and `start_positions[i+1]` (as well as `inset`), then set the new vertex position `new_halfedges[i]->vertex()->pos` to this new value: The reason for storing `new_halfedges` and `start_positions` in an array is that it makes it easy to access positions "to the left" and "to the right" of a given vertex. For instance, suppose we want to figure out the offset from the corner of a polygon. We might want to compute some geometric quantity involving the three vertex positions `start_positions[i-1]`, `start_positions[i]`, and `start_positions[i+1]` (as well as `inset`), then set the new vertex position `new_halfedges[i]->vertex()->pos` to this new value:
<center><img src="bevel_diagram.png"></center> <center><img src="local/bevel/bevel_diagram.png"></center>
A useful trick here is _modular arithmetic_: since we really have a "loop" of vertices, we want to make sure that indexing the next element (+1) and the previous element (-1) properly "wraps around." This can be achieved via code like A useful trick here is _modular arithmetic_: since we really have a "loop" of vertices, we want to make sure that indexing the next element (+1) and the previous element (-1) properly "wraps around." This can be achieved via code like
......
...@@ -8,16 +8,16 @@ permalink: /meshedit/global/catmull/ ...@@ -8,16 +8,16 @@ permalink: /meshedit/global/catmull/
# Catmull-Clark Subdivision # Catmull-Clark Subdivision
For an in-practice example, see the [User Guide](/Scotty3D/guide/model_mode). For an in-practice example, see the [User Guide](../guide/model).
The only difference between Catmull-Clark and [linear](../linear) subdivision is the choice of positions for new vertices. Whereas linear subdivision simply takes a uniform average of the old vertex positions, Catmull-Clark uses a very carefully-designed _weighted_ average to ensure that the surface converges to a nice, round surface as the number of subdivision steps increases. The original scheme is described in the paper _"Recursively generated B-spline surfaces on arbitrary topological meshes"_ by (Pixar co-founder) Ed Catmull and James Clark. Since then, the scheme has been thoroughly discussed, extended, and analyzed; more modern descriptions of the algorithm may be easier to read, including those from the [Wikipedia](https://en.wikipedia.org/wiki/Catmull-Clark_subdivision_surface) and [this webpage](http://www.rorydriscoll.com/2008/08/01/catmull-clark-subdivision-the-basics/). In short, the new vertex positions can be calculated by: The only difference between Catmull-Clark and [linear](linear) subdivision is the choice of positions for new vertices. Whereas linear subdivision simply takes a uniform average of the old vertex positions, Catmull-Clark uses a very carefully-designed _weighted_ average to ensure that the surface converges to a nice, round surface as the number of subdivision steps increases. The original scheme is described in the paper _"Recursively generated B-spline surfaces on arbitrary topological meshes"_ by (Pixar co-founder) Ed Catmull and James Clark. Since then, the scheme has been thoroughly discussed, extended, and analyzed; more modern descriptions of the algorithm may be easier to read, including those from the [Wikipedia](https://en.wikipedia.org/wiki/Catmull-Clark_subdivision_surface) and [this webpage](http://www.rorydriscoll.com/2008/08/01/catmull-clark-subdivision-the-basics/). In short, the new vertex positions can be calculated by:
1. setting the new vertex position at each face f to the average of all its original vertices (exactly as in linear subdivision), 1. setting the new vertex position at each face f to the average of all its original vertices (exactly as in linear subdivision),
2. setting the new vertex position at each edge e to the average of the new face positions (from step 1) and the original endpoint positions, and 2. setting the new vertex position at each edge e to the average of the new face positions (from step 1) and the original endpoint positions, and
3. setting the new vertex position at each vertex v to the weighted sum 3. setting the new vertex position at each vertex v to the weighted sum
<center><img src="catmull_clark_positions.png" style="height:80px"></center> <center><img src="global/catmull/catmull_clark_positions.png" style="height:80px"></center>
where _n_ is the degree of vertex _v_ (i.e., the number of faces containing _v_), and where _n_ is the degree of vertex _v_ (i.e., the number of faces containing _v_), and
......
...@@ -19,7 +19,7 @@ We now consider the case of a triangle-triangle edge flip. ...@@ -19,7 +19,7 @@ We now consider the case of a triangle-triangle edge flip.
Suppose we have a pair of triangles (a,b,c) and (c,b,d). After flipping the edge (b,c), we should now have triangles (a,d,c) and (a,b,d). A good first step for implementing any local mesh operation is to draw a diagram that clearly labels all elements affected by the operation: Suppose we have a pair of triangles (a,b,c) and (c,b,d). After flipping the edge (b,c), we should now have triangles (a,d,c) and (a,b,d). A good first step for implementing any local mesh operation is to draw a diagram that clearly labels all elements affected by the operation:
<center><img src="edge_flip_diagram.png"></center> <center><img src="./local/edge_flip_diagram.png"></center>
Here we have drawn a diagram of the region around the edge both before and after the edge operation (in this case, "flip"), labeling each type of element (halfedge, vertex, edge, and face) from zero to the number of elements. It is important to include every element affected by the operation, thinking very carefully about which elements will be affected. If elements are omitted during this phase, everything will break---even if the code written in the two phases is correct! In this example, for instance, we need to remember to include the halfedges "outside" the neighborhood, since their "twin" pointers will be affected. Here we have drawn a diagram of the region around the edge both before and after the edge operation (in this case, "flip"), labeling each type of element (halfedge, vertex, edge, and face) from zero to the number of elements. It is important to include every element affected by the operation, thinking very carefully about which elements will be affected. If elements are omitted during this phase, everything will break---even if the code written in the two phases is correct! In this example, for instance, we need to remember to include the halfedges "outside" the neighborhood, since their "twin" pointers will be affected.
......
...@@ -10,7 +10,7 @@ nav_order: 2 ...@@ -10,7 +10,7 @@ nav_order: 2
# Global Mesh Operations # Global Mesh Operations
In addition to local operations on mesh connectivity, Scotty3D provides several global remeshing operations (as outlined in the [User Guide](/Scotty3D/guide/model_mode)). Two different mechanisms are used to implement global operations: In addition to local operations on mesh connectivity, Scotty3D provides several global remeshing operations (as outlined in the [User Guide](../guide/model)). Two different mechanisms are used to implement global operations:
* _Repeated application of local operations._ Some mesh operations are most easily expressed by applying local operations (edge flips, etc.) to a sequence of mesh elements until the target output is achieved. A good example is [mesh simplification](simplify), which is a greedy algorithm that collapses one edge at a time. * _Repeated application of local operations._ Some mesh operations are most easily expressed by applying local operations (edge flips, etc.) to a sequence of mesh elements until the target output is achieved. A good example is [mesh simplification](simplify), which is a greedy algorithm that collapses one edge at a time.
* _Global replacement of the mesh._ Other mesh operations are better expressed by temporarily storing new mesh elements in a simpler mesh data structure (e.g., an indexed list of faces) and completely re-building the halfedge data structure from this data. A good example is [Catmull-Clark subdivision](catmull), where every polygon must be simultaneously split into quadrilaterals. * _Global replacement of the mesh._ Other mesh operations are better expressed by temporarily storing new mesh elements in a simpler mesh data structure (e.g., an indexed list of faces) and completely re-building the halfedge data structure from this data. A good example is [Catmull-Clark subdivision](catmull), where every polygon must be simultaneously split into quadrilaterals.
......
...@@ -8,7 +8,7 @@ grand_parent: "A2: MeshEdit" ...@@ -8,7 +8,7 @@ grand_parent: "A2: MeshEdit"
# Linear Subdivision # Linear Subdivision
For an in-practice example, see the [User Guide](/Scotty3D/guide/model_mode). For an in-practice example, see the [User Guide](../guide/model).
Unlike most other global remeshing operations, linear (and Catmull-Clark) subdivision will proceed by completely replacing the original halfedge mesh with a new one. The high-level procedure is: Unlike most other global remeshing operations, linear (and Catmull-Clark) subdivision will proceed by completely replacing the original halfedge mesh with a new one. The high-level procedure is:
...@@ -20,7 +20,7 @@ Given these lists, `Halfedge_Mesh::from_poly` will take care of allocating halfe ...@@ -20,7 +20,7 @@ Given these lists, `Halfedge_Mesh::from_poly` will take care of allocating halfe
Both linear and Catmull-Clark subdivision schemes will handle general _n_-gons (i.e., polygons with _n_ sides) rather than, say, quads only or triangles only. Each _n_-gon (including but not limited to quadrilaterals) will be split into _n_ quadrilaterals according to the following template: Both linear and Catmull-Clark subdivision schemes will handle general _n_-gons (i.e., polygons with _n_ sides) rather than, say, quads only or triangles only. Each _n_-gon (including but not limited to quadrilaterals) will be split into _n_ quadrilaterals according to the following template:
<center><img src="subdivide_quad.png" style="height:220px"></center> <center><img src="global/linear/subdivide_quad.png" style="height:220px"></center>
The high-level procedure is outlined in greater detail in `student/meshedit.cpp`. The high-level procedure is outlined in greater detail in `student/meshedit.cpp`.
......
...@@ -27,52 +27,52 @@ To facilitate user interaction, as well as global mesh processing operations (de ...@@ -27,52 +27,52 @@ To facilitate user interaction, as well as global mesh processing operations (de
Also, remember that in any case, _the program should not crash!_ So for instance, you should never return a pointer to an element that was deleted. Also, remember that in any case, _the program should not crash!_ So for instance, you should never return a pointer to an element that was deleted.
See the [User Guide](/Scotty3D/guide/model_mode) for demonstrations of each local operation. See the [User Guide](../guide/model) for demonstrations of each local operation.
* `Halfedge_Mesh::flip_edge` - should return the edge that was flipped * `Halfedge_Mesh::flip_edge` - should return the edge that was flipped
![](flip_edge.svg) ![](local/flip_edge.svg)
* `Halfedge_Mesh::split_edge` - should return the inserted vertex * `Halfedge_Mesh::split_edge` - should return the inserted vertex
![](split_edge.svg) ![](local/split_edge.svg)
* `Halfedge_Mesh::bisect_edge` - should bisect the edge and return the inserted vertex * `Halfedge_Mesh::bisect_edge` - should bisect the edge and return the inserted vertex
![](bisect_edge.svg) ![](local/bisect_edge.svg)
* `Halfedge_Mesh::collapse_edge` - should return the new vertex, corresponding to the collapsed edge * `Halfedge_Mesh::collapse_edge` - should return the new vertex, corresponding to the collapsed edge
![](collapse_edge.svg) ![](local/collapse_edge.svg)
* `Halfedge_Mesh::collapse_face` - should return the new vertex, corresponding to the collapsed face * `Halfedge_Mesh::collapse_face` - should return the new vertex, corresponding to the collapsed face
![](collapse_face.svg) ![](local/collapse_face.svg)
* `Halfedge_Mesh::inset_vertex` - should return the newly inserted vertex * `Halfedge_Mesh::inset_vertex` - should return the newly inserted vertex
![](inset_vertex.svg) ![](local/inset_vertex.svg)
* `Halfedge_Mesh::erase_vertex` - should return the new face, corresponding to the faces originally containing the vertex * `Halfedge_Mesh::erase_vertex` - should return the new face, corresponding to the faces originally containing the vertex
![](erase_vertex.svg) ![](local/erase_vertex.svg)
* `Halfedge_Mesh::erase_edge` - should return the new face, corresponding to the faces originally containing the edge * `Halfedge_Mesh::erase_edge` - should return the new face, corresponding to the faces originally containing the edge
![](erase_edge.svg) ![](local/erase_edge.svg)
* `Halfedge_Mesh::bevel_vertex` - should return the new face, corresponding to the beveled vertex * `Halfedge_Mesh::bevel_vertex` - should return the new face, corresponding to the beveled vertex
![](bevel_vertex.svg) ![](local/bevel_vertex.svg)
* `Halfedge_Mesh::bevel_edge` - should return the new face, corresponding to the beveled edge * `Halfedge_Mesh::bevel_edge` - should return the new face, corresponding to the beveled edge
![](bevel_edge.svg) ![](local/bevel_edge.svg)
* `Halfedge_Mesh::bevel_face` / `Halfedge_Mesh::extrude_face` / `Halfedge_Mesh::inset_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) ![](local/bevel_face.svg)
* `Halfedge_Mesh::extrude_vertex` - should return the new vertex * `Halfedge_Mesh::extrude_vertex` - should return the new vertex
![](extrude_vertex.svg) ![](local/extrude_vertex.svg)
\ No newline at end of file \ No newline at end of file
...@@ -8,7 +8,7 @@ grand_parent: "A2: MeshEdit" ...@@ -8,7 +8,7 @@ grand_parent: "A2: MeshEdit"
# Loop Subdivision # Loop Subdivision
For an in-practice example, see the [User Guide](/Scotty3D/guide/model_mode). For an in-practice example, see the [User Guide](../guide/model).
Loop subdivision (named after [Charles Loop](http://charlesloop.com/)) is a standard approximating subdivision scheme for triangle meshes. At a high level, it consists of two basic steps: Loop subdivision (named after [Charles Loop](http://charlesloop.com/)) is a standard approximating subdivision scheme for triangle meshes. At a high level, it consists of two basic steps:
...@@ -17,11 +17,11 @@ Loop subdivision (named after [Charles Loop](http://charlesloop.com/)) is a stan ...@@ -17,11 +17,11 @@ Loop subdivision (named after [Charles Loop](http://charlesloop.com/)) is a stan
The 4-1 subdivision looks like this: The 4-1 subdivision looks like this:
![4-1 Subdivision](loop_41.png) ![4-1 Subdivision](global/loop/loop_41.png)
And the following picture illustrates the weighted average: And the following picture illustrates the weighted average:
![Loop subdivision weights](loop_weights.png) ![Loop subdivision weights](global/loop/loop_weights.png)
In words, the new position of an old vertex is (1 - nu) times the old position + u times the sum of the positions of all of its neighbors. The new position for a newly created vertex v that splits Edge AB and is flanked by opposite vertices C and D across the two faces connected to AB in the original mesh will be 3/8 * (A + B) + 1/8 * (C + D). If we repeatedly apply these two steps, we will converge to a fairly smooth approximation of our original mesh. In words, the new position of an old vertex is (1 - nu) times the old position + u times the sum of the positions of all of its neighbors. The new position for a newly created vertex v that splits Edge AB and is flanked by opposite vertices C and D across the two faces connected to AB in the original mesh will be 3/8 * (A + B) + 1/8 * (C + D). If we repeatedly apply these two steps, we will converge to a fairly smooth approximation of our original mesh.
...@@ -32,7 +32,7 @@ We will implement Loop subdivision as the `Halfedge_Mesh::loop_subdivide()` meth ...@@ -32,7 +32,7 @@ We will implement Loop subdivision as the `Halfedge_Mesh::loop_subdivide()` meth
The following pictures (courtesy Denis Zorin) illustrate this idea: The following pictures (courtesy Denis Zorin) illustrate this idea:
![Subdivision via flipping](loop_flipping.png) ![Subdivision via flipping](global/loop/loop_flipping.png)
Notice that only blue (and not black) edges are flipped in this procedure; as described above, edges in the split mesh should be flipped if and only if they touch both an original vertex _and_ a new vertex (i.e., a midpoint of an original edge). Notice that only blue (and not black) edges are flipped in this procedure; as described above, edges in the split mesh should be flipped if and only if they touch both an original vertex _and_ a new vertex (i.e., a midpoint of an original edge).
......
...@@ -17,14 +17,14 @@ The following sections contain guidelines for implementing the functionality of ...@@ -17,14 +17,14 @@ The following sections contain guidelines for implementing the functionality of
- [Halfedge Mesh](halfedge) - [Halfedge Mesh](halfedge)
- [Local Mesh Operations](local) - [Local Mesh Operations](local)
- [Tutorial: Edge Flip](local/edge_flip) - [Tutorial: Edge Flip](edge_flip)
- [Beveling](local/bevel) - [Beveling](bevel)
- [Global Mesh Operations](global) - [Global Mesh Operations](global)
- [Triangulation](global/triangulate) - [Triangulation](triangulate)
- [Linear Subdivision](global/linear) - [Linear Subdivision](linear)
- [Catmull-Clark Subdivision](global/catmull) - [Catmull-Clark Subdivision](catmull)
- [Loop Subdivision](global/loop) - [Loop Subdivision](loop)
- [Isotropic Remeshing](global/remesh) - [Isotropic Remeshing](remesh)
- [Simplification](global/simplify) - [Simplification](simplify)
As always, be mindful of the [project philosophy](..). As always, be mindful of the [project philosophy](..).
...@@ -8,7 +8,7 @@ grand_parent: "A2: MeshEdit" ...@@ -8,7 +8,7 @@ grand_parent: "A2: MeshEdit"
# Isotropic Remeshing # Isotropic Remeshing
For an in-practice example, see the [User Guide](/Scotty3D/guide/model_mode). For an in-practice example, see the [User Guide](../guide/model).
Scotty3D also supports remeshing, an operation that keeps the number of samples roughly the same while improving the shape of individual triangles. The isotropic remeshing algorithm tries to make the mesh as "uniform" as possible, i.e., triangles as close as possible to equilateral triangles of equal size, and vertex degrees as close as possible to 6 (note: this algorithm is for **triangle meshes only**). The algorithm to be implemented is based on the paper [Botsch and Kobbelt, "A Remeshing Approach to Multiresolution Modeling"](https://www.graphics.rwth-aachen.de/media/papers/remeshing1.pdf) (Section 4), and can be summarized in just a few simple steps: Scotty3D also supports remeshing, an operation that keeps the number of samples roughly the same while improving the shape of individual triangles. The isotropic remeshing algorithm tries to make the mesh as "uniform" as possible, i.e., triangles as close as possible to equilateral triangles of equal size, and vertex degrees as close as possible to 6 (note: this algorithm is for **triangle meshes only**). The algorithm to be implemented is based on the paper [Botsch and Kobbelt, "A Remeshing Approach to Multiresolution Modeling"](https://www.graphics.rwth-aachen.de/media/papers/remeshing1.pdf) (Section 4), and can be summarized in just a few simple steps:
......
...@@ -10,7 +10,7 @@ grand_parent: "A2: MeshEdit" ...@@ -10,7 +10,7 @@ grand_parent: "A2: MeshEdit"
![Surface simplification via quadric error metric](quad_simplify.png) ![Surface simplification via quadric error metric](quad_simplify.png)
For an in-practice example, see the [User Guide](/Scotty3D/guide/model_mode). For an in-practice example, see the [User Guide](../guide/model).
Just as with images, meshes often have far more samples than we really need. The simplification method in Scotty3D simplifies a given triangle mesh by applying _quadric error simplification_ (note that this method is for **triangle meshes only**!). This method was originally developed at CMU by Michael Garland and Paul Heckbert, in their paper [Surface Simplification Using Quadric Error Metrics](http://www.cs.cmu.edu/~./garland/quadrics/quadrics.html). (Looking at this paper -- or the many slides and presentations online that reference it -- may be very helpful in understanding and implementing this part of the assignment!) Just as with images, meshes often have far more samples than we really need. The simplification method in Scotty3D simplifies a given triangle mesh by applying _quadric error simplification_ (note that this method is for **triangle meshes only**!). This method was originally developed at CMU by Michael Garland and Paul Heckbert, in their paper [Surface Simplification Using Quadric Error Metrics](http://www.cs.cmu.edu/~./garland/quadrics/quadrics.html). (Looking at this paper -- or the many slides and presentations online that reference it -- may be very helpful in understanding and implementing this part of the assignment!)
......
...@@ -8,7 +8,7 @@ grand_parent: "A2: MeshEdit" ...@@ -8,7 +8,7 @@ grand_parent: "A2: MeshEdit"
# Triangulation # Triangulation
For an in-practice example, see the [User Guide](/Scotty3D/guide/model_mode). For an in-practice example, see the [User Guide](../guide/model).
A variety of geometry processing algorithms become easier to implement (or are only well defined) when the input consists purely of triangles. The method `Halfedge_Mesh::triangulate` converts any polygon mesh into a triangle mesh by splitting each polygon into triangles. A variety of geometry processing algorithms become easier to implement (or are only well defined) when the input consists purely of triangles. The method `Halfedge_Mesh::triangulate` converts any polygon mesh into a triangle mesh by splitting each polygon into triangles.
...@@ -16,7 +16,7 @@ This transformation is performed in-place, i.e., the original mesh data is repla ...@@ -16,7 +16,7 @@ This transformation is performed in-place, i.e., the original mesh data is repla
There is more than one way to split a polygon into triangles. Two common patterns are to connect every vertex to a single vertex, or to "zig-zag" the triangulation across the polygon: There is more than one way to split a polygon into triangles. Two common patterns are to connect every vertex to a single vertex, or to "zig-zag" the triangulation across the polygon:
<center><img src="triangulate.png" style="height:300px"></center> <center><img src="global/triangulate/triangulate.png" style="height:300px"></center>
The `triangulate` routine is not required to produce any particular triangulation so long as: The `triangulate` routine is not required to produce any particular triangulation so long as:
......
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