0
votes

I want to create an application where application View will be divided with OpenGL 3d models in two different views attached to the Childframe using splitter. For this purpose i made a parent class extended from a view class , and inside this class i have initialize all the opengl required code.

for e.g.

#pragma once

#include <gl/gl.h>
#include <gl/glu.h>

#define IL   //when you dont want to use image library and you want to load everything by your self then remove this

// COpenGlView view

class COpenGlView : public CView
{
    DECLARE_DYNCREATE(COpenGlView)

protected:
    void oglBeginRendering();
    COpenGlView();           // protected constructor used by dynamic creation
    virtual ~COpenGlView();

/*******************/
        /* Private Members */
        /*******************/
        // Window information
        CWnd  *hWnd;
        HDC   hdc;          
        HGLRC hrc;          
        int   m_nPixelFormat;
        CRect m_rect;
        CRect m_oldWindow;
        CRect m_originalRect;
public:
        /******************/
        /* Public Members */
        /******************/
        UINT_PTR m_unpTimer;
        // View information variables
        float    m_fLastX;
        float    m_fLastY;
        float    m_fPosX;
        float    m_fPosY;
        float    m_fZoom;
        float    m_fRotX;
        float    m_fRotY;
        bool     m_bIsMaximized;

        float    m_fZoomSpeed;
        float    m_fRotateSpeed;
        GLuint texture[1];


        void oglCreate(CRect rect, CWnd *parent,CString strWindowName=L"OpenGl");
        virtual void oglInitialize(void);
        virtual void oglDrawScene(void);
        float   randFloat(const float& min, const float& max);
        int     randInt(const int& min, const int& max);

        void Reset();


        virtual void OnDraw(CDC* pDC);      // overridden to draw this view

#ifdef _DEBUG
    virtual void AssertValid() const;
#ifndef _WIN32_WCE
    virtual void Dump(CDumpContext& dc) const;
#endif
#endif

protected:
    DECLARE_MESSAGE_MAP()
public:
    afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
    afx_msg void OnPaint();
    afx_msg void OnMouseMove(UINT nFlags, CPoint point);
    afx_msg void OnSize(UINT nType, int cx, int cy);
    afx_msg void OnTimer(UINT_PTR nIDEvent);
    virtual void OnInitialUpdate();
};

here is the cpp

// OpenGlView.cpp : implementation file
//

#include "stdafx.h"

#include "OpenGlView.h"



// COpenGlView

IMPLEMENT_DYNCREATE(COpenGlView, CView)

COpenGlView::COpenGlView()
{

    m_fPosX = 0.0f;     // X position of model in camera view
    m_fPosY = 0.0f;     // Y position of model in camera view
    m_fZoom = 5.0f; // Zoom on model in camera view
    m_fRotX = 0.0f;     // Rotation on model in camera view
    m_fRotY = 0.0f;     // Rotation on model in camera view
    m_fZoomSpeed=0.05f;
    m_fRotateSpeed = 0.05f;
    m_bIsMaximized = false;

}

COpenGlView::~COpenGlView()
{
}

void COpenGlView::Reset()
{
    m_fPosX = 0.0f;     // X position of model in camera view
    m_fPosY = 0.0f;     // Y position of model in camera view
    m_fZoom = 5.0f; // Zoom on model in camera view
    m_fRotX = 0.0f;     // Rotation on model in camera view
    m_fRotY = 0.0f;     // Rotation on model in camera view
    m_fZoomSpeed=0.05f;
    m_fRotateSpeed = 0.05f;
    m_bIsMaximized = false;

}

BEGIN_MESSAGE_MAP(COpenGlView, CView)
    ON_WM_CREATE()
    ON_WM_PAINT()
    ON_WM_MOUSEMOVE()
    ON_WM_SIZE()
    ON_WM_TIMER()
END_MESSAGE_MAP()


// COpenGlView drawing

void COpenGlView::OnDraw(CDC* pDC)
{
    CDocument* pDoc = GetDocument();
    // TODO: add draw code here
}


// COpenGlView diagnostics

