PDA

View Full Version : Messed up VBO model loading code through lib3ds



Quaver
07-31-2013, 09:59 AM
I created a simple 3DSMax object of two spheres to test the lib3ds library, this is how it looks:

http://s22.postimg.org/w115tn9jl/3_DSMax.png

I struggled to find resources for how to load a lib3ds file into a VBO for OpenGL but I eventually managed to conjure up the following code:

model.h:

#include <stdlib.h>
#include <string.h>
#include <gl/gl.h>
#include "../lib/lib3ds/lib3ds.h"

typedef struct {
Lib3dsFile *file;
unsigned int faceCount;
GLuint vertices;
GLuint normalVertices;
} TModel;

extern TModel playerModel;

short loadModel(TModel *model, char *filename);

model.c:

#include <gl/gl.h>
#include "../lib/glext.h"

#include "model.h"

#include "init.h"

TModel playerModel;

short loadModel(TModel *model, char *filename) {
model->file = (Lib3dsFile*)lib3ds_file_open(filename);
if(!model->file) return 0;

{
unsigned int i;
for(i = 0; i < model->file->nmeshes; i++) {
model->faceCount += model->file->meshes[i]->nfaces;
}
}

{
size_t malloced = 0;

float (*vertices)[3];
float (*normals)[3];

vertices = (float(*)[3])malloc(sizeof(float) * 9 * model->faceCount);
if(vertices == NULL) return 0;

normals = (float(*)[3])malloc(sizeof(float) * 9 * model->faceCount);
if(normals == NULL) return 0;

unsigned int i, j;
for(i = 0; i < model->file->nmeshes; i++) {
/*float (*vertices)[3];
vertices = (float(*)[3])malloc(sizeof(float) * 3 * model->file->meshes[i]->nvertices);
float (*normals)[3];
normals = (float(*)[3])malloc(sizeof(float) * 9 * model->file->meshes[i]->nfaces);*/
lib3ds_mesh_calculate_vertex_normals(model->file->meshes[i], normals + malloced / sizeof(float));
for(j = 0; j < model->file->meshes[i]->nfaces; j++) {
memcpy(vertices + malloced, model->file->meshes[i]->vertices, sizeof(float) * 3 * model->file->meshes[i]->nvertices);
}
malloced += sizeof(float) * 3 * model->file->meshes[i]->nvertices;
}
glGenBuffers(1, &model->vertices);
glBindBuffer(GL_ARRAY_BUFFER, model->vertices);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 9 * /* faces */ model->faceCount, vertices, GL_STATIC_DRAW);

glGenBuffers(1, &model->normalVertices);
glBindBuffer(GL_ARRAY_BUFFER, model->normalVertices);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 9 * model->faceCount, normals, GL_STATIC_DRAW);

free(vertices);
free(normals);
}

lib3ds_file_free(model->file);
model->file = NULL;

return 1;
}


Then I load it like this:

loadModel(&playerModel, "models/player.3ds");

Here is the code I use to display it:

glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, playerModel.normalVertices);
glNormalPointer(GL_FLOAT, 0, NULL);
glVertexPointer(3, GL_FLOAT, 0, NULL);
glDrawArrays(GL_TRIANGLES, 0, playerModel.faceCount * 3);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);

And this is how it renders in my application:

http://s13.postimg.org/bvtbo88tj/VBORender.png

Any ideas as to what's wrong?

malexander
07-31-2013, 10:44 AM
At a glance, you're missing the



glBindBuffer(GL_ARRAY_BUFFER, playerModel.vertices);

Before the glVertexPointer() call. Also the glEnableClientState() calls are not necessary with VBOs, but that shouldn't break anything.

Quaver
07-31-2013, 10:57 AM
Thanks for your help. Using this code to draw the object:


glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, playerModel.normalVertices);
glNormalPointer(GL_FLOAT, 0, NULL);
glBindBuffer(GL_ARRAY_BUFFER, playerModel.vertices);
glVertexPointer(3, GL_FLOAT, 0, NULL);
glDrawArrays(GL_TRIANGLES, 0, playerModel.faceCount * 3);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);

It now looks like this:

http://s24.postimg.org/z956nmrud/VBORender2.png

So I'm sure it must be something with my loadModel function.

Quaver
08-01-2013, 03:12 AM
I added a memset 0 to vertices and normals like so:


vertices = (float(*)[3])malloc(sizeof(float) * 9 * model->faceCount);
if(vertices == NULL) return 0;
memset(vertices, 0, sizeof(float) * 9 * model->faceCount);

normals = (float(*)[3])malloc(sizeof(float) * 9 * model->faceCount);
if(normals == NULL) return 0;
memset(normals, 0, sizeof(float) * 9 * model->faceCount);

Same result as before.

Quaver
08-07-2013, 08:36 AM
I replaced my previous model with a simple cube, and am getting this:

http://s24.postimg.org/gdnrbf8yd/cube.png

Maybe I'm missing something, it seems that it's got the right size, but wrong locations.

Quaver
08-11-2013, 12:42 PM
* BUMP *

Is there maybe another forum I should post this on?