1. switched to new wxGLCanvas API (not using the implicit context)

2. pruned everything not related to OpenGL, making the remaining code much
   more readable
3. show using the same wxGLContext with multiple wxGLCanvases


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@45369 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2007-04-09 22:54:40 +00:00
parent bbe645133b
commit 43c742d005
2 changed files with 169 additions and 452 deletions

View File

@@ -1,13 +1,21 @@
///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Name: cube.cpp // Name: cube.cpp
// Purpose: wxGLCanvas demo program // Purpose: wxGLCanvas demo program
// Author: Julian Smart // Author: Julian Smart
// Modified by: // Modified by: Vadim Zeitlin to use new wxGLCanvas API (2007-04-09)
// Created: 04/01/98 // Created: 04/01/98
// RCS-ID: $Id$ // RCS-ID: $Id$
// Copyright: (c) Julian Smart // Copyright: (c) Julian Smart
// Licence: wxWindows licence // Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
// For compilers that support precompilation, includes "wx.h". // For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h" #include "wx/wxprec.h"
@@ -25,290 +33,109 @@
#endif #endif
#include "cube.h" #include "cube.h"
#include "../../sample.xpm"
#ifndef __WXMSW__ // for StopWatch, see remark below #if !defined(__WXMSW__) && !defined(__WXPM__)
#if defined(__WXMAC__) && !defined(__DARWIN__) #include "../../sample.xpm"
#include <utime.h>
#include <unistd.h>
#else
#include <sys/time.h>
#include <sys/unistd.h>
#endif
#else
#include <sys/timeb.h>
#endif #endif
#define ID_NEW_WINDOW 10000 // ============================================================================
#define ID_DEF_ROTATE_LEFT_KEY 10001 // implementation
#define ID_DEF_ROTATE_RIGHT_KEY 10002 // ============================================================================
/*---------------------------------------------------------- // ----------------------------------------------------------------------------
Control to get a keycode // MyApp: the application object
----------------------------------------------------------*/ // ----------------------------------------------------------------------------
class ScanCodeCtrl : public wxTextCtrl
IMPLEMENT_APP(MyApp)
bool MyApp::OnInit()
{ {
public: if ( !wxApp::OnInit() )
ScanCodeCtrl( wxWindow* parent, wxWindowID id, int code, return false;
const wxPoint& pos, const wxSize& size );
void OnChar( wxKeyEvent& WXUNUSED(event) ) // Create the main window
{ new MyFrame();
// Do nothing
}
void OnKeyDown(wxKeyEvent& event); return true;
private:
// Any class wishing to process wxWidgets events must use this macro
DECLARE_EVENT_TABLE()
};
BEGIN_EVENT_TABLE( ScanCodeCtrl, wxTextCtrl )
EVT_CHAR( ScanCodeCtrl::OnChar )
EVT_KEY_DOWN( ScanCodeCtrl::OnKeyDown )
END_EVENT_TABLE()
ScanCodeCtrl::ScanCodeCtrl( wxWindow* parent, wxWindowID id, int code,
const wxPoint& pos, const wxSize& size )
: wxTextCtrl( parent, id, wxEmptyString, pos, size )
{
SetValue( wxString::Format(wxT("0x%04x"), code) );
} }
void ScanCodeCtrl::OnKeyDown( wxKeyEvent& event ) int MyApp::OnExit()
{ {
SetValue( wxString::Format(wxT("0x%04x"), event.GetKeyCode()) ); delete m_glContext;
return wxApp::OnExit();
} }
/*------------------------------------------------------------------ void MyApp::SetCurrent(wxGLCanvas *canvas)
Dialog for defining a keypress
-------------------------------------------------------------------*/
class ScanCodeDialog : public wxDialog
{ {
public: wxCHECK_RET( canvas, _T("canvas can't be NULL") );
ScanCodeDialog( wxWindow* parent, wxWindowID id, const int code,
const wxString &descr, const wxString& title );
int GetValue();
private: if ( !m_glContext )
m_glContext = new wxGLContext(canvas);
ScanCodeCtrl *m_ScanCode; m_glContext->SetCurrent(*canvas);
wxTextCtrl *m_Description;
};
ScanCodeDialog::ScanCodeDialog( wxWindow* parent, wxWindowID id,
const int code, const wxString &descr, const wxString& title )
: wxDialog( parent, id, title, wxDefaultPosition, wxSize(96*2,76*2) )
{
new wxStaticText( this, wxID_ANY, _T("Scancode"), wxPoint(4*2,3*2),
wxSize(31*2,12*2) );
m_ScanCode = new ScanCodeCtrl( this, wxID_ANY, code, wxPoint(37*2,6*2),
wxSize(53*2,14*2) );
new wxStaticText( this, wxID_ANY, _T("Description"), wxPoint(4*2,24*2),
wxSize(32*2,12*2) );
m_Description = new wxTextCtrl( this, wxID_ANY, descr, wxPoint(37*2,27*2),
wxSize(53*2,14*2) );
new wxButton( this, wxID_OK, _T("Ok"), wxPoint(20*2,50*2), wxSize(20*2,13*2) );
new wxButton( this, wxID_CANCEL, _T("Cancel"), wxPoint(44*2,50*2),
wxSize(25*2,13*2) );
} }
int ScanCodeDialog::GetValue() // ----------------------------------------------------------------------------
{ // TestGLCanvas
int code; // ----------------------------------------------------------------------------
wxString buf = m_ScanCode->GetValue();
wxSscanf( buf.c_str(), _T("%i"), &code );
return code;
}
/*----------------------------------------------------------------------
Utility function to get the elapsed time (in msec) since a given point
in time (in sec) (because current version of wxGetElapsedTime doesn<73>t
works right with glibc-2.1 and linux, at least for me)
-----------------------------------------------------------------------*/
unsigned long StopWatch( unsigned long *sec_base )
{
unsigned long secs,msec;
#if defined(__WXMSW__)
struct timeb tb;
ftime( &tb );
secs = tb.time;
msec = tb.millitm;
#elif defined(__WXMAC__) && !defined(__DARWIN__)
wxLongLong tl = wxGetLocalTimeMillis();
secs = (unsigned long) (tl.GetValue() / 1000);
msec = (unsigned long) (tl.GetValue() - secs*1000);
#else
// think every unice has gettimeofday
struct timeval tv;
gettimeofday( &tv, (struct timezone *)NULL );
secs = tv.tv_sec;
msec = tv.tv_usec/1000;
#endif
if( *sec_base == 0 )
*sec_base = secs;
return( (secs-*sec_base)*1000 + msec );
}
/*----------------------------------------------------------------
Implementation of Test-GLCanvas
-----------------------------------------------------------------*/
BEGIN_EVENT_TABLE(TestGLCanvas, wxGLCanvas) BEGIN_EVENT_TABLE(TestGLCanvas, wxGLCanvas)
EVT_SIZE(TestGLCanvas::OnSize) EVT_SIZE(TestGLCanvas::OnSize)
EVT_PAINT(TestGLCanvas::OnPaint) EVT_PAINT(TestGLCanvas::OnPaint)
EVT_ERASE_BACKGROUND(TestGLCanvas::OnEraseBackground)
EVT_KEY_DOWN( TestGLCanvas::OnKeyDown ) EVT_KEY_DOWN(TestGLCanvas::OnKeyDown)
EVT_KEY_UP( TestGLCanvas::OnKeyUp )
EVT_ENTER_WINDOW( TestGLCanvas::OnEnterWindow )
END_EVENT_TABLE() END_EVENT_TABLE()
unsigned long TestGLCanvas::m_secbase = 0; static /* const */ int attribs[] = { WX_GL_RGBA, WX_GL_DOUBLEBUFFER, 0 };
int TestGLCanvas::m_TimeInitialized = 0;
unsigned long TestGLCanvas::m_xsynct;
unsigned long TestGLCanvas::m_gsynct;
TestGLCanvas::TestGLCanvas(wxWindow *parent, wxWindowID id, TestGLCanvas::TestGLCanvas(wxWindow *parent)
const wxPoint& pos, const wxSize& size, long style, const wxString& name) : wxGLCanvas(parent, wxID_ANY, attribs)
: wxGLCanvas(parent, (wxGLCanvas*) NULL, id, pos, size, style|wxFULL_REPAINT_ON_RESIZE , name )
{
m_init = false;
m_gllist = 0;
m_rleft = WXK_LEFT;
m_rright = WXK_RIGHT;
}
TestGLCanvas::TestGLCanvas(wxWindow *parent, const TestGLCanvas *other,
wxWindowID id, const wxPoint& pos, const wxSize& size, long style,
const wxString& name )
: wxGLCanvas(parent, other->GetContext(), id, pos, size, style|wxFULL_REPAINT_ON_RESIZE , name)
{
m_init = false;
m_gllist = other->m_gllist; // share display list
m_rleft = WXK_LEFT;
m_rright = WXK_RIGHT;
}
TestGLCanvas::~TestGLCanvas()
{ {
InitGL();
} }
// this function is called on each repaint so it should be fast
void TestGLCanvas::Render() void TestGLCanvas::Render()
{ {
wxPaintDC dc(this); wxGetApp().SetCurrent(this);
#ifndef __WXMOTIF__
if (!GetContext()) return;
#endif
SetCurrent();
// Init OpenGL once, but after SetCurrent
if (!m_init)
{
InitGL();
m_init = true;
}
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-0.5f, 0.5f, -0.5f, 0.5f, 1.0f, 3.0f);
glMatrixMode(GL_MODELVIEW);
/* clear color and depth buffers */
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glCallList(m_gllist);
if( m_gllist == 0 )
{
m_gllist = glGenLists( 1 );
glNewList( m_gllist, GL_COMPILE_AND_EXECUTE );
/* draw six faces of a cube */
glBegin(GL_QUADS);
glNormal3f( 0.0f, 0.0f, 1.0f);
glVertex3f( 0.5f, 0.5f, 0.5f); glVertex3f(-0.5f, 0.5f, 0.5f);
glVertex3f(-0.5f,-0.5f, 0.5f); glVertex3f( 0.5f,-0.5f, 0.5f);
glNormal3f( 0.0f, 0.0f,-1.0f);
glVertex3f(-0.5f,-0.5f,-0.5f); glVertex3f(-0.5f, 0.5f,-0.5f);
glVertex3f( 0.5f, 0.5f,-0.5f); glVertex3f( 0.5f,-0.5f,-0.5f);
glNormal3f( 0.0f, 1.0f, 0.0f);
glVertex3f( 0.5f, 0.5f, 0.5f); glVertex3f( 0.5f, 0.5f,-0.5f);
glVertex3f(-0.5f, 0.5f,-0.5f); glVertex3f(-0.5f, 0.5f, 0.5f);
glNormal3f( 0.0f,-1.0f, 0.0f);
glVertex3f(-0.5f,-0.5f,-0.5f); glVertex3f( 0.5f,-0.5f,-0.5f);
glVertex3f( 0.5f,-0.5f, 0.5f); glVertex3f(-0.5f,-0.5f, 0.5f);
glNormal3f( 1.0f, 0.0f, 0.0f);
glVertex3f( 0.5f, 0.5f, 0.5f); glVertex3f( 0.5f,-0.5f, 0.5f);
glVertex3f( 0.5f,-0.5f,-0.5f); glVertex3f( 0.5f, 0.5f,-0.5f);
glNormal3f(-1.0f, 0.0f, 0.0f);
glVertex3f(-0.5f,-0.5f,-0.5f); glVertex3f(-0.5f,-0.5f, 0.5f);
glVertex3f(-0.5f, 0.5f, 0.5f); glVertex3f(-0.5f, 0.5f,-0.5f);
glEnd();
glEndList();
}
else
{
glCallList(m_gllist);
}
glFlush(); glFlush();
SwapBuffers(); SwapBuffers();
} }
void TestGLCanvas::OnEnterWindow( wxMouseEvent& WXUNUSED(event) ) void TestGLCanvas::OnPaint(wxPaintEvent& WXUNUSED(event))
{ {
SetFocus(); wxPaintDC dc(this);
}
void TestGLCanvas::OnPaint( wxPaintEvent& WXUNUSED(event) )
{
Render(); Render();
} }
void TestGLCanvas::OnSize(wxSizeEvent& event) void TestGLCanvas::OnSize(wxSizeEvent& WXUNUSED(event))
{ {
// this is also necessary to update the context on some platforms
wxGLCanvas::OnSize(event);
// set GL viewport (not called by wxGLCanvas::OnSize on all platforms...) // set GL viewport (not called by wxGLCanvas::OnSize on all platforms...)
int w, h; int w, h;
GetClientSize(&w, &h); GetClientSize(&w, &h);
#ifndef __WXMOTIF__
if (GetContext())
#endif
{
SetCurrent();
glViewport(0, 0, (GLint) w, (GLint) h);
}
}
void TestGLCanvas::OnEraseBackground(wxEraseEvent& WXUNUSED(event)) wxGetApp().SetCurrent(this);
{ glViewport(0, 0, w, h);
// Do nothing, to avoid flashing.
} }
void TestGLCanvas::InitGL() void TestGLCanvas::InitGL()
{ {
SetCurrent(); wxGetApp().SetCurrent(this);
/* set viewing projection */ /* set viewing projection */
glMatrixMode(GL_PROJECTION); glMatrixMode(GL_PROJECTION);
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 */ /* position viewer */
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0f, 0.0f, -2.0f); glTranslatef(0.0f, 0.0f, -2.0f);
/* position object */ /* position object */
@@ -318,214 +145,130 @@ void TestGLCanvas::InitGL()
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING); glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0); glEnable(GL_LIGHT0);
}
GLfloat TestGLCanvas::CalcRotateSpeed( unsigned long acceltime ) // create the list of commands to draw the cube: then we can just (quickly)
{ // execute it in Render() later
GLfloat t,v; m_gllist = glGenLists(1);
glNewList(m_gllist, GL_COMPILE);
t = ((GLfloat)acceltime) / 1000.0f; /* draw six faces of a cube */
glBegin(GL_QUADS);
glNormal3f( 0.0f, 0.0f, 1.0f);
glVertex3f( 0.5f, 0.5f, 0.5f); glVertex3f(-0.5f, 0.5f, 0.5f);
glVertex3f(-0.5f,-0.5f, 0.5f); glVertex3f( 0.5f,-0.5f, 0.5f);
if( t < 0.5f ) glNormal3f( 0.0f, 0.0f,-1.0f);
v = t; glVertex3f(-0.5f,-0.5f,-0.5f); glVertex3f(-0.5f, 0.5f,-0.5f);
else if( t < 1.0f ) glVertex3f( 0.5f, 0.5f,-0.5f); glVertex3f( 0.5f,-0.5f,-0.5f);
v = t * (2.0f - t);
else
v = 0.75f;
return(v); glNormal3f( 0.0f, 1.0f, 0.0f);
} glVertex3f( 0.5f, 0.5f, 0.5f); glVertex3f( 0.5f, 0.5f,-0.5f);
glVertex3f(-0.5f, 0.5f,-0.5f); glVertex3f(-0.5f, 0.5f, 0.5f);
GLfloat TestGLCanvas::CalcRotateAngle( unsigned long lasttime, glNormal3f( 0.0f,-1.0f, 0.0f);
unsigned long acceltime ) glVertex3f(-0.5f,-0.5f,-0.5f); glVertex3f( 0.5f,-0.5f,-0.5f);
{ glVertex3f( 0.5f,-0.5f, 0.5f); glVertex3f(-0.5f,-0.5f, 0.5f);
GLfloat t,s1,s2;
t = ((GLfloat)(acceltime - lasttime)) / 1000.0f; glNormal3f( 1.0f, 0.0f, 0.0f);
s1 = CalcRotateSpeed( lasttime ); glVertex3f( 0.5f, 0.5f, 0.5f); glVertex3f( 0.5f,-0.5f, 0.5f);
s2 = CalcRotateSpeed( acceltime ); glVertex3f( 0.5f,-0.5f,-0.5f); glVertex3f( 0.5f, 0.5f,-0.5f);
return( t * (s1 + s2) * 135.0f ); glNormal3f(-1.0f, 0.0f, 0.0f);
} glVertex3f(-0.5f,-0.5f,-0.5f); glVertex3f(-0.5f,-0.5f, 0.5f);
glVertex3f(-0.5f, 0.5f, 0.5f); glVertex3f(-0.5f, 0.5f,-0.5f);
glEnd();
void TestGLCanvas::Action( long code, unsigned long lasttime, glEndList();
unsigned long acceltime )
{
GLfloat angle = CalcRotateAngle( lasttime, acceltime );
if (code == m_rleft)
Rotate( angle );
else if (code == m_rright)
Rotate( -angle );
} }
void TestGLCanvas::OnKeyDown( wxKeyEvent& event ) void TestGLCanvas::OnKeyDown( wxKeyEvent& event )
{ {
long evkey = event.GetKeyCode(); GLfloat x = 0,
if (evkey == 0) return; y = 0,
z = 0;
if (!m_TimeInitialized) bool inverse = false;
switch ( event.GetKeyCode() )
{ {
m_TimeInitialized = 1; case WXK_RIGHT:
m_xsynct = event.GetTimestamp(); inverse = true;
m_gsynct = StopWatch(&m_secbase); // fall through
m_Key = evkey; case WXK_LEFT:
m_StartTime = 0; // rotate around Z axis
m_LastTime = 0; z = 1;
m_LastRedraw = 0; break;
case WXK_DOWN:
inverse = true;
// fall through
case WXK_UP:
// rotate around Y axis
y = 1;
break;
default:
event.Skip();
return;
} }
unsigned long currTime = event.GetTimestamp() - m_xsynct; float angle = 5;
if ( inverse )
angle = -angle;
if (evkey != m_Key) wxGetApp().SetCurrent(this);
{
m_Key = evkey;
m_LastRedraw = m_StartTime = m_LastTime = currTime;
}
if (currTime >= m_LastRedraw) // Redraw:
{
Action( m_Key, m_LastTime-m_StartTime, currTime-m_StartTime );
#if defined(__WXMAC__) && !defined(__DARWIN__)
m_LastRedraw = currTime; // StopWatch() doesn't work on Mac...
#else
m_LastRedraw = StopWatch(&m_secbase) - m_gsynct;
#endif
m_LastTime = currTime;
}
event.Skip();
}
void TestGLCanvas::OnKeyUp( wxKeyEvent& event )
{
m_Key = 0;
m_StartTime = 0;
m_LastTime = 0;
m_LastRedraw = 0;
event.Skip();
}
void TestGLCanvas::Rotate( GLfloat deg )
{
SetCurrent();
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
glRotatef((GLfloat)deg, 0.0f, 0.0f, 1.0f); glRotatef(angle, x, y, z);
Refresh(false);
// refresh all cubes
for ( wxWindowList::const_iterator i = wxTopLevelWindows.begin();
i != wxTopLevelWindows.end();
++i )
{
(*i)->Refresh(false);
}
} }
// ----------------------------------------------------------------------------
/* ----------------------------------------------------------------------- // MyFrame: main application window
Main Window // ----------------------------------------------------------------------------
-------------------------------------------------------------------------*/
BEGIN_EVENT_TABLE(MyFrame, wxFrame) BEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU(wxID_EXIT, MyFrame::OnExit) EVT_MENU(wxID_EXIT, MyFrame::OnExit)
EVT_MENU( ID_NEW_WINDOW, MyFrame::OnNewWindow) EVT_MENU(wxID_NEW, MyFrame::OnNewWindow)
EVT_MENU( ID_DEF_ROTATE_LEFT_KEY, MyFrame::OnDefRotateLeftKey)
EVT_MENU( ID_DEF_ROTATE_RIGHT_KEY, MyFrame::OnDefRotateRightKey)
END_EVENT_TABLE() END_EVENT_TABLE()
// My frame constructor MyFrame::MyFrame()
MyFrame::MyFrame(wxWindow *parent, const wxString& title, const wxPoint& pos, : wxFrame(NULL, wxID_ANY, _T("wxWidgets OpenGL Cube Sample"),
const wxSize& size, long style) wxDefaultPosition, wxSize(400, 300))
: wxFrame(parent, wxID_ANY, title, pos, size, style)
{ {
m_canvas = NULL; m_canvas = new TestGLCanvas(this);
SetIcon(wxIcon(sample_xpm));
SetIcon(wxICON(sample));
// Make a menubar
wxMenu *winMenu = new wxMenu;
winMenu->Append(wxID_EXIT, _T("&Close"));
winMenu->Append(wxID_NEW, _T("&New") );
wxMenuBar *menuBar = new wxMenuBar;
menuBar->Append(winMenu, _T("&Window"));
SetMenuBar(menuBar);
Show();
} }
// Intercept menu commands
void MyFrame::OnExit( wxCommandEvent& WXUNUSED(event) ) void MyFrame::OnExit( wxCommandEvent& WXUNUSED(event) )
{ {
// true is to force the frame to close // true is to force the frame to close
Close(true); Close(true);
} }
/*static*/ MyFrame *MyFrame::Create(MyFrame *parentFrame, bool isCloneWindow)
{
wxString str = wxT("wxWidgets OpenGL Cube Sample");
if (isCloneWindow) str += wxT(" - Clone");
MyFrame *frame = new MyFrame(NULL, str, wxDefaultPosition,
wxSize(400, 300));
// Make a menubar
wxMenu *winMenu = new wxMenu;
winMenu->Append(wxID_EXIT, _T("&Close"));
winMenu->Append(ID_NEW_WINDOW, _T("&New") );
wxMenuBar *menuBar = new wxMenuBar;
menuBar->Append(winMenu, _T("&Window"));
winMenu = new wxMenu;
winMenu->Append(ID_DEF_ROTATE_LEFT_KEY, _T("Rotate &left"));
winMenu->Append(ID_DEF_ROTATE_RIGHT_KEY, _T("Rotate &right"));
menuBar->Append(winMenu, _T("&Key"));
frame->SetMenuBar(menuBar);
if (parentFrame)
{
frame->m_canvas = new TestGLCanvas( frame, parentFrame->m_canvas,
wxID_ANY, wxDefaultPosition, wxDefaultSize );
}
else
{
frame->m_canvas = new TestGLCanvas(frame, wxID_ANY,
wxDefaultPosition, wxDefaultSize);
}
// Show the frame
frame->Show(true);
return frame;
}
void MyFrame::OnNewWindow( wxCommandEvent& WXUNUSED(event) ) void MyFrame::OnNewWindow( wxCommandEvent& WXUNUSED(event) )
{ {
(void) Create(this, true); (void) new MyFrame();
} }
void MyFrame::OnDefRotateLeftKey( wxCommandEvent& WXUNUSED(event) )
{
ScanCodeDialog dial( this, wxID_ANY, m_canvas->m_rleft,
wxString(_T("Left")), _T("Define key") );
int result = dial.ShowModal();
if( result == wxID_OK )
m_canvas->m_rleft = dial.GetValue();
}
void MyFrame::OnDefRotateRightKey( wxCommandEvent& WXUNUSED(event) )
{
ScanCodeDialog dial( this, wxID_ANY, m_canvas->m_rright,
wxString(_T("Right")), _T("Define key") );
int result = dial.ShowModal();
if( result == wxID_OK )
m_canvas->m_rright = dial.GetValue();
}
/*------------------------------------------------------------------
Application object ( equivalent to main() )
------------------------------------------------------------------ */
IMPLEMENT_APP(MyApp)
bool MyApp::OnInit()
{
if ( !wxApp::OnInit() )
return false;
// Create the main frame window
(void) MyFrame::Create(NULL);
return true;
}