#ifdef _DEBUG
void COpenGlView::AssertValid() const
{
    CView::AssertValid();
}

#ifndef _WIN32_WCE
void COpenGlView::Dump(CDumpContext& dc) const
{
    CView::Dump(dc);
}
#endif
#endif //_DEBUG


// COpenGlView message handlers

int COpenGlView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CView::OnCreate(lpCreateStruct) == -1)
        return -1;



    return 0;
}

void COpenGlView::OnPaint()
{
    //CPaintDC dc(this); // device context for painting
    // TODO: Add your message handler code here
    // Do not call CView::OnPaint() for painting messages

    ValidateRect(NULL);
}

void COpenGlView::OnMouseMove(UINT nFlags, CPoint point)
{
    int diffX = (int)(point.x - m_fLastX);
    int diffY = (int)(point.y - m_fLastY);
    m_fLastX  = (float)point.x;
    m_fLastY  = (float)point.y;


    // Left mouse button

    if (nFlags & MK_LBUTTON)
    {
        m_fRotX += (float)m_fRotateSpeed * diffY;

        if ((m_fRotX > 360.0f) || (m_fRotX < -360.0f))
        {
            m_fRotX = 0.0f;
        }

        m_fRotY += (float)0.5f * diffX;

        if ((m_fRotY > 360.0f) || (m_fRotY < -360.0f))
        {
            m_fRotY = 0.0f;
        }
    }

    // Right mouse button
    else if (nFlags & MK_RBUTTON)
    {
        m_fZoom -= (float)m_fZoomSpeed * diffY;
    }

    // Middle mouse button
    else if (nFlags & MK_MBUTTON)
    {
        m_fPosX += (float)0.05f * diffX;
        m_fPosY -= (float)0.05f * diffY;
    }


    OnDraw(NULL);


    CView::OnMouseMove(nFlags, point);
}

void COpenGlView::OnSize(UINT nType, int cx, int cy)
{
    CView::OnSize(nType, cx, cy);

    if (0 >= cx || 0 >= cy || nType == SIZE_MINIMIZED) return;

    // Map the OpenGL coordinates.
    glViewport(0, 0, cx, cy);

    // Projection view
    glMatrixMode(GL_PROJECTION);

    glLoadIdentity();

    // Set our current view perspective
    gluPerspective(35.0f, (float)cx / (float)cy, 0.01f, 2000.0f);

    // Model view
    glMatrixMode(GL_MODELVIEW);

    switch (nType)
    {
        // If window resize token is "maximize"
        case SIZE_MAXIMIZED:
        {
            // Get the current window rect
            GetWindowRect(m_rect);

            // Move the window accordingly
            MoveWindow(6, 6, cx - 14, cy - 14);

            // Get the new window rect
            GetWindowRect(m_rect);

            // Store our old window as the new rect
            m_oldWindow = m_rect;

            break;
        }

        // If window resize token is "restore"
        case SIZE_RESTORED:
        {
            // If the window is currently maximized
            if (m_bIsMaximized)
            {
                // Get the current window rect
                GetWindowRect(m_rect);

                // Move the window accordingly (to our stored old window)
                MoveWindow(m_oldWindow.left, m_oldWindow.top - 18, m_originalRect.Width() - 4, m_originalRect.Height() - 4);

                // Get the new window rect
                GetWindowRect(m_rect);

                // Store our old window as the new rect
                m_oldWindow = m_rect;
            }

            break;
        }
    }
}


void COpenGlView::oglBeginRendering()
{
    SetTimer(1, 1, 0);
}

void COpenGlView::OnTimer(UINT_PTR nIDEvent)
{
    switch (nIDEvent)
    {
        case 1:
        {
            // Clear color and depth buffer bits
            wglMakeCurrent(hdc, hrc);

            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

            // Draw OpenGL scene
            oglDrawScene();

            // Swap buffers
            SwapBuffers(hdc);

            glFlush();
            wglMakeCurrent(NULL, NULL);



            break;
        }

        default:
            break;
    }


    CView::OnTimer(nIDEvent);
}

