1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        penguin.cpp
3 // Purpose:     wxGLCanvas demo program
4 // Author:      Robert Roebling
5 // Modified by: Sandro Sigala
6 // Created:     04/01/98
7 // RCS-ID:      $Id: penguin.cpp 43272 2006-11-10 15:16:02Z VZ $
8 // Copyright:   (c) Robert Roebling
9 // Licence:     wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11 
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14 
15 #ifdef __BORLANDC__
16 #pragma hdrstop
17 #endif
18 
19 #ifndef WX_PRECOMP
20 #include "wx/wx.h"
21 #endif
22 
23 #if !wxUSE_GLCANVAS
24     #error "OpenGL required: set wxUSE_GLCANVAS to 1 and rebuild the library"
25 #endif
26 
27 #include "penguin.h"
28 #ifdef __DARWIN__
29     #include <OpenGL/glu.h>
30 #else
31     #include <GL/glu.h>
32 #endif
33 
34 #include "../../sample.xpm"
35 
36 // ---------------------------------------------------------------------------
37 // MyApp
38 // ---------------------------------------------------------------------------
39 
40 // `Main program' equivalent, creating windows and returning main app frame
OnInit()41 bool MyApp::OnInit()
42 {
43     // Create the main frame window
44     MyFrame *frame = new MyFrame(NULL, wxT("wxWidgets Penguin Sample"),
45         wxDefaultPosition, wxDefaultSize);
46 
47 #if wxUSE_ZLIB
48     if (wxFileExists(wxT("penguin.dxf.gz")))
49         frame->GetCanvas()->LoadDXF(wxT("penguin.dxf.gz"));
50 #else
51     if (wxFileExists(wxT("penguin.dxf")))
52         frame->GetCanvas()->LoadDXF(wxT("penguin.dxf"));
53 #endif
54 
55     /* Show the frame */
56     frame->Show(true);
57 
58     return true;
59 }
60 
61 IMPLEMENT_APP(MyApp)
62 
63 // ---------------------------------------------------------------------------
64 // MyFrame
65 // ---------------------------------------------------------------------------
66 
BEGIN_EVENT_TABLE(MyFrame,wxFrame)67 BEGIN_EVENT_TABLE(MyFrame, wxFrame)
68     EVT_MENU(wxID_OPEN, MyFrame::OnMenuFileOpen)
69     EVT_MENU(wxID_EXIT, MyFrame::OnMenuFileExit)
70     EVT_MENU(wxID_HELP, MyFrame::OnMenuHelpAbout)
71 END_EVENT_TABLE()
72 
73 // MyFrame constructor
74 MyFrame::MyFrame(wxFrame *frame, const wxString& title, const wxPoint& pos,
75     const wxSize& size, long style)
76     : wxFrame(frame, wxID_ANY, title, pos, size, style)
77 {
78     SetIcon(wxIcon(sample_xpm));
79 
80     // Make the "File" menu
81     wxMenu *fileMenu = new wxMenu;
82     fileMenu->Append(wxID_OPEN, wxT("&Open..."));
83     fileMenu->AppendSeparator();
84     fileMenu->Append(wxID_EXIT, wxT("E&xit\tALT-X"));
85     // Make the "Help" menu
86     wxMenu *helpMenu = new wxMenu;
87     helpMenu->Append(wxID_HELP, wxT("&About..."));
88 
89     wxMenuBar *menuBar = new wxMenuBar;
90     menuBar->Append(fileMenu, wxT("&File"));
91     menuBar->Append(helpMenu, wxT("&Help"));
92     SetMenuBar(menuBar);
93 
94     m_canvas = new TestGLCanvas(this, wxID_ANY, wxDefaultPosition,
95         wxSize(300, 300), wxSUNKEN_BORDER);
96 }
97 
98 // File|Open... command
OnMenuFileOpen(wxCommandEvent & WXUNUSED (event))99 void MyFrame::OnMenuFileOpen( wxCommandEvent& WXUNUSED(event) )
100 {
101     wxString filename = wxFileSelector(wxT("Choose DXF Model"), wxT(""), wxT(""), wxT(""),
102 #if wxUSE_ZLIB
103         wxT("DXF Drawing (*.dxf;*.dxf.gz)|*.dxf;*.dxf.gz|All files (*.*)|*.*"),
104 #else
105         wxT("DXF Drawing (*.dxf)|*.dxf)|All files (*.*)|*.*"),
106 #endif
107         wxFD_OPEN);
108     if (!filename.IsEmpty())
109     {
110         m_canvas->LoadDXF(filename);
111         m_canvas->Refresh(false);
112     }
113 }
114 
115 // File|Exit command
OnMenuFileExit(wxCommandEvent & WXUNUSED (event))116 void MyFrame::OnMenuFileExit( wxCommandEvent& WXUNUSED(event) )
117 {
118     // true is to force the frame to close
119     Close(true);
120 }
121 
122 // Help|About... command
OnMenuHelpAbout(wxCommandEvent & WXUNUSED (event))123 void MyFrame::OnMenuHelpAbout( wxCommandEvent& WXUNUSED(event) )
124 {
125     wxMessageBox(wxT("OpenGL Penguin Sample (c) Robert Roebling, Sandro Sigala et al"));
126 }
127 
128 // ---------------------------------------------------------------------------
129 // TestGLCanvas
130 // ---------------------------------------------------------------------------
131 
BEGIN_EVENT_TABLE(TestGLCanvas,wxGLCanvas)132 BEGIN_EVENT_TABLE(TestGLCanvas, wxGLCanvas)
133     EVT_SIZE(TestGLCanvas::OnSize)
134     EVT_PAINT(TestGLCanvas::OnPaint)
135     EVT_ERASE_BACKGROUND(TestGLCanvas::OnEraseBackground)
136     EVT_MOUSE_EVENTS(TestGLCanvas::OnMouse)
137 END_EVENT_TABLE()
138 
139 TestGLCanvas::TestGLCanvas(wxWindow *parent, wxWindowID id,
140     const wxPoint& pos, const wxSize& size, long style, const wxString& name)
141     : wxGLCanvas(parent, id, pos, size, style|wxFULL_REPAINT_ON_RESIZE, name)
142 {
143     m_gldata.initialized = false;
144 
145     // initialize view matrix
146     m_gldata.beginx = 0.0f;
147     m_gldata.beginy = 0.0f;
148     m_gldata.zoom   = 45.0f;
149     trackball(m_gldata.quat, 0.0f, 0.0f, 0.0f, 0.0f);
150 }
151 
~TestGLCanvas()152 TestGLCanvas::~TestGLCanvas()
153 {
154 }
155 
OnPaint(wxPaintEvent & WXUNUSED (event))156 void TestGLCanvas::OnPaint( wxPaintEvent& WXUNUSED(event) )
157 {
158     // must always be here
159     wxPaintDC dc(this);
160 
161 #ifndef __WXMOTIF__
162     if (!GetContext()) return;
163 #endif
164 
165     SetCurrent();
166 
167     // Initialize OpenGL
168     if (!m_gldata.initialized)
169     {
170         InitGL();
171         ResetProjectionMode();
172         m_gldata.initialized = true;
173     }
174 
175     // Clear
176     glClearColor( 0.3f, 0.4f, 0.6f, 1.0f );
177     glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
178 
179     // Transformations
180     glLoadIdentity();
181     glTranslatef( 0.0f, 0.0f, -20.0f );
182     GLfloat m[4][4];
183     build_rotmatrix( m, m_gldata.quat );
184     glMultMatrixf( &m[0][0] );
185 
186     m_renderer.Render();
187 
188     // Flush
189     glFlush();
190 
191     // Swap
192     SwapBuffers();
193 }
194 
OnSize(wxSizeEvent & event)195 void TestGLCanvas::OnSize(wxSizeEvent& event)
196 {
197     // this is also necessary to update the context on some platforms
198     wxGLCanvas::OnSize(event);
199     // Reset the OpenGL view aspect
200     ResetProjectionMode();
201 }
202 
OnEraseBackground(wxEraseEvent & WXUNUSED (event))203 void TestGLCanvas::OnEraseBackground(wxEraseEvent& WXUNUSED(event))
204 {
205     // Do nothing, to avoid flashing on MSW
206 }
207 
208 // Load the DXF file.  If the zlib support is compiled in wxWidgets,
209 // supports also the ".dxf.gz" gzip compressed files.
LoadDXF(const wxString & filename)210 void TestGLCanvas::LoadDXF(const wxString& filename)
211 {
212     wxFileInputStream stream(filename);
213     if (stream.Ok())
214 #if wxUSE_ZLIB
215     {
216         if (filename.Right(3).Lower() == wxT(".gz"))
217         {
218             wxZlibInputStream zstream(stream);
219             m_renderer.Load(zstream);
220         } else
221         {
222             m_renderer.Load(stream);
223         }
224     }
225 #else
226     {
227         m_renderer.Load(stream);
228     }
229 #endif
230 }
231 
OnMouse(wxMouseEvent & event)232 void TestGLCanvas::OnMouse(wxMouseEvent& event)
233 {
234     if (event.Dragging())
235     {
236         wxSize sz(GetClientSize());
237 
238         /* drag in progress, simulate trackball */
239         float spin_quat[4];
240         trackball(spin_quat,
241             (2.0*m_gldata.beginx - sz.x) / sz.x,
242             (sz.y - 2.0*m_gldata.beginy) / sz.y,
243             (2.0*event.GetX() - sz.x)    / sz.x,
244             (sz.y - 2.0*event.GetY())    / sz.y);
245 
246         add_quats(spin_quat, m_gldata.quat, m_gldata.quat);
247 
248         /* orientation has changed, redraw mesh */
249         Refresh(false);
250     }
251 
252     m_gldata.beginx = event.GetX();
253     m_gldata.beginy = event.GetY();
254 }
255 
InitGL()256 void TestGLCanvas::InitGL()
257 {
258     static const GLfloat light0_pos[4]   = { -50.0f, 50.0f, 0.0f, 0.0f };
259 
260     // white light
261     static const GLfloat light0_color[4] = { 0.6f, 0.6f, 0.6f, 1.0f };
262 
263     static const GLfloat light1_pos[4]   = {  50.0f, 50.0f, 0.0f, 0.0f };
264 
265     // cold blue light
266     static const GLfloat light1_color[4] = { 0.4f, 0.4f, 1.0f, 1.0f };
267 
268     /* remove back faces */
269     glDisable(GL_CULL_FACE);
270     glEnable(GL_DEPTH_TEST);
271 
272     /* speedups */
273     glEnable(GL_DITHER);
274     glShadeModel(GL_SMOOTH);
275     glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
276     glHint(GL_POLYGON_SMOOTH_HINT, GL_FASTEST);
277 
278     /* light */
279     glLightfv(GL_LIGHT0, GL_POSITION, light0_pos);
280     glLightfv(GL_LIGHT0, GL_DIFFUSE,  light0_color);
281     glLightfv(GL_LIGHT1, GL_POSITION, light1_pos);
282     glLightfv(GL_LIGHT1, GL_DIFFUSE,  light1_color);
283     glEnable(GL_LIGHT0);
284     glEnable(GL_LIGHT1);
285     glEnable(GL_LIGHTING);
286 
287     glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
288     glEnable(GL_COLOR_MATERIAL);
289 }
290 
ResetProjectionMode()291 void TestGLCanvas::ResetProjectionMode()
292 {
293     int w, h;
294     GetClientSize(&w, &h);
295 #ifndef __WXMOTIF__
296     if ( GetContext() )
297 #endif
298     {
299         SetCurrent();
300         glViewport(0, 0, (GLint) w, (GLint) h);
301         glMatrixMode(GL_PROJECTION);
302         glLoadIdentity();
303         gluPerspective(45.0f, (GLfloat)w/h, 1.0, 100.0);
304         glMatrixMode(GL_MODELVIEW);
305         glLoadIdentity();
306     }
307 }
308