Late policy: The homework will be graded out of 100 points. We will accept late submissions up to Thursday, Sept. 27 at 23:59:59; however, for every day that is it is overdue, we will subtract 20 points from the total. For instance, it you turn it in late but turn it in by Tuesday, Sept. 25, at 23:59:59, we will take off 20 points. (We understand thst sometimes multiple assignments hit at once, or other life events intervene, and hence you have to make some tough choices. We'd rather let you turn something in late, with some points off, than have a "no late assignments accepted at all" policy, since the former encourages you to still do the assignment and learn something from it, while the latter just grinds down your soul.)
[I've gotten some good questions on this homework; I've included some clarifications and modifications in the writeup below in boldface.]
Using a high-level scripting language of your choice, write a program that implements the geometry transformations and lighting calculations Prof. Lee discussed in lecture to render an image of a scene consisting of a single 3-D object. For this assignment, you shouldn't worry too much about "modularity," "reuse," "extensibility," "good taste," etc., and you shouldn't worry at all about speed. This is a "quick and dirty" assignment that is primarily intended to make you review the material Prof. Lee has covered and make sure that you understand it. Direct3D and OpenGL handles most of this "behind the scenes," but we want to make sure you understand what is going on behind the scenes. Also, you wind up coding much of this "behind the scenes" work explicitly when you write vertex shaders in languages such as HLSL or Cg; hence, there is value in first testing your understanding of these basic computer graphics concepts using a simple language like MATLAB before we add the additional complexities of shader languages on top of it.
Your lighting model should include ambient and emissive components, as well as diffuse and specular components arising from a single light source.
At the top of your program, you should set variables that determine:
When we run your code, we should be able to change the variables at the top to render different scenes. The variables should be given easily understandable names.
You will need to find a 3-D model on the web, and figure out how to get that model in a format that you can read into your scripting language. We recommend choosing should a relatively simple model that consists of a small number of facets. You can often find programs to convert strange formats into easy-to-read ASCII formats. (If you get into 3-D graphics, wrangling the dozens of different formats is something you will have to wrestle with sooner or later, so you might as well start wrestling with it now.) No two students should be using the same model.
In the interest of simplicity, you should feel free to use the same emissive color for all the facets, the same specular color for all the facets, etc. If you feel like doing something more sophisticated, where different facets have different properties (maybe based on information from your 3D object file), you are welcome to do so, but it is not required for full credit.
For this assignment, use a "flat shading" model; throw away whatever normal information is in the file you downloaded, and have your program compute its own normal for each flat-faced triangle based on the vertex information for that triangle.
At an appropriate point in your processing chain, you should perform "backface culling" and remove those facets that are facing away from the camera. (Be careful to make sure the model you are using is following the conventions you are expecting it to!) Clarification: It seems that a lot of models out there are not consistent in following either a right hand or left hand rule. We want to see the line(s) in your code that perform(s) this culling operation, but if you see that half your facets randomly disappear when you turn this on because the modeler was sloppy, feel free to comment it out.
One you get things into "screen coordinates," you only need to worry about "clipping in z," i.e. delete all facets whose z-values all fall outside the viewingfrustum in the z-dimension. (If only some of the vertices fall outside the z-dimension, go ahead and render it.) We'll let the scripting languages native triangle drawing features worry about clipping in x and y.
Instead of using a z-buffer to handle the fact that some facets will obscure other facets, use "z-sorting." Z-sorting was popular when memory was expensive; for instance, the Playstation 1 uses z-sorting. Real-time implementations typically use some sophisticated data structures to do the sorting; here, you can just use the "sort" command built into whatever scripting language you use. For each facet, compute the average of the z-values of its vertices, and then sort the facets in order of these z-value averages. Then, render the facets in order of farthest to closest.
Again, don't worry about efficiency when doing the culling and sorting. It doesn't matter at this stage if your program runs more slowly with culling than without it. All we care about is that you understand the core operations.
Implementation language: You should choose a scripting language that has built-in matrix and vector operations, as well as a mechanism to draw filled 2-D triangles on the screen - we will let the language handle the rasterization process for you. (The language you choose may have built in 3-D graphics operations, but you should not use them for this assignment.)
We recommend using MATLAB; it has all the operations you need "out of the box," including dot and cross products; you can compute many dot and cross products at once with a single line of code. MATLAB's vectorization features let you write compact, expressive code. MATLAB is now used in the intro CS class for engineers, and is also extensively used throughout the ECE curriculum, particularly in ECE2025: Introduction to Signal Processing. CS students will have been less likely to be exposed to it; however, an advanced CS undergraduate, who has had exposure to many different kinds of programming languages, will have little difficulty picking it up. In any case, if you are CS major, you will find MATLAB to be a worthy weapon to add to your arsenal, as it lets you try out a variety of numerical algorithms with a minimal amount of fuss. Here is an examples session at a MATLAB prompt that illustrates various features. ECE students will find this familiar; CS students should be able to quickly get a "feel" for the language.
>> % MATLAB comments start with a % sign
>> % type 'help command' into MATLAB to get help on a particular command
>> % 'ones(rows,columns)' generates a rows-by-columns matrix of 1s
>> % * by itself is matrix multiplication, but .* will do elementwise multiplication
>> % a semicolon at the end of a command suppresses output
>> a = ones(3,1) * (9:-2:1)
a =
9 7 5 3 1
9 7 5 3 1
9 7 5 3 1
>> b = (11:-2:7)' * ones(1,5)
b =
11 11 11 11 11
9 9 9 9 9
7 7 7 7 7
>> c = a + b
c =
20 18 16 14 12
18 16 14 12 10
16 14 12 10 8
>> d = a * b
??? Error using ==> mtimes
Inner matrix dimensions must agree.
>> d = a .* b
d =
99 77 55 33 11
81 63 45 27 9
63 49 35 21 7
>> % compute columnwise cross product
>> cross(a,b)
ans =
-18 -14 -10 -6 -2
36 28 20 12 4
-18 -14 -10 -6 -2
>> % compute columnwise dot product
>> dot(a,b)
ans =
243 189 135 81 27
>> 1 / (c + 3)
??? Error using ==> mrdivide
Matrix dimensions must agree.
>> 1 ./ (c + 3)
ans =
0.0435 0.0476 0.0526 0.0588 0.0667
0.0476 0.0526 0.0588 0.0667 0.0769
0.0526 0.0588 0.0667 0.0769 0.0909
>> dude = [1 2 3; 5 6 7; 11 12 29]
dude =
1 2 3
5 6 7
11 12 29
>> inv(dude)
ans =
-1.4062 0.3437 0.0625
1.0625 0.0625 -0.1250
0.0937 -0.1562 0.0625
>> dude(:,2) = [99 100 101]'
dude =
1 99 3
5 100 7
11 101 29
>> dude(1:2,:)
ans =
1 99 3
5 100 7
>> % most importantly for this assignment, MATLAB will also draw triangles for you!
>> the image below was created via these commands:
>> axis([-10 10 -10 10])
>> axis square
>> % the first argument to patch consists of x coordinates, the second consists of y
>> coordinates, and the third consists of an RGB triple
>> patch([3 4 6],[-4 -3 -6],[1 0 0])
>> patch([1 5 9],[10 13 14],[0 1 0])
>> patch([-3 -6 -9],[1 2 5],[0 0 1])
>> patch([-1 -3 -5],[-4 -6 -7],[0.25 0.5 0.3])
If you don't want to use MATLAB, you might try Python, Ruby, or
Visual Basic, TCL, or Perl
with one of their numeric/scientific/graphical extensions; Mathematica
or Maple might also be useful. You can even use Scheme or Lisp, if you
can find one that will draw triangles.
If you insist,
you can use a compiled language
Java or C++ or something if you're
willing to lose the interactivity of use of an interpreted language.
The main reason we are asking you to use a flat shading model instead of Gourard shading is that MATLAB, as far as we can tell, will only do Gourard shading in a "colormap" sort of mode instead of a full RGB sort of mode.
Homogeneous coordinates in computer graphics are usually represented as rows vectors,
with operations conducted by doing row .* matrix
type operations. However, some of the "vectorized"
commands in MATLAB, such as cross and dot,
work better with coordinates stores along the columns; hence, you may find
it useful
to use some transposition operations (indicated using a single quote) to flip
between row and column representations as needed. Your mileage may vary.
Philosophy: The instructions to this assignment are deliberately a little bit vague - you should feel free to experiment a bit and come up with your own choices of parameters and implementation techniques. For instance, how exactly should you parameterize orientations, or the field of view? It's up to you! Here, you're not stuck with whatever choices an API designer made.
Deliverables: Package everything needed to run your script (3D data file, program, etc.), as well as three example scenes (in any common image format you'd like) created with your program with different parameters, and upload them to T-square as a zip file, StuffIt file, or gzipped tar file. Include "HW1" and as much as possible of your full name in the filename, e.g., HW1_Aaron_Lanterman.zip. (The upload procedure should be reasonably self explanatory once you log in to T-square.) Be sure to finish sufficiently in advance of the deadline that you will be able to work around any troubles T-square gives you to successfully submit before the deadline. If you have trouble getting T-square to work, please e-mail your compressed file to lanterma@ece.gatech.edu, with "MPG HW #1" and your full name in the header line; please only use this e-mail submission as a last resort if T-square isn't working.
The midnight due date is intended to discourage people from pulling all-nighters, which are not healthy.
Ground rules: You are welcome to discuss high-level implementation issues with your fellow students, but you should avoid actually looking at one another student's code as whole, and under no circumstances should you be copying any portion of another student's code. However, asking another student to focus on a few lines of your code discuss why a you are getting a particular kind of error is reasonable. Basically, these "ground rules" are intended to prevent a student from "freeloading" off another student, even accidentally, since they won't get the full yummy nutritional educational goodness out of the assignment if they do.
Assorted notes: