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.
@@ -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 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.
`Add Frames` inserts 90 empty frames into the timeline. `Crop End` deletes frames from the selected location to the end of the timeline.
### 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.
Note that IK handles need to be explicitly enabled using the checkbox.
@@ -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.
-`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
...
...
@@ -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.
- 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
...
...
@@ -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).
- 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.
- Triangulate: Each polygon is split into triangles.
@@ -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 ;-)
![light](window.png)
![light](render_mode/window.png)
## Moving Camera
...
...
@@ -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.)
![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.
...
...
@@ -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.
![ray](ray_log.png)
![ray](render_mode/ray_log.png)
## 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.
![ray](bvh.png)
![ray](render_mode/bvh.png)
## 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.
@@ -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.
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.
@@ -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.
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
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.
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.
@@ -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.
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:
...
...
@@ -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:
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
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),
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
@@ -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:
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.
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.
* _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.
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:
...
...
@@ -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:
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:
...
...
@@ -17,11 +17,11 @@ Loop subdivision (named after [Charles Loop](http://charlesloop.com/)) is a stan
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:
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
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).
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:
![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!)
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.
...
...
@@ -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: