Assignment 2: Green eggs and Bresenham

Due Thursday, March 18, before midnight

The goals for this assignment are:

  • Implement an canvas class capable of drawing lines and simple shapes

  • Implement a procedural artwork using your canvas class

1. Getting started

Following the instructions in Readme.md to build and run the code.

2. canvas class

Implement a class canvas, which can draw lines and triangles on a raster image. This class mirrors the APIs found in OpenGL 1.0 and Processing See the beginShape for an example that is similar to what you are building for this assignment.

The canvas class implements a state machine based api. For example, the following code creates a canvas with size (100,100) and draws a red line followed by a green line.

canvas drawer(100, 100);
drawer.background(0,0,0);

drawer.begin(LINES);

drawer.color(255,0,0);
drawer.vertex(0,0);
drawer.vertex(100,0);

drawer.color(0,255,0);
drawer.vertex(0, 0);
drawer.vertex(0,100);

drawer.end();

You are given basecode in canvas.h and canvas.cpp to use as a starting point. You are also given a raster image class, ppm_image, capable of saving PNG images and settings and getting pixel colors. Feel free to use your own ppm_image class from the previous assignment.

You may add any supporting methods and member variables to implement your class. For example, you might want to add member variables to store the current primitive or color. Or you might want to add functions to draw lines and triangles.

2.1. Requirements

  • Your canvas class should implement the following methods:

    • begin(PrimitiveType type) indicates that the following vertices correspond to a shape

    • end() indicates that all vertices have been specified and we should draw the primitive

    • vertex(int x, int y) specifies a vertex. Vertex positions should be clipped to the size of the raster image.

    • color(unsigned char r, unsigned char g, unsigned char b) specifies a color. All vertices specified after this call should have the given color.

    • background(unsigned char r, unsigned char g, unsigned char b) fills the canvas with a given color

3. Walkthrough and tips

Use draw_test.cpp to test the core functionality of your canvas

3.1. Line drawing

drawer.color(255, 255, 255);
test_line(drawer, 0, 50, 100, 50, "horizontal-line.png");
test_line(drawer, 50, 0, 50, 100, "vertical-line.png");
test_line(drawer, 0, 0, 100, 100, "diagonal-line-1.png");
test_line(drawer, 25, 10, 75, 25,  "h-lessthan-w-line-1.png");
test_line(drawer, 25, 25, 75, 75,  "w-lessthan-h-line-1.png");
test_line(drawer, 0, 100, 100, 0, "diagonal-line-2.png");
test_line(drawer, 25, 90, 75, 75,  "h-lessthan-w-line-2.png");
test_line(drawer, 25, 90, 75, 25,  "w-lessthan-h-line-2.png");
horizontal line
vertical line
diagonal line 1
h lessthan w line 1
w lessthan h line 1
diagonal line 2
h lessthan w line 2
w lessthan h line 2

3.2. Interpolated line colors

// test line interpolation
drawer.background(0, 0, 0);
drawer.begin(LINES);
drawer.color(255, 0, 255);
drawer.vertex(0, 0);
drawer.color(0, 255, 255);
drawer.vertex(100, 100);
drawer.end();
drawer.save("line-color-interpolation.png");
line color interpolation

3.3. Triangles

// test triangle with interpolation
drawer.background(0, 0, 0);
drawer.begin(TRIANGLES);
drawer.color(255, 0, 255);
drawer.vertex(10, 0);
drawer.color(0, 255, 255);
drawer.vertex(90, 50);
drawer.color(255, 255, 0);
drawer.vertex(10, 90);
drawer.end();
drawer.save("triangle.png");
triangle

3.4. Composite shapes

// test quad with interpolation
drawer.background(0, 0, 0);
drawer.begin(TRIANGLES);
drawer.color(255, 0, 255);
drawer.vertex(10, 10);
drawer.vertex(10, 90);
drawer.vertex(90, 90);

drawer.color(255, 255, 0);
drawer.vertex(90, 90);
drawer.vertex(90, 10);
drawer.vertex(10, 10);
drawer.end();
drawer.save("quad.png");
quad

4. Implement your own features

Implement at least 4 additional canvas features. Feel free to come up with your own ideas. Here are suggestions:

  • Make it easy for the user to draw different shapes

    • Circle: draw a circle with given position and radius

    • Rectangle: draw a rectangle with given center, width, and height

    • Star: draw a star shape

    • Flower, or other shapes using rose curves

  • Let the user set line widths

  • Add a point primitive

  • Support both filled shapes and outlined shapes

  • Support different blend modes, such as add, difference, and multiply

  • make it easy for users to specify gradients

  • Support alpha blending

5. Create a unique image

In the program, draw_art.cpp, use multiple effects to create one or more unique images. Feel free to be creative and use operations from the previous assignment. For example, additive blending can be used to create glowing objects.

Make sure to use your custom operations from the previous question in your artworks!! You will not get credit for operators which you don’t test and show work correctly!

Ideas for procedural patterns might be based on spirograph, random numbers and noise, gradients, or color palettes.

Below we create random circles and use the y position to determine its color using a gradient from yellow to cyan. This image also implements both a circle and circle outline.

RandomCircles

The image below creates random stars and colors the background with a gradient using triangles.

Sky

We can also use curves and flow fields to generate patterns. The following image draws line between two points which trace out a rose curve. We use additive blending with the current pixel color to do the coloring.

Rose7

We add noise to the points to get other, more organic, shapes. For this type of effect, a semi-random number which varies smoother often gives better results. Below I use

float noise(float t)
{
   float v = sin(t) * 1175.5453123;
   return v - int(v);
}
Rose8

The examples below use "difference" blending with white.

Rose5
Rose6

6. Update Readme.md

Update Readme.md to include documentation on your unique features and art created with your class.

7. What to hand in

  1. Your code. Make sure your code is checked into github

  2. One or more images created using your software

  3. Update Readme.md so it includes a writeup of the features your application supports