Issue in drawing ellipsoid with OpenGL

空扰寡人 提交于 2020-03-23 07:50:22

问题


this is the code I use to create and draw an ellipsoid with OpenGL with shader

  const float _2pi = 2.0f * M_PI;

  std::vector<glm::vec3> positions;
  std::vector<glm::vec3> normals;
  std::vector<glm::vec2> textureCoords;

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

    // V texture coordinate
    float V = i / (float)stacks;
    float phi = V * M_PI;

    for( int j = 0; j <= slices; ++j) {

      // U texture coordinate
      float U = j / (float)slices;
      float theta = U * _2pi;

      float X = a * cos(theta) * cos(phi);
      float Y = b * cos(theta) * sin(phi);
      float Z = c * sin(theta);

      positions.push_back( glm::vec3( X, Y, Z) );
      normals.push_back( glm::vec3(X, Y, Z) );
      textureCoords.push_back( glm::vec2(U, V) );

    }

  }

  // Now generate the index buffer
  std::vector<GLuint> indicies;

  for(int i=0; i <slices*stacks+slices; ++i) {

    indicies.push_back(i);
    indicies.push_back(i + slices + 1);
    indicies.push_back(i + slices);

    indicies.push_back(i + slices + 1);
    indicies.push_back(i);
    indicies.push_back(i + 1);

  }

  glGenVertexArrays(1, &vao);
  glBindVertexArray(vao);

  glGenBuffers(4, vbo);

  glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
  glBufferData(GL_ARRAY_BUFFER, positions.size() * sizeof(glm::vec3), positions.data(), GL_STATIC_DRAW);
  glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
  glEnableVertexAttribArray(0);

  glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
  glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(glm::vec3), normals.data(), GL_STATIC_DRAW);
  glVertexAttribPointer(2, 3, GL_FLOAT, GL_TRUE, 0, nullptr);
  glEnableVertexAttribArray(2);

  glBindBuffer(GL_ARRAY_BUFFER, vbo[2]);
  glBufferData(GL_ARRAY_BUFFER, textureCoords.size() * sizeof(glm::vec2), textureCoords.data(), GL_STATIC_DRAW);
  glVertexAttribPointer(8, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
  glEnableVertexAttribArray(8);

  glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, vbo[3]);
  glBufferData( GL_ELEMENT_ARRAY_BUFFER, indicies.size() * sizeof(GLuint), indicies.data(), GL_STATIC_DRAW);

  glBindVertexArray(0);
  glBindBuffer(GL_ARRAY_BUFFER, 0);
  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

while this is the code that I use to render it:

  glBindVertexArray(vao);

  glEnableVertexAttribArray(0);

  if(style == glObject::STYLE::WIREFRAME) glDrawElements(GL_LINES,     (slices * stacks + slices) * 6, GL_UNSIGNED_INT, nullptr);
  if(style == glObject::STYLE::SOLID)     glDrawElements(GL_TRIANGLES, (slices * stacks + slices) * 6, GL_UNSIGNED_INT, nullptr);

  glBindVertexArray(0);

It seems to work but I have some issue. Looking the image it is possible to see some vertex in the wrong position. I think that is something related to the indicies but I'm not sure. I have notice that depends by the number of stacks or slices that I use

UPDATE:

I take into account the suggestion of @Rabbid76 and this is the result. No more degenerated vertex and triangles in the rendering. However the rendering is not equal to the one of @Rabbid76 there is like a rotation of the vertex.

FINAL:

