Визуализация облака точек Kinect с использованием буфера вершин (VBO) - PullRequest
8 голосов
/ 27 сентября 2011

Я пытаюсь создать динамический визуализатор облака точек. Точки обновляются каждый кадр с помощью датчика Kinect. Для захвата кадров я использую OpenCV и GLUT для отображения. OpenCV API возвращает 640 x 480 (float *) для точек xyz и 640 x 480 (int *) для цветовых данных rgb. Чтобы получить максимальную производительность, я пытаюсь использовать Vertex Buffer Object в потоковом режиме вместо простого Vertex Array. Я могу сделать это с помощью Vertex Array, но в моей реализации VBO ничего не отображается. Я попробовал кучу разных заказов в декларациях, но не могу найти то, что мне не хватает. Может кто-нибудь попытаться указать мне правильное направление? Вот упрощенный код: (Я переписал не ту версию, как ее попросил Кристиан Рау, чтобы вы, ребята, могли понять мои ошибки)

int main()
{
    //Delaring variables, inittiating glut, setting camera and checking the compatibility as http://www.songho.ca/opengl/gl_vbo.html
    glutDisplayFunc(displayCB);
    glutIdleFunc(displayCB); 
    ... 
    //Inittiating the vertex buffers
    if(vboSupported)
    {
        glGenBuffers(1, &vertex_buffer);
        glBindBuffer(GL_ARRAY_BUFFER_ARB, buffer);
        glBufferData(GL_ARRAY_BUFFER_ARB, (sizeof(GLfloat) * 640 * 480 * 3), 0, GL_STREAM_DRAW_ARB);
        glBufferSubData(GL_ARRAY_BUFFER_ARB, 0,  (sizeof(float) * 640 * 480 * 3), point_cloud.points_position); 

        glGenBuffers(2, &color_buffer);
        glBindBuffer(GL_ARRAY_BUFFER_ARB, buffer);
        glBufferData(GL_ARRAY_BUFFER_ARB, (sizeof(GLbyte) * 640 * 480 * 3), 0, GL_STREAM_DRAW_ARB);
        glBufferSubData(GL_ARRAY_BUFFER_ARB, 0,  (sizeof(char) * 640 * 480 * 3), point_cloud.points_color); 
    }
    //glutMainLoop(), cleaning memory, ending main
    ..
}

//Updating the screen
void displayCB()
{
    point_cloud.update();

    // clear buffer
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

    // save the initial ModelView matrix before modifying ModelView matrix
    glPushMatrix();

        glBindBuffer(GL_ARRAY_BUFFER_ARB, color_buffer);
        glBufferSubData(GL_ARRAY_BUFFER_ARB, 0,  (sizeof(char) * 640 * 480 * 3), point_cloud.points_color); 
        glColorPointer(3, GL_UNSIGNED_BYTE, 0, 0);

        glBindBuffer(GL_ARRAY_BUFFER_ARB, vertex_buffer);
        glBufferSubData(GL_ARRAY_BUFFER_ARB, 0,  (sizeof(float) * 640 * 480 * 3), point_cloud.points_position); 
        glVertexPointer(3, GL_FLOAT, 0, 0));

        // enable vertex arrays
        glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_COLOR_ARRAY);

        glDrawArrays(GL_POINT, 0, 640*480);

        glDisableClientState(GL_VERTEX_ARRAY);  // disable vertex arrays
        glDisableClientState(GL_COLOR_ARRAY);

        glBindBuffer(GL_ARRAY_BUFFER_ARB, 0);

    glPopMatrix();

    glutSwapBuffers();
}

1 Ответ

0 голосов
/ 22 ноября 2011

PS: Программа запущена и работает, но я не вижу какого-либо улучшения средней производительности по сравнению с версией Vertex Array.Это нормально?ПРОБЛЕМА БЫЛА РЕШЕНА.Я сделал три изменения:

1 - I though that glGenBuffers first parameter was the number that
would be associated to the buffer, instead, its the number of
buffers that would be allocated. This doesn't matter anyway, because
now I'm using a single buffer and adding all the data to it. Didn't
solved the problem, but was going in the right way.

2 - There are two ways of being able to use OpenGL VBO functions.
First, you can bind the ARB  version functions by yourself OR you
can add glew.h and use glewInit() after starting an OpenGL context.
The second option is a LOT cleaner and I changed my code so I don't
use the ARB versions anymore. Still didn't solved the problem.

3 - Christian Rau asked me for glErrors in the code, so, I wrote it
after each OpenGL operation in displayCB. After glDrawArrays I got
an 0x00500 error, that means there is an invalid enum, so I noticed
I was using GL_POINT as parameter to glDrawArrays, instead of
GL_POINTS, so silly that makes me want to kill myself.

Окончательный код:

//EDIT: Added glew.h as a header and I´m not using the ARB version anymore
#include <glew.h>

    int main()
    {
        //Declaring variables, initiating glut, setting camera and checking the compatibility as http://www.songho.ca/opengl/gl_vbo.html
        glutDisplayFunc(displayCB);
        glutIdleFunc(displayCB); 
        ...

        //EDIT: IS VERY IMPORTANT TO ADD IT AS SOON AS YOU START AN OPENGL CONTEXT.
        initGlew();

        //Inittiating the vertex buffers
        if(vboSupported)
        {
           //EDIT: I was using two buffers, one for color and another for the vertex. I changed the code so I use  a single buffer now.
           //EDIT: Notice that I'm not using the ARB version of the functions anymore.
            glGenBuffers(1, &buffer);
            glBindBuffer(GL_ARRAY_BUFFER_ARB, buffer);
            glBufferData(GL_ARRAY_BUFFER_ARB, (sizeof(GLfloat) * 640 * 480 * 3) + (sizeof(GLbyte) * 640 * 480 * 3), 0, GL_STREAM_DRAW_ARB);
        }
        //glutMainLoop(), cleaning memory, ending main
        ..
    }

    //Updating the screen
    void displayCB()
    {
        point_cloud.update();

        // clear buffer
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

        // save the initial ModelView matrix before modifying ModelView matrix
        glPushMatrix();

            glBindBuffer(GL_ARRAY_BUFFER_ARB, buffer);
            glBufferSubData(GL_ARRAY_BUFFER_ARB, 0,  (sizeof(char) * 640 * 480 * 3), point_cloud.points_color); 
            glBufferSubData(GL_ARRAY_BUFFER_ARB, (sizeof(char) * 640 * 480 * 3), (sizeof(float) * 640 * 480 * 3), point_cloud.points_position);

            // enable vertex arrays
            glEnableClientState(GL_VERTEX_ARRAY);
            glEnableClientState(GL_COLOR_ARRAY);

            glColorPointer(3, GL_UNSIGNED_BYTE, 0, 0);
            //EDIT: Added the right offset at the vertex pointer position
            glVertexPointer(3, GL_FLOAT, 0, (void*)(sizeof(char) * 640 * 480 * 3));

            //EDIT: Was using GL_POINT instead of GL_POINTS
            glDrawArrays(GL_POINTS, 0, 640*480);

            glDisableClientState(GL_VERTEX_ARRAY);  // disable vertex arrays
            glDisableClientState(GL_COLOR_ARRAY);

            glBindBuffer(GL_ARRAY_BUFFER_ARB, 0);

        glPopMatrix();

        glutSwapBuffers();
    }
...