0

I'm trying to draw a selection box over an image drawn using glDrawPixels, but I cannot get it to show. In order to represent the coordinates of the box, I have 4 global integers that I update on mouse actions (the first 2 on click, the others when the mouse is dragged), which I then use in the drawing function. I'm sure that the drawing function is called when the mouse gets dragged, and that the four values at least get updated, since I tried printing them every time the drawing function gets called. The OpenGL calls I have in the main are:

glutInit(&argc, argv);
glutInitWindowSize(WINDOW_DIM, WINDOW_DIM);
glutInitWindowPosition(0, 0);
glutInitDisplayMode(GLUT_RGB|GLUT_DOUBLE);
glutCreateWindow("Window");
glutDisplayFunc(display);
glutMouseFunc(mouse);
glutMotionFunc(motion);
glClearColor(0.0, 0.0, 0.0, 1.0);
glDisable(GL_DEPTH_TEST);
glutMainLoop();

and my display function:

void display()
{
    printf("calling display\n");
    for(unsigned int i=0; i<WINDOW_DIM*WINDOW_DIM; ++i)
    {
        pixels[i]=colors[img[i]];
    }
    glClear(GL_COLOR_BUFFER_BIT);
    glDrawPixels(WINDOW_DIM, WINDOW_DIM, GL_RGB, GL_FLOAT, (float*)pixels);
    glutSwapBuffers();
    if(upd_xmin!=0 || upd_ymin!=0 || upd_xmax!=0 || upd_ymax!=0)
    {
        glDrawBuffer(GL_FRONT);
        glLogicOp(GL_XOR);
        glEnable(GL_COLOR_LOGIC_OP);
        printf("drawing selection\n");
        printf("coords %d %d %d %d\n", upd_xmin, upd_ymin, upd_xmax, upd_ymax);
        glColor3f(1.0, 1.0, 1.0);
        glLineWidth(3.0);
        glBegin(GL_LINE_LOOP);
        glVertex2i(upd_xmin, upd_ymin);
        glVertex2i(upd_xmin, upd_ymax);
        glVertex2i(upd_xmax, upd_ymax);
        glVertex2i(upd_xmax, upd_ymin);
        glEnd();
        glDisable(GL_COLOR_LOGIC_OP);
        glDrawBuffer(GL_BACK);
    }
}

As I said, I don't think the problem is with the mouse and motion function, seeing how the coordinates of the box (the upd_x and upd_y variables in the code above) get updated when there's a mouse event, but if needed I can post those as well.

Orgrim
  • 357
  • 1
  • 5
  • 13

2 Answers2

3

Don't swap the buffers in the middle. Just draw the selection box on the back-buffer like everything else:

selection

#include <GL/glut.h>

int StartX = -1;
int StartY = -1;
int EndX = -1;
int EndY = -1;

void mouse( int button, int state, int x, int y )
{
    if( button == GLUT_LEFT && state == GLUT_DOWN )
    {
        StartX = x;
        StartY = y;
    }
    if( button == GLUT_LEFT && state == GLUT_UP )
    {
        StartX = -1;
        StartY = -1;
        EndX = -1;
        EndY = -1;
    }
}

void motion( int x, int y )
{
    EndX = x;
    EndY = y;
    glutPostRedisplay();
}

void display()
{
    double w = glutGet( GLUT_WINDOW_WIDTH );
    double h = glutGet( GLUT_WINDOW_HEIGHT );

    glClear( GL_COLOR_BUFFER_BIT );

    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    double ar = w / h;
    glOrtho( -2 * ar, 2 * ar, -2, 2, -1, 1 );

    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();

    glBegin( GL_TRIANGLES );
    glColor3ub( 255, 0, 0 );
    glVertex2i( -1, -1 );
    glColor3ub( 0, 255, 0 );
    glVertex2i(  1, -1 );
    glColor3ub( 0, 0, 255 );
    glVertex2i(  0,  1 );
    glEnd();

    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    glOrtho( 0, w, h, 0, -1, 1 );

    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();

    if( StartX > 0 && StartY > 0 && EndX > 0 && EndY > 0 )
    {
        glLogicOp(GL_XOR);
        glEnable(GL_COLOR_LOGIC_OP);
        glColor3f(1.0, 1.0, 1.0);
        glLineWidth(3.0);
        glBegin(GL_LINE_LOOP);
        glVertex2i(StartX, StartY);
        glVertex2i(EndX, StartY);
        glVertex2i(EndX, EndY);
        glVertex2i(StartX, EndY);
        glEnd();
        glDisable(GL_COLOR_LOGIC_OP);
    }

    glutSwapBuffers();
}

int main( int argc, char **argv )
{
    glutInit( &argc, argv );
    glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE );
    glutInitWindowSize( 640, 480 );
    glutCreateWindow( "GLUT" );
    glutDisplayFunc( display );
    glutMouseFunc( mouse );
    glutMotionFunc( motion );
    glutMainLoop();
    return 0;
}

Since you weren't specifying them I added projection and modelview matrices.

genpfault
  • 51,148
  • 11
  • 85
  • 139
1

I believe the problem lies here:

glClear(GL_COLOR_BUFFER_BIT);
glDrawPixels(WINDOW_DIM, WINDOW_DIM, GL_RGB, GL_FLOAT, (float*)pixels);
glutSwapBuffers();
rest of drawing

Your render call should look like:

clear
render
swap buffers

Where render is all of your draw calls (including glDrawPixels).

Also, glDrawPixels was removed in OpenGL 3.2. Unless you absolutely need to use that particular method, why not use an orthographic projection to draw GUI elements (which the selection box can be though of as)?

Edit: Also, be aware that if you make draw calls after glDrawPixels, those may overwrite what you drew with glDrawPixels.

ssell
  • 6,429
  • 2
  • 34
  • 49