トップコンテンツプログラムノベルゲーム>OpenGLとの連携



OpenGL との連携

今回は wxWidgets 上で OpenGL を使ってみます。
まあ、今までやってきた内容の、1 つのまとめみたいな感じですね。

wx2_1.h (wx2_1.cpp のヘッダファイル) [表示・非表示]
 1.
 2.
 3.
 4.
 5.
 6.
 7.
 8.
 9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
/* wxWidgets関連 */
#include <wx/wxprec.h>
#include <wx/glcanvas.h>

#ifdef __BORLANDC__
#pragma hdrstop
#endif

#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif

/* OpenGL用 */
#ifdef  __WINDOWS__
#include <windows.h>
#endif

#include <GL/GL.h>
#include <GL/GLU.h>


// 前方参照用
class myApp;
class myFrame;
class myGLCanvas;
class myGLContext;


class myApp : public wxApp
{
public:
  myApp() { m_glContext = NULL; }
  myGLContext& GetContext(wxGLCanvas *canvas);

  virtual bool OnInit();
  virtual int OnExit();

private:
  myGLContext *m_glContext;
  myFrame* frame;
};


class myFrame : public wxFrame
{
public:
  myFrame(const wxString& title, const wxSize& size);

private:
  void OnClose(wxCloseEvent& event);
  void OnKeyDown(wxKeyEvent& event);

  myGLCanvas* canvas;
};


class myGLCanvas : public wxGLCanvas
{
public:
  myGLCanvas(wxWindow *parent);

private:
  void OnPaint(wxPaintEvent& event);
  void OnKeyDown(wxKeyEvent& event);
};

class myGLContext : public wxGLContext
{
public:
  myGLContext(wxGLCanvas *canvas);
  void drawRect();
};

wx2_1.cpp (OpenGL を使って四角形を表示) [表示・非表示]
 1.
 2.
 3.
 4.
 5.
 6.
 7.
 8.
 9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
#include "wx2_1.h"


// main 関数の代わり
IMPLEMENT_APP(myApp)

/***********************
 * myApp
 ***********************/
bool myApp::OnInit()
{
  if ( !wxApp::OnInit() )
    return false;

  frame = new myFrame("Window Test", wxSize(800, 600));

  return true;
}

int myApp::OnExit()
{
  delete m_glContext;

  return wxApp::OnExit();
}

myGLContext& myApp::GetContext(wxGLCanvas *canvas)
{
  if ( !m_glContext )
    m_glContext = new myGLContext(canvas);

  m_glContext->SetCurrent(*canvas);

  return *m_glContext;
}

/***********************
 * myFrame
 ***********************/
myFrame::myFrame(const wxString& title, const wxSize& size)
       : wxFrame(NULL, -1, title, wxDefaultPosition, size, 
				 wxMINIMIZE_BOX | wxSYSTEM_MENU | wxCAPTION | 
				 wxCLOSE_BOX | wxCLIP_CHILDREN)
{
  wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
  canvas = new myGLCanvas(this);

  // sizerによるレイアウト
  sizer->Add(0, 0, 1, wxEXPAND);
  sizer->Add(canvas, 0, wxEXPAND | wxALIGN_CENTER_HORIZONTAL | 
                       wxALIGN_CENTER_VERTICAL | wxSHAPED, 0);
  sizer->Add(0, 0, 1, wxEXPAND);

  SetSizer(sizer);
  SetBackgroundColour(*wxBLACK);
  SetClientSize(size);

  Show(true);

  // イベントハンドラの登録
  Bind(wxEVT_CLOSE_WINDOW, &myFrame::OnClose, this);
  Bind(wxEVT_KEY_DOWN, &myFrame::OnKeyDown, this);
}

void myFrame::OnClose(wxCloseEvent& WXUNUSED(event))
{
  if ( wxMessageBox("プログラムを終了してもいいですか?",
                    "確認",
                    wxICON_QUESTION | wxYES_NO | wxNO_DEFAULT) == wxNO )
  {
    return;
  }

  Destroy();
}

void myFrame::OnKeyDown(wxKeyEvent& event)
{
  switch (event.GetKeyCode())
  {
  case WXK_F11:
    ShowFullScreen(!IsFullScreen(), wxFULLSCREEN_ALL);
    break;

  default:
    event.Skip();
    return;
  }
}

/***********************
 * myGLCanvas
 ***********************/
myGLCanvas::myGLCanvas(wxWindow *parent)
    : wxGLCanvas(parent, wxID_ANY, NULL,
                 wxDefaultPosition, wxSize(800, 600),
                 wxFULL_REPAINT_ON_RESIZE)
{
  // イベントハンドラの登録
  Bind(wxEVT_PAINT, &myGLCanvas::OnPaint, this);
  Bind(wxEVT_KEY_DOWN, &myGLCanvas::OnKeyDown, this);
}

void myGLCanvas::OnKeyDown( wxKeyEvent& event )
{
  // 1階層下の親ウィンドウ(myFrame)のkeyDownハンドラに伝播させるための処理
  // (ここのハンドラ内ではイベント処理を行わないが)
  event.ResumePropagation(1);
  event.Skip(true);
}

void myGLCanvas::OnPaint(wxPaintEvent& WXUNUSED(event))
{
  wxPaintDC dc(this);  // キャンバス内を描画するのに必要らしい
  const wxSize ClientSize = GetClientSize();

  glViewport(0, 0, ClientSize.x, ClientSize.y);

  wxGetApp().GetContext(this).drawRect();

  SwapBuffers();
}

/***********************
 * myGLContext
 ***********************/
myGLContext::myGLContext(wxGLCanvas *canvas)
             : wxGLContext(canvas)
{
  SetCurrent(*canvas);

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f);
}

// 四角形を描画
void myGLContext::drawRect()
{
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glClearColor(0.5, 0.0, 0.6, 1.0);

  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();

  glTranslatef(0.0, 0.0, 0.0);
  glColor3f(1.0, 1.0, 0.0);
  glRectf(0.0, 0.0, 1.0, 1.0);

  glFlush();
}

実行結果はこちら。

OpenGLのテスト(四角形を表示)

やってる事は「それがどうかした?」というような内容ですが、それは置いといて。
sample の Cube のソースコードを参考に、できるだけいらない部分を削ったつもりでしたが、思ったよりも長くなってしまった…
それでは解説を。


3. OpenGL との連携へ