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:
Vadim Zeitlin
2007-04-15 00:54:32 +00:00
parent 43c05cf8e1
commit 50f5d508a8
2 changed files with 104 additions and 118 deletions

View File

@@ -66,79 +66,29 @@ int MyApp::OnExit()
return wxApp::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 ) if ( !m_glContext )
m_glContext = new wxGLContext(canvas); m_glContext = new TestGLContext(canvas);
m_glContext->SetCurrent(*canvas); m_glContext->SetCurrent(*canvas);
return *m_glContext;
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// TestGLCanvas // TestGLContext
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
BEGIN_EVENT_TABLE(TestGLCanvas, wxGLCanvas) TestGLContext::TestGLContext(wxGLCanvas *canvas)
EVT_SIZE(TestGLCanvas::OnSize) : wxGLContext(canvas)
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 */)
{ {
m_gllist = 0; 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 TestGLContext::Init()
void TestGLCanvas::Render()
{ {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); if ( m_gllist )
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() )
return; return;
/* set viewing projection */ /* set viewing projection */
@@ -146,21 +96,12 @@ void TestGLCanvas::InitGL()
glLoadIdentity(); glLoadIdentity();
glFrustum(-0.5f, 0.5f, -0.5f, 0.5f, 1.0f, 3.0f); 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_DEPTH_TEST);
glEnable(GL_LIGHTING); glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0); glEnable(GL_LIGHT0);
// create the list of commands to draw the cube: then we can just (quickly) // 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); m_gllist = glGenLists(1);
glNewList(m_gllist, GL_COMPILE); glNewList(m_gllist, GL_COMPILE);
@@ -194,11 +135,69 @@ void TestGLCanvas::InitGL()
glEndList(); 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 ) void TestGLCanvas::OnKeyDown( wxKeyEvent& event )
{ {
GLfloat x = 0, float *p = NULL;
y = 0,
z = 0;
bool inverse = false; bool inverse = false;
@@ -209,8 +208,8 @@ void TestGLCanvas::OnKeyDown( wxKeyEvent& event )
// fall through // fall through
case WXK_LEFT: case WXK_LEFT:
// rotate around Z axis // rotate around Y axis
z = 1; p = &m_yangle;
break; break;
case WXK_DOWN: case WXK_DOWN:
@@ -218,8 +217,8 @@ void TestGLCanvas::OnKeyDown( wxKeyEvent& event )
// fall through // fall through
case WXK_UP: case WXK_UP:
// rotate around Y axis // rotate around X axis
y = 1; p = &m_xangle;
break; break;
default: default:
@@ -231,19 +230,9 @@ void TestGLCanvas::OnKeyDown( wxKeyEvent& event )
if ( inverse ) if ( inverse )
angle = -angle; angle = -angle;
wxGetApp().SetCurrent(this); *p += angle;
glMatrixMode(GL_MODELVIEW); Refresh(false);
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();
}
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -256,10 +245,9 @@ BEGIN_EVENT_TABLE(MyFrame, wxFrame)
END_EVENT_TABLE() END_EVENT_TABLE()
MyFrame::MyFrame() MyFrame::MyFrame()
: wxFrame(NULL, wxID_ANY, _T("wxWidgets OpenGL Cube Sample"), : wxFrame(NULL, wxID_ANY, _T("wxWidgets OpenGL Cube Sample"))
wxDefaultPosition, wxSize(400, 300))
{ {
m_canvas = new TestGLCanvas(this); new TestGLCanvas(this);
SetIcon(wxICON(sample)); SetIcon(wxICON(sample));
@@ -275,6 +263,7 @@ MyFrame::MyFrame()
CreateStatusBar(); CreateStatusBar();
SetClientSize(400, 400);
Show(); Show();
} }
@@ -289,7 +278,3 @@ void MyFrame::OnNewWindow( wxCommandEvent& WXUNUSED(event) )
(void) new MyFrame(); (void) new MyFrame();
} }
void MyFrame::RefreshCanvas()
{
m_canvas->Refresh(false);
}

View File

@@ -14,14 +14,32 @@
#include "wx/glcanvas.h" #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 // Define a new application type
class MyApp: public wxApp class MyApp: public wxApp
{ {
public: public:
MyApp() { m_glContext = NULL; } MyApp() { m_glContext = NULL; }
// set the specified canvas for current output // get the context we use creating it on demand (and set it as current)
void SetCurrent(wxGLCanvas *canvas); TestGLContext& GetContext(wxGLCanvas *canvas);
// virtual wxApp methods // virtual wxApp methods
virtual bool OnInit(); virtual bool OnInit();
@@ -29,29 +47,21 @@ public:
private: private:
// the GL context we use for all our windows // the GL context we use for all our windows
wxGLContext *m_glContext; TestGLContext *m_glContext;
}; };
// Define a new frame type // Define a new frame type
class TestGLCanvas;
class MyFrame: public wxFrame class MyFrame: public wxFrame
{ {
public: public:
MyFrame(); MyFrame();
// update the image shown on the canvas (after the shared wxGLContext was
// updated, presumably)
void RefreshCanvas();
private: private:
void OnClose(wxCommandEvent& event); void OnClose(wxCommandEvent& event);
void OnNewWindow(wxCommandEvent& event); void OnNewWindow(wxCommandEvent& event);
void OnDefRotateLeftKey(wxCommandEvent& event); void OnDefRotateLeftKey(wxCommandEvent& event);
void OnDefRotateRightKey(wxCommandEvent& event); void OnDefRotateRightKey(wxCommandEvent& event);
TestGLCanvas *m_canvas;
DECLARE_EVENT_TABLE() DECLARE_EVENT_TABLE()
}; };
@@ -65,18 +75,9 @@ private:
void OnSize(wxSizeEvent& event); void OnSize(wxSizeEvent& event);
void OnKeyDown(wxKeyEvent& event); void OnKeyDown(wxKeyEvent& event);
// OpenGL calls can't be done until we're initialized // angles of rotation around x- and y- axis
bool IsInitialized() const { return m_gllist != 0; } float m_xangle,
m_yangle;
// 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;
DECLARE_EVENT_TABLE() DECLARE_EVENT_TABLE()
}; };