0
$\begingroup$

I am creating a Bezier curve tool in OpenGL and every time my program draws something in motion with cursor coordinates I see the previously drawn lines on the screen for a second or two before they disappear as shown below:

enter image description here

This is how it should look:

enter image description here

Below are my mouse motion functions and render function. I am using a double buffer and swap buffers each frame.

void passiveMotion(int x, int y)
{
    Point Cursor;
    Cursor.setxy(x, SCREEN_HEIGHT - y);
    if ((pointsVector[0].x != NULL) && (pointsVector[0].y != NULL))
    {
        drawLine(pointsVector[points], Cursor);
    }
    glutSwapBuffers();
}

void motion(int x, int y)
{
    Point Cursor;
    Cursor.setxy(x, SCREEN_HEIGHT - y);
    drawLine(pointsVector[points], Cursor);
    Point reverseCursor;
    reverseCursor.x = (2 * pointsVector[points].x) - Cursor.x;
    reverseCursor.y = (2 * pointsVector[points].y) - Cursor.y;
    drawLine(pointsVector[points], reverseCursor);

    vector<Point> finalPoints = final4Points();

    Point p1;
    p1.setxy(pointsVector[0].x, pointsVector[0].y);

    if ((finalPoints[1].x != NULL) && (finalPoints[1].y != NULL))
    {
        // draw bezier curve
        for (float i = 0; i < 1; i += 0.01)
        {
            // The Green Lines
            int xa = getPt(finalPoints[0].x, finalPoints[1].x, i);
            int ya = getPt(finalPoints[0].y, finalPoints[1].y, i);
            int xb = getPt(finalPoints[1].x, reverseCursor.x, i);
            int yb = getPt(finalPoints[1].y, reverseCursor.y, i);
            int xc = getPt(reverseCursor.x, finalPoints[3].x, i);
            int yc = getPt(reverseCursor.y, finalPoints[3].y, i);

            // The Blue Line
            int xm = getPt(xa, xb, i);
            int ym = getPt(ya, yb, i);
            int xn = getPt(xb, xc, i);
            int yn = getPt(yb, yc, i);

            // The Black Dot
            int x2 = getPt(xm, xn, i);
            int y2 = getPt(ym, yn, i);

            Point p2;
            p2.setxy(x2, y2);

            drawLine(p1, p2);
            p1 = p2;
        }
    }
    glutSwapBuffers();
}

