スポンサーリンク

| キーワード:

GLFWのコールバック関数でメンバ変数を呼び出す

glfwSetWindowUserPointerでthisポインタを指定し、非メンバ関数であるコールバック関数の第一引数からthisを取り出せるようにすれば、間接的にだが自作クラスのメンバ関数を呼び出す事ができる。

CglfwBase.hpp

#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(); }
};

main.cpp

#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();

}

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)


この記事のトラックバックURL: