I'm trying to load a model into my project and I get an exception at glDrawElements.
I read the model file (.nfg), and retain the vertices and indices into vectors, and I use Vertex Buffer Object to bind my model.
I tried this:
I modified the fourth parameter from (GLvoid*)(sizeof(Vector3) * x)
to (GLvoid*)(offset(Vertex, attribute)), but didn't do anything (in the link, the problem was that he was sending memory address in the 4th parameter, and I thought maybe I was sending the wrong parameter to the wrong attribute, which still, would be a problem when actually showing the model).
I'm using OpenGL ES 2.0 and I'm not doing this project for neither Android or iOS; currently working in Visual Studio 2013 on Windows 8.1
The model loader:
void loadModelNfg(const std::string &filename,
GLuint &vbo, GLuint &ibo, GLuint &num, Shaders shaders){
// put here the verteces and indices from the file
std::vector<Vertex> vertices;
std::vector<GLushort> indices;
_loadModelNfg(filename, vertices, indices);
std::cout << "Mesh Loader: loaded file: " << filename << "\n";
// creates OpenGL objects necessary for drawing
GLuint gl_vertex_buffer_object, gl_index_buffer_object;
// vertex buffer object -> object in which to keep the vertices
glGenBuffers(1, &gl_vertex_buffer_object);
glBindBuffer(GL_ARRAY_BUFFER, gl_vertex_buffer_object);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex),
&vertices[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
// index buffer object -> object in which to keep the indices
glGenBuffers(1, &gl_index_buffer_object);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gl_index_buffer_object);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLushort),
&indices[0], GL_STATIC_DRAW);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
vbo = gl_vertex_buffer_object;
ibo = gl_index_buffer_object;
num = indices.size();
}
Calling the previous function:
// for now, global variables:
GLuint vbo, ibo, num;
Shader myShaders;
int Init ( ESContext* esContext ) {
glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
// this one works: tried with a triangle
int ret = myShaders.Init("../Resources/Shaders/TriangleShaderVS.vs",
"../Resources/Shaders/TriangleShaderFS.fs");
if (ret == 0)
loadModelNfg("../../ResourcesPacket/Models/Bila.nfg", vbo, ibo, num, myShaders);
return ret;
}
Drawing the model:
void Draw(ESContext* esContext) {
Matrix world;
world.SetIdentity();
Matrix view = c.getView();
Matrix persp = c.getPerspective();
Matrix trans = world * view *persp;
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(myShaders.program);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
if (myShaders.positionAttribute != -1) {
glEnableVertexAttribArray(myShaders.positionAttribute);
glVertexAttribPointer(myShaders.positionAttribute, 3, GL_FLOAT,
GL_FALSE, sizeof(Vertex), (GLvoid*)(offsetof(Vertex, pos)));
}
if (myShaders.normalAttribute != -1) {
glEnableVertexAttribArray(myShaders.normalAttribute);
glVertexAttribPointer(myShaders.normalAttribute, 3, GL_FLOAT,
GL_FALSE, sizeof(Vertex), (GLvoid*)(offsetof(Vertex, norm)));
}
if (myShaders.binormalAttribute != -1) {
glEnableVertexAttribArray(myShaders.binormalAttribute);
glVertexAttribPointer(myShaders.binormalAttribute, 3, GL_FLOAT,
GL_FALSE, sizeof(Vertex), (GLvoid*)(offsetof(Vertex, binorm)));
}
if (myShaders.tangentAttribute != -1) {
glEnableVertexAttribArray(myShaders.tangentAttribute);
glVertexAttribPointer(myShaders.tangentAttribute, 3, GL_FLOAT,
GL_FALSE, sizeof(Vertex), (GLvoid*)(offsetof(Vertex, tgt)));
}
if (myShaders.texcoordAttribute != -1) {
glEnableVertexAttribArray(myShaders.texcoordAttribute);
glVertexAttribPointer(myShaders.texcoordAttribute, 2, GL_FLOAT,
GL_FALSE, sizeof(Vertex), (GLvoid*)(offsetof(Vertex, uv)));
}
if (myShaders.colorAttribute != -1) {
glEnableVertexAttribArray(myShaders.colorAttribute);
glVertexAttribPointer(myShaders.colorAttribute, 3, GL_FLOAT,
GL_FALSE, sizeof(Vertex), (GLvoid*)(offsetof(Vertex, col)));
}
if (myShaders.MVPuniform != -1) {
glUniformMatrix4fv(myShaders.MVPuniform, 1, GL_FALSE, (GLfloat*) trans.m);
}
// HERE GETS EXCEPTION
glDrawElements(GL_TRIANGLES, num, GL_UNSIGNED_SHORT, (GLvoid*) 0);
eglSwapBuffers (esContext->eglDisplay, esContext->eglSurface);
}
I am not sure that I am correctly binding the buffers in the loadModelNfg() function.
From what can this problem come and how can it be resolved?
EDIT:
GL_VENDOR: Imagination Technologies (Host GL: 'Intel');
GL_RENDERER: PowerVR PVRVFrame 4.2SGX 530 (Host 'Intel(R) HD Graphics 400');
GL_VERSION: OpenGL ES 2.0 (SDK build: 2.04.24.0809)
EDIT:
I surrounded the function with try-catch statement, but it still breaks when calling it:
try {
glDrawElements(GL_TRIANGLES, num, GL_UNSIGNED_SHORT, (GLvoid*)0);
}
catch (const std::exception& e) {
std::cout << e.what() << "\n";
}
I forgot to mention that the project/solution builds successful (after cleaning, or by rebuild).
After learning that OpenGL doesn't throw exceptions, I started looking how it handles errors. I found out that it "returns" error codes (or 0 if success), which can be found with glGetError().
Going withglGetError() through the code, I found out that the error was caused by glUseProgram(myShaders.program);.
Knowing that, I went through the functions which used myShaders variable, and I found that, after calling loadModelNfg("../../ResourcesPacket/Models/Bila.nfg", vbo, ibo, num, myShaders);, the variable got change.
Remembering that I don't use it anymore, I just removed it, and everything was fine.
What is strange is that I didn't modified the myShaders variable anywhere in that function (the code in the question is the final one). The problem, I think, is that I didn't declared the parameter const Shaders shaders.
So, the conclusion:
use glGetError() and breakpoints in code to find the real problem. It may not be the where it breaks!
PS: I hope it's ok that I put this as an answer. If it's not, I'll update the question.
Related
I'm trying to load and render a 3D model i exported from blender to 3ds format.
I'm using Assimp to load the model and OpenGL (GLEW) to render it. for some reason some. in some of the models only parts of the model gets rendered.
for some this can be fixed by selecting all objects in blender and clicking join. But for others this does not solve the problem.
Here is the code Im using to load the models in:
(all of the "Array"s here are std::vector)
void Mesh::recursiveProcess(aiNode* node,const aiScene* scene) {
for(int i=0;i<node->mNumMeshes;i++) {
aiMesh* mesh=scene->mMeshes[node->mMeshes[i]];
processMesh(mesh, scene);
}
for(int i=0;i<node->mNumChildren;i++) {
recursiveProcess(node->mChildren[i], scene);
}
}
void Mesh::processMesh(aiMesh* m,const aiScene* scene) {
for(int i=0;i<m->mNumVertices;i++) {
vertexArray.push_back(m->mVertices[i].x);
vertexArray.push_back(m->mVertices[i].y);
vertexArray.push_back(m->mVertices[i].z);
if(m->mNormals!=NULL) {
normalArray.push_back(m->mNormals[i].x);
normalArray.push_back(m->mNormals[i].y);
normalArray.push_back(m->mNormals[i].z);
}
if(m->mTextureCoords[0]!=NULL) {
uvArray.push_back(m->mTextureCoords[0][i].x);
uvArray.push_back(m->mTextureCoords[0][i].y);
}
if(m->mTangents!=NULL) {
tangentArray.push_back(m->mTangents[i].x);
tangentArray.push_back(m->mTangents[i].y);
tangentArray.push_back(m->mTangents[i].z);
}
}
for(int i=0;i<m->mNumFaces;i++) {
aiFace face=m->mFaces[i];
for(int j=0;j<face.mNumIndices;j++) {
indexArray.push_back(face.mIndices[j]);
}
}
}
void Mesh::Load(string path) {
vertexArray.clear();
indexArray.clear();
normalArray.clear();
uvArray.clear();
tangentArray.clear();
const aiScene* scene=aiImportFile(path.c_str(),
aiProcess_GenSmoothNormals |
aiProcess_CalcTangentSpace |
aiProcess_Triangulate |
aiProcess_FindInvalidData);
const char* err = aiGetErrorString();
if(err!=NULL&&sizeof(err) > 4 && scene==NULL) {
cout << "The file wasn't successfuly opened " << path << " Because " << err;
return;
}
recursiveProcess(scene->mRootNode,scene);
if(uvArray.size()==0) uvArray.push_back(0);
if(normalArray.size()==0) normalArray.push_back(0);
if(tangentArray.size()==0) tangentArray.push_back(0);
}
and here is how I'm rendering them;
first i create the buffers. i do this once
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, vertexArray.size() * sizeof(float), vertexArray.data(), GL_STATIC_DRAW);
glGenBuffers(1, &indexbuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexbuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexArray.size() * sizeof(unsigned int), indexArray.data(), GL_STATIC_DRAW);
glGenBuffers(1, &uvbuffer);
glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
glBufferData(GL_ARRAY_BUFFER, uvArray.size() * sizeof(float), uvArray.data(), GL_STATIC_DRAW);
then I execute this in the main render loop
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glEnable(GL_CULL_FACE);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), (void*)0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2*sizeof(float), (void*)0);
camera.Update();
mvp = camera.getProjection() * camera.getView() * Model;
shader.SetUniformLocationMatrix4fv("MVP", &mvp[0][0]);
glBindTexture(GL_TEXTURE_2D, akm_tex);
glUseProgram(shader);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexbuffer);
glDrawElements(
GL_TRIANGLES, // mode
indexArray.size(), // count
GL_UNSIGNED_INT, // type
(void*)0 // element array buffer offset
);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
here is how a model looks like in my program:
and here is how it look in blender
You missed to apply the transformations of the nodes to the vertex buffers you are rendering. Each assimp-node stores a local transformation which need to get applied to all its assigned meshes.
You can introduce in your shader a uniform-variable to represent the global transformation for the vertices. During rendering you need to multiply the local transformation with the global transformation and apply it via this uniform matrix.
Or you can just use glPushMAtrix and glPopMatrix and apply the local transformation of your current node as you can see here (recursive_render)
I'm trying to make a small application that loads and renders a model on iOS using assimp and GL ES. I've worked with OpenGL before but not GL ES; and never anything on iOS.
Currently I'm getting a EXC_BAD_ACCESS error upon calling glDrawElements; and I can't see what I'm doing wrong.
This is my Vertex type:
typedef struct {
float Position[3];
} Vertex;
And this is my Mesh type:
class Mesh {
public:
Vertex* vertices;
GLuint verticesCount;
GLubyte* indices;
GLuint indicesCount;
std::vector<Texture> textures;
GLuint vertexBuffer, indexBuffer;
Mesh(Vertex* vertices, GLubyte* indices, std::vector<Texture> textures);
};
I am pretty confident that I'm loading the models correctly through assimp as I've done it before and lifted this code from another project. So I'm using that data to pass into Mesh constructor and I am populating the VBO's using this:
glGenBuffers(1, &this->vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, this->vertexBuffer);
int sizeOfVerts = sizeof(Vertex) * this->verticesCount;
std::cout << "Size of verts in bytes " << unsigned(sizeOfVerts) << std::endl;
glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)sizeOfVerts, &this->vertices[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glGenBuffers(1, &this->indexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->indexBuffer);
int sizeOfInd = sizeof(GLubyte) * this->indicesCount;
std::cout << "Size of inds in bytes " << unsigned(sizeOfInd) << std::endl;
glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)sizeOfInd, &this->indices[0], GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
With the projection and view model matricies already set up in a pre-render function I am then calling this to render my meshes:
- (void)renderMesh:(Mesh*)mesh
{
glBindBuffer(GL_ARRAY_BUFFER, mesh->vertexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->indexBuffer);
glVertexAttribPointer(_positionSlot, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
int meshSize = mesh->indicesCount;
glDrawElements(GL_TRIANGLES, meshSize, GL_UNSIGNED_BYTE, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
With _positionSlot being an attrib location in my shader. I know my shader works as I have already used it to draw boring squared and such - so the error is definitely in the above code - somewhere.
Thanks in advance guys, I'll make sure I both upvote and accept :)
The reason this was happening is because I was using GLubyte for the Indices type; which is too small for my high poly model. Not sure why the error manifested itself with this error message though; on other platforms the same code would render a junk model. Perhaps iOS specific? Hopefully this can help someone else.
I have a sprite class to handle initializing a sprite and drawing it but i keep getting this error Exception thrown at 0x68ECC760 (nvoglv32.dll) this seems to be mainly because of _vboID and _vertNum I'm not exactly sure what is wrong with them though, here's the source code for it
void Sprite::init(int vertNum, float r, Shape shape) {
_vertNum = vertNum;
if (_vboID = 0) {
glGenBuffers(1, &_vboID);
}
std::vector<Vertex> vertexData(vertNum);
if (shape == Shape::CIRCLE) {
for (int i = 0; i < vertNum; i++) {
vertexData[i].setPosition(r*cos(i), r*sin(i));
}
}
for (int i = 0; i < _vertNum; i++) {
vertexData[i].setColor(1, 1, 1, 1);
}
glBindBuffer(GL_VERTEX_ARRAY, _vboID);
glBufferData(GL_VERTEX_ARRAY, sizeof(vertexData), vertexData.data(), GL_DYNAMIC_DRAW);
glBindBuffer(GL_VERTEX_ARRAY, 0);
}
void Sprite::draw() {
//bind buffer array
glBindBuffer(GL_VERTEX_ARRAY, _vboID);
//use first vertex attrib array
glEnableVertexAttribArray(0);
//pointer to vertices location
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, position));
//pointer to vertices color
glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, color));
//Draw the 6 vertices to the screen
glDrawArrays(GL_POLYGON, 0, _vertNum);
//Disable the vertex attrib array. This is not optional.
glDisableVertexAttribArray(0);
//Unbind the VBO
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
GL_VERTEX_ARRAY is not a valid buffer binding target. What you are looking for is GL_ARRAY_BUFFER.
When you use GL_VERTEX_ARRAY in contexts where a buffer binding target is expected, you should only get a GL_INVALID_ENUM error, and the calls will have no further effect. As a result, you have no GL_ARRAY_BUFFER bound during your glVertexAttribPointer call, which in a legacy or core profile will result the GL in interpreting your pointers as pointers to client memory.
You should really add some error checks, or use a debug callback, so that such simple mistakes can be spotted early.
I've been trying to use Vertex Buffer Objects to save vertex data on the GPU and reduce the overhead, but I cannot get it to work. The code is below.
From what I understand you generate the buffer with glGenBuffers, then you bind the buffer with glBindBuffer so it's ready to be used, then you write data to it with glBufferData and its done and can be unbinded and ready for use later with simply binding it again.
However the last part is what I'm having trouble with, when I bind it after I have created and loaded data to it and try to draw using it, it gives me lots of GL Error: Out of Memory.
I doubt that I am running out of memory for my simple mesh, so I must be doing something very wrong.
Thanks.
EDIT 1: I call glGetError after every frame, but since this is the only OpenGL I do in the entire program it shouldn't be a problem
//when loading the mesh we create the VBO
void createBuffer()
{
GLuint buf;
glGenBuffers(1, &buf);
glBindBuffer(GL_ARRAY_BUFFER, buf);
glBufferData(GL_ARRAY_BUFFER, vertNormalBuffer->size() * sizeof(GLfloat), (GLvoid*) bufferData, GL_STATIC_DRAW);
//EDIT 1: forgot to show how I handle the buffer
model->vertexNormalBuffer = &buf;
//Unbinds it
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void Fighter::doRedraw(GLuint shaderProgram)
{
glm::mat4 transformationMatrix = getTransform();
GLuint loc = glGetUniformLocation(shaderProgram,"modelviewMatrix");
glUniformMatrix4fv(loc, 1, GL_FALSE, (GLfloat*) &transformationMatrix);
glBindBuffer(GL_ARRAY_BUFFER, *model->vertexNormalBuffer);
//If I uncomment this line below all works wonderfully, but isnt the purpose of VBO of not uploading the same data again and again?
//glBufferData(GL_ARRAY_BUFFER, model->vertAndNormalArraySize * sizeof(GLfloat), model->vertAndNormalArray, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(2);
renderChild(model, model);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void Fighter::renderChild(ModelObject* model, ModelObject* parent)
{
//Recursively render the mesh children
for(int i = 0; i < model->nChildren; i++)
{
renderChild( dynamic_cast<ModelObject*>(model->children[i]), parent);
}
//Vertex and normal data are interlieved
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat),(void*)(model- >vertexDataPosition*sizeof(GLfloat)));
glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (void*)((model->vertexDataPosition + 4)*sizeof(GLfloat)));
//Draws using two sets of indices
glDrawElements(GL_QUADS, model->nQuads * 4, GL_UNSIGNED_INT,(void*) model->quadsIndices);
glDrawElements(GL_TRIANGLES, model->nTriangles * 3, GL_UNSIGNED_INT, (void*) model->trisIndices);
}
This is your problem:
model->vertexNormalBuffer = &buf;
/* ... */
glBindBuffer(GL_ARRAY_BUFFER, *model->vertexNormalBuffer);
You're storing the address of your buf variable, rather than its contents, and then it falls out of scope when createBuffer returns, and is most likely overwritten with other data, so when you're later rendering, you're using an uninitialized buffer. Just store the contents of buf in your vertexNormalBuffer field instead.
I'll admit I don't know why OpenGL thinks it proper to say that it's "out of memory" just because of that, but perhaps you're just invoking undefined behavior. It does explain, however, why it starts working when you re-fill the buffer with data after you rebind it, because you then implicitly initialize the buffer that you just bound.
I have the following pieces of code where I successfully create a vertex buffer object, initialize it with data, and render it using GLSL 4.0. However, when I go to update the data stored in the vertices after animation, OpenGL gives me the error code 0x502 and does not accept my updated vertices information.
Could someone point me in the direction as to why these code does not allow my vertices information to be successfully updated? I should also mention that sometimes, the data is successfully updated with is not always consistent/predictable.
Data Structure used
struct Vertex3{
glm::vec3 vtx; //0
glm::vec3 norm; //3
glm::vec3 tex; //6 Use for texturing or color
};
vector<Vertex3> geometry.vertices3;
Initialization Code
void solidus::Mesh::initVBO(){
geometry.totalVertexCount = geometry.getVertexCount();
// Allocate an OpenGL vertex array object.
glGenVertexArrays(1, &vertexArrayId);
glGenBuffers(2,geometry.vboObjects);
// Bind the vertex array object to store all the buffers and vertex attributes we create here.
glBindVertexArray(vertexArrayId);
glBindBuffer(GL_ARRAY_BUFFER, geometry.vboObjects[VERTEX_DATA]);
//size the size of the total vtx
GLuint byte_size = getTotalSize();
//Reserve the inital space for the vertex data
glBufferData(GL_ARRAY_BUFFER, byte_size, NULL, GL_STREAM_DRAW);
if(geometry.isStructVertex4())
initVBO4( );
else if(geometry.isStructVertex3())
initVBO3( );
else
initVBO2( );
//release
glBindVertexArray(0);
geometry.vertices4.clear();
//geometry.vertices3.clear();
geometry.vertices2.clear();
}
void solidus::Mesh::initVBO3( ){
//getTotalSize() == getVtxCount() * sizeof(Vertex3);
glBufferSubData(GL_ARRAY_BUFFER, 0, getTotalSize(), &geometry.vertices3[0]);
//Note: offsetof -- c++ standard library
//Note: glVertexAttribPointer- first parameter is location of GLSL variable
glEnableVertexAttribArray(0); // Vertex4 position
glVertexAttribPointer( (GLuint)0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex3), (GLvoid*)offsetof(Vertex3,vtx) );
// Vertex4 normal
glEnableVertexAttribArray(1);
glVertexAttribPointer( (GLuint)1, 3, GL_FLOAT, GL_TRUE, sizeof(Vertex3), (GLvoid*)offsetof(Vertex3,norm) );
// Texture coords
glEnableVertexAttribArray(2);
glVertexAttribPointer( (GLuint)2, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex3),(GLvoid*)offsetof(Vertex3,tex) );
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, geometry.vboObjects[INDEX_DATA]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*geometry.indices.size(), &geometry.indices[0], GL_STATIC_DRAW);
}
Update the Mesh Vertex information why does this fail
void solidus::Mesh::uploadVertexGLFx(){
glBindBuffer(GL_ARRAY_BUFFER, geometry.vboObjects[VERTEX_DATA]);
string e0="";
if(geometry.isStructVertex2()){
solidus::GLVBO::setVBOSubData(getTotalSize (), &geometry.vertices2[0]);
e0="Vertex2";
}else if(geometry.isStructVertex3()){
//THIS IS THE POINT OF INTEREST: at least suspected!!!!!
// getVtxCount() * sizeof(Vertex3) = getTotalSize
glBufferSubData(GL_ARRAY_BUFFER, 0, getTotalSize (), &geometry.vertices3[0]);
e0="Vertex3";
}else {
solidus::GLVBO::setVBOSubData(getTotalSize (), &geometry.vertices4[0]);
e0="Vertex4";
}
//report error is glGetError is not equal to 0
postMsg("failed to upload vertex for struct " + e0 , "uploadVertexGLFx",30);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
I modified my updateVertexGLFx function to the code listed below. The main difference with this good is that after I resupplied the vertices information to GL, I informed OpenGL of the pointer offset using gl*AtribPointer. Now the program reliably updates when I call my update function.
void solidus::Mesh::uploadVertexGLFx(){
glBindBuffer(GL_ARRAY_BUFFER, geometry.vboObjects[VERTEX_DATA]);
string e0="";
if(geometry.isStructVertex2()){
solidus::GLVBO::setVBOSubData(getTotalSize (), &geometry.vertices2[0]);
e0="Vertex2";
}else if(geometry.isStructVertex3()){
//glBufferData(GL_ARRAY_BUFFER, getTotalSize (), NULL, GL_STREAM_DRAW);
//THIS IS THE POINT OF INTEREST: at least suspected!!!!!
// getVtxCount() * sizeof(Vertex3) = getTotalSize
cout << "Total Size = " << getTotalSize() <<endl;
cout << "Vtx Count = " << getVtxCount() << endl;
cout << "Sizeof(Vertex3)=" <<sizeof(Vertex3)<<endl;
Vertex3 *f = new Vertex3[getVtxCount()];
for(int i=0; i<getVtxCount();i++){
f[i] = geometry.vertices3[i];
}
glBufferData(GL_ARRAY_BUFFER, getTotalSize(), NULL, GL_STREAM_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, getTotalSize (), f);
//Note: glVertexAttribPointer- first parameter is location of GLSL variable
glEnableVertexAttribArray(0); // Vertex4 position
glVertexAttribPointer( (GLuint)0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex3), (GLvoid*)offsetof(Vertex3,vtx) );
// Vertex4 normal
glEnableVertexAttribArray(1);
glVertexAttribPointer( (GLuint)1, 3, GL_FLOAT, GL_TRUE, sizeof(Vertex3), (GLvoid*)offsetof(Vertex3,norm) );
// Texture coords
glEnableVertexAttribArray(2);
glVertexAttribPointer( (GLuint)2, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex3),(GLvoid*)offsetof(Vertex3,tex) );
delete f;
f = nullptr;
e0="Vertex3";
}else {
solidus::GLVBO::setVBOSubData(getTotalSize (), &geometry.vertices4[0]);
e0="Vertex4";
}
//report error is glGetError is not equal to 0
postMsg("failed to upload vertex for struct " + e0 , "uploadVertexGLFx",30);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}