Использование VBO для рисования куба путем загрузки объекта волнового фронта

Мне необходимо использовать VBO для рисования куба, загрузив объект волнового фронта. рисуя треугольники. вот объект:

v -1.000000 -1.000000 1.000000
v -1.000000 1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v -1.000000 1.000000 -1.000000
v 1.000000 -1.000000 1.000000
v 1.000000 1.000000 1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 1.000000 -1.000000
vn -1.0000 0.0000 0.0000
vn 0.0000 0.0000 -1.0000
vn 1.0000 0.0000 0.0000
vn 0.0000 0.0000 1.0000
vn 0.0000 -1.0000 0.0000
vn 0.0000 1.0000 0.0000
f 2//1 3//1 1//1
f 4//2 7//2 3//2
f 8//3 5//3 7//3
f 6//4 1//4 5//4
f 7//5 1//5 3//5
f 4//6 6//6 8//6
f 2//1 4//1 3//1
f 4//2 8//2 7//2
f 8//3 6//3 5//3
f 6//4 2//4 1//4
f 7//5 5//5 1//5
f 4//6 2//6 6//6  

У меня также есть более крутой массив, заполненный мной, который равен 3-кратному количеству лиц, что составляет 36 индексов.

float colours[] = {
    0.583f,  0.771f,  0.014f,
    0.609f,  0.115f,  0.436f,
    0.327f,  0.483f,  0.844f,
    0.822f,  0.569f,  0.201f,
    0.435f,  0.602f,  0.223f,
    0.310f,  0.747f,  0.185f,
    0.597f,  0.770f,  0.761f,
    0.559f,  0.436f,  0.730f,
    0.359f,  0.583f,  0.152f,
    0.483f,  0.596f,  0.789f,
    0.559f,  0.861f,  0.639f,
    0.195f,  0.548f,  0.859f,
    }

Я храню информацию о вершинах, нормалях и цветах в массиве, который привязывается к буферу VBO:

 float* vbo = new float[78]

который находится в порядке вершин | нормалей | цветов, что составляет 24 индекса | 18 индексов | 36 индексов, я тестировал, он работает очень хорошо.

Я использую другой массив для хранения информации об индексах вершин, которая равна 36indices, например: f 2//1 3//1 1//1 я храню как 2/3/1 в своем массиве

 int *element = new int[36];

Я был протестирован, он работает хорошо, я инициализирую свой vbo следующим образом:

 static void init(void){
 .......
Gluint vbo_id,index_id;

glGenBuffers(1,&vbo_id);
glGenBuffers(1,&index_id);
glBindBuffer(GL_ARRAY_BUFFER,vbo_id); 
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,index_id);

glBufferData(GL_ARRAY_BUFFER,sizeof(vbo),vbo,GL_STATIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(element),element,GL_STATIC_DRAW); } 

а мой рисунок здесь

 static void display(void){
  .......
 glBindBuffer(GL_ARRAY_BUFFER,vbo_id);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,index_id);
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_COLOR_ARRAY);
    glEnableClientState(GL_NORMAL_ARRAY);
    glVertexPointer(3,GL_FLOAT,0,0);
    glNormalPointer(GL_FLOAT,0,(void*)(24*sizeof(float)));//binding 
    glColorPointer(3,GL_FLOAT,0,(void*)(42*sizeof(float)));

    for(int i=0;i<12;i++){

    glBegin(GL_TRIANGLES);
    glArrayElement(element[i]);
    glArrayElement(element[i+1]);
    glArrayElement(element[i+2]);
    glEnd();

    }
    /* have try this one too:
    glDrawElements(GL_TRIANGLES,3,GL_INT,0) */


    glDisableClientState(GL_COLOR_ARRAY);
    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_NORMAL_ARRAY);
    glBindBuffer(GL_ARRAY_BUFFER,0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
    }

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


person ShaoyuPei    schedule 16.05.2018    source источник


Ответы (1)


Тип vbo — это float*, поэтому sizeof(vbo) — это не размер массива, на который указывает vbo, а размер указателя. См. sizeof.
Обратите внимание, что третий параметр glBufferData должен быть размером буфера в байтах.

Размер float* vbo = new float[78] равен 78 * sizeof(float) или 78 * sizeof(*vbo)
, а размер int *element = new int[36] равен 36 * sizeof(int) или 36 * sizeof(*element)
Но sizeof(vbo) — это размер указателя на массив или такой же, как sizeof(float*).

Это означает, что вы должны изменить код следующим образом:

glBufferData(GL_ARRAY_BUFFER, 78*sizeof(float), vbo, GL_STATIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 36*sizeof(int), element, GL_STATIC_DRAW); 

Второй параметр glDrawElements должен быть числом индексов, а третий параметр должен быть GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT или GL_UNSIGNED_INT, в зависимости от типа данных индексов:

glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, NULL);

Обратите внимание, что лучше использовать unsigned int * вместо int* для типа данных индексного массива (element).


Ваше предположение неверно. Нельзя смешивать 24 координаты вершин, 18 векторов нормалей и 36 цветов с разными массивами индексов напрямую в одном Объект вершинного массива.

