CSCI-GA.2270-001
Graduate Computer Graphics
Warren Weaver Hall, Rm 109
Thursday at 5-6:50pm

Office hours: Wednesday, 4-5pm

Text: Class notes (so make sure you come to class!), will be posted on-line after each lecture.

Graders:

Jonathan Tompson, Bowen Zhang, Weitao (Vito) Wang, Jianxing (Morgan) Chen

Discussion list:

TBA

Student homework pages

Lectures:

Introductory lecture (January 26)
Simple applets and 2D matrix transformations
3D matrix transformations
Modeling shapes with polygons
Perspective and animation hierarchy
Better animation hierarchy + Splines
Ray tracing 1
Ray tracing 2
Ray tracing 3
Ray tracing 3
Z-buffers, part 1
Z-buffers, part 2
Advanced topics (if there is time)

Setting up a homepage and access to computers:

Most of you have the homepage and computers thing already figured out. But just to make sure you have at least one way to show your work on line, your NYU webpage can be activated and modified as follows:

To post assignments for this class, you should set up a subdirectory of your web site (preferably your NYU web site). Name this subdirectory "graphics". It should have a main "index.html" file, and that file should link to the various homework assignments. After the first class, you will send the grader an email, with subject line "graphics", telling him the URL.


LECTURES AND HOMEWORK:


Introductory lecture (January 26)
General overview of computer graphics, interactive demonstration of the sort of system you will be implementing this semester. Delineated the basic elements of graphics you will learn in this course:

  • Matrix transformations (translate, rotate, scale)
  • Geometric modeling (3D shapes, approximation by polygons)
  • Rendering (scan-conversion, materials, lighting, shading)
  • Animation (forward and inverse kinematics, dynamics)

Your homework, due before the start of the next class, is to write an essay saying why you are taking this class and what you hope to get out of it. The essay should be posted to the graphics/ web page that you will create for this class. Send an email to grader Jonathan Tompson telling him the URL of that web page, as we discussed in class.


Simple applets and 2D matrix transformations
In class on Feb 2 we showed how to create a simple java applet, by extending my java class BufferedApplet.java. Example applets we built in class were test1.java and test2.java. Feel free to download these and to use them as a basis to start your homework.

To compile and run from the command line, you can use the latest version of the Java Development Kit (JDK), which you can download from http://www.oracle.com/technetwork/java/javase/downloads

To compile all of your java files, you can just type in the command line:

   javac *.java

You can also develop from an Integrated Development Environment (IDE) such as Eclipse.

You can download Eclipse from the Eclipse Downloads page. Be sure to download Eclipse IDE for Java Developers.

Installing Eclipse is slightly more involved if you are on Windows than if you are on a Mac. So if you are on Windows, you can read this Tutorial for installing Eclipse on Windows.

To get your Java applet running from the Web, or in appletviewer from the command line, you need an html file that contains an applet tag. The simple test1.html file I used in class looked like this:

   <applet code=test1 width=640 height=480>
   </applet>
If you have test1.html in your current directory, you can either type into the command line:
   appletviewer test1.html
or you can click on test1.html from a finder window, to launch the applet in a browser.

After going through some example programs, in class we started to discuss matrix transformations, beginning with two dimensional transformations -- which are done using 3×3 matrices.

Consider any point (x,y) on the 2D plane. We can represent a any point on the plane in homogeneous coordinates as a column vector:

   x
   y
   w
to represent the point at position (x/w, y/w). For most points, we can just let w = 1.

For points at infinity (that is, direction vectors) we can let w = 0.

For example, consider the two column vectors below. The first represents the point at location (1,0) and the second represents the positive x direction:

   1          1
   0          0
   1          0
This representation lets us use matrices to transform both points and directions by matrix-vector multiplication:
x' m0,0 m0,1 m0,2 x
y'  ←  m1,0 m1,1 m1,2  ×  y
w' m2,0 m2,1 m2,2 w
The identity matrix transforms every point to itself:
x 1  0  0 x
y  ←  0  1  0  ×  y
w 0  0  1 w
A translation matrix moves every point by a fixed amount (dx,dy):
x+dx 1  0  dx x
y+dy  ←  0  1  dy  ×  y
w 0  0  1 w
A rotation matrix rotates every point about the origin by a fixed angle θ:
(x cosθ - y sinθ) cosθ -sinθ 0 x
(x sinθ + y cosθ)  ←  sinθ cosθ0  ×  y
w 0  0 1 w

