Quake 3 BSP渲染器绘制随机顶点

时间:2017-09-11 00:02:59

标签: c++ opengl

最近我一直在用OpenGL编写游戏引擎并提出问题。当我生成我的BSP文件(Quake 3)时,它会生成非常奇怪的顶点!我检查了顶点向量,下面是它包含的截图(它重复自己)

What vertex vector contains (vertexes)

我检查了glGetError,它没有返回任何内容(零)!我真的很难过,我不知道该怎么做。

这是我的代码:

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/vec3.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <vector>   
#include "map.h"
#include <fstream>
#include <memory>
#include "game_manager.h"

std::vector<BSPVerts> vertexes;

bool KikoBSP::load_map(std::string file_name)
{
    this->file.open(file_name.c_str(), std::ios::in | std::ios::binary);

    if (this->file.is_open())
    {
        this->file.read(reinterpret_cast<char*>(&this->header), sizeof(this->header));

        BSPEntities* ents = new BSPEntities;
        ents->ents_array = new char[this->header.lumps[BSPLUMPS::ENTITIES].length];

        this->num_textures = this->header.lumps[BSPLUMPS::TEXTURES].length / sizeof(BSPTexture);
        this->num_planes = this->header.lumps[BSPLUMPS::PLANES].length / sizeof(BSPPlane);
        this->num_textures = this->header.lumps[BSPLUMPS::TEXTURES].length / sizeof(BSPTexture);
        this->num_nodes = this->header.lumps[BSPLUMPS::NODES].length / sizeof(BSPNode);
        this->num_leafs = this->header.lumps[BSPLUMPS::LEAFS].length / sizeof(BSPLeaf);
        this->num_leaf_faces = this->header.lumps[BSPLUMPS::LEAF_FACES].length / sizeof(BSPLeafFace);
        this->num_leaf_brushes = this->header.lumps[BSPLUMPS::LEAF_BRUSHES].length / sizeof(BSPLeafBrush);
        this->num_models = this->header.lumps[BSPLUMPS::MODELS].length / sizeof(BSPModel);
        this->num_brushes = this->header.lumps[BSPLUMPS::BRUSHES].length / sizeof(BSPBrush);
        this->num_brush_sides = this->header.lumps[BSPLUMPS::BRUSHSIDES].length / sizeof(BSPBrushSides);
        this->num_vertexes = this->header.lumps[BSPLUMPS::VERTEXES].length / sizeof(BSPVerts);
        this->num_meshverts = this->header.lumps[BSPLUMPS::MESHVERTS].length / sizeof(BSPMeshVerts);
        this->num_effects = this->header.lumps[BSPLUMPS::EFFECTS].length / sizeof(BSPEffects);
        this->num_faces = this->header.lumps[BSPLUMPS::FACES].length / sizeof(BSPFaces);

        for (int32_t x = 0; x < this->num_vertexes; x++)
        {
            vertexes.push_back(*reinterpret_cast<BSPVerts*>(&x));
        }

        for (int32_t x = 0; x < this->num_textures; x++)
        {
            this->textures.push_back(*reinterpret_cast<BSPTexture*>(&x));
        }

        for (int32_t x = 0; x < this->num_meshverts; x++)
        {
            this->mesh_verts.push_back(*reinterpret_cast<BSPMeshVerts*>(&x));
        }

        for (int32_t x = 0; x < this->num_planes; x++)
        {
            this->planes.push_back(*reinterpret_cast<BSPPlane*>(&x));
        }

        for (int32_t x = 0; x < this->num_nodes; x++)
        {
            this->nodes.push_back(*reinterpret_cast<BSPNode*>(&x));
        }

        for (int32_t x = 0; x < this->num_leafs; x++)
        {
            this->leaf.push_back(*reinterpret_cast<BSPLeaf*>(&x));
        }

        for (int32_t x = 0; x < this->num_faces; x++)
        {
            this->faces.push_back(*reinterpret_cast<BSPFaces*>(&x));
        }

        for (int32_t x = 0; x < this->num_leaf_faces; x++)
        {
            this->leaf_faces.push_back(*reinterpret_cast<BSPLeafFace*>(&x));
        }

        for (int32_t x = 0; x < this->num_leaf_brushes; x++)
        {
            this->leaf_brush.push_back(*reinterpret_cast<BSPLeafBrush*>(&x));
        }

        for (int32_t x = 0; x < this->num_models; x++)
        {
            this->model.push_back(*reinterpret_cast<BSPModel*>(&x));
        }

        for (int32_t x = 0; x < this->num_brushes; x++)
        {
            this->brushes.push_back(*reinterpret_cast<BSPBrush*>(&x));
        }

        for (int32_t x = 0; x < this->num_brush_sides; x++)
        {
            this->brush_sides.push_back(*reinterpret_cast<BSPBrushSides*>(&x));
        }

        for (int32_t x = 0; x < this->num_effects; x++)
        {
            this->effect.push_back(*reinterpret_cast<BSPEffects*>(&x));
        }

        this->file.seekg(this->header.lumps[BSPLUMPS::ENTITIES].offset);
        this->file.read(reinterpret_cast<char*>(ents->ents_array), this->header.lumps[BSPLUMPS::ENTITIES].length); 

        this->file.seekg(this->header.lumps[BSPLUMPS::TEXTURES].offset);
        this->file.read(reinterpret_cast<char*>(textures.data()), this->header.lumps[BSPLUMPS::TEXTURES].length);

        this->file.seekg(this->header.lumps[BSPLUMPS::PLANES].offset);
        this->file.read(reinterpret_cast<char*>(this->planes.data()), this->header.lumps[BSPLUMPS::PLANES].length);

        this->file.seekg(this->header.lumps[BSPLUMPS::NODES].offset);
        this->file.read(reinterpret_cast<char*>(this->nodes.data()), this->header.lumps[BSPLUMPS::NODES].length);

        this->file.seekg(this->header.lumps[BSPLUMPS::LEAFS].offset);
        this->file.read(reinterpret_cast<char*>(this->leaf.data()), this->header.lumps[BSPLUMPS::LEAFS].length);

        this->file.seekg(this->header.lumps[BSPLUMPS::LEAF_FACES].offset);
        this->file.read(reinterpret_cast<char*>(this->leaf_faces.data()), this->header.lumps[BSPLUMPS::LEAF_FACES].length);

        this->file.seekg(this->header.lumps[BSPLUMPS::LEAF_BRUSHES].offset);
        this->file.read(reinterpret_cast<char*>(this->leaf_brush.data()), this->header.lumps[BSPLUMPS::LEAF_BRUSHES].length);

        this->file.seekg(this->header.lumps[BSPLUMPS::MODELS].offset);
        this->file.read(reinterpret_cast<char*>(this->model.data()), this->header.lumps[BSPLUMPS::MODELS].length);

        this->file.seekg(this->header.lumps[BSPLUMPS::BRUSHES].offset);
        this->file.read(reinterpret_cast<char*>(this->brushes.data()), this->header.lumps[BSPLUMPS::BRUSHES].length);

        this->file.seekg(this->header.lumps[BSPLUMPS::BRUSHSIDES].offset);
        this->file.read(reinterpret_cast<char*>(this->brush_sides.data()), this->header.lumps[BSPLUMPS::BRUSHSIDES].length);

        this->file.seekg(this->header.lumps[BSPLUMPS::VERTEXES].offset);

        for (int32_t x = 0; x < this->num_vertexes; x++)
        {
            this->file.read(reinterpret_cast<char*>(&vertexes.data()[x]), this->header.lumps[BSPLUMPS::VERTEXES].length);
        }

        this->file.seekg(this->header.lumps[BSPLUMPS::MESHVERTS].offset);
        this->file.read(reinterpret_cast<char*>(this->mesh_verts.data()), this->header.lumps[BSPLUMPS::MESHVERTS].length);

        this->file.seekg(this->header.lumps[BSPLUMPS::EFFECTS].offset);
        this->file.read(reinterpret_cast<char*>(this->effect.data()), this->header.lumps[BSPLUMPS::EFFECTS].length);

        this->file.seekg(this->header.lumps[BSPLUMPS::FACES].offset);
        this->file.read(reinterpret_cast<char*>(this->faces.data()), this->header.lumps[BSPLUMPS::FACES].length);

        std::printf("BSP VERSION: '%s'\n", this->header.magic);

        if (std::strncmp(this->header.magic, "IBSP", 4) == 0)
        {
            std::printf("SUCCESS: VALID BSP FORMAT!\n");
        }
        else
        {
            std::printf("ERROR: INVALID BSP FORMAT!\n");

            return false;
        }

        this->shader.load_shader("shaders/bsp.vs", "shaders/bsp.fs");

        /* heres where I try to store the data for the faces vertices */
        for (int32_t x = 0; x < this->num_faces; x++)
        {
            BSPFaces& face = this->faces[x];

            for (int32_t vertices = 0; vertices < this->num_vertexes; vertices++) 
            {
                BSPVerts* vert = reinterpret_cast<BSPVerts*>(&vertexes[x]);

                this->vertices_vector.push_back(vert[x].position.x);
                this->vertices_vector.push_back(vert[x].position.y);
                this->vertices_vector.push_back(vert[x].position.z);

                this->colors.push_back(vert[x].position.x / 0xFF);
                this->colors.push_back(vert[x].position.y / 0xFF);
                this->colors.push_back(vert[x].position.z / 0xFF);

                this->indices.push_back(vert[x].position.x);
                this->indices.push_back(vert[x].position.y);
                this->indices.push_back(vert[x].position.z);
            }
        }

        glGenVertexArrays(1, &this->vao);

        glBindVertexArray(this->vao);

        glGenBuffers(1, &this->vbo);
        glBindBuffer(GL_ARRAY_BUFFER, vbo);
        glBufferData(GL_ARRAY_BUFFER, this->vertices_vector.size() * sizeof(float), &this->vertices_vector.front(), GL_STATIC_DRAW);

        glGenBuffers(1, &this->color_vbo);
        glBindBuffer(GL_ARRAY_BUFFER, this->color_vbo);
        glBufferData(GL_ARRAY_BUFFER, this->colors.size() * sizeof(float), &this->colors.front(), GL_STATIC_DRAW);

        this->coord3d = glGetAttribLocation(this->shader.program, "coord3d");
        this->mvp = glGetUniformLocation(this->shader.program, "mvp");
        this->attrib_color = glGetAttribLocation(this->shader.program, "v_color");

        glBindBuffer(GL_ARRAY_BUFFER, this->vbo);
        glVertexAttribPointer(this->coord3d, // attribute
            3,                 // number of elements per vertex, here (R,G,B)
            GL_FLOAT,          // the currentBlock of each element
            GL_FALSE,          // take our values as-is
            0,                 // no extra data between each position
            nullptr               // offset of first element
        );

        glBindBuffer(GL_ARRAY_BUFFER, this->color_vbo);
        glVertexAttribPointer(this->attrib_color,
            3,
            GL_FLOAT,
            GL_FALSE,
            0,
            nullptr
        );

        glBindVertexArray(0);

        glVertexAttrib3fv(this->attrib_color, reinterpret_cast<float*>(this->colors.data()));

        return true;
    }
    else
    {
        std::printf("ERROR: COULDN'T OPEN FILE!\n");

        return false;
    }

    return false;
}

void KikoBSP::render(glm::vec3 position)
{
    glBindVertexArray(this->vao);
    glEnableVertexAttribArray(this->coord3d);
    glEnableVertexAttribArray(this->attrib_color);

    glm::mat4 model = glm::translate(glm::mat4(1.0), glm::vec3(position.x, position.y, position.z));
    glm::mat4 mvp = game_manager->projection * game_manager->view * model;
    glUniformMatrix4fv(this->mvp, 1, GL_FALSE, glm::value_ptr(mvp));

    glLineWidth(3.0);
    glDrawArrays(GL_LINES, 0, this->vertices_vector.size());

    glDisableVertexAttribArray(this->coord3d);
    glDisableVertexAttribArray(this->attrib_color);
    glBindVertexArray(0);
}

void KikoBSP::cleanup_map()
{
    /* delete[] textures;
    delete[] planes;
    delete[] this->leafs;
    delete[] this->nodes;
    delete[] this->leaf_this->faces;
    delete[] this->models;
    delete[] this->brushes;
    delete[] this->brush_sides;
    delete[] this->vertexes;
    delete[] this->mesh_verts;
    delete[] this->effects;
    delete[] this->this->faces;
    (use maybe later?) */
    this->file.close();
}

代码中没有错误,它只是绘制了这个:

What it draws

这显然不是地图!

另外,如果您需要,请继承我的头文件:

#pragma once
#pragma pack(2)

#include <iostream>
#include <cstdint>
#include <string>
#include <vector>
#include <glm/vec3.hpp>
#include <fstream>
#include "shader.h"
#include <memory>
#include <array>

#define FACE_POLYGON 1

enum BSPLUMPS
{
    ENTITIES,
    TEXTURES,
    PLANES,
    NODES,
    LEAFS,
    LEAF_FACES,
    LEAF_BRUSHES,
    MODELS,
    BRUSHES,
    BRUSHSIDES,
    VERTEXES,
    MESHVERTS,
    EFFECTS,
    FACES,
    LIGHTMAPS,
    LIGHTVOLS,
    VISDATA,
    MAX_LUMPS
};

struct BSPLump
{
    int32_t offset; /* offset to start of lump */
    int32_t length; /* length of lump, always multiple of 4 */
};

struct BSPHeader
{
    char magic[4]; /* ALWAYS IBSP */
    int32_t version; /* 0x2E for Quake 3 */
    BSPLump lumps[BSPLUMPS::MAX_LUMPS]; /* direntries */
};

struct BSPEntities
{
    char* ents_array;
};

struct BSPTexture
{
    char name[64];
    int32_t flags;
    int32_t contents;
};

struct BSPPlane
{
    glm::vec3 normal;
    float distance;
};

struct BSPNode
{
    int32_t plane;
    glm::ivec2 children;
    glm::ivec3 mins;
    glm::ivec3 maxs;
};

struct BSPLeaf
{
    int32_t cluster;
    int32_t area;
    glm::ivec3 mins;
    glm::ivec3 maxs;
    int32_t leafface;
    int32_t num_leaffaces;
    int32_t leaf_brush;
    int32_t num_leaf_brushes;
};

struct BSPLeafFace
{
    int32_t face;
};

struct BSPLeafBrush
{
    int32_t brush;
};

struct BSPModel
{
    glm::fvec3 mins;
    glm::fvec3 maxs;
    int32_t face;
    int32_t num_faces;
    int32_t brush;
    int32_t num_brushes;
};

struct BSPBrush
{
    int32_t brush_side;
    int32_t num_brush_sides;
    int32_t texture;
};

struct BSPBrushSides
{
    int32_t plane;
    int32_t texture;
};

struct BSPVerts
{
    glm::vec3 position;
    glm::vec2 tex_coord; /* same as float tex_coord[2][2] */
    glm::vec2 lm_coord; /* same as float tex_coord[2][2] */
    glm::vec3 normal;
    char color[4];
};

struct BSPMeshVerts
{
    int32_t offset;
};

struct BSPEffects
{
    char name[64];
    int32_t brush;
    int32_t unk; /* unknown */
};

struct BSPFaces
{
    int32_t texture;
    int32_t effect;
    int32_t type;
    int32_t vertex;
    int32_t num_vertexes;
    int32_t meshvert; /* start */
    int32_t num_of_meshverts;
    int32_t lm_index;
    glm::ivec2 lm_start;
    glm::ivec2 lm_size;
    glm::vec3 lm_origin;
    float lm_vecs[2][3];
    glm::fvec3 normal;
    glm::ivec2 size;
};

class KikoBSP
{
public:
    bool load_map(std::string);
    void render(glm::vec3);
    void draw_level();
    int32_t get_max();
    int32_t get_min();
    void get_vert();

    void cleanup_map();

    Shader shader;
    BSPHeader header;

    int32_t num_vertexes;

private:
    std::ifstream file;
    uint32_t vbo;
    uint32_t vao;
    uint32_t color_vbo;
    uint32_t ebo;

    int32_t coord3d;
    int32_t mvp;
    int32_t attrib_color;
    BSPFaces* cur_face;

    std::vector<float> vertices_vector;
    std::vector<float> colors;
    std::vector<float> indices;
    std::vector<BSPFaces> faces;
    std::vector<BSPTexture> textures;
    std::vector<BSPPlane> planes;
    std::vector<BSPNode> nodes;
    std::vector<BSPMeshVerts> mesh_verts;
    std::vector<BSPLeaf> leaf;
    std::vector<BSPLeafFace> leaf_faces;
    std::vector<BSPLeafBrush> leaf_brush;
    std::vector<BSPModel> model;
    std::vector<BSPBrush> brushes;
    std::vector<BSPBrushSides> brush_sides;
    std::vector<BSPEffects> effect;

    int32_t num_textures;
    int32_t num_planes;
    int32_t num_nodes;
    int32_t num_leafs;
    int32_t num_leaf_faces;
    int32_t num_leaf_brushes;
    int32_t num_models;
    int32_t num_brushes;
    int32_t num_brush_sides;
    int32_t num_meshverts;
    int32_t num_effects;
    int32_t num_faces;
    int32_t num_lightmaps;
    int32_t num_lightvols;
};

我认为问题是指数或顶点。我认为问题在于我如何存储顶点的数据。它真的很麻烦。

谢谢!所有帮助赞赏! :)

1 个答案:

答案 0 :(得分:1)

每当有人说'#34;代码中没有错误&#34;,你知道某些事情已经非常错误了!

例如,这应该做什么?

for (int32_t x = 0; x < this->num_vertexes; x++)
{
    vertexes.push_back(*reinterpret_cast<BSPVerts*>(&x));
}

看起来它在这里调用了一些未定义的行为。如果您只想填充数组,请执行以下操作:

vertexes.resize(num_vertices);

其次,从文件中读取顶点的代码看起来像是有逻辑错误:

for (int32_t x = 0; x < this->num_vertexes; x++)
{
    this->file.read(reinterpret_cast<char*>(&vertexes.data()[x]), this->header.lumps[BSPLUMPS::VERTEXES].length);
}

看起来它会读取每个顶点的整个顶点块,可能会导致奇怪的行为。你可能只是想这样做:

file.read(reinterpret_cast<char*>(vertexes.data()), header.lumps[BSPLUMPS::VERTEXES].length);

另外,关于您的代码与您的问题无关的说明:在任何地方使用this->会损害可读性并且不会对代码添加任何内容,请将其删除。

前一段时间我做了同样的BSP渲染器,我无法记住我留下的状态,但是你可以查看代码here