Smooth, efficient, perfect curves

Hi,

what you’re looking for is called a Ribbon or a Trail. Those can relatively easily be drawn using a triangle strip.

Create a vertex buffer std::deque<ci::vec2>>, which is empty at the start. In the first frame, you store the current position in a member variable. Every next frame, you check if the cursor has moved far enough from the initial position. If so, calculate a normal like so:

auto v = glm::normalize( current_position - previous_position );
auto n = vec2( -v.y, v.x );

, then add 2 vertices to your buffer:

vertices.push_back( current_position + thickness * n );
vertices.push_back( current_position - thickness * n );

, but before you do that you check if the buffer is full and remove the first two vertices if it is:

while( vertices.size() >= 100 ) {
    vertices.pop_front();
    vertices.pop_front();
}

Then set the initial position to the current position to get ready for the next frame. Finally, a quick and dirty way to render the ribbon is to use the built-in functions to render the triangle strip:

if( vertices.size() >= 4 ) {
    gl::begin( GL_TRIANGLE_STRIP );
    for( auto &vertex : vertices )
        gl::vertex( vertex );
    gl::end();
}

, but for better performance and more options I’d recommend creating a gl::Batch or gl::VboMesh with a fixed number of vertices, then update the vertex positions by mapping its vertex buffer in combination with a call to:

batch->draw( first, count ).

See this post for even more info.

Quadratic curves as described in this thread are just simple curves with 2 end points and a control point and are not suited to render wiggly lines.

-Paul

2 Likes