ZzkilzZ ZzkilzZ - 3 years ago 123
C++ Question

VAO gets deleted without calling glDeleteVertexArrays()

I have just started to learn OpenGL and I am currently trying to apply the OpenGL knowledge I have acquired in a small game architecture, but I am having a hard time making this work with Classes. I am trying to display a triangle on the screen using a separate class like this:
CubeModel.h

#pragma once
#include <vector>
#include <glad\glad.h>

class CubeModel
{
public:
//x y and z are dimensions of the cube
CubeModel();
CubeModel( float x, float y, float z);
~CubeModel();

void Bind();
void Unbind();

private:

unsigned int m_VAO, m_VBO;

std::vector<float> m_vertices = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f
};

std::vector<float> m_vertices2 = {
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,

-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,

-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,

0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,

-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 1.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,

-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f
};
};


CubeModel.cpp

#include "CubeModel.h"

CubeModel::CubeModel()
{
CubeModel(1.0f, 1.0f, 1.0f);
}

CubeModel::CubeModel(float x, float y, float z)
{
unsigned int VAO, VBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);

glBindVertexArray(VAO);

glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(m_vertices[0]) * m_vertices.size(),
m_vertices.data(), GL_STATIC_DRAW);

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);

glBindVertexArray(0);

m_VAO = VAO;
m_VBO = VBO;
}

CubeModel::~CubeModel()
{
glDeleteVertexArrays(1, &m_VAO);
glDeleteBuffers(1, &m_VBO);
}

void CubeModel::Bind()
{
glBindVertexArray(m_VAO);
}

void CubeModel::Unbind()
{
glBindVertexArray(0);
}


Game_State.h (where CubeModel is used):

#pragma once
#include "Window.h"
#include "Shader.h"
#include "CubeModel.h"

#define TIMESTEP 1.0f/100.0f

class Game_State
{
public:
Game_State();
~Game_State();

int Run();
bool IsDone();

private:
void HandleInput();
void Update(double deltatime);
void Render();

Window m_window;
double m_elapsedTime = 0;
Shader m_cubeShader;
CubeModel m_testCube;
};


Game_State.cpp:

#include "Game_State.h"

Game_State::Game_State()
: m_window("Title to be determined...", glm::vec2(1920, 1080))
, m_cubeShader("cubeshader.vs","cubeshader.fs")
{
}

Game_State::~Game_State()
{
}

int Game_State::Run()
{

while (m_elapsedTime > TIMESTEP)
{
m_elapsedTime -= TIMESTEP;
HandleInput();
Update(m_elapsedTime);
}

Render();

m_elapsedTime += glfwGetTime();
glfwSetTime(0.0f);

return 0;
}

void Game_State::Update(double deltatime)
{
m_window.Update();
}

void Game_State::Render()
{

m_window.BeginDraw(0.7f, 0.5f, 0.3f, 1.0f);

m_cubeShader.use();

m_testCube.Bind();
glDrawArrays(GL_TRIANGLES, 0, 6);

m_testCube.Unbind();

m_window.EndDraw();

}

void Game_State::HandleInput()
{
if (glfwGetKey(m_window.GetWindow(), GLFW_KEY_F11) == GLFW_PRESS)
{
m_window.ToggleFullscreen();
}

if (glfwGetKey(m_window.GetWindow(), GLFW_KEY_ESCAPE) == GLFW_PRESS)
{
m_window.CloseWindow();
}
}

bool Game_State::IsDone() { return m_window.IsDone(); }


When i tried to debug the code, everything was working and the VAO and VBO both got an ID but by the time i call the bind function before drawing it to the screen in a separate render function it binds the array with ID 0. Both the m_VAO and m_VBO gets reset to 0 by the time bind() is called, what is the reason for this?!?! I've tried using this exact code directly in the render function and it works so the render is fine it seems. (I'm using GLFW and GLAD)
Thanks in advance! :)

Answer Source

This:

CubeModel::CubeModel()
{
    CubeModel(1.0f, 1.0f, 1.0f);
}

is wrong. That creates a CubeModel temporary within the constructor. That's not the same thing as delegating the constructor. If that's what you wanted, you have to use the proper C++11 syntax:

CubeModel::CubeModel() : CubeModel(1.0f, 1.0f, 1.0f)
{}

Note that this may not be your only problem, since you neglected to post all of your code.

For example, CubeModel is technically copyable, but it shouldn't be. You make no special allowances for copying (which by its nature, would have to create a new VAO and buffer, and copy the data from the other VAO/buffer). So you need to delete the copy operations, and write appropriate move operations:

CubeModel(const CubeModel &) = delete;
CubeModel(CubeModel &&other) : m_VAO(other.m_VAO), m_VBO(other.m_VBO)
{
  other.m_VAO = 0;
  other.m_VBO = 0;
}

And do something similar for the move assignment operation. Or just leave it as being unassignable.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download