Assignment Chef icon Assignment Chef
All English tutorials

Programming lesson

From Photo to Sketch: Mastering Chaikin and Bézier Curves in C++ for CMSI 281/371

Learn how to implement Chaikin and Bézier curve algorithms in C++ to generate cartoon sketches from photos. This tutorial covers generate_points, draw_curve, and multi-iteration smoothing with practical examples and OpenGL integration.

Chaikin curve algorithm Bézier curve algorithm C++ curve implementation CMSI 281 assignment CMSI 371 assignment generate_points function draw_curve function OpenGL curve drawing cartoon sketch from photo computer graphics tutorial de Casteljau algorithm 3D rotation matrix C++ hierarchical modeling OpenGL C++ vector class graphics curve smoothing iterations AI art analogy curves

Introduction to Curve Algorithms in Computer Graphics

In computer graphics, curves are essential for modeling smooth shapes. Two popular techniques are the Chaikin curve algorithm and the Bézier curve algorithm. Both generate a smooth curve from a set of control points. The Chaikin algorithm works by cutting corners iteratively, while Bézier uses Bernstein polynomials. In this tutorial, you'll implement these algorithms in C++ for a CMSI 281/371 assignment, turning a headshot photo into a cartoon sketch.

Setting Up the Skeleton Code

You are provided with a Vertex class to store x and y coordinates. The skeleton uses a std::vector<Vertex> to hold control points. Key functions to implement: generate_points and draw_curve. The n_iter parameter controls how many times the algorithm runs, producing finer curves each iteration.

Implementing generate_points for Chaikin Curves

The Chaikin algorithm refines a polygon by inserting new points at 1/4 and 3/4 of each edge, then removing the original vertices. For a closed curve, connect the last point to the first. Pseudocode:

vector<Vertex> generate_points(vector<Vertex> pts) {
    vector<Vertex> newPts;
    for (size_t i = 0; i < pts.size(); i++) {
        size_t j = (i + 1) % pts.size(); // wrap around
        Vertex p1 = { 0.75*pts[i].x + 0.25*pts[j].x, 0.75*pts[i].y + 0.25*pts[j].y };
        Vertex p2 = { 0.25*pts[i].x + 0.75*pts[j].x, 0.25*pts[i].y + 0.75*pts[j].y };
        newPts.push_back(p1);
        newPts.push_back(p2);
    }
    return newPts;
}

For Bézier curves, use the de Casteljau algorithm: recursively split the control polygon at t=0.5.

Implementing draw_curve

This function calls generate_points repeatedly for n_iter iterations, then connects the resulting points with line segments. Example:

void draw_curve(vector<Vertex> pts, int n_iter) {
    for (int i = 0; i < n_iter; i++) {
        pts = generate_points(pts);
    }
    glBegin(GL_LINE_STRIP);
    for (Vertex v : pts) {
        glVertex2f(v.x, v.y);
    }
    glEnd();
}

For closed curves, use GL_LINE_LOOP.

Trend Example: Smoothing like AI Filters

Just as AI apps like TikTok's cartoon filter smooth facial features, Chaikin and Bézier curves smooth jagged control points into elegant lines. Think of each iteration as a 'filter' that refines the sketch, similar to how stable diffusion models generate art from rough prompts.

Testing with a Headshot

Plot control points around the photo's features (eyes, nose, mouth). Run 3-5 iterations. The more iterations, the smoother the curve, but too many may oversmooth details. Aim for a balance that captures the likeness, like Ed Sheeran's curly hair and beard.

Common Pitfalls

  • Forgetting to handle the closed curve wrap-around in generate_points.
  • Using GL_LINE_STRIP instead of GL_LINE_LOOP for closed shapes.
  • Not converting degrees to radians for rotation in later assignments.

Extending to 3D: Cube Rotation

In assignment 2, you apply rotation matrices to a cube. The same generate_points logic extends to 3D homogeneous coordinates. Implement rotation_matrix_x, rotation_matrix_y, and rotation_matrix_z using the standard rotation formulas. Use deg2rad to convert the global theta.

Hierarchical Modeling with Prisms

Assignment 3 builds prisms from planes. Start with init_plane to create a unit square, then extrude into a cube. Use transformations to assemble objects like a chair or table. The mat_mult function multiplies a transformation matrix by the entire points matrix for efficiency.

Conclusion

Mastering curve algorithms and 3D transformations in C++ is crucial for computer graphics. By implementing Chaikin and Bézier curves, you gain skills used in vector graphics, animation, and game development. Practice with different control points and iterations to see how curves evolve, just like how generative AI creates art from simple inputs.