I have been trying to write some classes to abstract OpenGl. So far I have written a VertexArray class that uses template functions which are working fine so far. However I have encountered problems with my VertexBuffer class that I have not been capable of fixing. C++ and OpenGl are still fairly new to me so the solution might be pretty simple.
Whenever I try to replace the Vertex Buffer creation code with the constructor of the VertexBuffer class things go wrong and nothing is displayed on the screen even though the code of the constructor and the one directly written in the Mesh class are (I believe) the same.
Here is the code:
VertexBuffer.h:
#ifndef VERTEX_BUFFER_H
#define VERTEX_BUFFER_H
class VertexBuffer {
private:
public:
unsigned int ID;
VertexBuffer(const void* data, unsigned int size);
VertexBuffer();
~VertexBuffer();
void bind();
void unbind();
};
#endif
VertexBuffer.cpp:
#include "VertexBuffer.h"
#define GLEW_STATIC
#include <GL/glew.h>
#include <iostream>
VertexBuffer::VertexBuffer(const void* data, unsigned int size) {
glGenBuffers(1, &ID);
glBindBuffer(GL_ARRAY_BUFFER, ID);
glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW);
std::cout << "ID = " << ID << std::endl;
std::cout << "data = " << data << std::endl;
std::cout << "size = " << size << std::endl << std::endl;
}
VertexBuffer::VertexBuffer() {}
VertexBuffer::~VertexBuffer() {
glDeleteBuffers(1, &ID);
}
void VertexBuffer::bind() {
glBindBuffer(GL_ARRAY_BUFFER, ID);
}
void VertexBuffer::unbind() {
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
The Mesh constructor where I have been trying to implement it via the class:
Mesh::Mesh(std::vector<Vertex> vertices) {
model = glm::mat4(1.0f);
indicesSize = vertices.size();
// generate vertex array object
va = VertexArray();
va.bind();
//============================================================
//This code works:
/*
glGenBuffers(1, &vb.ID);
glBindBuffer(GL_ARRAY_BUFFER, vb.ID);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * vertices.size(), &vertices[0], GL_STATIC_DRAW);
*/
//------------------------------------------------------------
//This code does not work:
vb = VertexBuffer(&vertices[0], sizeof(Vertex) * vertices.size());
//============================================================
// points
va.push<float>(3, 9, false);
// colors
va.push<float>(3, 9, false);
// normals
va.push<float>(3, 9, false);
};
I would be happy if anyone can help me. Thanks in advance!
You have to store vb
in some kind of smart pointer or add move semantics to VertexBuffer
.
vb = VertexBuffer(&vertices[0], sizeof(Vertex) * vertices.size());
^^^ [1]
in [1]
temporary VertexBuffer
is created, then by operator =
, the member ID
is copied in shallow way into vb
and finally at the end of expression temporary VertexBuffer
is destroyed with deleting generated ID
(by destructor of temporary instance), which is still stored in vb
, but it is not valid anymore.
Solution with move semantics could be like:
class VertexBuffer {
std::unique_ptr<unsigned int> ID;
public:
VertexBuffer& operator=(VertexBuffer&& other) {
ID = std::move(other.ID);
return *this;
}
~VertexBuffer() {
if (ID)
glDeleteBuffers(1, ID.get() );
}
};