Vertex Buffer Abstraction in OpenGl [duplicate] - c++

This question already has answers here:
OpenGL object in C++ RAII class no longer works
(2 answers)
Closed 1 year ago.
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() );
}
};

Related

Heap has been corrupted when using std::unique_ptr

I've been working on a Quake 3 BSP Loader in OpenGL and C++.
And I've ran into a problem, when I run my code. I get a problem, it says "heap has been corrupted!" in debug mode. I have commented the line it corrupts on. My comment is 'gives me the error at this line "Heap has been corrupted"'
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/vec3.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <vector>
#include "map.h"
#include <fstream>
#include <memory>
#include "game_manager.h"
#include <thread>
bool KikoBSP::load_map(std::string file_name)
{
this->file.open(file_name.c_str(), std::ios::in | std::ios::binary);
if (this->file.is_open())
{
this->file.read(reinterpret_cast<char*>(&this->header), sizeof(this->header));
std::unique_ptr<BSPEntities> ents(new BSPEntities);
ents->ents_array = new char[this->header.lumps[BSPLUMPS::ENTITIES].length];
this->num_textures = this->header.lumps[BSPLUMPS::TEXTURES].length / sizeof(BSPTexture);
this->num_planes = this->header.lumps[BSPLUMPS::PLANES].length / sizeof(BSPPlane);
this->num_textures = this->header.lumps[BSPLUMPS::TEXTURES].length / sizeof(BSPTexture);
this->num_nodes = this->header.lumps[BSPLUMPS::NODES].length / sizeof(BSPNode);
this->num_leafs = this->header.lumps[BSPLUMPS::LEAFS].length / sizeof(BSPLeaf);
this->num_leaf_faces = this->header.lumps[BSPLUMPS::LEAF_FACES].length / sizeof(BSPLeafFace);
this->num_leaf_brushes = this->header.lumps[BSPLUMPS::LEAF_BRUSHES].length / sizeof(BSPLeafBrush);
this->num_models = this->header.lumps[BSPLUMPS::MODELS].length / sizeof(BSPModel);
this->num_brushes = this->header.lumps[BSPLUMPS::BRUSHES].length / sizeof(BSPBrush);
this->num_brush_sides = this->header.lumps[BSPLUMPS::BRUSHSIDES].length / sizeof(BSPBrushSides);
this->num_vertexes = this->header.lumps[BSPLUMPS::VERTEXES].length / sizeof(BSPVerts);
this->num_meshverts = this->header.lumps[BSPLUMPS::MESHVERTS].length / sizeof(BSPMeshVerts);
this->num_effects = this->header.lumps[BSPLUMPS::EFFECTS].length / sizeof(BSPEffects);
this->num_faces = this->header.lumps[BSPLUMPS::FACES].length / sizeof(BSPFaces);
std::unique_ptr<BSPTexture[]> textures(new BSPTexture[this->num_textures]);
std::unique_ptr<BSPPlane[]> planes(new BSPPlane[this->num_planes]);
std::unique_ptr<BSPNode[]> nodes(new BSPNode[this->num_nodes]);
std::unique_ptr<BSPLeaf[]> leafs(new BSPLeaf[this->num_leafs]);
std::unique_ptr<BSPLeafFace[]> leaf_faces(new BSPLeafFace[this->num_leaf_faces]);
std::unique_ptr<BSPLeafBrush[]> leaf_brushes(new BSPLeafBrush[this->num_leaf_brushes]);
std::unique_ptr<BSPModel[]> models(new BSPModel[this->num_models]);
std::unique_ptr<BSPBrush[]> brushes(new BSPBrush[this->num_brushes]);
std::unique_ptr<BSPBrushSides[]> brush_sides(new BSPBrushSides[this->num_brush_sides]);
std::unique_ptr<BSPVerts[]> vertexes(new BSPVerts[this->num_vertexes]);
std::unique_ptr<BSPMeshVerts[]> mesh_verts(new BSPMeshVerts[this->num_mesh_verts]);
std::unique_ptr<BSPEffects[]> effects(new BSPEffects[this->num_effects]);
std::unique_ptr<BSPFaces[]> faces(new BSPFaces[this->num_faces]);
this->file.seekg(this->header.lumps[BSPLUMPS::ENTITIES].offset);
this->file.read(reinterpret_cast<char*>(ents->ents_array), this->header.lumps[BSPLUMPS::ENTITIES].length);
this->file.seekg(this->header.lumps[BSPLUMPS::TEXTURES].offset);
this->file.read(reinterpret_cast<char*>(textures.get()), this->header.lumps[BSPLUMPS::TEXTURES].length);
this->file.seekg(this->header.lumps[BSPLUMPS::PLANES].offset);
this->file.read(reinterpret_cast<char*>(planes.get()), this->header.lumps[BSPLUMPS::PLANES].length);
this->file.seekg(this->header.lumps[BSPLUMPS::NODES].offset);
this->file.read(reinterpret_cast<char*>(nodes.get()), this->header.lumps[BSPLUMPS::NODES].length);
this->file.seekg(this->header.lumps[BSPLUMPS::LEAFS].offset);
this->file.read(reinterpret_cast<char*>(leafs.get()), this->header.lumps[BSPLUMPS::LEAFS].length);
this->file.seekg(this->header.lumps[BSPLUMPS::LEAF_FACES].offset);
this->file.read(reinterpret_cast<char*>(leaf_faces.get()), this->header.lumps[BSPLUMPS::LEAF_FACES].length);
this->file.seekg(this->header.lumps[BSPLUMPS::LEAF_BRUSHES].offset);
this->file.read(reinterpret_cast<char*>(leaf_brushes.get()), this->header.lumps[BSPLUMPS::LEAF_BRUSHES].length);
this->file.seekg(this->header.lumps[BSPLUMPS::MODELS].offset);
this->file.read(reinterpret_cast<char*>(models.get()), this->header.lumps[BSPLUMPS::MODELS].length);
this->file.seekg(this->header.lumps[BSPLUMPS::BRUSHES].offset);
this->file.read(reinterpret_cast<char*>(brushes.get()), this->header.lumps[BSPLUMPS::BRUSHES].length);
this->file.seekg(this->header.lumps[BSPLUMPS::BRUSHSIDES].offset);
this->file.read(reinterpret_cast<char*>(brush_sides.get()), this->header.lumps[BSPLUMPS::BRUSHSIDES].length);
this->file.seekg(this->header.lumps[BSPLUMPS::VERTEXES].offset);
this->file.read(reinterpret_cast<char*>(vertexes.get()), this->header.lumps[BSPLUMPS::VERTEXES].length);
this->file.seekg(this->header.lumps[BSPLUMPS::MESHVERTS].offset);
this->file.read(reinterpret_cast<char*>(mesh_verts.get()), this->header.lumps[BSPLUMPS::MESHVERTS].length);
this->file.seekg(this->header.lumps[BSPLUMPS::EFFECTS].offset);
this->file.read(reinterpret_cast<char*>(effects.get()), this->header.lumps[BSPLUMPS::EFFECTS].length);
this->file.seekg(this->header.lumps[BSPLUMPS::FACES].offset);
this->file.read(reinterpret_cast<char*>(faces.get()), this->header.lumps[BSPLUMPS::FACES].length);
std::printf("BSP VERSION: '%s'\n", this->header.magic);
if (std::strncmp(this->header.magic, "IBSP", 4) == 0)
{
std::printf("SUCCESS: VALID BSP FORMAT!\n");
}
else
{
std::printf("ERROR: INVALID BSP FORMAT!\n");
return false;
}
std::printf("this->num_of_verts == %i\n", this->num_vertexes);
for (int32_t x = 0; x <= this->num_vertexes; x++)
{
this->vertices.push_back(vertexes.get()[x].position.x);
this->vertices.push_back(vertexes.get()[x].position.y); /* gives me the error at this line "Heap has been corrupted" */
this->vertices.push_back(vertexes.get()[x].position.z);
this->colors.push_back((float)x); /* doesnt follow my code style (using C-style cast), sorry!! I copied this from my old project ;) */
}
std::printf("this->vertices.size() == %i\n", this->vertices.size());
this->shader.load_shader("bsp.vs", "bsp.fs");
glGenVertexArrays(1, &this->vao);
glBindVertexArray(this->vao);
glGenBuffers(1, &this->vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, this->vertices.size() * sizeof(float), &this->vertices.front(), GL_STATIC_DRAW);
glGenBuffers(1, &this->color_vbo);
glBindBuffer(GL_ARRAY_BUFFER, this->color_vbo);
glBufferData(GL_ARRAY_BUFFER, this->colors.size() * sizeof(float), &this->colors.front(), GL_STATIC_DRAW);
this->coord3d = glGetAttribLocation(this->shader.program, "coord3d");
this->mvp = glGetUniformLocation(this->shader.program, "mvp");
this->attrib_color = glGetAttribLocation(this->shader.program, "v_color");
glBindBuffer(GL_ARRAY_BUFFER, this->vbo);
glVertexAttribPointer(this->coord3d, // attribute
3, // number of elements per vertex, here (R,G,B)
GL_FLOAT, // the currentBlock of each element
GL_FALSE, // take our values as-is
0, // no extra data between each position
nullptr // offset of first element
);
glBindBuffer(GL_ARRAY_BUFFER, this->color_vbo);
glVertexAttribPointer(this->attrib_color,
3,
GL_FLOAT,
GL_FALSE,
0,
nullptr
);
glBindVertexArray(0);
glVertexAttrib3fv(this->attrib_color, this->colors.data());
std::printf("size of vector = %i\n", this->vertices.size());
return true;
}
else
{
std::printf("ERROR: COULDN'T OPEN FILE!\n");
return false;
}
return false;
}
void KikoBSP::render(glm::vec3 position)
{
glBindVertexArray(this->vao);
glEnableVertexAttribArray(this->coord3d);
glEnableVertexAttribArray(this->attrib_color);
glm::mat4 model = glm::translate(glm::mat4(1.0f), glm::vec3(position.x, position.y, position.z));
glm::mat4 mvp = game_manager->projection * game_manager->view * model;
glUniformMatrix4fv(this->mvp, 1, GL_FALSE, glm::value_ptr(mvp));
glDrawArrays(GL_LINES, 0, this->vertices.size());
glDisableVertexAttribArray(this->coord3d);
glDisableVertexAttribArray(this->attrib_color);
glBindVertexArray(0);
}
void KikoBSP::cleanup_map()
{
/* OUTDATED FUNCTION BACK WHEN I WAS MANUALLY MANAGING MEMORY */
}
However, the error goes away, when I take off these lines:
this->file.seekg(this->header.lumps[BSPLUMPS::EFFECTS].offset);
this->file.read(reinterpret_cast<char*>(effects.get()), this->header.lumps[BSPLUMPS::EFFECTS].length);
this->file.seekg(this->header.lumps[BSPLUMPS::FACES].offset);
this->file.read(reinterpret_cast<char*>(faces.get()), this->header.lumps[BSPLUMPS::FACES].length);
Which leads me to believe the Heap is overflowing with all the allocated memory.
I also believe this, because when I was manually managing memory. I ran into the same problem as well. So I switched to unique_ptrs, and I'm still getting the same problem! :(
Anyone here have any ideas? Thanks! :)
You've got incorrect loop condition:
for (int32_t x = 0; x <= this->num_vertexes; x++)
In its last iteration x == num_vertexes, which means you are trying to read the value beyond the array boundary. Check with the debugger - you'll see that x takes this value when the heap corruption happens. Also, I'm pretty sure it's not the line you've marked causing heap corruption, but the line before - many debuggers show the next line to be executed, not the one being executed.
BTW I'm not familiar with the classes you use and thus can't say for sure, but you're most likely abusing the use of std::unique_ptr. Just use std::vector instead of unique pointer to dynamic array - it's way simplier, easier to use and should work exactly the way you expect.

