]>
git.saurik.com Git - wxWidgets.git/blob - samples/opengl/cube/cube.cpp
1 ///////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxGLCanvas demo program
4 // Author: Julian Smart
5 // Modified by: Vadim Zeitlin to use new wxGLCanvas API (2007-04-09)
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
32 #error "OpenGL required: set wxUSE_GLCANVAS to 1 and rebuild the library"
37 #if !defined(__WXMSW__) && !defined(__WXPM__)
38 #include "../../sample.xpm"
41 // ----------------------------------------------------------------------------
43 // ----------------------------------------------------------------------------
45 static void CheckGLError()
47 GLenum errLast
= GL_NO_ERROR
;
51 GLenum err
= glGetError();
52 if ( err
== GL_NO_ERROR
)
55 // normally the error is reset by the call to glGetError() but if
56 // glGetError() itself returns an error, we risk looping forever here
57 // so check that we get a different error than the last time
60 wxLogError(wxT("OpenGL error state couldn't be reset."));
66 wxLogError(wxT("OpenGL error %d"), err
);
70 // function to draw the texture for cube faces
71 static wxImage
DrawDice(int size
, unsigned num
)
73 wxASSERT_MSG( num
>= 1 && num
<= 6, wxT("invalid dice index") );
75 const int dot
= size
/16; // radius of a single dot
76 const int gap
= 5*size
/32; // gap between dots
78 wxBitmap
bmp(size
, size
);
81 dc
.SetBackground(*wxWHITE_BRUSH
);
83 dc
.SetBrush(*wxBLACK_BRUSH
);
85 // the upper left and lower right points
88 dc
.DrawCircle(gap
+ dot
, gap
+ dot
, dot
);
89 dc
.DrawCircle(size
- gap
- dot
, size
- gap
- dot
, dot
);
92 // draw the central point for odd dices
95 dc
.DrawCircle(size
/2, size
/2, dot
);
98 // the upper right and lower left points
101 dc
.DrawCircle(size
- gap
- dot
, gap
+ dot
, dot
);
102 dc
.DrawCircle(gap
+ dot
, size
- gap
- dot
, dot
);
105 // finally those 2 are only for the last dice
108 dc
.DrawCircle(gap
+ dot
, size
/2, dot
);
109 dc
.DrawCircle(size
- gap
- dot
, size
/2, dot
);
112 dc
.SelectObject(wxNullBitmap
);
114 return bmp
.ConvertToImage();
117 // ============================================================================
119 // ============================================================================
121 // ----------------------------------------------------------------------------
123 // ----------------------------------------------------------------------------
125 TestGLContext::TestGLContext(wxGLCanvas
*canvas
)
126 : wxGLContext(canvas
)
130 // set up the parameters we want to use
131 glEnable(GL_DEPTH_TEST
);
132 glEnable(GL_LIGHTING
);
134 glEnable(GL_TEXTURE_2D
);
136 // add slightly more light, the default lighting is rather dark
137 GLfloat ambient
[] = { 0.5, 0.5, 0.5, 0.5 };
138 glLightfv(GL_LIGHT0
, GL_AMBIENT
, ambient
);
140 // set viewing projection
141 glMatrixMode(GL_PROJECTION
);
143 glFrustum(-0.5f
, 0.5f
, -0.5f
, 0.5f
, 1.0f
, 3.0f
);
145 // create the textures to use for cube sides: they will be reused by all
146 // canvases (which is probably not critical in the case of simple textures
147 // we use here but could be really important for a real application where
148 // each texture could take many megabytes)
149 glGenTextures(WXSIZEOF(m_textures
), m_textures
);
151 for ( unsigned i
= 0; i
< WXSIZEOF(m_textures
); i
++ )
153 glBindTexture(GL_TEXTURE_2D
, m_textures
[i
]);
155 glTexEnvf(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_MODULATE
);
156 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP
);
157 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP
);
158 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
159 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
161 const wxImage
img(DrawDice(256, i
+ 1));
163 glPixelStorei(GL_UNPACK_ALIGNMENT
, 1);
164 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, img
.GetWidth(), img
.GetHeight(),
165 0, GL_RGB
, GL_UNSIGNED_BYTE
, img
.GetData());
171 void TestGLContext::DrawRotatedCube(float xangle
, float yangle
)
173 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
175 glMatrixMode(GL_MODELVIEW
);
177 glTranslatef(0.0f
, 0.0f
, -2.0f
);
178 glRotatef(xangle
, 1.0f
, 0.0f
, 0.0f
);
179 glRotatef(yangle
, 0.0f
, 1.0f
, 0.0f
);
181 // draw six faces of a cube of size 1 centered at (0, 0, 0)
182 glBindTexture(GL_TEXTURE_2D
, m_textures
[0]);
184 glNormal3f( 0.0f
, 0.0f
, 1.0f
);
185 glTexCoord2f(0, 0); glVertex3f( 0.5f
, 0.5f
, 0.5f
);
186 glTexCoord2f(1, 0); glVertex3f(-0.5f
, 0.5f
, 0.5f
);
187 glTexCoord2f(1, 1); glVertex3f(-0.5f
,-0.5f
, 0.5f
);
188 glTexCoord2f(0, 1); glVertex3f( 0.5f
,-0.5f
, 0.5f
);
191 glBindTexture(GL_TEXTURE_2D
, m_textures
[1]);
193 glNormal3f( 0.0f
, 0.0f
,-1.0f
);
194 glTexCoord2f(0, 0); glVertex3f(-0.5f
,-0.5f
,-0.5f
);
195 glTexCoord2f(1, 0); glVertex3f(-0.5f
, 0.5f
,-0.5f
);
196 glTexCoord2f(1, 1); glVertex3f( 0.5f
, 0.5f
,-0.5f
);
197 glTexCoord2f(0, 1); glVertex3f( 0.5f
,-0.5f
,-0.5f
);
200 glBindTexture(GL_TEXTURE_2D
, m_textures
[2]);
202 glNormal3f( 0.0f
, 1.0f
, 0.0f
);
203 glTexCoord2f(0, 0); glVertex3f( 0.5f
, 0.5f
, 0.5f
);
204 glTexCoord2f(1, 0); glVertex3f( 0.5f
, 0.5f
,-0.5f
);
205 glTexCoord2f(1, 1); glVertex3f(-0.5f
, 0.5f
,-0.5f
);
206 glTexCoord2f(0, 1); glVertex3f(-0.5f
, 0.5f
, 0.5f
);
209 glBindTexture(GL_TEXTURE_2D
, m_textures
[3]);
211 glNormal3f( 0.0f
,-1.0f
, 0.0f
);
212 glTexCoord2f(0, 0); glVertex3f(-0.5f
,-0.5f
,-0.5f
);
213 glTexCoord2f(1, 0); glVertex3f( 0.5f
,-0.5f
,-0.5f
);
214 glTexCoord2f(1, 1); glVertex3f( 0.5f
,-0.5f
, 0.5f
);
215 glTexCoord2f(0, 1); glVertex3f(-0.5f
,-0.5f
, 0.5f
);
218 glBindTexture(GL_TEXTURE_2D
, m_textures
[4]);
220 glNormal3f( 1.0f
, 0.0f
, 0.0f
);
221 glTexCoord2f(0, 0); glVertex3f( 0.5f
, 0.5f
, 0.5f
);
222 glTexCoord2f(1, 0); glVertex3f( 0.5f
,-0.5f
, 0.5f
);
223 glTexCoord2f(1, 1); glVertex3f( 0.5f
,-0.5f
,-0.5f
);
224 glTexCoord2f(0, 1); glVertex3f( 0.5f
, 0.5f
,-0.5f
);
227 glBindTexture(GL_TEXTURE_2D
, m_textures
[5]);
229 glNormal3f(-1.0f
, 0.0f
, 0.0f
);
230 glTexCoord2f(0, 0); glVertex3f(-0.5f
,-0.5f
,-0.5f
);
231 glTexCoord2f(1, 0); glVertex3f(-0.5f
,-0.5f
, 0.5f
);
232 glTexCoord2f(1, 1); glVertex3f(-0.5f
, 0.5f
, 0.5f
);
233 glTexCoord2f(0, 1); glVertex3f(-0.5f
, 0.5f
,-0.5f
);
242 // ----------------------------------------------------------------------------
243 // MyApp: the application object
244 // ----------------------------------------------------------------------------
250 if ( !wxApp::OnInit() )
262 return wxApp::OnExit();
265 TestGLContext
& MyApp::GetContext(wxGLCanvas
*canvas
)
269 // Create the OpenGL context for the first window which needs it:
270 // subsequently created windows will all share the same context.
271 m_glContext
= new TestGLContext(canvas
);
274 m_glContext
->SetCurrent(*canvas
);
279 // ----------------------------------------------------------------------------
281 // ----------------------------------------------------------------------------
283 BEGIN_EVENT_TABLE(TestGLCanvas
, wxGLCanvas
)
284 EVT_PAINT(TestGLCanvas::OnPaint
)
285 EVT_KEY_DOWN(TestGLCanvas::OnKeyDown
)
288 TestGLCanvas::TestGLCanvas(wxWindow
*parent
)
289 // With perspective OpenGL graphics, the wxFULL_REPAINT_ON_RESIZE style
290 // flag should always be set, because even making the canvas smaller should
291 // be followed by a paint event that updates the entire canvas with new
292 // viewport settings.
293 : wxGLCanvas(parent
, wxID_ANY
, NULL
/* attribs */,
294 wxDefaultPosition
, wxDefaultSize
,
295 wxFULL_REPAINT_ON_RESIZE
)
301 void TestGLCanvas::OnPaint(wxPaintEvent
& WXUNUSED(event
))
303 // This is required even though dc is not used otherwise.
306 // Set the OpenGL viewport according to the client size of this canvas.
307 // This is done here rather than in a wxSizeEvent handler because our
308 // OpenGL rendering context (and thus viewport setting) is used with
309 // multiple canvases: If we updated the viewport in the wxSizeEvent
310 // handler, changing the size of one canvas causes a viewport setting that
311 // is wrong when next another canvas is repainted.
312 const wxSize ClientSize
= GetClientSize();
314 glViewport(0, 0, ClientSize
.x
, ClientSize
.y
);
316 // Render the graphics and swap the buffers.
317 wxGetApp().GetContext(this).DrawRotatedCube(m_xangle
, m_yangle
);
321 void TestGLCanvas::OnKeyDown( wxKeyEvent
& event
)
325 bool inverse
= false;
327 switch ( event
.GetKeyCode() )
334 // rotate around Y axis
343 // rotate around X axis
362 // ----------------------------------------------------------------------------
363 // MyFrame: main application window
364 // ----------------------------------------------------------------------------
366 BEGIN_EVENT_TABLE(MyFrame
, wxFrame
)
367 EVT_MENU(wxID_NEW
, MyFrame::OnNewWindow
)
368 EVT_MENU(wxID_CLOSE
, MyFrame::OnClose
)
372 : wxFrame(NULL
, wxID_ANY
, wxT("wxWidgets OpenGL Cube Sample"))
374 new TestGLCanvas(this);
376 SetIcon(wxICON(sample
));
379 wxMenu
*menu
= new wxMenu
;
380 menu
->Append(wxID_NEW
);
381 menu
->AppendSeparator();
382 menu
->Append(wxID_CLOSE
);
383 wxMenuBar
*menuBar
= new wxMenuBar
;
384 menuBar
->Append(menu
, wxT("&Cube"));
390 SetClientSize(400, 400);
393 // test IsDisplaySupported() function:
394 static const int attribs
[] = { WX_GL_RGBA
, WX_GL_DOUBLEBUFFER
, 0 };
395 wxLogStatus("Double-buffered display %s supported",
396 wxGLCanvas::IsDisplaySupported(attribs
) ? "is" : "not");
399 void MyFrame::OnClose(wxCommandEvent
& WXUNUSED(event
))
401 // true is to force the frame to close
405 void MyFrame::OnNewWindow( wxCommandEvent
& WXUNUSED(event
) )