void myDisplay() 
{
    glClear(GL_COLOR_BUFFER_BIT);
    for (int i = 1; i < points; i++)
    {
        // draw main line & dot
        glColor3f(255, 0, 0);
        drawDot(pointsVector[i]);
        glColor3f(0, 0, 0);
        drawLine(pointsVector[i], pointsVector[i + 1]);

        // draw tangent lines and tangent dots
        glColor3f(0, 255, 0);
        drawLine(controlPoints[i + 1], reverseControlPoints[i + 1]);
        glColor3f(0, 0, 255);
        drawDot(controlPoints[i + 1]);
        drawDot(reverseControlPoints[i + 1]);

        vector<Point> finalPoints = final4Points();

        Point p1;
        p1.setxy(pointsVector[0].x, pointsVector[0].y);

        if((finalPoints[2].x != NULL) && (finalPoints[2].y != NULL))
        {
            // draw bezier curve
            for (float i = 0; i < 1; i += 0.01)
            {
                // The Green Lines
                int xa = getPt(finalPoints[0].x, finalPoints[1].x, i);
                int ya = getPt(finalPoints[0].y, finalPoints[1].y, i);
                int xb = getPt(finalPoints[1].x, finalPoints[2].x, i);
                int yb = getPt(finalPoints[1].y, finalPoints[2].y, i);
                int xc = getPt(finalPoints[2].x, finalPoints[3].x, i);
                int yc = getPt(finalPoints[2].y, finalPoints[3].y, i);

                // The Blue Line
                int xm = getPt(xa, xb, i);
                int ym = getPt(ya, yb, i);
                int xn = getPt(xb, xc, i);
                int yn = getPt(yb, yc, i);

                // The Black Dot
                int x2 = getPt(xm, xn, i);
                int y2 = getPt(ym, yn, i);

                Point p2;
                p2.setxy(x2, y2);

                drawLine(p1, p2);
                p1 = p2;
            }
        }
    }
    glutSwapBuffers();
}
$\endgroup$
5
  • 1
    $\begingroup$ Your function "passive_motion" is calling drawing functions and then glutSwapBuffers, without a call to "glClear", that is the origin of your trails (drawing without clearing buffer). As a suggestion, I would decouple input reading and rendering. E.g. Render everything in myDisplay and in motion() and passiveMotion() cache the mouse input values and deal with them in myDisplay when it's time to draw. $\endgroup$
    – PaulHK
    May 12, 2022 at 6:24
  • $\begingroup$ At what line should I call glClear()? I will look into implementing those suggestions, thank you! $\endgroup$ May 12, 2022 at 6:29
  • 1
    $\begingroup$ As suggested I would only have 1 rendering function (a rendering function in this case is something that clears the render buffer, draws to it and then calls some kind of present() function to display it). If you insist on making your input handling functions into rendering functions (again, not recommended) then you need to replicate how myDisplay() works by putting the glClear at the start of the function. However the graphics you drew in myDisplay will be destroyed by the graphics drawn in motion(), this is why it's a bad idea to couple input and rendering so tightly as in your example. $\endgroup$
    – PaulHK
    May 12, 2022 at 6:35
  • 1
    $\begingroup$ I explained why that is. I do not recommend your current strategy of rendering things in input functions. Store the input values into variables and move whatever it was you wanted to draw inside into a single render function. $\endgroup$
    – PaulHK
    May 12, 2022 at 6:43
  • 1
    $\begingroup$ Also, having all the drawing code coming from a single call means you can composite things correctly (draw in correct order). The temporary line section which is currently drawn inside motion() can be correctly drawn after the glClear and the bezier curve so that it appears on top of it. $\endgroup$
    – PaulHK
    May 12, 2022 at 6:53

1 Answer 1

0
$\begingroup$

Although not ideal after reading PaulHK's answer and solution in the coments I decided to call glClear(COLOR_BUFFER_BIT) at the start of the passive motion function, motion function, and display function. I then iterate through my points variable starting at i = 1; (this is very specific to my code) and draw all geometry I was having trouble with in the loop. This works perfectly and is fast. Based on mouse movement each time there is a callback I draw the entire geometry for each mouse function. glClear(COLOR_BUFFER_BIT) clears the screen each frame.

void passiveMotion(int x, int y)
{
    glClear(GL_COLOR_BUFFER_BIT);
    Point Cursor;
    Cursor.setxy(x, SCREEN_HEIGHT - y);
    if ((pointsVector[0].x != NULL) && (pointsVector[0].y != NULL))
    {
        drawLine(pointsVector[points], Cursor);
    }

    for (int i = 1; i < points; i++)
    {
        // draw main line & dot
        glColor3f(255, 0, 0);
        drawDot(pointsVector[i]);
        glColor3f(0, 0, 0);
        drawLine(pointsVector[i], pointsVector[i + 1]);

        // draw tangent lines and tangent dots
        glColor3f(0, 255, 0);
        drawLine(controlPoints[i + 1], reverseControlPoints[i + 1]);
        glColor3f(0, 0, 255);
        drawDot(controlPoints[i + 1]);
        drawDot(reverseControlPoints[i + 1]);

        vector<Point> finalPoints = final4Points();

        Point p1;
        p1.setxy(pointsVector[0].x, pointsVector[0].y);

        if ((finalPoints[2].x != NULL) && (finalPoints[2].y != NULL))
        {
            // draw bezier curve
            for (float i = 0; i < 1; i += 0.01)
            {
                // The Green Lines
                int xa = getPt(finalPoints[0].x, finalPoints[1].x, i);
                int ya = getPt(finalPoints[0].y, finalPoints[1].y, i);
                int xb = getPt(finalPoints[1].x, finalPoints[2].x, i);
                int yb = getPt(finalPoints[1].y, finalPoints[2].y, i);
                int xc = getPt(finalPoints[2].x, finalPoints[3].x, i);
                int yc = getPt(finalPoints[2].y, finalPoints[3].y, i);

                // The Blue Line
                int xm = getPt(xa, xb, i);
                int ym = getPt(ya, yb, i);
                int xn = getPt(xb, xc, i);
                int yn = getPt(yb, yc, i);

                // The Black Dot
                int x2 = getPt(xm, xn, i);
                int y2 = getPt(ym, yn, i);

                Point p2;
                p2.setxy(x2, y2);

                drawLine(p1, p2);
                p1 = p2;
            }
        }
    }

    glutSwapBuffers();
}

