c++ - Advanced loading of obj-files -
i can't seem find tutorial on how advanced obj-loading (aka. wavefront) want load model assigned textures , not, , tutorials i've found don't explain @ (just show window working) or basic, vertices, normals , indices.
so, first of all, suggestions tutorials?
here code, there need make work different textures?
data struct:
struct objectdata { vector <glm::vec3> vertices, normals, colors; vector <glm::vec2> texcoords; vector <gluint> vindices, uindices, nindices; };
object loader h:
class objectloader { private: struct material { string name; glm::vec3 color; }; vector <material*> materials; material *currentmaterial; objectdata *object; bool hasuv, hasnormals, isquads, indexchecked; string parsestring(string src, string code); glm::vec2 parsevec2(string src, string code); glm::vec3 parsevec3(string src, string code); void addindices(string str); void checkindices(string str); void loadobjects(string objpath); void loadmaterials(string matpath); public: objectloader(string objname); ~objectloader(); objectdata* getmodel(); glenum getrendermode(); };
object loader cpp:
objectloader::objectloader(string objname) { indexchecked = false; isquads = false; string filename = dir_objects + objname + "/" + objname; loadmaterials(filename + ".mtl"); loadobjects(filename + ".obj"); } objectloader::~objectloader() { } string objectloader::parsestring(string src, string code) { char buffer[64]; string scanstr = code + " %s"; sscanf_s(src.c_str(), scanstr.c_str(), &buffer, _countof(buffer)); return string(buffer); } glm::vec2 objectloader::parsevec2(string src, string code) { float x, y; string scanstr = code + " %f %f"; sscanf_s(src.c_str(), scanstr.c_str(), &x, &y); return glm::vec2(x, y); } glm::vec3 objectloader::parsevec3(string src, string code) { float x, y, z; string scanstr = code + " %f %f %f"; sscanf_s(src.c_str(), scanstr.c_str(), &x, &y, &z); return glm::vec3(x, y, z); } void objectloader::addindices(string str) { int v1 = -1, u1 = -1, n1 = -1, v2 = -1, u2 = -1, n2 = -1, v3 = -1, u3 = -1, n3 = -1, v4 = -1, u4 = -1, n4 = -1; checkindices(str); if (!hasuv && !hasnormals) { sscanf_s(str.c_str(),"f %d %d %d %d", &v1, &v2, &v3, &v4); } else if (hasuv && !hasnormals) { sscanf_s(str.c_str(),"f %d/%d %d/%d %d/%d %d/%d", &v1, &u1, &v2, &u2, &v3, &u3, &v4, &u4); } else if (!hasuv && hasnormals) { sscanf_s(str.c_str(),"f %d//%d %d//%d %d//%d %d//%d", &v1, &n1, &v2, &n2, &v3, &n3, &v4, &n4); } else if (hasuv && hasnormals) { sscanf_s(str.c_str(),"f %d/%d/%d %d/%d/%d %d/%d/%d %d/%d/%d", &v1, &u1, &n1, &v2, &u2, &n2, &v3, &u3, &n3, &v4, &u4, &n4); } v1--; u1--; n1--; v2--; u2--; n2--; v3--; u3--; n3--; v4--; u4--; n4--; if (v3 >= 0) { float r = currentmaterial->color.r; float g = currentmaterial->color.g; float b = currentmaterial->color.b; object->vindices.push_back(v1); object->vindices.push_back(v2); object->vindices.push_back(v3); object->colors.push_back(currentmaterial->color); object->colors.push_back(currentmaterial->color); object->colors.push_back(currentmaterial->color); if (v4 >= 0) { object->vindices.push_back(v4); object->colors.push_back(currentmaterial->color); isquads = true; } } if (u3 >= 0) { object->uindices.push_back(u1); object->uindices.push_back(u2); object->uindices.push_back(u3); if (u4 >= 0) { object->uindices.push_back(u4); } } if (n3 >= 0) { object->nindices.push_back(n1); object->nindices.push_back(n2); object->nindices.push_back(n3); if (n4 >= 0) { object->nindices.push_back(n4); } } } void objectloader::checkindices(string str) { if (!indexchecked) { int bestsample = 0; int samplev1 = -1, sampleu1 = -1, samplen1 = -1; int tmp = -1, samplev4 = -1; int form1 = sscanf_s(str.c_str(),"f %d", &samplev1); int form2 = sscanf_s(str.c_str(),"f %d/%d", &samplev1, &sampleu1); int form3 = sscanf_s(str.c_str(),"f %d//%d", &samplev1, &samplen1); int form4 = sscanf_s(str.c_str(),"f %d/%d/%d", &samplev1, &sampleu1, &samplen1); if (form1 > bestsample) { bestsample = form1; hasuv = false; hasnormals = false; } if (form2 > bestsample) { bestsample = form2; hasuv = true; hasnormals = false; } if (form3 > bestsample) { bestsample = form3; hasuv = false; hasnormals = true; } if (form4 > bestsample) { bestsample = form4; hasuv = true; hasnormals = true; } indexchecked = true; } } void objectloader::loadobjects(string objpath) { ifstream file(objpath); string buffer; object = new objectdata(); currentmaterial = materials[0]; if (file.is_open()) { while (!file.eof()) { getline(file, buffer); if (buffer.find("v ") == 0) { object->vertices.push_back(parsevec3(buffer, "v")); } else if (buffer.find("vn") == 0) { object->normals.push_back(parsevec3(buffer, "vn")); } else if (buffer.find("vt") == 0) { object->texcoords.push_back(parsevec2(buffer, "vt")); } else if (buffer.find("usemtl") == 0) { string name = parsestring(buffer, "usemtl"); (int = 0; < materials.size(); i++) { if (name == materials[i]->name) { currentmaterial = materials[i]; } } } else if (buffer.find("f ") != string::npos) { addindices(buffer); } } } else { printf("unable find: %s\n", objpath.c_str()); } } void objectloader::loadmaterials(string matpath) { ifstream file(matpath); string buffer; currentmaterial = null; if (file.is_open()) { while (!file.eof()) { getline(file, buffer); if (buffer.find("newmtl") == 0) { if (currentmaterial != null) { materials.push_back(currentmaterial); } currentmaterial = new material(); currentmaterial->name = parsestring(buffer, "newmtl"); } else if (buffer.find("kd") == 0) { currentmaterial->color = parsevec3(buffer, "kd"); } } } else { printf("unable find: %s\n", matpath.c_str()); } if (currentmaterial == null) { currentmaterial = new material(); currentmaterial->color = glm::vec3(1, 1, 1); } materials.push_back(currentmaterial); } objectdata* objectloader::getmodel() { return object; } glenum objectloader::getrendermode() { glenum mode = ((isquads) ? gl_quads : gl_triangles); return mode; }
Comments
Post a Comment