We can build more complex transformations by multiplying together transformation matrices:

(a0,0b0,0+a0,1b1,0+a0,2b2,0) (a0,0b0,1+a0,1b1,1+a0,2b2,1) (a0,0b0,2+a0,2b1,2+a0,2b2,2) a0,0 a0,1 a0,2 b0,0 b0,1 b0,2
(a1,0b0,0+a1,1b1,0+a1,2b2,0) (a1,0b0,1+a1,1b1,1+a1,2b2,1) (a1,0b0,2+a1,1b1,2+a1,2b2,2)  ←  a1,0 a1,1 a1,2  ×  b1,0 b1,1 b1,2
(a2,0b0,0+a2,1b1,0+a2,2b2,0) (a2,0b0,1+a2,1b1,1+a2,2b2,1) (a2,0b0,2+a2,1b1,2+a2,2b2,2) a2,0 a2,1 a2,2 b2,0 b2,1 b2,2
But we need to be careful, because matrix math is not commutative -- the order that we perform these rotations matters.

For example, first translating by (1,0) and then rotating by π/2 does not produce the same transformation as first rotating by π/2 and then translating by (1,0):

0  -1  0  0  -1  0  1  0  1 
1   0  1  ←  1   0  0  ×  0  1  0 
0   0  1  0   0  1  0  0  1 
 
0  -1  1  1  0  1  0  -1  0 
1   0  0  ←  0  1  0  ×  1   0  0 
0   0  1  0  0  1  0   0  1 

Next week we will cover other sorts of matrix transformations, such as scaling, skewing and perspective, and we will talk about 3D matrix transformations.

Your homework, due next February 9 before class starts, will be to build upon the simple applets that I showed in class, to make your own cool animated scene. You are encouraged to be creative, to have fun with it. Show me your imagination! Remember, you can draw onto the Graphics object using any method found in the API for the java.awt.Graphics object class. You can find the API documentation page on the web by doing a Google search for java Graphics.

You should create a subfolder for each homework assignment, inside the main folder on your class website that contains your index.html page. This will make things a lot easier as the semester goes along.

Link to this assignment from your main index.html page. Graders should be able to see your applet running after they click on the link.

For this and other assignments, you should put up links to all of your Java source files on the assignment page, so the graders can see your actual code.


3D Matrices
In class this week we discussed using 4×4 matrices to do linear coordinate transformations. After reviewing the form of the basic matrix primitives, below, do the this week's homework assignment. That assignment page contains extensive notes and hints about implementation.

3D Transformation Matrices:

Here are the basic 3D matrix primitives (not including perspective):

identity:
1000
0100
0010
0001
translationMatrix(a,b,c):
100a
010b
001c
0001
xRotationMatrix(θ):
1000
0cos(θ)-sin(θ)0
0sin(θ)cos(θ)0
0001
yRotationMatrix(θ):
cos(θ)0sin(θ)0
0100
-sin(θ)0cos(θ)0
0001
zRotationMatrix(θ):
cos(θ)-sin(θ)00
sin(θ)cos(θ)00
0010
0001
scaleMatrix(a,b,c):
a000
0b00
00c0
0001


Modeling shapes with polygons

Approximating curved shapes with vertices and polygonal faces

Because computers are better at solving simple problems, a very effective approach is to break any curved surface down into a collection of little flat surfaces.

This exploits the fact that people are much more sensitive to shading than to silhouettes. As long as we can shade a flat polygon so that it reacts to light in a way that makes it look curved, we can get away with approximating curves surfaces by such polygons.

There are two parts to representation of a shape: - an array of vertices. Each vertex has an x,y,z coordinate - an array of faces. Each face is an ordered array of vertex indices.

Our represention needs to distinguish (1) adjoining faces that are being used to approximate a single curved surface from (2) adjoining faces that are supposed to have a visible edge between them.

To do this we will adopt the following convention: (1) if two faces index into the same vertex, then this indicates a single smooth curved surface. (2) if two faces index into different vertices that just happen to have the same x,y,z position, this indicates an edge.

For example, the first example below is a very coarse approximation to a smooth sphere using an octahedral arrangement of vertices. The second example is is an octahedron, with eight faces and twelve edges.

// VERY COARSE APPROXIMATION OF A SPHERE USING EIGHT VERTICES:
//
//            3
//            | 4
//            |/
//      0-----+-----1
//           /|
//          5 |
//            2

