Solved

OpenGL Multiple Views (Animations) Rendered in Different Windows

Posted on 2003-10-21
2
3,837 Views
Last Modified: 2013-12-06
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
Comment
Question by:nexisvi
2 Comments
 

Accepted Solution

by:
nexisvi earned 0 total points
ID: 9592731
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: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

What is RenderMan: RenderMan is a not any particular piece of software. RenderMan is an industry standard, defining set of rules that any rendering software should use, to be RenderMan-compliant. Pixar's RenderMan is a flagship implementation of …
Performance in games development is paramount: every microsecond counts to be able to do everything in less than 33ms (aiming at 16ms). C# foreach statement is one of the worst performance killers, and here I explain why.
Email security requires an ever evolving service that stays up to date with counter-evolving threats. The Email Laundry perform Research and Development to ensure their email security service evolves faster than cyber criminals. We apply our Threat…
Finds all prime numbers in a range requested and places them in a public primes() array. I've demostrated a template size of 30 (2 * 3 * 5) but larger templates can be built such 210  (2 * 3 * 5 * 7) or 2310  (2 * 3 * 5 * 7 * 11). The larger templa…

839 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question