CS 5721 - Computer Graphics

Homework 1: Vectors and FrameBuffers (40 pts)
Due Date:
Sept. 17, 2007 (before class)

Description

In this assignment you will develop three C++ classes for use in your graphics programming assignments throughout the semester. The classes you will need to implement follow:

  • Vector2D
  • Vector3D
  • FrameBuffer

The vector classes should use double precision math and allow you to get and set the values in the vector. Your vector classes should also provide functions for normalizing the vector, determining the length, computing dot products with other vectors, and computing the cross product with other vectors. Additionally, you should provide operators that allow vectors to be added or subtracted together. You should also be able to multiply or divide your vectors by a scalar. The code will look much cleaner if you use operators to help provide access and perform the various math operations.

Your vector classes must also implement a member function that returns the contents of the vector as a pointer to an array of floats (note that you are not returning doubles here). The function should have the following signature:

float* vecfData(void); 

The FrameBuffer class will contain a 2D array with 3 integers at each array location. Three integers are needed to represent a color and each array location represents a pixel, so you are storing the color at each pixel in your FrameBuffer. Your FrameBuffer class should allow construction of any reasonably sized images (e.g. 512x512, 1280x1024, 2048x2048, etc...). You will need to implement member functions for acquiring the width and height, setting a color (3 integers) at a particular x and y index in the 2D array, blanking the image to a specific color (default of black is good), and outputing the image as an ASCII PPM formatted image file. You may also want to include functionality to "resize" or reinitialize the framebuffer to a different size. The format of ASCII PPM images follows:

P3
# Comment can go here
width height max
R G B R G B ... R G B
...
R G B R G B ... R G B

Note that there will be (width * height) R G B tuples in this file. max represents the largest value in the color data; you should set this to 255 for all of our examples since our values for R, G, or B are in the range [0,255]. You can think of the PPM file as having "height" rows with each row containing "width" R G B tuples. The rows go from the highest number row first (height-1) to the zeroth row last. You can find out more about the PPM format at the PPM specification page. Here's an example:

P3
# file.ppm
4 4 255
0  0  0         0  0  0        0  0  0       255  0  255
0  0  0         0 255 128    0  0  0       0  0  0
0  0  0         0  0  0        0 255 128   0  0  0  
255  0 255   0  0  0        0  0  0        0  0  0

The reason for choosing the PPM format over other formats is that it is simple and you can read the file easily to see if you have problems or errors.

You also need to provide a member function that will provide access to the contents of the FrameBuffer's 2D array. This function should have the following signature

int* bufferData(void);

and should return a pointer to a single array of integers. This linear array of integers contains all width by height pixels stored in the framebuffer, with the bottom row first followed by the second row, etc... This is an important function. Make sure it works. We will return back to using this later in the semester.

Testing

You should create a main.cpp file to test your classes. You are responsible for testing to make sure your classes are functional and correct. You should also include error checking in your code to make it robust. For instance, in the FrameBuffer class it should be an error when indices outside the array are accessed. Do your best to make your classes robust and error-free as these classes will continue to be used over the course of the semester.

Use the following as guides to test your vector classes - Vector2D and Vector3D:

  • create 2D and 3D vectors with initial values
  • be able to set the values of the vectors
  • add and subtract vectors of similar types
  • multiply vectors by scalars
  • normalize and retrieve the length of vectors
  • compute the dot and cross products

For instance,

Vector2D a(1.0, 3.0), b(5.0, 3.2), c(0.0, 0.0);
c = a + b;
std::cout << "c = [" << c.x() << ", " << c.y() << "]" << std::endl;

a.set(-4.0, 3.9);
b.set(14.2, 9.4);
std::cout << "a length = " << a.length() << std::endl;
std::cout << "b length = " << b.length() << std::endl;

double len = a.length();
a.normalize();
std::cout << "a = [" << a.x() << ", " << a.y() << "]" << std::endl;
std::cout << "new a length = " << a.length() << ", old length = " << len << std::endl;

a = a * len;
std::cout << "a = [" << a.x() << ", " << a.y() << "]" << std::endl;

To test the FrameBuffer class, create the following six PPM images:

  • all white (255, 255, 255), width=145, height=89
  • all black (0, 0, 0), width=48, height=480
  • all red (255, 0, 0), width=600, height=480
  • all green (0, 255, 0), width=10, height=10
  • pixel(0,0) [lower left] is color green, pixel(width-1,height-1) [upper right] is color red, pixel(width-1,0) [lower right] is color yellow(255,255,0), all other pixels are black, width=800, height=600

I do not need to see the image files. These are for your benefit in debugging your code. You should end up with 5 images, each of different color and size so you can verify that your code is working.

What to Turn In

You need to turn in ALL of your code for this assignment. This includes any C++ files along with the main.cpp file that tests your code. We MUST know how to compile your program. It is easiest if you create a README.txt file in your submission that describes how to compile the program. If you use any additional files (like project files from Visual C++/.Net/Whatever) you must include these as well.