void COpenGlView::OnInitialUpdate()
{
    CView::OnInitialUpdate();

    COpenGlView::oglInitialize();
    // TODO: Add your specialized code here and/or call the base class
}


void COpenGlView::oglCreate(CRect rect, CWnd *parent,CString strWindowName)
{
    CString className = AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW | CS_OWNDC, NULL, (HBRUSH)GetStockObject(BLACK_BRUSH), NULL);

    CreateEx(0, className,strWindowName, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, rect, parent, 0);

    // Set initial variables' values
    m_oldWindow    = rect;
    m_originalRect = rect;

    hWnd = parent;

    GLenum s = glGetError();

}

void COpenGlView::oglInitialize(void)
{
    // Initial Setup:
    //
    static PIXELFORMATDESCRIPTOR pfd =
    {
        sizeof(PIXELFORMATDESCRIPTOR),
        1,
        PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
        PFD_TYPE_RGBA,
        32, // bit depth
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        16, // z-buffer depth
        0, 0, 0, 0, 0, 0, 0,
    };


    // Get device context only once.
    //hdc = GetDC()->m_hDC;

    // Pixel format.
    m_nPixelFormat = ChoosePixelFormat(hdc, &pfd);
    SetPixelFormat(hdc, m_nPixelFormat, &pfd);

    // Create the OpenGL Rendering Context.
    hrc = wglCreateContext(hdc);
    wglMakeCurrent(hdc, hrc);

    // Basic Setup:
    //
    // Set color to use when clearing the background.

    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glClearDepth(1.0f);

    // Turn on backface culling
    glFrontFace(GL_CCW);
    glCullFace(GL_BACK);

    // Turn on depth testing

    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);

    GLenum a = glGetError();


    OnDraw(NULL);

    //wglMakeCurrent(NULL, NULL);
}

void COpenGlView::oglDrawScene(void)
{
    // Wireframe Mode

    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

    glBegin(GL_QUADS);
            // Front Side
            glVertex3f( 1.0f,  1.0f, 1.0f);
            glVertex3f(-1.0f,  1.0f, 1.0f);
            glVertex3f(-1.0f, -1.0f, 1.0f);
            glVertex3f( 1.0f, -1.0f, 1.0f);

            // Back Side
            glVertex3f(-1.0f, -1.0f, -1.0f);
            glVertex3f(-1.0f,  1.0f, -1.0f);
            glVertex3f( 1.0f,  1.0f, -1.0f);
            glVertex3f( 1.0f, -1.0f, -1.0f);

            // Top Side
            glVertex3f( 1.0f, 1.0f,  1.0f);
            glVertex3f( 1.0f, 1.0f, -1.0f);
            glVertex3f(-1.0f, 1.0f, -1.0f);
            glVertex3f(-1.0f, 1.0f,  1.0f);

            // Bottom Side
            glVertex3f(-1.0f, -1.0f, -1.0f);
            glVertex3f( 1.0f, -1.0f, -1.0f);
            glVertex3f( 1.0f, -1.0f,  1.0f);
            glVertex3f(-1.0f, -1.0f,  1.0f);

            // Right Side
            glVertex3f( 1.0f,  1.0f,  1.0f);
            glVertex3f( 1.0f, -1.0f,  1.0f);
            glVertex3f( 1.0f, -1.0f, -1.0f);
            glVertex3f( 1.0f,  1.0f, -1.0f);

            // Left Side
            glVertex3f(-1.0f, -1.0f, -1.0f);
            glVertex3f(-1.0f, -1.0f,  1.0f);
            glVertex3f(-1.0f,  1.0f,  1.0f);
            glVertex3f(-1.0f,  1.0f, -1.0f);
    glEnd();

    glLoadIdentity();

    glTranslatef(0.0f, 0.0f, -m_fZoom);
    glTranslatef(m_fPosX, m_fPosY, 0.0f);
    glRotatef(m_fRotX, 1.0f, 0.0f, 0.0f);
    glRotatef(m_fRotY, 0.0f, 1.0f, 0.0f);

    GLenum a = glGetError();

}


