glfwSetWindowUserPointerでthisポインタを指定し、非メンバ関数であるコールバック関数の第一引数からthisを取り出せるようにすれば、間接的にだが自作クラスのメンバ関数を呼び出す事ができる。
#pragma once #pragma comment(lib,"glfw3.lib") #include <gl/glfw/glfw3.h> class MyWindowBase { protected: GLFWwindow* _window; protected:
// コールバック関数から呼ばれるメンバ関数群 //////////////////////////
virtual void key(int key, int scancode, int action, int mods) {} virtual void mouse_button(int button, int action, int mods) {} virtual void mouse_move(double xpos, double ypos) {} virtual void mouse_wheel(double xoffset, double yoffset) {} virtual void framebuffer_size(int width, int height) {} ////////////////////////////////////////////// ////////////////////////////////////////////// virtual void setting() {} virtual void draw() {}
protected:
// GLFWに指定するコールバック関数(staticメンバ関数) ////////////////////////// // GLFWのコールバック関数にはこれを指定する。glfwSetWindowUserPointerで指定したthisポインタを // glfwGetWindowUserPointerで取得し、メンバ関数を呼び出す
static void key_callback(GLFWwindow* pwin, int key, int scancode, int action, int mods) { MyWindowBase* myw = static_cast<MyWindowBase*>(glfwGetWindowUserPointer(pwin)); myw->key(key, scancode, action, mods); } static void mouse_button_callback(GLFWwindow* pwin, int button, int action, int mods) { MyWindowBase* myw = static_cast<MyWindowBase*>(glfwGetWindowUserPointer(pwin)); myw->mouse_button(button, action, mods); } static void mouse_move_callback(GLFWwindow* pwin, double xpos, double ypos) { MyWindowBase* myw = static_cast<MyWindowBase*>(glfwGetWindowUserPointer(pwin)); myw->mouse_move(xpos, ypos); } static void mouse_wheel_callback(GLFWwindow* pwin, double xoffset, double yoffset) { MyWindowBase* myw = static_cast<MyWindowBase*>(glfwGetWindowUserPointer(pwin)); myw->mouse_wheel(xoffset, yoffset); } static void framebuffer_size_callback(GLFWwindow* pwin, int width, int height) { MyWindowBase* myw = static_cast<MyWindowBase*>(glfwGetWindowUserPointer(pwin)); myw->framebuffer_size(width, height); } static void draw_callback(GLFWwindow* pwin) { MyWindowBase* myw = static_cast<MyWindowBase*>(glfwGetWindowUserPointer(pwin)); myw->draw(); }
public:
// ここでGLFWの初期化を行う ///////////////////////////////// int init(int winwidth,int winheight,const char* wintitle) {
// GLFW の初期化 if (glfwInit() == GL_FALSE) { // 初期化に失敗したら終了 return 1; }
// ウィンドウを作成 _window = glfwCreateWindow( winwidth, //width winheight, //height wintitle,//title NULL, //monitor NULL //share ); //////////////////////////////////////////////////////////////////////////////// // ウィンドウを作成できなければ終了 if (_window == nullptr) { glfwTerminate(); return 1; }
//////////////////////////////////////////////////////////////////////////////// // 自身のポインタをGLFWwindowオブジェクトにセット glfwSetWindowUserPointer(_window, this);
//////////////////////////////////////////// // コールバック関数の設定 glfwSetKeyCallback(_window, MyWindowBase::key_callback); glfwSetMouseButtonCallback(_window, MyWindowBase::mouse_button_callback); glfwSetScrollCallback(_window, MyWindowBase::mouse_wheel_callback); glfwSetCursorPosCallback(_window, MyWindowBase::mouse_move_callback); glfwSetFramebufferSizeCallback(_window, MyWindowBase::framebuffer_size_callback); glfwSetWindowRefreshCallback(_window, MyWindowBase::draw_callback); glfwMakeContextCurrent(_window); }
// イベントループ /////////////////////////////////
void loop() { while (glfwWindowShouldClose(_window) == GL_FALSE) { draw(); // イベント取得 glfwPollEvents(); } glfwTerminate(); }
};
#include <memory> #include <iostream> #include<windows.h> #include "CglfwBase.hpp" #pragma comment(lib,"opengl32.lib") class MyWindow :public MyWindowBase { int width; int height; public:
virtual void setting()override { glfwGetFramebufferSize(_window, &width, &height); } virtual void key(int key, int scancode, int action, int mods)override { // https://www.glfw.org/docs/latest/group__keys.html#ga99aacc875b6b27a072552631e13775c7 // action ... GLFW_PRESS , GLFW_REPEAT , GLFW_RELEASE //特殊キー if (key == GLFW_KEY_UP && action == GLFW_PRESS) { } if (key == GLFW_KEY_DOWN && action == GLFW_PRESS) { } if (key == GLFW_KEY_LEFT && action == GLFW_PRESS) { } if (key == GLFW_KEY_RIGHT && action == GLFW_PRESS) { } if (key >= GLFW_KEY_A && key <= GLFW_KEY_Z) { if (action == GLFW_PRESS) { const char* key_name = glfwGetKeyName(key, 0); printf("key - %s\n", key_name); } } } virtual void mouse_button(int button, int action, int mods)override { double xpos, ypos; glfwGetCursorPos(_window, &xpos, &ypos); if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS) { printf("mouse L pressed\n"); } if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_RELEASE) { printf("mouse L released\n"); } if (button == GLFW_MOUSE_BUTTON_RIGHT && action == GLFW_PRESS) { } if (button == GLFW_MOUSE_BUTTON_RIGHT && action == GLFW_RELEASE) { } if (button == GLFW_MOUSE_BUTTON_MIDDLE && action == GLFW_PRESS) { } draw(); } virtual void mouse_move(double xpos, double ypos)override { printf("mouse is moving\n"); draw(); } // マウスホイールを処理するコールバック関数 virtual void mouse_wheel(double xoffset, double yoffset)override { if (yoffset < 0) { } if (yoffset > 0) { } draw(); } virtual void framebuffer_size(int _width, int _height)override { width = _width; height = _height; } virtual void draw()override { ///////////////////// // 描画 glViewport(0, 0, width, height); glClearColor(0.3, 0.3, 0.3, 1); glClear(GL_COLOR_BUFFER_BIT); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); float v = 0.7; glBegin(GL_TRIANGLES); glColor3f(0, 0, 1); glVertex3f(-v, -v, 0.0); glColor3f(1, 0, 1); glVertex3f(v, -v, 0.0); glColor3f(1, 1, 1); glVertex3f(v, v, 0.0); glEnd(); // ///////////////////// glFlush(); glfwSwapBuffers(_window); }
}; int main() { MyWindow win; win.init(600,600,"glfw window"); win.setting(); win.loop(); }