Атрибуты вершины для каждой позиции вершины формируют набор данных. Это означает, что вам нужно создать кортежи координат вершины, вектора нормали и цвета.

Подробнее см. Визуализация сеток с несколькими индексами

Я рекомендую использовать std::vector и сделать это как-то так:

#include <vector>

// 8  vertex coordiantes: 8 * 3 float 
std::vector<float> v{
  -1.0f, -1.0f,  1.0f,
  -1.0f,  1.0f,  1.0f,
  -1.0f, -1.0f, -1.0f,
  -1.0f,  1.0f, -1.0f,
   1.0f, -1.0f,  1.0f,
   1.0f,  1.0f,  1.0f,
   1.0f, -1.0f, -1.0f,
   1.0f,  1.0f, -1.0f };

// 6  normal vectors: 6 * 3 float
std::vector<float> nv{
   -1.0f,  0.0f,  0.0f,
    0.0f,  0.0f, -1.0f,
    1.0f,  0.0f,  0.0f,
    0.0f,  0.0f,  1.0f,
    0.0f, -1.0f,  0.0f,
    0.0f,  1.0f,  0.0f };

// 12 colors coordiantes: 12 * 3 float 
std::vector<float> c{
    0.583f,  0.771f,  0.014f,
    0.609f,  0.115f,  0.436f,
    0.327f,  0.483f,  0.844f,
    0.822f,  0.569f,  0.201f,
    0.435f,  0.602f,  0.223f,
    0.310f,  0.747f,  0.185f,
    0.597f,  0.770f,  0.761f,
    0.559f,  0.436f,  0.730f,
    0.359f,  0.583f,  0.152f,
    0.483f,  0.596f,  0.789f,
    0.559f,  0.861f,  0.639f,
    0.195f,  0.548f,  0.859f };

// 12 faces 3*2 indices/face: 12 * 3 * 2 unsigned int 
std::vector<unsigned int> indices{
    2, 1,    3, 1,    1, 1,
    4, 2,    7, 2,    3, 2,
    8, 3,    5, 3,    7, 3,
    6, 4,    1, 4,    5, 4,
    7, 5,    1, 5,    3, 5,
    4, 6,    6, 6,    8, 6,
    2, 1,    4, 1,    3, 1,
    4, 2,    8, 2,    7, 2,
    8, 3,    6, 3,    5, 3,
    6, 4,    2, 4,    1, 4,
    7, 5,    5, 5,    1, 5,
    4, 6,    2, 6,    6, 6 };

Создайте данные массива вершин

// final vertex attributes 12 * 3 *(3 + 3 + 3) floats
// x0 y0 z0    nvx0 nvy0 nvz0    cr0 cg0 cb0
// x1 y1 z1    nvx1 nvy1 nvz1    cr1 cg1 cb1
std::vector<float> va; 

const unsigned int no_of_faces = 12;
for (unsigned int f=0; f<no_of_faces; ++f )
{
    for (unsigned int t=0; t<3; ++t )
    {
        unsigned int vi = indices[(f*3+t)*2]-1;   // vertex index
        unsigned int ni = indices[(f*3+t)*2+1]-1; // normal vector index
        unsigned int ci = f;                      // color index

        va.insert(va.end(), v.begin()  + vi*3, v.begin()  + vi*3+3); // insert vertex coordinate
        va.insert(va.end(), nv.begin() + ni*3, nv.begin() + ni*3+3); // insert normal vector
        va.insert(va.end(), c.begin()  + ci*3, c.begin()  + ci*3+3); // insert color
    }
}

Создайте объект Vertex Buffer:

GLuint vbo;
glGenBuffers( 1, &vbo );
glBindBuffer( GL_ARRAY_BUFFER, vbo );
glBufferData( GL_ARRAY_BUFFER, va.size()*sizeof(*va.data()), va.data(), GL_STATIC_DRAW );

Определите массивы общих данных атрибутов вершин:

glVertexPointer( 3, GL_FLOAT, 9*sizeof(*va.data()), 0 );
glEnableClientState( GL_VERTEX_ARRAY );
glNormalPointer( GL_FLOAT, 9*sizeof(*va.data()), (void*)(3*sizeof(*va.data())) ); 
glEnableClientState( GL_NORMAL_ARRAY );
glColorPointer( 3, GL_FLOAT, 9*sizeof(*va.data()), (void*)(6*sizeof(*va.data())) ); 
glEnableClientState( GL_COLOR_ARRAY );
glBindBuffer( GL_ARRAY_BUFFER, 0 );

Нарисуйте массив:

glDrawArrays( GL_TRIANGLES, 0, 36 );

Предварительный просмотр:

куб

person Rabbid76    schedule 16.05.2018
comment
Привет, я следую вашим инструкциям, но происходит сбой, он должен использовать sizeof(*float) или sizeof(*va.data())? и это должно быть glDrawArrays(GL_TRIANGLES, 0, 12)? ;Я проверяю, что va имеет правильный вывод., - person ShaoyuPei; 20.05.2018