glBufferSubData has peaks with small buffer sizes

I am making a simple 2D game engine with OpenGL, and my SpriteRenderer class makes batches of sprites which use the same shader or texture. Once I sort them first by texture, then by shader, and then by depth, the uploadData() method of my SpriteRenderer class uploads the CPU generated vertex data to the GPU. For this I am using the orphaning method, which is said to be faster than a simple glBufferData call.
My problem is, when I have small numbers of sprites (<15), I have frames with huge stalls, but with numbers >20 up to 10 000 it runs smoothly. I wrapped opengl function into c++ classes. If I replace the VertexBufferObject::uploadOrphaned() method by the VertexBufferObject::upload() method, the stall goes away. Here is my vbo class:
//vbo.h
class VertexBufferObject
{
public:
VertexBufferObject();
VertexBufferObject(size_t allocSize);
~VertexBufferObject();
inline ui32 id(){ return (ui32)m_id; }
template <class T>
void addData(const T& data)
{
const byte* convertedData = reinterpret_cast<const byte*>(&data);
size_t size = sizeof(T);
for (ui32 i = 0; i < size; i++)m_data.add(convertedData[i]);
}
void initialize();
void resetData();
void upload(GLenum drawType);
void uploadOrphaned(GLenum drawType);
inline void bind() { ::glBindBuffer(GL_ARRAY_BUFFER, m_id); }
inline void unbind(){ ::glBindBuffer(GL_ARRAY_BUFFER, 0); }
private:
GLuint m_id;
//this is my custom dynamic array class, this is a hobby project
//and I enjoy reinventing the wheel :)
Array<byte> m_data;
and below is the cpp file:
VertexBufferObject::VertexBufferObject() :m_id(0)
{
}
VertexBufferObject::VertexBufferObject(size_t allocSize) : m_id(0), m_data(allocSize)
{
}
VertexBufferObject::~VertexBufferObject()
{
if (m_id != 0) ::glDeleteBuffers(1, &m_id);
}
void VertexBufferObject::initialize()
{
if (m_id == 0) ::glGenBuffers(1, &m_id);
}
void VertexBufferObject::upload(GLenum drawType)
{
glBufferData(GL_ARRAY_BUFFER, m_data.size(), &m_data[0], drawType);
}
void VertexBufferObject::uploadOrphaned(GLenum drawType)
{
glBufferData(GL_ARRAY_BUFFER, m_data.size() * 2, NULL, drawType);
glBufferSubData(GL_ARRAY_BUFFER, 0, m_data.size(), &m_data[0]);
}
void VertexBufferObject::resetData()
{
m_data.strip();
}
I am learning opengl, so my VertexBufferObject class contains what I already know. I know there are other methods to upload data, but I want to understand the reason of the current problem with this simple method. I looked around forums including here, and nobody had a similar issue that I found of. Maybe my class has some errors?

Importing and Displaying .fbx files in OpenGl

I have been trying to import and display an fbx file using the FBX SDK.Untill. I managed to load in the file, but I got stuck at the part where I have to display it.
The questions:
What exactly are those indices?
How should I display the vertices?
Here is the class that I made:
3dModelBasicStructs.h
struct vertex
{
float x,y,z;
};
struct texturecoords
{
float a,b;
};
struct poligon
{
int a,b,c;
};
Model.h
#ifndef MODEL_H
#define MODEL_H
#define FBXSDK_NEW_API
#define MAX_VERTICES 80000
#define MAX_POLIGONS 80000
#include <fbxsdk.h>
#include "3dModelBasicStructs.h"
#include <iostream>
#include <GL/glut.h>
using namespace std;
class Model
{
public:
Model(char*);
~Model();
void ShowDetails();
char* GetModelName();
void SetModelName( char* );
void GetFbxInfo( FbxNode* );
void RenderModel();
void InitializeVertexBuffer( vertex* );
private:
char Name[25];
vertex vertices[MAX_VERTICES];
poligon poligons[MAX_POLIGONS];
int *indices;
int numIndices;
int numVertices;
};
#endif
Model.cpp
#include "Model.h"
Model::Model(char *filename)
{
cout<<"\nA model has been built!";
numVertices=0;
numIndices=0;
FbxManager *manager = FbxManager::Create();
FbxIOSettings *ioSettings = FbxIOSettings::Create(manager, IOSROOT);
manager->SetIOSettings(ioSettings);
FbxImporter *importer=FbxImporter::Create(manager,"");
importer->Initialize(filename,-1,manager->GetIOSettings());
FbxScene *scene = FbxScene::Create(manager,"tempName");
importer->Import(scene);
importer->Destroy();
FbxNode* rootNode = scene->GetRootNode();
this->SetModelName(filename);
if(rootNode) { this->GetFbxInfo(rootNode); }
}
Model::~Model()
{
cout<<"\nA model has been destroied!";
}
void Model::ShowDetails()
{
cout<<"\nName:"<<Name;
cout<<"\nVertices Number:"<<numVertices;
cout<<"\nIndices which i never get:"<<indices;
}
char* Model::GetModelName()
{
return Name;
}
void Model::SetModelName(char *x)
{
strcpy(Name,x);
}
void Model::GetFbxInfo( FbxNode* Node )
{
int numKids = Node->GetChildCount();
FbxNode *childNode = 0;
for ( int i=0 ; i<numKids ; i++)
{
childNode = Node->GetChild(i);
FbxMesh *mesh = childNode->GetMesh();
if ( mesh != NULL)
{
//================= Get Vertices ====================================
int numVerts = mesh->GetControlPointsCount();
for ( int j=0; j<numVerts; j++)
{
FbxVector4 vert = mesh->GetControlPointAt(j);
vertices[numVertices].x=(float)vert.mData[0];
vertices[numVertices].y=(float)vert.mData[1];
vertices[numVertices++].z=(float)vert.mData[2];
cout<<"\n"<<vertices[numVertices-1].x<<" "<<vertices[numVertices- 1].y<<" "<<vertices[numVertices-1].z;
this->InitializeVertexBuffer(vertices);
}
//================= Get Indices ====================================
int *indices = mesh->GetPolygonVertices();
numIndices+=mesh->GetPolygonVertexCount();
}
this->GetFbxInfo(childNode);
}
}
void Model::RenderModel()
{
glDrawElements(GL_TRIANGLES,36,GL_INT,indices);
}
void Model::InitializeVertexBuffer(vertex *vertices)
{
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3,GL_FLOAT,0,vertices);
//glDrawArrays(GL_TRIANGLES,0,36);
}
Sadly , When i try to use drawelements i get this error:
Unhandled exception at 0x77e215de in A new begging.exe: 0xC0000005: Access violation reading location 0xcdcdcdcd.
2) How should I display the vertices?
Questions like these indicate, that you should work through some OpenGL tutorials. Those are the basics and you need to know them.
This is a good start regarding your problem, but you'll need to work through the whole tutorial
http://opengl.datenwolf.net/gltut/html/Basics/Tut01%20Following%20the%20Data.html
1) What exactly are those indices ?
You have a list of vertices. The index of a vertex is the position at which it is in that list. You can draw vertex arrays by its indices using glDrawElements
Update due to comment
Say you have a cube with shared vertices (uncommon in OpenGL, but I'm too lazy for writing down 24 vertices).
I have them in my program in an array, that forms a list of their positions. You load them from a file, I'm writing them a C array:
GLfloat vertices[3][] = {
{-1,-1, 1},
{ 1,-1, 1},
{ 1, 1, 1},
{-1, 1, 1},
{-1,-1,-1},
{ 1,-1,-1},
{ 1, 1,-1},
{-1, 1,-1},
};
This gives the vertices indices (position in the array), in the picture it looks like
To draw a cube we have to tell OpenGL in which vertices, in which order make a face. So let's have a look at the faces:
We're going to build that cube out of triangles. 3 consecutive indices make up a triangle. For the cube this is
GLuint face_indices[3][] = {
{0,1,2},{2,3,0},
{1,5,6},{6,2,1},
{5,4,7},{7,6,5},
{4,0,3},{3,7,4},
{3,2,6},{6,7,2},
{4,5,0},{1,0,5}
};
You can draw this then by pointing OpenGL to the vertex array
glVertexPointer(3, GL_FLOAT, 0, &vertices[0][0]);
and issuing a batches call on the array with vertices. There are 6*2 = 12 triangles, each triangle consisting of 3 vertices, which makes a list of 36 indices.
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, &face_indices[0][0]);

