PDA

View Full Version : I am looking for loader obj with mtl



mairan21
01-10-2015, 06:39 AM
I am looking for loader obj with mtl, i have loader obj but this loader does not support textures in .mtl.
My loader obj.


GLuint LoadObj(char * file) {

FILE * fp = fopen(file, "r");

if (fp == NULL) {
printf("ERROR: Cannot read model file \"%s\".\n", file);
return -1;
}

std::vector<vec3> * v = new std::vector<vec3>();
std::vector<vec3> * n = new std::vector<vec3>();
std::vector<vec3> * t = new std::vector<vec3>();
std::vector<SFace> * f = new std::vector<SFace>();

char buf[128];

while (fgets(buf, 128, fp) != NULL) {
if (buf[0] == 'v' && buf[1] == ' ') {
vec3 * vertex = new vec3();
sscanf(buf, "v %f %f %f", &vertex->x, &vertex->y, &vertex->z);
v->push_back(*vertex);
}
if (buf[0] == 'v' && buf[1] == 't') {
vec3 * vertex = new vec3();
sscanf(buf, "vt %f %f", &vertex->x, &vertex->y);
t->push_back(*vertex);
}
if (buf[0] == 'v' && buf[1] == 'n') {
vec3 * vertex = new vec3();
sscanf(buf, "vn %f %f %f", &vertex->x, &vertex->y, &vertex->z);
n->push_back(*vertex);
}
if (buf[0] == 'f' && buf[1] == ' ') {
SFace * face = new SFace();
sscanf(buf, "f %d/%d/%d %d/%d/%d %d/%d/%d",
&face->v[0], &face->t[0], &face->n[0],
&face->v[1], &face->t[1], &face->n[1],
&face->v[2], &face->t[2], &face->n[2]
);
f->push_back(*face);
}
}

fclose(fp);

GLuint dlId;
dlId = glGenLists(1);
glNewList(dlId, GL_COMPILE);
glBegin(GL_TRIANGLES);
for (int i = 0; i < f->size(); ++i) {
for (int j = 0; j < 3; ++j) {
vec3 * cv = &(*v)[((*f)[i].v[j] - 1)];
vec3 * ct = &(*t)[((*f)[i].t[j] - 1)];
vec3 * cn = &(*n)[((*f)[i].n[j] - 1)];
glTexCoord2f(ct->x, ct->y);
glNormal3f(cn->x, cn->y, cn->z);
glVertex3f(cv->x, cv->y, cv->z);
}
}
glEnd();
glEndList();

delete v;
delete n;
delete t;
delete f;

return dlId;

}

mast4as
01-10-2015, 09:57 AM
I found some information on this format here:

http://www.scratchapixel.com/old/lessons/3d-advanced-lessons/obj-file-format/

GClements
01-10-2015, 11:59 AM
A description of the MTL format can be found here (http://paulbourke.net/dataformats/mtl/).

The other references I've found appear to be copies of that but with some of the formatting lost.

For rendering, I suggest that you "unweld" the OBJ structure first. By that, I mean identify the distinct combinations of (vertex position, texture coordinate, normal) indices used in the face definitions and create a separate vertex for each one, so that you can draw many faces with a single glDrawElements() call.

Carmine
01-12-2015, 11:42 AM
if (buf[0] == 'f' && buf[1] == ' ') {
SFace * face = new SFace();
sscanf(buf, "f %d/%d/%d %d/%d/%d %d/%d/%d",
&face->v[0], &face->t[0], &face->n[0],
&face->v[1], &face->t[1], &face->n[1],
&face->v[2], &face->t[2], &face->n[2]
);
f->push_back(*face);
}
You may run into trouble here. Texture and normal info is optional in OBJ format. For example you can have statements like -

f 15 47 29, or f 15//22 24//21 29//16.

You may also encounter faces with more than 3 vertices, such as f 45 12 24 67 29 30 44

It's also possible, though rare, to encounter negative face indices, such as f -2 -7 -3 -27

But your code looks good for triangulated OBJs with textures and normals specified.

If you end up writing your own MTL code, here's a couple of tips: 1) Do not call glMaterial for every polygon rendered. It will be painfully slow. Talked to someone who did that. It took about 8 hours to render a model with a few thousand polys. 2) As you read in polys, put them in bins by material, and render them that way (i.e. all blue polys in one display list, all red polys ....). Material bins can be avoided if you generate the models yourself, in which case you can write OBJ files that already have polys grouped by material.

Sorry, my employer does not allow us to give out code developed in house. Our OBJ reader is sort of klunky anyway. It does not do material binning. You could add material binning to your code in a day or two. Good luck.