#include "../../sample.xpm"
#endif
+// ----------------------------------------------------------------------------
+// constants
+// ----------------------------------------------------------------------------
+
+// control ids
+enum
+{
+ SpinTimer = wxID_HIGHEST + 1
+};
+
// ----------------------------------------------------------------------------
// helper functions
// ----------------------------------------------------------------------------
// so check that we get a different error than the last time
if ( err == errLast )
{
- wxLogError(_T("OpenGL error state couldn't be reset."));
+ wxLogError(wxT("OpenGL error state couldn't be reset."));
return;
}
errLast = err;
- wxLogError(_T("OpenGL error %d"), err);
+ wxLogError(wxT("OpenGL error %d"), err);
}
}
// function to draw the texture for cube faces
static wxImage DrawDice(int size, unsigned num)
{
- wxASSERT_MSG( num >= 1 && num <= 6, _T("invalid dice index") );
+ wxASSERT_MSG( num >= 1 && num <= 6, wxT("invalid dice index") );
const int dot = size/16; // radius of a single dot
const int gap = 5*size/32; // gap between dots
// implementation
// ============================================================================
-// ----------------------------------------------------------------------------
-// MyApp: the application object
-// ----------------------------------------------------------------------------
-
-IMPLEMENT_APP(MyApp)
-
-bool MyApp::OnInit()
-{
- if ( !wxApp::OnInit() )
- return false;
-
- // Create the main window
- new MyFrame();
-
- return true;
-}
-
-int MyApp::OnExit()
-{
- delete m_glContext;
-
- return wxApp::OnExit();
-}
-
-TestGLContext& MyApp::GetContext(wxGLCanvas *canvas)
-{
- if ( !m_glContext )
- m_glContext = new TestGLContext(canvas);
- else
- m_glContext->SetCurrent(*canvas);
-
- return *m_glContext;
-}
-
// ----------------------------------------------------------------------------
// TestGLContext
// ----------------------------------------------------------------------------
glEnable(GL_LIGHT0);
glEnable(GL_TEXTURE_2D);
- // add slightly more light, the default lightning is rather dark
+ // add slightly more light, the default lighting is rather dark
GLfloat ambient[] = { 0.5, 0.5, 0.5, 0.5 };
glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
const wxImage img(DrawDice(256, i + 1));
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img.GetWidth(), img.GetHeight(),
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img.GetWidth(), img.GetHeight(),
0, GL_RGB, GL_UNSIGNED_BYTE, img.GetData());
}
CheckGLError();
}
+
+// ----------------------------------------------------------------------------
+// MyApp: the application object
+// ----------------------------------------------------------------------------
+
+IMPLEMENT_APP(MyApp)
+
+bool MyApp::OnInit()
+{
+ if ( !wxApp::OnInit() )
+ return false;
+
+ new MyFrame();
+
+ return true;
+}
+
+int MyApp::OnExit()
+{
+ delete m_glContext;
+
+ return wxApp::OnExit();
+}
+
+TestGLContext& MyApp::GetContext(wxGLCanvas *canvas)
+{
+ if ( !m_glContext )
+ {
+ // Create the OpenGL context for the first window which needs it:
+ // subsequently created windows will all share the same context.
+ m_glContext = new TestGLContext(canvas);
+ }
+
+ m_glContext->SetCurrent(*canvas);
+
+ return *m_glContext;
+}
+
// ----------------------------------------------------------------------------
// TestGLCanvas
// ----------------------------------------------------------------------------
BEGIN_EVENT_TABLE(TestGLCanvas, wxGLCanvas)
- EVT_SIZE(TestGLCanvas::OnSize)
EVT_PAINT(TestGLCanvas::OnPaint)
-
EVT_KEY_DOWN(TestGLCanvas::OnKeyDown)
+ EVT_TIMER(SpinTimer, TestGLCanvas::OnSpinTimer)
END_EVENT_TABLE()
TestGLCanvas::TestGLCanvas(wxWindow *parent)
- : wxGLCanvas(parent, wxID_ANY, NULL /* attribs */)
+ // With perspective OpenGL graphics, the wxFULL_REPAINT_ON_RESIZE style
+ // flag should always be set, because even making the canvas smaller should
+ // be followed by a paint event that updates the entire canvas with new
+ // viewport settings.
+ : wxGLCanvas(parent, wxID_ANY, NULL /* attribs */,
+ wxDefaultPosition, wxDefaultSize,
+ wxFULL_REPAINT_ON_RESIZE),
+ m_xangle(30.0),
+ m_yangle(30.0),
+ m_spinTimer(this,SpinTimer)
{
- m_xangle =
- m_yangle = 30;
}
void TestGLCanvas::OnPaint(wxPaintEvent& WXUNUSED(event))
{
+ // This is required even though dc is not used otherwise.
wxPaintDC dc(this);
- wxGetApp().GetContext(this).DrawRotatedCube(m_xangle, m_yangle);
+ // Set the OpenGL viewport according to the client size of this canvas.
+ // This is done here rather than in a wxSizeEvent handler because our
+ // OpenGL rendering context (and thus viewport setting) is used with
+ // multiple canvases: If we updated the viewport in the wxSizeEvent
+ // handler, changing the size of one canvas causes a viewport setting that
+ // is wrong when next another canvas is repainted.
+ const wxSize ClientSize = GetClientSize();
+
+ glViewport(0, 0, ClientSize.x, ClientSize.y);
+ // Render the graphics and swap the buffers.
+ wxGetApp().GetContext(this).DrawRotatedCube(m_xangle, m_yangle);
SwapBuffers();
}
-void TestGLCanvas::OnSize(wxSizeEvent& event)
+void TestGLCanvas::Spin(float xSpin, float ySpin)
{
- // don't prevent default processing from taking place
- event.Skip();
+ m_xangle += xSpin;
+ m_yangle += ySpin;
- 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);
+ Refresh(false);
}
-void TestGLCanvas::OnKeyDown( wxKeyEvent& event )
+void TestGLCanvas::OnKeyDown(wxKeyEvent& event)
{
- float *p = NULL;
-
- bool inverse = false;
+ float angle = 5.0;
switch ( event.GetKeyCode() )
{
case WXK_RIGHT:
- inverse = true;
- // fall through
+ Spin( 0.0, -angle );
+ break;
case WXK_LEFT:
- // rotate around Y axis
- p = &m_yangle;
+ Spin( 0.0, angle );
break;
case WXK_DOWN:
- inverse = true;
- // fall through
+ Spin( -angle, 0.0 );
+ break;
case WXK_UP:
- // rotate around X axis
- p = &m_xangle;
+ Spin( angle, 0.0 );
+ break;
+
+ case WXK_SPACE:
+ if ( m_spinTimer.IsRunning() )
+ m_spinTimer.Stop();
+ else
+ m_spinTimer.Start( 25 );
break;
default:
event.Skip();
return;
}
+}
- float angle = 5;
- if ( inverse )
- angle = -angle;
-
- *p += angle;
-
- Refresh(false);
+void TestGLCanvas::OnSpinTimer(wxTimerEvent& WXUNUSED(event))
+{
+ Spin(0.0, 4.0);
}
+
// ----------------------------------------------------------------------------
// MyFrame: main application window
// ----------------------------------------------------------------------------
END_EVENT_TABLE()
MyFrame::MyFrame()
- : wxFrame(NULL, wxID_ANY, _T("wxWidgets OpenGL Cube Sample"))
+ : wxFrame(NULL, wxID_ANY, wxT("wxWidgets OpenGL Cube Sample"))
{
new TestGLCanvas(this);
menu->AppendSeparator();
menu->Append(wxID_CLOSE);
wxMenuBar *menuBar = new wxMenuBar;
- menuBar->Append(menu, _T("&Cube"));
+ menuBar->Append(menu, wxT("&Cube"));
SetMenuBar(menuBar);
SetClientSize(400, 400);
Show();
+
+ // test IsDisplaySupported() function:
+ static const int attribs[] = { WX_GL_RGBA, WX_GL_DOUBLEBUFFER, 0 };
+ wxLogStatus("Double-buffered display %s supported",
+ wxGLCanvas::IsDisplaySupported(attribs) ? "is" : "not");
}
void MyFrame::OnClose(wxCommandEvent& WXUNUSED(event))
void MyFrame::OnNewWindow( wxCommandEvent& WXUNUSED(event) )
{
- (void) new MyFrame();
+ new MyFrame();
}