QGLBuffer and VBO

I have a problem with QGLBuffer. I'm trying to implement a dynamic VBO with QT + Opengl.
In the .h file
struct CVert {
float x;
float y;
};
...
typedef struct CVert CVert;
CVert* m_data;
QGLBuffer* m_bufferData;
int m_size;
in the .cpp
Constructor.
m_size = numberOfVertex;
m_bufferData = new QGLBuffer(QGLBuffer::VertexBuffer);
m_bufferData->create();
m_bufferData->bind();
m_bufferData->setUsagePattern(QGLBuffer::DynamicDraw);
m_bufferData->allocate(2*sizeof(float)* p_size);
m_data = (CVert*)m_bufferData->map (QGLBuffer::ReadWrite);
In the execution of the program I change some m_data values
m_data[pos].x = X1
m_data[pos].y = y1
In the draw method.
glEnableClientState(GL_VERTEX_ARRAY);
if (m_bufferData->bind ()) {
glVertexPointer( 2, GL_FLOAT, 0, (char *) NULL );;
glDrawArrays( GL_LINES, 0,m_size );
glDisableClientState(GL_VERTEX_ARRAY);
}
But nothig it's being drawn.
I've checked that m_data is not null, and m_bufferData->bind() returns true.
What am I doing wrong?
I think i've solved. Every time i've to edit the VBO.
I have to
m_data = (CVert*)data->map (QGLBuffer::ReadWrite);
m_data[pos].x = X1;
m_data[pos].y = y1
data->unmap ();
it's doesn't work if I map only once in the constructor

