代写CS 5310 Computer Graphics Graphics System Specification (C)代写C/C++编程
- 首页 >> OS编程CS 5310 Computer Graphics
Graphics System Specification (C)
1 Overview
The purpose of a computer graphics system is to enable a user to construct scenes and views to achieve a desired result. Often, speed or real-time performance is also a major concern. Building complex systems requires careful software design in order to minimize complexity, unexpected effects of changes, readability, and expandability. Modularityin computer graphics system design is an important component of achieving these goals.
The following document specifies the data structures, functions, and functionality for a basic 3D rendering system using C. The data types within the system include the following.
• Pixel - data structure for holding image data for a single point
• Image - data structure for holding the data for a single image
• Z-buffer - a depth image, usually part of the Image data structure
• Point - a 2D or 3D location in model space
• Line - a line segment in 2D or 3D model space
• Circle - a 2D circle
• Ellipse - a 2D ellipse
• Polygon - a closed shape consisting of line segments
• Polyline - a sequence of connected line segments
• Color - a representation of light energy
• Light - a light source
• Vector - a direction in 2D or 3D model space
• Matrix - a 2D or 3D transformation matrix
• Element - a element of a model of a scene
• Module - a collection of elements
• View2D - information required for a 2D view of a scene
• ViewPerspective - information required for a perspective view of a scene
• ViewOrthographic - information required for an orthographic view of a scene
Over the course of the semester, you will implement each of the above data structures using a C struct data type. The required fields and their purposes are given in the specification below. For each data type, you will also implement a set of functions. The function prototypes and and a description of the purpose of each required function are also included in the specification, and you are free to add additional functionality. If your code supports the required data types and functionality, then you will be able to run a series of test programs to evaluate and debug your system.
1.1 C versus C++
Many aspects of computer graphics are appropriate for an object-based approach to software design. Primi- tives such as lines, circles, points and polygons naturally exist as objects that need to be created, manipulated, drawn into an image, and destroyed. We may also want to store a symbolic representation of a scene by saving lists of primitives to a file, which is a natural part of an object-oriented approach.
The ideas of modularity and object-based design are possible to implement in either C or C++. The features of C++ give more structure and flexibility to the object-based approach; C gives the programmer lower-level control of information and forces a deeper understanding of how the information flow occurs. A continuum of possible software system structures are possible between the two extremes of a pure object-based C++ design and a modular, but strict C implementation.
As an example, consider the action of drawing a line into an image. Using C++, we might have a class and method prototyped as below. Creating a Line object and calling line .draw(src, color) would draw a line into the image of the specified color.
class Line { public:
Point a; Point b;
Line(const Point &a, const Point &b);
int draw(Image &src, const Color &c); };
int Line::draw(Image &src, const Color &c) {
// all of the required information is in the Line class or Image class // draw the line from a to b with color c
return(0); }
The straight C code below has identical functionality and about the same level of modularity. In the main program, calling lineDraw(line, src, color) with a Line structure, an Image and a Color will draw the line in the image.
typedef struct { Point a;
Point b; } Line;
int lineDraw(Line *line, Image *src, Color *b) {
// all of the required information is in the Line or Image structures // draw the line from a to b with color c
return(0); }
The difference between the two is that in C all of the information required by a function must be explicitly passed through the parameters. In C++, the object on which a method is called can provide some, if not all of the information. Note also that in C passing by reference is not an option: all C parameters are passed by value, which means copies of the parameters get passed to the function. In C++, passing by reference is possible. Note that in both C and C++ we want to avoid passing whole data structures.
2 Image
The image is a basic object in computer graphics. Conceptually, it is a canvas on which object primitives can draw themselves. A useful way of thinking about the image is to treat it as a storage device that holds color data. In graphics we may want our image to also hold depth data–distance from the camera. Other objects can write to or read from the image as necessary, modifying the values stored in the image. An image needs to know how to read from and write itself to a file. Note that the data type of the file does not need to match the internal data type of the image.
To represent a single pixel, we need at least three numbers for color images: R, G, and B, corresponding to the red, green, and blue values of the pixel. In graphics, we are also often mixing images together through the use of an alpha channel. The alpha value of a pixel indicates its transparency. We are also often dealing with objects that have an associated depth, so we know what surfaces are in front of what other surfaces. You will want to use a float type to represent the RGB, alpha, and depth values in your image. You can organize the data as you see fit.
One possible organization method is to create an FPixel type like the following with all five values inter- leaved through the image data structure. An alternative approach would be to have an FPixel data structure that has just the RGB values and then create separate alpha and z fields in your Image data structure (pre-ferred).
Option 1 Option 2
typedef struct { typedef struct {
float rgb[3]; float rgb[3];
float a; } FPixel;
float z;
} FPixel;
Then you can use a single or double pointer ofFPixel type to represent all of the necessary image data.
Image Fields
• data: pointer or double pointer to space for storing Pixels (e.g. FPixel type)
• rows: number of rows in the image
• cols: number of columns in the image
• depth: (optional) store your z values here, this would be a float pointer (array)
• alpha: (optional) store your alpha values here, this would be a float pointer (array)
• maxval: (optional) maximum value for a pixel
• filename: (optional) char array to hold the filename of the image
2.1 Image Functions
All of the Image functions either take in an Image pointer (Image *) as an argument or return a new Image pointer. You never want to pass an Image into a function, always pass in an Image pointer. In general, if you’re passing around any data structure bigger than a float or a double, use a pointer to avoid copying the contents of the struct.
Constructors and destructors:
• Image *image create(int rows, int cols) – Allocates an Image structure and initializes the top level fields to appropriate values. Allocates space for an image of the specified size, unless rows or cols is 0, in which case it should set both rows and cols to 0 and the data pointers to NULL. Returns a pointer to the allocated Image structure. Returns a NULL pointer only if a malloc operation fails.
• void image free(Image *src) – de-allocates image data and frees the Image structure.
• void image init(Image *src) – given an uninitialized Image structure, sets the rows and cols fields to zero and the data field to NULL.
• int image alloc(Image *src, int rows, int cols) – allocates space for the image data given rows and columns and initializes the image data to appropriate values, such as 0.0 for RGB and 1.0 for A and Z. Returns 0 if the operation is successful. Returns a non-zero value if the operation
fails. This function should free existing memory if rows and cols are both non-zero.
• void image dealloc(Image *src) – de-allocates image data and resets the Image structure fields. The function does not free the Image structure.
I/O functions:
• Image *image read(char *filename) – reads a PPM image from the given filename. An op- tional extension is to determine the image type from the filename and permit the use of different file types. Initializes the alpha channel to 1.0 and the z channel to 1.0. Returns a NULL pointer if the operation fails.
• int image write(Image *src, char *filename) – writes a PPM image to the given file- name. Returns 0 on success. Optionally, you can look at the filename extension and write different file types.
Access
• FPixel image getf(Image *src, int r, int c) – returns the FPixel at (r, c).
• float image getc(Image *src, int r, int c, int b) – returns the value of band b at pixel (r, c).
• float image geta(Image *src, int r, int c) – returns the alpha value at pixel (r, c).
• float image getz(Image *src, int r, int c) – returns the depth value at pixel (r, c).
• void image setf(Image *src, int r, int c, FPixel val) – sets the values of pixel (r,
c) to the FPixel val. If your FPixel contains just r, g, b values then this function should not modify the corresponding alpha or z values.
• void image setc(Image *src, int r, int c, int b, float val) – sets the value of pixel (r, c) band b to val.
• void image seta(Image *src, int r, int c, float val) – sets the alpha value of pixel (r, c) to val.
• void image setz(Image *src, int r, int c, float val) – sets the depth value of pixel (r, c) to val.
• The programmer can also access to the image data directly. You may choose whether to organize the image data as a 1-D single pointer or a 2-D double-pointer.
• You are welcome to define macros for access functions instead of true functions. You can also try using the inline keyword, which tells the compiler to substitute the code in the function for the function
call (eliminating the function call) at compile time.
Utility
• void image reset(Image *src) – resets every pixel to a default value (e.g. Black, alpha value of 1.0, z value of 1.0).
• void image fill(Image *src, FPixel val) – sets every FPixel to the given value.
• void image fillrgb(Image *src, float r, float g, float b) – sets the (r, g, b) val- ues of each pixel to the given color.
• void image filla(Image *src, float a) – sets the alpha value of each pixel to the given value.
• void image fillz(Image *src, float z) – sets the z value of each pixel to the given value.
3 Color
As we move into shading and 3D color calculations, it will be important to use floating point math rather than integer math to represent colors. The Color type is the same as the RGB component of an FPixel. You may also want to create functions that convert between an integer and a float representation, doing appropriate scaling. Colors, which are used for calculating shading, use a range of [0, 1], while Pixels for writing to an integer-based file format generally use a range of [0, 255], although 16-bits per pixel is becoming more common.
A simple way to define a Color in C is as an array of floats. typedef float Color[3];
However, this representation can also be cumbersome for some tasks (like copying). So the recommended method of making a Color type in C is as below.
typedef struct { float c[3];
} Color;
A simple assignment will copy a color if you use the struct definition.
3.1 Color Functions
Define the following functions for the Color type.
void color copy(Color *to, Color *from)
– copies the Color data.
void color set(Color *to, float r, float g, float b)
– sets the Color data.
In addition, add the following functions for an Image.
void image setColor( Image *src, int r, int c, Color val )
– copies the Color data to the proper pixel.
Color image getColor( Image *src, int r, int c )
– returns a Color structure built from the pixel values.
4 Primitive Objects
Primitive objects like pixels, lines, circles, and polygons must hold enough information to know where and how to draw themselves in an image. The primitives Point, Line, Circle, and Ellipse are required for this assignment. The minimum fields required for each type are listed below. Note that on this assignment all z-values will be ignored. However, we’ll need them for 3D in a few weeks. Why we’re using 4-element vectors for 3D will become clear soon.
InC, while you could use typedef double Point[4];, it is probably easier to use a struct.
Point fields
• double val[4] – four element vector of doubles.
Line fields
• int zBuffer; – whether to use the z-buffer, should default to true (1).
• Point a – starting point
• Point b – ending point
Circle fields
• double r – radius,
• Point c – center
Ellipse fields
• double ra – major axis radius
• double rb – minor axis radius
• Point c – center
• double a – (optional) angle of major axis relative to the X-axis
Polyline fields (C)
• int zBuffer; – whether to use the z-buffer; should default to true (1).
• int numVertex – Number of vertices
• Point *vertex – vertex information
4.1 Primitive Functions
Point
• void point set2D(Point *p, double x, double y)
– set the first two values of the vector to x and y. Set the third value to 0.0 and the fourth value to 1.0.
• void point set3D(Point *p, double x, double y, double z)
– set the point’s values to x and y and z. Set the homogeneous coordinate to 1.0.
• void point set(Point *p, double x, double y, double z, double h)
– set the four values of the vector to x, y, z, and h, respectively.
• void point normalize(Point *p)
– normalize the x and y values of a point by its homogeneous coordinate: x = x/h, y = y/h.
• void point copy(Point *to, Point *from)
– copy the point data structure.
• void point draw(Point *p, Image *src, Color c)
– draw the point into src using color c.
• void point drawf(Point *p, Image *src, FPixel c)
– draw the p into src using FPixel c.
• void point print(Point *p, FILE *fp)
– use fprintf to print the contents of the Point to the stream fp. The FILE pointer fp can be an actual file opened using fopen or a standard output stream like stdout or stderr, both defined in stdio.h. The point print function doesn’t care which it is, it just uses fprintf, which takes a FILE pointer as the first argument.
Line
• void line set2D(Line *l, double x0, double y0, double x1, double y1)
– initialize a 2D line.
• void line set(Line *l, Point ta, Point tb)
– initialize a line to ta and tb.
• void line zBuffer(Line *l, int flag)
– set the z-buffer flag to the given value.
• void line normalize(Line *l)
– normalize the x and y values of the endpoints by their homogeneous coordinate.
• void line copy(Line *to, Line *from)
– copy the linedata structure.
• void line draw(Line *l, Image *src, Color c)
– draw the line into src using color c and the z-buffer, if appropriate.
Circle
• void circle set(Circle *c, Point tc, double tr)
– initialize to center tc and radius tr.
• void circle draw(Circle *c, Image *src, Color p)
– draw the circle into src using color p.
• void circle drawFill(Circle *c, Image *src, Color p)
– draw a filled circle into src using color p.
Ellipse
• void ellipse set(Ellipse *e, Point tc, double ta, double tb)
– initialize an ellipse to location tc and radii ta and tb.
• void ellipse draw(Ellipse *e, Image *src, Color p)
– draw into src using color p.
• void ellipse drawFill(Ellipse *e, Image *src, Color p)
– draw a filled ellipse into src using color p.
Polyline
The functions polyline create and polyline free manage both the Polyline data structure and the memory required for the vertex list.
• Polyline *polyline create()
– returns an allocated Polyline pointer initialized so that numVertex is 0 and vertex is NULL.
• Polyline *polyline createp(int numV, Point *vlist)
– returns an allocated Polyline pointer with the vertex list initialized to the points in vlist.
• void polyline free(Polyline *p)
– frees the internal data and the Polyline pointer.
The functions polyline init, polyline set, and polyline clear work on a pre-existing Polyline data structure and manage only the memory required for the vertex list.
• void polyline init(Polyline *p)
– initializes the pre-existing Polyline to an empty Polyline.
• void polyline set(Polyline *p, int numV, Point *vlist)
– initializes the vertex list to the points in vlist. De-allocates/allocates the vertex list for p, as necessary.
• void polyline clear(Polyline *p)
– frees the internal data for a Polyline, if necessary, and sets numVertex to 0 and vertex to NULL.
• void polyline zBuffer(Polyline *p, int flag)
– sets the z-buffer flag to the given value.
• void polyline copy(Polyline *to, Polyline *from)
– De-allocates/allocates space as necessary in the destination Polyline data structure and copies the vertex data from the source polyline (from) to the destination (to).
• void polyline print(Polyline *p, FILE *fp)
– prints Polyline data to the stream designated by the FILE pointer.
• void polyline normalize( Polyline *p )
– normalize the x and y values of each vertex by the homogeneous coordinate.
• void polyline draw(Polyline *p, Image *src, Color c)
– draw the polyline using color c and the z-buffer, if appropriate.
5 Polygon
Polygons require a more complex type than the other primitive objects because they are variable sized structures. Polygons are very similar to Polylines, but they can also be filled with a color. It is assumed that the last vertex of a polygon connects back to the first. As you develop your system, you may want to add more fields into your polygon than the required fields listed below.
Polygon fields (C)
• int oneSided – whether to consider the polygon one-sided (1) or two-sided (0) for shading
• int nVertex – Number of vertices
• Point *vertex – vertex information
• Color *color – color information for each vertex.
• Vector *normal – surface normal information for each vertex.
• int zBuffer; – whether to use the z-buffer; should default to true (1)
5.1 Polygon Functions
Polygon
The functions polygon create and polygon free manage both the Polygon data structure and the memory required for the vertex list.
• Polygon *polygon create()
– returns an allocated Polygon pointer initialized so that numVertex is 0 and vertex is NULL.
• Polygon *polygon createp(int numV, Point *vlist)
– returns an allocated Polygon pointer with the vertex list initialized to a copy of the points in vlist.
• void polygon free(Polygon *p)
– frees the internal data for a Polygon and the Polygon pointer.
The functions polygon init, polygon set, and polygon clear work on a pre-existing Polygon data structure and manage only the memory required for the vertex list.
• void polygon init(Polygon *p)
– initializes the existing Polygon to an empty Polygon.
• void polygon set(Polygon *p, int numV, Point *vlist)
– initializes the vertex array to the points in vlist.
• void polygon clear(Polygon *p)
– frees the internal data and resets the fields.
• void polygon setSided(Polygon *p, int oneSided)
– sets the oneSided field to the value.
• void polygon setColors(Polygon *p, int numV, Color *clist)
– initializes the color array to the colors inclist.
• void polygon setNormals(Polygon *p, int numV, Vector *nlist)
– initializes the normal array to the vectors innlist.
• void polygon setAll(Polygon *p, int numV, Point *vlist, Color *clist, Vector *nlist, int zBuffer, int oneSided)
– initializes the vertex list to the points in vlist, the colors to the colors inclist, the normals to the vectors innlist, and the zBuffer and oneSided flags to their respectively values.
• void polygon zBuffer(Polygon *p, int flag)
– sets the z-buffer flag to the given value.
• void polygon copy(Polygon *to, Polygon *from)
– De-allocates/allocates space and copies the vertex and color data from one polygon to the other.
• void polygon print(Polygon *p, FILE *fp)
– prints polygon data to the stream designated by the FILE pointer.
• void polygon normalize( Polygon *p )
– normalize the x and y values of each vertex by the homogeneous coord.
• void polygon draw(Polygon *p, Image *src, Color c)
– draw the outline of the polygon using color c
• void polygon drawFill(Polygon *p, Image *src, Color c)
– draw the filled polygon using color c with the scanline z-buffer rendering algorithm.
• void polygon drawFillB(Polygon *p, Image *src, Color c)
– draw the filled polygon using color c with the Barycentric coordinates algorithm.