//--------------------------------------------------------

// Get an random integer within a specified range

//--------------------------------------------------------

int COpenGlView::randInt(const int& min, const int& max) {
    return ((rand()%(int)(((max) + 1)-(min)))+ (min)); 
}

//--------------------------------------------------------

// Get a random float within a specified range

//--------------------------------------------------------

float COpenGlView::randFloat(const float& min, const float& max) {
    float range = max - min;
    float num = range * rand() / RAND_MAX;
    return (num + min);
}

then i extended two more view classes from the same class class

C3dRightView : public COpenGlView 

and

C3dRightView : public COpenGlView 

then in childframe class i added splitter code and called these two classes in the splitter window. The problem is both opengl view code works fine but if i stop one of the initialization of opengl then the other one display. I tried everything and i cant display two different graphical opengl animation in both of these two different views. I have checked the HDC memory map and it seems like both classes are using parent with respect to their dynamic hdc object but if i stop ones code then other view display properly.

detail classes are below

class C3dRightView : public COpenGlView
{
    DECLARE_DYNCREATE(C3dRightView)

protected:
    GLuint m_left_texture[53];

    C3dRightView();           // protected constructor used by dynamic creation
    virtual ~C3dRightView();

public:
    virtual void OnDraw(CDC* pDC);      // overridden to draw this view
#ifdef _DEBUG
    virtual void AssertValid() const;
#ifndef _WIN32_WCE
    virtual void Dump(CDumpContext& dc) const;
#endif
#endif


protected:
    DECLARE_MESSAGE_MAP()
public:
    afx_msg void OnPaint();
    virtual void OnInitialUpdate();

    void oglDrawScene(void);
    void oglInitialize(void);
    afx_msg void OnTimer(UINT_PTR nIDEvent);
};


void C3dRightView::OnPaint()
{
    CPaintDC dc(this); // device context for painting
    // TODO: Add your message handler code here
    // Do not call CView::OnPaint() for painting messages
}



void C3dRightView::OnInitialUpdate()
{
    hdc = C3dRightView::GetDC()->m_hDC;

    /** If i open below code then left view stop displaying model **/
        COpenGlView::OnInitialUpdate();
        oglInitialize();
    //-=-=-=-=-=-=-==--=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

    oglBeginRendering();
    // TODO: Add your specialized code here and/or call the base class
}


void C3dRightView::oglInitialize(void)
{
    COpenGlView::oglInitialize();

}
void C3dRightView::oglDrawScene(void)
{
    // Wireframe Mode

    glShadeModel(GL_SMOOTH);    

    glClearColor(0.0f, 1.0f, 1.0f, 0.0f);

    glLoadIdentity();
    //glTranslatef(0.0f, 0.0f, -m_fZoom);//this is for zoom using left mouse click but no placing
    glTranslatef(m_fPosX, m_fPosY,-m_fZoom); // this is for placing + zooming using middle scroll button mouse click

    glRotatef(m_fRotX, 1.0f, 0.0f, 0.0f);//these two for mouse movement
    glRotatef(m_fRotY, 0.0f, 1.0f, 0.0f);
    glRotated(90,0.0f, 0.0f, -1.0f);
    glRotatef(180,1.0f,0,0.0f);
    GLenum a = glGetError();

    glBegin(GL_TRIANGLES);                              // Start Drawing A Triangle
        glColor3f(1.0f,0.0f,0.0f);                      // Red
        glVertex3f( 0.0f, 1.0f, 0.0f);                  // Top Of Triangle (Front)
        glColor3f(0.0f,1.0f,0.0f);                      // Green
        glVertex3f(-1.0f,-1.0f, 1.0f);                  // Left Of Triangle (Front)
        glColor3f(0.0f,0.0f,1.0f);                      // Blue
        glVertex3f( 1.0f,-1.0f, 1.0f);                  // Right Of Triangle (Front)
        glColor3f(1.0f,0.0f,0.0f);                      // Red
        glVertex3f( 0.0f, 1.0f, 0.0f);                  // Top Of Triangle (Right)
        glColor3f(0.0f,0.0f,1.0f);                      // Blue
        glVertex3f( 1.0f,-1.0f, 1.0f);                  // Left Of Triangle (Right)
        glColor3f(0.0f,1.0f,0.0f);                      // Green
        glVertex3f( 1.0f,-1.0f, -1.0f);                 // Right Of Triangle (Right)
        glColor3f(1.0f,0.0f,0.0f);                      // Red
        glVertex3f( 0.0f, 1.0f, 0.0f);                  // Top Of Triangle (Back)
        glColor3f(0.0f,1.0f,0.0f);                      // Green
        glVertex3f( 1.0f,-1.0f, -1.0f);                 // Left Of Triangle (Back)
        glColor3f(0.0f,0.0f,1.0f);                      // Blue
        glVertex3f(-1.0f,-1.0f, -1.0f);                 // Right Of Triangle (Back)
        glColor3f(1.0f,0.0f,0.0f);                      // Red
        glVertex3f( 0.0f, 1.0f, 0.0f);                  // Top Of Triangle (Left)
        glColor3f(0.0f,0.0f,1.0f);                      // Blue
        glVertex3f(-1.0f,-1.0f,-1.0f);                  // Left Of Triangle (Left)
        glColor3f(0.0f,1.0f,0.0f);                      // Green
        glVertex3f(-1.0f,-1.0f, 1.0f);                  // Right Of Triangle (Left)
    glEnd();    

}

