'how to correctly set and retrieve glfw WindowUserPointer for callback functions
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
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
