Синий экран смерти, вызванный программой Quad Tree

Я пишу древовидную структуру для планеты, которая уменьшается и увеличивается в деталях, когда вы находитесь далеко от квадра и очень близко к нему. Тем не менее, я сталкиваюсь с некоторыми действительно серьезными и раздражающими ошибками.

У меня есть две константы, определяемые препроцессором, которые определяют размер дерева Quad (QUAD_WIDTH и QUAD_HEIGHT), когда я изменяю значение на что угодно, кроме 32 (например, 16 или 64), я получаю синий экран смерти. Я использую code :: blocks в качестве своей IDE, еще одна вещь: всякий раз, когда я пытаюсь отладить программу в code :: blocks, я также получаю синий экран смерти (не имеет значения, являются ли константы 32 или нет)

Почему это так? И как я могу это исправить.
введите описание изображения здесь
PQuad.cpp

#include "..\include\PQuad.h"#include "..\include\Color3.h"
#include <iostream>
#include <vector>
#include <cmath>

#include <GL/glew.h>
#include <GL/glu.h>
#include <GL/gl.h>

#define QUAD_WIDTH 32
#define QUAD_HEIGHT 32

#define NUM_OF_CHILDREN 4

#define MAX_DEPTH 4

PQuad::PQuad(FaceDirection face_direction, float planet_radius)  {
this->built = false;
this->spherised = false;
this->face_direction = face_direction;
this->radius = planet_radius;
this->planet_centre = glm::vec3(0, 0, 0);
}

PQuad::~PQuad()  {
}

std::vector<PQuad> PQuad::get_children()  {
return children;
}

bool PQuad::get_built()  {
return this->built;
}

int PQuad::get_depth()  {
return this->depth;
}

float *PQuad::get_table()  {
return tree;
}

float PQuad::get_element_width()  {
return element_width;
}

glm::vec3 PQuad::get_position()  {
return position;
}

glm::vec3 PQuad::get_centre()  {
return centre;
}

void PQuad::get_recursive(glm::vec3 player_pos, std::vector<PQuad*>& out_children)  {
for (size_t i = 0; i < children.size(); i++)  {
children[i].get_recursive(player_pos, out_children);
}

if (this->should_draw(player_pos) ||
this->depth == 0)  {
out_children.emplace_back(this);
}
}

GLuint PQuad::get_vertexbuffer()  {
return vbo_vertices;
}

GLuint PQuad::get_colorbuffer()  {
return vbo_colors;
}

GLuint PQuad::get_normalbuffer()  {
return vbo_normals;
}

GLuint PQuad::get_elementbuffer()  {
return ibo_elements;
}

void PQuad::set_parent(PQuad *quad)  {
this->parent = quad;
}

void PQuad::set_child_index(int child_index)  {
this->child_index = child_index;
}

void PQuad::set_depth(int depth)  {
this->depth = depth;
}

void PQuad::set_root(bool root)  {
this->root = root;
}

void PQuad::calculate_position()  {
this->element_width = depth == 0 ? 1.0f : parent->get_element_width() / 2.0f;

float quad_y = child_index / 2 == 0 ? 0 : element_width * QUAD_HEIGHT - element_width;
float quad_x = child_index % 2 == 0 ? 0 : element_width * QUAD_WIDTH - element_width;

if (this->depth != 0)  {
quad_x += parent->get_position().x;
quad_y += parent->get_position().y;
}

this->position = glm::vec3(quad_x, quad_y, 0);
}

void PQuad::construct()  {
if (!this->built)  {
std::vector<glm::vec3> vertices;
std::vector<glm::vec3> normals;
std::vector<Color3> colors;
std::vector<GLushort> elements;

construct_vertices(&vertices, &colors);
construct_elements(&elements);
spherise(&vertices, &normals);
construct_normals(&vertices, &elements, &normals);

construct_buffers(&vertices, &colors, &elements, &normals);

float distance = radius;

if (!spherised)  {
distance = QUAD_WIDTH;
}

construct_depth_table(distance);

this->built = true;
}
}

void PQuad::construct_depth_table(float distance)  {
tree[0] = -1;

for (int i = 1; i < MAX_DEPTH; i++)  {
tree[i] = distance;

distance /= 2.0f;
}
}

