----------------------------------------------------------------
我正在尝试创建一个类别的类,该类可以照顾使用基本功能(例如Window
toggling full screen
和窗口调整大小)的窗口。我可以用
binding ESC to close the window
退出,但是当我按下ESC
时,我一直在第16行中访问F11
,不确定为什么会发生这种情况。
我已经尝试在调用toggel函数之前添加打印语句,我看到有效的值,但是一旦达到
Exception thrown at 0x001D6F6B in IDK.exe: 0xC0000005: Access violation reading location 0xCCCCCF78.
,我就会遇到相同的错误,并且我被卡住了。 window.h
Window.cpp
代码在以下示例中正常运行:
glfwGetWindowPos(_window, &_windowedMode.xpos, &_windowedMode.ypos);
,但是,一旦我进入图片,它就会出现同样的问题。camera.h
#pragma once
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
struct WindowProperties
{
int xpos, ypos;
int width, height;
};
class Window
{
private:
std::string _title;
bool _fullscreen;
GLFWwindow* _window;
float _aspectRatio;
WindowProperties _windowedMode;
static void framebufferSizeCallback(GLFWwindow* window, int width, int height)
{
Window* windowInstance = static_cast<Window*>(glfwGetWindowUserPointer(window));
if (windowInstance)
{
windowInstance->handleFramebufferResize(width, height);
}
}
static void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
Window* windowInstance = static_cast<Window*>(glfwGetWindowUserPointer(window));
if (windowInstance)
{
windowInstance->handleKeyPress(key, scancode, action, mods);
}
}
public:
Window(const std::string& title, WindowProperties winProp, bool fullscreen = false)
: _title(title)
, _windowedMode(winProp)
, _fullscreen(fullscreen)
, _window(nullptr)
, _aspectRatio(static_cast<float>(_windowedMode.width) / static_cast<float>(_windowedMode.height)) {}
void toggleFullscreen()
{
_fullscreen = !_fullscreen;
if (_fullscreen)
{
glfwGetWindowPos(_window, &_windowedMode.xpos, &_windowedMode.ypos);
glfwGetWindowSize(_window, &_windowedMode.width, &_windowedMode.height);
GLFWmonitor* monitor = glfwGetPrimaryMonitor();
const GLFWvidmode* mode = glfwGetVideoMode(monitor);
glfwSetWindowMonitor(_window, monitor, 0, 0, mode->width, mode->height, mode->refreshRate);
}
else
{
// Return to windowed mode with previous position and size
glfwSetWindowMonitor(_window, nullptr,
_windowedMode.xpos, _windowedMode.ypos,
_windowedMode.width, _windowedMode.height,
0);
}
}
void handleFramebufferResize(int width, int height)
{
_windowedMode.width = width;
_windowedMode.height = height;
_aspectRatio = static_cast<float>(width) / static_cast<float>(height);
glViewport(0, 0, width, height);
}
void handleKeyPress(int key, int scancode, int action, int mods)
{
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
{
glfwSetWindowShouldClose(_window, true);
}
else if (key == GLFW_KEY_F11 && action == GLFW_PRESS)
{
toggleFullscreen();
}
}
bool init()
{
if (!glfwInit())
{
std::cerr << "Failed to initialize GLFW!" << std::endl;
return false;
}
_window = glfwCreateWindow(_windowedMode.width, _windowedMode.height, _title.c_str(),
_fullscreen ? glfwGetPrimaryMonitor() : nullptr, nullptr);
if (!_window)
{
std::cerr << "Failed to create GLFW window!" << std::endl;
glfwTerminate();
return false;
}
glfwMakeContextCurrent(_window);
glfwSwapInterval(1);
glfwSetWindowUserPointer(_window, this);
// Use lambda functions to bind the instance
glfwSetFramebufferSizeCallback(_window, [](GLFWwindow* window, int width, int height)
{
Window* windowInstance = static_cast<Window*>(glfwGetWindowUserPointer(window));
if (windowInstance)
{
windowInstance->handleFramebufferResize(width, height);
}
});
glfwSetKeyCallback(_window, [](GLFWwindow* window, int key, int scancode, int action, int mods) {
Window* windowInstance = static_cast<Window*>(glfwGetWindowUserPointer(window));
if (windowInstance)
{
windowInstance->handleKeyPress(key, scancode, action, mods);
}
});
if (glewInit() != GLEW_OK)
{
std::cerr << "Failed to initialize GLEW!" << std::endl;
glfwTerminate();
return false;
}
glEnable(GL_DEPTH_TEST);
return true;
}
float getAspectRatio() const { return _aspectRatio; }
GLFWwindow* getWindow() const { return _window; }
void setKeyCallback(GLFWkeyfun callback) { glfwSetKeyCallback(_window, callback); }
void setScrollCallback(GLFWscrollfun callback) { glfwSetScrollCallback(_window, callback); }
void setCursorPositionCallback(GLFWcursorposfun callback) { glfwSetCursorPosCallback(_window, callback); }
~Window()
{
if (_window)
{
glfwDestroyWindow(_window);
_window = nullptr;
}
glfwTerminate();
}
};
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include "Window.h"
#define PI 3.14159265358979
WindowProperties windowedMode(100, 100, 920, 900);
float deltaTime = 0.0f;
float lastFrame = 0.0f;
int main()
{
Window window("IDK Window", windowedMode, false);
if (!window.init())
{
return -1;
}
float vertices[] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f,
0.0f, 0.5f, 0.0f,
-0.5f, -0.5f, 0.0f
};
// Create and bind VAO/VBO
GLuint VAO, VBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// Configure vertex attributes
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// Unbind to avoid accidental modification
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
glLineWidth(2.0f);
while (!glfwWindowShouldClose(window.getWindow()))
{
float currentTime = static_cast<float>(glfwGetTime());
deltaTime = currentTime - lastFrame;
lastFrame = currentTime;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Draw lines
glBindVertexArray(VAO);
glDrawArrays(GL_LINES, 0, 8);
glfwSwapBuffers(window.getWindow());
glfwPollEvents();
}
glfwTerminate();
return 0;
}
Cameracontroller:
Camera.h
crashing应用程序:
#pragma once
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
enum Camera_Movement
{
FORWARD,
BACKWARD,
LEFT,
RIGHT,
UP,
DOWN
};
// Default camera values
const float YAW = -90.0f;
const float PITCH = 0.0f;
const float SPEED = 2.5f;
const float SENSITIVITY = 0.1f;
const float ZOOM = 45.0f;
class Camera
{
public:
glm::vec3 Position;
glm::vec3 Front;
glm::vec3 Up;
glm::vec3 Right;
glm::vec3 WorldUp;
// euler Angles
float Yaw;
float Pitch;
// camera options
float MovementSpeed;
float MouseSensitivity;
float Zoom;
// constructor with vectors
Camera( glm::vec3 position = glm::vec3(0.0f, 0.0f, 0.0f),glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f), float yaw = YAW, float pitch = PITCH)
: Front(glm::vec3(0.0f, 0.0f, -1.0f)), MovementSpeed(SPEED), MouseSensitivity(SENSITIVITY), Zoom(ZOOM)
{
Position = position;
WorldUp = up;
Yaw = yaw;
Pitch = pitch;
updateCameraVectors();
}
// constructor with scalar values
Camera(float posX, float posY, float posZ, float upX, float upY, float upZ, float yaw, float pitch)
: Front(glm::vec3(0.0f, 0.0f, -1.0f)), MovementSpeed(SPEED), MouseSensitivity(SENSITIVITY), Zoom(ZOOM)
{
Position = glm::vec3(posX, posY, posZ);
WorldUp = glm::vec3(upX, upY, upZ);
Yaw = yaw;
Pitch = pitch;
updateCameraVectors();
}
// Camera movement methods
glm::mat4 GetViewMatrix();
void ProcessKeyboard(Camera_Movement direction, float deltaTime);
void ProcessMouseMovement(float xoffset, float yoffset, GLboolean constrainPitch = true);
void ProcessMouseScroll(float yoffset);
private:
void updateCameraVectors();
};
当您在内存中访问地址时遇到错误时,问题可能不会在线路附近触发它,因为其他事情完全可以干扰该线路试图访问的内存。由于添加相机课后您会遇到错误,因此我们知道要看那里。由于该问题来自GLFW函数,因此我们浏览了相机类代码中的所有GLFW函数,问题在于,当您先前在窗口类中设置它们时,您将在相机类中设置新的GLFW回调。这说明了问题的来源,以及为什么在相机类中设置新回调后,您会在窗口类中遇到GLFW问题。
#include "Camera.h"
#include <iostream>
glm::mat4 Camera::GetViewMatrix()
{
return glm::lookAt(Position, Position + Front, Up);
}
// processes input received from any keyboard-like input system. Accepts input parameter in the form of camera defined ENUM (to abstract it from windowing systems)
void Camera::ProcessKeyboard(Camera_Movement direction, float deltaTime)
{
float velocity = MovementSpeed * deltaTime;
if (direction == FORWARD)
Position += Front * velocity;
if (direction == BACKWARD)
Position -= Front * velocity;
if (direction == LEFT)
Position -= Right * velocity;
if (direction == RIGHT)
Position += Right * velocity;
if (direction == UP)
Position += Up * velocity;
if (direction == DOWN)
Position -= Up * velocity;
}
// processes input received from a mouse input system. Expects the offset value in both the x and y direction.
void Camera::ProcessMouseMovement(float xoffset, float yoffset, GLboolean constrainPitch)
{
xoffset *= MouseSensitivity;
yoffset *= MouseSensitivity;
Yaw += xoffset;
Pitch += yoffset;
// make sure that when pitch is out of bounds, screen doesn't get flipped
if (constrainPitch)
{
if (Pitch > 89.0f)
Pitch = 89.0f;
if (Pitch < -89.0f)
Pitch = -89.0f;
}
// update Front, Right and Up Vectors using the updated Euler angles
updateCameraVectors();
}
// processes input received from a mouse scroll-wheel event. Only requires input on the vertical wheel-axis
void Camera::ProcessMouseScroll(float yoffset)
{
Zoom -= (float)yoffset;
if (Zoom < 1.0f)
Zoom = 1.0f;
if (Zoom > 45.0f)
Zoom = 45.0f;
}
void Camera::updateCameraVectors()
{
// calculate the new Front vector
glm::vec3 front;
front.x = cos(glm::radians(Yaw)) * cos(glm::radians(Pitch));
front.y = sin(glm::radians(Pitch));
front.z = sin(glm::radians(Yaw)) * cos(glm::radians(Pitch));
Front = glm::normalize(front);
// also re-calculate the Right and Up vector
Right = glm::normalize(glm::cross(Front, WorldUp)); // normalize the vectors, because their length gets closer to 0 the more you look up or down which results in slower movement.
Up = glm::normalize(glm::cross(Right, Front));
}
要解决此问题,您应该只处理一个类(窗口类别或更广泛的上下文类以管理GLFW函数)内部的任何GLFWSET功能。在OpenGL和GLFW中,每个窗口都通过一个活动上下文来管理一切。因此,您的想法似乎是在两个不同的类中设置多个回调,然后Glfw将通过记住两个回调和调用这两个呼叫(听起来像是一件有趣的事情,可以尝试一下自己的实现)来管理此问题),但这无效。每个窗口一个上下文,每个回调类型一个回调(虽然仅在一个类中进行GLFWSET呼叫并不是绝对必要的,但我强烈建议您避免彼此脚趾的单独类别的单独类)。我的最终建议是使用调试器逐步浏览您的代码并查看变量并在每个步骤中调用堆栈,尤其是在C/C ++中使用OpenGL。