-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathWindow.cpp
237 lines (204 loc) · 5.39 KB
/
Window.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
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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
//
// Window 関連の処理
//
#include <cmath>
#include "Window.h"
// カメラの画角
const GLdouble fovy(40.0);
// 前方面の位置
const GLdouble zNear(1.0);
// 後方面の位置
const GLdouble zFar(20.0);
// 回転中心までの距離の初期値
const GLfloat initialPosition[] = { 0.0f, 0.0f, 5.0f };
// ホイールによる前後移動の速度
const GLfloat distanceStep(0.1f);
//
// コンストラクタ
//
Window::Window(const char *title, int width, int height)
: window(glfwCreateWindow(width, height, title, NULL, NULL))
, blightness(0), selection(0)
{
if (window == NULL)
{
// ウィンドウが作成できなかった
std::cerr << "Can't create GLFW window." << std::endl;
exit(1);
}
// 現在のウィンドウを処理対象にする
glfwMakeContextCurrent(window);
// 作成したウィンドウに対する設定
glfwSwapInterval(1);
// ゲームグラフィックス特論の都合にもとづく初期化
ggInit();
// このインスタンスの this ポインタを記録しておく
glfwSetWindowUserPointer(window, this);
// キーボードを操作した時の処理
glfwSetKeyCallback(window, keyboard);
// マウスボタンを操作したときの処理
glfwSetMouseButtonCallback(window, mouse);
// マウスホイール操作時に呼び出す処理
glfwSetScrollCallback(window, wheel);
// ウィンドウのサイズ変更時に呼び出す処理を登録する
glfwSetFramebufferSizeCallback(window, resize);
// カメラの初期位置を設定する
position[0] = -initialPosition[0];
position[1] = -initialPosition[1];
position[2] = -initialPosition[2];
// ウィンドウの設定を初期化する
resize(window, width, height);
}
//
// デストラクタ
//
Window::~Window()
{
glfwDestroyWindow(window);
}
//
// カラーバッファを入れ替えてイベントを取り出す
//
void Window::swapBuffers()
{
// カラーバッファを入れ替える
glfwSwapBuffers(window);
// OpenGL のエラーをチェックする
ggError("SwapBuffers");
// イベントを取り出す
glfwPollEvents();
// マウスの位置を調べる
double x, y;
glfwGetCursorPos(window, &x, &y);
// 左ボタンドラッグ
if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_1))
{
// トラックボール回転
tb.motion(static_cast<GLfloat>(x), static_cast<GLfloat>(y));
}
}
//
// キーボードをタイプした時の処理
//
void Window::keyboard(GLFWwindow *window, int key, int scancode, int action, int mods)
{
// このインスタンスの this ポインタを得る
Window *const instance(static_cast<Window *>(glfwGetWindowUserPointer(window)));
if (instance)
{
if (action == GLFW_PRESS)
{
switch (key)
{
case GLFW_KEY_SPACE:
break;
case GLFW_KEY_BACKSPACE:
case GLFW_KEY_DELETE:
break;
case GLFW_KEY_UP:
if (instance->blightness < 10) instance->blightness++;
break;
case GLFW_KEY_DOWN:
if (instance->blightness > 0) instance->blightness--;
break;
case GLFW_KEY_RIGHT:
instance->selection++;
break;
case GLFW_KEY_LEFT:
if (instance->selection > 0) instance->selection--;
break;
default:
break;
}
}
}
}
//
// マウスボタンを操作したときの処理
//
void Window::mouse(GLFWwindow *window, int button, int action, int mods)
{
// このインスタンスの this ポインタを得る
Window *const instance(static_cast<Window *>(glfwGetWindowUserPointer(window)));
if (instance)
{
double x, y;
glfwGetCursorPos(window, &x, &y);
switch (button)
{
case GLFW_MOUSE_BUTTON_1:
// トラックボール処理
if (action)
{
// トラックボール処理開始
instance->tb.start(static_cast<float>(x), static_cast<float>(y));
}
else
{
// トラックボール処理終了
instance->tb.stop(static_cast<float>(x), static_cast<float>(y));
}
break;
case GLFW_MOUSE_BUTTON_2:
break;
case GLFW_MOUSE_BUTTON_3:
break;
default:
break;
}
}
}
//
// マウスホイール操作時の処理
//
void Window::wheel(GLFWwindow *window, double x, double y)
{
// このインスタンスの this ポインタを得る
Window *const instance(static_cast<Window *>(glfwGetWindowUserPointer(window)));
if (instance)
{
if (glfwGetKey(window, GLFW_KEY_LEFT_CONTROL) || glfwGetKey(window, GLFW_KEY_RIGHT_CONTROL))
{
// Control キーが押されていれば左右位置を調整する
instance->position[0] += distanceStep * static_cast<GLfloat>(y);
}
else if (glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) || glfwGetKey(window, GLFW_KEY_RIGHT_SHIFT))
{
// Shift キーが押されていれば高さを調整する
instance->position[1] += distanceStep * static_cast<GLfloat>(y);
}
else
{
// 何も押されていなければ
if (fabs(x) > fabs(y))
{
// 左右位置を調整する
instance->position[0] += distanceStep * static_cast<GLfloat>(x);
}
else
{
// 前後位置を調整する
instance->position[2] += distanceStep * static_cast<GLfloat>(y);
}
}
}
}
//
// ウィンドウのサイズ変更時の処理
//
void Window::resize(GLFWwindow *window, int width, int height)
{
// このインスタンスの this ポインタを得る
Window *const instance(static_cast<Window *>(glfwGetWindowUserPointer(window)));
if (instance)
{
// ウィンドウ全体をビューポートにする
glViewport(0, 0, width, height);
// 投影変換行列を初期化する
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(fovy, GLdouble(width) / GLdouble(height), zNear, zFar);
// トラックボール処理の範囲を設定する
instance->tb.region(width, height);
}
}