void PQuad::construct_children()  {
calculate_position();

if (depth < (int)MAX_DEPTH)  {
children.reserve((int)NUM_OF_CHILDREN);

for (int i = 0; i < (int)NUM_OF_CHILDREN; i++)  {
children.emplace_back(PQuad(this->face_direction, this->radius));
PQuad *child = &children.back();

child->set_depth(depth + 1);
child->set_child_index(i);
child->set_parent(this);

child->construct_children();
}
} else {
leaf = true;
}
}

void PQuad::construct_vertices(std::vector<glm::vec3> *vertices, std::vector<Color3> *colors)  {
vertices->reserve(QUAD_WIDTH * QUAD_HEIGHT);

for (int y = 0; y < QUAD_HEIGHT; y++)  {
for (int x = 0; x < QUAD_WIDTH; x++)  {
switch (face_direction)  {
case YIncreasing:
vertices->emplace_back(glm::vec3(position.x + x * element_width, QUAD_HEIGHT - 1, -(position.y + y * element_width)));
break;
case YDecreasing:
vertices->emplace_back(glm::vec3(position.x + x * element_width, 0, -(position.y + y * element_width)));
break;
case XIncreasing:
vertices->emplace_back(glm::vec3(QUAD_WIDTH - 1, position.y + y * element_width, -(position.x + x * element_width)));
break;
case XDecreasing:
vertices->emplace_back(glm::vec3(0, position.y + y * element_width, -(position.x + x * element_width)));
break;
case ZIncreasing:
vertices->emplace_back(glm::vec3(position.x + x * element_width, position.y + y * element_width, 0));
break;
case ZDecreasing:
vertices->emplace_back(glm::vec3(position.x + x * element_width, position.y + y * element_width, -(QUAD_WIDTH - 1)));
break;
}

// Position the bottom, right, front vertex of the cube from being (0,0,0) to (-16, -16, 16)
(*vertices)[vertices->size() - 1] -= glm::vec3(QUAD_WIDTH / 2.0f, QUAD_WIDTH  / 2.0f, -(QUAD_WIDTH / 2.0f));

colors->emplace_back(Color3(255.0f, 255.0f, 255.0f, false));
}
}

switch (face_direction)  {
case YIncreasing:
this->centre = glm::vec3(position.x + QUAD_WIDTH / 2.0f, QUAD_HEIGHT - 1, -(position.y + QUAD_HEIGHT / 2.0f));
break;
case YDecreasing:
this->centre = glm::vec3(position.x + QUAD_WIDTH / 2.0f, 0, -(position.y + QUAD_HEIGHT / 2));
break;
case XIncreasing:
this->centre = glm::vec3(QUAD_WIDTH - 1, position.y + QUAD_HEIGHT / 2.0f, -(position.x + QUAD_WIDTH / 2.0f));
break;
case XDecreasing:
this->centre = glm::vec3(0, position.y + QUAD_HEIGHT / 2.0f, -(position.x + QUAD_WIDTH / 2.0f));
break;
case ZIncreasing:
this->centre = glm::vec3(position.x + QUAD_WIDTH / 2.0f, position.y + QUAD_HEIGHT / 2.0f, 0);
break;
case ZDecreasing:
this->centre = glm::vec3(position.x + QUAD_WIDTH / 2.0f, position.y + QUAD_HEIGHT / 2.0f, -(QUAD_HEIGHT - 1));
break;
}

this->centre -= glm::vec3(QUAD_WIDTH / 2.0f, QUAD_WIDTH  / 2.0f, -(QUAD_WIDTH / 2.0f));
}

void PQuad::construct_elements(std::vector<GLushort> *elements)  {
int index = 0;

elements->reserve((QUAD_WIDTH - 1) * (QUAD_HEIGHT - 1) * 6);

for (int y = 0; y < QUAD_HEIGHT - 1; y++)  {
for (int x = 0; x < QUAD_WIDTH - 1; x++)  {
GLushort bottom_left = x + y * QUAD_WIDTH;
GLushort bottom_right = (x + 1) + y * QUAD_WIDTH;
GLushort top_left = x + (y + 1) * QUAD_WIDTH;
GLushort top_right = (x + 1) + (y + 1) * QUAD_WIDTH;

elements->emplace_back(top_left);
elements->emplace_back(bottom_right);
elements->emplace_back(bottom_left);

elements->emplace_back(top_left);
elements->emplace_back(top_right);
elements->emplace_back(bottom_right);
}
}
}

