2015-05-05 4 views
0

Я пытаюсь нарисовать исосферу с помощью VBO и glDrawArrays. После каждого разбиения, когда глубина достигает 0, я добавляю 3 новых вершины к вектору. Наконец, в Render() я вызываю glDrawArrays(enum mode, 0, vector.size), но результат выглядит странно. Я думаю, что это результат неправильного определения сферных индексов. Во-первых, я использовал glDrawElements, но только около 1/4 сферы было нарисовано на экране, затем я изменил использование glDrawArrays и получил результат, как показано ниже.Рисунок Icosphere с использованием VBO

Не могли бы помочь показать, где я ошибаюсь, пожалуйста?

есть линии, соединяющие 2 противоположные точки

there are lines which connect 2 opposite points

Это код для создания вершин:

int numsToDraw, numberOfVerices = 0;; 

vector<GLfloat> vertices; 
vector<GLfloat> normals; 
vector<GLfloat> texture; 
vector<GLuint> indices; 

void normalize3f(float v[3]){ 
    GLfloat d = sqrtf(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]); 
    if (d == 0.0f){ 
     fprintf(stderr, "Zero length vector. \n"); 
     return; 
    } 
    v[0] /= d; 
    v[1] /= d; 
    v[2] /= d; 
} 

void addVertices(GLfloat v[]){ 
    for (int i = 0; i < 3; i++){ 
     vertices.push_back(v[i]); 
    } 
} 

void subdivide(GLfloat v1[], GLfloat v2[], GLfloat v3[], int depth){ 
    GLfloat v12[3], v23[3], v31[3]; 

    if (depth == 0){ 
     addVertices(v1); 
     addVertices(v2); 
     addVertices(v3); 
     //indices.push_back(numberOfVerices); 
     //numberOfVerices++; 
     return; 
    } 

    for (int i = 0; i < 3; i++){ 
     v12[i] = v1[i]+v2[i]; 
     v23[i] = v2[i]+v3[i]; 
     v31[i] = v3[i]+v1[i]; 
    } 

    normalize3f(v12); 
    normalize3f(v23); 
    normalize3f(v31); 
    subdivide(v1, v12, v31, depth-1); 
    subdivide(v2, v23, v12, depth-1); 
    subdivide(v3, v31, v23, depth-1); 
    subdivide(v12, v23, v31, depth-1); 
} 

void drawSphere(int depth){ 
    for(int i = 0; i < 20; i++){ 
     subdivide(icosahedron[icoindices[i][0]], 
        icosahedron[icoindices[i][1]], 
        icosahedron[icoindices[i][2]], depth); 
    } 
} 

Это то, что я имею в настройке РВО:

drawSphere(1); 

    glGenBuffers(1, &vboVertex); 
    glBindBuffer(GL_ARRAY_BUFFER, vboVertex); 
    glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(GLfloat), &vertices[0], GL_STATIC_DRAW); 
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL); 
    glEnableVertexAttribArray(0); 

    glGenBuffers(1, &vboTexture); 
    glBindBuffer(GL_ARRAY_BUFFER, vboTexture); 
    glBufferData(GL_ARRAY_BUFFER, texture.size() * sizeof(GLfloat), &texture[0], GL_STATIC_DRAW); 
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0); 
    glEnableVertexAttribArray(1); 

    glGenBuffers(1, &vboIndex); 
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndex); 
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLuint), &indices[0], GL_STATIC_DRAW); 

    numsToDraw = indices.size(); 

Это мой способ визуализации:

glClearColor(0.0, 0.0, 0.0, 1.0);/* Make our background black */ 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

    glEnable(GL_PRIMITIVE_RESTART); 
    glPrimitiveRestartIndex(GL_PRIMITIVE_RESTART_FIXED_INDEX); 
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndex); 

    glPushMatrix(); 
    glLoadIdentity(); 
    glActiveTexture(GL_TEXTURE0); 
    glBindTexture(GL_TEXTURE_2D, texture_test[0]); 
    glUniform1i(textureLocation, 0); 
    glm::mat4 Projection = glm::perspective(50.0f, 5.0f/3.0f, 1.0f, 100.0f); 
     glm::mat4 View = glm::lookAt(
      glm::vec3(0, 5, 2), 
      glm::vec3(0, 0, 0), 
      glm::vec3(0, 1, 0) 
     ); 

     /* Animations */ 
     GLfloat angle = (GLfloat) (i); 
     View = glm::translate(View, glm::vec3(2.0f, 0.0f, 0.0f)); 
     View = glm::rotate(View, angle * 0.5f, glm::vec3(0.0f, 0.0f, 1.0f)); 
     /* ******* */ 

     glm::mat4 Model = glm::mat4(1.0f); 
     glm::mat4 MVP = Projection * View * Model; 

     glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "mvpMatrix"), 1, GL_FALSE, glm::value_ptr(MVP)); 
    glDrawArrays(GL_LINE_LOOP, 0, vertices.size()); 
    //glDrawElements(GL_LINE_LOOP, numsToDraw, GL_UNSIGNED_INT, NULL); 
    glPopMatrix(); 

ответ

2

Вершины вы продуцируют не совместимы с примитивным используется для вызова отрисовки здесь:

glDrawArrays(GL_LINE_LOOP, 0, vertices.size()); 

GL_LINE_LOOP оказывает связное множество линий через все ваши вершины. Но когда вы создаете свои вершины, вы создаете 3 вершины на треугольник:

addVertices(v1); 
addVertices(v2); 
addVertices(v3); 

Таким образом, при визуализации с GL_LINE_LOOP, линия будет нарисована из последней вершины каждого треугольника к первой вершине следующего треугольника, в то время как никакая линия не будет проведена между v2 и v3. Глядя только два треугольника с вершинами v1, v2, v3 и v1', v2', v3', отрезки нарисованные будут:

v1 v2 
v2 v3 
v3 v1' 
v1' v2' 
v2' v3' 

Отрезок между v3 и v1' соответствует дополнительных линий, которые вы видите. То, что вы действительно хотите:

v1 v2 
v2 v3 
v3 v1 
v1' v2' 
v2' v3' 
v3' v1' 

Самый прямой способ исправить это использовать GL_TRIANGLES в качестве примитивного типа, так что непосредственно соответствует вершины, которые производятся:

glDrawArrays(GL_TRIANGES, 0, vertices.size()); 

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

glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 

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

addVertices(v1); 
addVertices(v2); 

addVertices(v2); 
addVertices(v3); 

addVertices(v3); 
addVertices(v1); 

Это соответствует желательная последовательность вершин выше.Затем вы можете нарисовать это с помощью:

glDrawArrays(GL_LINES, 0, vertices.size()); 

Будьте осторожны при вводе значений перечисления для этих решений. Последний аргумент glPolygonMode() - это GL_LINE в первом варианте, а первый аргумент glDrawArrays() - это GL_LINES во втором варианте. Они выглядят очень похожими, но имеют разные значения.