如何从派生类实例化基类内部的数组?

时间:2018-09-02 21:56:37

标签: c++ arrays inheritance opengl

我有一个包含未分配的指针_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 :(得分:1)

总帐缓冲区问题

sizeof( type )运算符以 bytes 为单位返回大小,例如代码:

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

将打印输出:4

因此在以下行:

_vertices = new float[sizeof(vertices)];

您正在分配存储数组vertices所需的数据量的4倍。应该是这样的:

_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

来自MSDN的功能memcpy_s

  

参数

     

dest   新缓冲区。

     

destSize   目标缓冲区的大小,对于memcpy_s为以字节为单位,对于wmemcpy_s为宽字符(wchar_t)。

     

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类来简化一些代码,但是我认为,解决代码中的误解非常重要你已经写了。

OOP问题

我相当确定上述内容可以解决您的问题。但是,只是要确保构造函数:

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

不会覆盖GameRenderable构造函数,将首先调用GameRenderable构造函数(使用参数_3D),因此请确保GameRenderable构造函数中的代码不会不要破坏任何东西(我看不到)。