the second view file is like this

class C3dLeftView : public COpenGlView
{
    DECLARE_DYNCREATE(C3dLeftView)

protected:
    GLuint m_left_texture[53];
    C3dLeftView();           // protected constructor used by dynamic creation
    virtual ~C3dLeftView();

public:
    virtual void OnDraw(CDC* pDC);      // overridden to draw this view
#ifdef _DEBUG
    virtual void AssertValid() const;
#ifndef _WIN32_WCE
    virtual void Dump(CDumpContext& dc) const;
#endif
#endif

protected:
    DECLARE_MESSAGE_MAP()
public:
    afx_msg void OnPaint();
    virtual void OnInitialUpdate();

    void oglDrawScene(void);
    void oglInitialize(void);
    afx_msg void OnTimer(UINT_PTR nIDEvent);
};


void C3dLeftView::OnPaint()
{
    CPaintDC dc(this); // device context for painting
    // TODO: Add your message handler code here
    // Do not call CView::OnPaint() for painting messages
}

void C3dLeftView::OnInitialUpdate()
{
    hdc = C3dLeftView::GetDC()->m_hDC;
    COpenGlView::OnInitialUpdate();
    oglInitialize();
    oglBeginRendering();
    // TODO: Add your specialized code here and/or call the base class
}


void C3dLeftView::oglInitialize(void)
{
    COpenGlView::oglInitialize();


}
void C3dLeftView::oglDrawScene(void)
{
    glShadeModel(GL_SMOOTH);    

    glClearColor(0.0f, 1.0f, 0.0f, 1.0f);

    glLoadIdentity();
    //glTranslatef(0.0f, 0.0f, -m_fZoom);//this is for zoom using left mouse click but no placing
    glTranslatef(m_fPosX, m_fPosY,-m_fZoom); // this is for placing + zooming using middle scroll button mouse click

    glRotatef(m_fRotX, 1.0f, 0.0f, 0.0f);//these two for mouse movement
    glRotatef(m_fRotY, 0.0f, 1.0f, 0.0f);
    glRotated(90,0.0f, 0.0f, -1.0f);
    glRotatef(180,1.0f,0,0.0f);
    GLenum a = glGetError();

    glBegin(GL_TRIANGLES);                              // Start Drawing A Triangle
        glColor3f(1.0f,0.0f,0.0f);                      // Red
        glVertex3f( 0.0f, 1.0f, 0.0f);                  // Top Of Triangle (Front)
        glColor3f(0.0f,1.0f,0.0f);                      // Green
        glVertex3f(-1.0f,-1.0f, 1.0f);                  // Left Of Triangle (Front)
        glColor3f(0.0f,0.0f,1.0f);                      // Blue
        glVertex3f( 1.0f,-1.0f, 1.0f);                  // Right Of Triangle (Front)
        glColor3f(1.0f,0.0f,0.0f);                      // Red
        glVertex3f( 0.0f, 1.0f, 0.0f);                  // Top Of Triangle (Right)
        glColor3f(0.0f,0.0f,1.0f);                      // Blue
        glVertex3f( 1.0f,-1.0f, 1.0f);                  // Left Of Triangle (Right)
        glColor3f(0.0f,1.0f,0.0f);                      // Green
        glVertex3f( 1.0f,-1.0f, -1.0f);                 // Right Of Triangle (Right)
        glColor3f(1.0f,0.0f,0.0f);                      // Red
        glVertex3f( 0.0f, 1.0f, 0.0f);                  // Top Of Triangle (Back)
        glColor3f(0.0f,1.0f,0.0f);                      // Green
        glVertex3f( 1.0f,-1.0f, -1.0f);                 // Left Of Triangle (Back)
        glColor3f(0.0f,0.0f,1.0f);                      // Blue
        glVertex3f(-1.0f,-1.0f, -1.0f);                 // Right Of Triangle (Back)
        glColor3f(1.0f,0.0f,0.0f);                      // Red
        glVertex3f( 0.0f, 1.0f, 0.0f);                  // Top Of Triangle (Left)
        glColor3f(0.0f,0.0f,1.0f);                      // Blue
        glVertex3f(-1.0f,-1.0f,-1.0f);                  // Left Of Triangle (Left)
        glColor3f(0.0f,1.0f,0.0f);                      // Green
        glVertex3f(-1.0f,-1.0f, 1.0f);                  // Right Of Triangle (Left)
    glEnd();    

    /*************************************************************************************/


}

