我创建了一个
Camera
类,其中包含 std::map<int, void(Camera::*)()
的键盘映射,以方便游戏中的键绑定选项和比使用 switch 语句可以完成的更高性能的键操作查找。
我无法使用
glfwSetKeyCallback
函数从键盘映射访问操作功能,并且我一直遇到 keyCallback 函数和 GLFWkeyfun
之间的签名不匹配的情况。
这是
Camera
课程:
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 }
};
};
这些是我的 cpp 文件中的相关函数定义:
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;
}
我尝试了这个解决方案,它允许我编译程序,但是在调用
auto afunc = keyboard_map[key];
函数的 keyCallBack
行时,程序崩溃了,但没有产生错误代码。
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);
}
});
}
);
我完全找不到这个问题的解决方案。有人可以帮助我理解为什么我的原始方法中存在签名不匹配,为什么访问地图会导致我尝试的其他方法崩溃,以及如何让此设置按预期工作?
编辑:错误:“
void(Camera::*)(GLFWwindow* window, int key, int scancode, int action, int mods)
类型的参数与GLFWkeyfun
类型的参数不兼容”
您正在尝试为您的 glfwSetKeyCallback()
回调使用
非静态类方法。这是行不通的,因为
glfwSetKeyCallback()
需要一个 C 风格的函数指针。因此,您必须:
keyCallBack()
保持静态keyCallBack()
类中完全删除 Camera
并将其设为独立函数无论哪种方式,正如您已经知道的,您都可以使用
glfwSetWindowUserPointer()
将 Camera*
指针存储到 GLWindow
中,然后在回调中使用 glfwGetWindowUserPointer()
返回到 Camera
对象。但是,您显示的代码没有在任何地方调用 glfwSetWindowUserPointer()
。