Commit 77a6b9ea authored by allai5's avatar allai5
Browse files

new docs dump

parent cbbc4fa0
---
layout: default
title: Home
nav_order: 1
---
<!--![15-462 F20 Renders](results/me_f20.png)-->
<!--![15-462 F20 Renders](results/pt_f20_2.png)-->
![15-462 F20 Renders](results/me_f20_crop.png)
# Scotty3D
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
constitutes the majority of the coursework for 15-462/662 (Computer Graphics) at Carnegie Mellon University
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.
- [User Guide](guide): learn the intended functionality for end users.
......@@ -48,18 +56,18 @@ solution that meets a few fundamental criteria:
* [Failing gracefully](https://en.wikipedia.org/wiki/Fault_tolerance) is
preferable to failing utterly---for instance, if a rare corner case is difficult
to handle, it is far better to simply refuse to perform the operation than to
let the program crash!
let the program crash!
* Your implementation should follow the [principle of least
surprise](https://en.wikipedia.org/wiki/Principle_of_least_astonishment). A user
should be able to expect that things behave more or less as they are described
in the User Guide.
in the User Guide.
* You should not use an algorithm whose performance is [asymptotically
worse](https://en.wikipedia.org/wiki/Asymptotic_computational_complexity) just
because it makes your code easier to write (for instance, using [bubble
sort](https://en.wikipedia.org/wiki/Bubble_sort) rather than [merge
sort](https://en.wikipedia.org/wiki/Merge_sort) on large data sets).
sort](https://en.wikipedia.org/wiki/Merge_sort) on large data sets).
* That being said, when it comes to performance, [premature optimization is
the root of all evil!](https://en.wikipedia.org/wiki/Program_optimization#When_to_optimize) The only way to know whether an optimization matters is to [measure performance](https://en.wikipedia.org/wiki/Profiling_(computer_programming)), and understand [bottlenecks](https://en.wikipedia.org/wiki/Program_optimization#Bottlenecks).
the root of all evil!](https://en.wikipedia.org/wiki/Program_optimization#When_to_optimize) The only way to know whether an optimization matters is to [measure performance](https://en.wikipedia.org/wiki/Profiling_(computer_programming)), and understand [bottlenecks](https://en.wikipedia.org/wiki/Program_optimization#Bottlenecks).
* Finally, you should take pride in your craft. Beautiful things just tend to work better.
Just to reiterate the main point above:
......@@ -75,5 +83,5 @@ good design choices with you, and you should also feel free to discuss these
choices with your classmates. Practically speaking, it is ok for routines to
simply show an error if they encounter a rare and difficult corner case---as long as it
does not interfere with successful operation of the program (i.e., if it does
not crash or yield bizarre behavior). Your main goal here above all else should be
not crash or yield bizarre behavior). Your main goal here above all else should be
to develop _effective tool for modeling, rendering, and animation_.
---
layout: default
title: "Local Ops: Beveling"
permalink: /meshedit/bevel/
title: "Bevelling"
permalink: /meshedit/local/bevel/
parent: "Local Operations"
grand_parent: "A2: MeshEdit"
---
# Beveling
# Beveling
Here we provide some additional detail about the bevel operations and their implementation in Scotty3D. Each bevel operation has two components:
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::bevel_edge_positions`, and `HalfedgeMesh::bevel_face_positions`.
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).**
......@@ -31,13 +33,13 @@ 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:
![BevelIndexing](bevel_indexing.png)
<center><img src="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
// Get the number of vertices in the new polygon
int N = (int)hs.size();
// Assuming we're looking at vertex i, compute the indices
// of the next and previous elements in the list using
// modular arithmetic---note that to get the previous index,
......@@ -47,7 +49,7 @@ A useful trick here is _modular arithmetic_: since we really have a "loop" of ve
int a = (i+N-1) % N;
int b = i;
int c = (i+1) % N;
// Get the actual 3D vertex coordinates at these vertices
Vec3 pa = start_positions[a];
Vec3 pb = start_positions[b];
......
---
layout: default
title: "Catmull-Clark Subdivision"
parent: Global Operations
grand_parent: "A2: MeshEdit"
permalink: /meshedit/global/catmull/
---
......@@ -12,9 +14,11 @@ The only difference between Catmull-Clark and [linear](../linear) subdivision is
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
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>
![catmull clark positions](catmull_clark_positions.png)
where _n_ is the degree of vertex _v_ (i.e., the number of faces containing _v_), and
......
---
layout: default
title: "Edge Flip Tutorial"
permalink: /meshedit/edge_flip
permalink: /meshedit/local/edge_flip
nav_order: 1
parent: Local Operations
grand_parent: "A2: MeshEdit"
---
# Edge Flip Tutorial
......@@ -12,15 +15,15 @@ Here we provide a step-by-step guide to implementing a simplified version of the
We now consider the case of a triangle-triangle edge flip.
#### PHASE 0: Draw a Diagram
### PHASE 0: Draw a Diagram
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:
![](edge_flip_before_after.png)
<center><img src="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.
#### PHASE I: Collect elements
### PHASE I: Collect elements
Once you've drawn your diagram, simply collect all the elements from the "before" picture. Give them the same names as in your diagram, so that you can debug your code by comparing with the picture.
......@@ -35,22 +38,22 @@ Once you've drawn your diagram, simply collect all the elements from the "before
HalfedgeRef h7 = h2->twin();
HalfedgeRef h8 = h4->twin();
HalfedgeRef h9 = h5->twin();
// VERTICES
VertexRef v0 = h0->vertex();
VertexRef v1 = h3->vertex();
// ...you fill in the rest!...
// EDGES
EdgeRef e1 = h5->edge();
EdgeRef e2 = h4->edge();
// ...you fill in the rest!...
// FACES
FaceRef f0 = h0->face();
// ...you fill in the rest!...
#### PHASE II: Allocate new elements
### PHASE II: Allocate new elements
If your edge operation requires new elements, now is the time to allocate them. For the edge flip, we don't need any new elements; but suppose that for some reason we needed a new vertex v4\. At this point we would allocate the new vertex via
......@@ -58,7 +61,7 @@ If your edge operation requires new elements, now is the time to allocate them.
(The name used for this new vertex should correspond to the label you give it in your "after" picture.) Likewise, new edges, halfedges, and faces can be allocated via the methods `mesh.new_edge()`, `mesh.new_halfedge()`, and `mesh.new_face()`.
#### PHASE III: Reassign Elements
### PHASE III: Reassign Elements
Next, update the pointers for all the mesh elements that are affected by the edge operation. Be exhaustive! In other words, go ahead and specify every pointer for every element, even if it did not change. Once things are working correctly, you can always optimize by removing unnecessary assignments. But get it working correctly first! Correctness is more important than efficiency.
......@@ -74,27 +77,27 @@ Next, update the pointers for all the mesh elements that are affected by the edg
h1->edge() = e3;
h1->face() = f0;
// ...you fill in the rest!...
// ...and don't forget about the "outside" elements!...
h9->next() = h9->next(); // didn't change, but set it anyway!
h9->twin() = h4;
h9->vertex() = v1;
h9->edge() = e1;
h9->face() = h9->face(); // didn't change, but set it anyway!
// VERTICES
v0->halfedge() = h2;
v1->halfedge() = h5;
v2->halfedge() = h4;
v3->halfedge() = h3;
// EDGES
e0->halfedge() = h0; //...you fill in the rest!...
// FACES
f0->halfedge() = h0; //...you fill in the rest!...
#### PHASE IV: Delete unused elements
### PHASE IV: Delete unused elements
If your edge operation eliminates elements, now is the best time to deallocate them: at this point, you can be sure that they are no longer needed. For instance, since we do not need the vertex allocated in PHASE II, we could write
......@@ -102,7 +105,7 @@ If your edge operation eliminates elements, now is the best time to deallocate t
You should be careful that this mesh element is not referenced by any other element in the mesh. But if your "before" and "after" diagrams are correct, that should not be an issue!
#### Design considerations
### Design considerations
The basic algorithm outlined above will handle most edge flips, but you should also think carefully about possible corner-cases. You should also think about other design issues, like "how much should this operation cost?" For instance, for this simple triangle-triangle edge flip it might be reasonable to:
......
---
layout: default
title: "MeshEdit Overview"
title: "Global Operations"
permalink: /meshedit/global/
parent: "A2: MeshEdit"
has_children: true
has_toc: false
nav_order: 2
---
# Global Mesh Operations
......@@ -23,4 +27,4 @@ Three subdivision schemes are supported by Scotty3D: [Linear](linear), [Catmull-
## Performance
All subdivision operations, as well as re-meshing and simplification, should complete almost instantaneously (no more than a second) on meshes of a few hundred polygons or fewer. If performance is worse than this, ensure that implementations are not repeatedly iterating over more elements than needed, or allocating/deallocating more memory than necessary. A useful debugging technique is to print out (or otherwise keep track of, e.g., via an integer counter or a profiler) the number of times basic methods like `Halfedge::next()` or `Halfedge_Mesh::new_vertex()` are called during a single execution of one of the methods; for most methods this number should be some reasonably small constant (no more than, say, 1000!) times the number of elements in the mesh.
\ No newline at end of file
All subdivision operations, as well as re-meshing and simplification, should complete almost instantaneously (no more than a second) on meshes of a few hundred polygons or fewer. If performance is worse than this, ensure that implementations are not repeatedly iterating over more elements than needed, or allocating/deallocating more memory than necessary. A useful debugging technique is to print out (or otherwise keep track of, e.g., via an integer counter or a profiler) the number of times basic methods like `Halfedge::next()` or `Halfedge_Mesh::new_vertex()` are called during a single execution of one of the methods; for most methods this number should be some reasonably small constant (no more than, say, 1000!) times the number of elements in the mesh.
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