Torroidal Sweep of Drawn Shape
|CS 6491 Computer Graphics (Graduate)||Jarek Rossignac||Fall 2014||Java/Processing||No||Code N/A|
This was the biggest project for Jarek Rossignac's Graduate Computer Graphics class. As with a few other projects, I worked with another student on this, although I ended up implementing ~95% of the project by myself, as well as implementing some extra functionality, like free-form loops and rotational axes, that seemed to me to be "appropriate" for a tool like this. We had to support drawing two shapes and a rotational axis, and then implment various kinds of morphs between these shapes, which would be rotated around the axis (which might not be straight) to generate a lathed-like mesh.
The primary objective of this project is to generate a 3D mesh by revolving a 2D stroke about a spine. This simple idea is made more complex by including functionality to morph between two strokes, to define a variable thickness, and to bend the spine. The result produces very interesting 3D shapes. The concepts used in building this application have a variety of applications, such as designing parts using a computer aided design system, or animating a figure between two keyframes.
Our application lets the user define a series of weighted control points that define a variable thickness stroke. The weight at each point corresponds to the radius of the polyloop bounding the stroke at each point. The radius of each point is given an initial value based on the velocity of the mouse as the user was drawing the points. By default, slower mouse movements result in smaller radii, but we gave the option to invert this behavior. The user defined points are then smoothed and resampled, resulting in a fixed number of control points that are evenly spaced. Additionally, a linear interpolation is used to smooth the width of each point. We have implemented three different types of offsets to define the offset curve: normal, ball and radial.
The normal offset was the most trivial to implement. The offset polyloop positions are found by adding the normal, scaled by the radius, to the control point for each control point in the stroke. For the radial offset, instead of defining the polyloop positions based on the normals we compute them by finding the intersection points of circles centered at adjacent control points. For a point where there is a small overlap between that point’s circle and the adjacent point’s circle, the normal position is used for that point. For a large overlap, we find the two positions where the circles intersect and use those for the offset points. The ball offset is found similarly, however instead of having one circle centered on the control point, we define two circles tangent to the control point on either side of the stroke.
The 3D mesh is generated by sweeping the slices generated by the linear morph about the spine. A series of translations and rotations are used to orient the slices at evenly spaced positions about the spine. The rotation is reliant on using the canvas normal crossed with the tangent of the spine to get the binormal - this along with the canvas normal define the plane within which the rotation occurs. We use the original distance from the spine as a radius and the original distance along the spine to determine the rotational center.
While computing the positions needed to draw the mesh, we also compute the coloring to shade the model. We compute both per-vertex and per-face colors. The per-face coloring is used to shade the mesh with flat shading, and the per-vertex coloring allows us to shade the mesh with Gouraud shading. The color of the vertices for each slice is computed by linearly interpolating between red and green over the 180 degree sweep. Additionally, the end caps of the sweep are textured with a hatching pattern. This is accomplished by overlaying an image on the polyloop that defines the end slices. The image is positioned by computing texture coordinates for each vertex. The texture coordinates are computed by building a reference frame in the plane of the polygon, and every point of the polygon is then projected onto those axes to find the coordinates in the new frame.
To show the mesh as a wire frame, we draw edges between the points of the mesh instead of filling the triangles. Back-facing edges are colored in a light gray. We determine which edges are back facing by comparing the normal of that edge’s face with the direction of the vector from the eye to that edge. If the dot-product of those two vectors is negative, then that face is back-facing. Although our application colors the culled edges a lighter color, it does not check for the occlusion of front-facing edges.
Below are videos of the mesh-building and editing process, with links if the clips don't play :
|Various Offset Calculations|
|Qunitic Interpolated Strokes|
|Move Control Points in 3-D|
|Wire Frame Culling|