OpenGL Cube in C++

247 views Asked by At

I am having some issues trying to rendering a cube using OpenGL and C++. I was able to get a simple square on the screen, after adding the extra vertices, a slightly tilted triangle was shown instead... Now I have tried to use an element buffer. I filled the element_buffer [] with extra values (I admittedly found on a tutorial) and have nothing being displayed. Any help would be great.

 #include "CubeAsset.h"    
        CubeAsset::CubeAsset() {
          // model coordinates, origin at centre.
          GLfloat vertex_buffer [] {
             -0.5f,-0.5f,-0.5f, // triangle 0 : begin
            -0.5f,-0.5f, 0.5f,
            -0.5f, 0.5f, 0.5f, // triangle 0 : end
        0.5f, 0.5f,-0.5f, // triangle 2 : begin
        -0.5f,-0.5f,-0.5f,
        -0.5f, 0.5f,-0.5f, // triangle 2 : end
        0.5f,-0.5f, 0.5f,
        -0.5f,-0.5f,-0.5f,
        0.5f,-0.5f,-0.5f,
        0.5f, 0.5f,-0.5f,
        0.5f,-0.5f,-0.5f,
        -0.5f,-0.5f,-0.5f,
        -0.5f,-0.5f,-0.5f,
        -0.5f, 0.5f, 0.5f,
        -0.5f, 0.5f,-0.5f,
        0.5f,-0.5f, 0.5f,
        -0.5f,-0.5f, 0.5f,
        -0.5f,-0.5f,-0.5f,
        -0.5f, 0.5f, 0.5f,
        -0.5f,-0.5f, 0.5f,
        0.5f,-0.5f, 0.5f,
        0.5f, 0.5f, 0.5f,
        0.5f,-0.5f,-0.5f,
        0.5f, 0.5f,-0.5f,
        0.5f,-0.5f,-0.5f,
        0.5f, 0.5f, 0.5f,
        0.5f,-0.5f, 0.5f,
        0.5f, 0.5f, 0.5f,
        0.5f, 0.5f,-0.5f,
        -0.5f, 0.5f,-0.5f,
        0.5f, 0.5f, 0.5f,
        -0.5f, 0.5f,-0.5f,
        -0.5f, 0.5f, 0.5f,
        0.5f, 0.5f, 0.5f,
        -0.5f, 0.5f, 0.5f,
        0.5f,-0.5f, 0.5f
      };

      element_buffer_length = 36;
      GLubyte element_buffer []  {
          0, 1, 2, 2, 3, 0,
          0, 3, 4, 4, 5, 0,
          0, 5, 6, 6, 1, 0,
          1, 6, 7, 7, 2, 1,
          7, 4, 3, 3, 2, 7,
          4, 7, 6, 6, 5, 4

      };

      // Transfer buffers to the GPU
      //

      // create buffer
      glGenBuffers(1, &vertex_buffer_token);

      // immediately bind the buffer and transfer the data
      glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_token);
      glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 12, vertex_buffer, GL_STATIC_DRAW);

      glGenBuffers(1, &element_buffer_token);
      glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, element_buffer_token);
      glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * element_buffer_length, element_buffer, GL_STATIC_DRAW);
    }

    CubeAsset::~CubeAsset() {
    }

    #ifdef DEBUG
    #define checkGLError() checkError(__FILE__, __LINE__)
    #else
    // define symbol to be nothing
    #define checkGLError()
    #endif

    void checkError(std::string file, int line) {
      GLenum gl_error = glGetError();
      if(GL_NO_ERROR != gl_error) {
        std::cerr << "GL error in " << file << " at line " << line << " error: " << gl_error << std::endl;
        exit(-1);
      }
    }

    void CubeAsset::Draw(GLuint program_token) {
      if(!glIsProgram(program_token)) {
        std::cerr << "Drawing Cube with invalid program" << std::endl;
        return;
      }
      GLint validation_ok;
      glValidateProgram(program_token);
      glGetProgramiv(program_token, GL_VALIDATE_STATUS, &validation_ok);
      if(!validation_ok) {
        GLint maxLength = 0;
        glGetProgramiv(program_token, GL_INFO_LOG_LENGTH, &maxLength);

        //The maxLength includes the NULL character
        std::vector<char> errorLog(maxLength);
        glGetProgramInfoLog(program_token, maxLength, &maxLength, &errorLog[0]);

        std::cerr << "Invalid program " << program_token << " with error code " << validation_ok << std::endl;
        for(auto c: errorLog) {
          std::cerr << c;
        }
        exit(-1);
      }

      GLuint position_attrib = glGetAttribLocation(program_token, "position");
      checkGLError();

      glUseProgram(program_token);
      checkGLError();

      // use the previously transferred buffer as the vertex array.  This way
      // we transfer the buffer once -- at construction -- not on every frame.
      glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_token);
      glVertexAttribPointer(
                            position_attrib,               /* attribute */
                            3,                             /* size */
                            GL_FLOAT,                      /* type */
                            GL_FALSE,                      /* normalized? */
                            0,                             /* stride */
                            (void*)0                       /* array buffer offset */
                            );
      glEnableVertexAttribArray(position_attrib);

      checkGLError();

      glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, element_buffer_token);
      glDrawElements(
                     GL_TRIANGLES,
                     element_buffer_length,
                     GL_UNSIGNED_INT,
                     (GLvoid*) 0
                     );

      checkGLError();

      glDisableVertexAttribArray(position_attrib);
    }

The header file:

#ifndef CUBEASSET_H
#define CUBEASSET_H

#include <vector>

#include <GL/gl.h>
#include <glm/glm.hpp>
#include <glm/ext.hpp>

#include "GameAsset.h"

class CubeAsset : public GameAsset {
 public:
  CubeAsset();
  ~CubeAsset();
  virtual void Draw(GLuint);

 private:
  GLuint element_buffer_length;
  GLuint vertex_buffer_token, element_buffer_token;
};

#endif // CUBEASSET_H
1

There are 1 answers

1
Reto Koradi On

You have a type mismatch. You indices in your code are of type GLubyte:

GLubyte element_buffer []  {
    0, 1, 2, 2, 3, 0,
    ...

But the rest of the code treats the as GLuint:

glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * element_buffer_length, ...);
...
glDrawElements(GL_TRIANGLES, element_buffer_length, GL_UNSIGNED_INT, ...);

You need to settle on using a consistent type, either GLubyte everywhere, or GLuint everywhere.