Как я могу создать экземпляр массива внутри базового класса из производного класса? - PullRequest
0 голосов
/ 03 сентября 2018

У меня есть базовый класс, который содержит неназначенный указатель _vertices, и я хочу заполнить его из конструктора производного класса:

class GameRenderable {  
    bool _indexed;
    int _vertSize;
    int _idxSize;

    unsigned int VAO, VBO, EBO;
    unsigned int _texture0;

protected:
    float *_vertices;
    unsigned int *_indices;

public:
    GameRenderable(GameRenderableMode grm);
    ~GameRenderable();

    void Render();

protected:
    void SetupBuffer(int, int);
};

void GameRenderable::SetupBuffer(int vs, int is) {
    _indexed = false;

    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);

    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, vs, _vertices, GL_STATIC_DRAW);

    // position attribute
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);
    // texture coord attribute
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
    glEnableVertexAttribArray(1);

    _idxSize = is;
    _vertSize = vs;
}

void GameRenderable::Render() {
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, _texture0);

    glBindVertexArray(VAO);

    glm::mat4 model = glm::mat4(1.0f);
    GetShader()->setMat4("model", model);

    glDrawArrays(GL_TRIANGLES, 0, _vertSize);
}

Производные классы:

class Cube : public GameRenderable {
public:
    Cube();
    ~Cube();
};

Cube::Cube():GameRenderable(GameRenderableMode::_3D) {
    /* Cube ASCII
          E--------F    A   -0.5f,  0.5f, -0.5f
         /|       /|    B    0.5f,  0.5f, -0.5f
        A--------B |    C   -0.5f, -0.5f, -0.5f
        | |      | |    D    0.5f, -0.5f, -0.5f
        | G------|-H    E   -0.5f,  0.5f,  0.5f
        |/       |/     F    0.5f,  0.5f,  0.5f
        C--------D      G   -0.5f, -0.5f,  0.5f
                        H    0.5f, -0.5f,  0.5f
    */
    float vertices[] = {
        -0.5f, -0.5f, -0.5f,  0.0f, 0.0f,
         0.5f, -0.5f, -0.5f,  1.0f, 0.0f,
         0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
         0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
        -0.5f,  0.5f, -0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, 0.0f,

        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
         0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
         0.5f,  0.5f,  0.5f,  1.0f, 1.0f,
         0.5f,  0.5f,  0.5f,  1.0f, 1.0f,
        -0.5f,  0.5f,  0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,

        -0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
        -0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
        -0.5f,  0.5f,  0.5f,  1.0f, 0.0f,

         0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
         0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
         0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
         0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
         0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
         0.5f,  0.5f,  0.5f,  1.0f, 0.0f,

        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
         0.5f, -0.5f, -0.5f,  1.0f, 1.0f,
         0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
         0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,

        -0.5f,  0.5f, -0.5f,  0.0f, 1.0f,
         0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
         0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
         0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
        -0.5f,  0.5f,  0.5f,  0.0f, 0.0f,
        -0.5f,  0.5f, -0.5f,  0.0f, 1.0f
    };

    _vertices = new float[sizeof(vertices)];
    memcpy_s(_vertices, sizeof(vertices), vertices, sizeof(float));

    SetupBuffer(36, 0);
    SetupTexture("container.jpg");
}

Cube::~Cube() {
}

Когда я вызываю SetupBuffer(), массив, переданный openGL, всегда представляет собой только 1 элемент, и ничего не рисуется. Если я помещу код SetupBuffer() прямо в конструктор, он будет работать.

1 Ответ

0 голосов
/ 03 сентября 2018

Проблемы с буфером GL

Оператор sizeof( type ) возвращает размер в байтах , например, код:

std::cout << sizeof(float) << std::endl;

напечатает вывод: 4

так в следующей строке:

_vertices = new float[sizeof(vertices)];

Вы выделяете в 4 раза больше данных, необходимых для хранения массива vertices. Это должно быть что-то вроде:

_vertices = new float[sizeof(vertices) / sizeof(float)];
//this is more ugly but could also be:
_vertices = (float*)(new char[sizeof(vertices)]);
//that works since an ascii 'char' is 1 byte

функция memcpy_s от MSDN:

Параметры

dest Новый буфер.

destSize Размер буфера назначения, в байтах для memcpy_s и широких символов (wchar_t) для wmemcpy_s.

src Буфер для копирования.

count Количество символов для копирования.

поэтому вызов должен быть примерно таким:

memcpy_s(_vertices, sizeof(vertices), vertices, sizeof(vertices));
//although, I would just use the regular 'memcpy':
memcpy(_vertices, vertices, sizeof(vertices));

Ваша функция SetupBuffer принимает параметр vs, который вводится непосредственно в glBufferData, однако glBufferData также принимает размер в байтах:

size

Указывает размер в байтах нового хранилища данных объекта буфера.

, поэтому ввод значения 36 будет недостаточным. Вы хотите найти способ передать значение sizeof(vertices), хотя, поскольку вы знаете шаг каждой вершины (5 операций с плавающей запятой), вы можете изменить вызов на:

glBufferData(GL_ARRAY_BUFFER, vs * 5 * sizeof(float), _vertices, GL_STATIC_DRAW);

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

ООП Вопросы

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

Cube::Cube() : GameRenderable(GameRenderableMode::_3D) {

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...