double vertices[][] = { {-1, 0, 0}, { 1, 0, 0}, { 0,-1, 0}, { 0, 1, 0}, { 0, 0,-1}, { 0, 0, 1}, };

int faces[][] = { {0,2,5}, {0,5,3}, {0,3,4}, {0,4,2}, {1,5,2}, {1,3,5}, {1,4,3}, {1,2,4}, };

// OCTAHEDRON -- NEEDS 24 VERTICES, THREE FOR EACH OF THE EIGHT FACES.

double vertices[][] = { { 0, 0,-1}, { 0,-1, 0}, {-1, 0, 0}, { 1, 0, 0}, { 0,-1, 0}, { 0, 0,-1}, {-1, 0, 0}, { 0, 1, 0}, { 0, 0,-1}, { 0, 0,-1}, { 0, 1, 0}, { 1, 0, 0}, {-1, 0, 0}, { 0,-1, 0}, { 0, 0, 1}, { 0, 0, 1}, { 0,-1, 0}, { 1, 0, 0}, { 0, 0, 1}, { 0, 1, 0}, {-1, 0, 0}, { 1, 0, 0}, { 0, 1, 0}, { 0, 0, 1}, };

int faces[][] = { {0,1,2}, {3,4,5}, {6,7,8}, {9,10,11}, {12,13,14}, {15,16,17}, {18,19,20}, {21,22,23}, };

A unit cube can be described using this vertices/faces description as six faces and 24 vertices (four vertices for each of its six faces). Because the cube contains edges between adjoining faces, the faces cannot share vertices. Hence the need (as we discussed in class) for 24 vertices, rather than 8.

I leave it to you to figure out the vertices and faces arrays for a cube. In fact, that's part of your homework assignment for this week.

