前回は単純にウインドウを表示させただけだったが、調べていくとOpenGLを使って描画することができるらしい。wxGLCanvasというクラスが用意されているようで、そこにOpenGLの関数を与えてあげると描画してくれるようだ。WxWili - wxGLCanvasなどを参考に、以前作ったOpenGLクラスと組み合わせて、実際に描画してみた。
まず、前回のコードを次のように修正した。
- mainwindow.hpp
class MainWindow : public wxFrame { private: GLPanel *panel_; //追加 public: MainWindow(const wxString& title); };
- mainwindow.cpp
MainWindow::MainWindow(const wxString& title) : wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(350, 250)) { panel_=new GLPanel(this, NULL, wxID_ANY); //追加 Centre(); }
GLPanelというwxGLCanvasの派生クラスを用意して、メインウインドウに配置した。GLPanelはどうなっているかというと、
- glpanel.hpp
#ifndef __GLPANEL_HPP__ #define __GLPANEL_HPP__ #include <wx/wx.h> #include <wx/glcanvas.h> #include "opengl.hpp" class GLPanel : public wxGLCanvas { private: bool isInitialized_; OpenGL gl_; public: GLPanel(wxWindow* parent, wxGLContext* sharedContext, wxWindowID id); void OnPaint(wxPaintEvent &event); void OnSize(wxSizeEvent &event); void OnEraseBackground(wxEraseEvent& event); }; #endif //__GLPANEL_HPP__
- glpanel.cpp
#include "glpanel.hpp" GLPanel::GLPanel(wxWindow* parent, wxGLContext* sharedContext, wxWindowID id) : wxGLCanvas(parent, sharedContext, id), isInitialized_(false) { Connect(wxEVT_SIZE, wxSizeEventHandler(GLPanel::OnSize)); Connect(wxEVT_PAINT, wxPaintEventHandler(GLPanel::OnPaint)); Connect(wxEVT_ERASE_BACKGROUND, wxEraseEventHandler(GLPanel::OnEraseBackground)); } void GLPanel::OnPaint(wxPaintEvent &event) { wxPaintDC dc(this); if(!GetContext()){ return; } if(!isInitialized_){ SetCurrent(); gl_.init(); int w; int h; GetClientSize(&w, &h); gl_.setViewport(w, h); isInitialized_=true; } gl_.draw(); glFlush(); SwapBuffers(); } void GLPanel::OnSize(wxSizeEvent &event) { wxGLCanvas::OnSize(event); if(GetContext()) { SetCurrent(); gl_.setViewport(event.GetSize().GetWidth(), event.GetSize().GetHeight()); Refresh(); } } void GLPanel::OnEraseBackground(wxEraseEvent& event) { // Do nothing, to avoid flashing. }
OpenGLというクラスを持ったwxGLCanvasの派生クラスを作成する。OnPaint、OnSize、OnEraceBackgroudメンバ関数はそれぞれ、wxEVT_PAINT、wxEVT_SIZE、wxEVT_ERACE_BACKGROUNDというイベントが発生した際に呼び出されるイベントハンドラとなっている。OnSizeメンバ関数の内部で、OpenGLクラスを使って描画処理を行っている。そのため、通常のOpenGLプログラムに似た流れの処理が記載されている。
ここまで来ると、OpenGLクラスの正体もだんだんと見えてくる。OpenGLクラスはOpenGLの初期化関数や、描画関数をもったクラスとなっている。今回はここに以前作ったOpenGLクラスを組み込んでみた。
- opengl.hpp
#ifndef __OPENGL_HPP__ #define __OPENGL_HPP__ #include <wx/glcanvas.h> class OpenGL{ public: void init(); void setViewport(int w, int h); void draw(); }; #endif //__OPENGL_HPP__
- opengl.cpp
#include "opengl.hpp" #include "glbasicshape.hpp" using namespace DECS::GL; void OpenGL::init() { glClearColor(1, 1, 1, 1); } void OpenGL::setViewport(int w, int h) { glViewport(0, 0, (GLint)w, (GLint)h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-w / 200.0, w / 200.0, -h / 200.0, h / 200.0, -1.0, 1.0); } void OpenGL::draw() { GLPosition center(0.3, 0.3, 0.0); GLdouble r = 0.35; GLColor cColor(1.0, 1.0, 0.0); GLCircle circle(GL_POLYGON, center, r, cColor); GLPosition tPoint1(-0.9, -0.9, 0.0); GLPosition tPoint2(0.5, -0.4, 0.0); GLPosition tPoint3(-0.9, 0.0, 0.0); GLColor tColor(1.0, 0.0, 1.0); GLTriangle tri(GL_POLYGON, tPoint1, tPoint2, tPoint3, tColor); GLPosition sPoint1(-0.9, 0.9, 0.0); GLPosition sPoint2(-0.5, 0.9, 0.0); GLPosition sPoint3(-0.2, 0.4, 0.0); GLPosition sPoint4(-0.9, 0.5, 0.0); GLColor sColor(0.0, 1.0, 1.0); GLSquare square(GL_POLYGON, sPoint1, sPoint2, sPoint3, sPoint4); GLPosition begin(0.9, -0.9, 0.0); GLPosition end(-0.9, -0.6, 0.0); GLColor lColor(0.5, 0.5, 0.5); GLLine line(begin, end, lColor); glClear(GL_COLOR_BUFFER_BIT); circle.draw(); tri.draw(); square.draw(); line.draw(); }
drawメンバ関数が実際の描画内容を書いている部分になる。ここにdglbasicshape.hppで定義したGLCircleやGLTriangle、GLLine、GLSquareを使ってみた。
これをビルドして実行すると、
今回は前回リンクしたライブラリに加えて、
- opengl32.lib
- wxmsw28d_gl.lib
の2つを追加している。
コメント