I have created a Camera class containing a keymap of std::map<int, void(Camera::*)() to facilitate an in-game option for key bindings and higher performance key-action lookup than what could be accomplished with switch statements.
I have trouble accessing the action-functions from the keymap with the glfwSetKeyCallback function and I keep running into a signature mismatch between my keyCallback function and GLFWkeyfun.
This is the Camera class:
class Camera {
Camera();
private:
void Mouse_Input();
void Joystick_input();
void keyCallBack(GLFWwindow* window, int key, int scancode, int action, int mods);
void forward() {
position += velocity * Orientation;
}
void backward() {
position -= velocity * Orientation;
}
void left() {// Left
position -= velocity * glm::normalize(glm::cross(Orientation, Up));
}
void right() {
position += velocity * glm::normalize(glm::cross(Orientation, Up));
}
void up() {
position += velocity * Up;
}
void down() {
position -= velocity * Up;
}
void sprint() {
velocity *= 2.f;
}
void noclip() {
noClip = !noClip;
if (!noClip) {
gravity(position, velocity);
}
}
void close() {
glfwSetWindowShouldClose(Window::handle, true);
}
public:
alignas(16) glm::mat4 view;
alignas(16) glm::mat4 proj;
alignas(16) glm::vec3 position;
void update(float FOVdeg, float nearPlane, float farPlane);
protected:
bool noClip = true;
bool firstClick = true;
float velocity = 0.05f;
float sensitivity = 1.75f;
glm::vec3 Orientation;
glm::vec3 Up;
using pfunc = void (Camera::*)();
std::map<int, pfunc> keyboard_map
{
{ GLFW_KEY_W, &Camera::forward },
{ GLFW_KEY_A, &Camera::left },
{ GLFW_KEY_S, &Camera::backward },
{ GLFW_KEY_D, &Camera::right },
{ GLFW_KEY_SPACE, &Camera::up },
{ GLFW_KEY_LEFT_CONTROL, &Camera::down },
{ GLFW_KEY_LEFT_SHIFT, &Camera::sprint },
{ GLFW_KEY_V, &Camera::noclip },
{ GLFW_KEY_ESCAPE, &Camera::close }
};
};
These are the relevant function definitions from my cpp file:
void Camera::keyCallBack(GLFWwindow* window, int key, int scancode, int action, int mods) {
if (!GLFW_PRESS | !GLFW_REPEAT) {
return;
}
auto afunc = keyboard_map[key];//gets camera action function from map
(this->*afunc)();//executes action function
}
void Camera::update(float FOVdeg, float nearPlane, float farPlane)
{
if (glfwJoystickPresent(GLFW_JOYSTICK_1)) {//Check for joystick
std::jthread t_Console([&] { Joystick_input(); });
}
std::jthread t_PC([this] { glfwSetKeyCallback(Window::handle, &Camera::keyCallBack); }); //Line causing the error
std::jthread t_mouse([&] { Mouse_Input(); });
if (!noClip) {
gravity(position, velocity);
}
view = glm::lookAt(position, position + Orientation, Up);
proj = glm::perspective(glm::radians(FOVdeg), (float)GPU::Extent.width / GPU::Extent.height, nearPlane, farPlane);
proj[1][1] *= -1;
}
I tried this solution which allowed me to compile the program, but the program crashes without producing an error code when calling the line auto afunc = keyboard_map[key]; of the keyCallBack function.
std::jthread t_test([this]()
{
glfwSetKeyCallback(Window::handle,
[](GLFWwindow* window, int key, int scancode, int action, int mods)
{
auto* instance = static_cast<Camera*>(glfwGetWindowUserPointer(window));
if (instance) {
instance->keyCallBack(window, key, scancode, action, mods);
}
});
}
);
I am completely lost for a solution to this problem. Could someone help me understand why there is a signature mismatch in my original method, why accessing the map is causing the program to crash with the other method I tried, and how I can get this set up to work as intended?
Edit:
Error 31 C2664
GLFWkeyfun glfwSetKeyCallback(GLFWwindow *,GLFWkeyfun): cannot convert argument 2 fromvoid (__cdecl vk::Camera::* )(GLFWwindow *,int,int,int,int)toGLFWkeyfun
You are trying to use a non-static class method for your
glfwSetKeyCallback()callback. That will not work, asglfwSetKeyCallback()expects a C-style function pointer instead. So, you will have to either:keyCallBack()be statickeyCallBack()from theCameraclass altogether and make it a standalone functionEither way, as you already know, you can use
glfwSetWindowUserPointer()to store aCamera*pointer into theGLWindow, and then useglfwGetWindowUserPointer()inside your callback to get back to yourCameraobject. However, the code you have shown is not callingglfwSetWindowUserPointer()anywhere.