l00kitsjake
l00kitsjake

Reputation: 1015

Drawing Multiple Lines with Mouse in OpenGL

I'm trying to draw multiple line segments with my mouse in my OpenGL and C++ program. Right now I can draw one, and once I start drawing another one, the previous one disappears.

Below is my code that is relevant to the mouse drawing. Any suggestions on how I can draw multiple lines?

LineSegment seg;

void mouse(int button, int state, int x, int y) {

    if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {                 // if left button is clicked, that is the start point
        seg.x1 = seg.x2 = x;
        seg.y1 = seg.y2 = y;
    }

    if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {                   // once they lift the mouse, thats the finish point
        seg.x2 = x;
        seg.y2 = y;
    }

}

void motion(int x, int y) {
    seg.x2 = x;
    seg.y2 = y;

    glutPostRedisplay();                                                    // refresh the screen showing the motion of the line
}

void display(void) {
    glClear(GL_COLOR_BUFFER_BIT);                                           // clear the screen

    glBegin(GL_LINES);                                                          // draw lines
    glVertex2f(seg.x1, seg.y1);
    glVertex2f(seg.x2, seg.y2);

    glEnd();

    glutSwapBuffers();
}

Upvotes: 1

Views: 4891

Answers (2)

Keith Thomas
Keith Thomas

Reputation: 163

You need to set up some logic to save the state of the lines you have already drawn. Currently, you never start drawing another line, you just reset the start position of the current line.

Here is a possible solution for what you're looking for:

std::vector<LineSegment> segs;
LineSegment currentSeg;

void mouse(int button, int state, int x, int y) {

    if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {                 
        LineSegment newSeg; // Make a new segment
        newSeg.x1 = newSeg.x2 = x;
        newSeg.y1 = newSeg.y2 = y;
        segs.insert(newSeg); // Insert segment into segment vector
        currentSeg = newSeg;
    }

    if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {  
        currentSeg.x2 = x;
        currentSeg.y2 = y;
    }
}

void motion(int x, int y) {
    currentSeg.x2 = x;
    currentSeg.y2 = y;

    glutPostRedisplay();                          
}

void display(void) {
    glClear(GL_COLOR_BUFFER_BIT);  

    glBegin(GL_LINES);                                                          

    // Iterate through segments in your vector and draw each
    for(const auto& seg : segs) {
      glVertex2f(seg.x1, seg.y1);
      glVertex2f(seg.x2, seg.y2);
    }

    glEnd();

    glutSwapBuffers();
}

Upvotes: 1

Xirema
Xirema

Reputation: 20386

void display(void) {
    glClear(GL_COLOR_BUFFER_BIT);                                           // clear the screen

    glBegin(GL_LINES);                                                          // draw lines
    glVertex2f(seg.x1, seg.y1);
    glVertex2f(seg.x2, seg.y2);

    glEnd();

    glutSwapBuffers();
}

You need to save in a data structure the previous line segments and add to it whenever you click with the mouse. Then the drawloop needs to iterate through that data structure and draw each of the saved line segments.

std::vector<LineSegment> segmentvector;
//Each time you release the mouse button, add the current line segment to this vector
/*...*/

glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_LINES);
for(const LineSegment & seg : segmentvector) {
    glVertex2f(seg.x1, seg.y1);
    glVertex2f(seg.x2, seg.y2);
}

glVertex2f(currseg.x1, currseg.y1);
glVertex2f(currseg.x2, currseg.y2);
glEnd();

I would also STRONGLY ADVISE that you not use Fixed-Function-Pipeline functions when learning OpenGL. There are lots of tutorials online for learning modern OpenGL.

Upvotes: 2

Related Questions