如何正确设置和检索回调函数的 glfw WindowUserPointer
考虑一个简单的MouseInputHandler
,它用作InputHandler
类的成员。 MouseInputHandler
和 InputHandler
都有一个成员 InputConfig* conf
来访问灵敏度和鼠标速度等内容。
这似乎工作正常,直到我引入了滚动回调功能,该功能在 MouseInputHandler
的构造函数中初始化。我使用MouseInputHandler的成员函数scrollXCallback作为scrollback函数。为此,我需要使用 glfwSetWindowUserPointer
设置 glfwWindowUserPointer 并将其设置为 MouseInputHandler
的实例。另外,我需要定义一个函数“func”来获取窗口用户指针并调用实际的回调函数。
我遇到的问题是,当调用滚动回调时,程序崩溃。
我发现在成员回滚函数中访问的 InputConf *conf
的内存地址与我从 rotate
访问 *conf
时的内存地址不同> 会员功能。
我想这与我在非成员回调“func”中使用的 static_cast 有关,但我不知道如何解决这个问题。有人可以准确解释这里发生了什么吗?
mouse.hpp
#ifndef A_MOUSEINPUT_HPP
#define A_MOUSEINPUT_HPP
#include "InputConfig.hpp"
#include "camera.hpp"
#include <glfw/glfw3.h>
struct InputConfig
{
float speed = 0.05f;
float defaultSpeed = 0.05f;
float fastSpeed = 0.2f;
float sensitivity = 150.0f;
bool invertX = true;
bool invertY = false;
};
class MouseInputHandler
{
private:
GLFWwindow *window;
Camera *camera;
InputConfig *conf;
bool firstClick = true;
// mouse state
Vector<double, 2> lastMousePos;
Vector<double, 2> mousePos;
Vector<double, 3> rotationCenter;
public:
MouseInputHandler(GLFWwindow *window, Camera *camera, InputConfig *conf):
window(window), camera(camera), conf(conf)
{
// scroll callback
// -----------
glfwSetWindowUserPointer(window, this);
auto func = [](GLFWwindow* w, double, double yOffset)
{
static_cast<MouseInputHandler*>(glfwGetWindowUserPointer(w))->scrollX_callback(yOffset);
};
glfwSetScrollCallback(window, func);
}
void scrollX_callback(double yoffset)
{
float fac = conf->sensitivity; // <<<<<<<<< THIS FAILS, conf has different address here than in rotate()???
camera->zoom(fac/10.0*yoffset);
}
void operator()()
{
updateMousePos();
// Handles mouse inputs
if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS)
{
rotate();
}
if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS)
{
pan();
}
if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT) == GLFW_RELEASE && glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_RELEASE)
{
firstClick = true;
}
}
private:
void updateMousePos()
{
// Stores the coordinates of the cursor
double mouseX, mouseY;
// Fetches the coordinates of the cursor
glfwGetCursorPos(window, &mouseX, &mouseY);
// prevent jumping view on first click
if(firstClick)
{
mousePos = Vector<double, 2>(mouseX, mouseY);
firstClick = false;
}
lastMousePos = mousePos;
mousePos = Vector<double, 2>(mouseX, mouseY);
}
void rotate()
{
std::cout << conf << std::endl;
camera->rotateX( - conf->sensitivity * dy());
camera->rotateY( - conf->sensitivity * dx());
}
void pan()
{
camera->moveX(-conf->sensitivity/10.0*dx());
camera->moveY(conf->sensitivity/10.0*dy());
}
float dx()
{
return (mousePos.x() - lastMousePos.x())/lastMousePos.x();
}
float dy()
{
return (mousePos.y() - lastMousePos.y())/lastMousePos.y();
}
};
class InputHandler
{
private:
GLFWwindow *window;
InputConfig *conf;
MouseInputHandler mouse;
public:
InputHandler(GLFWwindow *window, Camera *camera):
window(window), conf(new InputConfig), mouse(window, camera, conf)
{
std::cout << conf << std::endl;
}
~InputHandler()
{
delete conf;
conf = nullptr;
}
GLFWwindow *getWindow()
{
return window;
}
InputConfig *getConfig()
{
return conf;
}
// call instance to handle events
void operator()(bool doMouse, bool doKey)
{
if(doMouse) mouse();
}
};
#endif
Consider a simple MouseInputHandler
which is used as a member of a InputHandler
class. Both, the MouseInputHandler
and the InputHandler
have a member InputConfig* conf
to access stuff like sensitivity and mouse speed.
This seems to work fine until i introduced the scroll callback functionality, which is initialized in the constructor of MouseInputHandler
. I use the member function scrollXCallback
of MouseInputHandler
as scrollback function. To do this i needed to set the glfwWindowUserPointer with glfwSetWindowUserPointer
and set it to the instance of MouseInputHandler
. Additionally i needed to define a function ´func´ the gets the window user pointer and calls the actual callback function.
The problem that i am experiencing is that when the scroll callback is called the program crashes.
I found out that the InputConf *conf
that is accessed in the member scrollback function has a different memory adress than when i access *conf
from the rotate
member function.
i guess it has to do with the static_cast i use in the non member callback ´func´ but i do not know how to solve this. Can somebody explain what is happening here exactly?
mouse.hpp
#ifndef A_MOUSEINPUT_HPP
#define A_MOUSEINPUT_HPP
#include "InputConfig.hpp"
#include "camera.hpp"
#include <glfw/glfw3.h>
struct InputConfig
{
float speed = 0.05f;
float defaultSpeed = 0.05f;
float fastSpeed = 0.2f;
float sensitivity = 150.0f;
bool invertX = true;
bool invertY = false;
};
class MouseInputHandler
{
private:
GLFWwindow *window;
Camera *camera;
InputConfig *conf;
bool firstClick = true;
// mouse state
Vector<double, 2> lastMousePos;
Vector<double, 2> mousePos;
Vector<double, 3> rotationCenter;
public:
MouseInputHandler(GLFWwindow *window, Camera *camera, InputConfig *conf):
window(window), camera(camera), conf(conf)
{
// scroll callback
// -----------
glfwSetWindowUserPointer(window, this);
auto func = [](GLFWwindow* w, double, double yOffset)
{
static_cast<MouseInputHandler*>(glfwGetWindowUserPointer(w))->scrollX_callback(yOffset);
};
glfwSetScrollCallback(window, func);
}
void scrollX_callback(double yoffset)
{
float fac = conf->sensitivity; // <<<<<<<<< THIS FAILS, conf has different address here than in rotate()???
camera->zoom(fac/10.0*yoffset);
}
void operator()()
{
updateMousePos();
// Handles mouse inputs
if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS)
{
rotate();
}
if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS)
{
pan();
}
if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT) == GLFW_RELEASE && glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_RELEASE)
{
firstClick = true;
}
}
private:
void updateMousePos()
{
// Stores the coordinates of the cursor
double mouseX, mouseY;
// Fetches the coordinates of the cursor
glfwGetCursorPos(window, &mouseX, &mouseY);
// prevent jumping view on first click
if(firstClick)
{
mousePos = Vector<double, 2>(mouseX, mouseY);
firstClick = false;
}
lastMousePos = mousePos;
mousePos = Vector<double, 2>(mouseX, mouseY);
}
void rotate()
{
std::cout << conf << std::endl;
camera->rotateX( - conf->sensitivity * dy());
camera->rotateY( - conf->sensitivity * dx());
}
void pan()
{
camera->moveX(-conf->sensitivity/10.0*dx());
camera->moveY(conf->sensitivity/10.0*dy());
}
float dx()
{
return (mousePos.x() - lastMousePos.x())/lastMousePos.x();
}
float dy()
{
return (mousePos.y() - lastMousePos.y())/lastMousePos.y();
}
};
class InputHandler
{
private:
GLFWwindow *window;
InputConfig *conf;
MouseInputHandler mouse;
public:
InputHandler(GLFWwindow *window, Camera *camera):
window(window), conf(new InputConfig), mouse(window, camera, conf)
{
std::cout << conf << std::endl;
}
~InputHandler()
{
delete conf;
conf = nullptr;
}
GLFWwindow *getWindow()
{
return window;
}
InputConfig *getConfig()
{
return conf;
}
// call instance to handle events
void operator()(bool doMouse, bool doKey)
{
if(doMouse) mouse();
}
};
#endif
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论