penguin.cpp 8.6 KB

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