std::string LoadObj( std::vector<shape_t>& shapes, std::vector<material_t>& materials, // [output] std::istream& inStream, MaterialReader& readMatFn) { std::stringstream err; std::vector<float> v; std::vector<float> vn; std::vector<float> vt; std::vector<std::vector<vertex_index> > faceGroup; std::string name; // material std::map<std::string, int> material_map; std::map<vertex_index, unsigned int> vertexCache; int material = -1; shape_t shape; int maxchars = 8192; // Alloc enough size. std::vector<char> buf(maxchars); // Alloc enough size. while (inStream.peek() != -1) { inStream.getline(&buf[0], maxchars); std::string linebuf(&buf[0]); // Trim newline '\r\n' or '\n' if (linebuf.size() > 0) { if (linebuf[linebuf.size()-1] == '\n') linebuf.erase(linebuf.size()-1); } if (linebuf.size() > 0) { if (linebuf[linebuf.size()-1] == '\r') linebuf.erase(linebuf.size()-1); } // Skip if empty line. if (linebuf.empty()) { continue; } // Skip leading space. const char* token = linebuf.c_str(); token += strspn(token, " \t"); assert(token); if (token[0] == '\0') continue; // empty line if (token[0] == '#') continue; // comment line // vertex if (token[0] == 'v' && isSpace((token[1]))) { token += 2; float x, y, z; parseFloat3(x, y, z, token); v.push_back(x); v.push_back(y); v.push_back(z); continue; } // normal if (token[0] == 'v' && token[1] == 'n' && isSpace((token[2]))) { token += 3; float x, y, z; parseFloat3(x, y, z, token); vn.push_back(x); vn.push_back(y); vn.push_back(z); continue; } // texcoord if (token[0] == 'v' && token[1] == 't' && isSpace((token[2]))) { token += 3; float x, y; parseFloat2(x, y, token); vt.push_back(x); vt.push_back(y); continue; } // face if (token[0] == 'f' && isSpace((token[1]))) { token += 2; token += strspn(token, " \t"); std::vector<vertex_index> face; while (!isNewLine(token[0])) { vertex_index vi = parseTriple(token, v.size() / 3, vn.size() / 3, vt.size() / 2); face.push_back(vi); int n = strspn(token, " \t\r"); token += n; } faceGroup.push_back(face); continue; } // use mtl if ((0 == strncmp(token, "usemtl", 6)) && isSpace((token[6]))) { char namebuf[4096]; token += 7; sscanf(token, "%s", namebuf); bool ret = exportFaceGroupToShape(shape, vertexCache, v, vn, vt, faceGroup, material, name, false); faceGroup.clear(); if (material_map.find(namebuf) != material_map.end()) { material = material_map[namebuf]; } else { // { error!! material not found } material = -1; } continue; } // load mtl if ((0 == strncmp(token, "mtllib", 6)) && isSpace((token[6]))) { char namebuf[4096]; token += 7; sscanf(token, "%s", namebuf); std::string err_mtl = readMatFn(namebuf, materials, material_map); if (!err_mtl.empty()) { faceGroup.clear(); // for safety return err_mtl; } continue; } // group name if (token[0] == 'g' && isSpace((token[1]))) { // flush previous face group. bool ret = exportFaceGroupToShape(shape, vertexCache, v, vn, vt, faceGroup, material, name, true); if (ret) { shapes.push_back(shape); } shape = shape_t(); //material = -1; faceGroup.clear(); std::vector<std::string> names; while (!isNewLine(token[0])) { std::string str = parseString(token); names.push_back(str); token += strspn(token, " \t\r"); // skip tag } assert(names.size() > 0); // names[0] must be 'g', so skipt 0th element. if (names.size() > 1) { name = names[1]; } else { name = ""; } continue; } // object name if (token[0] == 'o' && isSpace((token[1]))) { // flush previous face group. bool ret = exportFaceGroupToShape(shape, vertexCache, v, vn, vt, faceGroup, material, name, true); if (ret) { shapes.push_back(shape); } //material = -1; faceGroup.clear(); shape = shape_t(); // @todo { multiple object name? } char namebuf[4096]; token += 2; sscanf(token, "%s", namebuf); name = std::string(namebuf); continue; } // Ignore unknown command. } bool ret = exportFaceGroupToShape(shape, vertexCache, v, vn, vt, faceGroup, material, name, true); if (ret) { shapes.push_back(shape); } faceGroup.clear(); // for safety return err.str(); }
std::string LoadMtl ( std::map<std::string, int>& material_map, std::vector<material_t>& materials, std::istream& inStream) { material_map.clear(); std::stringstream err; material_t material; int maxchars = 8192; // Alloc enough size. std::vector<char> buf(maxchars); // Alloc enough size. while (inStream.peek() != -1) { inStream.getline(&buf[0], maxchars); std::string linebuf(&buf[0]); // Trim newline '\r\n' or '\n' if (linebuf.size() > 0) { if (linebuf[linebuf.size()-1] == '\n') linebuf.erase(linebuf.size()-1); } if (linebuf.size() > 0) { if (linebuf[linebuf.size()-1] == '\r') linebuf.erase(linebuf.size()-1); } // Skip if empty line. if (linebuf.empty()) { continue; } // Skip leading space. const char* token = linebuf.c_str(); token += strspn(token, " \t"); assert(token); if (token[0] == '\0') continue; // empty line if (token[0] == '#') continue; // comment line // new mtl if ((0 == strncmp(token, "newmtl", 6)) && isSpace((token[6]))) { // flush previous material. if (!material.name.empty()) { material_map.insert(std::pair<std::string, int>(material.name, materials.size())); materials.push_back(material); } // initial temporary material InitMaterial(material); // set new mtl name char namebuf[4096]; token += 7; sscanf(token, "%s", namebuf); material.name = namebuf; continue; } // ambient if (token[0] == 'K' && token[1] == 'a' && isSpace((token[2]))) { token += 2; float r, g, b; parseFloat3(r, g, b, token); material.ambient[0] = r; material.ambient[1] = g; material.ambient[2] = b; continue; } // diffuse if (token[0] == 'K' && token[1] == 'd' && isSpace((token[2]))) { token += 2; float r, g, b; parseFloat3(r, g, b, token); material.diffuse[0] = r; material.diffuse[1] = g; material.diffuse[2] = b; continue; } // specular if (token[0] == 'K' && token[1] == 's' && isSpace((token[2]))) { token += 2; float r, g, b; parseFloat3(r, g, b, token); material.specular[0] = r; material.specular[1] = g; material.specular[2] = b; continue; } // transmittance if (token[0] == 'K' && token[1] == 't' && isSpace((token[2]))) { token += 2; float r, g, b; parseFloat3(r, g, b, token); material.transmittance[0] = r; material.transmittance[1] = g; material.transmittance[2] = b; continue; } // ior(index of refraction) if (token[0] == 'N' && token[1] == 'i' && isSpace((token[2]))) { token += 2; material.ior = parseFloat(token); continue; } // emission if(token[0] == 'K' && token[1] == 'e' && isSpace(token[2])) { token += 2; float r, g, b; parseFloat3(r, g, b, token); material.emission[0] = r; material.emission[1] = g; material.emission[2] = b; continue; } // shininess if(token[0] == 'N' && token[1] == 's' && isSpace(token[2])) { token += 2; material.shininess = parseFloat(token); continue; } // illum model if (0 == strncmp(token, "illum", 5) && isSpace(token[5])) { token += 6; material.illum = parseInt(token); continue; } // dissolve if ((token[0] == 'd' && isSpace(token[1]))) { token += 1; material.dissolve = parseFloat(token); continue; } if (token[0] == 'T' && token[1] == 'r' && isSpace(token[2])) { token += 2; material.dissolve = parseFloat(token); continue; } // ambient texture if ((0 == strncmp(token, "map_Ka", 6)) && isSpace(token[6])) { token += 7; material.ambient_texname = token; continue; } // diffuse texture if ((0 == strncmp(token, "map_Kd", 6)) && isSpace(token[6])) { token += 7; material.diffuse_texname = token; continue; } // specular texture if ((0 == strncmp(token, "map_Ks", 6)) && isSpace(token[6])) { token += 7; material.specular_texname = token; continue; } // normal texture if ((0 == strncmp(token, "map_Ns", 6)) && isSpace(token[6])) { token += 7; material.normal_texname = token; continue; } // normal texture (I ADDED THIS) if ((0 == strncmp(token, "map_bump", 8)) && isSpace(token[8])) { token += 9; material.normal_texname = token; continue; } // unknown parameter const char* _space = strchr(token, ' '); if(!_space) { _space = strchr(token, '\t'); } if(_space) { int len = _space - token; std::string key(token, len); std::string value = _space + 1; material.unknown_parameter.insert(std::pair<std::string, std::string>(key, value)); } } // flush last material. material_map.insert(std::pair<std::string, int>(material.name, materials.size())); materials.push_back(material); return err.str(); }
std::string LoadMtl ( std::map<std::string, material_t>& material_map, const char* filename, const char* mtl_basepath) { material_map.clear(); std::stringstream err; std::string filepath; if (mtl_basepath) { filepath = std::string(mtl_basepath) + std::string(filename); } else { filepath = std::string(filename); } std::ifstream ifs(filepath.c_str()); if (!ifs) { err << "Cannot open file [" << filepath << "]" << std::endl; return err.str(); } material_t material; int maxchars = 8192; // Alloc enough size. std::vector<char> buf(maxchars); // Alloc enough size. while (ifs.peek() != -1) { ifs.getline(&buf[0], maxchars); std::string linebuf(&buf[0]); // Trim newline '\r\n' or '\r' if (linebuf.size() > 0) { if (linebuf[linebuf.size()-1] == '\n') linebuf.erase(linebuf.size()-1); } if (linebuf.size() > 0) { if (linebuf[linebuf.size()-1] == '\n') linebuf.erase(linebuf.size()-1); } // Skip if empty line. if (linebuf.empty()) { continue; } // Skip leading space. const char* token = linebuf.c_str(); token += strspn(token, " \t"); assert(token); if (token[0] == '\0') continue; // empty line if (token[0] == '#') continue; // comment line // new mtl if ((0 == strncmp(token, "newmtl", 6)) && isSpace((token[6]))) { // flush previous material. material_map.insert(std::pair<std::string, material_t>(material.name, material)); // initial temporary material InitMaterial(material); // set new mtl name char namebuf[4096]; token += 7; sscanf(token, "%s", namebuf); material.name = namebuf; continue; } // ambient if (token[0] == 'K' && token[1] == 'a' && isSpace((token[2]))) { token += 2; float r, g, b; parseFloat3(r, g, b, token); material.ambient[0] = r; material.ambient[1] = g; material.ambient[2] = b; continue; } // diffuse if (token[0] == 'K' && token[1] == 'd' && isSpace((token[2]))) { token += 2; float r, g, b; parseFloat3(r, g, b, token); material.diffuse[0] = r; material.diffuse[1] = g; material.diffuse[2] = b; continue; } // specular if (token[0] == 'K' && token[1] == 's' && isSpace((token[2]))) { token += 2; float r, g, b; parseFloat3(r, g, b, token); material.specular[0] = r; material.specular[1] = g; material.specular[2] = b; continue; } // transmittance if (token[0] == 'K' && token[1] == 't' && isSpace((token[2]))) { token += 2; float r, g, b; parseFloat3(r, g, b, token); material.transmittance[0] = r; material.transmittance[1] = g; material.transmittance[2] = b; continue; } // ior(index of refraction) if (token[0] == 'N' && token[1] == 'i' && isSpace((token[2]))) { token += 2; material.ior = parseFloat(token); continue; } // emission if(token[0] == 'K' && token[1] == 'e' && isSpace(token[2])) { token += 2; float r, g, b; parseFloat3(r, g, b, token); material.emission[0] = r; material.emission[1] = g; material.emission[2] = b; continue; } // shininess if(token[0] == 'N' && token[1] == 's' && isSpace(token[2])) { token += 2; material.shininess = parseFloat(token); continue; } // illum model if (0 == strncmp(token, "illum", 5) && isSpace(token[5])) { token += 6; material.illum = parseInt(token); continue; } // dissolve if ((token[0] == 'd' && isSpace(token[1]))) { token += 1; material.dissolve = parseFloat(token); continue; } if (token[0] == 'T' && token[1] == 'r' && isSpace(token[2])) { token += 2; material.dissolve = parseFloat(token); continue; } // ambient texture if ((0 == strncmp(token, "map_Ka", 6)) && isSpace(token[6])) { token += 7; material.ambient_texname = token; continue; } // diffuse texture if ((0 == strncmp(token, "map_Kd", 6)) && isSpace(token[6])) { token += 7; material.diffuse_texname = token; continue; } // specular texture if ((0 == strncmp(token, "map_Ks", 6)) && isSpace(token[6])) { token += 7; material.specular_texname = token; continue; } // normal texture if (IsBumpMap(token)) { while (*token == '-') { // parse bump map options... if((0 == strncmp(token, "-bm", 3)) && isSpace(token[3])) { token += 4; material.bump_scale = parseFloat(token); } else { ParseUnsupportedBumpModifier(token, err); } // skip space token += strspn(token, " \t"); } material.normal_texname = token; continue; } // unknown parameter const char* _space = strchr(token, ' '); if(!_space) { _space = strchr(token, '\t'); } if(_space) { int len = _space - token; std::string key(token, len); std::string value = _space + 1; material.unknown_parameter.insert(std::pair<std::string, std::string>(key, value)); } } // flush last material. material_map.insert(std::pair<std::string, material_t>(material.name, material)); return err.str(); }
std::string ObjLoader::LoadObj(shapes_t& shapes, const char* filename, const char* mtl_basepath) { shapes.reset(); std::stringstream err; std::istringstream ifs(FileUtils::getInstance()->getStringFromFile(filename)); std::map<vertex_index, ssize_t> vertexCache; //std::ifstream ifs(filename); if (!ifs) { err << "Cannot open file [" << filename << "]" << std::endl; return err.str(); } std::vector<float> v; std::vector<float> vn; std::vector<float> vt; std::vector<std::vector<vertex_index> > faceGroup; std::string name; // material std::map<std::string, material_t> material_map; material_t material; int maxchars = 8192; // Alloc enough size. std::vector<char> buf(maxchars); // Alloc enough size. while (ifs.peek() != -1) { ifs.getline(&buf[0], maxchars); std::string linebuf(&buf[0]); // Trim newline '\r\n' or '\r' if (linebuf.size() > 0) { if (linebuf[linebuf.size()-1] == '\n') linebuf.erase(linebuf.size()-1); } if (linebuf.size() > 0) { if (linebuf[linebuf.size()-1] == '\n') linebuf.erase(linebuf.size()-1); } // Skip if empty line. if (linebuf.empty()) { continue; } // Skip leading space. const char* token = linebuf.c_str(); token += strspn(token, " \t"); assert(token); if (token[0] == '\0') continue; // empty line if (token[0] == '#') continue; // comment line // vertex if (token[0] == 'v' && isSpace((token[1]))) { token += 2; float x, y, z; parseFloat3(x, y, z, token); v.push_back(x); v.push_back(y); v.push_back(z); continue; } // normal if (token[0] == 'v' && token[1] == 'n' && isSpace((token[2]))) { token += 3; float x, y, z; parseFloat3(x, y, z, token); vn.push_back(x); vn.push_back(y); vn.push_back(z); continue; } // texcoord if (token[0] == 'v' && token[1] == 't' && isSpace((token[2]))) { token += 3; float x, y; parseFloat2(x, y, token); vt.push_back(x); vt.push_back(y); continue; } // face if (token[0] == 'f' && isSpace((token[1]))) { token += 2; token += strspn(token, " \t"); std::vector<vertex_index> face; while (!isNewLine(token[0])) { // fix warning, cast to int, i think int is enough vertex_index vi = parseTriple(token, (int)v.size() / 3, (int)vn.size() / 3, (int)vt.size() / 2); face.push_back(vi); auto n = strspn(token, " \t\r"); token += n; } faceGroup.push_back(face); continue; } // use mtl if ((0 == strncmp(token, "usemtl", 6)) && isSpace((token[6]))) { char namebuf[4096]; token += 7; sscanf(token, "%s", namebuf); if (material_map.find(namebuf) != material_map.end()) { material = material_map[namebuf]; } else { // { error!! material not found } InitMaterial(material); } continue; } // load mtl if ((0 == strncmp(token, "mtllib", 6)) && isSpace((token[6]))) { char namebuf[4096]; token += 7; sscanf(token, "%s", namebuf); std::string err_mtl = LoadMtl(material_map, namebuf, mtl_basepath); if (!err_mtl.empty()) { faceGroup.clear(); // for safety //return err_mtl; } continue; } // group name if (token[0] == 'g' && isSpace((token[1]))) { // flush previous face group. shape_t shape; exportFaceGroupToShape(vertexCache, shapes, v, vn, vt, faceGroup, material, name); faceGroup.clear(); std::vector<std::string> names; while (!isNewLine(token[0])) { std::string str = parseString(token); names.push_back(str); token += strspn(token, " \t\r"); // skip tag } assert(names.size() > 0); // names[0] must be 'g', so skipt 0th element. if (names.size() > 1) { name = names[1]; } else { name = ""; } continue; } // object name if (token[0] == 'o' && isSpace((token[1]))) { // flush previous face group. shape_t shape; exportFaceGroupToShape(vertexCache, shapes, v, vn, vt, faceGroup, material, name); faceGroup.clear(); // @todo { multiple object name? } char namebuf[4096]; token += 2; sscanf(token, "%s", namebuf); name = std::string(namebuf); continue; } // Ignore unknown command. } shape_t shape; exportFaceGroupToShape(vertexCache, shapes, v, vn, vt, faceGroup, material, name); faceGroup.clear(); // for safety return err.str(); }
void ObjectParser( TArray<FVector>& positions, TArray<FVector>& normals, TArray<FVector2D>& uvs, TArray<int32>& indices ) { char filepath[1024]; sprintf_s(filepath, "../../../../../../Siggraph2017/assets/Simplygon/InfinityBlade/InfinityBladeAdversaries/Enemy_Bear/clean_Enemy_Bear_099.obj"); std::ifstream ifs(filepath); if (!ifs) { UE_LOG(LogTemp, Warning, TEXT("output : %s"), L"オブジェクトファイルの読み込みに失敗しました"); } int maxchars = 8192; // Alloc enough size. std::vector<char> buf(maxchars); // Alloc enough size. while (ifs.peek() != -1) { ifs.getline(&buf[0], maxchars); std::string linebuf(&buf[0]); // Trim newline '\r\n' or '\r' if (linebuf.size() > 0) { if (linebuf[linebuf.size() - 1] == '\n') linebuf.erase(linebuf.size() - 1); } if (linebuf.size() > 0) { if (linebuf[linebuf.size() - 1] == '\n') linebuf.erase(linebuf.size() - 1); } // Skip if empty line. if (linebuf.empty()) { continue; } // Skip leading space. const char* token = linebuf.c_str(); token += strspn(token, " \t"); assert(token); if (token[0] == '\0') continue; // empty line if (token[0] == '#') continue; // comment line // vertex if (token[0] == 'v' && isSpace((token[1]))) { token += 2; float xyz[3]; parseFloat3(xyz[0], xyz[1], xyz[2], token); positions.Add(FVector(xyz[0], xyz[1], xyz[2])); continue; } // normal if (token[0] == 'v' && token[1] == 'n' && isSpace((token[2]))) { token += 3; float xyz[3]; parseFloat3(xyz[0], xyz[1], xyz[2], token); normals.Add(FVector(xyz[0], xyz[1], xyz[2])); continue; } // texcoord if (token[0] == 'v' && token[1] == 't' && isSpace((token[2]))) { token += 3; float uv[2]; parseFloat2(uv[0], uv[1], token); uvs.Add(FVector2D(uv[0], 1.0f - uv[1])); continue; } // face if (token[0] == 'f' && isSpace((token[1]))) { token += 2; token += strspn(token, " \t"); std::vector<vertex_index> face; int tmp[3]; int tmp_index = 0; while (!isNewLine(token[0])) { vertex_index vi = parseTriple(token, 3, 3, 2); tmp[tmp_index] = vi.v_idx; tmp_index++; int n = strspn(token, " \t\r"); token += n; } indices.Add(tmp[2]); indices.Add(tmp[1]); indices.Add(tmp[0]); continue; } // use mtl if ((0 == strncmp(token, "usemtl", 6)) && isSpace((token[6]))) { continue; } // load mtl if ((0 == strncmp(token, "mtllib", 6)) && isSpace((token[6]))) { continue; } // group name if (token[0] == 'g' && isSpace((token[1]))) { continue; } // object name if (token[0] == 'o' && isSpace((token[1]))) { continue; } // Ignore unknown command. } }