In general, you can create a Java class Geometry that contains these two data structures:

   public class Geometry
   {
      double vertices[][];
      int faces[][];

// OTHER CODE AND DATA GO HERE }

To create different kinds of shapes, you can add methods to your Geometry class that fill in the vertices and faces values in various useful and interesting ways.

For example, as we discussed in class, some shapes can be described parametrically. As two parameters each vary from a minimum to a maximum value, we evaluate some function that returns the (x,y,z) coordinates of the point on the surface associated with those parameter values.

One example of this is the description of a unit sphere as a latitude/longitude globe generated by two parameters:

   0 <= θ <= 2π 
   -π/2 <= φ <= π/2

with the associated function

  f(θ,φ) = (cosθ  cosφ , sinθ  cosφ , sinφ)

Another example is the parametric description of a unit torus (a "unit torus" is a torus centered on the origin, whose large ring diameter is 1.0). The torus is generated by two parameters:

   0 <= θ <= 2π 
   0 <= φ <= 2π 

with the associated function

   f(θ,φ) = ( (1 + r cosφ) cosθ , (1 + r cosφ) sinθ , r sinφ )

where "r" is the radius of the tube thickness.

When dealing with such a shape, we want to create a set of vertices that form a rectangular mesh. The user of our modeler should be able to specify how many steps to take from the lowest to the highest values of each of the two parameters.

For example, we might implement a method globe(int m, int n) within the Geometry class, which fills the geometry object's vertices and faces array with values that form the shape of a sphere, taking m steps in longitude (from 0 to 2π) and n steps in latitute (from -π/2 to π/2).

As we discussed in class, a shape that forms a rectangular mesh contains ((m+1) * (n+1)) vertices, and (m * n) faces, where each face indexes four vertices.

The vertex whose value of θ is (2π * i / m) and whose value of φ is (-&pi/2 + &phi * j / n), is stored in vertices[i + (m + 1) * j].

For example, a sphere with m == 3 and n == 3 will have 16 vertices, that we can think of as being arranged in a 4×4 grid:

     12 13 14 15
      8  9 10 11
      4  5  6  7
      0  1  2  3

and its nine faces will be:

   {
      { 0, 1, 5, 4}, { 1, 2, 6, 5}, { 2, 3, 7, 6},
      { 4, 5, 9, 8}, { 5, 6,10, 9}, { 6, 7,11,10},
      { 8, 9,13,12}, { 9,10,14,13}, {10,11,15,14},
   };

An interesting hybrid shape is a cylinder. The tubular sides of the cylinder form a kind of mesh that can be parametrized by θ and z, where:

   0 <= θ <= 2π
   -1 <= z <= 1
with the associated function:
   f(θ,z) = ( cosθ , sinθ , z )
The end-cap in positive z can be parameterized by angle and radius:
   0 <= θ <= 2π
   0 <= r <= 1
with the associated function:
   f(θ,z) = ( r cosθ , r sinθ , 1.0 )
The end-cap in negative z needs to circle around the other way, so that the vertices of the resulting polygons will be oriented counterclockwise when seen from the outside of the cylinder:
   f(θ,z) = ( r cos(-&theta); , r sin(-&theta); , -1.0 )

HOMEWORK, DUE BEFORE CLASS STARTS, THURSDAY FEBRUARY 23

Implement a geometry class. Add methods that generate a sphere, a cylinder and a cube.

Once you have these three shapes, you can model approximations to lots of different objects, such as people, molecules, cars, robots, trees, houses, chairs, and lots of other things, by creating multiple Geometry objects and using matrices to transform them.

Build a scene using models created from your shapes. Be creative. If you'd like, feel free to generate other primitive shapes,

For now, you can render all of your transformed shapes by drawing the edges of the faces using the g.drawLine command, just as you did for last week's assignment.

I strongly recommend you do not wait until the last minute to complete this week's assignment. You won't be able to get it done at the last moment.


Perspective and animation hierarchy
We covered two topics on February 23:

Please read over both of those pages of notes carefully. Your homework assignment, which will be due before the start of class on March 1, is described at the bottom of the notes about Transformation Hierarchy.


Better animation hierarchy + Splines
Better animation hierarchy

As we discussed in class, the way you did animation in the previous assignment was limited, since the animation hierarchy was "baked in" to the code. It's much better to do this hierarchy as data, rather than code, so that users can make changes to the hierarchy during run-time.

In class I explained how my little example of a one-armed man, shown in the old style as scenetest1.java, can be more elegantly expressed using the new style, as in scenetest2.java.

To support this, you can add some data structures to your Geometry object that support an interface something like the following:

public class Geometry
{
   ...
   public Matrix getMatrix() { ... }             // access to this geometry object's matrix
   public void add(Geometry child) { ... }       // add a child geometry object
   public void remove(Geometry child) { ... }    // remove a child geometry object
   public int getNumChildren() { ... }           // find out how many children there are
   public Geometry getChild(int index) { ... }   // get the ith child
   ...
}
The matrix of a Geometry object contains the object's transformation relative to its parent object. These structures allow the objects in your scene to form a hierarchical tree. You should make a special object called world, which forms the root of this tree. Your renderer will traverse the tree, starting at this root world object, to find all the objects in your scene.

Note that you do not need to maintain an explicit matrix stack. Instead, you can keep a separate globalMatrix inside each Geometry object, which contains the result, in each animation frame, of multiplying the parent object's globalMatrix by the object's relative matrix.

After you have computed the value an object's globalMatrix for the current animation frame, you can then use that globalMatrix to transform the vertices of the object, placing the transformed vertices into a working array (don't modify the values of the Geometry object's original vertices array).

You can then render the Geometry object by using the faces together with the transformed vertex locations in this working array.

Your homework, which will be due before class on Thursday March 22 (after Spring break), will consist of two parts: (1) Change over to the better way of maintaining a matrix/object hierarchy, and (2) Doing animation by implementing splines as we discussed in class.

For the first part of your homework -- changing to the improved method of specifying a hierarchical scene -- you can use the same scene and object hierarchy that you used in the previous assignment, or you can create something new. I leave that choice up to you -- but it's more fun to try something new.

For the course notes and assignment for the second part of the homework, here is a link to an introduction to animating with splines.


Ray tracing 1
In class on March 22 we started to talk about ray tracing, but there is no assignment yet. Just finish up the hierarchy/splines assignment for Thursday, March 29.

In class this coming Thursday, I will repeat the small amount of math I showed you for intersecting a ray with a sphere. That was just a taste, to give you the general idea of how it works.


Ray tracing 2
Notes (and homework) for the March 29 class about ray tracing are here.


Ray tracing 3
Notes (and homework) for the April 5 class about ray tracing are here.


Ray tracing 3
We went over the math for ray tracing very very carefully.

Your homework is to complete the ray tracing assignments. People who had already completed them by April 12 will get extra credit.


Z-buffers, part 1
The notes and assignment for this week are here.


Z-buffers, part 2
The notes and assignment for the second part of the z-buffer algorithm are here.

For those of you who are feeling confident and ambitious (and have gotten everything else done), here are some notes from this week's lecture on texturing.


Advanced topics