void motion(int x, int y)
{
    glClear(GL_COLOR_BUFFER_BIT);

    Point Cursor;
    Cursor.setxy(x, SCREEN_HEIGHT - y);
    drawLine(pointsVector[points], Cursor);
    Point reverseCursor;
    reverseCursor.x = (2 * pointsVector[points].x) - Cursor.x;
    reverseCursor.y = (2 * pointsVector[points].y) - Cursor.y;
    drawLine(pointsVector[points], reverseCursor);

    vector<Point> finalPoints = final4Points();

    Point p1;
    p1.setxy(pointsVector[0].x, pointsVector[0].y);

    if ((finalPoints[1].x != NULL) && (finalPoints[1].y != NULL))
    {
        // draw bezier curve
        for (float i = 0; i < 1; i += 0.01)
        {
            // The Green Lines
            int xa = getPt(finalPoints[0].x, finalPoints[1].x, i);
            int ya = getPt(finalPoints[0].y, finalPoints[1].y, i);
            int xb = getPt(finalPoints[1].x, reverseCursor.x, i);
            int yb = getPt(finalPoints[1].y, reverseCursor.y, i);
            int xc = getPt(reverseCursor.x, finalPoints[3].x, i);
            int yc = getPt(reverseCursor.y, finalPoints[3].y, i);

            // The Blue Line
            int xm = getPt(xa, xb, i);
            int ym = getPt(ya, yb, i);
            int xn = getPt(xb, xc, i);
            int yn = getPt(yb, yc, i);

            // The Black Dot
            int x2 = getPt(xm, xn, i);
            int y2 = getPt(ym, yn, i);

            Point p2;
            p2.setxy(x2, y2);

            drawLine(p1, p2);
            p1 = p2;
        }
    }

    for (int i = 1; i < points; i++)
    {
        // draw main line & dot
        glColor3f(255, 0, 0);
        drawDot(pointsVector[i]);
        glColor3f(0, 0, 0);
        drawLine(pointsVector[i], pointsVector[i + 1]);

        // draw tangent lines and tangent dots
        glColor3f(0, 255, 0);
        drawLine(controlPoints[i + 1], reverseControlPoints[i + 1]);
        glColor3f(0, 0, 255);
        drawDot(controlPoints[i + 1]);
        drawDot(reverseControlPoints[i + 1]);

        vector<Point> finalPoints = final4Points();

        Point p1;
        p1.setxy(pointsVector[0].x, pointsVector[0].y);

        if ((finalPoints[2].x != NULL) && (finalPoints[2].y != NULL))
        {
            // draw bezier curve
            for (float i = 0; i < 1; i += 0.01)
            {
                // The Green Lines
                int xa = getPt(finalPoints[0].x, finalPoints[1].x, i);
                int ya = getPt(finalPoints[0].y, finalPoints[1].y, i);
                int xb = getPt(finalPoints[1].x, finalPoints[2].x, i);
                int yb = getPt(finalPoints[1].y, finalPoints[2].y, i);
                int xc = getPt(finalPoints[2].x, finalPoints[3].x, i);
                int yc = getPt(finalPoints[2].y, finalPoints[3].y, i);

                // The Blue Line
                int xm = getPt(xa, xb, i);
                int ym = getPt(ya, yb, i);
                int xn = getPt(xb, xc, i);
                int yn = getPt(yb, yc, i);

                // The Black Dot
                int x2 = getPt(xm, xn, i);
                int y2 = getPt(ym, yn, i);

                Point p2;
                p2.setxy(x2, y2);

                drawLine(p1, p2);
                p1 = p2;
            }
        }
    }
    glutSwapBuffers();
}
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.