if comment below code inside initialupdate function of the view then other view codes works fine.

    COpenGlView::OnInitialUpdate();
    oglInitialize();

some how the initialupdate code of the parent code works for its one child rather than two of them.

2

2 Answers

1
votes

Edit: no the reason can not be wglMakeCurrent() like I initially thought, you seem to call it enough.

The reason may be that you call your oglInitialize() too lot of times however. It depends how you create your views and splitters, but that code you did not post. One way to fix it is to limit how lot of times your views will actually "initially update".

Initialize your hdc member to 0 in constructor (actually always initialize all members in constructors):

COpenGlView::COpenGlView()
{
    hdc = 0;
    // ... etc your stuff
}

Do your ogl initialization only once when hdc is 0:

void C3dRightView::OnInitialUpdate()
{
    if ( hdc == 0 )
    {
        hdc = GetDC()->m_hDC;
        COpenGlView::OnInitialUpdate();
        oglBeginRendering();
    }
}

Here too:

void C3dLeftView::OnInitialUpdate()
{
    if ( hdc == 0 )
    {
        hdc = GetDC()->m_hDC;
        COpenGlView::OnInitialUpdate();
        oglBeginRendering();
    }
}

That should work I trust.

Edit2: Tried your code. C3dRightView::OnInitialUpdate was not like I posted above. I am not exactly sure what messes up the initialization. For example following fix to CChildFrame::OnCreateClient seems to work:

if (!m_wndSplitter.CreateView( 0, 1, RUNTIME_CLASS(C3dRightView), CSize(cr.Width()/2, cr.Height()), pContext))
{
    MessageBox(L"Error setting up splitter frames!", L"Init Error!", MB_OK | MB_ICONERROR);
    return FALSE;
}

// had to add this line here:
m_wndSplitter.GetPane( 0, 1 )->SendMessage(WM_INITIALUPDATE);

return TRUE;
-1
votes

Even though it might be late, but here is my answer which can help you in future :)

in Ontimer function call pdoc->UpdateAll(NULL,NULL,NULL) function. pdoc is pointer to your documents class. It will request all views to update, and you will get both windows working :).