This was a group assignment and the report represents joint efforts of
Keshav Srinivasan (140260001) and Kumar Ayush (140260016)
This report is structured as follows. Section A summarises a comparison between the features our program has and what the specifications demanded. Section B describes the timeline of our project, highlighting certain decisions we took and the implications they had. Section C describes known bugs. Section D is a concluding note. We end with citing our sources, and an appendix of exemplar screenshots.
A. Are the specs met?
- The color_t, pen_t, fill_t, point_t and line_t classes are implemented as described.
- Our triangle_t class does not store the color of the border. The triangle is drawn with the current pen color.
- The drawing_t class is implemented as described.
- The canvas_t class is implemented as described, except we have a 1D array, which represents the squashed 2D array of pixels since glDrawPixels requires a pointer to a 1D array. This seemed easier to do.
- We save and load as described
- We have a concept of drawing points as well.
- While drawing lines and triangles, we interpret successively clicked vertices as having a desire to draw a series of lines and triangles i.e. clicking a third point while in line mode will draw another line between the second and third point.
- Right-click takes back the last point clicked, not only in line and triangle mode, but works as 'Undo' for all actions in the program except clear.
- Our fill is a toggle, a mode of its own. You can keep clicking once in fill mode and it fills the respective quad.
- We have an eraser mode on pressing 'E'. This is a toggle mode.
- The co-ordinate system in my pixel array was set to (0,0) at top-left corner while the mouse() function returned co-ordinates with (0,0) at bottom-left corner. We made an explicit conversion while mutating pixels.
B. The Story
- Skeletal structure of all classes is written.
- We now have to implement the draw method for the point. We have an argument if we should draw a point or not, and if we do, should we do it with a width? A circular width or a square width? For ease of implementation, we settled for a square width, but there is an ambiguity here. If the pen width is an odd number, we can get away with drawing a square around the clicked point. But for an even width, the clicked point will lie asymmetrically within the drawn square. We eventually settled that this bias is OK since the maximum error we have is of one pixel.
- The Bresenham algorithm is a bit complicated for drawing a line with thickness. But since we were drawing our points with a thickness, this allowed us to get away with implementing the Bresenham for 1-pixel thickness. This is less efficient, but works beautifully.
- Drawing triangles was a trivial step, so was floodfill.
- Our next hurdle was wrapping our head around the idea that canvas_t has an object of type drawing_t but drawing_t requires canvas_t to mutate the pixel array contained by it. There was a circular dependency arising. We discovered the concept of forward declarations in C++ and this was hence resolved.
- To maintain a vector of all drawn objects, we defined another class shape_t which is generic to all the other classes that can be drawn. Save and Load was a trivial step, once we had defined shape_t well enough.
- The next challenge was to implement Undo, we needed a temporary pixel buffer. But for all practical purposes, we got away with a trick. We popped the last inserted object from our vector of all objects, then we saved it to a temporary file and loaded it. For less enough objects on the screen, this process was instantaneous.
C. All's Not Well
- You cannot undo consecutive fill actions, hangs the program indefinitely.
- Any invalid input while entering colors and widths hangs the program indefinitely.
- If we have a window size larger than the screen, the co-ordinate reported by the mouse is offset by the amount the window is clipped out of the screen, resulting in incomprehensible behaviour often.
D. Thank You
We really had a lot of fun doing this assignment, and learnt a lot more about C++ as well, along with reinforcing the graphics concepts learnt in classroom.
Time spent coding: ~12 hours
Time spent drawing: ~6 hours
- Used default parameter values in declaration of method rather than definiton following this
- Usage of glDrawPixels and the method to store array in canvas_t inspired from here
- Bresenham Line implementation taken from the course's tutorials.
Fig 1. Points
Fig 2. Lines
Fig 3. Triangles
Fig 4. Fill
Fig 5. Undo, the fill from previous image were removed by undo
Fig 6. Eraser
We had to make an image of an indoor scene to finish the assignment. Here's that for you
Fig 7. Original Shot
Fig 8. Step 1
Fig 9. Step 2
Fig 10. Step 3
Fig 11. Final Image