reorganized the code to put the logic in wxGLContext-derived class but keep the state in the window
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@45476 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
		@@ -66,79 +66,29 @@ int MyApp::OnExit()
 | 
			
		||||
    return wxApp::OnExit();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MyApp::SetCurrent(wxGLCanvas *canvas)
 | 
			
		||||
TestGLContext& MyApp::GetContext(wxGLCanvas *canvas)
 | 
			
		||||
{
 | 
			
		||||
    wxCHECK_RET( canvas, _T("canvas can't be NULL") );
 | 
			
		||||
 | 
			
		||||
    if ( !m_glContext )
 | 
			
		||||
        m_glContext = new wxGLContext(canvas);
 | 
			
		||||
        m_glContext = new TestGLContext(canvas);
 | 
			
		||||
 | 
			
		||||
    m_glContext->SetCurrent(*canvas);
 | 
			
		||||
 | 
			
		||||
    return *m_glContext;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ----------------------------------------------------------------------------
 | 
			
		||||
// TestGLCanvas
 | 
			
		||||
// TestGLContext
 | 
			
		||||
// ----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
BEGIN_EVENT_TABLE(TestGLCanvas, wxGLCanvas)
 | 
			
		||||
    EVT_SIZE(TestGLCanvas::OnSize)
 | 
			
		||||
    EVT_PAINT(TestGLCanvas::OnPaint)
 | 
			
		||||
 | 
			
		||||
    EVT_KEY_DOWN(TestGLCanvas::OnKeyDown)
 | 
			
		||||
END_EVENT_TABLE()
 | 
			
		||||
 | 
			
		||||
static const int attribs[] = { WX_GL_RGBA, WX_GL_DOUBLEBUFFER, 0 };
 | 
			
		||||
 | 
			
		||||
TestGLCanvas::TestGLCanvas(wxWindow *parent)
 | 
			
		||||
            : wxGLCanvas(parent, wxID_ANY, NULL /* attribs */)
 | 
			
		||||
TestGLContext::TestGLContext(wxGLCanvas *canvas)
 | 
			
		||||
             : wxGLContext(canvas)
 | 
			
		||||
{
 | 
			
		||||
    m_gllist = 0;
 | 
			
		||||
 | 
			
		||||
    // notice that we can't call InitGL() from here: we must wait until the
 | 
			
		||||
    // window is shown on screen to be able to perform OpenGL calls
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// this function is called on each repaint so it should be fast
 | 
			
		||||
void TestGLCanvas::Render()
 | 
			
		||||
void TestGLContext::Init()
 | 
			
		||||
{
 | 
			
		||||
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 | 
			
		||||
    glCallList(m_gllist);
 | 
			
		||||
 | 
			
		||||
    glFlush();
 | 
			
		||||
    SwapBuffers();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TestGLCanvas::OnPaint(wxPaintEvent& WXUNUSED(event))
 | 
			
		||||
{
 | 
			
		||||
    wxGetApp().SetCurrent(this);
 | 
			
		||||
 | 
			
		||||
    // initialize if not done yet
 | 
			
		||||
    InitGL();
 | 
			
		||||
 | 
			
		||||
    wxPaintDC dc(this);
 | 
			
		||||
 | 
			
		||||
    Render();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TestGLCanvas::OnSize(wxSizeEvent& event)
 | 
			
		||||
{
 | 
			
		||||
    // don't prevent default processing from taking place
 | 
			
		||||
    event.Skip();
 | 
			
		||||
 | 
			
		||||
    if ( !IsInitialized() )
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    // set GL viewport (not called by wxGLCanvas::OnSize on all platforms...)
 | 
			
		||||
    int w, h;
 | 
			
		||||
    GetClientSize(&w, &h);
 | 
			
		||||
 | 
			
		||||
    wxGetApp().SetCurrent(this);
 | 
			
		||||
    glViewport(0, 0, w, h);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TestGLCanvas::InitGL()
 | 
			
		||||
{
 | 
			
		||||
    if ( IsInitialized() )
 | 
			
		||||
    if ( m_gllist )
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    /* set viewing projection */
 | 
			
		||||
@@ -146,21 +96,12 @@ void TestGLCanvas::InitGL()
 | 
			
		||||
    glLoadIdentity();
 | 
			
		||||
    glFrustum(-0.5f, 0.5f, -0.5f, 0.5f, 1.0f, 3.0f);
 | 
			
		||||
 | 
			
		||||
    /* position viewer */
 | 
			
		||||
    glMatrixMode(GL_MODELVIEW);
 | 
			
		||||
    glLoadIdentity();
 | 
			
		||||
    glTranslatef(0.0f, 0.0f, -2.0f);
 | 
			
		||||
 | 
			
		||||
    /* position object */
 | 
			
		||||
    glRotatef(30.0f, 1.0f, 0.0f, 0.0f);
 | 
			
		||||
    glRotatef(30.0f, 0.0f, 1.0f, 0.0f);
 | 
			
		||||
 | 
			
		||||
    glEnable(GL_DEPTH_TEST);
 | 
			
		||||
    glEnable(GL_LIGHTING);
 | 
			
		||||
    glEnable(GL_LIGHT0);
 | 
			
		||||
 | 
			
		||||
    // create the list of commands to draw the cube: then we can just (quickly)
 | 
			
		||||
    // execute it in Render() later
 | 
			
		||||
    // execute it in DrawRotatedCube() later
 | 
			
		||||
    m_gllist = glGenLists(1);
 | 
			
		||||
    glNewList(m_gllist, GL_COMPILE);
 | 
			
		||||
 | 
			
		||||
@@ -194,11 +135,69 @@ void TestGLCanvas::InitGL()
 | 
			
		||||
    glEndList();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TestGLContext::DrawRotatedCube(float xangle, float yangle)
 | 
			
		||||
{
 | 
			
		||||
    Init();
 | 
			
		||||
 | 
			
		||||
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 | 
			
		||||
 | 
			
		||||
    glMatrixMode(GL_MODELVIEW);
 | 
			
		||||
    glLoadIdentity();
 | 
			
		||||
    glTranslatef(0.0f, 0.0f, -2.0f);
 | 
			
		||||
    glRotatef(xangle, 1.0f, 0.0f, 0.0f);
 | 
			
		||||
    glRotatef(yangle, 0.0f, 1.0f, 0.0f);
 | 
			
		||||
 | 
			
		||||
    glCallList(m_gllist);
 | 
			
		||||
 | 
			
		||||
    glFlush();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ----------------------------------------------------------------------------
 | 
			
		||||
// TestGLCanvas
 | 
			
		||||
// ----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
BEGIN_EVENT_TABLE(TestGLCanvas, wxGLCanvas)
 | 
			
		||||
    EVT_SIZE(TestGLCanvas::OnSize)
 | 
			
		||||
    EVT_PAINT(TestGLCanvas::OnPaint)
 | 
			
		||||
 | 
			
		||||
    EVT_KEY_DOWN(TestGLCanvas::OnKeyDown)
 | 
			
		||||
END_EVENT_TABLE()
 | 
			
		||||
 | 
			
		||||
TestGLCanvas::TestGLCanvas(wxWindow *parent)
 | 
			
		||||
            : wxGLCanvas(parent, wxID_ANY, NULL /* attribs */)
 | 
			
		||||
{
 | 
			
		||||
    m_xangle =
 | 
			
		||||
    m_yangle = 30;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TestGLCanvas::OnPaint(wxPaintEvent& WXUNUSED(event))
 | 
			
		||||
{
 | 
			
		||||
    wxPaintDC dc(this);
 | 
			
		||||
 | 
			
		||||
    wxGetApp().GetContext(this).DrawRotatedCube(m_xangle, m_yangle);
 | 
			
		||||
 | 
			
		||||
    SwapBuffers();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TestGLCanvas::OnSize(wxSizeEvent& event)
 | 
			
		||||
{
 | 
			
		||||
    // don't prevent default processing from taking place
 | 
			
		||||
    event.Skip();
 | 
			
		||||
 | 
			
		||||
    if ( !IsShown() )
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    // set GL viewport (not called by wxGLCanvas::OnSize on all platforms...)
 | 
			
		||||
    int w, h;
 | 
			
		||||
    GetClientSize(&w, &h);
 | 
			
		||||
 | 
			
		||||
    wxGetApp().GetContext(this);
 | 
			
		||||
    glViewport(0, 0, w, h);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TestGLCanvas::OnKeyDown( wxKeyEvent& event )
 | 
			
		||||
{
 | 
			
		||||
    GLfloat x = 0,
 | 
			
		||||
            y = 0,
 | 
			
		||||
            z = 0;
 | 
			
		||||
    float *p = NULL;
 | 
			
		||||
 | 
			
		||||
    bool inverse = false;
 | 
			
		||||
 | 
			
		||||
@@ -209,8 +208,8 @@ void TestGLCanvas::OnKeyDown( wxKeyEvent& event )
 | 
			
		||||
            // fall through
 | 
			
		||||
 | 
			
		||||
        case WXK_LEFT:
 | 
			
		||||
            // rotate around Z axis
 | 
			
		||||
            z = 1;
 | 
			
		||||
            // rotate around Y axis
 | 
			
		||||
            p = &m_yangle;
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case WXK_DOWN:
 | 
			
		||||
@@ -218,8 +217,8 @@ void TestGLCanvas::OnKeyDown( wxKeyEvent& event )
 | 
			
		||||
            // fall through
 | 
			
		||||
 | 
			
		||||
        case WXK_UP:
 | 
			
		||||
            // rotate around Y axis
 | 
			
		||||
            y = 1;
 | 
			
		||||
            // rotate around X axis
 | 
			
		||||
            p = &m_xangle;
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        default:
 | 
			
		||||
@@ -231,19 +230,9 @@ void TestGLCanvas::OnKeyDown( wxKeyEvent& event )
 | 
			
		||||
    if ( inverse )
 | 
			
		||||
        angle = -angle;
 | 
			
		||||
 | 
			
		||||
    wxGetApp().SetCurrent(this);
 | 
			
		||||
    *p += angle;
 | 
			
		||||
 | 
			
		||||
    glMatrixMode(GL_MODELVIEW);
 | 
			
		||||
    glRotatef(angle, x, y, z);
 | 
			
		||||
 | 
			
		||||
    // refresh all cubes
 | 
			
		||||
    for ( wxWindowList::const_iterator i = wxTopLevelWindows.begin();
 | 
			
		||||
          i != wxTopLevelWindows.end();
 | 
			
		||||
          ++i )
 | 
			
		||||
    {
 | 
			
		||||
        MyFrame *frame = (MyFrame *)*i;
 | 
			
		||||
        frame->RefreshCanvas();
 | 
			
		||||
    }
 | 
			
		||||
    Refresh(false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ----------------------------------------------------------------------------
 | 
			
		||||
@@ -256,10 +245,9 @@ BEGIN_EVENT_TABLE(MyFrame, wxFrame)
 | 
			
		||||
END_EVENT_TABLE()
 | 
			
		||||
 | 
			
		||||
MyFrame::MyFrame()
 | 
			
		||||
       : wxFrame(NULL, wxID_ANY, _T("wxWidgets OpenGL Cube Sample"),
 | 
			
		||||
                 wxDefaultPosition, wxSize(400, 300))
 | 
			
		||||
       : wxFrame(NULL, wxID_ANY, _T("wxWidgets OpenGL Cube Sample"))
 | 
			
		||||
{
 | 
			
		||||
    m_canvas = new TestGLCanvas(this);
 | 
			
		||||
    new TestGLCanvas(this);
 | 
			
		||||
 | 
			
		||||
    SetIcon(wxICON(sample));
 | 
			
		||||
 | 
			
		||||
@@ -275,6 +263,7 @@ MyFrame::MyFrame()
 | 
			
		||||
 | 
			
		||||
    CreateStatusBar();
 | 
			
		||||
 | 
			
		||||
    SetClientSize(400, 400);
 | 
			
		||||
    Show();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -289,7 +278,3 @@ void MyFrame::OnNewWindow( wxCommandEvent& WXUNUSED(event) )
 | 
			
		||||
    (void) new MyFrame();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MyFrame::RefreshCanvas()
 | 
			
		||||
{
 | 
			
		||||
    m_canvas->Refresh(false);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -14,14 +14,32 @@
 | 
			
		||||
 | 
			
		||||
#include "wx/glcanvas.h"
 | 
			
		||||
 | 
			
		||||
// the rendering context used by all GL canvases
 | 
			
		||||
class TestGLContext : public wxGLContext
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    TestGLContext(wxGLCanvas *canvas);
 | 
			
		||||
 | 
			
		||||
    // render the cube showing it at given angles
 | 
			
		||||
    void DrawRotatedCube(float xangle, float yangle);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    // one-time OpenGL initialization, safe to call many times
 | 
			
		||||
    void Init();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    // the list of commands to draw the cube
 | 
			
		||||
    GLuint m_gllist;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Define a new application type
 | 
			
		||||
class MyApp: public wxApp
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    MyApp() { m_glContext = NULL; }
 | 
			
		||||
 | 
			
		||||
    // set the specified canvas for current output
 | 
			
		||||
    void SetCurrent(wxGLCanvas *canvas);
 | 
			
		||||
    // get the context we use creating it on demand (and set it as current)
 | 
			
		||||
    TestGLContext& GetContext(wxGLCanvas *canvas);
 | 
			
		||||
 | 
			
		||||
    // virtual wxApp methods
 | 
			
		||||
    virtual bool OnInit();
 | 
			
		||||
@@ -29,29 +47,21 @@ public:
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    // the GL context we use for all our windows
 | 
			
		||||
    wxGLContext *m_glContext;
 | 
			
		||||
    TestGLContext *m_glContext;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Define a new frame type
 | 
			
		||||
class TestGLCanvas;
 | 
			
		||||
 | 
			
		||||
class MyFrame: public wxFrame
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    MyFrame();
 | 
			
		||||
 | 
			
		||||
    // update the image shown on the canvas (after the shared wxGLContext was
 | 
			
		||||
    // updated, presumably)
 | 
			
		||||
    void RefreshCanvas();
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    void OnClose(wxCommandEvent& event);
 | 
			
		||||
    void OnNewWindow(wxCommandEvent& event);
 | 
			
		||||
    void OnDefRotateLeftKey(wxCommandEvent& event);
 | 
			
		||||
    void OnDefRotateRightKey(wxCommandEvent& event);
 | 
			
		||||
 | 
			
		||||
    TestGLCanvas *m_canvas;
 | 
			
		||||
 | 
			
		||||
    DECLARE_EVENT_TABLE()
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -65,18 +75,9 @@ private:
 | 
			
		||||
    void OnSize(wxSizeEvent& event);
 | 
			
		||||
    void OnKeyDown(wxKeyEvent& event);
 | 
			
		||||
 | 
			
		||||
    // OpenGL calls can't be done until we're initialized
 | 
			
		||||
    bool IsInitialized() const { return m_gllist != 0; }
 | 
			
		||||
 | 
			
		||||
    // one-time OpenGL initialization, only does something if !IsInitialized()
 | 
			
		||||
    void InitGL();
 | 
			
		||||
 | 
			
		||||
    // render to window
 | 
			
		||||
    void Render();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    // the list of commands to draw the cube
 | 
			
		||||
    GLuint m_gllist;
 | 
			
		||||
    // angles of rotation around x- and y- axis
 | 
			
		||||
    float m_xangle,
 | 
			
		||||
          m_yangle;
 | 
			
		||||
 | 
			
		||||
    DECLARE_EVENT_TABLE()
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user