Создание массивов вершин для OpenGL

Я хочу использовать некоторые удобные методы для создания массивов вершин и цветов для использования в объектах. Из того, что я видел при создании массивов, это пример того, что я сейчас использую:

GLfloat * CDMeshVertexesCreateRectangle(CGFloat height, CGFloat width) {

// Requires the rendering method GL_TRIANGLE_FAN
GLfloat *squareVertexes = (GLfloat *) malloc(8 * sizeof(GLfloat));
squareVertexes[0] = -(width / 2);
squareVertexes[1] = -(height / 2);
squareVertexes[2] = -(width / 2);
squareVertexes[3] = (height / 2);
squareVertexes[4] = (width / 2);
squareVertexes[5] = (height / 2);
squareVertexes[6] = (width / 2);
squareVertexes[7] = -(height / 2);

return squareVertexes;

}

Но когда я использую его для чего-то вроде этого:

GLuint memoryPointer = 0;
    GLuint colourMemoryPointer = 0;

    GLfloat *vertexes = CDMeshVertexesCreateRectangle(200, 200);
    GLfloat *colors = CDMeshColorsCreateGrey(1.0, 4);

    // Allocate the buffer
    glGenBuffers(1, &memoryPointer);
    // Bind the buffer object (tell OpenGL what to use)
    glBindBuffer(GL_ARRAY_BUFFER, memoryPointer);

    // Allocate space for the VBO
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertexes), vertexes, GL_STATIC_DRAW);


    // Allocate the buffer
    glGenBuffers(1, &colourMemoryPointer);
    // Bind the buffer object (tell OpenGL what to use)
    glBindBuffer(GL_ARRAY_BUFFER, colourMemoryPointer);

    // Allocate space for the VBO
    glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);

    glEnableClientState(GL_VERTEX_ARRAY); // Activate vertex coordinates array
    glEnableClientState(GL_COLOR_ARRAY);

    glBindBuffer(GL_ARRAY_BUFFER, memoryPointer);
    glVertexPointer(2, GL_FLOAT, 0, 0);   

    glBindBuffer(GL_ARRAY_BUFFER, colourMemoryPointer);
    glColorPointer(4, GL_FLOAT, 0, 0);

    //render
    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

    glDisableClientState(GL_VERTEX_ARRAY); // Deactivate vertex coordinates array
    glDisableClientState(GL_COLOR_ARRAY);

    free(vertexes);
    free(colors);

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

GLfloat Square[8] = {
-100, -100,
-100, 100,
100, 100,
100, -100
};

Кто-нибудь знает, где я ошибаюсь?


person Croc    schedule 14.07.2011    source источник
comment
sizeof(vertexes) возвращает размер указателя (скорее всего, 4), а не размер массива. Отдельно нужно следить за размером. Хотя не уверен, что это причина ваших проблем.   -  person    schedule 14.07.2011


Ответы (1)


У вас есть две проблемы в вашем коде. Сначала этот узор:

glBufferData(GL_ARRAY_BUFFER, sizeof(vertexes), vertexes, GL_STATIC_DRAW);

sizeof(vertexes) оценивает размер переменной-указателя, а не размер буфера. Ошибка новичка в C/C++, мы все так делали. Необходимо следить за размером самостоятельно. Итак, сделайте это так:

int allocate_a_buffer(CGFloat height, CGFloat width, GLfloat **buffer, size_t *buffer_size) 
{
// Requires the rendering method GL_TRIANGLE_FAN
    return  ( *buffer = (GLfloat *) malloc( *buffer_size = ( <xxx> * sizeof(GLfloat)) ) ) != 0;
}

а также

GLfloat *vertices;
size_t vertices_size;

if( !allocate_a_buffer(..., &vertices, &vertices_size) ) {
    error();
    return;
}
glBufferData(GL_ARRAY_BUFFER, vertices_size, vertices, GL_STATIC_DRAW);

Если вы используете C++, просто используйте std::vector, переданный по ссылке:

void initialize_buffer(..., std::vector<GLfloat> &buffer)
{
    buffer.resize(...);
    for(int n = ...; ...; ...) {
         buffer[n] = ...;
    }
}

а также

std::vector<GLfloat> vertices;
initialize_buffer(..., vertices);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(vertices[0]), &vertices[0], GL_STATIC_DRAW);

гораздо меньше пуха.


Другая проблема заключается в том, что этот код, по-видимому, вызывается функцией рисования. Весь смысл буферных объектов в том, что вы инициализируете их только один раз, а затем только связываете и рисуете из них в подпрограмме отображения. Таким образом, glDrawArrays относится к другой функции, чем остальная часть этого кода, а именно к процедуре отображения, в то время как остальная часть относится к коду загрузки данных и управления данными сцены.

person datenwolf    schedule 14.07.2011
comment
Большое спасибо за ваш ответ, все сработало, кроме того, где вы пытались присвоить значение vertex_size, что сработало, когда я добавил указатель. Кроме того, код OpenGL представлен в качестве демонстрации, я только связываю и рисую буферы вершин в подпрограмме отображения. - person Croc; 15.07.2011
comment
@Croc: я думаю, вы имеете в виду разыменование. Да этого не хватало. - person datenwolf; 15.07.2011