[Last Call] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 3879
  • Last Modified:

OpenGL Multiple Views (Animations) Rendered in Different Windows

Ok, I have an SDI MFC application which is using OpenGL to display one of several graphs or animations in a single window dedicated to the OpenGl rendering.  I also have another window which allows me to change what's being drawn in the OpenGL window.  For example, in the OpenGL window I could be displaying a graph, or an animated model of the same data, depending on what I select in the other window.  Each view being displayed in the OpenGL window is based on the same data (stored in the document) so the only difference between a view is how the data is being interpreted and displayed in the OpenGL window.  I can even start an animation process, and while in the animation loop I can switch between views in the OpenGL window without disturbing the flow of the animation.  

What I would like to do is have the ability to create multiple OpenGL windows that each render a different view of the data during the animation.  Since each view would be using the same data, I'm not worried about synchronizing the views during the animation (they are already synchronized).  I'm having problems getting OpenGl to render things in different windows at the same time.  I'm trying to create several OpenGL windows, based on the same class.

In my view class, I create child windows (of base class CWnd) to be used to render OpenGL in:

//Creating a graph in one window
p_GraphWindow = new CGlWindow(m_hWnd, this);    
p_GraphWindow->m_pclGLView->myCam->View(1);      //View 1 means to draw a graph

//Creating an animation in another window
p_Animation = new CGlWindow(m_hWnd, this);    
p_GraphWindow->m_pclGLView->myCam->View(2);  //View 2 means to draw a model

You can see that each of these views is creating a new instance of the same class (CGlWindow).  As you will see in the CGlWindow constructor, m_pclGLView is a pointer to an additional class (a new instance of which is created inside the constructor) which takes care of the OpenGL rendering.  So each window is the same, however each window looks to its own camera object (myCam) to decide on the way it's going to interpret and display the data.  

Here is part of the CGlWindow constructor (I simplified it a bit by taking out some unrelated stuff)...

CGlWindow::CGlWindow(HWND pWin, CWnd *pclWnd)
{            
    m_Pwnd = pclWnd;  //Pointer to parent window
    CString szClassName = AfxRegisterWndClass( NULL,0,NULL,0);
   
      DWORD windowStyle = WS_VISIBLE | WS_CAPTION | WS_POPUPWINDOW |    THICKFRAME | WS_VSCROLL;
      CreateEx( 0, szClassName, "VBN", windowStyle, 0, 0, 700, 700, pWin, NULL );
      m_pclGLView = new CGlView(this);  /*Create an instance of the OpenGl
rendering class, passing it a pointer to this window so it knows which window to render in.*/
}

Here is a simplified constructor for CGlView, which is the class that is handeling all the OpenGl rendering for each window...

CGlView::CGlView(CWnd *pclWnd)
{
      myCam = new CCamera();  //Create a camera object to associate with this view
      m_hDC  = ::GetDC(pclWnd->m_hWnd);  //Get window handle of window we want to
                                                                         //render in
      
      BOOL bSuccess;
      RECT rect;
      pclWnd->GetClientRect(&rect);
      int iWidth = rect.right - rect.left;
      int iHeight = rect.top - rect.bottom;
      bSuccess = bSetWindowPixelFormat(m_hDC);
      ASSERT(&bSuccess);
      bSuccess = bCreateViewGLContext(m_hDC);
      ASSERT(&bSuccess);
      vInitGl(iWidth, iHeight);
}

So, lets say I have created to instances of my own CWnd class.  Each window creates an instance of my opengl rendering class, and keeps a pointer to this instance.  That rendering class also has a pointer to the window, so it knows which window to render in.  Each instance also has it's own camera object, which tells it how to interpret and draw the data (since each window is essentially the same, the only difference is which view mode the camera is set to).

Here is how I am currently rendering each scene in the main application loop

if (p_GlWindow){
            p_GlWindow->m_pclGLView->vRenderScene();
      }
      if (p_AnimationWindow){
            p_AnimationWindow->m_pclGLView->vRenderScene();
      }
}

So for each different view in turn, I execute that views vRenderScene(); Here is a simple version of one of the views vRenderScene();

void CGlView::vRenderScene(){
      
            float colour[3];            
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);      // Clear Screen And Depth Buffer
            glLoadIdentity();
            glPopMatrix();
            glTranslatef(myCam->x(), myCam->y(), myCam->z());

            if (myCam->View()==1){ //View 1 = Normal View
//etc
}
            else if (myCam->View()==2){ //View 1 = Model View
//etc
}
      SwapBuffers(m_hDC);  //m_hDC is the pointer to the window handle which this view is supposed to be rendered in
}


Now what seems to be happening is that OpenGl is only rendering in the last window I create, and not updating the other windows at all.  I can create 3 different windows, each with a different view, and it looks fine until I start playing around with the windows.  At that point, I can tell that it initializes each window fine but is only continuously refreshing the last window I created.  If I start resizing the other windows, it will actually resize the object being rendered inside the latest window at the same time (so all windows seem to be calling the same instance of the rendering classes resize method).  

I've tried testing to see if each window is pointing to a unique instance of the myCam class, and also a unique instance of my opengl rendering class GlView by giving those classes a member called "name", giving each instance a different name, running the program in debug mode and following each windows pointers to check the "name" members and make sure they are all unique.  It seems like this is the case.  Does this have something to do with viewports?  Maybe I need to do something special to create multiple viewports?

I'm sure I've made this a lot more complicated then it needs to be in my explanation, so I apologize in advance (I think I tend to overcomplicate things a lot).  I greatly appreciate any help the experts in this forum can give me.  

Thanks in advance
0
nexisvi
Asked:
nexisvi
1 Solution
 
nexisviAuthor Commented:
I ended up answering my own question.  I guess when you have to sit down and think about how to explain your problem, you often end up bringing up something you hadn't though of.  For anyone who ever runs into a similar problem,  what I was missing was a line that sets the rendering context to the current window that I want to render.  like this...

wglMakeCurrent(m_hDC,m_hGLContext);

m_hDC is a handle to the current window, and m_hGLContext is that windows context (I stored both of these as members of each instance of my Glwindow class.  Basically, when each window is going thorugh it's rendering, it sets the context to itself using the above line, then at the end of everything I do a SwapBuffers(m_hDCarray[i]) in a loop.  The m_hDCarray is basically just an array of pointers to each windows handle, and it goes through the array updating each window.
0

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now