1 Reply Latest reply on Mar 1, 2013 7:47 AM by Diego_Intel

    [Bug Report] - Modelview Matrix Doesn't Update After Selection

    mconnor

      First off I'm not sure this is the correct place to put this kind of thing, so if I should direct this somewhere else please let me know.

       

      I am running an i5-2520M with HD Graphics 3000 driver version 9.17.10.2932 on Windows 7 Enterprise 64-bit.  I noticed while debugging a program that models would appear in places where they shouldn't be, seemingly for no reason.  After poking around for a while it appears that when using the old style OpenGL selection via glRenderMode(GL_SELECT) after returning to the regular GL_RENDER mode the modelview matrix cannot be updated using glLoadMatrixf(...) until an object is drawn, essentially causing the first model drawn after selection to be placed in the location of the last model drawn during selection.  I took an OpenGL tutorial program from the internet to avoid having to do all the GL window setup and modified it to duplicate the issue (please ignore any code remnants that appear as a result).  If you run the program shown below on a card running the above driver you should notice that at first there appears to be 2 partially overlapping triangles which is what we expect.  In actuality the left (solid red) triangle is being drawn in the same location twice and the right triangle (partially transparent green) is being drawn once.  This is to help show the issue in a second.  After the program loops through selection to rendering (slowed down via a sleep call so the change is visible) you'll notice all of a sudden the first red triangle drawn is in the location of the green triangle while the second red triangle drawn using the exact same modelview matrix and vertex data immediately after the first is in the correct location (where it appeared originally).  If you hit spacebar you can toggle on/off the switch to GL_SELECT mode which will make the problem appear/disappear respectively.  This bug does not appear on any of the non-Intel cards that I've tested.  Any help with this issue would be appreciated.

       

      // Duplicated issue code source

       

      // Includes

       

      #include <windows.h>

      #include <gl/gl.h>

       

      // Function Declarations

       

      LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

      void EnableOpenGL(HWND hWnd, HDC * hDC, HGLRC * hRC);

      void DisableOpenGL(HWND hWnd, HDC hDC, HGLRC hRC);

       

      bool allowselect = true;

      // WinMain

       

      int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

                         LPSTR lpCmdLine, int iCmdShow)

      {

          //Window setup

          WNDCLASS wc;

          HWND hWnd;

          HDC hDC;

          HGLRC hRC;

          MSG msg;

          BOOL quit = FALSE;

          float theta = 0.0f;

         

          // register window class

          wc.style = CS_OWNDC;

          wc.lpfnWndProc = WndProc;

          wc.cbClsExtra = 0;

          wc.cbWndExtra = 0;

          wc.hInstance = hInstance;

          wc.hIcon = LoadIcon( NULL, IDI_APPLICATION );

          wc.hCursor = LoadCursor( NULL, IDC_ARROW );

          wc.hbrBackground = (HBRUSH)GetStockObject( BLACK_BRUSH );

          wc.lpszMenuName = NULL;

          wc.lpszClassName = "GLSample";

          RegisterClass( &wc );

         

          // create main window

          hWnd = CreateWindow(

              "GLSample", "OpenGL Sample",

              WS_CAPTION | WS_POPUPWINDOW | WS_VISIBLE,

              0, 0, 256, 256,

              NULL, NULL, hInstance, NULL );

         

          // enable OpenGL for the window

          EnableOpenGL( hWnd, &hDC, &hRC );

         

          //Triangle vertices

          GLfloat vertices[6];

          vertices[0] = 0.0f;

          vertices[1] = 1.0f;

          vertices[2] = 0.87f;

          vertices[3] = -0.5f;

          vertices[4] = -0.87f;

          vertices[5] = -0.5f;

       

          //Modelview matrices for triangles

          GLfloat mat[16];

          GLfloat mat2[16];

          for(int k = 0; k < 16; k++)

          {

              mat[k] = mat2[k]= 0.0f;

          }

          mat[0] = mat[5] = mat[10] = mat[15] = 1.0f;

          mat[12] = -0.1;

       

          mat2[0] = mat2[5] = mat2[10] = mat2[15] = 1.0f;

          mat2[12] = 0.1;

       

          //For selection buffer

          GLuint test[1];

       

          bool select = false;

         

          //Turn on transparency to see problem easily

          glEnable(GL_BLEND);

          glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

         

         

          while ( !quit )

          {

             

             

              // check for messages

              if ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE )  )

              {

                 

                  // handle or dispatch messages

                  if ( msg.message == WM_QUIT )

                  {

                      quit = TRUE;

                  }

                  else

                  {

                      TranslateMessage( &msg );

                      DispatchMessage( &msg );

                  }

                 

              }

              else

              {

                  Sleep(500);

                             

                  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

                  if(select && allowselect)

                  {

                      select = false;

                      glSelectBuffer(1, test);

                      glRenderMode(GL_SELECT);

                  }

                  else

                  {

                      select = true;

                      GLint hits = glRenderMode(GL_RENDER);               

                  }   

                         

                  glLoadIdentity();

                 

                  //Pass vertex data

                  glEnableClientState(GL_VERTEX_ARRAY);

                  glVertexPointer(2, GL_FLOAT, 0, &vertices);

                 

                  //Set left triangle color (red, solid)

                  glColor4f(1.0, 0.0, 0.0, 1.0);           

                 

                  //Set modelview as target matrix

                  glMatrixMode(GL_MODELVIEW_MATRIX);

       

                  //Load position of left triangle and draw

                  glLoadMatrixf(mat);

                  glDrawArrays(GL_TRIANGLES, 0, 3);

       

                  //Repeat same procedure to draw again (should draw in identical location, but doesn't if previous rendermode was GL_SELECT)

                  glLoadMatrixf(mat);

                  glDrawArrays(GL_TRIANGLES, 0, 3);

       

                  //Load location of right triangle, set color to a translucent green and draw

                  glLoadMatrixf(mat2);       

                  glColor4f(0.0, 1.0, 0.0, 0.35);

                  glDrawArrays(GL_TRIANGLES, 0, 3);           

                 

                  //If we aren't in select mode (bool select set to true for next frame) then swap front/back buffers

                  if(select || !allowselect)

                  {

                      SwapBuffers( hDC );

                  }           

              }

             

          }

         

          // shutdown OpenGL

          DisableOpenGL( hWnd, hDC, hRC );

         

          // destroy the window explicitly

          DestroyWindow( hWnd );

         

          return msg.wParam;

         

      }

       

      // Window Procedure

       

      LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

      {

         

          switch (message)

          {

             

          case WM_CREATE:

              return 0;

             

          case WM_CLOSE:

              PostQuitMessage( 0 );

              return 0;

             

          case WM_DESTROY:

              return 0;

             

          case WM_KEYDOWN:

              switch ( wParam )

              {

                 

              case VK_ESCAPE:

                  PostQuitMessage(0);

                  return 0;

                  break;

              case VK_SPACE:

                  allowselect = !allowselect;

                  break;           

              }

              return 0;

         

          default:

              return DefWindowProc( hWnd, message, wParam, lParam );

                 

          }

         

      }

       

      // Enable OpenGL

       

      void EnableOpenGL(HWND hWnd, HDC * hDC, HGLRC * hRC)

      {

          PIXELFORMATDESCRIPTOR pfd;

          int format;

         

          // get the device context (DC)

          *hDC = GetDC( hWnd );

         

          // set the pixel format for the DC

          ZeroMemory( &pfd, sizeof( pfd ) );

          pfd.nSize = sizeof( pfd );

          pfd.nVersion = 1;

          pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;

          pfd.iPixelType = PFD_TYPE_RGBA;

          pfd.cColorBits = 24;

          pfd.cDepthBits = 16;

          pfd.iLayerType = PFD_MAIN_PLANE;

          format = ChoosePixelFormat( *hDC, &pfd );

          SetPixelFormat( *hDC, format, &pfd );

         

          // create and enable the render context (RC)

          *hRC = wglCreateContext( *hDC );

          wglMakeCurrent( *hDC, *hRC );

         

      }

       

      // Disable OpenGL

       

      void DisableOpenGL(HWND hWnd, HDC hDC, HGLRC hRC)

      {

          wglMakeCurrent( NULL, NULL );

          wglDeleteContext( hRC );

          ReleaseDC( hWnd, hDC );

      }