Overview
In this project you will implement a simple sketch-based modeling
system. The basic system supports two kinds of
primitives (or basic shapes): boxes
and cylinders. You can optionally add additional primitive types. Each
type of primitive is matched to a set of input
gestures, which are 2D strokes drawn by the user. The user can thus
create a 3D scene interactively by "sketching" various primitives.
In addition to sketching shapes with the left mouse button, the user
can move existing shapes
around using the middle button. Every shape is
given a constraint that limits how the shape moves when grabbed by the
user via the middle mouse button. Initially, each object is constrained
to move in the plane of the surface on which it was created. The user
can interactively define new constraints to move the object in a
different plane, or along a given direction. Primitives are organized
into a hierarchy via nested transforms. When a new primitive is
sketched on top of an existing one, it is added to the scene as a
"child" of the existing one, meaning it is defined in the coordinate
system of the existing primitive. When the existing one is moved, all
of its children automatically move with it. But when a child is moved,
it moves independently.
This project is loosely based on the SIGGRAPH 1996 paper:
SKETCH: An
Interface for Sketching 3D Scenes. (We will see the video in class.)
Support
Code
You are given support code for this project and will need to
- link to the jot library
(the same as for projects 1 and 2),
- copy the project support code, follow the instructions in the README file to compile, and
- implement the missing functionality.
For more information about
jot, see
the instructions given in
project 1.
Note: Jot was updated a bit for
this project. The previous versions should still work, but we recommend
you use the newer version for improved rendering and better handling of
input gestures. Pre-compiled jot on CAEN will be updated on 2/15 (after
students turn in project 2).
Copy the project support
code to your local machine. (On windows, you can execute the
following commands using cygwin, which we recommend):
% scp -r red.engin.umich.edu:/afs/engin.umich.edu/class/perm/eecs487/proj3 .
(Note the 'dot' at the end of line.) The above command overwrites all
proj3 files, including any files that
you may have made changes to. To copy 'old' versions of files while
leaving the new untouched (sync-ing operation):
% rsync -avz red.engin.umich.edu:/afs/engin.umich.edu/class/perm/eecs487/proj3 .
(Do this from the parent directory containing the proj3 subdirectory.)
On (CAEN) machines, windows users can copy the files from:
Z:\proj3
This assumes that you mounted the eecs487 directory on CAEN as
explained in the project 3
README. If you
mounted the network drive differently, change the above path
accordingly.
Tasks
The tasks and grading
scheme for this project are as follows:
- Implement the correct transform needed to scale and position a
box in the scene. (15 pts)
- Write code to generate mesh vertices and faces to form the shape
of a canonical cylinder. (15 pts)
- Implement the correct transform needed to scale and position a
cylinder in the scene. (15 pts)
- Fix the selection of 3D axes so that newly drawn axes align with
the natural features of the selected shape. (15 points)
- Write code to let the user move objects in the scene by dragging
with the middle button pressed. (10 pts)
- Write code to let the user define new constraints for a given
object. (10 pts)
- Design an interesting scene and take one or more screen grabs.
(10 pts)
- Use appropriate code design; use point, vector, line, and matrix
classes appropriately, and document your code reasonably. (10 pts)
These tasks are explained in more detail below.
- Box transformation. The
existing support code in sketch_pen.C matches the user's input gestures
to 3 world-space directions to create a 3D "axis" (or line) for each
straight line drawn by the user. When 3 perpendicular axes are drawn,
the function SketchPen::create_box() is called to create a canonical
box (a cube located at the origin with sides of length 1). Finish the
implementation of this function to apply the correct transform to the
box so that: the corner at (0,0,0) maps to the 3D location of the start
of the first axis, and the directions and lengths of the 3 sides of the
box are taken from the axes.
- Create canonical cylinder.
When the user draws two parallel axes, SketchPen::create_cylinder() is
invoked. The first piece of missing functionality you should implement
is to create a mesh that represents a canonical cylinder whose base
lies in the XZ plane centered at the origin, whose radius is 1, and
whose height (rising along the positive Y direction) is 1. The comments
in SketchPen::create_cylinder() provide more details.
- Cylinder transformation.
Define the 4x4 matrix to
transform the canonical cylinder so that its world-space location,
radius, height, and orientation match the given axes. Most of the
information comes from the 1st axis; the 2nd axis only determines the
radius of the cylinder, as in the following examples. More
details are given in the comments in SketchPen::create_cylinder().
Left: a 2nd axis being drawn parallel to
the red one. Right: the resulting cylinder.
|
|
Left: a similar situation with axes drawn
in the floor plane. Right: the resulting cylinder rests halfway inside
the floor.
|
|
- 3D axis selection. Fix
the implementation of SketchPen::rebuild_coord_sys() so that axes align
with natural directions of the parent object. E.g., at a point on the
side of a cylinder, one axis should point along the length of the
cylinder, another should point along the surface normal, and the third
should be perpendicular to the first two. The key to achieving this
effect is to understand that in the parent's object space, the natural
directions are determined by the canonical directions (1,0,0), (0,1,0),
and (0,0,1). These directions are mapped to world space by the parent
object's object-to-world transform.
- Moving objects. In
node_manip.C, finish the implementation of NodeManip::move() so that
when the user clicks on an object with the middle button and drags the
mouse, the object moves according to its current constraint.
- Setting new constraints.
Add code in NodeManip::down() to set a new constraint on an object if
the user clicks on the object with the middle button while 1 or 2 axes
are currently active. If one axis is active, set a line constraint so
the object moves along the direction of the axis. If 2 axes are active,
set a plane contraint, where the plane normal is the cross product of
the two axis directions.
- Scene design. Use your
system to create an interesting scene. Render the scene from
an interesting viewpoint, grab a screen shot and and show the class by
posting the image on the phorum as an attachment. Please use
the thread dedicated to project 3 images. You can post multiple
images. (Please include your images in the directory that you hand in
as well.)
- Comment your code reasonably, particularly your design
decisions
and choice of approach.
- Modularize your code: use a suitable number helper functions
with
descriptive names.
- Use descriptive variable and function names: apply a suitable
tradeoff between symbol-length and descriptiveness.
- Learn about and use existing functionality in jot/mlib for
working with points, vectors, lines, and matrices.
Bottom
line: Make your code readable!
10
points
Extended system (up to 15 bonus
points):
The following are optional, but can be attempted by ambitious
students:
- Custom rendering style.
Add a custom rendering style (e.g. using GLSL) that makes sense for a
sketch-based modeling system.
- Additional primitives.
Implement additional primitives, mapping them to gestures of your
choice. Possible ideas are: sphere, duct (i.e., a tube that
follows the path of a curve in 3D), surface of revolution, and extruded
shape defined from a planar shape. Corresponding gestures might be as
follows. Sphere: draw a circle and tap the center. Duct: draw a circle,
then draw a free-hand stroke from the center of the circle. Surface of
revolution: draw an axis, then draw a "profile" curve indicating the
shape to sweep around the axis. Extrude: first draw a planar shape by
drawing its outline, then draw an axis perpendicular to it to define an
inflated shape composed of 2 copies of the outline shape offset from
each other, and joined with a ruled surface. For any primitive you
contruct, consider assigning texture coordinates as well. These can be
used in your renderer, either to apply conventional texture maps or for
more elaborate effects like bump mapping (or both).
- Additional constraints.
Add support for an additional type of motion constraint:
rotation. If the user grabs a node with the middle button while a
single axis is active in the scene, then the constraint should depend
on the user's initial motion (the first few mouse motions while the
cursor is still near the down point). If the motion is roughly parallel
to the axis, use a line constraint as before. But if the motion is
cross-wise to the axis, activate a rotation constraint that restricts
the node to rotate around the rooted vector defined by the axis.
Handing
in
Turn in your proj3 directory, including:
- all your project 3 source files
- a subdirectory, 'images', containing images you created (e.g.
anything you posted on the phorum)
- no model files or binary files please!
- a brief
write-up in text
format that discusses:
- anything about your
implementation that is noteworthy, and
- feedback on
this assignment, including suggestions for how it should be changed
next time.
Name your file
writeup-<uniqname>.txt .
Example:
writeup-rmanoj.txt
Copy your files
to the following
directory on IFS:
/afs/umich.edu/class/eecs487/w07/submit/<uniqname>/p3/
This path is accessible from any machine you've logged into
using your ITCS (umich.edu) password. Report problems to ITCS.
- The timestamp on your key files (p3.C and your writeup) will
indicate the time of submission and if this is past the deadline your
submission will be considered late. Therefore, you are allowed multiple
'submissions' as long as you respect the deadline.
- Test
the compilation: Your submission must compile without errors and
warnings (except those from external libraries like OpenGL, JOT etc.)
on CAEN Linux or Windows machines. Mention
the platform in your writeup. Code that doesn't compile will be
heavily penalized. (There is no need to compile on IFS; we will do the
grading using the CAEN setup.)
Multiple
submissions:
- You are allowed to overwrite your files in the above directory as
many times as you want.
- If the timestamp on these files is past the deadline your
submission will be considered late.
- Test this submission procedure and please let the GSI know well
in advance if you encounter and problems.
Due date
The project is due on March 12, 2007, by 11:59pm. Turning it in 48
hours earlier is worth a 4% bonus; turning it in 24 hours early is
worth a 2% bonus.
Last
updated: February 14, 2007.