Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Page 1 of 2 12 LastLast
Results 1 to 10 of 11

Thread: Rubberband rectangle and local coordinates with MFC context being removed

  1. #1
    Junior Member Newbie
    Join Date
    Oct 2012
    Posts
    11

    Rubberband selection rectangle and local coordinates

    ( quick why)
    I have a GDI+ rubberband or sweep rectangle that I have been using with OPengl and a MFC application. BUT as some have you already know, if you are using OPengl and GDI+ (which I was/is) .. Win7 aero or Win8 aero Desktop Window Manager (DWM) gets VERY mad at you where the sweept rectangle flickers like crazy if Aero is on.

    So to remove GDI+ I created a opengl rubber band rectangle XOR and front buffer, but that is having 2 issue's:

    Issues:
    1. I cannot get the sweep rectangle to track my mouse curser of the box select , keep in mind I have created a 3d environment. What it wants to do is draw it in client cooridinates inside of OpenGL instead of the client rect of the opengl view. I want it to behave like standard CAD zooming/selection where I can have the 3d environment rotated but it draws to the screen like a standard zoom/selection rectangle

    see picture below
    Attachment 1051

    2. The rubberband rectangle draws with the XOR and I cannot get it to draw just with a standard zoom / selection window color ie white



    LButtonDown : Initialize Sweep rectangle
    MouseMove : SweepingDrawRect
    LButtonUp : De-initilize SweepRectangle

    Code sample:

    void CGLView::InitializeDrawRectangle( int linestyle)
    {
    if(m_bSweepRectInitilized) return;
    //get client rectangle
    CRect rectClient;
    ::GetClientRect(m_hWnd,&rectClient);

    GLsizei w, h;
    w = rectClient.Width();
    h = rectClient.Height();


    // set drawing mode to front-buffer, etc
    glDrawBuffer(GL_FRONT);


    glDisable(GL_DEPTH_TEST);
    glLogicOp(GL_XOR);
    glEnable(GL_COLOR_LOGIC_OP);

    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    glDisable(GL_DEPTH_TEST);


    // save the current projection matrix and set up a new convenient projection matrix


    if (h==0)
    h=1;
    if(w==0)
    w=1;


    int viewport[4];

    glGetIntegerv(GL_VIEWPORT, viewport);

    glPushMatrix();
    glMatrixMode(GL_PROJECTION);
    glPushMatrix();
    glLoadIdentity();
    gluOrtho2D(0.0, viewport[2], 0.0, viewport[3]);

    glViewport(0,0,w,h);


    // gluOrtho2D(0, rectClient.Width(), 0, rectClient.Height());*/


    // gluOrtho(0, winWidth, 0, winHeight, -1, 1);
    // gluOrtho2D(0, winWidth, 0, winHeight);
    /* if (w <= h)
    ::glOrtho (-nRange, nRange, -(nRange*h/w), (nRange*h/w), -(nRange*10000.0f), (nRange*10000.0f));
    else
    ::glOrtho (-(nRange*w/h), (nRange*w/h), -nRange, nRange, -(nRange*10000.0f), (nRange*10000.0f));*/



    glMatrixMode (GL_MODELVIEW);
    glLoadIdentity();

    glDisable(GL_LIGHTING); //turn off lighting effects

    // glOrtho(0, rectClient.Width(), 0, rectClient.Height(), -1, 1);
    // gluOrtho2D (0.0, (GLdouble) winWidth, 0.0, (GLdouble) winHeight);
    // glViewport(-1, -1, rectClient.Width() + 2, rectClient.Height() + 2);

    // save the current model view matrix
    m_bSweepRectInitilized=1;

    }



    void CGLView::SweepingDrawRect(HDC hDC, int x1, int y1, int x2, int y2)
    {
    wglMakeCurrent(m_hgldc, m_hrc);

    glDrawBuffer(GL_FRONT);
    glEnable(GL_COLOR_LOGIC_OP);
    glLogicOp(GL_XOR);
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    glDisable(GL_DEPTH_TEST);// make sure you do this to get rid of flicker

    // Perform the logic rendering
    glLineWidth(2.0);
    if(x1 < x2)
    {
    glColor4f(0.0f, 0.0f, 0.0f, 0.5f);
    }
    else
    {
    glColor4f(0.0f, 0.2f, 1.0f, 0.5f);
    }

    // CRect rectClient;
    // ::GetClientRect(m_hWnd,&rectClient);

    int viewport[4];

    glGetIntegerv(GL_VIEWPORT, viewport);

    // OpenGL window coordinates are different from GDI's
    glRectd(x1, viewport[3]-y1,x2, viewport[3]-y2);


    glDisable(GL_COLOR_LOGIC_OP);

    wglMakeCurrent(NULL, NULL);
    glDrawBuffer(GL_BACK);

    glFlush(); // must flush here
    }

    It works pretty good with the exception of the above..
    Last edited by EricMar; 06-09-2013 at 08:27 AM. Reason: I missed something

  2. #2
    Senior Member OpenGL Pro
    Join Date
    Jan 2012
    Location
    Australia
    Posts
    1,105
    Code :
    gluOrtho2D(0.0, viewport[2], 0.0, viewport[3])

    Why are you using the old viewport for the current projection? If you are drawing in screen coordinates wont you want the current screen size.

    Also in OpenGL I would not be using XOR at all just redraw the view and then draw the selection rect last.

  3. #3
    Junior Member Newbie
    Join Date
    Oct 2012
    Posts
    11
    That is my issue, I was trying to draw to screen coordinates but I couldn't get that too work...
    unless I'm missing something...

    I assume that I can do a:

    // glOrtho(0, rectClient.Width(), 0, rectClient.Height(), -1, 1);
    // gluOrtho2D (0.0, (GLdouble) winWidth, 0.0, (GLdouble) winHeight);

    but I couldn't get either of those to work...

    So ultimately how do you set OpenGL to screen coordinate mode?

    Wouldn't doing redrawing the entire view, work but if you have ton of stuff on the screen wouldn't that take to much time and cause flicker...?
    Last edited by EricMar; 06-11-2013 at 09:21 AM.

  4. #4
    Senior Member OpenGL Pro
    Join Date
    Jan 2012
    Location
    Australia
    Posts
    1,105
    first gluOrtho2D and glOrtho( are mutually exclusive since the both initialize the same matrix. gluOrtho2D is for drawing in 2D in screen coordinates. If your redraw is really slow you can capture the screen to a buffer and just blit that buffer instead of redrawing the whole screen but then you have a problem with pan and zoom (the same problem exists with the XOR method). If you use double buffering you won't have a flicker problem.

  5. #5
    Junior Member Newbie
    Join Date
    Oct 2012
    Posts
    11
    I added the gluOrtho2D(0, w, 0, h); to the initialize function

    It does draw the rectangle it is some set value off of the cursor??? very odd... It seems to stay in the X+, Y+ zone
    Click image for larger version. 

Name:	cursor.jpg 
Views:	112 
Size:	76.6 KB 
ID:	1055
    It does redraw itself and erase itself but that doesn't track the cursor and if I rotate the screen off as well...

  6. #6
    Senior Member OpenGL Pro
    Join Date
    Jan 2012
    Location
    Australia
    Posts
    1,105
    What is your viewport? And what coordinate system is the mouse cursor in?

  7. #7
    Member Regular Contributor
    Join Date
    Jun 2013
    Posts
    474
    Quote Originally Posted by EricMar View Post
    So ultimately how do you set OpenGL to screen coordinate mode?
    There are three transformations involved: model-view, projection, viewport.
    If you want to draw in "pixel coordinates", the usual approach is to set the model-view matrix to the identity matrix, and the projection matrix to either gluOrtho2D(0, w, 0, h) or gluOrtho2D(0, w, h, 0) depending upon whether you want the origin at the bottom-left or top-left. That basically sets the projection transformation to the inverse of the viewport transformation, so that the combination of the three is an identity transformation.

    Quote Originally Posted by EricMar View Post
    Wouldn't doing redrawing the entire view, work but if you have ton of stuff on the screen wouldn't that take to much time and cause flicker...?
    It won't cause flicker provided that you have double-buffering enabled. Whether it takes too much time depends upon the complexity of the scene, the performance of the video hardware, and the efficiency of the code. If it's too slow, you can cache the rendered scene in a framebuffer object (provided that you're using OpenGL 3 or later, or have either the GL_EXT_framebuffer_object or GL_ARB_framebuffer_object extension; with older versions, you needed to use a platform-specific mechanism to get an off-screen rendering surface).

  8. #8
    Junior Member Newbie
    Join Date
    Oct 2012
    Posts
    11
    I assume by viewport you mean size ?

    I just have it set to

    CRect rectClient;
    ::GetClientRect(m_hWnd,&rectClient);

    GLsizei w, h;
    w = rectClient.Width();
    h = rectClient.Height();

    glViewport(0,0,w,h);
    gluOrtho2D(0, w, 0, h);

    The mouse coordinates come from The OnMouseMove from windows and I just pass in what the point is from
    void CTestOpenGLView::OnMouseMove(UINT nFlags, CPoint point)

  9. #9
    Junior Member Newbie
    Join Date
    Oct 2012
    Posts
    11
    OK, I seemed to have it now tracking the mouse ONLY if I don't do nothing to the view, if pan the screen or if I rotate the screen then it again loses the mouse cursor...

  10. #10
    Member Regular Contributor
    Join Date
    Jun 2013
    Posts
    474
    Quote Originally Posted by EricMar View Post
    OK, I seemed to have it now tracking the mouse ONLY if I don't do nothing to the view, if pan the screen or if I rotate the screen then it again loses the mouse cursor...
    Coordinates passed to glVertex() are transformed by both the model-view matrix and the projection matrix. If you want the coordinates to correspond to window pixel coordinates, the projection matrix needs to be set with gluOrtho2D() and the model-view matrix needs to be the identity matrix. E.g.:
    Code :
    draw_scene();
    glMatrixMode(GL_PROJECTION);
    gluOrtho2D(0, w, 0, h);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    draw_rectangle();
    If you need to preserve the matrices, you need to push and pop both of them, but you're usually better off setting them both from scratch (i.e. starting with glLoadIdentity()) at the start of rendering.
    Also, avoid using glGetIntegerv(GL_VIEWPORT, ...), as glGet() causes a pipeline stall. Instead, store the viewport dimensions whenever you call glViewport(), and use the stored values.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •