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();
|
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);
|
|
||||||
}
|
|
||||||
|
@@ -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()
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user