View File

@@ -18,7 +18,18 @@
class MyApp: public wxApp class MyApp: public wxApp
{ {
public: public:
bool OnInit(); MyApp() { m_glContext = NULL; }
// set the specified canvas for current output
void SetCurrent(wxGLCanvas *canvas);
// virtual wxApp methods
virtual bool OnInit();
virtual int OnExit();
private:
// the GL context we use for all our windows
wxGLContext *m_glContext;
}; };
// Define a new frame type // Define a new frame type
@@ -27,7 +38,7 @@ class TestGLCanvas;
class MyFrame: public wxFrame class MyFrame: public wxFrame
{ {
public: public:
static MyFrame *Create(MyFrame *parentFrame, bool isCloneWindow = false); MyFrame();
void OnExit(wxCommandEvent& event); void OnExit(wxCommandEvent& event);
void OnNewWindow(wxCommandEvent& event); void OnNewWindow(wxCommandEvent& event);
@@ -35,70 +46,33 @@ public:
void OnDefRotateRightKey(wxCommandEvent& event); void OnDefRotateRightKey(wxCommandEvent& event);
private: private:
MyFrame(wxWindow *parent, const wxString& title, const wxPoint& pos,
const wxSize& size, long style = wxDEFAULT_FRAME_STYLE);
TestGLCanvas *m_canvas; TestGLCanvas *m_canvas;
DECLARE_EVENT_TABLE() DECLARE_EVENT_TABLE()
}; };
#if wxUSE_GLCANVAS class TestGLCanvas : public wxGLCanvas
class TestGLCanvas: public wxGLCanvas
{ {
friend class MyFrame;
public: public:
TestGLCanvas( wxWindow *parent, wxWindowID id = wxID_ANY, TestGLCanvas(wxWindow *parent);
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = 0, const wxString& name = _T("TestGLCanvas") );
TestGLCanvas( wxWindow *parent, const TestGLCanvas *other,
wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize, long style = 0,
const wxString& name = _T("TestGLCanvas") );
~TestGLCanvas();
void OnPaint(wxPaintEvent& event); void OnPaint(wxPaintEvent& event);
void OnSize(wxSizeEvent& event); void OnSize(wxSizeEvent& event);
void OnEraseBackground(wxEraseEvent& event);
void OnKeyDown(wxKeyEvent& event); void OnKeyDown(wxKeyEvent& event);
void OnKeyUp(wxKeyEvent& event);
void OnEnterWindow(wxMouseEvent& event);
void Render();
void InitGL();
void Rotate(GLfloat deg);
static GLfloat CalcRotateSpeed(unsigned long acceltime);
static GLfloat CalcRotateAngle( unsigned long lasttime,
unsigned long acceltime );
void Action( long code, unsigned long lasttime,
unsigned long acceltime );
private: private:
bool m_init; // one-time OpenGL initialization
void InitGL();
// render to window
void Render();
// the list of commands to draw the cube
GLuint m_gllist; GLuint m_gllist;
long m_rleft;
long m_rright;
static unsigned long m_secbase; DECLARE_EVENT_TABLE()
static int m_TimeInitialized;
static unsigned long m_xsynct;
static unsigned long m_gsynct;
long m_Key;
unsigned long m_StartTime;
unsigned long m_LastTime;
unsigned long m_LastRedraw;
DECLARE_EVENT_TABLE()
}; };
#endif // #if wxUSE_GLCANVAS #endif // _WX_CUBE_H_
#endif // #ifndef _WX_CUBE_H_