-1

私は、惑星のクワッド ツリー構造を書いています。これは、クワッドから遠く離れて受容的に近づくと、詳細が減少したり増加したりします。ただし、非常に深刻で迷惑なバグに遭遇しています。

クワッド ツリーのサイズ (QUAD_WIDTH と QUAD_HEIGHT) を決定する 2 つのプリプロセッサ定義定数があり、値を 32 以外 (たとえば 16 または 64) に変更すると、ブルー スクリーンが表示されます。IDE として code::blocks を使用しています。もう 1 つ: 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;
}
4

2 に答える 2

6

ブルー スクリーン オブ デスは、通常のユーザー スペース プログラムから到達することは不可能なはずです...何をしても。

しかし残念なことに、デバイス ドライバーと頻繁にやり取りするソフトウェアを作成するときに、この種のシステム レベルのバグに遭遇するのは簡単です。これは、デバイス ドライバーもソフトウェアであり、バグがないわけではないためです (デバイス ドライバーのバグは、システム全体を停止させる可能性があります)。 BSOD)。

これは、間違ったパラメーターで OpenGL を呼び出していること、およびビデオ カードのドライバーにバグがあり、問題を検出して失敗コードを返す代わりに、マシンをダウンさせるだけであることを意味します。

操作のログを使用して、各ステップごとにファイルに書き込むことを試みることができるため、BSOD を取得して再起動した後、ファイルに最後に書き込まれたコマンドを確認できます。appendでファイルを開き、ログ行を書き込んでからファイルを閉じる必要があることに注意してください。これでも、BSOD を取得したときにファイルの内容が実際にディスクに書き込まれることを 100% 保証するわけではありませんが、この場合の IMO の可能性は高いはずです。より良い代替手段は、シリアル回線を介してログメッセージを送信するか、ネットワークを使用して別のコンピューターに送信することです。

追跡して解決するのが難しい問題かもしれません。

別のオプションは、別の OpenGL 実装 (Mesa など) を使用することです。別の実装を使用すると、呼び出しがより適切にチェックされ、間違ったパラメーターを使用した呼び出しを見つけることができます。

コードがビデオ ドライバーのバグを引き起こしているだけで、コードが何も悪いことをしていない可能性さえあります。ただし、これはあなたの最後の考えです。

于 2012-09-09T05:44:26.153 に答える
0

実際、答えは非常に簡単です。WindowsのCode::Blocksのデバッガーに本当に問題があります。私はそれが複数のシステムのブルースクリーンを見てきました。出力ステートメントまたは別のIDEの使用に切り替えます。

于 2012-09-09T15:21:25.927 に答える