This is the creation vertex and indices code:

      std::vector<glm::vec3> positions;
      std::vector<glm::vec3> normals;
      std::vector<glm::vec2> textureCoords;

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

        // V texture coordinate.
        float V = i / (float)stacks;
        float phi = V * M_PI;

        for( int j = 0; j <= slices; ++j) {

          // U texture coordinate.
          float U = j / (float)slices;
          float theta = U * 2.0f * M_PI;

          float X = cos(theta) * sin(phi);
          float Y = cos(phi);
          float Z = sin(theta) * sin(phi);

          positions.push_back( glm::vec3( X, Y, Z) * radius );
          normals.push_back( glm::vec3(X, Y, Z) );
          textureCoords.push_back( glm::vec2(U, V) );

        }

      }

      // Now generate the index buffer
      std::vector<GLuint> indicies;

      int noPerSlice = slices + 1;

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

        for (int j=0; j < slices; ++j) {

          int start_i = (i * noPerSlice) + j;

          indicies.push_back( start_i );
          indicies.push_back( start_i + noPerSlice + 1 );
          indicies.push_back( start_i + noPerSlice );

          indicies.push_back( start_i + noPerSlice + 1 );
          indicies.push_back( start_i );
          indicies.push_back( start_i + 1 );

        }

      }

      glGenVertexArrays(1, &vao);
      glBindVertexArray(vao);

      glGenBuffers(4, vbo);

      glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
      glBufferData(GL_ARRAY_BUFFER, positions.size() * sizeof(glm::vec3), positions.data(), GL_STATIC_DRAW);
      glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
      glEnableVertexAttribArray(0);

      glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
      glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(glm::vec3), normals.data(), GL_STATIC_DRAW);
      glVertexAttribPointer(2, 3, GL_FLOAT, GL_TRUE, 0, nullptr);
      glEnableVertexAttribArray(2);

      glBindBuffer(GL_ARRAY_BUFFER, vbo[2]);
      glBufferData(GL_ARRAY_BUFFER, textureCoords.size() * sizeof(glm::vec2), textureCoords.data(), GL_STATIC_DRAW);
      glVertexAttribPointer(8, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
      glEnableVertexAttribArray(8);

      glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo[3]);
      glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicies.size() * sizeof(GLuint), indicies.data(), GL_STATIC_DRAW);

      glBindVertexArray(0);
      glBindBuffer(GL_ARRAY_BUFFER, 0);
      glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

This is the rendering one:

    glBindVertexArray(vao);

    glEnableVertexAttribArray(0);

    if(style == glObject::STYLE::WIREFRAME) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    if(style == glObject::STYLE::SOLID)     glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

    glDrawElements(GL_TRIANGLES, (slices * stacks + slices) * 6, GL_UNSIGNED_INT, nullptr);

    glBindVertexArray(0);

回答1:


You have confused phi and theta. theta is the angle of the points around the circumference of a slice in range [0, 2*PI]. phi is the angle of the points form the south to the north in range [-PI, PI]:

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

    // V texture coordinate
    float V = i / (float)stacks;
    float phi = V * M_PI - M_PI/2.0;

    for ( int j = 0; j <= slices; ++j) {

        // U texture coordinate
        float U = j / (float)slices;
        float theta = U * _2pi;

        float X = a * cos(phi) * cos(theta);
        float Y = b * cos(phi) * sin(theta);
        float Z = c * sin(phi);

        positions.push_back( glm::vec3( X, Y, Z) );
        normals.push_back( glm::vec3(X, Y, Z) );
        textureCoords.push_back( glm::vec2(U, V) );
    }
}

The number of points of a slice (around the circumference) is noPerSlice = slices + 1. The first index of a point of a quad is start_i = (i * noPerSlice) + j, where i is the index of the stack and j the index around the slice. Create slices quads around the circumference and stacks slices form the south to the north:

int noPerSlice = slices + 1;
for(int i=0; i < stacks; ++i) {
    for (int j = 0; j < slices; ++j) {

        int start_i = (i * noPerSlice) + j;

        indicies.push_back( start_i );
        indicies.push_back( start_i + noPerSlice + 1 );
        indicies.push_back( start_i + noPerSlice );

        indicies.push_back( start_i + noPerSlice + 1 );
        indicies.push_back( start_i );
        indicies.push_back( start_i + 1 );
    }
}




回答2:


i think

slices*stacks+slices

should be

slices*stacks+stacks

the +stacks is for the extra quads from the duplicate vertex in every stack

although this fixes the number of indices, you still have degenerate triangles along the duplicate vertices where theta equals zero



来源:https://stackoverflow.com/questions/60686457/issue-in-drawing-ellipsoid-with-opengl

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!