Access Violation when writing to pointer variables in dynamically allocated classes

Ok so the title doesn't explain my situation very well so I'll try to explain a little better here:
Here is part of my class structure:
ObjectView (abstract class)
ShipView : ObjectView (child of object view)
In a method I create a new ShipView:
ShipView *shipview (in header file).
shipview = new ShipView(in main part of code).
I then run shipview->Initialise();
to set everything up in the new class.
But when I get to any lines of code that try to write to a pointer declared in the ObjectView class it won't allow me to do so and gives me an Access Violation message.
The message that I get is below:
"Unhandled exception at 0x00a0cf1c in AsteroidGame.exe: 0xC0000005: Access violation writing location 0xbaadf011."
For example this line:
_ObjectData = new Model[mesh->mNumVertices];
will give me the error.
Just fyi I have put this in the header file:
struct Model{
GLfloat x,y,z;
GLfloat nX,nY,nZ;
GLfloat u,v;
};
Model *_ObjectData;
However if I was to do something along the lines of
Model *_ObjectData = new Model[mesh->mNumVertices];
(declare and initialise all at once)
it would work....
It's like it doesn't know the header file is there, or the class has not been properly constructed therefore the memory has not been allocated properly.
Any help would be greatly appreciated.
EDIT
Header File:
class ObjectView
{
public:
ObjectView(void);
virtual ~ObjectView(void);
void Initialise(std::string objectpath, std::string texturepath);
void InitialiseVBO(const aiScene* sc);
void RenderObject();
virtual void ScaleObject() = 0;
virtual void TranslateObject() = 0;
virtual void RotateObject() = 0;
protected:
struct Model{
GLfloat x,y,z;
GLfloat nX,nY,nZ;
GLfloat u,v;
};
Model *_ObjectData;
struct Indices{
GLuint x,y,z;
};
Indices *_IndicesData;
TextureLoader _textureloader;
GLuint _objectTexture;
GLuint _objectVBO;
GLuint _indicesVBO;
int _numOfIndices;
};
Code:
void ObjectView::InitialiseVBO(const aiScene* sc)
{
const aiMesh* mesh = sc->mMeshes[0];
_ObjectData = new Model[mesh->mNumVertices];
for(unsigned int i = 0; i < mesh->mNumVertices; i++)
{
_ObjectData[i].x = mesh->mVertices[i].x;
_ObjectData[i].y = mesh->mVertices[i].y;
_ObjectData[i].z = mesh->mVertices[i].z;
_ObjectData[i].nX = mesh->mNormals[i].x;
_ObjectData[i].nY = mesh->mNormals[i].y;
_ObjectData[i].nZ = mesh->mNormals[i].z;
_ObjectData[i].u = mesh->mTextureCoords[0][i].x;
_ObjectData[i].v = 1-mesh->mTextureCoords[0][i].y;
}
glGenBuffers(1, &_objectVBO);
glBindBuffer(GL_ARRAY_BUFFER, _objectVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(Model) * mesh->mNumVertices, &_ObjectData[0].x, GL_STATIC_DRAW);
_IndicesData = new Indices[mesh->mNumFaces];
for(unsigned int i = 0; i < mesh->mNumFaces; ++i)
{
for (unsigned int a = 0; a < 3; ++a)
{
unsigned int temp = mesh->mFaces[i].mIndices[a];
if(a == 0)
_IndicesData[i].x = temp;
else if(a == 1)
_IndicesData[i].y = temp;
else
_IndicesData[i].z = temp;
}
}
glGenBuffers(1, &_indicesVBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indicesVBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices) * mesh->mNumFaces, _IndicesData, GL_STATIC_DRAW);
_numOfIndices = sizeof(Indices) * mesh->mNumFaces;
glBindBuffer(GL_ARRAY_BUFFER, 0);
delete _ObjectData;
delete _IndicesData;
}
If
_ObjectData = new Model[mesh->mNumVertices];
crashes while
Model *_ObjectData = new Model[mesh->mNumVertices];
doesn't, it certainly looks like your object hasn't been initialized.
My psychic debugger suggests that you have declared a different variable, also called shipview, which is what you're calling Initialize() on.
0xbaadf011 is probably an offset from 0xbaadf00d which is a hexadecimal synonym for Bad Food. It is certainly an uninitialized pointer.
You are obviously not setting your pointers before using them. I suggest looking at the call stack when it crashes, set a breakpoint at one of the functions above your crash, then restart the program and run it line by line until you find the pointer that is set to 0xbaadf011 or 0xbaadf00d. Then figure out where you were supposed to set that pointer.