void PQuad::construct_normals(std::vector<glm::vec3> *vertices, std::vector<GLushort> *elements, std::vector<glm::vec3> *normals)  {
normals->reserve(QUAD_WIDTH * QUAD_HEIGHT);

for (int i = 0; i < elements->size() / 3; i++)  {
int index1 = elements->at(i * 3);
int index2 = elements->at(i * 3 + 1);
int index3 = elements->at(i * 3 + 2);

glm::vec3 side1 = vertices->at(index1) - vertices->at(index3);
glm::vec3 side2 = vertices->at(index1) - vertices->at(index2);
glm::vec3 normal = glm::cross(side1, side2);
normal = glm::normalize(normal);

normals->emplace_back(normal);
normals->emplace_back(normal);
normals->emplace_back(normal);
}
}

void PQuad::spherise(std::vector<glm::vec3> *vertices, std::vector<glm::vec3> *normals)  {
for (int i = 0; i < QUAD_WIDTH * QUAD_HEIGHT; i++)  {
glm::vec3 normal = glm::normalize(vertices->at(i) - planet_centre);

(*vertices)[i] = (float)(radius) * normal;
}

glm::vec3 normal = glm::normalize(centre - planet_centre);

centre = normal * (float)(radius);

this->spherised = true;
}

void PQuad::construct_buffers(std::vector<glm::vec3> *vertices, std::vector<Color3> *colors, std::vector<GLushort> *elements, std::vector<glm::vec3> *normals)  {
glGenBuffers(1, &vbo_vertices);
glBindBuffer(GL_ARRAY_BUFFER, vbo_vertices);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * vertices->size(), &((*vertices)[0]), GL_STATIC_DRAW);

glGenBuffers(1, &vbo_colors);
glBindBuffer(GL_ARRAY_BUFFER, vbo_colors);
glBufferData(GL_ARRAY_BUFFER, sizeof(Color3) * colors->size(), &((*colors)[0]), GL_STATIC_DRAW);

glGenBuffers(1, &vbo_normals);
glBindBuffer(GL_ARRAY_BUFFER, vbo_normals);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * normals->size(), &((*normals)[0]), GL_STATIC_DRAW);

glGenBuffers(1, &ibo_elements);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_elements);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort) * elements->size(), &((*elements)[0]), GL_STATIC_DRAW);
}

float distance3(glm::vec3 v1, glm::vec3 v2)  {
return sqrt(pow(abs(v1.x - v2.x), 2) + pow(abs(v1.y - v2.y), 2) + pow(abs(v1.z - v2.z), 2));
}

bool PQuad::should_draw(glm::vec3 player_position)  {
float distance = distance3(player_position, centre);

if (distance < tree[depth])  {
return true;
}

return false;
}

-1

Решение

Синий экран смерти просто невозможно будет достать из обычной пользовательской космической программы … независимо от того, что вы делаете.

Однако, к сожалению, легко столкнуться с подобной ошибкой системного уровня при написании программного обеспечения, которое интенсивно взаимодействует с драйверами устройств, потому что они также являются программными и не свободны от ошибок (а ошибка в драйвере устройства может разрушить всю систему при BSOD).

Смысл в том, что вы делаете какой-то вызов OpenGL с неправильными параметрами, и что драйвер вашей видеокарты имеет ошибку, и вместо того, чтобы обнаружить проблему и перенастроить код ошибки, он просто отключает компьютер.

Вы можете попытаться использовать журнал операций, записывая в файл каждый шаг, чтобы после получения BSOD и перезагрузки вы могли проверить, какая последняя команда была записана в файл. Обратите внимание, что вы должны открыть файл в приложении, написать строку журнала и затем закрыть файл. Даже это не дает вам 100% гарантии, что содержимое файла действительно будет записано на диск, когда вы получите BSOD, но IMO в этом случае вероятность должна быть высокой. Лучшей альтернативой будет просто отправка сообщений журнала через последовательную линию или использование сети на другой компьютер.

Это может быть трудной проблемой для отслеживания и решения.

Другим вариантом будет использование другой реализации OpenGL (например, Mesa). Может быть, с другой реализацией вызовы проверяются лучше, и вы можете определить, что это за вызов с неправильными параметрами.

Возможно даже, что ваш код просто вызывает ошибку в видеодрайвере, и ваш код ничего не делает неправильно. Это должно быть вашим прошлой думал однако.

6

Другие решения

На самом деле ответ довольно прост. Что-то действительно не так с отладчиком в Code :: Blocks в Windows. Я видел это синий экран нескольких систем. Переключитесь на использование операторов вывода или другой IDE.

0